diff --git a/.circleci/config.yml b/.circleci/config.yml index 35cf643d031..def054c14a9 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -3,261 +3,68 @@ defaults: &defaults - image: circleci/node:15.2.1-browsers version: 2.1 + +parameters: + custom_springboot_args: + type: string + default: "--spring.profiles.active=clickhouse" + commands: build_push_image: + description: "Build and push cBioPortal image to Dockerhub. Check parameters below for configurable options." parameters: + docker_repo: + description: Docker repo name + type: string + default: "cbioportal/cbioportal-dev" + app_type: + description: Type of cBioPortal App (web OR web-and-data OR both) + type: enum + enum: ["web", "web-and-data"] push: description: Push image to DockerHub - type: string - default: "false" + type: enum + enum: ["true", "false"] steps: - run: - name: Build cBioPortal docker image - environment: - DOCKER_REPO: cbioportal/cbioportal-dev + name: Build and Push cBioPortal docker image command: | export DOCKER_TAG=$CIRCLE_SHA1 - URL="https://hub.docker.com/v2/repositories/cbioportal/cbioportal-dev/tags/$DOCKER_TAG-web-shenandoah" + export DOCKER_REPO=<> + export APP_TYPE=<> + + if [ $APP_TYPE = "web" ]; then + URL="https://hub.docker.com/v2/repositories/$DOCKER_REPO/tags/$DOCKER_TAG-web-shenandoah" + elif [ $APP_TYPE = "web-and-data" ]; then + URL="https://hub.docker.com/v2/repositories/$DOCKER_REPO/tags/$DOCKER_TAG" + else + echo "Unknown app type provided. Accepted values are ['web', 'web-and-data']" + exit 1 + fi + TAG_FOUND=$(curl -s $URL | jq -r .name) - if [ $TAG_FOUND = "$DOCKER_TAG-web-shenandoah" ]; then + if [ $APP_TYPE = "web" ] && [ $TAG_FOUND = "$DOCKER_TAG-web-shenandoah" ]; then echo "Image already exists. Pulling remote image and skipping build step!" docker pull $DOCKER_REPO:$DOCKER_TAG-web-shenandoah exit 0 fi - cd cbioportal-test - ./scripts/build-push-image.sh --src=/tmp/repos/cbioportal --push=<> --skip_web_and_data=true - if [ "<>" = "false" ]; then - EXISTS=$(docker inspect --type=image $DOCKER_REPO:$DOCKER_TAG-web-shenandoah > /dev/null; echo $?); - else - EXISTS=$(docker manifest inspect $DOCKER_REPO:$DOCKER_TAG-web-shenandoah > /dev/null; echo $?); + if [ $APP_TYPE = "web-and-data" ] && [ $TAG_FOUND = "$DOCKER_TAG" ]; then + echo "Image already exists. Pulling remote image and skipping build step!" + docker pull $DOCKER_REPO:$DOCKER_TAG + exit 0 fi - if [ $EXISTS -eq 0 ]; then - echo "Build succeeded!" + + cd cbioportal-test + if [ $APP_TYPE = "web" ]; then + ./scripts/build-push-image.sh --src=/tmp/repos/cbioportal --push=<> --skip_web_and_data=true + elif [ $APP_TYPE = "web-and-data" ]; then + ./scripts/build-push-image.sh --src=/tmp/repos/cbioportal --push=<> --skip_web=true else - echo "Build failed!" + echo "Unknown app type provided. Accepted values are ['web', 'web-and-data']" exit 1 fi jobs: - build_backend: - docker: - - image: maven:3-eclipse-temurin-21 - working_directory: /tmp/repos/cbioportal - steps: - - checkout - - run: - name: Concatenate poms to use as cache key for mvn deps - command: cat $(git ls-files '*pom.xml*') > poms_combined - - restore_cache: - keys: - - v1-mvn-dependencies-{{ checksum "poms_combined" }} - - v1-mvn-dependencies- - - run: - name: Build and unzip jar - command: | - cp src/main/resources/application.properties.EXAMPLE src/main/resources/application.properties && \ - mvn -DskipTests clean package - - save_cache: - paths: - - ~/.m2 - key: v1-mvn-dependencies-{{ checksum "poms_combined" }} - - persist_to_workspace: - root: /tmp/repos - paths: - - cbioportal - - pull_frontend_codebase: - <<: *defaults - working_directory: /tmp/repos - steps: - - checkout - - run: - name: Pull frontend code - command: | - export FRONTEND_VERSION=$(grep '' pom.xml | sed 's///g' | sed 's|||' | tr -d '[:blank:]') && \ - export FRONTEND_ORG=$(grep 'frontend\.groupId' pom.xml | sed 's///g' | sed 's|||' | tr -d '[:blank:]' | cut -d. -f3) && \ - git clone https://github.com/$FRONTEND_ORG/cbioportal-frontend.git && \ - cd cbioportal-frontend && \ - git fetch --tags - - persist_to_workspace: - root: /tmp/repos - paths: - - cbioportal-frontend - - install_yarn: - <<: *defaults - working_directory: /tmp/repos/cbioportal-frontend - steps: - - attach_workspace: - at: /tmp/repos - #- run: - # name: "Install yarn at specific version" - # command: - # sudo npm install --global yarn@1.22.4 - - run: - name: "Show yarn and node versions" - command: | - node --version - yarn --version - # cache build artifacts. Use concatenation of all source files as cache - # key. If there are no changes to src/ and yarn.lock, no need to rebuild - - run: - name: "Concatenate all source files to use as hash key for caching dist folder" - command: "cat yarn.lock $(find src/ -type f | sort) webpack.config.js vendor-bundles.webpack.config.js > has_source_changed" - - restore_cache: - keys: - - v4-dependencies-plus-dist-{{ checksum "has_source_changed" }} - - v4-dependencies-{{ checksum "yarn.lock" }} - # Download and cache dependencies - - run: yarn -# - run: -# name: "Make sure lock file is still the same" -# command: 'git diff --exit-code yarn.lock > /dev/null || (echo -e "New package lock file at $(cat yarn.lock | curl -F c=@- https://ptpb.pw | grep url) (include this file in your PR to fix this test)"; git diff --exit-code yarn.lock; exit 1)' - - save_cache: - paths: - - node_modules - key: v4-dependencies-{{ checksum "yarn.lock" }} - - run: - name: "Run build if no dist folder" - command: 'ls dist || yarn run build' - environment: - DISABLE_SOURCEMAP: true - NO_PARALLEL: true - no_output_timeout: 25m - - run: cd /tmp/repos/cbioportal-frontend/end-to-end-test && (ls node_modules || yarn install --frozen-lockfile --ignore-engines) - - save_cache: - paths: - - node_modules - - dist - - common-dist - key: v4-dependencies-plus-dist-{{ checksum "has_source_changed" }} - - persist_to_workspace: - root: /tmp/repos - paths: - - cbioportal-frontend - - end_to_end_tests_localdb: - working_directory: /tmp/repos/cbioportal-frontend - machine: - enabled: true - image: ubuntu-2204:2023.02.1 - resource_class: large - steps: - - attach_workspace: - at: /tmp/repos - - run: - name: Setup python libraries - command: | - pip3 install requests pyyaml - - run: - name: Install dependencies - command: | - sudo apt-get update && \ - sudo apt-get install jq - - run: - name: Determine what backend image to run - command: | - if [[ -n "${CIRCLE_PR_USERNAME}" ]]; then \ - sed -i '/BACKEND.*/d' env/custom.sh && \ - echo -e "\nexport BACKEND=$CIRCLE_PR_USERNAME:$CIRCLE_SHA1" >> $PORTAL_SOURCE_DIR/env/custom.sh; \ - else \ - echo -e "\nexport BACKEND=$CIRCLE_PROJECT_USERNAME:$CIRCLE_SHA1" >> $PORTAL_SOURCE_DIR/env/custom.sh; \ - fi - - run: - name: Setup e2e-environment - command: | - source $PORTAL_SOURCE_DIR/env/custom.sh || true && \ - cd $TEST_HOME/runtime-config && \ - ./setup_environment.sh && ./setup_environment.sh >> $BASH_ENV - - run: - name: Build custom backend - command: | - mkdir -p $E2E_WORKSPACE; \ - mv /tmp/repos/cbioportal $E2E_WORKSPACE - - run: - name: Setup docker compose assets - command: | - $TEST_HOME/docker_compose/setup.sh - no_output_timeout: 25m - - run: - name: Create MySQL data directory - command: | - docker volume rm --force cbioportal-docker-compose_cbioportal_mysql_data && mkdir -p $CBIO_DB_DATA_DIR && rm -rf $CBIO_DB_DATA_DIR/* - - restore_cache: - keys: - - v8-cbio-database-files-{{ checksum "/tmp/db_data_md5key" }} - - restore_cache: - keys: - - v8-keycloak-database-files-{{ checksum "e2e-localdb-workspace/keycloak/keycloak-config-generated.json" }} - - run: - name: Init database - command: | - cd $TEST_HOME/docker_compose && echo $CBIO_DB_DATA_DIR && ls -la $CBIO_DB_DATA_DIR && \ - [ "$(ls -A $CBIO_DB_DATA_DIR)" ] && echo "DB initialization is not needed." || ./initdb.sh - - run: - name: Change owner of MySQL database files (needed by cache) - command: | - sudo chmod -R 777 $CBIO_DB_DATA_DIR && \ - sudo chown -R circleci:circleci $CBIO_DB_DATA_DIR - - save_cache: - paths: - - /tmp/repos/cbioportal-frontend/e2e-localdb-workspace/cbio_db_data - key: v9-cbio-database-files-{{ checksum "/tmp/db_data_md5key" }} - - run: - name: Start cbioportal and other services - command: | - $TEST_HOME/docker_compose/start.sh - - run: - name: Change owner of keycloak MySQL database files (needed by cache) - command: | - if (ls "$KC_DB_DATA_DIR"/* 2> /dev/null > /dev/null); then \ - sudo chmod -R 777 $KC_DB_DATA_DIR && \ - sudo chown -R circleci:circleci $KC_DB_DATA_DIR; \ - fi - - save_cache: - paths: - - /tmp/repos/cbioportal-frontend/e2e-localdb-workspace/kc_db_data - key: v9-keycloak-database-files-{{ checksum "e2e-localdb-workspace/keycloak/keycloak-config-generated.json" }} - - run: - name: Run end-2-end tests with studies in local database - command: | - cd $PORTAL_SOURCE_DIR && \ - $TEST_HOME/docker_compose/test.sh - - run: - name: "Make sure all screenshots are tracked (otherwise the test will always be successful)" - command: 'for f in $TEST_HOME/screenshots/reference/*.png; do git ls-files --error-unmatch $f > /dev/null 2> /dev/null || (echo -e "\033[0;31m $f not tracked \033[0m" && touch screenshots_not_tracked); done; ls screenshots_not_tracked > /dev/null 2> /dev/null && exit 1 || exit 0' - - store_artifacts: - path: /tmp/repos/cbioportal-frontend/end-to-end-test/local/screenshots - destination: /screenshots - - store_artifacts: - path: /tmp/repos/cbioportal-frontend/end-to-end-test/shared/image-compare - destination: /image-compare - - store_artifacts: - path: /tmp/repos/cbioportal-frontend/end-to-end-test/local/errorShots - destination: /errorShots - - store_test_results: - path: /tmp/repos/cbioportal-frontend/end-to-end-test/local/junit - - store_artifacts: - path: /tmp/repos/cbioportal-frontend/end-to-end-test/local/junit - - store_artifacts: - path: /tmp/repos/cbioportal-frontend/end-to-end-test/shared/imageCompare.html - destination: /imageCompare.html - - store_artifacts: - path: /tmp/repos/cbioportal-frontend/end-to-end-test/local/junit/customReport.json - destination: /customReport.json - - store_artifacts: - path: /tmp/repos/cbioportal-frontend/end-to-end-test/local/junit/errors/ - destination: /errors - - environment: - PORTAL_SOURCE_DIR: /tmp/repos/cbioportal-frontend/ - TEST_HOME: /tmp/repos/cbioportal-frontend/end-to-end-test/local - E2E_WORKSPACE: /tmp/repos/cbioportal-frontend/e2e-localdb-workspace - CBIO_DB_DATA_DIR: /tmp/repos/cbioportal-frontend/e2e-localdb-workspace/cbio_db_data - KC_DB_DATA_DIR: /tmp/repos/cbioportal-frontend/e2e-localdb-workspace/kc_db_data - DOCKER_IMAGE_SESSION_SERVICE: cbioportal/session-service:0.5.0 - FRONTEND_TEST_DO_NOT_LOAD_EXTERNAL_FRONTEND: true - pull_cbioportal_test_codebase: machine: image: ubuntu-2204:2024.08.1 @@ -306,7 +113,60 @@ jobs: paths: - cbioportal - build_image: + build_frontend: + <<: *defaults + working_directory: /tmp/repos + environment: + BRANCH_ENV: master + steps: + - attach_workspace: + at: /tmp/repos + - run: + name: Generate cache key for dist + command: | + cd cbioportal-frontend + echo "Concatenate all source files to use as hash key." + cat yarn.lock $(find src/ -type f | sort) webpack.config.js vendor-bundles.webpack.config.js > has_source_changed + - restore_cache: + keys: + - v5-dependencies-plus-dist-{{ checksum "cbioportal-frontend/has_source_changed" }} + - v5-dependencies-{{ checksum "cbioportal-frontend/yarn.lock" }} + - run: + name: Download dependencies + command: | + cd cbioportal-frontend + yarn + - save_cache: + name: Save dependency cache + key: v5-dependencies-{{ checksum "cbioportal-frontend/yarn.lock" }} + paths: + - cbioportal-frontend/node_modules + - run: + name: Build frontend application + environment: + DISABLE_SOURCEMAP: true + NO_PARALLEL: true + command: | + cd cbioportal-frontend + ls dist || yarn run build + - run: + name: Build frontend tests + command: | + cd cbioportal-frontend/end-to-end-test + ls node_modules || yarn install --frozen-lockfile --ignore-engines + - save_cache: + name: Save dependency plus dist cache + key: v5-dependencies-plus-dist-{{ checksum "cbioportal-frontend/has_source_changed" }} + paths: + - cbioportal-frontend/node_modules + - cbioportal-frontend/dist + - cbioportal-frontend/common-dist + - persist_to_workspace: + root: /tmp/repos + paths: + - cbioportal-frontend + + build_web_image: machine: image: ubuntu-2204:2024.08.1 resource_class: medium @@ -317,6 +177,7 @@ jobs: - attach_workspace: at: /tmp/repos - build_push_image: + app_type: "web" push: "false" - run: name: Save cbioportal image as tar @@ -328,7 +189,42 @@ jobs: paths: - "*.tar" - push_image: + build_web_and_data_image: + machine: + image: ubuntu-2204:2024.08.1 + resource_class: medium + working_directory: /tmp/repos + environment: + DOCKER_REPO: cbioportal/cbioportal-dev + steps: + - attach_workspace: + at: /tmp/repos + - build_push_image: + app_type: "web-and-data" + push: "false" + - run: + name: Save cbioportal image as tar + command: | + export DOCKER_TAG=$CIRCLE_SHA1 + docker save -o $DOCKER_TAG.tar $DOCKER_REPO:$DOCKER_TAG + - persist_to_workspace: + root: /tmp/repos + paths: + - "*.tar" + + push_web_image: + machine: + image: ubuntu-2204:2024.08.1 + resource_class: medium + working_directory: /tmp/repos + steps: + - attach_workspace: + at: /tmp/repos + - build_push_image: + app_type: "web" + push: "true" + + push_web_and_data_image: machine: image: ubuntu-2204:2024.08.1 resource_class: medium @@ -337,8 +233,101 @@ jobs: - attach_workspace: at: /tmp/repos - build_push_image: + app_type: "web-and-data" push: "true" + run_e2e_localdb_tests: + working_directory: /tmp/repos + machine: + image: ubuntu-2204:2024.08.1 + resource_class: large + environment: + DOCKER_REPO: cbioportal/cbioportal-dev + DOCKER_IMAGE_MYSQL: cbioportal/mysql:8.0-database-test + steps: + - attach_workspace: + at: /tmp/repos + - run: + name: Load cbioportal image + command: | + export DOCKER_TAG=$CIRCLE_SHA1 + docker load -i $DOCKER_TAG.tar + - run: + name: Generate keycloak config + environment: + STUDIES: 'ascn_test_study study_hg38 teststudy_genepanels study_es_0 lgg_ucsf_2014_test_generic_assay' + command: | + git clone https://github.com/cbioportal/cbioportal-docker-compose.git + cd cbioportal-test + ./utils/gen-keycloak-config.sh --studies="$STUDIES" --template='/tmp/repos/cbioportal-docker-compose/dev/keycloak/keycloak-config.json' --out='/tmp/repos/keycloak-config-generated.json' + - run: + name: Start backend server with keycloak + environment: + KEYCLOAK_CONFIG_PATH: '/tmp/repos/keycloak-config-generated.json' + APPLICATION_PROPERTIES_PATH: '/tmp/repos/cbioportal-frontend/end-to-end-test/local/runtime-config/portal.properties' + command: | + cd cbioportal-test + export DOCKER_IMAGE_CBIOPORTAL=$DOCKER_REPO:$CIRCLE_SHA1 + nohup ./scripts/docker-compose.sh --portal_type='keycloak' >> /tmp/repos/docker-compose-logs.txt 2>&1 & + - run: + name: Check keycloak connection at localhost + command: | + cd cbioportal-test + ./utils/check-connection.sh --url=localhost:8081 --max_retries=50 + - run: + name: Check backend connection at localhost + command: | + cd cbioportal-test + ./utils/check-connection.sh --url=localhost:8080 --max_retries=50 + - run: + name: Run end-2-end tests with studies in local database + environment: + CBIOPORTAL_URL: http://localhost:8080 + JUNIT_REPORT_PATH: ./local/junit/ + SCREENSHOT_DIRECTORY: ./local/screenshots + PORTAL_SOURCE_DIR: /tmp/repos/cbioportal-frontend + TEST_HOME: /tmp/repos/cbioportal-frontend/end-to-end-test/local + FRONTEND_TEST_DO_NOT_LOAD_EXTERNAL_FRONTEND: true + SPEC_FILE_PATTERN: ./local/specs/**/*.spec.js + command: | + cd $PORTAL_SOURCE_DIR && \ + $TEST_HOME/docker_compose/test.sh + - run: + name: Make sure all screenshots are tracked (otherwise the test will always be successful) + environment: + TEST_HOME: /tmp/repos/cbioportal-frontend/end-to-end-test/local + command: | + cd cbioportal-frontend + for f in end-to-end-test/local/screenshots/reference/*.png; do + git ls-files --error-unmatch $f > /dev/null 2> /dev/null || + (echo -e "\033[0;31m $f not tracked \033[0m" && touch screenshots_not_tracked); + done; + ls screenshots_not_tracked > /dev/null 2> /dev/null && exit 1 || exit 0 + - store_artifacts: + path: /tmp/repos/docker-compose-logs.txt + - store_artifacts: + path: /tmp/repos/cbioportal-frontend/end-to-end-test/local/screenshots + destination: /screenshots + - store_artifacts: + path: /tmp/repos/cbioportal-frontend/end-to-end-test/shared/image-compare + destination: /image-compare + - store_artifacts: + path: /tmp/repos/cbioportal-frontend/end-to-end-test/local/errorShots + destination: /errorShots + - store_test_results: + path: /tmp/repos/cbioportal-frontend/end-to-end-test/local/junit + - store_artifacts: + path: /tmp/repos/cbioportal-frontend/end-to-end-test/local/junit + - store_artifacts: + path: /tmp/repos/cbioportal-frontend/end-to-end-test/shared/imageCompare.html + destination: /imageCompare.html + - store_artifacts: + path: /tmp/repos/cbioportal-frontend/end-to-end-test/local/junit/completeResults.json + destination: /completeResults.json + - store_artifacts: + path: /tmp/repos/cbioportal-frontend/end-to-end-test/local/junit/errors/ + destination: /errors + run_api_tests: machine: image: ubuntu-2204:2024.08.1 @@ -359,6 +348,7 @@ jobs: name: Instantiate a cbioportal instance environment: APP_CLICKHOUSE_MODE: "true" + APP_CUSTOM_ARGS: << pipeline.parameters.custom_springboot_args >> command: | cd cbioportal-test export DOCKER_IMAGE_CBIOPORTAL=$DOCKER_REPO:$CIRCLE_SHA1-web-shenandoah @@ -473,9 +463,9 @@ jobs: resource_class: medium working_directory: /tmp/repos environment: - SUCCESS_MESSAGE: 'passing' + SUCCESS_MESSAGE: 'Passing' SUCCESS_COLOR: 'brightgreen' - FAILURE_MESSAGE: 'failing' + FAILURE_MESSAGE: 'Failing' FAILURE_COLOR: 'FF0A0A' SEVERITY_THRESHOLD: 'CRITICAL' TEST_REPO_URL: 'git@github.com:cBioPortal/cbioportal-test.git' @@ -518,44 +508,49 @@ jobs: git push workflows: - end_to_end_tests: - jobs: - - build_backend - - pull_frontend_codebase - - install_yarn: - requires: - - pull_frontend_codebase - - end_to_end_tests_localdb: - requires: - - build_backend - - pull_frontend_codebase - - install_yarn tests: jobs: - checkout_pr - pull_cbioportal_test_codebase - pull_cbioportal_frontend_codebase - - build_image: + - build_frontend: + requires: + - pull_cbioportal_frontend_codebase + - build_web_image: requires: - checkout_pr - pull_cbioportal_test_codebase - - push_image: + - build_web_and_data_image: + requires: + - checkout_pr + - pull_cbioportal_test_codebase + - push_web_image: context: - api-tests requires: - checkout_pr - pull_cbioportal_test_codebase + - push_web_and_data_image: + context: + - api-tests + requires: + - checkout_pr + - pull_cbioportal_test_codebase + - run_e2e_localdb_tests: + requires: + - build_frontend + - build_web_and_data_image - run_api_tests: context: - api-tests requires: - - build_image + - build_web_image - pull_cbioportal_frontend_codebase - run_security_tests: context: - docker-scout requires: - - build_image + - build_web_image - update_security_status_badge: requires: - run_security_tests diff --git a/.githooks/spotless_pre_commit_hook.sh b/.githooks/spotless_pre_commit_hook.sh new file mode 100644 index 00000000000..f569dea38e2 --- /dev/null +++ b/.githooks/spotless_pre_commit_hook.sh @@ -0,0 +1,28 @@ +#!/bin/bash +HOOK_FILE=".git/hooks/pre-commit" + +# Ensure hooks directory exists +mkdir -p .git/hooks + +# If the pre-commit hook doesn't exist, create it with a shebang line +if [[ ! -f "$HOOK_FILE" ]]; then + echo "#!/bin/bash" > "$HOOK_FILE" + echo "set -e" >> "$HOOK_FILE" +fi + +# Check if Spotless is already in the pre-commit hook, and add it if missing +if ! grep -qxF "mvn spotless:apply" "$HOOK_FILE"; then + echo "echo 'Running Spotless on staged files...'" >> "$HOOK_FILE" + echo "mvn spotless:apply" >> "$HOOK_FILE" +fi + +# Check if `git add -u` is already in the pre-commit hook, and add it if missing +if ! grep -qxF "git add -u" "$HOOK_FILE"; then + echo "echo 'Adding formatted files back to commit...'" >> "$HOOK_FILE" + echo "git add -u" >> "$HOOK_FILE" +fi + +# Make sure the pre-commit hook is executable +chmod +x "$HOOK_FILE" + +echo "✅ Spotless pre-commit hook installed successfully!" diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 00000000000..7b307bc11e4 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,27 @@ +--- +name: Bug report +about: Create a report to help us improve +title: "[BUG]" +labels: bug, triage +assignees: '' + +--- + +**Describe the bug** +A clear and concise description of what the bug is. + +**To Reproduce** +Steps to reproduce the behavior: +1. Go to '...' +2. Click on '....' +3. Scroll down to '....' +4. See error + +**Expected behavior** +A clear and concise description of what you expected to happen. + +**Screenshots** +If applicable, add screenshots to help explain your problem. + +**Additional context** +Add any other context about the problem here. diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 00000000000..9c4346172a9 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,20 @@ +--- +name: Feature request +about: Suggest an idea for this project +title: "[FEATURE REQUEST]" +labels: feature, triage +assignees: '' + +--- + +**Is your feature request related to a problem? Please describe.** +A clear and concise description of what the problem is. + +**Describe the solution you'd like** +What would you want to happen? + +**Describe alternatives you've considered** +Any alternative solutions or features you've considered. + +**Additional context** +Add any other context or screenshots about the feature request here. diff --git a/.github/ISSUE_TEMPLATE/question-for-cbioportal-team.md b/.github/ISSUE_TEMPLATE/question-for-cbioportal-team.md new file mode 100644 index 00000000000..5f2da344295 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/question-for-cbioportal-team.md @@ -0,0 +1,16 @@ +--- +name: Question for cBioPortal team +about: Submit questions related to cBioPortal data or your cBioPortal deployment +title: "[USER SUPPORT]" +labels: support, triage +assignees: dippindots + +--- + +**How can we help** +What kind of support are you looking for? e.g. +- Data submitssion (have new data and want us to host data) +- Installation support (get questions when installing your cBioPortal instance) + +**Describe the your question** +A clear description of what the question is. diff --git a/.github/workflows/auto-label.yml b/.github/workflows/auto-label.yml new file mode 100644 index 00000000000..1cd7f72b864 --- /dev/null +++ b/.github/workflows/auto-label.yml @@ -0,0 +1,22 @@ +name: Auto Label New Issues + +on: + issues: + types: [opened] + +jobs: + add-label: + runs-on: ubuntu-latest + steps: + - name: Add default label to new issues or pull requests + uses: actions/github-script@v6 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + // Add default label 'triage' to new issues so that new issues can be added to the project board automatically + await github.rest.issues.addLabels({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.payload.issue.number, + labels: ['triage'] + }); diff --git a/.github/workflows/core-test.yml b/.github/workflows/core-test.yml index 9664fa7d31e..3d58f307694 100644 --- a/.github/workflows/core-test.yml +++ b/.github/workflows/core-test.yml @@ -23,7 +23,7 @@ jobs: website: oracle.com release: 21 - name: 'Cache Maven packages' - uses: actions/cache@v1 + uses: actions/cache@v4 with: path: ~/.m2 key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }} @@ -45,14 +45,18 @@ jobs: working-directory: ./cbioportal run: | cp src/main/resources/application.properties.EXAMPLE src/main/resources/application.properties + - name: 'Create settings.xml for github packages' + working-directory: ./cbioportal + run: | + echo "github${{ github.actor }}${{ secrets.GITHUB_TOKEN }}" > settings.xml - name: 'Build cBioPortal once without tests' working-directory: ./cbioportal run: | - mvn -q -U -Ppublic -DskipTests clean install + mvn --settings settings.xml -q -U -Ppublic -DskipTests clean install - name: 'Build cbioportal with tests' working-directory: ./cbioportal run: | - mvn -q -U -Ppublic clean install + mvn --settings settings.xml -q -U -Ppublic clean install - name: 'Run tests separately' working-directory: ./cbioportal run: | @@ -60,4 +64,4 @@ jobs: - name: 'Run integration tests separately' working-directory: ./cbioportal run: | - mvn -U -Ppublic integration-test -Ddb.test.username=cbio_user -Ddb.test.password=somepassword \ No newline at end of file + mvn -U -Ppublic integration-test -Ddb.test.username=cbio_user -Ddb.test.password=somepassword diff --git a/.github/workflows/dockerimage.yml b/.github/workflows/dockerimage.yml index 7987d50f7b4..dbf3daa1314 100644 --- a/.github/workflows/dockerimage.yml +++ b/.github/workflows/dockerimage.yml @@ -3,12 +3,6 @@ on: push: branches: - master - - release-* - - rc - - rfc* - - demo-* - - fusion-sv-migration - - redis-branch-up-to-date tags: '*' jobs: @@ -46,7 +40,7 @@ jobs: uses: docker/setup-buildx-action@v3 - name: Publish Docker Image on Tag - uses: docker/build-push-action@v3 + uses: docker/build-push-action@v6 with: context: . push: true @@ -93,7 +87,7 @@ jobs: uses: docker/setup-buildx-action@v3 - name: Publish Docker Image on Tag - uses: docker/build-push-action@v3 + uses: docker/build-push-action@v6 with: context: . push: true @@ -128,3 +122,81 @@ jobs: image: ${{ steps.meta.outputs.tags }} dependency-snapshot: 'true' github-token: '${{ secrets.GITHUB_TOKEN }}' + + update_master_k8s_deployment: + needs: build_and_publish_web + if: github.repository == 'cBioPortal/cbioportal' && github.ref == 'refs/heads/master' + runs-on: ubuntu-latest + env: + DEPLOYMENT_FILE_PATH: "argocd/aws/203403084713/clusters/cbioportal-prod/apps/cbioportal" + DEPLOYMENT_FILE_NAMES: "cbioportal_backend_master_blue.yaml cbioportal_backend_master_green.yaml" + K8S_REPO: 'knowledgesystems/knowledgesystems-k8s-deployment' + ARGOCD_CLI_VER: '2.13.3' + ARGOCD_SERVER: 'argocd.cbioportal.org' + ARGOCD_APP: 'cbioportal' + ARGOCD_RESOURCE_OPTIONS: '--resource apps:Deployment:default/cbioportal-backend-master-blue --resource apps:Deployment:default/cbioportal-backend-master-green' + steps: + - name: Extract metadata + id: meta + uses: docker/metadata-action@v4 + with: + images: | + cbioportal/cbioportal + # Do not generate latest tag + flavor: | + latest=false + suffix=-web-shenandoah + tags: | + type=ref,event=branch + type=semver,pattern={{version}} + + - name: Extract Image Tag + run: | + DOCKER_TAG=${{ steps.meta.outputs.tags }} + docker pull $DOCKER_TAG + DOCKER_SHA=$(docker inspect --format="{{index .RepoDigests 0}}" $DOCKER_TAG) + echo "DOCKER_SHA=$DOCKER_SHA" >> $GITHUB_ENV + + - name: Checkout K8s Repo + uses: actions/checkout@v4 + with: + repository: ${{ env.K8S_REPO }} + token: ${{ secrets.K8S_REPO_TOKEN }} + + - name: Update Master Deployment File + run: | + for FILE in $DEPLOYMENT_FILE_NAMES; do + sed -i "s|image:.*|image: $DOCKER_SHA|" $DEPLOYMENT_FILE_PATH/$FILE + done + + - name: Add and commit changes to deployment file + run: | + git config --global user.email "cBioPortal-Action@github.com" + git config --global user.name "cBioPortal Backend Github Action" + if ! git diff --quiet; then + git add -A + git commit -m "Update master deployment" + else + echo "No changes to commit." + fi + + - name: Push changes to K8s repo + uses: ad-m/github-push-action@master + with: + github_token: '${{ secrets.K8S_REPO_TOKEN }}' + repository: ${{ env.K8S_REPO }} + branch: master + + - name: Setup ArgoCD + uses: clowdhaus/argo-cd-action/@main + with: + version: ${{ env.ARGOCD_CLI_VER }} + command: login ${{ env.ARGOCD_SERVER }} + options: --username ${{ secrets.ARGOCD_2034_USERNAME }} --password ${{ secrets.ARGOCD_2034_PASSWORD }} + + - name: Sync master deployment + uses: clowdhaus/argo-cd-action/@main + with: + version: ${{ env.ARGOCD_CLI_VER }} + command: app sync ${{ env.ARGOCD_APP }} + options: ${{ env.ARGOCD_RESOURCE_OPTIONS }} diff --git a/.github/workflows/integration-test.yml b/.github/workflows/integration-test.yml index a45a7fff646..9468d33b5f9 100644 --- a/.github/workflows/integration-test.yml +++ b/.github/workflows/integration-test.yml @@ -19,7 +19,7 @@ jobs: website: oracle.com release: 21 - name: 'Cache Maven packages' - uses: actions/cache@v1 + uses: actions/cache@v4 with: path: ~/.m2 key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }} @@ -31,7 +31,8 @@ jobs: - name: 'Build cbioportal' working-directory: ./cbioportal run: | - mvn -DskipTests clean install + echo "github${{ github.actor }}${{ secrets.GITHUB_TOKEN }}" > settings.xml + mvn --settings settings.xml -DskipTests clean install - name: 'Checkout cbioportal-docker-compose repo' uses: actions/checkout@master with: @@ -46,8 +47,6 @@ jobs: sed 's|spring.datasource.username=.*|spring.datasource.username=cbio_user|' | \ sed 's|spring.datasource.password=.*|spring.datasource.password=somepassword|' \ > application.properties - - name: 'Copy cgds.sql file into Docker Compose' - run: cp ./cbioportal/src/main/resources/db-scripts/cgds.sql ./cbioportal-docker-compose/data/. - name: 'Dump Properties' working-directory: ./cbioportal-docker-compose run: cat config/application.properties diff --git a/.github/workflows/label-check.yml b/.github/workflows/label-check.yml index ce8dd33328f..ce82906f7ec 100644 --- a/.github/workflows/label-check.yml +++ b/.github/workflows/label-check.yml @@ -32,20 +32,27 @@ jobs: id: check_labels run: | PR_NUMBER=$(jq -r ".number" $GITHUB_EVENT_PATH) - PR_LABELS=$(curl -s "https://api.github.com/repos/${{ github.repository }}/pulls/$PR_NUMBER" | \ + PR_LABELS_STRING=$(curl -s "https://api.github.com/repos/${{ github.repository }}/pulls/$PR_NUMBER" | \ jq -r '.labels[].name') + mapfile -t PR_LABELS <<< "$PR_LABELS_STRING" mapfile -t AVAILABLE_LABELS < labels.txt - for LABEL in ${PR_LABELS[@]}; do - if [[ "$LABEL" == "skip-changelog" ]]; then + pr_label_index=0 + while [ $pr_label_index -lt ${#PR_LABELS[@]} ] ; do + pr_label="${PR_LABELS[$pr_label_index]}" + if [[ "$pr_label" == "skip-changelog" ]] ; then echo "PR contains a valid label: skip-changelog" exit 0 # Valid label found, exit successfully fi - for AVAILABLE_LABEL in "${AVAILABLE_LABELS[@]}"; do - if [[ "$AVAILABLE_LABEL" == "$LABEL" ]]; then - echo "PR contains a valid label: $LABEL" + available_label_index=0 + while [ $available_label_index -lt ${#AVAILABLE_LABELS[@]} ] ; do + available_label="${AVAILABLE_LABELS[$available_label_index]}" + if [[ "$available_label" == "$pr_label" ]] ; then + echo "PR contains a valid label: $pr_label" exit 0 # Valid label found, exit successfully fi + available_label_index=$(($available_label_index+1)) done + pr_label_index=$(($pr_label_index+1)) done echo "No valid label found on PR." echo "Available label options from release-drafter.yml:" diff --git a/.github/workflows/maven-package-build.yml b/.github/workflows/maven-package-build.yml new file mode 100644 index 00000000000..9c30ac21283 --- /dev/null +++ b/.github/workflows/maven-package-build.yml @@ -0,0 +1,106 @@ +name: Build & Publish Maven Package + +on: + release: + types: + - published + workflow_dispatch: + inputs: + source_ref: + description: "Branch, release tag, or commit hash to build" + type: string + required: true + +env: + JAVA_VERSION: '21' + JAVA_DIST: 'temurin' + MAVEN_SERVER: 'central' + DEPLOYMENT_NAME_PREFIX: 'cbioportal' + +jobs: + maven-central: + runs-on: ubuntu-latest + permissions: + contents: read + steps: + - name: Checkout repository (manual trigger) + if: github.event_name == 'workflow_dispatch' + uses: actions/checkout@v4 + with: + ref: ${{ inputs.source_ref }} + + - name: Checkout repository (automatic trigger) + if: github.event_name == 'release' + uses: actions/checkout@v4 + + - name: Setup application.properties + run: | + cp src/main/resources/application.properties.EXAMPLE src/main/resources/application.properties + + - name: Setup java for Maven Central + uses: actions/setup-java@v4 + with: + java-version: ${{ env.JAVA_VERSION }} + distribution: ${{ env.JAVA_DIST }} + server-id: ${{ env.MAVEN_SERVER }} + server-username: MAVEN_USERNAME + server-password: MAVEN_PASSWORD + gpg-private-key: ${{ secrets.MAVEN_CENTRAL_GPG_KEY }} + gpg-passphrase: MAVEN_GPG_PASSPHRASE + + - name: Set maven version from source ref (manual trigger) + if: github.event_name == 'workflow_dispatch' + run: mvn versions:set -DnewVersion=${{ inputs.source_ref }} -DgenerateBackupPoms=false + + - name: Set maven version from release tag (automatic trigger) + if: github.event_name == 'release' + run: mvn versions:set -DnewVersion=${{ github.event.release.tag_name }} -DgenerateBackupPoms=false + + - name: Publish package to Maven Central + run: | + if [ "${{ github.event_name }}" == "workflow_dispatch" ]; then + TAG=${{ inputs.source_ref }} + elif [ "${{ github.event_name }}" == "release" ]; then + TAG=${{ github.event.release.tag_name }} + else + echo "Action triggered through a invalid event!"; + exit 1 + fi + + mvn --batch-mode deploy -DskipTests -DmavenCentral=true -DmavenCentralDeploymentName="$DEPLOYMENT_NAME_PREFIX-$TAG" + env: + MAVEN_USERNAME: ${{ secrets.MAVEN_CENTRAL_USERNAME }} + MAVEN_PASSWORD: ${{ secrets.MAVEN_CENTRAL_PASSWORD }} + MAVEN_GPG_PASSPHRASE: ${{ secrets.MAVEN_CENTRAL_GPG_PASSPHRASE }} + ref: ${{ inputs.source_ref }} + + - name: Check publish status + env: + ARTIFACT_ID: "cbioportal" + GROUP_ID_PATH: "io/github/cbioportal" + MAX_RETRIES: 30 + INTERVAL_SECONDS: 60 + run: | + if [ "${{ github.event_name }}" == "workflow_dispatch" ]; then + VERSION=${{ inputs.source_ref }} + elif [ "${{ github.event_name }}" == "release" ]; then + VERSION=${{ github.event.release.tag_name }} + else + echo "Action triggered through a invalid event!"; + exit 1 + fi + + URL="https://repo1.maven.org/maven2/${GROUP_ID_PATH}/${ARTIFACT_ID}/${VERSION}" + + for ((i=1; i<=$MAX_RETRIES; i++)); do + if curl --silent --head --fail "$URL" > /dev/null; then + echo "Package successfully published!" + exit 0 + else + echo "Package not yet published! Retrying check in $INTERVAL_SECONDS seconds..." + sleep "$INTERVAL_SECONDS" + fi + done + + echo "Successful publish status NOT FOUND after $MAX_RETRIES attempts." + exit 1 diff --git a/.github/workflows/retype-action.yml b/.github/workflows/retype-action.yml index 78d405220ca..8e18160d023 100644 --- a/.github/workflows/retype-action.yml +++ b/.github/workflows/retype-action.yml @@ -19,7 +19,7 @@ jobs: with: dotnet-version: 7.0.x - - uses: retypeapp/action-build@latest + - uses: retypeapp/action-build@ddc4449f15ae65b75e13198b88200bfd64aef168 # before v3.10.0, which breaks the news on homepage - uses: retypeapp/action-github-pages@latest with: diff --git a/.github/workflows/security-integration-test.yml b/.github/workflows/security-integration-test.yml index 5fd20693a50..9f5b6aa28d6 100644 --- a/.github/workflows/security-integration-test.yml +++ b/.github/workflows/security-integration-test.yml @@ -19,7 +19,7 @@ jobs: website: oracle.com release: 21 - name: 'Cache Maven packages' - uses: actions/cache@v1 + uses: actions/cache@v4 with: path: ~/.m2 key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }} diff --git a/.github/workflows/snapshot-release.yml b/.github/workflows/snapshot-release.yml new file mode 100644 index 00000000000..66a5f773f6e --- /dev/null +++ b/.github/workflows/snapshot-release.yml @@ -0,0 +1,40 @@ +name: Update POM for Snapshot Release + +on: + release: + types: + - published + +jobs: + update-pom: + runs-on: ubuntu-latest + if: github.event_name == 'release' + permissions: + contents: write + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + ref: 'master' + token: '${{ secrets.GITHUB_TOKEN }}' + + - name: Setup Git identity + run: | + git config --local user.email "github-actions@github.com" + git config --local user.name "github-actions" + + - name: Download semver management tool + run: | + wget -q https://raw.githubusercontent.com/fsaintjacques/semver-tool/master/src/semver + chmod +x semver + + - name: Update pom with snapshot release version + run: | + TAG=${{ github.event.release.tag_name }} + VERSION=${TAG#v} + SNAPSHOT_VERSION=$(./semver bump patch $VERSION) + SNAPSHOT_TAG=v"$SNAPSHOT_VERSION"-SNAPSHOT + sed -i "s|\(.*\)-SNAPSHOT|$SNAPSHOT_TAG|" pom.xml + git add pom.xml + git commit -m "Prepare for $SNAPSHOT_TAG" + git push \ No newline at end of file diff --git a/.github/workflows/sonarcloud.yml b/.github/workflows/sonarcloud.yml index 080f26af165..c8609df429d 100644 --- a/.github/workflows/sonarcloud.yml +++ b/.github/workflows/sonarcloud.yml @@ -18,13 +18,13 @@ jobs: with: java-version: 21 - name: Cache SonarCloud packages - uses: actions/cache@v1 + uses: actions/cache@v4 with: path: ~/.sonar/cache key: ${{ runner.os }}-sonar restore-keys: ${{ runner.os }}-sonar - name: Cache Maven packages - uses: actions/cache@v1 + uses: actions/cache@v4 with: path: ~/.m2 key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }} diff --git a/.github/workflows/spotless-check.yml b/.github/workflows/spotless-check.yml new file mode 100644 index 00000000000..c4d889c3f96 --- /dev/null +++ b/.github/workflows/spotless-check.yml @@ -0,0 +1,35 @@ +name: Spotless Check + +on: + push: + branches: + - master + pull_request: + branches: + - master + - release-* + - rc + +jobs: + spotless-check: + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Set up JDK 21 + uses: actions/setup-java@v3 + with: + distribution: 'temurin' + java-version: '21' + + - name: Cache Maven dependencies + uses: actions/cache@v3 + with: + path: ~/.m2 + key: maven-${{ runner.os }}-${{ hashFiles('**/pom.xml') }} + restore-keys: maven-${{ runner.os }}- + + - name: Run Spotless Check + run: mvn spotless:check diff --git a/.github/workflows/sprint-issues-rollover.yml b/.github/workflows/sprint-issues-rollover.yml new file mode 100644 index 00000000000..46b40dc57a6 --- /dev/null +++ b/.github/workflows/sprint-issues-rollover.yml @@ -0,0 +1,23 @@ +# This workflow will move all unfinish tickets to the next sprint + +name: "Sprint Issues Rollover" + +on: + schedule: + # Runs every Monday at 6pm EST + - cron: "0 22 * * 1" + +jobs: + main: + name: Move to next sprint + runs-on: ubuntu-latest + steps: + - uses: blombard/move-to-next-iteration@master + with: + owner: cBioPortal + number: 19 # The project number as you see it in the URL + token: ${{secrets.PROJECT_PAT}} # Needs 'project' write perms + iteration-field: Sprint # https://github.com/blombard/move-to-next-iteration/issues/7 + iteration: current + new-iteration: next + excluded-statuses: Done diff --git a/CODE_STYLE.md b/CODE_STYLE.md new file mode 100644 index 00000000000..1e0225e8ecb --- /dev/null +++ b/CODE_STYLE.md @@ -0,0 +1,392 @@ +## Introduction + +This document defines the coding standards for source files in the cBioPortal (Backend). + +The structure of this document is based on the [Google Java Style](https://google.github.io/styleguide/javaguide.html) reference and is a _work in progress_. + +## Source File Basics + +### File encoding: UTF-8 + +Source files must be encoded using `UTF-8`. + +### Indentation + +* Indentation uses _spaces_ (not tabs) +* Unix (LF), not DOS (CRLF) line endings +* Eliminate all trailing whitespace + * On Linux, Mac, etc.: `find . -type f -name "*.java" -exec perl -p -i -e "s/[ \t]$//g" {} \;` + +## Source file structure + +A source file consists of the following, in this exact order: + +* License +* Package statement +* Import statements +* Exactly one top-level class + +Exactly one blank line separates each of the above sections. + +### License (Need Help With License) + +Each source file must specify the following license at the very top of the file: + +```java +/* + * Copyright 2002-2023 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +``` + +Always check the date range in the license header. For example, if you've modified a file in 2022 whose header still reads: + +``` +* Copyright 2002-2018 the original author or authors. +``` + +Then be sure to update it to 2023 accordingly: + +``` +* Copyright 2002-2023 the original author or authors. +``` + +### Import statements + +The import statements are structured as follow: + +* import `org.cbioportal.*` +* import `org.springframework.*` +* import all other imports +* blank line +* import `java.*` +* blank line +* blank line +* import static all other imports + +Static imports should not be used in production code, but they should be used in test code, especially for things like `import static org.assertj.core.api.Assertions.assertThat;`. + +Although static imports are generally forbidden in production code, the following are use cases for which static imports are permissible. + +* constants (including enum constants): such as those in `java.nio.charset.StandardCharsets` or `org.springframework.core.annotation.MergedAnnotations.SearchStrategy` +* static factory methods for third-party DSLs: such as the methods in `org.junit.platform.engine.discovery.DiscoverySelectors` when used with the JUnit Platform `Launcher` API + +Wildcard imports such as `import java.util.*` or `import static org.assertj.core.api.Assertions.*` are forbidden, even in test code. + +### Java source file organization + +The following governs how the elements of a source file are organized: + +1. static fields +1. normal fields +1. constructors +1. (private) methods called from constructors +1. static factory methods +1. JavaBean properties (i.e., getters and setters) +1. method implementations coming from interfaces +1. private or protected templates that get called from method implementations coming from interfaces +1. other methods +1. `equals`, `hashCode`, and `toString` + +Note that private or protected methods called from method implementations should be placed immediately below the methods where they're used. In other words if there 3 interface method implementations with 3 private methods (one used from each), then the order of methods should include 1 interface and 1 private method in sequence, not 3 interface and then 3 private methods at the bottom. + +Above all, the organization of the code should feel _natural_. + +## Formatting + +### Braces + +#### Block-like constructs: K&R style + +Braces mostly follow the _Kernighan and Ritchie style_ (a.k.a., "Egyptian brackets") for nonempty blocks and block-like constructs: + +* No line break before the opening brace but prefixed by a single space +* Line break after the opening brace +* Line break before the closing brace +* Line break after the closing brace if that brace terminates a statement or the body of a method, constructor, or named class +* Line break before else, catch and finally statements + +Example: + +```java +return new MyClass() { + @Override + public void method() { + if (condition()) { + something(); + } + else { + try { + alternative(); + } + catch (ProblemException ex) { + recover(); + } + } + } +}; +``` + +### Line wrapping + +90 characters is the _preferred_ line length we aim for. In some cases the preferred length can be achieved by refactoring code slightly. In other cases it's just not possible. + +90 is not a hard limit. Lines between 90-105 are perfectly acceptable in many cases where it aids readability and where wrapping has the opposite effect of reducing readability. This is a judgement call and it's also important to seek consistency. Many times you can learn by looking how specific situations are handled in other parts of the code. + +Lines between 105-120 are allowed but discouraged and should be few. + +No lines should exceed 120 characters. + +The one big exception to the above line wrapping rules is Javadoc where we aim to wrap around 80 characters for maximum readability in all kinds of contexts -- for example, reading on Github, on your phone, etc. + +When wrapping a lengthy expression, 90 characters is the length at which we aim to wrap. Place separator symbols at the end of the current line rather than at the beginning of the next line. In this context, the following are considered separator symbols: `,`, `+`, `?`, `:`, `&&`, `||`. For example: + +```java +if (thisLengthyMethodCall(param1, param2) && anotherCheck() && + yetAnotherCheck()) { + + // .... +} +``` + +### Blank Lines + +Add two blank lines before the following elements: + +* `static {}` block +* Fields +* Constructors +* Inner classes + +Add one blank line after a method signature that is multiline, i.e. + +```java +@Override +protected Object invoke(FooBarOperationContext context, + AnotherSuperLongName name) { + + // code here +} +``` + +For inner-classes, extra blank lines around fields and constructors are typically not +added as the inner class is already separated by 2 lines, unless the inner class is +more substantial in which case the 2 extra lines could still help with readability. + +## Class declaration + +Try as much as possible to put the `implements`, `extends` section of a class declaration on the same line as the class itself. + +Order the classes so that the most important comes first. + +## Naming + +### Constant names + +Constant names use `CONSTANT_CASE`: all uppercase letters, with words separated by underscores. + +Every constant is a `static final` field, but not all `static final` fields are constants. Constant case should therefore be chosen only if the field **is really** a constant. + +Example: + +```java +// Constants +private static final Object NULL_HOLDER = new NullHolder(); +public static final int DEFAULT_PORT = -1; + +// Not constants +private static final ThreadLocal executorHolder = new ThreadLocal(); +private static final Set internalAnnotationAttributes = new HashSet(); +``` + +### Variable names + +Avoid using single characters as variable names. For instance prefer `Method method` to `Method m`. + +## Programming Practices + +### File history + +* A file should look like it was crafted by a single author, not like a history of changes. +* Don't artificially spread things out that belong together. + +### Organization of setter methods + +Choose wisely where to add a new setter method; it should not be simply added at the end of the list. Perhaps the setter is related to another setter or relates to a group. In that case it should be placed near related methods. + +* Setter order should reflect order of importance, not historical order. +* Ordering of _fields_ and _setters_ should be **consistent**. + +### Ternary Operator + +Wrap the ternary operator within parentheses -- for example, `return (foo != null ? foo : "default");`. + +Also make sure that the _not null_ condition comes first. + +### Null Checks + +Use the `org.springframework.util.Assert.notNull` static method to check that a method argument is not `null` and throw an `IllegalArgumentException` otherwise. Format the exception message so that the name of the parameter comes first with its first character capitalized, followed by "_must not be null_". For instance: + +```java +public void handle(Event event) { + Assert.notNull(event, "Event must not be null"); + //... +} +``` + +For other use cases, use the `org.springframework.util.Assert.state` static method to ensure a variable is not `null` and throw an `IllegalStateException` otherwise. Format the exception message so that the identifier related to the variable (name, type or description) comes first with its first character capitalized, followed by "_must not be null_". For instance: + +```java +//... +Event event = ... +Assert.state(event != null, "Event must not be null"); +//... +``` + +### Null Safety of APIs and fields + + +Nullable fields, return values and parameters are expected to be specified explicitly using `@Nullable`: + +```java +import org.springframework.lang.Nullable; + +public class MyClass { + + @Nullable + private Class nullableType; + + public void setNullableType(@Nullable Class nullableType) { + this.nullableType = nullableType; + } + + @Nullable + public Class getNullableType() { + return this.nullableType; + } +} +``` + +[`org.springframework.lang.Contract` annotation](https://docs.spring.io/spring-framework/docs/6.2.0-SNAPSHOT/javadoc-api/org/springframework/lang/Contract.html) can be used to specify some aspects of the method behavior depending on the arguments that are then [taken in account by NullAway](https://github.com/uber/NullAway/wiki/Supported-Annotations#contracts). See for example how `@Contract` is used in Spring Framework codebase in the `Assert` class: + +`Related guidelines: + +* When overriding a method, null-safety annotations of the super method need to be specified on the overridden method unless you want to override null-safety. +* Use `@SuppressWarnings("NullAway")` when NullAway triggers irrelevant errors, which can happen due to [NullAway bugs or missing features](https://github.com/uber/NullAway/issues) or when the analysis is not able to prove null-safety (can happen with lambdas). + +### Use of @Override + +Always add `@Override` on methods overriding or implementing a method declared in a super type. + +### Utility classes + +A class that is only a collection of static utility methods must be named with a `Utils` suffix, must have a `private` default constructor, and must be `abstract`. Making the class `abstract` and providing a `private` _default_ constructor prevent anyone from instantiating it. For example: + +```java +public abstract MyUtils { + + private MyUtils() { + /* prevent instantiation */ + } + + // static utility methods +} +``` + +### Field and method references + +A field of a class should _always_ be referenced using `this`. A method of a class, however, should never be referenced using `this`. + +### Local variable type inference + +The use of `var` for variable declarations (_local variable type inference_) is only allowed where it can improve +readability. Instead, declare variables using the concrete type or interface (where applicable). + +## Javadoc + +### Javadoc formatting + +The following template summarizes typical Javadoc usage for a method. + +```java +/** + * Parse the specified {@link Element} and register the resulting + * {@link BeanDefinition BeanDefinition(s)}. + *

Implementations must return the primary {@link BeanDefinition} that results + * from the parsing if they will ever be used in a nested fashion (for example as + * an inner tag in a {@code } tag). Implementations may return + * {@code null} if they will not be used in a nested fashion. + * @param element the element that is to be parsed into one or more {@link BeanDefinition BeanDefinitions} + * @param parserContext the object encapsulating the current state of the parsing process; + * provides access to a {@link org.springframework.beans.factory.support.BeanDefinitionRegistry} + * @return the primary {@link BeanDefinition} + */ +BeanDefinition parse(Element element, ParserContext parserContext); +``` + +In particular, please note: + +* Use an imperative style (i.e. _Return_ and not _Returns_) for the first sentence. +* No blank lines between the description and the parameter descriptions. +* If the description is defined with multiple paragraphs, start each of them with `

`. +* If a parameter description needs to be wrapped, do not indent subsequent lines (see `parserContext`). + +The Javadoc of a class has some extra rules that are illustrated by the sample below: + +```java +/* + * Interface used by the {@link DefaultBeanDefinitionDocumentReader} to handle custom, + * top-level (directly under {@code }) tags. + * + *

Implementations are free to turn the metadata in the custom tag into as many + * {@link BeanDefinition BeanDefinitions} as required. + * + *

The parser locates a {@link BeanDefinitionParser} from the associated + * {@link NamespaceHandler} for the namespace in which the custom tag resides. + * + * @author Rob Harrop + * @since 2.0 + * @see NamespaceHandler + * @see AbstractBeanDefinitionParser + */ +``` + +* The order of tags for type-level Javadoc is: `@author`, `@param`, `@see`, `@deprecated`. +* The order of tags for constructor-level, method-level, and field-level Javadoc is: `@param`, `@return`, `@throws`, `@see`, `@deprecated`. +* In contrast to constructor-level, method-level, and field-level Javadoc, the paragraphs of a class description _are_ separated by blank lines. + +The following are additional general rules to apply when writing Javadoc: + +* Use `{@code}` to wrap code statements or values such as `null`. +* If a type is only referenced by a `{@link}` element, use the fully qualified name in order to avoid an unnecessary `import` declaration. + +## Tests + +### Testing cBioPortal + +Tests must be written using JUnit 4 + +Stretch Goal Upgrade tests to JUnit 5!! + +### Naming + +Each test class name must end with a `Tests` suffix. + +### Assertions + +Use AssertJ for assertions. + +### Mocking + +Use the BDD Mockito support. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index c0bad8162ab..c07160376eb 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -28,7 +28,7 @@ From the [GitHub Help Page of Using Pull Requests](https://help.github.com/artic ### Programming * Make sure you have a [GitHub account](https://github.com/signup/free). - * Familiarize yourself with the [project documentation](https://docs.cbioportal.org), including the [Feature Development Guide](https://docs.cbioportal.org/development/feature-development-guide/), the [Architecture docs](https://docs.cbioportal.org/2.1-deployment/architecture-overview), the [backend code organization](docs/Backend-Code-Organization.md) and [backend development guidelines](docs/Backend-Development-Guidelines.md). + * Familiarize yourself with the [project documentation](https://docs.cbioportal.org), including the [Feature Development Guide](https://docs.cbioportal.org/development/feature-development-guide/), the [Architecture docs](https://docs.cbioportal.org/2.1-deployment/architecture-overview), the [backend code organization](https://docs.cbioportal.org/development/backend-code-organization/) and [backend development guidelines](https://docs.cbioportal.org/development/backend-development-guidelines/). * Find a [good first issue](https://github.com/cBioPortal/cbioportal/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc+label%3A%22good+first+issue%22) to start with * Check if the issue will require frontend or backend changes. If it is for the frontend look at how to set up the [frontend repo](https://github.com/cbioPortal/cbioportal-frontend/) instead * Fork the cbioportal or cbioportal-frontend project on GitHub depending on what your working on. For general instructions on forking a GitHub project, see [Forking a Repo](https://help.github.com/articles/fork-a-repo/) and [Syncing a fork](https://help.github.com/articles/syncing-a-fork/). @@ -64,7 +64,12 @@ A few tips: When you are ready to submit your pull-request: * Push your branch to your GitHub project. -* Open the pull request to the branch you've based your work on +* Always create a [draft pull request](https://github.blog/news-insights/product-news/introducing-draft-pull-requests/) first to indicate work in progress and gather early feedback. +* Ensure all CI checks and tests pass before marking the pull request as ready. +* Review your own code for formatting, correctness, and best practices. +* Provide a clear PR description to help reviewers understand the changes. +* Make sure your PR is based on the correct branch. +* Once you think the pull request is ready, you can [Mark a pull request as ready for review](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/changing-the-stage-of-a-pull-request#marking-a-pull-request-as-ready-for-review). For more details on submitting a pull-request, please see: [GitHub Guide to Collaborating with issues and pull requests](https://help.github.com/en/github/collaborating-with-issues-and-pull-requests). diff --git a/README.md b/README.md index 8b164e38dd1..6edd84c6806 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ See [https://docs.cbioportal.org](https://docs.cbioportal.org) See [LICENSE](./LICENSE) ## 💻 Run Backend -cBioPortal consists of several components, please read the [Architecture docs](https://docs.cbioportal.org/architecture-overview/) to figure out what repo would be relevant to edit. If you e.g. only want to make frontend changes, one can directly edit [the frontend repo](https://github.com/cbioportal/cbioportal-frontend) instead. Read the instructions in that repo for more info on how to do frontend development. This repo only contains the backend part. Before editing the backend, it's good to read the [backend code organization](docs/Backend-Code-Organization.md). +cBioPortal consists of several components, please read the [Architecture docs](https://docs.cbioportal.org/architecture-overview/) to figure out what repo would be relevant to edit. If you e.g. only want to make frontend changes, one can directly edit [the frontend repo](https://github.com/cbioportal/cbioportal-frontend) instead. Read the instructions in that repo for more info on how to do frontend development. This repo only contains the backend part. Before editing the backend, it's good to read the [backend code organization](docs/development/Backend-Code-Organization.md). ### Local Development @@ -129,3 +129,4 @@ Read the [Architecture docs](https://docs.cbioportal.org/2.1-deployment/architec - https://github.com/cBioPortal/cbioportal-frontend - https://github.com/cbioportal/session-service - https://github.com/cBioPortal/datahub/ +- https://github.com/cBioPortal/cbioportal-core diff --git a/docker/web-and-data/Dockerfile b/docker/web-and-data/Dockerfile index c8658f23fac..973c3c86b93 100644 --- a/docker/web-and-data/Dockerfile +++ b/docker/web-and-data/Dockerfile @@ -44,10 +44,11 @@ RUN apt-get update; apt-get install -y --no-install-recommends \ RUN mkdir -p /cbioportal #Download core files -RUN wget https://github.com/cBioPortal/cbioportal-core/releases/download/v1.0.9/core-1.0.9.jar -P core/ ; cd core ; jar -xf core-1.0.9.jar scripts/ requirements.txt ; chmod -R a+x scripts/ ; cd ..; +RUN wget https://github.com/cBioPortal/cbioportal-core/releases/download/v1.0.10/core-1.0.10.jar -P core/ ; cd core ; jar -xf core-1.0.10.jar scripts/ requirements.txt ; chmod -R a+x scripts/ ; cd ..; COPY --from=build /cbioportal/src/main/resources/db-scripts /cbioportal/db-scripts +COPY --from=build /cbioportal/test/test_data/study_es_0 /cbioportal/test/study_es_0 # install build and runtime dependencies # ignore update failure980[1298[01 w2308s @@ -73,4 +74,4 @@ COPY --from=build ${DEPENDENCY}/BOOT-INF/classes $PORTAL_WEB_HOME/ # add entrypoint COPY --from=build /cbioportal/docker/web-and-data/docker-entrypoint.sh /usr/local/bin/ ENTRYPOINT ["docker-entrypoint.sh"] -CMD ["sh", "-c", "java $(echo $JAVA_OPTS) -cp /cbioportal-webapp:/cbioportal-webapp/lib/* org.cbioportal.PortalApplication $(echo $WEBAPP_OPTS)"] +CMD ["sh", "-c", "java $(echo $JAVA_OPTS) -cp /cbioportal-webapp:/cbioportal-webapp/lib/* org.cbioportal.application.PortalApplication $(echo $WEBAPP_OPTS)"] diff --git a/docs/About-Us.md b/docs/About-Us.md index 01f1e7f7d9d..630ead4d99d 100644 --- a/docs/About-Us.md +++ b/docs/About-Us.md @@ -50,17 +50,17 @@ The cBioPortal for Cancer Genomics was originally developed at [Memorial Sloan K ## The Hyve * Oleguer Plantalech * Jessica Singh -* Matthijs Pon * Tim Kuijpers -* Mirella Kalafati * Sowmiyaa Senthil Kumar * Floris Vleugels * Laura Varela * Zeynep Karagoz +* Henk-Jan van den Ham ## SE4BIO * Pieter Lukasse * Ruslan Forostianov +* Guizela Huelsz Prince ## Bilkent University * Ugur Dogrusoz @@ -85,11 +85,13 @@ The cBioPortal for Cancer Genomics was originally developed at [Memorial Sloan K * Zachary Heins * Michael Heuer * Anders Jacobsen +* Mirella Kalafati * Peter Kok * Erik Larsson * Dong Li * Divya Madala * Tamba Monrose +* Matthijs Pon * Irina Pulyakhina * Pichai Raman * M Furkan Sahin @@ -124,9 +126,8 @@ The cBioPortal for Cancer Genomics was originally developed at [Memorial Sloan K * Marie-José and Henry R. Kravis Center for Molecular Oncology at MSK * Dana Farber Cancer Institute * American Association for Cancer Research through AACR Project GENIE -* Prostate Cancer Foundation -* The Cholangiocarcinoma Foundation -* Robertson Foundation +* Break Through Cancer +* Gray Foundation ### Past: * NCI, through [ITCR grant NCI-U24CA220457](https://itcr.nci.nih.gov/funded-project/cbioportal-cancer-genomics) @@ -139,3 +140,6 @@ The cBioPortal for Cancer Genomics was originally developed at [Memorial Sloan K * Adenoid Cystic Carcinoma Research Foundation * POETIC Consortium * Parker Institute for Cancer Immunotherapy +* Prostate Cancer Foundation +* The Cholangiocarcinoma Foundation +* Robertson Foundation diff --git a/docs/Architecture-Overview.md b/docs/Architecture-Overview.md index 8f54bc36ddd..a2751d84e0c 100644 --- a/docs/Architecture-Overview.md +++ b/docs/Architecture-Overview.md @@ -2,9 +2,11 @@ cBioPortal consists of the following components: - [backend](https://github.com/cBioPortal/cbioportal) - - MySQL database + - MySQL OLTP database - REST API written in Java Spring - - Redis cache for storing frequently used queries (optional) + - Optional components for performance enhancements: + - Clickhouse OLAP database for large cohorts (see [clickhouse mode](https://github.com/cbioPortal/cbioportal-docker-compose#clickhouse-mode)) + - Redis cache for storing study view initial load and other frequent queries and pages - [validator](https://github.com/cBioPortal/cbioportal/tree/master/core/src/main/scripts/importer) checks file formats before importing data into the database - [frontend](https://github.com/cBioPortal/cbioportal-frontend) @@ -25,7 +27,7 @@ to import data as well as the validator. The backend can be configured to connect to a Redis cache to store database query results for improved performance. The backend is organized as a multi-module Maven project. -See [cBioPortal backend code organization](Backend-Code-Organization.md). +See [cBioPortal backend code organization](./development/Backend-Code-Organization.md). ## Validator The diff --git a/docs/Backend-Code-Organization.md b/docs/Backend-Code-Organization.md deleted file mode 100644 index 9dad44b06fa..00000000000 --- a/docs/Backend-Code-Organization.md +++ /dev/null @@ -1,122 +0,0 @@ -# cBioPortal Backend Code Organization - -## Maven Project - -The backend code is structured as a [Maven](https://maven.apache.org/index.html) -project. Included in the repository are [pom.xml files](https://maven.apache.org/pom.html#What_is_the_POM) -which define the code components and modules which make up the backend. The pom.xml -files also list dependencies on external open source libraries, and dependencies between cBioPortal Maven modules. -They also give instructions for how to build and package code components into a -deployable format. - -### Refactoring - -The code base is undergoing a long term refactoring effort which is nearing completion. - -#### Web service refactoring - -The original data distribution service (still in operation) was a custom servlet called -[webservice.do](https://github.com/cBioPortal/cbioportal/blob/v3.1.5/core/src/main/java/org/mskcc/cbio/portal/servlet/WebService.java) -This servlet takes a "cmd" argument which selects the category of data requested. -More details can be seen on the cBioPortal [webAPI](https://www.cbioportal.org/webAPI) tab. - -An example request: -`curl -X GET "https://www.cbioportal.org/webservice.do?cmd=getGeneticProfiles&cancer_study_id=brca_tcga"` - -The new data distribution approach follows a [RESTful](https://en.wikipedia.org/wiki/Representational_state_transfer) approach, -mapping various URL paths to data services, allowing the specification of database -entities within the path as helpful. - -An example request: -`curl -X GET "https://www.cbioportal.org/api/studies/brca_tcga/molecular-profiles"` - -#### Presentation / frontend refactoring - -The original presentation code was written as a set of java service pages ([JSP](https://en.wikipedia.org/wiki/JavaServer_Pages)), -connected to servlets which populated needed data for page rendering into request attributes -within the backend server. You can see examples of the setting of these request attributes in -[this example servlet](https://github.com/cBioPortal/cbioportal/blob/master/core/src/main/java/org/mskcc/cbio/portal/servlet/QueryBuilder.java) - -This has largely been superceded and expanded on by a new [React](https://reactjs.org/) -javascript application located in a separate -[GitHub repository](https://github.com/cBioPortal/cbioportal-frontend), which maintains a -browser data store populated from the new RESTful Web API. Although the new frontend -project is not dependent on the original custom servlets for data delivery, we may continue -to use the servlet / JSP delivery path to embed configuration data in the initial HTML page -in order to allow us to optimize loading times. Some of this logic has already been -migrated out of the core module and moved to the portal module. - -### Current Maven Modules - -#### The core module - -The [core](https://github.com/cBioPortal/cbioportal/blob/master/core) module contains the oldest code in the code base. Much of -the backend web data services logic has been re-implemented and expanded in -other backend maven modules, such as [model](https://github.com/cBioPortal/cbioportal/blob/master/model), -[persistence-mybatis](https://github.com/cBioPortal/cbioportal/blob/master/persistence/persistence-mybatis), -[service](https://github.com/cBioPortal/cbioportal/blob/master/service), and [web](https://github.com/cBioPortal/cbioportal/blob/master/web). We plan to discontinue the legacy -webservice.do data servlet and fully transition to the new data services API in -the near future. The core module will then be purged of much of the legacy -code. Any surviving functionality (such as the handling of global configuration -properties) may be relocated into new modules. It is therefore important that -no new code features be introduced which are dependent on the core module -functionality. - -#### The central stack modules : web, service, persistence - -Three maven modules make up the central stack of the new web API implementation. - -* [web](https://github.com/cBioPortal/cbioportal/blob/master/web) : define Web API request handlers, map endpoints, select services -* [service](https://github.com/cBioPortal/cbioportal/blob/master/service) : call persistence module or utils, apply business logic -* [persistence](https://github.com/cBioPortal/cbioportal/blob/master/persistence) : retrieve data from database. Two submodules: - * [persistence-api](https://github.com/cBioPortal/cbioportal/blob/master/persistence/persistence-api) : declaration of repository classes / functions, caching markup - * [persistence-mybatis](https://github.com/cBioPortal/cbioportal/blob/master/persistence/persistence-mybatis) : implementation of persistence-api using [MyBatis](https://mybatis.org/mybatis-3/) mappers - -#### Other modules - -* [model](https://github.com/cBioPortal/cbioportal/blob/master/model) : data model POJO classes (used throughout the stack) -* [security](https://github.com/cBioPortal/cbioportal/blob/master/security) : user authentication methods and authorization, request filters -* [business](https://github.com/cBioPortal/cbioportal/blob/master/business) : a legacy refactor of webservice.do, has active dataSource definition -* [portal](https://github.com/cBioPortal/cbioportal/blob/master/portal) : web application packaging and launch -* [scripts](https://github.com/cBioPortal/cbioportal/blob/master/scripts) : data import tool packaging (from core module scripts package) -* [db_scripts](https://github.com/cBioPortal/cbioportal/blob/master/db_scripts) : installation and migration scripts for the database - -#### External code modules - -* [cbioportal-frontend](https://github.com/cBioPortal/cbioportal-frontend) : a React application using MobX and TypeScript -* [session-service](https://github.com/cBioPortal/session-service) : an external session key/query specifier storage system - -**cbioportal-frontend** is packaged in the web application as a default frontend -implementation, but the source of the frontend code can also be directed to an external -source host and be deployed independently of the backend web application. See -[details](Deployment-Procedure.md) - -**session-service** is imported into the web module in order to set up a proxy service -which receives and forwards requests for saved cBioPortal sessions to a separate system -providing this storage (using a document based database) The code is needed for handling -modeled types such as VirtualStudy and Session - -### cBioPortal Module Dependencies - -![Module Dependencies](images/maven-module-dependencies.png) - -_A module is directly dependent on all modules which touch it from below (touching only at a corner -does not count). Dependencies are transitive : web is dependent on service, service -is dependent on persistence-mybatis, therefore web is also dependent on -persistence-mybatis. During packaging, all dependencies are made available to the -dependent package for use. Avoid creating new dependencies between modules. -**cyclical dependencies will cause errors during build**_ - -Module | Dependencies ------- | ------------ -portal | core, _cbioportal-frontend_ -scripts | core -core | web -web | business, service, _session-service_ -security-spring | service -service | persistence-mybatis -persistence-mybatis | persistence-api, db-scripts -persistence-api | model -business | model -db-scripts | -model | diff --git a/docs/Data-Loading.md b/docs/Data-Loading.md index 5911dae03ec..03917ef3d19 100644 --- a/docs/Data-Loading.md +++ b/docs/Data-Loading.md @@ -10,6 +10,8 @@ Getting your study data into cBioPortal requires four steps: 3. [Validating your study data](#validating-your-study-data) 4. [Loading your study data](#loading-data) +If using a ClickHouse OLAP database in conjunction with the MySQL OLTP database, additional steps will be needed after completing the steps above. For guidance, see these [tools](https://github.com/cBioPortal/cbioportal-core/blob/main/scripts/clickhouse_import_support/README.md) in the cbioportal-core repository. These are available as a Docker image (used during a [Docker Compose launch](https://github.com/cBioPortal/cbioportal-docker-compose?tab=readme-ov-file#clickhouse-mode) of a ClickHouse Mode portal.) + ## Setting up the validator ### Installation diff --git a/docs/Donate.md b/docs/Donate.md index a17d38ba893..9da579de985 100644 --- a/docs/Donate.md +++ b/docs/Donate.md @@ -1,8 +1,6 @@ ## The cBioPortal Foundation -The mission of cBioPortal Foundation is to support the development and adoption of the cBioPortal for Cancer Genomics, open-source software for the interactive exploration of multidimensional cancer genomics data sets. The cBioPortal aims to significantly lower the barriers between complex genomic data and cancer researchers by providing rapid, intuitive, and high-quality access to molecular profiles and clinical attributes from large-scale cancer genomics projects, and by doing so, empower researchers to translate these rich data sets into biologic insights and clinical applications. - -The cBioPortal Foundation will help further the mission of cBioPortal by supporting hackathons, user meetings, internships and other activities. +Our mission is to enhance, sustain, and expand the open-source cBioPortal platform to empower researchers worldwide ## Contribute to cBioPortal Foundation @@ -16,6 +14,4 @@ Retirement Accounts • Charitable Trusts Stocks • Bonds • Real Estate • Collectibles • Art Cryptocurrency • Privately Held Business Interests -[Asset & Large Contributions](https://lohas.org/client/cbioportal-foundation/#donation_form) - -[!button Donate](https://abqwvktl.donorsupport.co/page/FUNFLDNZDHK) +[!button icon="heart-fill" text="Online Donations" variant="danger"](https://abqwvktl.donorsupport.co/page/FUNFLDNZDHK) [!button icon="heart-fill" text="Asset & Large Contributions" variant="primary"](https://lohas.org/client/cbioportal-foundation/#donation_form) diff --git a/docs/File-Formats.md b/docs/File-Formats.md index ccdafd68756..6801fde3a70 100644 --- a/docs/File-Formats.md +++ b/docs/File-Formats.md @@ -796,7 +796,7 @@ Allele specific copy number (ASCN) annotation is also supported and may be added 49. **ASCN.ASCN_INTEGER_COPY_NUMER (Optional)**: Absolute integer copy-number estimate. ### Example cBioPortal mutation data file -An example cBioPortal mutation data file can be found in the cBioPortal test study [study_es_0](https://github.com/cBioPortal/cbioportal/blob/master/core/src/test/scripts/test_data/study_es_0/data_mutations_extended.maf). +An example cBioPortal mutation data file can be found in the cBioPortal test study [study_es_0](https://github.com/cBioPortal/cbioportal/blob/master/test/test_data/study_es_0/data_mutations_extended.maf). ### Filtered mutations A special case for **Entrez_Gene_Id=0** and **Hugo_Symbol=Unknown**: when this combination is given, the record is parsed in the same way as **Variant_Classification=IGR** and therefore filtered out. diff --git a/docs/Hardware-Requirements.md b/docs/Hardware-Requirements.md index 4746fef4c20..40ad0a45f9d 100644 --- a/docs/Hardware-Requirements.md +++ b/docs/Hardware-Requirements.md @@ -4,7 +4,7 @@ Hardware requirements will vary depending on the volume of users you anticipate will access your cBioPortal instance and the amount of data loaded in the portal. We run [cbioportal.org](https://www.cbioportal.org) on an AWS r5.xlarge instance with 32 GB and 4 vCPUs. The public database consumes ~50 GB of disk -space. The site is visited by several thousands of users a day. For on-premise +space. The site is visited by thousands of users a day. For on-premise installation recommendations one can look at the AWS instance type specs: | Platform | instance type | (v)CPUs | RAM(GB) | Storage (GB) | diff --git a/docs/Migration-Guide.md b/docs/Migration-Guide.md index 06496997b8e..7a1e93ae9f3 100644 --- a/docs/Migration-Guide.md +++ b/docs/Migration-Guide.md @@ -2,6 +2,12 @@ This page describes various changes deployers will need to make as they deploy newer versions of the portal. +## v6.2 -> v6.3 +- cBioPortal Database Migration: [v6.3.0](https://github.com/cBioPortal/cbioportal/releases/tag/v6.3.0) introduces breaking changes to the cBioPortal database schema. Please see the [Database Migration Guide](https://docs.cbioportal.org/updating-your-cbioportal-installation/#running-the-migration-script) before upgrading cBioPortal to v6.3.0. + +## v6.0 -> v6.1 +- cBioPortal Frontend Package: [v6.1.0](https://github.com/cBioPortal/cbioportal/releases/tag/v6.1.0) replaces JitPack with GitHub Packages for distributing the [frontend package](https://github.com/orgs/cBioPortal/packages?repo_name=cbioportal-frontend). This requires users to authenticate with GitHub when building cBioPortal from source. Check [docs](https://docs.cbioportal.org/deployment/deploy-without-docker/build-from-source/) for detailed instructions. + ## v6.0.23 -> v6.0.24 - Redis HTTP Session: diff --git a/docs/News.md b/docs/News.md index 3c527bf7332..d8066150158 100644 --- a/docs/News.md +++ b/docs/News.md @@ -1,3 +1,27 @@ +## May 06, 2025 +* **Added data** consisting of 4,571 samples from 10 studies: + * [Pancreatic Adenocarcinoma (MSK, Nat Med 2024)](https://www.cbioportal.org/study/summary?id=pdac_msk_2024) *2336 samples* + * [Cerebrospinal Fluid Circulating Tumor DNA (MSK, Acta Neuropathol Commun 2024)](https://www.cbioportal.org/study/summary?id=csf_msk_2024) *1007 samples* + * [Ovarian Cancer (Gray Foundation, Cancer Discov 2024)](https://www.cbioportal.org/study/summary?id=ovary_geomx_gray_foundation_2024) *567 samples* + * [Normal Melanocytes (UCSF, Nature 2020)](https://www.cbioportal.org/study/summary?id=normal_skin_melanocytes_2024) *153 samples* + * [Normal Keratinocytes from human skin (UCSF, BioRxiv 2024)](https://www.cbioportal.org/study/summary?id=normal_skin_keratinocytes_2024) *136 samples* + * [BRAF Fusions - ARCHER Clinical Sequencing Cohort (MSK, Clin Cancer Res 2024)](https://www.cbioportal.org/study/summary?id=braf_msk_archer_2024) *107 samples* + * [BRAF Fusions - IMPACT Clinical Sequencing Cohort (MSK, Clin Cancer Res 2024)](https://www.cbioportal.org/study/summary?id=braf_msk_impact_2024) *105 samples* + * [Sarcoma (UCLA, Cell 2024)](https://www.cbioportal.org/study/summary?id=sarcoma_ucla_2024) *63 samples* + * [Classical Hodgkins Lymphoma (SCCC, Blood Cancer Discov 2023)](https://www.cbioportal.org/study/summary?id=chl_sccc_2023) *61 samples* + * [Normal Fibroblasts from human skin (UCSF, BioRxiv 2024)](https://www.cbioportal.org/study/summary?id=normal_skin_fibroblast_2024) *18 samples* + +* **Gene Tables Update:** Updated tables of genes (main and alias), based on [Oct 1, 2024 HGNC release](https://www.genenames.org/download/archive/monthly/tsv/). See seedDB release notes [here](https://github.com/cBioPortal/datahub/tree/master/seedDB#latest-seed-database-schema-2131) for details. + +## April 17, 2025 +* Released a [new about page](https://about.cbioportal.org/), which includes a roadmap and an overview of 2024 accomplishments. + +## January 28, 2025 +* **Enhancement:** You can now re-order the stacked bar charts in the Plots Tab alphabetically, by the number of samples or by the data category in the plot. This enhancement allows you to create more ready-to-publish figures using cBioPortal. As usual, the plots created in the Plots Tab can be downloaded in different formats. [Example: specimen type for each cancer type in MSK-IMPACT Clinical Sequencing Cohort (MSK, Nat Med 2017](https://www.cbioportal.org/study/plots?id=msk_impact_2017&plots_horz_selection=%7B%22dataType%22%3A%22clinical_attribute%22%2C%22selectedDataSourceOption%22%3A%22CANCER_TYPE%22%2C%22mutationCountBy%22%3A%22MutationType%22%2C%22logScale%22%3A%22false%22%7D&plots_vert_selection=%7B%22selectedGeneOption%22%3A7157%2C%22dataType%22%3A%22clinical_attribute%22%2C%22selectedDataSourceOption%22%3A%22SPECIMEN_TYPE%22%2C%22mutationCountBy%22%3A%22MutationType%22%2C%22logScale%22%3A%22false%22%7D&plots_coloring_selection=%7B%7D) + +![image](https://github.com/user-attachments/assets/c147794f-390a-4dec-a252-8fd324ea72e9) + + ## December 18, 2024 * **Added data** consisting of 34,904 samples from 9 studies: * [MSK-CHORD (MSK, Nature 2024)](https://www.cbioportal.org/study/summary?id=msk_chord_2024) *25040 samples* diff --git a/docs/RFC-List.md b/docs/RFC-List.md index 0dd7167a187..a4ee903dd23 100644 --- a/docs/RFC-List.md +++ b/docs/RFC-List.md @@ -7,6 +7,7 @@ See this [shared google folder](https://drive.google.com/drive/folders/0B6z8AlO4 # For Developers Creating new RFCs +* Evaluate whether your feature enhancement warrants an RFC. See the [Feature Development Guide](./development/feature-development-guide.md) for more details * Use the [RFC Template](https://docs.google.com/document/d/1nXi_to7U7qDR41hmrVtIPZBrRS1z4WI4OiT79s6Pc4I/edit) * Create your RFC within this [shared google folder](https://drive.google.com/drive/folders/0B6z8AlO4d-qMT0Zpd0J4cW5LbHc), and pick a new incremental number. * Add a Link to your RFC on this page. diff --git a/docs/SUMMARY.md b/docs/SUMMARY.md index ff211dfa423..43b2809d0f8 100644 --- a/docs/SUMMARY.md +++ b/docs/SUMMARY.md @@ -2,6 +2,7 @@ * [Home](README.md) * [About Us](About-Us.md) +* [Supported Data Types](Supported-Data-Types.md) * [List of RFCs](RFC-List.md) * [User Guide](user-guide/README.md) * [New Users](user-guide/new-users.md) @@ -26,8 +27,10 @@ * [Importing the Seed Database](deployment/deploy-without-docker/Import-the-Seed-Database.md) * [Deploying the Web Application](deployment/deploy-without-docker/Deploying.md) * [Loading a Sample Study](deployment/deploy-without-docker/Load-Sample-Cancer-Study.md) + * [Standalone Deployment](deployment/standalone/README.md) * [Deploy with Kubernetes](deployment/kubernetes/README.md) * [Authorization and Authentication](deployment/authorization-and-authentication/README.md) + * [Spring Security](deployment/authorization-and-authentication/Spring-Security.md) * [User Authorization](deployment/authorization-and-authentication/User-Authorization.md) * [Authenticating Users via SAML](deployment/authorization-and-authentication/Authenticating-Users-via-SAML.md) * [Authenticating Users via LDAP](deployment/authorization-and-authentication/Authenticating-Users-via-LDAP.md) @@ -67,6 +70,8 @@ * [Feature Development Guide](development/feature-development-guide.md) * [cBioPortal Entity-relationship Diagram](development/cBioPortal-ER-Diagram.md) * [cBioPortal Database Versioning](development/Database-Versioning.md) + * [Backend Code Organization](development/Backend-Code-Organization.md) + * [Backend Development Guidelines](development/Backend-Development-Guidelines.md) * [Build cBioPortal with a different frontend version](development/Build-Different-Frontend.md) * [Session Service](development/session-service-working.md) * [Manual test cases](development/manual-test-cases.md) @@ -74,4 +79,3 @@ * [Deployment Procedure](development/Deployment-Procedure.md) * [Security](development/Security.md) * [This documentation site](development/Documentation-site.md) -* [Donate](Donate.md) diff --git a/docs/Supported-Data-Types.md b/docs/Supported-Data-Types.md new file mode 100644 index 00000000000..ac7ca7f7d72 --- /dev/null +++ b/docs/Supported-Data-Types.md @@ -0,0 +1,42 @@ +# Supported Data Types + +cBioPortal is a multimodal cancer data visualization tool and supports a variety of data types. For some data types, we have explicit support; for others, you can leverage generic assay or clinical data to assign arbitrary data to either a sample or patient. Beyond including data directly into cBioPortal, one can also link in additional external viewers specialized for particular data types, or even entirely different dashboards or portals. This combination of structured and flexible data formats, as well as the option to link out to other viewers, allows cBioPortal to be used for many different combinations of clinical data and profiling methods. + +## Molecular Data + +| Assay | Processed Data | cBioPortal Data Type | Example cBioPortal Study | +| --- | --- | --- | --- | +| Bulk DNA Sequencing | Mutations | [Mutations](./File-Formats.md#mutation-data) | [MSK-IMPACT (Nat Med, 2017)](https://www.cbioportal.org/study/summary?id=msk_impact_2017) | +| - | Copy Number Alterations per Gene (CNA) | [CNA](./File-Formats.md#discrete-copy-number-data) | [MSK-IMPACT (Nat Med, 2017)](https://www.cbioportal.org/study/summary?id=msk_impact_2017) | +| - | Arm Level CNA Data | [Generic Assay](./File-Formats.md#arm-level-cna-data) | [TCGA Pancan (Cell 2018)](https://www.cbioportal.org/study/summary?id=acc_tcga_pan_can_atlas_2018) | +| - | Copy Number Segmentation | [Segmented Data](./File-Formats.md#segmented-data) | [MSK-IMPACT (Nat Med, 2017)](https://www.cbioportal.org/patient?studyId=msk_impact_2017&caseId=P-0000004) | +| - | Structural Variants | [Structural Variants](./File-Formats.md#structural-variant-data) | [PCAWG (Nature, 2020)](https://www.cbioportal.org/study/summary?id=pancan_pcawg_2020) | +| - | Mutational Signatures | [Generic Assay](./File-Formats.md#mutational-signature-data) | [PCAWG (Nature, 2020)](https://www.cbioportal.org/study/summary?id=pancan_pcawg_2020) | +| - | Genetic Ancestry | [Generic Assay](./File-Formats.md#generic-assay) | [TCGA Pancan (Cell, 2018)](https://www.cbioportal.org/study/summary?id=acc_tcga_pan_can_atlas_2018) | +| Bulk RNA Sequencing | Expression | [Expression](./File-Formats.md#expression-data) | [TCGA Pancan (Cell, 2018)](https://www.cbioportal.org/study/summary?id=acc_tcga_pan_can_atlas_2018) | +| Bulk DNA Methylation | Methylation per probe | [Generic Assay](./File-Formats.md#methylation-data) | [TCGA Pancan (Cell, 2018)](https://www.cbioportal.org/study/summary?id=acc_tcga_pan_can_atlas_2018) | +| Proteomics | Protein Expression | [Protein Expression](./File-Formats.md#protein-level-data) | [Cancer Cell Line Encyclopedia (Broad, 2019)](https://www.cbioportal.org/study/summary?id=ccle_broad_2019) | +| Other Assays | Any sample-level and/or patient-level attributes (e.g. LHA types, microbiome) | [Generic Assay](./File-Formats.md#generic-assay) | | + + +### External Viewer Integration + +There are several other data types for which there is no native support. However cBioPortal offers a generic way of linking in additional viewers using the [Resource Data Format](./File-Formats#resource-data). Technically this is known as an iframe link. These viewers can be linked at the cohort, patient or individual sample level. Beyond just linking viewers, we also have several suggestions on what kind of derived data can be added from these assays directly into cBioPortal for multimodal analysis. This mainly leverages the [Generic Assay Format](./File-Formats#generic-assay). + + +| Assay | External Viewer | Derived data to load into cBioPortal | Example cBioPortal Study | +| --- | --- | --- | --- | +| scRNAseq | CellxGene, Vitesssce, Broad Single Cell Portal | Cell fractions per sample, pseudobulk expression per gene per sample | [HTAN Vanderbilt (Cell, 2021)](https://www.cbioportal.org/study/summary?id=msk_spectrum_tme_2022) | +| GeoMx | Minerva | RNA expression per Region of Interest | [Ovarian Cancer (Gray Foundation, Cancer Discov 2024)](https://www.cbioportal.org/study/summary?id=ovary_geomx_gray_foundation_2024) | +| CyCIF/ORION | Minerva | Cell marker density in tumor regions | [Colorectal Adenocarcinoma (DFCI/Orion, 2024)](https://www.cbioportal.org/study/summary?id=crc_orion_2024) | +| H&E | Minerva, CDSA| | [MSK SPECTRUM (Nature, 2022)](https://www.cbioportal.org/patient/openResource_HE?studyId=msk_spectrum_tme_2022&caseId=P-0042164) | +| CT | OHIF | Tumor volume, density, etc. | [TCGA Pancan (Cell, 2021)](https://viewer.imaging.datacommons.cancer.gov/viewer/1.3.6.1.4.1.14519.5.2.1.8421.4017.206944705526266221852495854472) | +| scDNAseq | CellxGene, Vitesssce, Broad Single Cell Portal | | | +| scATACseq | CellxGene, Vitesssce, Broad Single Cell Portal | | | +| Tapestri | TBD | Protein expression per sample | TBD | +| 3D CyCIF | TBD | TBD | TBD | +| Your custom assay | Your custom viewer | Any sample-level or patient-level data | | + +## Clinical Data + +The clinical data are free-form de-identified patient and sample attributes. We don't follow a specific ontology, but rely on the authors of the published studies to determine the organization of their clinical data. The only exception is the cancer type categorization which uses the [Oncotree](https://oncotree.info) ontology. We do allow encoding of the data type for each column (e.g. numerical, text, etc). More details can be found in the [Clinical Data File Formats section](./File-Formats.md#clinical-data). We also have a [timeline format](./File-Formats.md#timeline-data) for incorporating treatment information (see e.g. [this](https://genie.cbioportal.org/patient/summary?studyId=nsclc_public_genie_bpc&caseId=GENIE-DFCI-004022) AACR GENIE lung cancer case). diff --git a/docs/Updating-your-cBioPortal-installation.md b/docs/Updating-your-cBioPortal-installation.md index 6f4d4abc515..371a4cf2985 100644 --- a/docs/Updating-your-cBioPortal-installation.md +++ b/docs/Updating-your-cBioPortal-installation.md @@ -16,10 +16,12 @@ If you get `DB version expected by Portal: 0` (i.e. you are building the new rel #### Step1 -In your `application.properties` file (e.g. `/src/main/resources/application.properties`) add the following property: +In your `application.properties` file (e.g. `/src/main/resources/application.properties`) add the following properties: ``` # this is the *expected* DB version (expected by the code). Don't set it manually, it is filled by maven: db.version=${db.version} +# this is the *expected* derived table schema version (expected by the code). Don't set it manually, it is filled by maven: +derived_table.version=${derived_table.version} ``` #### Step2 diff --git a/docs/deployment/authorization-and-authentication/Spring-Security.md b/docs/deployment/authorization-and-authentication/Spring-Security.md new file mode 100644 index 00000000000..bd9af2d36de --- /dev/null +++ b/docs/deployment/authorization-and-authentication/Spring-Security.md @@ -0,0 +1,4 @@ +# Spring Security +The cBioPortal app leverages [Spring Security](https://spring.io/projects/spring-security) to configure authorization and authentication. Some example settings can be found in the [security.properties.EXAMPLE](https://github.com/cBioPortal/cbioportal/blob/master/src/main/resources/security.properties.EXAMPLE) file. For more information on how to configure Spring Security, see the documentation: + +- [OAuth2 Configuration](https://docs.spring.io/spring-boot/reference/web/spring-security.html#web.security.oauth2) diff --git a/docs/deployment/customization/Customizing-your-instance-of-cBioPortal.md b/docs/deployment/customization/Customizing-your-instance-of-cBioPortal.md index a32ae690acd..a7c7d7f0079 100644 --- a/docs/deployment/customization/Customizing-your-instance-of-cBioPortal.md +++ b/docs/deployment/customization/Customizing-your-instance-of-cBioPortal.md @@ -284,6 +284,12 @@ If the download_group is present in user groups then download options are shown disabled string + + google_tag_manager_id + enables google tag manager on your site + disabled + string + diff --git a/docs/deployment/customization/application.properties-Reference.md b/docs/deployment/customization/application.properties-Reference.md index 27effb73292..9d41a7f2ed4 100644 --- a/docs/deployment/customization/application.properties-Reference.md +++ b/docs/deployment/customization/application.properties-Reference.md @@ -1,6 +1,6 @@ # More application.properties Settings -This page describes the main properties within application.properties. +This page describes the main properties within application.properties. Note that auth-related properties can be found in [security.properties-Reference](./security.properties-Reference.md). ## Database Settings @@ -268,14 +268,6 @@ Example of json file contents: } ``` -### Choose the display name for authenticated users - -By default the display name for authenticated users is email, but it can be changed for the user name: - -``` -skin.user_display_name=username -``` - ### Hide p- and q-values in survival types table ``` diff --git a/docs/deployment/customization/security.properties-Reference.md b/docs/deployment/customization/security.properties-Reference.md index c63b828ed23..6ac72562886 100644 --- a/docs/deployment/customization/security.properties-Reference.md +++ b/docs/deployment/customization/security.properties-Reference.md @@ -1,6 +1,6 @@ -# Application Properties +# Security Properties -The following are the properties for configuring authentication and authorization in the application. +The following are the properties for configuring authentication and authorization in the application. The cBioPortal application mainly uses Spring Security for auth configuration; see also [Spring Security](./../authorization-and-authentication/authorization-and-authentication/Spring-Security.md) docs. ## Authentication Configuration @@ -134,4 +134,4 @@ To enable all origins use * ```properties security.cors.allowed-origins=* ##Or http://localhost:8080,http://localhost:8081 -``` \ No newline at end of file +``` diff --git a/docs/deployment/deploy-without-docker/Build-from-Source.md b/docs/deployment/deploy-without-docker/Build-from-Source.md index 52625640bd1..6e4674fe500 100644 --- a/docs/deployment/deploy-without-docker/Build-from-Source.md +++ b/docs/deployment/deploy-without-docker/Build-from-Source.md @@ -2,7 +2,7 @@ ## Building with Maven -To compile the cBioPortal source code, move into the root directory and run the following maven command: +To compile the cBioPortal source code, move into the root directory and run the following maven command. ``` mvn -DskipTests clean install diff --git a/docs/deployment/deploy-without-docker/Load-Sample-Cancer-Study.md b/docs/deployment/deploy-without-docker/Load-Sample-Cancer-Study.md index 37c653026de..14e166fcd2e 100644 --- a/docs/deployment/deploy-without-docker/Load-Sample-Cancer-Study.md +++ b/docs/deployment/deploy-without-docker/Load-Sample-Cancer-Study.md @@ -38,9 +38,9 @@ export PORTAL_HOME=/Users/johndoe/cbioportal The sample gene panel has to be imported before gene panel study data can be added to the database. ``` -cd cbioportal-core/src/main/resources/scripts -./importGenePanel.pl --data ../../test/scripts/test_data/study_es_0/data_gene_panel_testpanel1.txt -./importGenePanel.pl --data ../../test/scripts/test_data/study_es_0/data_gene_panel_testpanel2.txt +cd cbioportal-core/scripts +./importGenePanel.pl --data ../tests/test_data/study_es_0/data_gene_panel_testpanel1.txt +./importGenePanel.pl --data ../tests/test_data/study_es_0/data_gene_panel_testpanel2.txt ``` After loading gene panels into the database, please restart Tomcat or call the `/api/cache` endpoint with a `DELETE` http-request @@ -56,13 +56,13 @@ First it's useful to validate the study `study_es_0`, to check if the data is fo To do so, go to the importer folder: ``` -cd cbioprtal-core/src/main/scripts/importer +cd cbioprtal-core/scripts/importer ``` and then run the following command: ``` -./validateData.py -s ../../../test/scripts/test_data/study_es_0/ -n +./validateData.py -s ../../tests/test_data/study_es_0/ -n ``` If all goes well, you should see the final output message: @@ -76,13 +76,13 @@ Validation of study succeeded with warnings. To import the sample study: ``` -cd cbioportal-core/src/main/scripts/importer +cd cbioportal-core/scripts/importer ``` and then run the following command: ``` -./metaImport.py -s ../../../test/scripts/test_data/study_es_0/ -n -o +./metaImport.py -s ../../tests/test_data/study_es_0/ -n -o ``` You will see a series of output messages, hopefully ending with a status message like this: diff --git a/docs/deployment/deploy-without-docker/README.md b/docs/deployment/deploy-without-docker/README.md new file mode 100644 index 00000000000..78dd83954a5 --- /dev/null +++ b/docs/deployment/deploy-without-docker/README.md @@ -0,0 +1,10 @@ +# Deploy without Docker + +We strongly encourage to use Docker due to the complex architecture of the app, but if that's not possible you can build the various aspects of the application yourself: + + 1. [Software Requirements](Software-Requirements.md) + 2. [Pre-Build Steps](Pre-Build-Steps.md) + 3. [Building from Source](Build-from-Source.md) + 4. [Importing the Seed Database](Import-the-Seed-Database.md) + 5. [Deploying the Web Application](Deploying.md) + 6. [Loading a Sample Study](Load-Sample-Cancer-Study.md) diff --git a/docs/deployment/docker/README.md b/docs/deployment/docker/README.md index 7760ecbf94b..29be29f2644 100644 --- a/docs/deployment/docker/README.md +++ b/docs/deployment/docker/README.md @@ -15,7 +15,8 @@ Make sure that you have the latest version of Docker installed on your machine. In this example we use [Docker Compose](https://docs.docker.com/compose/) to spin up all the different required containers/services for cBioPortal. ### Quick Start - +Important when using Windows:
+Please use the WSL input window (WSL2 Terminal) directly and not "Windows PowerShell" or "Git Bash". ``` git clone https://github.com/cBioPortal/cbioportal-docker-compose.git cd cbioportal-docker-compose @@ -25,7 +26,7 @@ docker compose up You should now be able to see the cBioPortal website at http://localhost:8080 -Import studies with: +Import studies with:
(Hint: Don't close the current terminal but open a second terminal and change the path to "/cbioportal-docker-compose") ``` docker compose run cbioportal metaImport.py -u http://cbioportal:8080 -s study/lgg_ucsf_2014/ -o @@ -66,12 +67,12 @@ This will start all four containers (services) defined [here](https://github.com - the session service Java web app. This service has a REST API and stores session information (e.g. what genes are being queried) and user specific data (e.g. saved cohorts) in a separate mongo database - the mongo database that persists the data for the session service -It will take a few minutes the first time to import the seed database and perform migrations if necessary. Each container outputs logs to the terminal. For each log you'll see the name of the container that outputs it (e.g. `cbioportal_container` or `cbioportal_session_database_container`). If all is well you won't see any significant errors (maybe some warnings, that's fine to ignore). If all went well you should be able to visit the cBioPortal homepage on http://localhost:8080. You'll notice that no studies are shown on the homepage yet: +It will take a few minutes the first time to import the seed database and perform migrations if necessary. Each container outputs logs to the terminal. For each log you'll see the name of the container that outputs it (e.g. `cbioportal_container` or `cbioportal_session_database_container`). If all is well you won't see any significant errors (maybe some warnings, that's fine to ignore). If all went well you should be able to visit the cBioPortal homepage on http://localhost:8080. You'll notice that cBioPortal already comes preloaded with a small `Low-Grade Gliomas (UCSF, Science 2014)` study and the recommended gene panels: -Screen Shot 2022-01-24 at 2 10 10 PM +Screen Shot 2022-01-24 at 2 10 10 PM -Go to the next step to see how to import studies. +Go to the next step to see how to import other studies. ##### Notes on detached mode @@ -106,9 +107,19 @@ the preferred way to run as it provides a UI for listing the containers and inte To import studies you can run: ``` -docker compose run cbioportal metaImport.py -u http://cbioportal:8080 -s study/lgg_ucsf_2014/ -o +docker compose run cbioportal metaImport.py -u http://cbioportal:8080 -s study/msk_impact_2017/ -o + +## Sync clickhouse (ONLY for clickhouse mode, see below) +docker compose exec cbioportal-clickhouse-importer bash /workdir/sync-databases.sh ``` -This will import the [lgg_ucsf_2014 study](https://www.cbioportal.org/patient?studyId=lgg_ucsf_2014) into your local database. It will take a few minutes to import. After importing, restart the cbioportal web container: +This will import the [msk_impact_2017 study](https://www.cbioportal.org/study/summary?id=msk_impact_2017) into your local database. It will take a few minutes to import. + +If you are running cBioPortal in [Clickhouse Mode](#clickhouse-mode), run the following command to sync databases. +```shell +docker compose exec cbioportal-clickhouse-importer bash /workdir/sync-databases.sh +``` + +After importing and syncing, restart the cbioportal web container: ``` docker compose restart cbioportal @@ -146,6 +157,26 @@ co-expression tab. If you are using MacOS or Windows, make sure to take a look at [these notes](notes-for-non-linux.md) to allocate more memory for the virtual machine in which all Docker processes are running. +## Clickhouse Mode ## +For cBioPortal instances with large cohorts (>100K samples), we developed a "Clickhouse mode" of the Study View. This mode uses Clickhouse as an additional database next to MySQL for 10x faster querying (see [video](https://www.youtube.com/watch?v=8PAJRCeycU4)). The mode is experimental and is currently used only by the public-facing [GENIE instance](https://genie.cbioportal.org). We plan to roll it out to other portals later this year (see [roadmap ticket](https://github.com/orgs/cBioPortal/projects/16?query=sort%3Aupdated-desc+is%3Aopen&pane=issue&itemId=92222076&issue=cBioPortal%7Croadmap%7C1)). Follow the steps below to run cBioPortal Docker Compose in clickhouse mode. +1. Modify [.env](https://github.com/cBioPortal/cbioportal-docker-compose/blob/master/.env) to use release >= 6.0.27 of cBioPortal. + ```text + ... + DOCKER_IMAGE_CBIOPORTAL=cbioportal/cbioportal:6.0.27 + ... + ``` +2. Run init script + ```shell + ./init.sh + ``` +3. Start cBioPortal with clickhouse + ```shell + docker compose -f docker-compose.yml -f addon/clickhouse/docker-compose.clickhouse.yml up + ``` + +### Clickhouse Cloud +The Clickhouse setup mentioned above is fully compatible with a remote Clickhouse database. For production environments, you can set up a Clickhouse database using [Clickhouse Cloud](https://clickhouse.com/cloud) and update the clickhouse database credentials in the [.env](https://github.com/cBioPortal/cbioportal-docker-compose/blob/master/.env) to match your database credentials. For the clickhouse sync step to work properly, your credentials should have both `read` and `write` permissions. + ## More commands ## For documentation on how to import a study, see [this tutorial](import_data.md) For more uses of the cBioPortal image, see [this file](example_commands.md) diff --git a/docs/deployment/docker/example_commands.md b/docs/deployment/docker/example_commands.md index b1b35f1c5cc..fb7ec1e8b3b 100644 --- a/docs/deployment/docker/example_commands.md +++ b/docs/deployment/docker/example_commands.md @@ -8,7 +8,7 @@ gene panel files in `./study` which is mounted inside the container on `/study/. docker compose run \ -v :/gene_panels/gene_panel.txt:ro \ cbioportal \ - bash -c 'cd /cbioportal/core/src/main/scripts/ && ./importGenePanel.pl --data /gene_panels/gene_panel.txt' + bash -c 'cd /core/scripts/ && ./importGenePanel.pl --data /gene_panels/gene_panel.txt' ``` ### Importing data ### @@ -37,19 +37,19 @@ In some setups the data validation step may not have direct access to the web AP ```shell docker compose run \ -v "/portalinfo:/portalinfo" \ - -w /cbioportal/core/src/main/scripts \ + -w /core/scripts/ \ cbioportal \ ./dumpPortalInfo.pl /portalinfo ``` -Then, grant the validation/loading command access to this folder and tell the script it to use it instead of the API: +Then, grant the validation/loading command access to this folder and tell the script to use it instead of the API: ```shell docker compose run \ -v ":/report" \ -v "/portalinfo:/portalinfo:ro" \ cbioportal \ - metaImport.py -p /portalinfo -s /study --html=/report/report.html + metaImport.py -p /portalinfo -s /study/name_of_study --html=/report/report.html ``` ### Inspecting or adjusting the database ### diff --git a/docs/deployment/docker/import_data.md b/docs/deployment/docker/import_data.md index cc7d8910639..4e99cdec6de 100644 --- a/docs/deployment/docker/import_data.md +++ b/docs/deployment/docker/import_data.md @@ -16,13 +16,13 @@ These are the commands for importing `study_es_0` gene panels (`data_gene_panel_ ```shell docker compose run \ cbioportal \ - bash -c 'cd /core/scripts/ && ./importGenePanel.pl --data /cbioportal/core/src/test/scripts/test_data/study_es_0/data_gene_panel_testpanel1.txt' + bash -c 'cd /core/scripts/ && ./importGenePanel.pl --data /cbioportal/test/study_es_0/data_gene_panel_testpanel1.txt' ``` ```shell docker compose run \ cbioportal \ - bash -c 'cd /core/scripts/ && ./importGenePanel.pl --data /cbioportal/core/src/test/scripts/test_data/study_es_0/data_gene_panel_testpanel2.txt' + bash -c 'cd /core/scripts/ && ./importGenePanel.pl --data /cbioportal/test/study_es_0/data_gene_panel_testpanel2.txt' ``` #### Step 2 - Import data @@ -32,7 +32,7 @@ To import data for your study, please reference the example commands in [this fi Command for importing `study_es_0` data: ```shell -docker compose run cbioportal metaImport.py -u http://cbioportal:8080 -s /cbioportal/core/src/test/scripts/test_data/study_es_0 -o +docker compose run cbioportal metaImport.py -u http://cbioportal:8080 -s /cbioportal/test/study_es_0 -o ``` :warning: after importing a study, remember to restart `cbioportal` to see the study on the home page. Run `docker compose restart cbioportal`. diff --git a/docs/deployment/standalone/README.md b/docs/deployment/standalone/README.md new file mode 100644 index 00000000000..94ac62d3d5d --- /dev/null +++ b/docs/deployment/standalone/README.md @@ -0,0 +1,461 @@ +# Deploy Standalone Isolated Version + +## Overview +In some cases a cBioPortal instance needs to be completely isolated from connecting to outside resources. While cBioPortal will run in an isolated environment some features will not be available. In this documentation we cover how to setup and deploy a docker version of cBioPortal that is isolated from all outside services. + + +## Setup Instructions + +### Docker Configuration and Setup +Our docker configuration is based off the default cBioPortal docker configuration however we have made some changes to support our requirements. We create two networks in this deployment. The first being a bridge network that allows the services to connect to the outside world. The second is an internal network that only allows for services to talk to other services in that network. Most of the services are configured to use the internal network, with the exception being the NGINX and cBioPortal services. The NGINX needs to be able to communicate with the outside world in order to make the cBioPortal instance available to the outside world. The cBioPortal instance needs to be able to communicate with the outside world in order to allow for authentication with an outside service. However, if the cBioPortal instance does not authenticate then the service can be deployed only on the internal network. + + +``` +services: + nginx-wrapper: + restart: unless-stopped + image: nginx:1.27.1 + container_name: cbioportal-nginx-wrapper-container + ports: #NGINX_WRAPPER + - 80:80 + - 443:443 + expose: + - "8777" + volumes: + - ./config/nginx.conf:/etc/nginx/conf.d/default.conf + - ./cert/cert.cer:/etc/nginx/cert.cer + - ./cert/cert.key:/etc/nginx/cert.key + - ./gn-static:/gn-static + depends_on: + - cbioportal + networks: + - cbio-bridge + - cbio-internal + cbioportal: + restart: unless-stopped + image: cbioportal/cbioportal:6.0.12 + container_name: cbioportal-container + cap_add: + - NET_ADMIN + - NET_RAW + environment: + SHOW_DEBUG_INFO: "true" + PORTAL_HOME: "/cbioportal-webapp" + extra_hosts: + - "civicdb.org:127.0.0.1" + - "mutationassessor.org:127.0.0.1" + - "cancerhotspots.org:127.0.0.1" + - "genomenexus.org:127.0.0.1" + volumes: + - ./config/cbioportal_ipblock.sh:/cbioportal_ipblock.sh + - ./config/application.properties:/cbioportal-webapp/application.properties:ro + depends_on: + - cbioportal-database + - cbioportal-session + networks: + - cbio-internal + - cbio-bridge + command: /bin/sh -c "/cbioportal_ipblock.sh && rm -rf /cbioportal-webapp/lib/servlet-api-2.5.jar && java -Xms2g -Xmx4g -cp '/cbioportal-webapp:/cbioportal-webapp/lib/*' org.cbioportal.PortalApplication --spring.config.location=/cbioportal-webapp/application.properties --session.service.url=http://cbioportal-session:5000/api/sessions/portal/" + cbioportal-database: + restart: unless-stopped + image: mysql:5.7 + container_name: cbioportal-database-container + environment: + MYSQL_DATABASE: cbioportal + MYSQL_USER: cbio_user + MYSQL_PASSWORD: somepassword + MYSQL_ROOT_PASSWORD: somepassword + volumes: + - ./data/cgds.sql:/docker-entrypoint-initdb.d/cgds.sql:ro + - ./data/seed.sql.gz:/docker-entrypoint-initdb.d/seed.sql.gz:ro + - cbioportal_mysql_data:/var/lib/mysql + networks: + - cbio-internal + cbioportal-session: + restart: unless-stopped + image: cbioportal/session-service:0.6.1 + container_name: cbioportal-session-container + environment: + SERVER_PORT: 5000 + JAVA_OPTS: -Dspring.data.mongodb.uri=mongodb://cbioportal-session-database:27017/session-service + depends_on: + - cbioportal-session-database + networks: + - cbio-internal + cbioportal-session-database: + restart: unless-stopped + image: mongo:4.2 + container_name: cbioportal-session-database-container + environment: + MONGO_INITDB_DATABASE: session_service + volumes: + - ../cbioportal_mongo_data:/data/db + networks: + - cbio-internal + oncokb: + image: oncokb/oncokb:3.20.3 + ports: #TODO: CHANGE TO EXPOSE + - "8080:8080" + environment: + JAVA_OPTS: > + -Djdbc.driverClassName=com.mysql.jdbc.Driver + -Djdbc.url=jdbc:mysql://oncokb-mysql:3306/oncokb?useUnicode=yes&characterEncoding=UTF-8&useSSL=false + -Djdbc.username=oncokb_user + -Djdbc.password=somepassword + -Doncokb_transcript.url=http://oncokb-transcript:9090-Doncokb_transcript.token= + -Dgenome_nexus.grch37.url=http://gn-spring-boot:8888 + -Dgenome_nexus.grch38.url=http://gn-spring-boot-grch38:8888 + -Dis_public_instance=false + -Dcancerhotspots.website.link=http://cancerhotspots:8888 + depends_on: + - "oncokb-transcript" + networks: + - cbio-internal + volumes: + - ./config/oncokb.config:/src/main/resources/properties/config.properties:ro + oncokb-mysql: + restart: unless-stopped + image: mysql:5.7.28 + environment: + MYSQL_DATABASE: oncokb + MYSQL_USER: oncokb_user + MYSQL_PASSWORD: somepassword + MYSQL_ROOT_PASSWORD: somepassword + volumes: + - ../oncokb:/var/lib/mysql + networks: + - cbio-internal + oncokb-transcript: + image: oncokb/oncokb-transcript:0.9.4 + ports: #TODO: CHANGE TO EXPOSE + - "9090:9090" + environment: + - SPRING_PROFILES_ACTIVE=prod,api-docs,no-liquibase + - APPLICATION_REDIS_ENABLED=false + - SPRING_DATASOURCE_URL=jdbc:mysql://oncokb-transcript-mysql:3306/oncokb_transcript?useUnicode=yes&characterEncoding=UTF-8&useSSL=false + - SPRING_DATASOURCE_USERNAME=oncokb_user + - SPRING_DATASOURCE_PASSWORD=somepassword + depends_on: + - "oncokb-transcript-mysql" + networks: + - cbio-internal + oncokb-transcript-mysql: + restart: unless-stopped + image: mysql:5.7.28 + environment: + MYSQL_DATABASE: oncokb_transcript + MYSQL_USER: oncokb_user + MYSQL_PASSWORD: somepassword + MYSQL_ROOT_PASSWORD: somepassword + volumes: + - ../oncokb_transcript:/var/lib/mysql + networks: + - cbio-internal + cancerhotspots: + image: ksg/cancerhotspots + ports: #TODO: CHANGE TO EXPOSE + - "8888:28080" + networks: + - cbio-internal + gn-spring-boot: + image: genomenexus/gn-spring-boot:1.4.1 + ports: #TODO: CHANGE TO EXPOSE + - "8888:8888" + cap_add: + - NET_ADMIN + - NET_RAW + environment: + - SERVER_PORT=8888 + command: > + java + -Dspring.data.mongodb.uri=mongodb://gn-mongo:27017/annotator + -Dgn_vep.region.url=http://gn-vep:8080/vep/human/region/VARIANT + -Drevue.url=http://nginx-wrapper:8777/VUEs.json + -Dgenexrefs.url=http://127.0.0.1/genexrefs + -Dmyvariantinfo.url=http://127.0.0.1/myvariant + -Dpdb.header_service_url=http://127.0.0.1/pdb + -Doncokb.url=http://oncokb/api/v1/annotate/mutations/byProteinChange?PROTEINCHANGE + -jar /app.war + links: + - gn-mongo + depends_on: + - gn-mongo + - gn-vep + networks: + - cbio-internal + gn-mongo: + image: genomenexus/gn-mongo:0.31 + restart: always + environment: + - REF_ENSEMBL_VERSION=grch37_ensembl98 + - SPECIES=homo_sapiens + networks: + - cbio-internal + gn-vep: + image: genomenexus/genome-nexus-vep:v0.0.1 + environment: + - VEP_ASSEMBLY=GRCh37 + - VEP_FASTAFILERELATIVEPATH=homo_sapiens/98_GRCh37/Homo_sapiens.GRCh37.75.dna.primary_assembly.fa.gz + user: root + restart: always + ports: #TODO: CHANGE TO EXPOSE + - "6060:8080" + volumes: + - ../gn-vep-data/98_GRCh37:/opt/vep/.vep + - ../gn-vep-data/98_GRCh37:/root/.vep/ + networks: + - cbio-internal + gn-spring-boot-grch38: + image: genomenexus/gn-spring-boot:v1.2.2 + ports: #TODO: CHANGE TO EXPOSE + - "8889:8888" + environment: + - SERVER_PORT=8888 + command: > + java + -Dspring.data.mongodb.uri=mongodb://gn-mongo-grch38:27017/annotator + -Dgn_vep.region.url=http://gn-vep-grch38:8080/vep/human/region/VARIANT + -Drevue.url=http://nginx-wrapper:8777/VUEs.json + -Dgenexrefs.url=http://127.0.0.1/genexrefs + -Dmyvariantinfo.url=http://127.0.0.1/myvariant + -Dpdb.header_service_url=http://127.0.0.1/pdb + -jar + /app.war + links: + - gn-mongo-grch38 + depends_on: + - gn-mongo-grch38 + - gn-vep-grch38 + networks: + - cbio-internal + gn-mongo-grch38: + image: genomenexus/gn-mongo:v0.24_grch38_ensembl95 + restart: always + networks: + - cbio-internal + gn-vep-grch38: + image: genomenexus/genome-nexus-vep:v0.0.1 + environment: + - VEP_ASSEMBLY=GRCh38 + - VEP_FASTAFILERELATIVEPATH=homo_sapiens/98_GRCh38/Homo_sapiens.GRCh38.dna.toplevel.fa.gz + user: root + restart: always + ports: #TODO: CHANGE TO EXPOSE + - "6061:8080" + volumes: + - ../gn-vep-data/98_GRCh38/:/opt/vep/.vep/ + - ../gn-vep-data/98_GRCh38:/root/.vep/ + networks: + - cbio-internal + +networks: + cbio-internal: + internal: true + ipam: + config: + - subnet: 192.187.1.0/24 + cbio-bridge: + driver: bridge + ipam: + driver: default + config: + - subnet: 192.187.0.0/24 +``` + +### NGINX Configuration and Setup +The NGINX configuration below supports HTTPS, a static landing page, cBioPortal being hosted as a subdirectory. You will need to provide your own certificates. You will note in the configuration that we host the static site in the `/gn-static` directory. This directory will also need to contain an index file as well as any supporting resources. The `/gn-static` is also used by a site the connects to a server running on port 8777. This hosts the `VUEs.json` file used by Genome Nexus and the port is only available to services inside the internal network. We also have a location lookup for `/reactapp` that handles cBioPortal requests that do not support running cBioPortal in a subdirectory. + + +``` +server { + listen 80; + + return 301 https://$host$request_uri; +} + +server { + + listen 443 ssl; + + ssl_certificate /etc/nginx/cert.cer; + ssl_certificate_key /etc/nginx/cert.key; + + ssl_session_cache builtin:1000 shared:SSL:10m; + ssl_protocols TLSv1 TLSv1.1 TLSv1.2; + ssl_ciphers HIGH:!aNULL:!eNULL:!EXPORT:!CAMELLIA:!DES:!MD5:!PSK:!RC4; + ssl_prefer_server_ciphers on; + + access_log /var/log/nginx/cbioportal_login.access.log; + + client_max_body_size 1024g; + client_body_buffer_size 1024m; + + proxy_http_version 1.1; + chunked_transfer_encoding off; + + location / { + root /gn-static; + } + + location /cbioportal { + proxy_pass http://cbioportal:8443; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $remote_addr; + proxy_set_header X-Forwarded-Proto https; + proxy_set_header X-Forwarded-Scheme https; + proxy_set_header Connection keep-alive; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Transfer-Encoding ""; + proxy_send_timeout "20m"; + proxy_read_timeout "20m"; + } + + location /reactapp { + return 301 /cbioportal$request_uri; + } + + expires -1; +} + +server { + listen 8777; + location / { + root /gn-static; + } + + expires -1; +} +``` + +### cBioPortal Configuration and Setup +Our cBioPortal configuration of changes that need to be reflected in the configuration file. The first is that the public instance of Genome Nexus can no longer be accessed. To accomplish this we update the url for Genome Nexus to be a local path and create proxy services for the internal Genome Nexus. Additionally, we configure the server to support being behind a reverse proxy (NGINX) and set the context path to `/cbioportal`. We set our database settings to communicate with our MySQL instance. Finally, we configure security for OAuth2 authentication and authorization. + + +``` +# Genome Nexus Configuration + +genomenexus.url=/cbioportal/proxy/genomenexus +genomenexus.url.grch38=/cbioportal/proxy/genomenexus38 + +proxy.routes.genomenexus=http://gn-spring-boot:8888 +proxy.routes.genomenexus38=http://gn-spring-boot-grch38:8888 + +# Server Configuration +server.forward-headers-strategy=FRAMEWORK +server.use-forward-headers=true +server.port=8443 +server.servlet.context-path=/cbioportal +server.tomcat.redirect-context-root=false + +security.cors.allowed-origins=* + +# database +spring.datasource.url=jdbc:mysql://cbioportal-database:3306/cbioportal?useSSL=false&allowPublicKeyRetrieval=true +spring.datasource.username=cbio_user +spring.datasource.password=somepassword +spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver +spring.jpa.database-platform=org.hibernate.dialect.MySQL5InnoDBDialect + + +# security +authenticate=oauth2 +authorization=true +oauth2.logout.url=/../ + +spring.security.oauth2.client.registration.google.client-id= +spring.security.oauth2.client.registration.google.client-secret= +``` + +To limit the ability for our server to communicate with outside services we leverage iptables that allow only communication to DNS entries and ports we authorize. All other communications are blocked. In the example below we block all communication except to specific Google services for which we use for authorization. + +``` +apt-get update +apt-get install -y --no-install-recommends iptables + +echo "Iptables chain block installation - Starting" +# Create some new chains for these rules +iptables -N BLOCK_OUTBOUND_HTTP +iptables -N BLOCK_OUTBOUND_HTTPS +iptables -N OUTBOUND_HTTP_WHITELIST +iptables -N OUTBOUND_HTTPS_WHITELIST +iptables -N RESTRICT_OUTBOUND_WEB + +# Block all outgoing HTTP +iptables -A BLOCK_OUTBOUND_HTTP +iptables -A BLOCK_OUTBOUND_HTTP -p tcp --dport 80 -j LOG --log-prefix 'cbioportal iptable block: ' +iptables -A BLOCK_OUTBOUND_HTTP -p tcp --dport 80 -j REJECT +iptables -A BLOCK_OUTBOUND_HTTP -j RETURN + +# Block all outgoing HTTPS +iptables -A BLOCK_OUTBOUND_HTTPS +iptables -A BLOCK_OUTBOUND_HTTPS -p tcp --dport 443 -j LOG --log-prefix 'cbioportal iptable block: ' +iptables -A BLOCK_OUTBOUND_HTTPS -p tcp --dport 443 -j REJECT +iptables -A BLOCK_OUTBOUND_HTTPS -j RETURN + +# Allow HTTP to specific destination hosts (replace with a hostname, IP, network, etc.) +iptables -A OUTBOUND_HTTP_WHITELIST -p tcp ! --dport 80 -j RETURN +iptables -A OUTBOUND_HTTP_WHITELIST -j RETURN + +# Allow HTTPS to specific destination hosts (replace with a hostname, IP, network, etc.) +iptables -A OUTBOUND_HTTPS_WHITELIST -p tcp ! --dport 443 -j RETURN +iptables -A OUTBOUND_HTTPS_WHITELIST --destination gmail.googleapis.com -j ACCEPT +iptables -A OUTBOUND_HTTPS_WHITELIST --destination accounts.google.com -j ACCEPT +iptables -A OUTBOUND_HTTPS_WHITELIST --destination googleusercontent.com -j ACCEPT +iptables -A OUTBOUND_HTTPS_WHITELIST --destination google.com -j ACCEPT +iptables -A OUTBOUND_HTTPS_WHITELIST -j RETURN + +# Group the above into an easier to include chain +iptables -A RESTRICT_OUTBOUND_WEB -j OUTBOUND_HTTP_WHITELIST +iptables -A RESTRICT_OUTBOUND_WEB -j OUTBOUND_HTTPS_WHITELIST +iptables -A RESTRICT_OUTBOUND_WEB -j BLOCK_OUTBOUND_HTTP +iptables -A RESTRICT_OUTBOUND_WEB -j BLOCK_OUTBOUND_HTTPS +iptables -A RESTRICT_OUTBOUND_WEB -j RETURN + +# Link the new chains into our OUTPUT chain +iptables -A OUTPUT -j RESTRICT_OUTBOUND_WEB +iptables -A OUTPUT -j ACCEPT +echo "Iptables chain block installation - Complete" +``` + +### OncoKB Setup +You will need to obtain OncoKB transcript information and an OncoKB license in order to use it. Contact the OncoKB team to learn more. + + +### GenomeNexus Setup + +Populate Genome Nexus Data + +``` +cd ../ +sudo mkdir gn-vep-data && cd "$_" + +sudo mkdir 98_GRCh37 && cd "$_" +sudo curl -o 98_GRCh37.tar https://oncokb.s3.amazonaws.com/gn-vep-data/98_GRCh37/98_GRCh37.tar +sudo tar xvf 98_GRCh37.tar + +cd .. +sudo mkdir 98_GRCh38 && cd "$_" +sudo curl -o 98_GRCh38.tar https://oncokb.s3.amazonaws.com/gn-vep-data/98_GRCh38/98_GRCh38.tar +sudo tar xvf 98_GRCh38.tar +``` + + +### Cancer Hotspots Setup +The default Cancer Hotspots does not support docker by default. You can either add your own files as listed below our use the DFCI forked version: https://github.com/dfci/cancerhotspots. + +docker/Dockerfile + +``` +FROM maven:3.9.9-eclipse-temurin-8 +COPY $PWD . +RUN mvn clean install -DskipTests +ENTRYPOINT java -jar webapp/target/cancerhotspots.jar +``` + +Build + +``` +docker build -t ksg/cancerhotspots -f docker/Dockerfile . +``` + diff --git a/docs/development/Backend-Code-Organization.md b/docs/development/Backend-Code-Organization.md new file mode 100644 index 00000000000..a30e04e2d22 --- /dev/null +++ b/docs/development/Backend-Code-Organization.md @@ -0,0 +1,96 @@ +# cBioPortal Backend Code Organization + +## Maven Project + +The backend code is structured as a [Maven](https://maven.apache.org/index.html) +project. Included in the repository are [pom.xml files](https://maven.apache.org/pom.html#What_is_the_POM) +which define the code components and modules which make up the backend. The pom.xml +files also list dependencies on external open source libraries, and dependencies between cBioPortal Maven modules. +They also give instructions for how to build and package code components into a +deployable format. + +### Frontend data exchange + +The frontend is a [React](https://reactjs.org/) javascript application located +in a separate [GitHub +repository](https://github.com/cBioPortal/cbioportal-frontend) repo, which +communicates with the backend via a REST API. We also use JSP to embed +configuration data in the initial HTML page in order to allow us to optimize +loading times. + +### Current Maven Modules + +TODO: This is out of date. See https://github.com/cBioPortal/cbioportal/issues/11403. + +#### The core module + +The [core](https://github.com/cBioPortal/cbioportal/blob/master/core) module contains the oldest code in the code base. Much of +the backend web data services logic has been re-implemented and expanded in +other backend maven modules, such as [model](https://github.com/cBioPortal/cbioportal/blob/master/model), +[persistence-mybatis](https://github.com/cBioPortal/cbioportal/blob/master/persistence/persistence-mybatis), +[service](https://github.com/cBioPortal/cbioportal/blob/master/service), and [web](https://github.com/cBioPortal/cbioportal/blob/master/web). We plan to discontinue the legacy +webservice.do data servlet and fully transition to the new data services API in +the near future. The core module will then be purged of much of the legacy +code. Any surviving functionality (such as the handling of global configuration +properties) may be relocated into new modules. It is therefore important that +no new code features be introduced which are dependent on the core module +functionality. + +#### The central stack modules : web, service, persistence + +Three maven modules make up the central stack of the new web API implementation. + +* [web](https://github.com/cBioPortal/cbioportal/blob/master/web) : define Web API request handlers, map endpoints, select services +* [service](https://github.com/cBioPortal/cbioportal/blob/master/service) : call persistence module or utils, apply business logic +* [persistence](https://github.com/cBioPortal/cbioportal/blob/master/persistence) : retrieve data from database. Two submodules: + * [persistence-api](https://github.com/cBioPortal/cbioportal/blob/master/persistence/persistence-api) : declaration of repository classes / functions, caching markup + * [persistence-mybatis](https://github.com/cBioPortal/cbioportal/blob/master/persistence/persistence-mybatis) : implementation of persistence-api using [MyBatis](https://mybatis.org/mybatis-3/) mappers + +#### Other modules + +* [model](https://github.com/cBioPortal/cbioportal/blob/master/model) : data model POJO classes (used throughout the stack) +* [security](https://github.com/cBioPortal/cbioportal/blob/master/security) : user authentication methods and authorization, request filters +* [business](https://github.com/cBioPortal/cbioportal/blob/master/business) : a legacy refactor of webservice.do, has active dataSource definition +* [portal](https://github.com/cBioPortal/cbioportal/blob/master/portal) : web application packaging and launch +* [scripts](https://github.com/cBioPortal/cbioportal/blob/master/scripts) : data import tool packaging (from core module scripts package) +* [db_scripts](https://github.com/cBioPortal/cbioportal/blob/master/db_scripts) : installation and migration scripts for the database + +#### External code modules + +* [cbioportal-frontend](https://github.com/cBioPortal/cbioportal-frontend) : a React application using MobX and TypeScript +* [session-service](https://github.com/cBioPortal/session-service) : an external session key/query specifier storage system + +**cbioportal-frontend** is packaged in the web application as a default frontend +implementation, but the source of the frontend code can also be directed to an external +source host and be deployed independently of the backend web application. See +[details](Deployment-Procedure.md) + +**session-service** is imported into the web module in order to set up a proxy service +which receives and forwards requests for saved cBioPortal sessions to a separate system +providing this storage (using a document based database) The code is needed for handling +modeled types such as VirtualStudy and Session + +### cBioPortal Module Dependencies + +![Module Dependencies](images/maven-module-dependencies.png) + +_A module is directly dependent on all modules which touch it from below (touching only at a corner +does not count). Dependencies are transitive : web is dependent on service, service +is dependent on persistence-mybatis, therefore web is also dependent on +persistence-mybatis. During packaging, all dependencies are made available to the +dependent package for use. Avoid creating new dependencies between modules. +**cyclical dependencies will cause errors during build**_ + +Module | Dependencies +------ | ------------ +portal | core, _cbioportal-frontend_ +scripts | core +core | web +web | business, service, _session-service_ +security-spring | service +service | persistence-mybatis +persistence-mybatis | persistence-api, db-scripts +persistence-api | model +business | model +db-scripts | +model | diff --git a/docs/Backend-Development-Guidelines.md b/docs/development/Backend-Development-Guidelines.md similarity index 92% rename from docs/Backend-Development-Guidelines.md rename to docs/development/Backend-Development-Guidelines.md index 3e7b60c931e..949862fffc5 100644 --- a/docs/Backend-Development-Guidelines.md +++ b/docs/development/Backend-Development-Guidelines.md @@ -1,5 +1,7 @@ # cBioPortal Development Guidelines +TODO: these guidelines are out of date, see https://github.com/cBioPortal/cbioportal/issues/11403 + 1. Avoid introducing new functionality in the core module or creating new dependencies on the existing core module code. 1. One exception to the previous guideline is that new data import functions should be added to the core module scripts package. 1. Do not expand the business module. diff --git a/docs/user-guide/faq.md b/docs/user-guide/faq.md index b3a229d1cab..86b33d0e7e0 100644 --- a/docs/user-guide/faq.md +++ b/docs/user-guide/faq.md @@ -108,7 +108,7 @@ The TCGA firehose legacy datasets are imported directly from the original TCGA D We are also actively curating datasets from the literature. Studies from the literature were curated from the data published with the manuscripts. We sometimes reach out to the investigators to acquire additional data, such as clinical attributes. All mutation calls (in VCF or MAF format) are processed through an internal pipeline to annotate the variant effects in a consistent way across studies. Please [contact us](mailto:cbioportal@googlegroups.com) to suggest additional public datasets to curate or view the list of studies suggested for curation in our [Datahub on Github](https://github.com/cBioPortal/datahub/issues?q=is%3Aissue+is%3Aopen+label%3A%22new+public+study%22). #### How do I get updates on new portal developments and new data sets? -Please subscribe to our low-volume [news mailing list](https://groups.google.com/group/cbioportal-news) or follow [@cbioportal on Twitter](https://twitter.com/cbioportal). +Follow @cbioportal on [Bluesky](https://bsky.app/profile/cbioportal.bsky.social) or [Twitter](https://twitter.com/cbioportal) for regular updates. To read our quarterly newsletter, follow us on [LinkedIn](https://www.linkedin.com/company/cbioportal) or subscribe to our low-volume [news mailing list](https://groups.google.com/group/cbioportal-news). #### Does the portal work on all browsers and operating systems? We support and test on the following web browsers: Safari, Google Chrome, Firefox and Edge. (As of release v3.5.4 we no longer support Internet Explorer 11). If you notice any incompatibilities, please let us know. #### How do I cite the cBioPortal? @@ -119,7 +119,7 @@ Please cite the following portal papers: Remember also to cite the source of the data if you are using a publicly available dataset. #### Can I use figures from the cBioPortal in my publications or presentations? -Yes, you are free to use any of the figures from the portal in your publications or presentations (many are available in SVG or PDF format for easier scaling and editing). When you do, please cite Cerami et al., Cancer Discov. 2012, and Gao et al., Sci. Signal. 2013 (see the previous question for full citations). +Yes, you are free to use any of the figures from the portal in your publications or presentations (many are available in SVG or PDF format for easier scaling and editing). When you do, please cite cBioPortal (see the previous question for full citation instructions). #### Can I save or bookmark my results in cBioPortal? You can bookmark your query results and share the URL with collaborators. We store all queries via Session IDs, and these are saved indefinitely. Use the bookmark tab to retrieve the full link, or generate a short link via the bit.ly link generator. #### How is the cBioPortal for Cancer Genomics different from the Genomic Data Commons (GDC)? diff --git a/docs/user-guide/overview.md b/docs/user-guide/overview.md index b928ca907db..81a0b7d6877 100644 --- a/docs/user-guide/overview.md +++ b/docs/user-guide/overview.md @@ -7,7 +7,7 @@ These tutorial slides contain annoted screenshots to walk you through using the 3. Patient View [Google slides](https://docs.google.com/presentation/d/1Jr_2yEfgjKBn4DBiXRk4kmhIbtsRp6gd0iD3k1fIUUk) | [PDF](https://raw.githubusercontent.com/cBioPortal/cbioportal/master/docs/tutorials/cBioPortal%20Tutorial%203%20Patient%20View.pdf) 4. Virtual Studies [Google slides](https://docs.google.com/presentation/d/1rQE5rbFNdmup-rAtySHFxlLp3i4qa8SBA7MiQpMdn1I) | [PDF](https://raw.githubusercontent.com/cBioPortal/cbioportal/master/docs/tutorials/cBioPortal%20Tutorial%204%20Virtual%20Studies.pdf) 5. Onco Query Language (OQL) [Google slides](https://docs.google.com/presentation/d/1U39xgVujtBodwW20qIfcGu4E5n2zzaKkl2KmzzHqj4A) | [PDF](https://raw.githubusercontent.com/cBioPortal/cbioportal/master/docs/tutorials/cBioPortal%20Tutorial%205%20Onco%20Query%20Language.pdf) -6. Group Comparison [Google slides](https://docs.google.com/presentation/d/1P2boDph8IfpvjxoxDj_496CLHGtshzJnbbZhszPsmf4) | [PDF](https://raw.githubusercontent.com/cBioPortal/cbioportal/master/docs/tutorials/cBioPortal%20Tutorial%205%20Onco%20Query%20Language.pdf) +6. Group Comparison [Google slides](https://docs.google.com/presentation/d/1P2boDph8IfpvjxoxDj_496CLHGtshzJnbbZhszPsmf4) | [PDF](https://raw.githubusercontent.com/cBioPortal/cbioportal/master/docs/tutorials/cBioPortal%20Tutorial%206%20Group%20Comparison.pdf) 7. Pathways [Google slides](https://docs.google.com/presentation/d/1O5WGucz0lrfdY25b5QS6zaID_26i434EYXBluqZfT2g) | [PDF](https://raw.githubusercontent.com/cBioPortal/cbioportal/master/docs/tutorials/cBioPortal%20Tutorial%207%20Pathways.pdf) ### Webinar Recordings @@ -29,6 +29,7 @@ Short videos that show how to perform specific analyses or how to use specific p 7. How to run a query for genes of interest [youtube.com](https://www.youtube.com/watch?v=MH-kY5usA70) 8. How to download data [youtube.com](https://www.youtube.com/watch?v=JId304dp3tc) 9. Navigating AACR GENIE - Biopharma Collaborative (BPC) dataset [youtube.com](https://www.youtube.com/playlist?list=PLE2tjlUyHL8Gn4ythnuvf2BxWJVpAxkMM) +10. Using Chromoscope to explore structural variants [youtube.com](https://www.youtube.com/watch?v=e378l2MmgKY) ### Documentation * Frequently Asked Questions [FAQ](/user-guide/faq.md) diff --git a/docs/web-API-and-Clients.md b/docs/web-API-and-Clients.md index 9cae58a1c43..dff8affc273 100644 --- a/docs/web-API-and-Clients.md +++ b/docs/web-API-and-Clients.md @@ -56,7 +56,7 @@ Although we recommend [cBioPortalData](/#cbioportaldata-recommended) or [cbiopor ``` library(rapiclient) -client <- get_api(url = "https://www.cbioportal.org/api/v2/api-docs") +client <- get_api(url = "https://www.cbioportal.org/api/v3/api-docs") ``` #### CGDSR (deprecated) @@ -74,7 +74,7 @@ Generate a client in Python using [bravado](https://github.com/Yelp/bravado) lik ```python from bravado.client import SwaggerClient -cbioportal = SwaggerClient.from_url('https://www.cbioportal.org/api/v2/api-docs', +cbioportal = SwaggerClient.from_url('https://www.cbioportal.org/api/v3/api-docs', config={"validate_requests":False,"validate_responses":False,"validate_swagger_spec": False}) ``` diff --git a/jitpack.yml b/jitpack.yml deleted file mode 100644 index 4d456953698..00000000000 --- a/jitpack.yml +++ /dev/null @@ -1,2 +0,0 @@ -before_install: - - cp src/main/resources/application.properties.EXAMPLE src/main/resources/application.properties \ No newline at end of file diff --git a/log.out b/log.out deleted file mode 100644 index cbcab756f1c..00000000000 --- a/log.out +++ /dev/null @@ -1,2 +0,0 @@ -*** Couldn't find a suitable DSN, Sentry operations will do nothing! See documentation: https://docs.sentry.io/clients/java/ *** -No 'stacktrace.app.packages' was configured, this option is highly recommended as it affects stacktrace grouping and display on Sentry. See documentation: https://docs.sentry.io/clients/java/config/#in-application-stack-frames diff --git a/pom.xml b/pom.xml index 9e8555525b2..3d4803c0286 100644 --- a/pom.xml +++ b/pom.xml @@ -1,686 +1,843 @@ - 4.0.0 - - - org.springframework.boot - spring-boot-starter-parent - 3.4.1 - - - org.cbioportal - cbioportal - 6.0.26-SNAPSHOT - - cBioPortal for Cancer Genomics - - - 21 - 21 - 21 - 21 - 21 - yyyyMMdd-HHmm - ${maven.build.timestamp} - - com.github.cbioportal - v6.0.25 - - - 2.13.1 - - - - 1.1.6.RELEASE - - 2.12.5 - 8.0.28 - 8.2.0 - 3.0.0 - UTF-8 - UTF-8 - - - cBioPortal_cbioportal - ${project.groupId}:${project.artifactId} - cbioportal - https://sonarcloud.io - **src/test/**/*.* - - - 0.8.11 - jacoco - reuseReports - java - - ${project.basedir}/target/site/jacoco/jacoco.xml - - - com.mysql.jdbc.Driver - - - jdbc:mysql://127.0.0.1:3306/cgds_test?sessionVariables=default_storage_engine=InnoDB&allowLoadLocalInfile=true - cbio_user - somepassword - - - provided - 720 - - - - 1.6.3 - 3.0.4 - 1.19.4 - 5.15.0 - 4.1.1 - - - - 3.22.0 - 3.6.1 - 2.8.3 - 4.4 - 0.11.2 - 4.11.0 - 32.1.3-jre - 1.16.0 - 1.7 - 1.1 - 3.7.1 - 1.1.1 - 3.12.14 - 0.8.2 - 3.2.0 - 3.14.0 + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> + 4.0.0 + + + org.springframework.boot + spring-boot-starter-parent + 3.4.1 + + + io.github.cbioportal + cbioportal + v6.3.2-SNAPSHOT + jar + cBioPortal for Cancer Genomics + + + jdt_apt + + 21 + 21 + 21 + 21 + yyyyMMdd-HHmm + ${maven.build.timestamp} + + io.github.cbioportal + frontend-cbioportal + v6.3.1 + + 2.14.2 + 1.0.2 + + + + 1.1.6.RELEASE + + 2.12.5 + 8.0.28 + 8.2.0 + 3.0.0 + UTF-8 + UTF-8 + + + cBioPortal_cbioportal + ${project.groupId}:${project.artifactId} + cbioportal + https://sonarcloud.io + **src/test/**/*.* + + + 0.8.11 + jacoco + reuseReports + java + + ${project.basedir}/target/site/jacoco/jacoco.xml + + com.mysql.jdbc.Driver + + jdbc:mysql://127.0.0.1:3306/cgds_test?sessionVariables=default_storage_engine=InnoDB&allowLoadLocalInfile=true + cbio_user + somepassword + + + provided + 720 + + + 1.6.3 + 3.0.4 + 1.19.4 + 5.15.0 + 4.1.1 + + + 3.22.0 + 3.6.1 + 2.8.3 + 4.4 + 0.11.2 + 4.11.0 + 32.1.3-jre + 1.16.0 + 1.7 + 1.1 + 3.7.1 + 1.1.1 + 3.12.14 + 0.8.2 + 3.2.0 + 3.14.0 4.17.0 - 7.1.0 + 7.1.0 1.19.7 1.78 - - - - org.mskcc - org.mskcc.mondrian - - - - - org.springframework.boot - spring-boot-starter - - - org.springframework.boot - spring-boot-starter-test - test - - - org.junit.vintage - junit-vintage-engine - test - - - org.slf4j - slf4j-api - - - ch.qos.logback - logback-core - - - ch.qos.logback - logback-classic - - - pl.pragmatists - JUnitParams - 1.1.0 - test - - - org.springframework.boot - spring-boot-starter-web - - - org.springframework.boot - spring-boot-starter-validation - - - org.mybatis.spring.boot - mybatis-spring-boot-starter - ${mybatis.starter.version} - - - org.redisson - redisson - ${redisson.version} - - - org.apache.commons - commons-math3 - ${commons-math3.version} - - - org.springdoc - springdoc-openapi-starter-webmvc-ui - ${springdoc.version} - - - org.springframework.security - spring-security-core - - - org.apache.commons - commons-collections4 - ${apache-commons-collections.version} - - - io.jsonwebtoken - jjwt-api - ${io-jsonwebtoken.version} - - - io.jsonwebtoken - jjwt-impl - ${io-jsonwebtoken.version} - - - io.jsonwebtoken - jjwt-jackson - ${io-jsonwebtoken.version} - - - com.google.guava - guava - ${google_guava.version} - - - commons-codec - commons-codec - ${commons_codec.version} - - - commons-validator - commons-validator - ${commons_validator.version} - - - com.github.romain-warnan - simple-java-bitly - ${simple_java_bitly.version} - - - org.apache.httpcomponents - httpclient - - - - - org.ehcache - ehcache - ${ehcache.version} - - - com.googlecode.json-simple - json-simple - ${json_simple.version} - - - org.springframework.boot - spring-boot-starter-cache - - - com.datumbox - datumbox-framework-lib - ${datumbox.version} - - - org.springframework.security - spring-security-config - - - org.springframework.security - spring-security-web - - - org.springframework.security - spring-security-jwt - 1.1.1.RELEASE - - - com.auth0 - jwks-rsa - 0.22.1 - - - com.mysql - mysql-connector-j - ${mysql.version} - - - org.springframework.boot - spring-boot-starter-thymeleaf - - - org.springframework.security - spring-security-test - test - - - org.seleniumhq.selenium - selenium-java - ${selenium.version} - test - - - org.testcontainers - testcontainers - test - - - org.testcontainers - mysql - test - - - org.testcontainers - mockserver - test - - - org.mock-server - mockserver-client-java - ${mockserver.version} - test - - - com.github.dasniko - testcontainers-keycloak - ${dasniko-testcontainer-keycloak.version} - test - - - org.testcontainers - selenium - test - - - com.h2database - h2 - test - - - org.springframework.boot - spring-boot-starter-data-mongodb - - - - com.github.jitpack - maven-simple - 0.1 - - - - org.springframework.boot - spring-boot-starter-oauth2-client - - - org.springframework.boot - spring-boot-starter-oauth2-resource-server - - - org.springframework.security - spring-security-saml2-service-provider - - - org.springframework.session - spring-session-data-redis - - - org.springframework.boot - spring-boot-starter-data-redis - - - org.springframework.boot - spring-boot-devtools - runtime - true - - - io.sentry - sentry-spring-boot-starter-jakarta - ${sentry.version} - - - org.apache.httpcomponents.client5 - httpclient5 - test - - - - com.clickhouse - clickhouse-jdbc - 0.6.2 - - all - - - org.testcontainers - clickhouse - ${clickhouse_testcontainer.version} - test - - - org.mybatis.spring.boot - mybatis-spring-boot-test-autoconfigure - 3.0.3 - test - - - org.springframework.boot - spring-boot-testcontainers - test - + 1.6.3 + + + org.mskcc + org.mskcc.mondrian + + + Deployment + + + + ${project.groupId}:${project.artifactId} + https://www.cbioportal.org + + + GNU AFFERO GENERAL PUBLIC LICENSE v3.0 + https://www.gnu.org/licenses/agpl-3.0.html + + + + + Zain Nasir + nasirz1@mskcc.org + Memorial Sloan Kettering Cancer Center + https://www.mskcc.org/ + + + + scm:git:git://github.com/cBioPortal/cbioportal.git + scm:git:ssh://github.com:cBioPortal/cbioportal.git + https://github.com/cBioPortal/cbioportal/tree/master + + + + + org.springframework.boot + spring-boot-starter + + + org.springframework.boot + spring-boot-starter-test + test + + + org.junit.vintage + junit-vintage-engine + test + + + org.slf4j + slf4j-api + + + ch.qos.logback + logback-core + + + ch.qos.logback + logback-classic + + + pl.pragmatists + JUnitParams + 1.1.0 + test + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-validation + + + org.mybatis.spring.boot + mybatis-spring-boot-starter + ${mybatis.starter.version} + + + org.redisson + redisson + ${redisson.version} + + + org.apache.commons + commons-math3 + ${commons-math3.version} + + + org.springdoc + springdoc-openapi-starter-webmvc-ui + ${springdoc.version} + + + org.springframework.security + spring-security-core + + + org.apache.commons + commons-collections4 + ${apache-commons-collections.version} + + + io.jsonwebtoken + jjwt-api + ${io-jsonwebtoken.version} + + + io.jsonwebtoken + jjwt-impl + ${io-jsonwebtoken.version} + + + io.jsonwebtoken + jjwt-jackson + ${io-jsonwebtoken.version} + + + com.google.guava + guava + ${google_guava.version} + + + commons-codec + commons-codec + ${commons_codec.version} + + + commons-validator + commons-validator + ${commons_validator.version} + + + com.github.romain-warnan + simple-java-bitly + ${simple_java_bitly.version} + + + org.apache.httpcomponents + httpclient + + + + + org.ehcache + ehcache + ${ehcache.version} + + + com.googlecode.json-simple + json-simple + ${json_simple.version} + + + org.springframework.boot + spring-boot-starter-cache + + + com.datumbox + datumbox-framework-lib + ${datumbox.version} + + + org.springframework.security + spring-security-config + + + org.springframework.security + spring-security-web + + + org.springframework.security + spring-security-jwt + 1.1.1.RELEASE + + + com.auth0 + jwks-rsa + 0.22.1 + + + com.mysql + mysql-connector-j + ${mysql.version} + + + org.springframework.boot + spring-boot-starter-thymeleaf + + + org.springframework.security + spring-security-test + test + + + org.seleniumhq.selenium + selenium-java + ${selenium.version} + test + + + org.testcontainers + testcontainers + test + + + org.testcontainers + mysql + test + + + org.testcontainers + mockserver + test + + + org.mock-server + mockserver-client-java + ${mockserver.version} + test + + + javax.servlet + javax.servlet-api + + + + + com.github.dasniko + testcontainers-keycloak + ${dasniko-testcontainer-keycloak.version} + test + + + org.testcontainers + selenium + test + + + com.h2database + h2 + test + + + org.springframework.boot + spring-boot-starter-data-mongodb + + + org.springframework.boot + spring-boot-starter-oauth2-client + + + org.springframework.boot + spring-boot-starter-oauth2-resource-server + + + org.springframework.security + spring-security-saml2-service-provider + + + org.springframework.session + spring-session-data-redis + + + org.springframework.boot + spring-boot-starter-data-redis + + + org.springframework.boot + spring-boot-devtools + runtime + true + + + io.sentry + sentry-spring-boot-starter-jakarta + ${sentry.version} + + + org.apache.httpcomponents.client5 + httpclient5 + test + + + + com.clickhouse + clickhouse-jdbc + 0.6.2 + + all + + + org.testcontainers + clickhouse + ${clickhouse_testcontainer.version} + test + + + org.mybatis.spring.boot + mybatis-spring-boot-test-autoconfigure + 3.0.3 + test + + + org.springframework.boot + spring-boot-testcontainers + test + + + org.mapstruct + mapstruct + ${mapstruct.version} + + + + + org.osgi + org.osgi.service.component.annotations + 1.5.1 + provided + + + + + + + org.testcontainers + testcontainers-bom + ${testcontainers.version} + pom + import + - - - - - org.testcontainers - testcontainers-bom - ${testcontainers.version} - pom - import - - - - - - cbioportal - - - - org.apache.maven.plugins - maven-wrapper-plugin - 3.2.0 - - - - - - src/main/resources/application.properties - src/main/resources/maven.properties - - - - - - src/main/resources - true - - artwork/** - content/** - tutorials/** - webapp/** - templates/** - *.pdf - db-scripts/** - - - - - src/main/resources - false - - webapp/** - templates/** - - - - - src/main/resources/db-scripts - db-scripts - false - - cgds.sql - migration.sql - clickhouse/clickhouse.sql - clickhouse/materialized_views.sql - - - - - - src/main/resources/db-scripts - false - - clickhouse/clickhouse.sql - clickhouse/materialized_views.sql - - - - src/test/resources - false - - - - - - org.springframework.boot - spring-boot-maven-plugin - - - repackage - - exec - - - - - - - - io.github.git-commit-id - git-commit-id-maven-plugin - 5.0.0 - - - get-the-git-infos - initialize - - revision - - - - validate-the-git-infos - package - - validateRevision - - - - - ${project.basedir}/.git - true - - ${project.build.outputDirectory}/git.properties - full - - - - org.apache.maven.plugins - maven-dependency-plugin - - - unpack - prepare-package - - unpack - - - - - ${frontend.groupId} - cbioportal-frontend - ${frontend.version} - jar - - ${project.build.directory}/classes - *index* - true - - - - - - - - org.apache.maven.plugins - maven-wrapper-plugin - - - org.jacoco - jacoco-maven-plugin - ${jacoco.version} - - - default-prepare-agent - - prepare-agent - - - - default-report - - report - - - - XML - - - - - - - - - org.apache.maven.plugins - maven-surefire-plugin - - ${skipTests} - - **/*IntegrationTest.java - - - - - maven-failsafe-plugin - - ${skipITs} - - **/*IntegrationTest.java - - - - - - integration-test - verify - - - - + + + + cbioportal + + + + org.apache.maven.plugins + maven-wrapper-plugin + 3.2.0 + + + + + + src/main/resources/application.properties + src/main/resources/maven.properties + + + + + + src/main/resources + true + + artwork/** + content/** + tutorials/** + webapp/** + templates/** + *.pdf + db-scripts/** + + + + src/main/resources + false + + webapp/** + templates/** + + + + + src/main/resources/db-scripts + db-scripts + false + + cgds.sql + migration.sql + clickhouse/clickhouse.sql + clickhouse/materialized_views.sql + + + + + + src/main/resources/db-scripts + false + + clickhouse/clickhouse.sql + clickhouse/materialized_views.sql + + + + src/test/resources + false + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.13.0 + + 21 + + + org.mapstruct + mapstruct-processor + ${mapstruct.version} + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + repackage + + exec + + + + + + + io.github.git-commit-id + git-commit-id-maven-plugin + 5.0.0 + + + get-the-git-infos + initialize + + revision + + + + validate-the-git-infos + package + + validateRevision + + + + + ${project.basedir}/.git + true + + ${project.build.outputDirectory}/git.properties + full + + + + org.apache.maven.plugins + maven-dependency-plugin + + + unpack + prepare-package + + unpack + + + + + ${frontend.groupId} + ${frontend.artifactId} + ${frontend.version} + jar + + ${project.build.directory}/classes + *index* + true + + + + + + + + org.apache.maven.plugins + maven-wrapper-plugin + + + org.jacoco + jacoco-maven-plugin + ${jacoco.version} + + + default-prepare-agent + + prepare-agent + + + + default-report + + report + + + + XML + + + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + + ${skipTests} + + **/*IntegrationTest.java + + + + + maven-failsafe-plugin + + ${skipITs} + + **/*IntegrationTest.java + + + + + + integration-test + verify + + + + + + + com.diffplug.spotless + spotless-maven-plugin + 2.44.3 + + + + src/main/java/**/*.java + src/test/java/**/*.java + + + 1.25.2 + + + + + + + + + + check + apply + + + + + + + org.apache.maven.plugins + maven-antrun-plugin + 3.1.0 + + + validate + + run + + + + + + + + + + + + + + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + + org.umlgraph.doclet.UmlGraphDoc + + org.umlgraph + umlgraph + 5.6 + + -views -all + true + + + + + + + + maven-snapshots + https://repository.apache.org/content/repositories/snapshots/ + + + maven-shade-plugin + + https://mvnrepository.com/artifact/org.apache.maven.plugins/maven-shade-plugin + + + + + + + shiboleth + + https://build.shibboleth.net/nexus/content/repositories/releases/ + + + + maven-central + https://repo1.maven.org/maven2/ + + + + + + default + + true + + + false + + true + + + + integration-test + + true + + false + + + + + maven-central + + + mavenCentral + true + + + + + + org.sonatype.central + central-publishing-maven-plugin + 0.7.0 + true + + central + true + ${mavenCentralDeploymentName} + + + + org.apache.maven.plugins + maven-source-plugin + 3.3.0 + + + attach-sources + verify + + jar-no-fork + + + + + + org.apache.maven.plugins + maven-gpg-plugin + 3.1.0 + + + sign-artifacts + verify + + sign + + + + + + --pinentry-mode + loopback + + + + + org.apache.maven.plugins + maven-javadoc-plugin + 3.6.3 + + + attach-javadoc + + jar + + + + + java + none + + - - - - - - org.apache.maven.plugins - maven-javadoc-plugin - - org.umlgraph.doclet.UmlGraphDoc - - org.umlgraph - umlgraph - 5.6 - - -views -all - true - - - - - - - - - jboss-third-party - - https://repository.jboss.org/nexus/content/repositories/thirdparty-releases/ - - - maven-snapshots - https://repository.apache.org/content/repositories/snapshots/ - - - maven-shade-plugin - - https://mvnrepository.com/artifact/org.apache.maven.plugins/maven-shade-plugin - - - - - - - jitpack.io - https://jitpack.io - - - - jboss-third-party - - https://repository.jboss.org/nexus/content/repositories/thirdparty-releases/ - - - - shiboleth - - https://build.shibboleth.net/nexus/content/repositories/releases/ - - - - maven-central - https://repo1.maven.org/maven2/ - - - - - - default - - true - - - false - - true - - - - integration-test - - true - - false - - - + + + diff --git a/retype.yml b/retype.yml index 146442fdf6a..a44cc4317ad 100644 --- a/retype.yml +++ b/retype.yml @@ -21,6 +21,9 @@ links: - text: Google Group link: https://groups.google.com/g/cbioportal icon: comment-discussion + - text: Donate + link: /donate + icon: heart-fill https://groups: google: @@ -34,3 +37,7 @@ edit: repo: "https://github.com/cbioportal/cbioportal/" branch: master base: /docs/ + +integrations: + googleAnalytics: + id: G-HEJSRG35RS diff --git a/src/main/java/org/cbioportal/AsyncConfig.java b/src/main/java/org/cbioportal/AsyncConfig.java deleted file mode 100644 index a1e5b3041a4..00000000000 --- a/src/main/java/org/cbioportal/AsyncConfig.java +++ /dev/null @@ -1,31 +0,0 @@ -package org.cbioportal; - -import org.springframework.beans.factory.annotation.Value; -import org.springframework.core.env.Environment; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.annotation.Configuration; -import org.springframework.scheduling.annotation.EnableAsync; -import org.springframework.scheduling.annotation.AsyncConfigurer; -import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; - -import java.lang.Runtime; -import java.util.concurrent.Executor; - -@Configuration -@EnableAsync -public class AsyncConfig implements AsyncConfigurer { - - - @Value("${multithread.core_pool_size:#{T(java.lang.Runtime).getRuntime().availableProcessors()}}") - private int corePoolSize; - - @Override - public Executor getAsyncExecutor() { - ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); - executor.setCorePoolSize(corePoolSize); - executor.setThreadNamePrefix("ThreadPoolTaskExecutor-"); - executor.initialize(); - return executor; - } - -} diff --git a/src/main/java/org/cbioportal/PortalApplication.java b/src/main/java/org/cbioportal/PortalApplication.java index bfe458a121b..0daf0424e51 100644 --- a/src/main/java/org/cbioportal/PortalApplication.java +++ b/src/main/java/org/cbioportal/PortalApplication.java @@ -8,20 +8,17 @@ import org.springframework.context.annotation.PropertySources; import org.springframework.transaction.annotation.EnableTransactionManagement; -@SpringBootApplication(exclude = { - MongoAutoConfiguration.class, - MongoDataAutoConfiguration.class -}) +@SpringBootApplication(exclude = {MongoAutoConfiguration.class, MongoDataAutoConfiguration.class}) @PropertySources({ - @PropertySource(ignoreResourceNotFound = true, value = "classpath:application.properties"), - @PropertySource(ignoreResourceNotFound = true, value = "classpath:security.properties"), - @PropertySource(ignoreResourceNotFound = true, value = "classpath:maven.properties"), - @PropertySource(ignoreResourceNotFound = true, value = "classpath:git.properties"), - @PropertySource(ignoreResourceNotFound = true, value = "classpath:springdoc.properties") + @PropertySource(ignoreResourceNotFound = true, value = "classpath:application.properties"), + @PropertySource(ignoreResourceNotFound = true, value = "classpath:security.properties"), + @PropertySource(ignoreResourceNotFound = true, value = "classpath:maven.properties"), + @PropertySource(ignoreResourceNotFound = true, value = "classpath:git.properties"), + @PropertySource(ignoreResourceNotFound = true, value = "classpath:springdoc.properties") }) @EnableTransactionManagement public class PortalApplication { - public static void main(String[] args) { - SpringApplication.run(PortalApplication.class, args); - } + public static void main(String[] args) { + SpringApplication.run(PortalApplication.class, args); + } } diff --git a/src/main/java/org/cbioportal/WebAppConfig.java b/src/main/java/org/cbioportal/WebAppConfig.java deleted file mode 100644 index 2f951690c33..00000000000 --- a/src/main/java/org/cbioportal/WebAppConfig.java +++ /dev/null @@ -1,91 +0,0 @@ -package org.cbioportal; - -import java.util.List; - -import org.cbioportal.web.ExecuterTimeInterceptor; -import org.cbioportal.web.util.InvolvedCancerStudyExtractorInterceptor; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.web.servlet.HandlerInterceptor; -import org.springframework.web.servlet.config.annotation.InterceptorRegistry; -import org.springframework.web.servlet.config.annotation.PathMatchConfigurer; -import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; -import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; -import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; -import org.springframework.web.servlet.handler.WebRequestHandlerInterceptorAdapter; - -// TODO Consider creating separate DispatcherServlets as in the original web.xml -// See: https://stackoverflow.com/a/30686733/11651683 -@Configuration -//@EnableAspectJAutoProxy // TODO no idea what this does; is this logging aspect still useful? -public class WebAppConfig implements WebMvcConfigurer { - - private static final String SINGLE_PAGE_APP_ROOT = "forward:/"; - - @Value("${springdoc.swagger-ui.path:/swagger-ui.html}") - private String swaggerRedirectUrl; - - @Override - public void addResourceHandlers(ResourceHandlerRegistry registry) { - registry.addResourceHandler("/images/**").addResourceLocations("classpath:/webapp/images/"); - registry.addResourceHandler("/reactapp/**").addResourceLocations("classpath:/reactapp/"); - registry.addResourceHandler("/js/**").addResourceLocations("classpath:/js/"); - } - - @Override - public void addViewControllers(ViewControllerRegistry registry) { - registry.addRedirectViewController("/api", swaggerRedirectUrl); - registry.addRedirectViewController("/installations", "https://installationmap.netlify.app/"); - registry.addRedirectViewController("/tutorials", "https://docs.cbioportal.org/user-guide/overview/#tutorial-slides"); - registry.addRedirectViewController("/oql", "https://docs.cbioportal.org/user-guide/oql/"); - registry.addRedirectViewController("/donate", "https://docs.cbioportal.org/donate/"); - - List endpoints = List.of( - "/results/*", - "/results**", - "/patient/*", - "/patient**", - "/study/*", - "/study", - "/mutation_mapper/*", - "/mutation_mapper", - "/index.do/*", - "/case.do/*", - "/loading/*", - "/comparison", - "/comparison/*", - "/restore", - "/index.do**", - "/oncoprinter**", - "/encodedRedirect", - "/datasets**", - "/ln**", - "/webAPI**", - "/news**", - "/visualize**" - ); - - endpoints.forEach( route -> registry.addViewController(route).setViewName(SINGLE_PAGE_APP_ROOT)); - } - - @Bean - public HandlerInterceptor involvedCancerStudyExtractorInterceptor() { - return new InvolvedCancerStudyExtractorInterceptor(); - } - - @Override - public void addInterceptors(InterceptorRegistry registry) { - registry.addInterceptor(involvedCancerStudyExtractorInterceptor()); - registry.addInterceptor(new WebRequestHandlerInterceptorAdapter( - new ExecuterTimeInterceptor() - )).addPathPatterns("/**"); - } - - @Override - public void configurePathMatch(PathMatchConfigurer configurer) { - // Adds support for trailing slash Matches - configurer.setUseTrailingSlashMatch(true); - } - -} diff --git a/src/main/java/org/cbioportal/application/AsyncConfig.java b/src/main/java/org/cbioportal/application/AsyncConfig.java new file mode 100644 index 00000000000..dd9d87645c1 --- /dev/null +++ b/src/main/java/org/cbioportal/application/AsyncConfig.java @@ -0,0 +1,46 @@ +package org.cbioportal.application; + +import java.util.concurrent.Executors; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.boot.web.embedded.tomcat.TomcatProtocolHandlerCustomizer; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.task.AsyncTaskExecutor; +import org.springframework.core.task.support.TaskExecutorAdapter; +import org.springframework.scheduling.annotation.EnableAsync; +import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; + +@Configuration +@EnableAsync +public class AsyncConfig { + + @Value("${multithread.core_pool_size:#{T(java.lang.Runtime).getRuntime().availableProcessors()}}") + private int corePoolSize; + + @Bean + @ConditionalOnProperty( + value = "spring.threads.virtual.enabled", + havingValue = "false", + matchIfMissing = true) + public ThreadPoolTaskExecutor getAsyncExecutor() { + ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); + executor.setCorePoolSize(corePoolSize); + executor.setThreadNamePrefix("ThreadPoolTaskExecutor-"); + executor.initialize(); + return executor; + } + + @Bean + @ConditionalOnProperty(value = "spring.threads.virtual.enabled", havingValue = "true") + public AsyncTaskExecutor applicationTaskExecutor() { + return new TaskExecutorAdapter(Executors.newVirtualThreadPerTaskExecutor()); + } + + @Bean + @ConditionalOnProperty(value = "spring.threads.virtual.enabled", havingValue = "true") + public TomcatProtocolHandlerCustomizer protocolHandlerVirtualThreadExecutorCustomizer() { + return protocolHandler -> + protocolHandler.setExecutor(Executors.newVirtualThreadPerTaskExecutor()); + } +} diff --git a/src/main/java/org/cbioportal/application/WebAppConfig.java b/src/main/java/org/cbioportal/application/WebAppConfig.java new file mode 100644 index 00000000000..9c3c7b5306f --- /dev/null +++ b/src/main/java/org/cbioportal/application/WebAppConfig.java @@ -0,0 +1,92 @@ +package org.cbioportal.application; + +import java.util.List; +import org.cbioportal.legacy.web.ExecuterTimeInterceptor; +import org.cbioportal.legacy.web.util.InvolvedCancerStudyExtractorInterceptor; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.HandlerInterceptor; +import org.springframework.web.servlet.config.annotation.InterceptorRegistry; +import org.springframework.web.servlet.config.annotation.PathMatchConfigurer; +import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; +import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; +import org.springframework.web.servlet.handler.WebRequestHandlerInterceptorAdapter; + +// TODO Consider creating separate DispatcherServlets as in the original web.xml +// See: https://stackoverflow.com/a/30686733/11651683 +@Configuration +// @EnableAspectJAutoProxy // TODO no idea what this does; is this logging aspect still useful? +public class WebAppConfig implements WebMvcConfigurer { + + private static final String SINGLE_PAGE_APP_ROOT = "forward:/"; + + @Value("${springdoc.swagger-ui.path:/swagger-ui.html}") + private String swaggerRedirectUrl; + + @Override + public void addResourceHandlers(ResourceHandlerRegistry registry) { + registry.addResourceHandler("/images/**").addResourceLocations("classpath:/webapp/images/"); + registry.addResourceHandler("/reactapp/**").addResourceLocations("classpath:/reactapp/"); + registry.addResourceHandler("/js/**").addResourceLocations("classpath:/js/"); + } + + @Override + public void addViewControllers(ViewControllerRegistry registry) { + registry.addRedirectViewController("/api", swaggerRedirectUrl); + registry.addRedirectViewController("/installations", "https://installationmap.netlify.app/"); + registry.addRedirectViewController( + "/tutorials", "https://docs.cbioportal.org/user-guide/overview/#tutorial-slides"); + registry.addRedirectViewController("/oql", "https://docs.cbioportal.org/user-guide/oql/"); + registry.addRedirectViewController("/donate", "https://docs.cbioportal.org/donate/"); + + List endpoints = + List.of( + "/results/*", + "/results**", + "/results/comparison/*", + "/results/pathways/*", + "/patient/*", + "/patient**", + "/study/*", + "/study", + "/mutation_mapper/*", + "/mutation_mapper", + "/index.do/*", + "/case.do/*", + "/loading/*", + "/comparison", + "/comparison/*", + "/restore", + "/index.do**", + "/oncoprinter**", + "/encodedRedirect", + "/datasets**", + "/ln**", + "/webAPI**", + "/news**", + "/visualize**"); + + endpoints.forEach(route -> registry.addViewController(route).setViewName(SINGLE_PAGE_APP_ROOT)); + } + + @Bean + public HandlerInterceptor involvedCancerStudyExtractorInterceptor() { + return new InvolvedCancerStudyExtractorInterceptor(); + } + + @Override + public void addInterceptors(InterceptorRegistry registry) { + registry.addInterceptor(involvedCancerStudyExtractorInterceptor()); + registry + .addInterceptor(new WebRequestHandlerInterceptorAdapter(new ExecuterTimeInterceptor())) + .addPathPatterns("/**"); + } + + @Override + public void configurePathMatch(PathMatchConfigurer configurer) { + // Adds support for trailing slash Matches + configurer.setUseTrailingSlashMatch(true); + } +} diff --git a/src/main/java/org/cbioportal/application/documentation/ExternalPageController.java b/src/main/java/org/cbioportal/application/documentation/ExternalPageController.java new file mode 100644 index 00000000000..27f121e9cc0 --- /dev/null +++ b/src/main/java/org/cbioportal/application/documentation/ExternalPageController.java @@ -0,0 +1,52 @@ +package org.cbioportal.application.documentation; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.URL; +import java.net.URLConnection; +import java.net.URLDecoder; +import java.util.Collections; +import java.util.Map; +import org.springframework.stereotype.Controller; +import org.springframework.transaction.annotation.Transactional; +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.bind.annotation.ResponseBody; + +// Retrieve the content of an external page +// Make it auto-scannable +@Controller +public class ExternalPageController { + + // service name: getexternalpage.json + // available via GET method + // sourceURL is required + @Transactional + @RequestMapping( + value = "/api/getexternalpage.json", + method = {RequestMethod.GET}) + public @ResponseBody Map getExternalPage( + @RequestParam(required = true) String sourceURL) throws IOException { + String decodedString, pageText = ""; + + // decode the sourceURL and open a connection + sourceURL = URLDecoder.decode(sourceURL, "UTF-8"); + URL url = new URL(sourceURL); + URLConnection connection = url.openConnection(); + + // create a reader + BufferedReader in = + new BufferedReader(new InputStreamReader(connection.getInputStream(), "UTF-8")); + + // read + while ((decodedString = in.readLine()) != null) { + pageText += decodedString + "\n"; + } + in.close(); + + // turn the pageText into a singletonMap for json and return + return Collections.singletonMap("response", pageText); + } +} diff --git a/src/main/java/org/cbioportal/application/proxy/LegacyProxyController.java b/src/main/java/org/cbioportal/application/proxy/LegacyProxyController.java new file mode 100644 index 00000000000..dbf4ad51d53 --- /dev/null +++ b/src/main/java/org/cbioportal/application/proxy/LegacyProxyController.java @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2015 Memorial Sloan-Kettering Cancer Center. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS + * FOR A PARTICULAR PURPOSE. The software and documentation provided hereunder + * is on an "as is" basis, and Memorial Sloan-Kettering Cancer Center has no + * obligations to provide maintenance, support, updates, enhancements or + * modifications. In no event shall Memorial Sloan-Kettering Cancer Center be + * liable to any party for direct, indirect, special, incidental or + * consequential damages, including lost profits, arising out of the use of this + * software and its documentation, even if Memorial Sloan-Kettering Cancer + * Center has been advised of the possibility of such damage. + */ + +/* + * This file is part of cBioPortal. + * + * cBioPortal is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package org.cbioportal.application.proxy; + +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.HashMap; +import java.util.Map; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpMethod; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Controller; +import org.springframework.util.StringUtils; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.client.RestTemplate; + +@Controller +@RequestMapping("/api/proxy") +public class LegacyProxyController { + + private String bitlyURL; + private String sessionServiceURL; + private Boolean enableOncokb; + + @Value("${bitly.url:''}") + public void setBitlyURL(String property) { + this.bitlyURL = property; + } + + @Value("${session.service.url:''}") // default is empty string + public void setSessionServiceURL(String property) { + this.sessionServiceURL = property; + } + + @Value("${show.oncokb:true}") + public void setEnableOncokb(Boolean property) { + if (property == null) { + property = true; + } + this.enableOncokb = property; + } + + // This is a general proxy for future use. + // Please modify and improve it as needed with your best expertise. The author does not have fully + // understanding + // of JAVA proxy when creating this proxy. + // Created by Hongxin + @RequestMapping(value = "/{path}") + public @ResponseBody String getProxyURL( + @PathVariable String path, + @RequestBody(required = false) String body, + HttpMethod method, + HttpServletRequest request, + HttpServletResponse response) + throws URISyntaxException, IOException { + Map pathToUrl = new HashMap<>(); + + pathToUrl.put("bitly", bitlyURL); + pathToUrl.put("3dHotspots", "https://www.3dhotspots.org/api/hotspots/3d/"); + + String URL = pathToUrl.get(path) == null ? "" : pathToUrl.get(path); + + if (path != null && StringUtils.startsWithIgnoreCase(path, "oncokb") && !enableOncokb) { + response.sendError(403, "OncoKB service is disabled."); + return ""; + } + + // If request method is GET, include query string + if (method.equals(HttpMethod.GET) && request.getQueryString() != null) { + URL += "?" + request.getQueryString(); + } + return respProxy(URL, method, body, response); + } + + private String respProxy(String url, HttpMethod method, Object body, HttpServletResponse response) + throws IOException { + try { + RestTemplate restTemplate = new RestTemplate(); + URI uri = new URI(url); + ResponseEntity responseEntity = + restTemplate.exchange(uri, method, new HttpEntity<>(body), String.class); + return responseEntity.getBody(); + } catch (Exception exception) { + String errorMessage = "Unexpected error: " + exception.getLocalizedMessage(); + response.sendError(503, errorMessage); + return errorMessage; + } + } + + @RequestMapping(value = "/bitly", method = RequestMethod.GET) + public @ResponseBody String getBitlyURL( + HttpMethod method, HttpServletRequest request, HttpServletResponse response) + throws URISyntaxException, IOException { + return respProxy(bitlyURL + request.getQueryString(), method, null, response); + } +} diff --git a/src/main/java/org/cbioportal/application/proxy/Monkifier.java b/src/main/java/org/cbioportal/application/proxy/Monkifier.java new file mode 100644 index 00000000000..f6108146d32 --- /dev/null +++ b/src/main/java/org/cbioportal/application/proxy/Monkifier.java @@ -0,0 +1,52 @@ +package org.cbioportal.application.proxy; + +import jakarta.servlet.http.HttpServletRequest; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; +import org.apache.commons.codec.binary.Base64; +import org.springframework.stereotype.Component; +import org.springframework.util.CollectionUtils; +import org.springframework.web.util.UriComponentsBuilder; + +@Component +public class Monkifier { + public String decodeBase64(String value) { + return new String(Base64.decodeBase64(value.getBytes())); + } + + public String encodeBase64(String value) { + return value == null ? "" : new String(Base64.encodeBase64(value.getBytes())); + } + + public String decodeQueryString(HttpServletRequest request) { + if (request.getQueryString() == null) { + return null; + } + + return this.decodeQueryString(request.getParameterMap()); + } + + public String decodeQueryString(Map encodedQueryParams) { + Map> decodedQueryParams = + encodedQueryParams.entrySet().stream() + .collect( + Collectors.toMap( + e -> this.decodeBase64(e.getKey()), + e -> + Arrays.stream(e.getValue()) + .map(this::decodeBase64) + .collect(Collectors.toList()))); + + return UriComponentsBuilder.newInstance() + .queryParams(CollectionUtils.toMultiValueMap(decodedQueryParams)) + .build() + // encode to avoid potentially invalid query strings + .encode() + .toString() + // remove ? from the beginning of the query string, + // we only want the parameters (e.g: param1=value1¶m2=value2) + .replaceFirst("\\?", ""); + } +} diff --git a/src/main/java/org/cbioportal/application/proxy/ProxyController.java b/src/main/java/org/cbioportal/application/proxy/ProxyController.java new file mode 100644 index 00000000000..6ea63b46f01 --- /dev/null +++ b/src/main/java/org/cbioportal/application/proxy/ProxyController.java @@ -0,0 +1,157 @@ +package org.cbioportal.application.proxy; + +import jakarta.servlet.http.HttpServletRequest; +import java.io.UnsupportedEncodingException; +import java.net.URI; +import java.net.URISyntaxException; +import java.nio.charset.StandardCharsets; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.http.converter.StringHttpMessageConverter; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseStatus; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.client.RestTemplate; + +// TODO Consider creating separate DispatcherServlets as in the original web.xml +// See: https://stackoverflow.com/a/30686733/11651683 + +@RestController +@RequestMapping("/proxy") +public class ProxyController { + private static final String DEFAULT_ONCOKB_URL = "https://public.api.oncokb.org/api/v1"; + + @Autowired private Monkifier monkifier; + + @Value("${oncokb.token:}") + private String oncokbToken; + + @Value("${oncokb.public_api.url:https://public.api.oncokb.org/api/v1}") + private String oncokbApiUrl; + + @Value("${show.oncokb:false}") + private Boolean showOncokb; + + /** + * This dev endpoint can be used (with a personal access token) instead of the production + * endpoint. This is useful when debugging the frontend proxy API calls. + */ + @RequestMapping("/dev/oncokb/**") + public String devProxyOncokb( + @RequestBody(required = false) String body, HttpMethod method, HttpServletRequest request) + throws URISyntaxException { + String token = request.getHeader("X-Proxy-User-Agreement"); + token = (token == null || token.isEmpty()) ? "NA" : token; + + return exchangeOncokbData( + body, + request.getPathInfo().replaceFirst("/dev/oncokb", ""), + request.getQueryString(), + method, + getOncokbHeaders(request, token)); + } + + @RequestMapping("/A8F74CD7851BDEE8DCD2E86AB4E2A711/**") + public String proxyEncodedOncokb( + @RequestBody(required = false) String body, HttpMethod method, HttpServletRequest request) + throws URISyntaxException, UnsupportedEncodingException { + // make sure that the custom Proxy User Agreement header exists + String proxyUserAgreement = request.getHeader("X-Proxy-User-Agreement"); + if (proxyUserAgreement == null + || !proxyUserAgreement.equals( + "I/We do NOT use this obfuscated proxy to programmatically obtain private OncoKB data. " + + "I/We know that I/we should get a valid data access token by registering at https://www.oncokb.org/account/register.")) { + throw new OncoKBProxyUserAgreementException(); + } + + String decodedBody = body == null ? null : this.monkifier.decodeBase64(body); + String encodedPath = + request.getRequestURI().replaceFirst("/proxy/A8F74CD7851BDEE8DCD2E86AB4E2A711/", ""); + String decodedPath = this.monkifier.decodeBase64(encodedPath); + String decodedQueryString = this.monkifier.decodeQueryString(request); + + String response = + exchangeOncokbData( + decodedBody, decodedPath, decodedQueryString, method, getOncokbHeaders(request)); + + return "\"" + this.monkifier.encodeBase64(response) + "\""; + } + + private String exchangeOncokbData( + String body, String pathInfo, String queryString, HttpMethod method, HttpHeaders httpHeaders) + throws URISyntaxException { + return exchangeData( + body, + buildUri(this.oncokbApiUrl + pathInfo, queryString), + method, + httpHeaders, + String.class) + .getBody(); + } + + private HttpHeaders getOncokbHeaders(HttpServletRequest request) { + return this.getOncokbHeaders(request, null); + } + + private HttpHeaders getOncokbHeaders(HttpServletRequest request, String token) { + String oncokbToken = token == null ? this.oncokbToken : token; + + if (!this.showOncokb) { + throw new OncoKBServiceIsDisabledException(); + } + + HttpHeaders httpHeaders = initHeaders(request); + + if (!StringUtils.isEmpty(oncokbToken)) { + httpHeaders.add("Authorization", "Bearer " + oncokbToken); + } + + return httpHeaders; + } + + private HttpHeaders initHeaders(HttpServletRequest request) { + HttpHeaders httpHeaders = new HttpHeaders(); + + String contentType = request.getHeader("Content-Type"); + if (contentType != null) { + httpHeaders.setContentType(MediaType.valueOf(contentType)); + } + + return httpHeaders; + } + + private URI buildUri(String path, String queryString, boolean useSecureProtocol) + throws URISyntaxException { + return buildUri((useSecureProtocol ? "https" : "http") + ":/" + path, queryString); + } + + private URI buildUri(String path, String queryString) throws URISyntaxException { + return new URI(path + (queryString == null ? "" : "?" + queryString)); + } + + private ResponseEntity exchangeData( + String body, URI uri, HttpMethod method, HttpHeaders httpHeaders, Class responseType) { + RestTemplate restTemplate = new RestTemplate(); + restTemplate + .getMessageConverters() + .add(0, new StringHttpMessageConverter(StandardCharsets.UTF_8)); + return restTemplate.exchange(uri, method, new HttpEntity<>(body, httpHeaders), responseType); + } + + @ResponseStatus(code = HttpStatus.NOT_FOUND, reason = "OncoKB service is disabled") + public class OncoKBServiceIsDisabledException extends RuntimeException {} + + @ResponseStatus(code = HttpStatus.BAD_REQUEST, reason = "Fair Usage Agreement is missing") + public class OncoKBProxyUserAgreementException extends RuntimeException {} + + @ResponseStatus(code = HttpStatus.BAD_REQUEST, reason = "Unknown/Invalid hostname") + public class UnknownHostException extends RuntimeException {} +} diff --git a/src/main/java/org/cbioportal/application/rest/mapper/CancerStudyMetadataMapper.java b/src/main/java/org/cbioportal/application/rest/mapper/CancerStudyMetadataMapper.java new file mode 100644 index 00000000000..efacc478cf8 --- /dev/null +++ b/src/main/java/org/cbioportal/application/rest/mapper/CancerStudyMetadataMapper.java @@ -0,0 +1,27 @@ +package org.cbioportal.application.rest.mapper; + +import java.util.List; +import org.cbioportal.application.rest.response.CancerStudyMetadataDTO; +import org.cbioportal.domain.cancerstudy.CancerStudyMetadata; +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; +import org.mapstruct.factory.Mappers; + +@Mapper +public interface CancerStudyMetadataMapper { + CancerStudyMetadataMapper INSTANCE = Mappers.getMapper(CancerStudyMetadataMapper.class); + + @Mapping(target = "importDate", source = "importDate", dateFormat = "yyyy-MM-dd HH:mm:ss") + @Mapping(target = "studyId", source = "cancerStudyIdentifier") + @Mapping(target = "cancerTypeId", source = "typeOfCancerId") + // TODO: ReadPermission needs to be implemented + @Mapping(target = "readPermission", source = "publicStudy") + CancerStudyMetadataDTO toDto(CancerStudyMetadata cancerStudyMetadata); + + @Mapping(target = "importDate", source = "importDate", dateFormat = "yyyy-MM-dd HH:mm:ss") + @Mapping(target = "studyId", source = "cancerStudyIdentifier") + @Mapping(target = "cancerTypeId", source = "typeOfCancerId") + // TODO: ReadPermission needs to be implemented + @Mapping(target = "readPermission", source = "publicStudy") + List toDtos(List cancerStudyMetadataList); +} diff --git a/src/main/java/org/cbioportal/application/rest/mapper/SampleMapper.java b/src/main/java/org/cbioportal/application/rest/mapper/SampleMapper.java new file mode 100644 index 00000000000..7c6dffc2be6 --- /dev/null +++ b/src/main/java/org/cbioportal/application/rest/mapper/SampleMapper.java @@ -0,0 +1,30 @@ +package org.cbioportal.application.rest.mapper; + +import java.util.List; +import org.cbioportal.application.rest.response.SampleDTO; +import org.cbioportal.domain.sample.Sample; +import org.cbioportal.legacy.utils.Encoder; +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; +import org.mapstruct.factory.Mappers; + +@Mapper(imports = Encoder.class) +public interface SampleMapper { + SampleMapper INSTANCE = Mappers.getMapper(SampleMapper.class); + + @Mapping(target = "patientId", source = "patientStableId") + @Mapping(target = "sampleId", source = "stableId") + @Mapping(target = "studyId", source = "cancerStudyIdentifier") + @Mapping( + target = "uniqueSampleKey", + expression = + "java( Encoder.calculateBase64(sample.stableId()," + "sample.cancerStudyIdentifier()) )") + @Mapping( + target = "uniquePatientKey", + expression = + "java( Encoder.calculateBase64(sample.patientStableId(), " + + "sample.cancerStudyIdentifier()) )") + SampleDTO toSampleDTO(Sample sample); + + List toDtos(List samples); +} diff --git a/src/main/java/org/cbioportal/application/rest/request/StudyViewFilterDTO.java b/src/main/java/org/cbioportal/application/rest/request/StudyViewFilterDTO.java new file mode 100644 index 00000000000..8ec09718115 --- /dev/null +++ b/src/main/java/org/cbioportal/application/rest/request/StudyViewFilterDTO.java @@ -0,0 +1,248 @@ +package org.cbioportal.application.rest.request; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonInclude.Include; +import jakarta.validation.Valid; +import jakarta.validation.constraints.AssertTrue; +import jakarta.validation.constraints.Size; +import java.util.List; +import java.util.Objects; +import org.cbioportal.legacy.model.AlterationFilter; +import org.cbioportal.legacy.model.GeneFilter; +import org.cbioportal.legacy.model.StudyViewStructuralVariantFilter; +import org.cbioportal.legacy.web.parameter.ClinicalDataFilter; +import org.cbioportal.legacy.web.parameter.DataFilter; +import org.cbioportal.legacy.web.parameter.GenericAssayDataFilter; +import org.cbioportal.legacy.web.parameter.GenomicDataFilter; +import org.cbioportal.legacy.web.parameter.MutationDataFilter; +import org.cbioportal.legacy.web.parameter.SampleIdentifier; +import org.cbioportal.legacy.web.parameter.filter.AndedPatientTreatmentFilters; +import org.cbioportal.legacy.web.parameter.filter.AndedSampleTreatmentFilters; + +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(Include.NON_NULL) +public class StudyViewFilterDTO { + + @Size(min = 1) + private List sampleIdentifiers; + + @Size(min = 1) + private List studyIds; + + private List clinicalDataFilters; + private List geneFilters; + @Valid private List structuralVariantFilters; + private AndedSampleTreatmentFilters sampleTreatmentFilters; + private AndedSampleTreatmentFilters sampleTreatmentGroupFilters; + private AndedSampleTreatmentFilters sampleTreatmentTargetFilters; + private AndedPatientTreatmentFilters patientTreatmentFilters; + private AndedPatientTreatmentFilters patientTreatmentGroupFilters; + private AndedPatientTreatmentFilters patientTreatmentTargetFilters; + private List> genomicProfiles; + private List genomicDataFilters; + private List genericAssayDataFilters; + private List> caseLists; + private List customDataFilters; + private AlterationFilter alterationFilter; + private List clinicalEventFilters; + private List mutationDataFilters; + + @AssertTrue + private boolean isEitherSampleIdentifiersOrStudyIdsPresent() { + return sampleIdentifiers != null ^ studyIds != null; + } + + @AssertTrue + private boolean isEitherValueOrRangePresentInClinicalDataIntervalFilters() { + return validateDataFilters(clinicalDataFilters); + } + + @AssertTrue + private boolean isEitherValueOrRangePresentInGenomicDataIntervalFilters() { + return validateDataFilters(genomicDataFilters); + } + + @AssertTrue + private boolean isEitherValueOrRangePresentInGenericAssayDataIntervalFilters() { + return validateDataFilters(genericAssayDataFilters); + } + + @AssertTrue + private boolean isEitherValueOrRangePresentInCustomDataFilters() { + return validateDataFilters(customDataFilters); + } + + private boolean validateDataFilters(List dataFilters) { + long invalidCount = 0; + + if (dataFilters != null) { + invalidCount = + dataFilters.stream() + .flatMap(f -> f.getValues().stream()) + .filter(Objects::nonNull) + .filter(v -> v.getValue() != null == (v.getStart() != null || v.getEnd() != null)) + .count(); + } + + return invalidCount == 0; + } + + public List getSampleIdentifiers() { + return sampleIdentifiers; + } + + public void setSampleIdentifiers(List sampleIdentifiers) { + this.sampleIdentifiers = sampleIdentifiers; + } + + public List getStudyIds() { + return studyIds; + } + + public void setStudyIds(List studyIds) { + this.studyIds = studyIds; + } + + public List getClinicalDataFilters() { + return clinicalDataFilters; + } + + public void setClinicalDataFilters(List clinicalDataFilters) { + this.clinicalDataFilters = clinicalDataFilters; + } + + public List getGeneFilters() { + return geneFilters; + } + + public void setGeneFilters(List geneFilters) { + this.geneFilters = geneFilters; + } + + public List getStructuralVariantFilters() { + return structuralVariantFilters; + } + + public void setStructuralVariantFilters( + List structuralVariantFilters) { + this.structuralVariantFilters = + (structuralVariantFilters != null) ? structuralVariantFilters : List.of(); + } + + public List> getGenomicProfiles() { + return genomicProfiles; + } + + public void setGenomicProfiles(List> genomicProfiles) { + this.genomicProfiles = genomicProfiles; + } + + public List getGenomicDataFilters() { + return genomicDataFilters; + } + + public void setGenomicDataFilters(List genomicDataFilters) { + this.genomicDataFilters = genomicDataFilters; + } + + public AndedSampleTreatmentFilters getSampleTreatmentFilters() { + return sampleTreatmentFilters; + } + + public void setSampleTreatmentFilters(AndedSampleTreatmentFilters sampleTreatmentFilters) { + this.sampleTreatmentFilters = sampleTreatmentFilters; + } + + public AndedPatientTreatmentFilters getPatientTreatmentFilters() { + return patientTreatmentFilters; + } + + public void setPatientTreatmentFilters(AndedPatientTreatmentFilters patientTreatmentFilters) { + this.patientTreatmentFilters = patientTreatmentFilters; + } + + public List> getCaseLists() { + return caseLists; + } + + public void setCaseLists(List> caseLists) { + this.caseLists = caseLists; + } + + public List getGenericAssayDataFilters() { + return genericAssayDataFilters; + } + + public void setGenericAssayDataFilters(List genericAssayDataFilters) { + this.genericAssayDataFilters = genericAssayDataFilters; + } + + public List getCustomDataFilters() { + return customDataFilters; + } + + public void setCustomDataFilters(List customDataFilters) { + this.customDataFilters = customDataFilters; + } + + public AlterationFilter getAlterationFilter() { + return alterationFilter; + } + + public void setAlterationFilter(AlterationFilter alterationFilter) { + this.alterationFilter = (alterationFilter != null) ? alterationFilter : new AlterationFilter(); + } + + public AndedSampleTreatmentFilters getSampleTreatmentGroupFilters() { + return sampleTreatmentGroupFilters; + } + + public void setSampleTreatmentGroupFilters( + AndedSampleTreatmentFilters sampleTreatmentGroupFilters) { + this.sampleTreatmentGroupFilters = sampleTreatmentGroupFilters; + } + + public AndedPatientTreatmentFilters getPatientTreatmentGroupFilters() { + return patientTreatmentGroupFilters; + } + + public void setPatientTreatmentGroupFilters( + AndedPatientTreatmentFilters patientTreatmentGroupFilters) { + this.patientTreatmentGroupFilters = patientTreatmentGroupFilters; + } + + public AndedSampleTreatmentFilters getSampleTreatmentTargetFilters() { + return sampleTreatmentTargetFilters; + } + + public void setSampleTreatmentTargetFilters( + AndedSampleTreatmentFilters sampleTreatmentTargetFilters) { + this.sampleTreatmentTargetFilters = sampleTreatmentTargetFilters; + } + + public AndedPatientTreatmentFilters getPatientTreatmentTargetFilters() { + return patientTreatmentTargetFilters; + } + + public void setPatientTreatmentTargetFilters( + AndedPatientTreatmentFilters patientTreatmentTagetFilters) { + this.patientTreatmentTargetFilters = patientTreatmentTagetFilters; + } + + public List getClinicalEventFilters() { + return clinicalEventFilters; + } + + public void setClinicalEventFilters(List clinicalEventFilters) { + this.clinicalEventFilters = clinicalEventFilters; + } + + public List getMutationDataFilters() { + return mutationDataFilters; + } + + public void setMutationDataFilters(List mutationDataFilters) { + this.mutationDataFilters = mutationDataFilters; + } +} diff --git a/src/main/java/org/cbioportal/application/rest/response/CancerStudyMetadataDTO.java b/src/main/java/org/cbioportal/application/rest/response/CancerStudyMetadataDTO.java new file mode 100644 index 00000000000..5f7d9b30ee1 --- /dev/null +++ b/src/main/java/org/cbioportal/application/rest/response/CancerStudyMetadataDTO.java @@ -0,0 +1,33 @@ +package org.cbioportal.application.rest.response; + +import io.swagger.v3.oas.annotations.media.Schema; +import org.cbioportal.domain.cancerstudy.TypeOfCancer; + +@Schema(name = "CancerStudyMetadata", description = "Represents a cancer study") +public record CancerStudyMetadataDTO( + String studyId, + String cancerTypeId, + String name, + String description, + Boolean publicStudy, + String pmid, + String citation, + String groups, + Integer status, + String importDate, + Integer allSampleCount, + Integer sequencedSampleCount, + Integer cnaSampleCount, + Integer mrnaRnaSeqSampleCount, + Integer mrnaRnaSeqV2SampleCount, + Integer mrnaMicroarraySampleCount, + Integer miRnaSampleCount, + Integer methylationHm27SampleCount, + Integer rppaSampleCount, + Integer massSpectrometrySampleCount, + Integer completeSampleCount, + String referenceGenome, + Integer treatmentCount, + Integer structuralVariantCount, + TypeOfCancer typeOfCancer, + Boolean readPermission) {} diff --git a/src/main/java/org/cbioportal/application/rest/response/SampleDTO.java b/src/main/java/org/cbioportal/application/rest/response/SampleDTO.java new file mode 100644 index 00000000000..7b0ad1b9db7 --- /dev/null +++ b/src/main/java/org/cbioportal/application/rest/response/SampleDTO.java @@ -0,0 +1,13 @@ +package org.cbioportal.application.rest.response; + +import org.cbioportal.domain.sample.SampleType; + +public record SampleDTO( + String sampleId, + SampleType sampleType, + String patientId, + String studyId, + Boolean sequenced, + Boolean copyNumberSegmentPresent, + String uniqueSampleKey, + String uniquePatientKey) {} diff --git a/src/main/java/org/cbioportal/application/rest/vcolumnstore/ColumnStoreSampleController.java b/src/main/java/org/cbioportal/application/rest/vcolumnstore/ColumnStoreSampleController.java new file mode 100644 index 00000000000..b33e3a8ed1a --- /dev/null +++ b/src/main/java/org/cbioportal/application/rest/vcolumnstore/ColumnStoreSampleController.java @@ -0,0 +1,328 @@ +package org.cbioportal.application.rest.vcolumnstore; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.ArraySchema; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import jakarta.validation.Valid; +import jakarta.validation.constraints.Max; +import jakarta.validation.constraints.Min; +import java.util.List; +import org.cbioportal.application.rest.mapper.SampleMapper; +import org.cbioportal.application.rest.response.SampleDTO; +import org.cbioportal.domain.sample.Sample; +import org.cbioportal.domain.sample.usecase.SampleUseCases; +import org.cbioportal.legacy.model.CancerStudy; +import org.cbioportal.legacy.model.meta.BaseMeta; +import org.cbioportal.legacy.service.StudyService; +import org.cbioportal.legacy.service.exception.PatientNotFoundException; +import org.cbioportal.legacy.service.exception.SampleNotFoundException; +import org.cbioportal.legacy.service.exception.StudyNotFoundException; +import org.cbioportal.legacy.utils.security.AccessLevel; +import org.cbioportal.legacy.utils.security.PortalSecurityConfig; +import org.cbioportal.legacy.web.parameter.Direction; +import org.cbioportal.legacy.web.parameter.HeaderKeyConstants; +import org.cbioportal.legacy.web.parameter.PagingConstants; +import org.cbioportal.legacy.web.parameter.SampleFilter; +import org.cbioportal.legacy.web.parameter.sort.SampleSortBy; +import org.cbioportal.shared.enums.ProjectionType; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Profile; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/api/column-store") +@Validated +@Profile("clickhouse") +public class ColumnStoreSampleController { + public static final int SAMPLE_MAX_PAGE_SIZE = 10000000; + private static final String SAMPLE_DEFAULT_PAGE_SIZE = "10000000"; + + private final SampleUseCases sampleUseCases; + + private final StudyService studyService; + + @Value("${authenticate}") + private String authenticate; + + public ColumnStoreSampleController(SampleUseCases sampleUseCases, StudyService studyService) { + this.sampleUseCases = sampleUseCases; + this.studyService = studyService; + } + + @GetMapping(value = "/samples", produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(description = "Get all samples matching keyword") + @ApiResponse( + responseCode = "200", + description = "OK", + content = @Content(array = @ArraySchema(schema = @Schema(implementation = Sample.class)))) + public ResponseEntity> getSamplesByKeyword( + @Parameter(description = "Search keyword that applies to the study ID") + @RequestParam(required = false) + String keyword, + @Parameter(description = "Level of detail of the response") + @RequestParam(defaultValue = "SUMMARY") + ProjectionType projection, + @Parameter(description = "Page size of the result list") + @Max(PagingConstants.MAX_PAGE_SIZE) + @Min(PagingConstants.MIN_PAGE_SIZE) + @RequestParam(defaultValue = PagingConstants.DEFAULT_PAGE_SIZE) + Integer pageSize, + @Parameter(description = "Page number of the result list") + @Min(PagingConstants.MIN_PAGE_NUMBER) + @RequestParam(defaultValue = PagingConstants.DEFAULT_PAGE_NUMBER) + Integer pageNumber, + @Parameter(description = "Name of the property that the result list is sorted by") + @RequestParam(required = false) + SampleSortBy sortBy, + @Parameter(description = "Direction of the sort") @RequestParam(defaultValue = "ASC") + Direction direction) { + String sort = sortBy == null ? null : sortBy.getOriginalValue(); + List studyIds = null; + + // TODO is there a better way to do this? something like @PreAuthorize? + // (this code segment is duplicate of the legacy SampleController) + if (PortalSecurityConfig.userAuthorizationEnabled(authenticate)) { + /* + If using auth, filter the list of samples returned using the list of study ids the + user has access to. If the user has access to no studies, the endpoint should not 403, + but instead return an empty list. + */ + studyIds = + studyService + .getAllStudies( + null, + ProjectionType.SUMMARY.name(), // force to summary so that post filter doesn't NPE + PagingConstants.MAX_PAGE_SIZE, + 0, + null, + direction.name(), + null, + AccessLevel.READ) + .stream() + .map(CancerStudy::getCancerStudyIdentifier) + .toList(); + } + + if (projection == ProjectionType.META) { + HttpHeaders responseHeaders = getMetaSamplesHeaders(keyword, studyIds); + return new ResponseEntity<>(responseHeaders, HttpStatus.OK); + } else { + List samples = + sampleUseCases + .getAllSamplesUseCase() + .execute(keyword, studyIds, projection, pageSize, pageNumber, sort, direction.name()); + + return new ResponseEntity<>(SampleMapper.INSTANCE.toDtos(samples), HttpStatus.OK); + } + } + + @PreAuthorize( + "hasPermission(#sampleFilter, 'SampleFilter', T(org.cbioportal.legacy.utils.security.AccessLevel).READ)") + @PostMapping( + value = "/samples/fetch", + consumes = MediaType.APPLICATION_JSON_VALUE, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(description = "Fetch samples by ID") + @ApiResponse( + responseCode = "200", + description = "OK", + content = @Content(array = @ArraySchema(schema = @Schema(implementation = Sample.class)))) + public ResponseEntity> fetchSamples( + @Parameter(required = true, description = "List of sample identifiers") + @Valid + @RequestBody(required = false) + SampleFilter sampleFilter, + @Parameter(description = "Level of detail of the response") + @RequestParam(defaultValue = "SUMMARY") + ProjectionType projection) { + if (projection == ProjectionType.META) { + HttpHeaders responseHeaders = fetchMetaSamplesHeaders(sampleFilter); + return new ResponseEntity<>(responseHeaders, HttpStatus.OK); + } else { + List samples = sampleUseCases.fetchSamplesUseCase().execute(sampleFilter, projection); + return new ResponseEntity<>(SampleMapper.INSTANCE.toDtos(samples), HttpStatus.OK); + } + } + + @PreAuthorize( + "hasPermission(#studyId, 'CancerStudyId', T(org.cbioportal.legacy.utils.security.AccessLevel).READ)") + @GetMapping(value = "/studies/{studyId}/samples", produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(description = "Get all samples in a study") + @ApiResponse( + responseCode = "200", + description = "OK", + content = @Content(array = @ArraySchema(schema = @Schema(implementation = Sample.class)))) + public ResponseEntity> getAllSamplesInStudy( + @Parameter(required = true, description = "Study ID e.g. acc_tcga") @PathVariable + String studyId, + @Parameter(description = "Level of detail of the response") + @RequestParam(defaultValue = "SUMMARY") + ProjectionType projection, + @Parameter(description = "Page size of the result list") + @Max(SAMPLE_MAX_PAGE_SIZE) + @Min(PagingConstants.MIN_PAGE_SIZE) + @RequestParam(defaultValue = SAMPLE_DEFAULT_PAGE_SIZE) + Integer pageSize, + @Parameter(description = "Page number of the result list") + @Min(PagingConstants.MIN_PAGE_NUMBER) + @RequestParam(defaultValue = PagingConstants.DEFAULT_PAGE_NUMBER) + Integer pageNumber, + @Parameter(description = "Name of the property that the result list is sorted by") + @RequestParam(required = false) + SampleSortBy sortBy, + @Parameter(description = "Direction of the sort") @RequestParam(defaultValue = "ASC") + Direction direction) + throws StudyNotFoundException { + if (projection == ProjectionType.META) { + HttpHeaders responseHeaders = getMetaSamplesInStudyHeaders(studyId); + return new ResponseEntity<>(responseHeaders, HttpStatus.OK); + } else { + List samples = + sampleUseCases + .getAllSamplesInStudyUseCase() + .execute( + studyId, + projection, + pageSize, + pageNumber, + sortBy == null ? null : sortBy.getOriginalValue(), + direction.name()); + + return new ResponseEntity<>(SampleMapper.INSTANCE.toDtos(samples), HttpStatus.OK); + } + } + + @PreAuthorize( + "hasPermission(#studyId, 'CancerStudyId', T(org.cbioportal.legacy.utils.security.AccessLevel).READ)") + @GetMapping( + value = "/studies/{studyId}/samples/{sampleId}", + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(description = "Get a sample in a study") + @ApiResponse( + responseCode = "200", + description = "OK", + content = @Content(schema = @Schema(implementation = Sample.class))) + public ResponseEntity getSampleInStudy( + @Parameter(required = true, description = "Study ID e.g. acc_tcga") @PathVariable + String studyId, + @Parameter(required = true, description = "Sample ID e.g. TCGA-OR-A5J2-01") @PathVariable + String sampleId) + throws SampleNotFoundException, StudyNotFoundException { + return new ResponseEntity<>( + SampleMapper.INSTANCE.toSampleDTO( + sampleUseCases.getSampleInStudyUseCase().execute(studyId, sampleId)), + HttpStatus.OK); + } + + @PreAuthorize( + "hasPermission(#studyId, 'CancerStudyId', T(org.cbioportal.legacy.utils.security.AccessLevel).READ)") + @GetMapping( + value = "/studies/{studyId}/patients/{patientId}/samples", + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(description = "Get all samples of a patient in a study") + @ApiResponse( + responseCode = "200", + description = "OK", + content = @Content(array = @ArraySchema(schema = @Schema(implementation = Sample.class)))) + public ResponseEntity> getAllSamplesOfPatientInStudy( + @Parameter(required = true, description = "Study ID e.g. acc_tcga") @PathVariable + String studyId, + @Parameter(required = true, description = "Patient ID e.g. TCGA-OR-A5J2") @PathVariable + String patientId, + @Parameter(description = "Level of detail of the response") + @RequestParam(defaultValue = "SUMMARY") + ProjectionType projection, + @Parameter(description = "Page size of the result list") + @Max(SAMPLE_MAX_PAGE_SIZE) + @Min(PagingConstants.MIN_PAGE_SIZE) + @RequestParam(defaultValue = SAMPLE_DEFAULT_PAGE_SIZE) + Integer pageSize, + @Parameter(description = "Page number of the result list") + @Min(PagingConstants.MIN_PAGE_NUMBER) + @RequestParam(defaultValue = PagingConstants.DEFAULT_PAGE_NUMBER) + Integer pageNumber, + @Parameter(description = "Name of the property that the result list is sorted by") + @RequestParam(required = false) + SampleSortBy sortBy, + @Parameter(description = "Direction of the sort") @RequestParam(defaultValue = "ASC") + Direction direction) + throws PatientNotFoundException, StudyNotFoundException { + if (projection == ProjectionType.META) { + HttpHeaders responseHeaders = getMetaSamplesOfPatientInStudyHeaders(studyId, patientId); + return new ResponseEntity<>(responseHeaders, HttpStatus.OK); + } else { + List samples = + sampleUseCases + .getAllSamplesOfPatientInStudyUseCase() + .execute( + studyId, + patientId, + projection, + pageSize, + pageNumber, + sortBy == null ? null : sortBy.getOriginalValue(), + direction.name()); + + return new ResponseEntity<>(SampleMapper.INSTANCE.toDtos(samples), HttpStatus.OK); + } + } + + private HttpHeaders fetchMetaSamplesHeaders(SampleFilter sampleFilter) { + HttpHeaders httpHeaders = new HttpHeaders(); + BaseMeta baseMeta = sampleUseCases.fetchMetaSamplesUseCase().execute(sampleFilter); + httpHeaders.add(HeaderKeyConstants.TOTAL_COUNT, baseMeta.getTotalCount().toString()); + + return httpHeaders; + } + + private HttpHeaders getMetaSamplesHeaders(String keyword, List studyIds) { + HttpHeaders httpHeaders = new HttpHeaders(); + httpHeaders.add( + HeaderKeyConstants.TOTAL_COUNT, + sampleUseCases + .getMetaSamplesUseCase() + .execute(keyword, studyIds) + .getTotalCount() + .toString()); + + return httpHeaders; + } + + private HttpHeaders getMetaSamplesInStudyHeaders(String studyId) throws StudyNotFoundException { + HttpHeaders httpHeaders = new HttpHeaders(); + httpHeaders.add( + HeaderKeyConstants.TOTAL_COUNT, + sampleUseCases.getMetaSamplesInStudyUseCase().execute(studyId).getTotalCount().toString()); + + return httpHeaders; + } + + private HttpHeaders getMetaSamplesOfPatientInStudyHeaders(String studyId, String patientId) + throws StudyNotFoundException, PatientNotFoundException { + HttpHeaders httpHeaders = new HttpHeaders(); + httpHeaders.add( + HeaderKeyConstants.TOTAL_COUNT, + sampleUseCases + .getMetaSamplesOfPatientInStudyUseCase() + .execute(studyId, patientId) + .getTotalCount() + .toString()); + + return httpHeaders; + } +} diff --git a/src/main/java/org/cbioportal/application/rest/vcolumnstore/ColumnStoreStudyController.java b/src/main/java/org/cbioportal/application/rest/vcolumnstore/ColumnStoreStudyController.java new file mode 100644 index 00000000000..f940b6c1b07 --- /dev/null +++ b/src/main/java/org/cbioportal/application/rest/vcolumnstore/ColumnStoreStudyController.java @@ -0,0 +1,98 @@ +package org.cbioportal.application.rest.vcolumnstore; + +import io.swagger.v3.oas.annotations.Hidden; +import io.swagger.v3.oas.annotations.Parameter; +import java.util.List; +import org.cbioportal.application.rest.mapper.CancerStudyMetadataMapper; +import org.cbioportal.application.rest.response.CancerStudyMetadataDTO; +import org.cbioportal.domain.cancerstudy.usecase.GetCancerStudyMetadataUseCase; +import org.cbioportal.legacy.web.parameter.Direction; +import org.cbioportal.legacy.web.parameter.sort.StudySortBy; +import org.cbioportal.shared.SortAndSearchCriteria; +import org.cbioportal.shared.enums.ProjectionType; +import org.springframework.context.annotation.Profile; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +/** + * REST controller for managing and retrieving cancer study metadata from a column-store data + * source. + * + *

This controller provides an endpoint to fetch cancer study metadata with support for + * filtering, sorting, and controlling the level of detail in the response. It is designed to work + * with a column-store database, which is optimized for querying large datasets efficiently. + * + * @see GetCancerStudyMetadataUseCase + * @see CancerStudyMetadataDTO + * @see ProjectionType + * @see StudySortBy + * @see Direction + */ +@RestController +@RequestMapping("/api/column-store") +@Profile("clickhouse") +public class ColumnStoreStudyController { + + private final GetCancerStudyMetadataUseCase getCancerStudyMetadataUseCase; + + /** + * Constructs a new {@link ColumnStoreStudyController} with the specified use case. + * + * @param getCancerStudyMetadataUseCase the use case responsible for retrieving cancer study + * metadata. + */ + public ColumnStoreStudyController(GetCancerStudyMetadataUseCase getCancerStudyMetadataUseCase) { + this.getCancerStudyMetadataUseCase = getCancerStudyMetadataUseCase; + } + + /** + * Retrieves a list of cancer study metadata based on the specified criteria. + * + *

This endpoint supports filtering by keyword, controlling the level of detail in the response + * through the projection parameter, and sorting the results by a specified property and + * direction. + * + *

Note: This endpoint is marked as {@link Hidden} and will not be exposed in the API + * documentation. + * + * @param keyword the search keyword that applies to the name and cancer type of the studies. This + * parameter is optional. + * @param projection the level of detail of the response. Defaults to {@link + * ProjectionType#SUMMARY}. + * @param sortBy the name of the property that the result list is sorted by. This parameter is + * optional. + * @param direction the direction of the sort. Defaults to {@link Direction#ASC}. + * @return a {@link ResponseEntity} containing a list of {@link CancerStudyMetadataDTO} objects + * and an HTTP status code {@link HttpStatus#OK}. + * @see ProjectionType + * @see StudySortBy + * @see Direction + */ + @Hidden + @GetMapping(value = "/studies", produces = MediaType.APPLICATION_JSON_VALUE) + public ResponseEntity> getAllStudies( + @Parameter(description = "Search keyword that applies to name and cancer type of the studies") + @RequestParam(required = false) + String keyword, + @Parameter(description = "Level of detail of the response") + @RequestParam(defaultValue = "SUMMARY") + ProjectionType projection, + @Parameter(description = "Name of the property that the result list is sorted by") + @RequestParam(required = false) + StudySortBy sortBy, + @Parameter(description = "Direction of the sort") @RequestParam(defaultValue = "ASC") + Direction direction) { + + var sortAndSearchCriteria = + new SortAndSearchCriteria( + keyword, (sortBy != null ? sortBy.getOriginalValue() : ""), direction.toString()); + return ResponseEntity.ok( + CancerStudyMetadataMapper.INSTANCE.toDtos( + getCancerStudyMetadataUseCase.execute(projection, sortAndSearchCriteria))); + } +} diff --git a/src/main/java/org/cbioportal/application/rest/vcolumnstore/ColumnarStoreAlterationEnrichmentController.java b/src/main/java/org/cbioportal/application/rest/vcolumnstore/ColumnarStoreAlterationEnrichmentController.java new file mode 100644 index 00000000000..8875ce0a549 --- /dev/null +++ b/src/main/java/org/cbioportal/application/rest/vcolumnstore/ColumnarStoreAlterationEnrichmentController.java @@ -0,0 +1,85 @@ +package org.cbioportal.application.rest.vcolumnstore; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.ArraySchema; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import jakarta.validation.Valid; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.logging.Logger; +import java.util.stream.Collectors; +import org.cbioportal.domain.alteration.usecase.GetAlterationEnrichmentsUseCase; +import org.cbioportal.legacy.model.AlterationEnrichment; +import org.cbioportal.legacy.model.EnrichmentType; +import org.cbioportal.legacy.model.MolecularProfileCaseIdentifier; +import org.cbioportal.legacy.service.exception.MolecularProfileNotFoundException; +import org.cbioportal.legacy.web.parameter.MolecularProfileCasesGroupAndAlterationTypeFilter; +import org.cbioportal.legacy.web.parameter.MolecularProfileCasesGroupFilter; +import org.springframework.context.annotation.Profile; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.RequestBody; +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.bind.annotation.RestController; + +@RestController +@RequestMapping("/api/column-store") +@Profile("clickhouse") +public class ColumnarStoreAlterationEnrichmentController { + + private final GetAlterationEnrichmentsUseCase getAlterationEnrichmentsUseCase; + private final Logger logger = + Logger.getLogger(ColumnarStoreAlterationEnrichmentController.class.getName()); + + public ColumnarStoreAlterationEnrichmentController( + GetAlterationEnrichmentsUseCase getAlterationEnrichmentsUseCase) { + this.getAlterationEnrichmentsUseCase = getAlterationEnrichmentsUseCase; + } + + @PreAuthorize( + "hasPermission(#groupsAndAlterationTypes, 'MolecularProfileCasesGroupAndAlterationTypeFilter', T(org.cbioportal.legacy.utils.security.AccessLevel).READ)") + @RequestMapping( + value = "/alteration-enrichments/fetch", + method = RequestMethod.POST, + consumes = MediaType.APPLICATION_JSON_VALUE, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(summary = "Fetch alteration enrichments in molecular profiles") + @ApiResponse( + responseCode = "200", + description = "OK", + content = + @Content( + array = @ArraySchema(schema = @Schema(implementation = AlterationEnrichment.class)))) + public ResponseEntity> fetchAlterationEnrichments( + @Parameter(description = "Type of the enrichment e.g. SAMPLE or PATIENT") + @RequestParam(defaultValue = "SAMPLE") + EnrichmentType enrichmentType, + @Parameter( + required = true, + description = + "List of groups containing sample identifiers and list of Alteration Types") + @Valid + @RequestBody(required = false) + MolecularProfileCasesGroupAndAlterationTypeFilter groupsAndAlterationTypes) + throws MolecularProfileNotFoundException { + Map> groupCaseIdentifierSet = + groupsAndAlterationTypes.getMolecularProfileCasesGroupFilter().stream() + .collect( + Collectors.toMap( + MolecularProfileCasesGroupFilter::getName, + MolecularProfileCasesGroupFilter::getMolecularProfileCaseIdentifiers)); + + return ResponseEntity.ok( + getAlterationEnrichmentsUseCase.execute( + groupCaseIdentifierSet, + enrichmentType, + groupsAndAlterationTypes.getAlterationEventTypes())); + } +} diff --git a/src/main/java/org/cbioportal/application/rest/vcolumnstore/ColumnarStoreStudyViewController.java b/src/main/java/org/cbioportal/application/rest/vcolumnstore/ColumnarStoreStudyViewController.java new file mode 100644 index 00000000000..043af8ae077 --- /dev/null +++ b/src/main/java/org/cbioportal/application/rest/vcolumnstore/ColumnarStoreStudyViewController.java @@ -0,0 +1,700 @@ +package org.cbioportal.application.rest.vcolumnstore; + +import static java.util.stream.Collectors.toSet; + +import io.swagger.v3.oas.annotations.Hidden; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.ArraySchema; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import jakarta.validation.Valid; +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Set; +import org.cbioportal.application.rest.mapper.SampleMapper; +import org.cbioportal.application.rest.response.SampleDTO; +import org.cbioportal.domain.sample.Sample; +import org.cbioportal.domain.studyview.StudyViewService; +import org.cbioportal.infrastructure.service.BasicDataBinner; +import org.cbioportal.infrastructure.service.ClinicalDataBinner; +import org.cbioportal.legacy.model.AlterationCountByGene; +import org.cbioportal.legacy.model.CaseListDataCount; +import org.cbioportal.legacy.model.ClinicalData; +import org.cbioportal.legacy.model.ClinicalDataBin; +import org.cbioportal.legacy.model.ClinicalDataCountItem; +import org.cbioportal.legacy.model.ClinicalEventKeyCode; +import org.cbioportal.legacy.model.ClinicalEventTypeCount; +import org.cbioportal.legacy.model.ClinicalViolinPlotData; +import org.cbioportal.legacy.model.CopyNumberCountByGene; +import org.cbioportal.legacy.model.DensityPlotData; +import org.cbioportal.legacy.model.GenericAssayDataBin; +import org.cbioportal.legacy.model.GenericAssayDataCountItem; +import org.cbioportal.legacy.model.GenomicDataBin; +import org.cbioportal.legacy.model.GenomicDataCount; +import org.cbioportal.legacy.model.GenomicDataCountItem; +import org.cbioportal.legacy.model.PatientTreatmentReport; +import org.cbioportal.legacy.model.SampleTreatmentReport; +import org.cbioportal.legacy.service.ClinicalDataDensityPlotService; +import org.cbioportal.legacy.service.CustomDataService; +import org.cbioportal.legacy.service.ViolinPlotService; +import org.cbioportal.legacy.service.exception.StudyNotFoundException; +import org.cbioportal.legacy.service.util.CustomDataSession; +import org.cbioportal.legacy.web.columnar.util.CustomDataFilterUtil; +import org.cbioportal.legacy.web.columnar.util.NewStudyViewFilterUtil; +import org.cbioportal.legacy.web.parameter.ClinicalDataBinCountFilter; +import org.cbioportal.legacy.web.parameter.ClinicalDataCountFilter; +import org.cbioportal.legacy.web.parameter.ClinicalDataFilter; +import org.cbioportal.legacy.web.parameter.DataBinMethod; +import org.cbioportal.legacy.web.parameter.GenericAssayDataBinCountFilter; +import org.cbioportal.legacy.web.parameter.GenericAssayDataCountFilter; +import org.cbioportal.legacy.web.parameter.GenericAssayDataFilter; +import org.cbioportal.legacy.web.parameter.GenomicDataBinCountFilter; +import org.cbioportal.legacy.web.parameter.GenomicDataCountFilter; +import org.cbioportal.legacy.web.parameter.GenomicDataFilter; +import org.cbioportal.legacy.web.parameter.MutationOption; +import org.cbioportal.legacy.web.parameter.Projection; +import org.cbioportal.legacy.web.parameter.SampleIdentifier; +import org.cbioportal.legacy.web.parameter.StudyViewFilter; +import org.cbioportal.legacy.web.util.DensityPlotParameters; +import org.springframework.context.annotation.Profile; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/api/column-store") +@Profile("clickhouse") +public class ColumnarStoreStudyViewController { + + private final StudyViewService studyViewService; + private final BasicDataBinner basicDataBinner; + private final ClinicalDataBinner clinicalDataBinner; + private final ClinicalDataDensityPlotService clinicalDataDensityPlotService; + private final ViolinPlotService violinPlotService; + private final CustomDataService customDataService; + private final CustomDataFilterUtil customDataFilterUtil; + + public ColumnarStoreStudyViewController( + StudyViewService studyViewService, + BasicDataBinner basicDataBinner, + ClinicalDataBinner clinicalDataBinner, + ClinicalDataDensityPlotService clinicalDataDensityPlotService, + ViolinPlotService violinPlotService, + CustomDataService customDataService, + CustomDataFilterUtil customDataFilterUtil) { + this.studyViewService = studyViewService; + this.basicDataBinner = basicDataBinner; + this.clinicalDataBinner = clinicalDataBinner; + this.clinicalDataDensityPlotService = clinicalDataDensityPlotService; + this.violinPlotService = violinPlotService; + this.customDataService = customDataService; + this.customDataFilterUtil = customDataFilterUtil; + } + + @Hidden + @PostMapping( + value = "/filtered-samples/fetch", + consumes = MediaType.APPLICATION_JSON_VALUE, + produces = MediaType.APPLICATION_JSON_VALUE) + @PreAuthorize( + "hasPermission(#studyViewFilter, 'StudyViewFilter', T(org.cbioportal.legacy.utils.security.AccessLevel).READ)") + public ResponseEntity> fetchFilteredSamples( + @RequestParam(defaultValue = "false") Boolean negateFilters, + @RequestBody(required = false) StudyViewFilter studyViewFilter) { + return ResponseEntity.ok( + SampleMapper.INSTANCE.toDtos(studyViewService.getFilteredSamples(studyViewFilter))); + } + + @Hidden // should unhide when we remove legacy controller + @PostMapping( + value = "/mutated-genes/fetch", + consumes = MediaType.APPLICATION_JSON_VALUE, + produces = MediaType.APPLICATION_JSON_VALUE) + @PreAuthorize( + "hasPermission(#studyViewFilter, 'StudyViewFilter', T(org.cbioportal.legacy.utils.security.AccessLevel).READ)") + public ResponseEntity> fetchMutatedGenes( + @RequestBody(required = false) StudyViewFilter studyViewFilter) + throws StudyNotFoundException { + return ResponseEntity.ok(studyViewService.getMutatedGenes(studyViewFilter)); + } + + @Hidden // should unhide when we remove legacy controller + @PostMapping( + value = "/molecular-profile-sample-counts/fetch", + consumes = MediaType.APPLICATION_JSON_VALUE, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(description = "Fetch sample counts by study view filter") + @PreAuthorize( + "hasPermission(#studyViewFilter, 'StudyViewFilter', T(org.cbioportal.legacy.utils.security.AccessLevel).READ)") + @ApiResponse( + responseCode = "200", + description = "OK", + content = + @Content(array = @ArraySchema(schema = @Schema(implementation = GenomicDataCount.class)))) + public ResponseEntity> fetchMolecularProfileSampleCounts( + @Parameter(required = true, description = "Study view filter") + @Valid + @RequestBody(required = false) + StudyViewFilter studyViewFilter) + throws StudyNotFoundException { + return ResponseEntity.ok(studyViewService.getMolecularProfileSampleCounts(studyViewFilter)); + } + + @Hidden // should unhide when we remove legacy controller + @PostMapping( + value = "/cna-genes/fetch", + consumes = MediaType.APPLICATION_JSON_VALUE, + produces = MediaType.APPLICATION_JSON_VALUE) + @PreAuthorize( + "hasPermission(#studyViewFilter, 'StudyViewFilter', T(org.cbioportal.legacy.utils.security.AccessLevel).READ)") + public ResponseEntity> fetchCnaGenes( + @RequestBody(required = false) StudyViewFilter studyViewFilter) + throws StudyNotFoundException { + return ResponseEntity.ok(studyViewService.getCnaGenes(studyViewFilter)); + } + + @Hidden // should unhide when we remove legacy controller + @PostMapping( + value = "/structuralvariant-genes/fetch", + consumes = MediaType.APPLICATION_JSON_VALUE, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(description = "Fetch structural variant genes by study view filter") + @ApiResponse( + responseCode = "200", + description = "OK", + content = + @Content( + array = @ArraySchema(schema = @Schema(implementation = AlterationCountByGene.class)))) + @PreAuthorize( + "hasPermission(#studyViewFilter, 'StudyViewFilter', T(org.cbioportal.legacy.utils.security.AccessLevel).READ)") + public ResponseEntity> fetchStructuralVariantGenes( + @Parameter(required = true, description = "Study view filter") + @Valid + @RequestBody(required = false) + StudyViewFilter studyViewFilter) + throws StudyNotFoundException { + return ResponseEntity.ok(studyViewService.getStructuralVariantGenes(studyViewFilter)); + } + + @Hidden // should unhide when we remove legacy controller + @PostMapping( + value = "/clinical-data-counts/fetch", + consumes = MediaType.APPLICATION_JSON_VALUE, + produces = MediaType.APPLICATION_JSON_VALUE) + @PreAuthorize( + "hasPermission(#clinicalDataCountFilter, 'ClinicalDataCountFilter', T(org.cbioportal.legacy.utils.security.AccessLevel).READ)") + public ResponseEntity> fetchClinicalDataCounts( + @RequestBody(required = false) ClinicalDataCountFilter clinicalDataCountFilter) { + + List attributes = clinicalDataCountFilter.getAttributes(); + StudyViewFilter studyViewFilter = clinicalDataCountFilter.getStudyViewFilter(); + + if (attributes.size() == 1) { + NewStudyViewFilterUtil.removeClinicalDataFilter( + attributes.getFirst().getAttributeId(), studyViewFilter.getClinicalDataFilters()); + } + List result = + studyViewService.getClinicalDataCounts( + studyViewFilter, attributes.stream().map(ClinicalDataFilter::getAttributeId).toList()); + return ResponseEntity.ok(result); + } + + @Hidden // should unhide when we remove legacy controller + @PostMapping( + value = "/sample-lists-counts/fetch", + consumes = MediaType.APPLICATION_JSON_VALUE, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(description = "Fetch case list sample counts by study view filter") + @PreAuthorize( + "hasPermission(#studyViewFilter, 'StudyViewFilter', T(org.cbioportal.legacy.utils.security.AccessLevel).READ)") + public List fetchCaseListCounts( + @Parameter(required = true, description = "Study view filter") + @Valid + @RequestBody(required = false) + StudyViewFilter studyViewFilter) { + + return studyViewService.getCaseListDataCounts(studyViewFilter); + } + + @Hidden // should unhide when we remove legacy controller + @PostMapping( + value = "/clinical-data-bin-counts/fetch", + consumes = MediaType.APPLICATION_JSON_VALUE, + produces = MediaType.APPLICATION_JSON_VALUE) + @PreAuthorize( + "hasPermission(#clinicalDataBinCountFilter, 'DataBinCountFilter', T(org.cbioportal.legacy.utils.security.AccessLevel).READ)") + public ResponseEntity> fetchClinicalDataBinCounts( + @RequestParam(defaultValue = "DYNAMIC") DataBinMethod dataBinMethod, + @RequestBody(required = false) ClinicalDataBinCountFilter clinicalDataBinCountFilter) { + List clinicalDataBins = + clinicalDataBinner.fetchClinicalDataBinCounts( + dataBinMethod, clinicalDataBinCountFilter, true); + return new ResponseEntity<>(clinicalDataBins, HttpStatus.OK); + } + + @Hidden // should unhide when we remove legacy controller + @PostMapping( + value = "/clinical-data-density-plot/fetch", + consumes = MediaType.APPLICATION_JSON_VALUE, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(description = "Fetch clinical data density plot bins by study view filter") + @ApiResponse( + responseCode = "200", + description = "OK", + content = @Content(schema = @Schema(implementation = DensityPlotData.class))) + @Validated + @PreAuthorize( + "hasPermission(#studyViewFilter, 'StudyViewFilter', T(org.cbioportal.legacy.utils.security.AccessLevel).READ)") + public ResponseEntity fetchClinicalDataDensityPlot( + @Parameter(required = true, description = "Clinical Attribute ID of the X axis") @RequestParam + String xAxisAttributeId, + @Parameter(description = "Number of the bins in X axis") @RequestParam(defaultValue = "50") + Integer xAxisBinCount, + @Parameter(description = "Starting point of the X axis, if different than smallest value") + @RequestParam(required = false) + BigDecimal xAxisStart, + @Parameter(description = "Starting point of the X axis, if different than largest value") + @RequestParam(required = false) + BigDecimal xAxisEnd, + @Parameter(required = true, description = "Clinical Attribute ID of the Y axis") @RequestParam + String yAxisAttributeId, + @Parameter(description = "Number of the bins in Y axis") @RequestParam(defaultValue = "50") + Integer yAxisBinCount, + @Parameter(description = "Starting point of the Y axis, if different than smallest value") + @RequestParam(required = false) + BigDecimal yAxisStart, + @Parameter(description = "Starting point of the Y axis, if different than largest value") + @RequestParam(required = false) + BigDecimal yAxisEnd, + @Parameter(description = "Use log scale for X axis") + @RequestParam(required = false, defaultValue = "false") + Boolean xAxisLogScale, + @Schema(defaultValue = "false") + @Parameter(description = "Use log scale for Y axis") + @RequestParam(required = false, defaultValue = "false") + Boolean yAxisLogScale, + @Parameter(required = true, description = "Study view filter") @RequestBody(required = false) + StudyViewFilter studyViewFilter) { + DensityPlotParameters densityPlotParameters = + new DensityPlotParameters.Builder() + .xAxisAttributeId(xAxisAttributeId) + .yAxisAttributeId(yAxisAttributeId) + .xAxisBinCount(xAxisBinCount) + .yAxisBinCount(yAxisBinCount) + .xAxisStart(xAxisStart) + .yAxisStart(yAxisStart) + .xAxisEnd(xAxisEnd) + .yAxisEnd(yAxisEnd) + .xAxisLogScale(xAxisLogScale) + .yAxisLogScale(yAxisLogScale) + .build(); + + List combinedClinicalDataList = + studyViewService.getClinicalDataForXyPlot( + studyViewFilter, List.of(xAxisAttributeId, yAxisAttributeId), false); + + DensityPlotData result = + clinicalDataDensityPlotService.getDensityPlotData( + combinedClinicalDataList, densityPlotParameters, studyViewFilter); + + return new ResponseEntity<>(result, HttpStatus.OK); + } + + @Hidden // should unhide when we remove legacy controller + @PreAuthorize( + "hasPermission(#studyViewFilter, 'StudyViewFilter', T(org.cbioportal.legacy.utils.security.AccessLevel).READ)") + @PostMapping( + value = "/clinical-data-violin-plots/fetch", + consumes = MediaType.APPLICATION_JSON_VALUE, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation( + description = + "Fetch violin plot curves per categorical clinical data value, filtered by study view filter") + @ApiResponse( + responseCode = "200", + description = "OK", + content = @Content(schema = @Schema(implementation = ClinicalViolinPlotData.class))) + public ResponseEntity fetchClinicalDataViolinPlots( + @Parameter( + required = true, + description = "Clinical Attribute ID of the categorical attribute") + @RequestParam + String categoricalAttributeId, + @Parameter(required = true, description = "Clinical Attribute ID of the numerical attribute") + @RequestParam + String numericalAttributeId, + @Parameter( + description = + "Starting point of the violin plot axis, if different than smallest value") + @RequestParam(required = false) + BigDecimal axisStart, + @Parameter( + description = + "Ending point of the violin plot axis, if different than largest value") + @RequestParam(required = false) + BigDecimal axisEnd, + @Parameter(description = "Number of points in the curve") + @RequestParam(required = false, defaultValue = "100") + BigDecimal numCurvePoints, + @Parameter(description = "Use log scale for the numerical attribute") + @RequestParam(required = false, defaultValue = "false") + Boolean logScale, + @Parameter(description = "Sigma stepsize multiplier") + @RequestParam(required = false, defaultValue = "1") + BigDecimal sigmaMultiplier, + @Parameter(required = true, description = "Study view filter") + @Valid + @RequestBody(required = false) + StudyViewFilter studyViewFilter) { + // fetch the samples by using the provided study view filter + List filteredSamples = studyViewService.getFilteredSamples(studyViewFilter); + + // remove the numerical clinical data filter from the study view filter. + // this new modified filter is used to fetch sample and patient clinical data. + // this is required to get the complete violin plot data. + // filteredSamples reflects only the original unmodified study view filter. + // we will need to fetch samples again to get the samples corresponding to this modified filter, + // otherwise patient to sample mapping may be incomplete. + if (studyViewFilter.getClinicalDataFilters() != null) { + studyViewFilter.getClinicalDataFilters().stream() + .filter(f -> f.getAttributeId().equals(numericalAttributeId)) + .findAny() + .ifPresent(f -> studyViewFilter.getClinicalDataFilters().remove(f)); + } + + List combinedClinicalDataList = + studyViewService.getClinicalDataForXyPlot( + studyViewFilter, + List.of(numericalAttributeId, categoricalAttributeId), + true // filter out clinical data with empty attribute values due to Clickhouse migration + ); + + // Only mutation count can use log scale + boolean useLogScale = logScale && numericalAttributeId.equals("MUTATION_COUNT"); + + Set sampleIdsSet = filteredSamples.stream().map(Sample::internalId).collect(toSet()); + + ClinicalViolinPlotData result = + violinPlotService.getClinicalViolinPlotData( + combinedClinicalDataList, + sampleIdsSet, + axisStart, + axisEnd, + numCurvePoints, + useLogScale, + sigmaMultiplier, + studyViewFilter); + + return new ResponseEntity<>(result, HttpStatus.OK); + } + + @Hidden // should unhide when we remove legacy controller + @PostMapping( + value = "/genomic-data-counts/fetch", + consumes = MediaType.APPLICATION_JSON_VALUE, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(description = "Fetch genomic data counts by GenomicDataCountFilter") + @ApiResponse( + responseCode = "200", + description = "OK", + content = + @Content( + array = @ArraySchema(schema = @Schema(implementation = GenomicDataCountItem.class)))) + @PreAuthorize( + "hasPermission(#genomicDataCountFilter, 'GenomicDataCountFilter', T(org.cbioportal.legacy.utils.security.AccessLevel).READ)") + public ResponseEntity> fetchGenomicDataCounts( + @Parameter(required = true, description = "Genomic data count filter") + @Valid + @RequestBody(required = false) + GenomicDataCountFilter genomicDataCountFilter) + throws StudyNotFoundException { + List genomicDataFilters = genomicDataCountFilter.getGenomicDataFilters(); + StudyViewFilter studyViewFilter = genomicDataCountFilter.getStudyViewFilter(); + // when there is only one filter, it means study view is doing a single chart filter operation + // remove filter from studyViewFilter to return all data counts + // the reason we do this is to make sure after chart get filtered, user can still see unselected + // portion of the chart + if (genomicDataFilters.size() == 1) { + NewStudyViewFilterUtil.removeSelfFromGenomicDataFilter( + genomicDataFilters.get(0).getHugoGeneSymbol(), + genomicDataFilters.get(0).getProfileType(), + studyViewFilter); + } + + // This endpoint is CNA specific. The name choice of "genomic data" does not imply it support + // other genomic data types + List result = + studyViewService.getCNACountsByGeneSpecific(studyViewFilter, genomicDataFilters); + + return new ResponseEntity<>(result, HttpStatus.OK); + } + + @Hidden // should unhide when we remove legacy controller + @PostMapping( + value = "/generic-assay-data-counts/fetch", + consumes = MediaType.APPLICATION_JSON_VALUE, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(description = "Fetch generic assay data counts by study view filter") + @ApiResponse( + responseCode = "200", + description = "OK", + content = + @Content( + array = + @ArraySchema(schema = @Schema(implementation = GenericAssayDataCountItem.class)))) + @PreAuthorize( + "hasPermission(#genericAssayDataCountFilter, 'GenericAssayDataCountFilter', T(org.cbioportal.legacy.utils.security.AccessLevel).READ)") + public ResponseEntity> fetchGenericAssayDataCounts( + @Parameter(required = true, description = "Generic assay data count filter") + @Valid + @RequestBody(required = false) + GenericAssayDataCountFilter genericAssayDataCountFilter) { + + List gaFilters = + genericAssayDataCountFilter.getGenericAssayDataFilters(); + StudyViewFilter studyViewFilter = genericAssayDataCountFilter.getStudyViewFilter(); + // when there is only one filter, it means study view is doing a single chart filter operation + // remove filter from studyViewFilter to return all data counts + // the reason we do this is to make sure after chart get filtered, user can still see unselected + // portion of the chart + + if (gaFilters.size() == 1) { + NewStudyViewFilterUtil.removeSelfFromGenericAssayFilter( + gaFilters.getFirst().getStableId(), studyViewFilter); + } + + return ResponseEntity.ok( + studyViewService.getGenericAssayDataCounts(studyViewFilter, gaFilters)); + } + + @Hidden // should unhide when we remove legacy controller + @PostMapping( + value = "/mutation-data-counts/fetch", + consumes = MediaType.APPLICATION_JSON_VALUE, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(description = "Fetch mutation data counts by GenomicDataCountFilter") + @PreAuthorize( + "hasPermission(#genomicDataCountFilter, 'GenomicDataCountFilter', T(org.cbioportal.legacy.utils.security.AccessLevel).READ)") + public ResponseEntity> fetchMutationDataCounts( + @Parameter(description = "Level of detail of the response") + @RequestParam(defaultValue = "SUMMARY") + Projection projection, + @Parameter(required = true, description = "Genomic data count filter") + @Valid + @RequestBody(required = false) + GenomicDataCountFilter genomicDataCountFilter) { + List genomicDataFilters = genomicDataCountFilter.getGenomicDataFilters(); + StudyViewFilter studyViewFilter = genomicDataCountFilter.getStudyViewFilter(); + // when there is only one filter, it means study view is doing a single chart filter operation + // remove filter from studyViewFilter to return all data counts + // the reason we do this is to make sure after chart get filtered, user can still see unselected + // portion of the chart + if (genomicDataFilters.size() == 1 && projection == Projection.SUMMARY) { + NewStudyViewFilterUtil.removeSelfFromMutationDataFilter( + genomicDataFilters.get(0).getHugoGeneSymbol(), + genomicDataFilters.get(0).getProfileType(), + MutationOption.MUTATED, + studyViewFilter); + } + + List result = + projection == Projection.SUMMARY + ? studyViewService.getMutationCountsByGeneSpecific(studyViewFilter, genomicDataFilters) + : studyViewService.getMutationTypeCountsByGeneSpecific( + studyViewFilter, genomicDataFilters); + + return ResponseEntity.ok(result); + } + + @Hidden // should unhide when we remove legacy controller + @PostMapping( + value = "/clinical-event-type-counts/fetch", + consumes = MediaType.APPLICATION_JSON_VALUE, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(description = "Get Counts of Clinical Event Types by Study View Filter") + @ApiResponse( + responseCode = "200", + description = "OK", + content = + @Content( + array = + @ArraySchema(schema = @Schema(implementation = ClinicalEventTypeCount.class)))) + @PreAuthorize( + "hasPermission(#studyViewFilter, 'StudyViewFilter', T(org.cbioportal.legacy.utils.security.AccessLevel).READ)") + public ResponseEntity> getClinicalEventTypeCounts( + @Parameter(required = true, description = "Study view filter") + @Valid + @RequestBody(required = false) + StudyViewFilter studyViewFilter) { + return ResponseEntity.ok(studyViewService.getClinicalEventTypeCounts(studyViewFilter)); + } + + @PostMapping( + value = "/treatments/patient-counts/fetch", + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(description = "Get all patient level treatments") + @ApiResponse( + responseCode = "200", + description = "OK", + content = @Content(schema = @Schema(implementation = PatientTreatmentReport.class))) + @PreAuthorize( + "hasPermission(#studyViewFilter, 'StudyViewFilter', T(org.cbioportal.legacy.utils.security.AccessLevel).READ)") + public ResponseEntity fetchPatientTreatmentCounts( + @Parameter(required = false) + @RequestParam(name = "tier", required = false, defaultValue = "Agent") + ClinicalEventKeyCode tier, + @Parameter(required = true, description = "Study view filter") + @Valid + @RequestBody(required = false) + StudyViewFilter studyViewFilter) { + return ResponseEntity.ok(studyViewService.getPatientTreatmentReport(studyViewFilter)); + } + + @PostMapping( + value = "/treatments/sample-counts/fetch", + produces = MediaType.APPLICATION_JSON_VALUE) + @ApiResponse( + responseCode = "200", + description = "OK", + content = @Content(schema = @Schema(implementation = SampleTreatmentReport.class))) + @PreAuthorize( + "hasPermission(#studyViewFilter, 'StudyViewFilter', T(org.cbioportal.legacy.utils.security.AccessLevel).READ)") + public ResponseEntity fetchSampleTreatmentCounts( + @Parameter(required = false) + @RequestParam(name = "tier", required = false, defaultValue = "Agent") + ClinicalEventKeyCode tier, + @Parameter(required = true, description = "Study view filter") + @Valid + @RequestBody(required = false) + StudyViewFilter studyViewFilter) { + return ResponseEntity.ok(studyViewService.getSampleTreatmentReport(studyViewFilter)); + } + + @Hidden // should unhide when we remove legacy controller + @PostMapping( + value = "/custom-data-counts/fetch", + consumes = MediaType.APPLICATION_JSON_VALUE, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(description = "Fetch custom data counts by study view filter") + @ApiResponse( + responseCode = "200", + description = "OK", + content = + @Content( + array = @ArraySchema(schema = @Schema(implementation = ClinicalDataCountItem.class)))) + @PreAuthorize( + "hasPermission(#clinicalDataCountFilter, 'DataCountFilter', T(org.cbioportal.legacy.utils.security.AccessLevel).READ)") + public ResponseEntity> fetchCustomDataCounts( + @Parameter(required = true, description = "Custom data count filter") + @Valid + @RequestBody(required = false) + ClinicalDataCountFilter clinicalDataCountFilter) { + + List attributes = clinicalDataCountFilter.getAttributes(); + StudyViewFilter studyViewFilter = clinicalDataCountFilter.getStudyViewFilter(); + if (attributes.size() == 1) { + NewStudyViewFilterUtil.removeClinicalDataFilter( + attributes.getFirst().getAttributeId(), studyViewFilter.getCustomDataFilters()); + } + + List filteredSampleIdentifiers = + studyViewService.getFilteredSamples(studyViewFilter).stream() + .map( + sample -> + NewStudyViewFilterUtil.buildSampleIdentifier( + sample.cancerStudyIdentifier(), sample.stableId())) + .toList(); + + if (filteredSampleIdentifiers.isEmpty()) { + return new ResponseEntity<>(new ArrayList<>(), HttpStatus.OK); + } + + final List attributeIds = + attributes.stream().map(ClinicalDataFilter::getAttributeId).toList(); + Map customDataSessionsMap = + customDataService.getCustomDataSessions(attributeIds); + + List result = + customDataFilterUtil.getCustomDataCounts(filteredSampleIdentifiers, customDataSessionsMap); + + return new ResponseEntity<>(result, HttpStatus.OK); + } + + @Hidden // should unhide when we remove legacy controller + @PostMapping( + value = "/custom-data-bin-counts/fetch", + consumes = MediaType.APPLICATION_JSON_VALUE, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(description = "Fetch custom data bin counts by study view filter") + @ApiResponse( + responseCode = "200", + description = "OK", + content = + @Content(array = @ArraySchema(schema = @Schema(implementation = ClinicalDataBin.class)))) + @PreAuthorize( + "hasPermission(#clinicalDataBinCountFilter, 'DataBinCountFilter', T(org.cbioportal.legacy.utils.security.AccessLevel).READ)") + public ResponseEntity> fetchCustomDataBinCounts( + @Parameter(description = "Method for data binning") @RequestParam(defaultValue = "DYNAMIC") + DataBinMethod dataBinMethod, + @Parameter(required = true, description = "Clinical data bin count filter") + @Valid + @RequestBody(required = false) + ClinicalDataBinCountFilter clinicalDataBinCountFilter) { + List customDataBins = + basicDataBinner.getDataBins(dataBinMethod, clinicalDataBinCountFilter, true); + return ResponseEntity.ok(customDataBins); + } + + @Hidden // should unhide when we remove legacy controller + @PostMapping( + value = "/genomic-data-bin-counts/fetch", + consumes = MediaType.APPLICATION_JSON_VALUE, + produces = MediaType.APPLICATION_JSON_VALUE) + @ApiResponse( + responseCode = "200", + description = "OK", + content = + @Content(array = @ArraySchema(schema = @Schema(implementation = GenomicDataBin.class)))) + @PreAuthorize( + "hasPermission(#genomicDataBinCountFilter, 'DataBinCountFilter', T(org.cbioportal.legacy.utils.security.AccessLevel).READ)") + public ResponseEntity> fetchGenomicDataBinCounts( + @RequestParam(defaultValue = "DYNAMIC") DataBinMethod dataBinMethod, + @RequestBody(required = false) GenomicDataBinCountFilter genomicDataBinCountFilter) { + List genomicDataBins = + basicDataBinner.getDataBins(dataBinMethod, genomicDataBinCountFilter, true); + return ResponseEntity.ok(genomicDataBins); + } + + @Hidden // should unhide when we remove legacy controller + @PostMapping( + value = "/generic-assay-data-bin-counts/fetch", + consumes = MediaType.APPLICATION_JSON_VALUE, + produces = MediaType.APPLICATION_JSON_VALUE) + @ApiResponse( + responseCode = "200", + description = "OK", + content = + @Content( + array = @ArraySchema(schema = @Schema(implementation = GenericAssayDataBin.class)))) + @PreAuthorize( + "hasPermission(#genericAssayDataBinCountFilter, 'DataBinCountFilter', T(org.cbioportal.legacy.utils.security.AccessLevel).READ)") + public ResponseEntity> fetchGenericAssayDataBinCounts( + @RequestParam(defaultValue = "DYNAMIC") DataBinMethod dataBinMethod, + @RequestBody(required = false) + GenericAssayDataBinCountFilter genericAssayDataBinCountFilter) { + List genericAssayDataBins = + basicDataBinner.getDataBins(dataBinMethod, genericAssayDataBinCountFilter, true); + return ResponseEntity.ok(genericAssayDataBins); + } +} diff --git a/src/main/java/org/cbioportal/application/security/CancerStudyPermissionEvaluator.java b/src/main/java/org/cbioportal/application/security/CancerStudyPermissionEvaluator.java new file mode 100644 index 00000000000..e4b32bd5ea3 --- /dev/null +++ b/src/main/java/org/cbioportal/application/security/CancerStudyPermissionEvaluator.java @@ -0,0 +1,512 @@ +/* + * Copyright (c) 2015 - 2019 Memorial Sloan-Kettering Cancer Center. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS + * FOR A PARTICULAR PURPOSE. The software and documentation provided hereunder + * is on an "as is" basis, and Memorial Sloan-Kettering Cancer Center has no + * obligations to provide maintenance, support, updates, enhancements or + * modifications. In no event shall Memorial Sloan-Kettering Cancer Center be + * liable to any party for direct, indirect, special, incidental or + * consequential damages, including lost profits, arising out of the use of this + * software and its documentation, even if Memorial Sloan-Kettering Cancer + * Center has been advised of the possibility of such damage. + */ + +/* + * This file is part of cBioPortal. + * + * cBioPortal is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package org.cbioportal.application.security; + +import java.io.Serializable; +import java.util.*; +import java.util.stream.Collectors; +import org.cbioportal.application.security.util.CancerStudyExtractorUtil; +import org.cbioportal.legacy.model.CancerStudy; +import org.cbioportal.legacy.model.MolecularProfile; +import org.cbioportal.legacy.model.MolecularProfileCaseIdentifier; +import org.cbioportal.legacy.model.Patient; +import org.cbioportal.legacy.model.SampleList; +import org.cbioportal.legacy.persistence.cachemaputil.CacheMapUtil; +import org.cbioportal.legacy.utils.security.AccessLevel; +import org.cbioportal.legacy.web.parameter.ClinicalDataCountFilter; +import org.cbioportal.legacy.web.parameter.DataBinCountFilter; +import org.cbioportal.legacy.web.parameter.GenericAssayDataCountFilter; +import org.cbioportal.legacy.web.parameter.GenomicDataCountFilter; +import org.cbioportal.legacy.web.parameter.MolecularProfileCasesGroupAndAlterationTypeFilter; +import org.cbioportal.legacy.web.parameter.SampleFilter; +import org.cbioportal.legacy.web.parameter.StudyViewFilter; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.security.access.PermissionEvaluator; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.authority.AuthorityUtils; + +/** + * A custom PermissionEvaluator implementation that checks whether a particular user has access to a + * particular cancer study. + * + *

Anonymous users will only get access to public studies. + * + * @author Benjamin Gross + */ +public class CancerStudyPermissionEvaluator implements PermissionEvaluator { + + private final CacheMapUtil cacheMapUtil; + + private static final String ALL_CANCER_STUDIES_ID = "all"; + private static final String ALL_TCGA_CANCER_STUDIES_ID = "all_tcga"; + private static final String ALL_TARGET_CANCER_STUDIES_ID = "all_nci_target"; + private static final String TARGET_TYPE_CANCER_STUDY_ID = "CancerStudyId"; + private static final String TARGET_TYPE_MOLECULAR_PROFILE_ID = "MolecularProfileId"; + private static final String TARGET_TYPE_GENETIC_PROFILE_ID = "GeneticProfileId"; + private static final String TARGET_TYPE_SAMPLE_LIST_ID = "SampleListId"; + private static final String TARGET_TYPE_COLLECTION_OF_SAMPLE_LIST_IDS = + "Collection"; + private static final String TARGET_TYPE_COLLECTION_OF_CANCER_STUDY_IDS = + "Collection"; + private static final String TARGET_TYPE_COLLECTION_OF_MOLECULAR_PROFILE_IDS = + "Collection"; + private static final String TARGET_TYPE_COLLECTION_OF_GENETIC_PROFILE_IDS = + "Collection"; + private static final Logger log = LoggerFactory.getLogger(CancerStudyPermissionEvaluator.class); + + private final String APP_NAME; + private String DEFAULT_APP_NAME = "public_portal"; + + private final String FILTER_GROUPS_BY_APP_NAME; + + private final String PUBLIC_CANCER_STUDIES_GROUP; + + // @Value("${always_show_study_group:}") + // private void setPublicCancerStudiesGroup(String property) { + // PUBLIC_CANCER_STUDIES_GROUP = property; + // if (log.isDebugEnabled()) { + // log.debug("setPublicCancerStudiesGroup(), always_show_study_group = " + ((property + // == null) ? "null" : property)); + // } + // if (property != null && property.trim().isEmpty()) { + // PUBLIC_CANCER_STUDIES_GROUP = null; + // } + // } + + public CancerStudyPermissionEvaluator( + final String appName, + final String doFilterGroupsByAppName, + final String alwaysShowCancerStudyGroup, + final CacheMapUtil cacheMapUtil) { + this.APP_NAME = appName; + this.FILTER_GROUPS_BY_APP_NAME = doFilterGroupsByAppName; + this.PUBLIC_CANCER_STUDIES_GROUP = alwaysShowCancerStudyGroup; + this.cacheMapUtil = cacheMapUtil; + } + + /** + * Implementation of {@code PermissionEvaluator}. this method handles the direct evaluation of + * user access to individual instances from the data model. + * + * @param authentication + * @param targetDomainObject CancerStudy, MolecularProfile, SampleList, or Patient + * @param permission + */ + @Override + public boolean hasPermission( + Authentication authentication, Object targetDomainObject, Object permission) { + if (log.isDebugEnabled()) { + log.debug("hasPermission(), checking permissions on targetDomainObject"); + } + if (targetDomainObject == null) { + if (log.isDebugEnabled()) { + log.debug("hasPermission(), targetDomainObject is null, returning false"); + } + return false; + } + CancerStudy cancerStudy = getRelevantCancerStudyFromTarget(targetDomainObject); + if (log.isDebugEnabled()) { + if (cancerStudy == null) { + log.debug("hasPermission(), stable cancer study is null."); + } + if (authentication == null) { + log.debug("hasPermission(), authentication is null."); + } + } + // nothing to do if stable cancer study is null or authentication is null + // return false as spring-security document specifies + if (cancerStudy == null || authentication == null) { + return false; + } + + // Actually, it's not entirely clear why we do this null test, since the + // authentication will always have authorities. + Object user = authentication.getPrincipal(); + if (user != null) { + return hasAccessToCancerStudy(authentication, cancerStudy, (AccessLevel) permission); + } else { + return false; + } + } + + /** + * Implementation of {@code PermissionEvaluator}. + * + * @param authentication + * @param targetId Serialized String cancer study id, String molecular profile id, String genetic + * profile id, String sample list id, Collection of cancer study ids, + * Collection of molecular profile ids, Collection of genetic profile ids, or + * Collection of sample list ids + * @param targetType String 'CancerStudyId', 'MolecularProfileId', 'GeneticProfileId', + * 'SampleListId', 'Collection', 'Collection', + * 'Collection', or 'Collection' + * @param permission + */ + @Override + public boolean hasPermission( + Authentication authentication, Serializable targetId, String targetType, Object permission) { + if (log.isDebugEnabled()) { + log.debug("hasPermission(), checking permissions on targetId"); + } + if (targetId == null) { + if (log.isDebugEnabled()) { + log.debug("hasPermission(), targetId is null, returning false"); + } + return false; + } + if (TARGET_TYPE_CANCER_STUDY_ID.equals(targetType)) { + return hasAccessToCancerStudy(authentication, (String) targetId, permission); + } else if (TARGET_TYPE_MOLECULAR_PROFILE_ID.equals(targetType) + || TARGET_TYPE_GENETIC_PROFILE_ID.equals(targetType)) { + return hasAccessToMolecularProfile(authentication, (String) targetId, permission); + } else if (TARGET_TYPE_SAMPLE_LIST_ID.equals(targetType)) { + return hasAccessToSampleList(authentication, (String) targetId, permission); + } else if (TARGET_TYPE_COLLECTION_OF_CANCER_STUDY_IDS.equals(targetType)) { + return hasAccessToCancerStudies(authentication, (Collection) targetId, permission); + } else if (TARGET_TYPE_COLLECTION_OF_MOLECULAR_PROFILE_IDS.equals(targetType) + || TARGET_TYPE_COLLECTION_OF_GENETIC_PROFILE_IDS.equals(targetType)) { + return hasAccessToMolecularProfiles( + authentication, (Collection) targetId, permission); + } else if (TARGET_TYPE_COLLECTION_OF_SAMPLE_LIST_IDS.equals(targetType)) { + return hasAccessToSampleLists(authentication, (Collection) targetId, permission); + } else if (targetType.contains("Filter")) { + switch (targetId) { + case SampleFilter sampleFilter -> { + return hasAccessToCancerStudies( + authentication, + CancerStudyExtractorUtil.extractCancerStudyIdsFromSampleFilter( + sampleFilter, this.cacheMapUtil), + permission); + } + case StudyViewFilter studyViewFilter -> { + return hasAccessToCancerStudies( + authentication, studyViewFilter.getUniqueStudyIds(), permission); + } + case ClinicalDataCountFilter clinicalDataCountFilter -> { + Set studyIds = new HashSet<>(); + if (clinicalDataCountFilter.getStudyViewFilter() != null) { + studyIds = clinicalDataCountFilter.getStudyViewFilter().getUniqueStudyIds(); + } + return hasAccessToCancerStudies(authentication, studyIds, permission); + } + case DataBinCountFilter dataBinCountFilter -> { + Set studyIds = new HashSet<>(); + if (dataBinCountFilter.getStudyViewFilter() != null) { + studyIds = dataBinCountFilter.getStudyViewFilter().getUniqueStudyIds(); + } + return hasAccessToCancerStudies(authentication, studyIds, permission); + } + case GenomicDataCountFilter genomicDataCountFilter -> { + Set studyIds = new HashSet<>(); + if (genomicDataCountFilter.getStudyViewFilter() != null) { + studyIds = genomicDataCountFilter.getStudyViewFilter().getUniqueStudyIds(); + } + return hasAccessToCancerStudies(authentication, studyIds, permission); + } + case GenericAssayDataCountFilter genericAssayDataCountFilter -> { + Set studyIds = new HashSet<>(); + if (genericAssayDataCountFilter.getStudyViewFilter() != null) { + studyIds = genericAssayDataCountFilter.getStudyViewFilter().getUniqueStudyIds(); + } + return hasAccessToCancerStudies(authentication, studyIds, permission); + } + + case MolecularProfileCasesGroupAndAlterationTypeFilter + molecularProfileCasesGroupAndAlterationTypeFilter -> { + Set molecularProfileIds = + molecularProfileCasesGroupAndAlterationTypeFilter + .getMolecularProfileCasesGroupFilter() + .stream() + .flatMap(group -> group.getMolecularProfileCaseIdentifiers().stream()) + .map(MolecularProfileCaseIdentifier::getMolecularProfileId) + .collect(Collectors.toSet()); + return hasAccessToMolecularProfiles(authentication, molecularProfileIds, permission); + } + + default -> log.debug("hasPermission(), unknown targetType '" + targetType + "'"); + } + } else { + if (log.isDebugEnabled()) { + log.debug("hasPermission(), unknown targetType '" + targetType + "'"); + } + } + return false; + } + + private CancerStudy getRelevantCancerStudyFromTarget(Object targetDomainObject) { + if (targetDomainObject instanceof CancerStudy) { + return (CancerStudy) targetDomainObject; + } else if (targetDomainObject instanceof MolecularProfile) { + MolecularProfile molecularProfile = (MolecularProfile) targetDomainObject; + if (molecularProfile.getCancerStudy() != null) { + return molecularProfile.getCancerStudy(); + } + // cancer study was not included so get it from cache + return cacheMapUtil.getCancerStudyMap().get(molecularProfile.getCancerStudyIdentifier()); + } else if (targetDomainObject instanceof SampleList) { + SampleList sampleList = (SampleList) targetDomainObject; + if (sampleList.getCancerStudy() != null) { + return sampleList.getCancerStudy(); + } + // cancer study was not included so get it from cache + return cacheMapUtil.getCancerStudyMap().get(sampleList.getCancerStudyIdentifier()); + } else if (targetDomainObject instanceof Patient) { + Patient patient = (Patient) targetDomainObject; + if (patient.getCancerStudy() != null) { + return patient.getCancerStudy(); + } + // cancer study was not included so get it from cache + return cacheMapUtil.getCancerStudyMap().get(patient.getCancerStudyIdentifier()); + } + // unable to handle targetDomainObject type + if (log.isDebugEnabled()) { + log.debug( + "hasPermission(), targetDomainObject class is '" + + targetDomainObject.getClass().getName() + + "'"); + } + return null; + } + + /** + * Helper function to determine if given user has access to given cancer study. + * + * @param cancerStudy cancer study to check for + * @param authentication Spring Authentication of the logged-in user. + * @return boolean + */ + private boolean hasAccessToCancerStudy( + Authentication authentication, CancerStudy cancerStudy, AccessLevel permission) { + + // The 'list' permission is only requested by the /api/studies endpoint of StudyController. This + // permission is + // requested by the Study Overview page when the portal instance is configured to show all + // studies (with non- + // authorized study options greyed out), instead of only showing authorized studies. + // When the 'list' permission is requested, CancerPermissionEvaluator returns true always. + if (AccessLevel.LIST == permission) { + return true; + } + + Set grantedAuthorities = getGrantedAuthorities(authentication); + String stableStudyID = cancerStudy.getCancerStudyIdentifier(); + if (log.isDebugEnabled()) { + log.debug("hasAccessToCancerStudy(), cancer study stable id: " + stableStudyID); + log.debug("hasAccessToCancerStudy(), user: " + authentication.getPrincipal().toString()); + for (String authority : grantedAuthorities) { + log.debug("hasAccessToCancerStudy(), authority: " + authority); + } + } + // everybody has access the 'all' cancer study + if (stableStudyID.equalsIgnoreCase(ALL_CANCER_STUDIES_ID)) { + return true; + } + // if a user has access to 'all', simply return true + if (grantedAuthorities.contains(ALL_CANCER_STUDIES_ID.toUpperCase())) { + if (log.isDebugEnabled()) { + log.debug("hasAccessToCancerStudy(), user has access to ALL cancer studies, return true"); + } + return true; + } + // if a user has access to 'all_tcga', simply return true for tcga studies + if (grantedAuthorities.contains(ALL_TCGA_CANCER_STUDIES_ID.toUpperCase()) + && stableStudyID.toUpperCase().endsWith("_TCGA")) { + if (log.isDebugEnabled()) { + log.debug( + "hasAccessToCancerStudy(), user has access to ALL_TCGA cancer studies return true"); + } + return true; + } + // if a user has access to 'all_target', simply return true for target studies + if (grantedAuthorities.contains(ALL_TARGET_CANCER_STUDIES_ID.toUpperCase()) + && (stableStudyID.toUpperCase().endsWith("_TARGET") + || stableStudyID.equalsIgnoreCase("ALL_TARGET_PHASE1") + || stableStudyID.equalsIgnoreCase("ALL_TARGET_PHASE2"))) { + if (log.isDebugEnabled()) { + log.debug( + "hasAccessToCancerStudy(), user has access to ALL_NCI_TARGET cancer studies return true"); + } + return true; + } + // check if user is in study groups + // performance now takes precedence over group accuracy (minimal risk to caching cancer study + // groups) + // need to filter out empty groups, this can cause issue if grantedAuthorities and groups both + // contain empty string + Set groups = + Arrays.stream(cancerStudy.getGroups().split(";")) + .filter(g -> !g.isEmpty()) + .collect(Collectors.toSet()); + if (!Collections.disjoint(groups, grantedAuthorities)) { + if (log.isDebugEnabled()) { + log.debug("hasAccessToCancerStudy(), user has access by groups return true"); + } + return true; + } + // finally, check if the user has this study specifically listed in his 'groups' (a 'group' of + // this study only) + boolean toReturn = grantedAuthorities.contains(stableStudyID.toUpperCase()); + if (log.isDebugEnabled()) { + if (toReturn == true) { + log.debug( + "hasAccessToCancerStudy(), user has access to this cancer study: '" + + stableStudyID.toUpperCase() + + "', returning true."); + } else { + log.debug( + "hasAccessToCancerStudy(), user does not have access to the cancer study: '" + + stableStudyID.toUpperCase() + + "', returning false."); + } + } + return toReturn; + } + + private boolean hasAccessToCancerStudy( + Authentication authentication, String cancerStudyId, Object permission) { + // everybody has access the 'all' cancer study + // we have to check this right here (instead of checking later) + // because the 'all' cancer study does not exist in the database + if (cancerStudyId.equalsIgnoreCase(ALL_CANCER_STUDIES_ID)) { + return true; + } + CancerStudy cancerStudy = cacheMapUtil.getCancerStudyMap().get(cancerStudyId); + if (cancerStudy == null) { + return false; + } + return hasPermission(authentication, cancerStudy, permission); + } + + private boolean hasAccessToMolecularProfile( + Authentication authentication, String molecularProfileId, Object permission) { + MolecularProfile molecularProfile = + cacheMapUtil.getMolecularProfileMap().get(molecularProfileId); + if (molecularProfile == null) { + return false; + } + return hasPermission(authentication, molecularProfile, permission); + } + + private boolean hasAccessToSampleList( + Authentication authentication, String sampleListId, Object permission) { + SampleList sampleList = cacheMapUtil.getSampleListMap().get(sampleListId); + if (sampleList == null) { + return false; + } + return hasPermission(authentication, sampleList, permission); + } + + private boolean hasAccessToCancerStudies( + Authentication authentication, Collection cancerStudyIds, Object permission) { + for (String cancerStudyId : cancerStudyIds) { + if (!hasPermission(authentication, cancerStudyId, TARGET_TYPE_CANCER_STUDY_ID, permission)) { + return false; + } + } + return true; + } + + private boolean hasAccessToMolecularProfiles( + Authentication authentication, Collection molecularProfileIds, Object permission) { + for (String molecularProfileId : molecularProfileIds) { + MolecularProfile molecularProfile = + cacheMapUtil.getMolecularProfileMap().get(molecularProfileId); + if (molecularProfile == null + || !hasPermission(authentication, molecularProfile, permission)) { + return false; + } + } + return true; + } + + private boolean hasAccessToSampleLists( + Authentication authentication, Collection sampleListIds, Object permission) { + for (String sampleListId : sampleListIds) { + SampleList sampleList = cacheMapUtil.getSampleListMap().get(sampleListId); + if (sampleList == null || !hasPermission(authentication, sampleList, permission)) { + return false; + } + } + return true; + } + + private Set getGrantedAuthorities(Authentication authentication) { + String appName = getAppName().toUpperCase(); + // need to filter out empty authorities, this can cause issue if grantedAuthorities and groups + // both contain empty string + Set allAuthorities = + AuthorityUtils.authorityListToSet(authentication.getAuthorities()).stream() + .map(authority -> authority.replaceAll("^ROLE_", "")) + .filter(a -> !a.isEmpty()) + .collect(Collectors.toSet()); + Set grantedAuthorities = new HashSet<>(); + if (filterGroupsByAppName()) { + for (String au : allAuthorities) { + if (au.toUpperCase().startsWith(appName + ":")) { + grantedAuthorities.add(au.substring(appName.length() + 1).toUpperCase()); + } + } + } else { + for (String au : allAuthorities) { + grantedAuthorities.add(au.toUpperCase()); + } + } + // all users are allowed access to PUBLIC studies + if (log.isDebugEnabled()) { + log.debug( + "PUBLIC_CANCER_STUDIES_GROUP= " + + ((PUBLIC_CANCER_STUDIES_GROUP == null) ? "null" : PUBLIC_CANCER_STUDIES_GROUP)); + } + if (PUBLIC_CANCER_STUDIES_GROUP != null) { + grantedAuthorities.add(PUBLIC_CANCER_STUDIES_GROUP.toUpperCase()); + } + return grantedAuthorities; + } + + private String getAppName() { + if (log.isDebugEnabled()) { + log.debug("getAppName(), APP_NAME = " + ((APP_NAME == null) ? "null" : APP_NAME)); + } + return (APP_NAME == null || APP_NAME.trim().isEmpty()) ? DEFAULT_APP_NAME : APP_NAME; + } + + private boolean filterGroupsByAppName() { + if (log.isDebugEnabled()) { + log.debug( + "filterGroupsByAppName(), FILTER_GROUPS_BY_APP_NAME = " + + ((FILTER_GROUPS_BY_APP_NAME == null) ? "null" : FILTER_GROUPS_BY_APP_NAME)); + } + return FILTER_GROUPS_BY_APP_NAME == null || Boolean.parseBoolean(FILTER_GROUPS_BY_APP_NAME); + } +} diff --git a/src/main/java/org/cbioportal/application/security/basic/BasicRestfulAuthenticationSuccessHandler.java b/src/main/java/org/cbioportal/application/security/basic/BasicRestfulAuthenticationSuccessHandler.java new file mode 100644 index 00000000000..7a8ccc09bbb --- /dev/null +++ b/src/main/java/org/cbioportal/application/security/basic/BasicRestfulAuthenticationSuccessHandler.java @@ -0,0 +1,37 @@ +package org.cbioportal.application.security.basic; + +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.servlet.http.HttpSession; +import java.io.IOException; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContext; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.core.context.SecurityContextHolderStrategy; +import org.springframework.security.web.DefaultRedirectStrategy; +import org.springframework.security.web.RedirectStrategy; +import org.springframework.security.web.authentication.AuthenticationSuccessHandler; +import org.springframework.security.web.context.HttpSessionSecurityContextRepository; +import org.springframework.security.web.context.SecurityContextRepository; + +public class BasicRestfulAuthenticationSuccessHandler implements AuthenticationSuccessHandler { + + private final SecurityContextHolderStrategy securityContextHolderStrategy = + SecurityContextHolder.getContextHolderStrategy(); + private final SecurityContextRepository securityContextRepository = + new HttpSessionSecurityContextRepository(); + private final RedirectStrategy redirectStrategy = new DefaultRedirectStrategy(); + + @Override + public void onAuthenticationSuccess( + HttpServletRequest request, HttpServletResponse response, Authentication authentication) + throws IOException { + HttpSession session = request.getSession(true); + session.setAttribute("user_id", request.getParameter("user_id")); + SecurityContext context = this.securityContextHolderStrategy.createEmptyContext(); + context.setAuthentication(authentication); + this.securityContextHolderStrategy.setContext(context); + this.securityContextRepository.saveContext(context, request, response); + redirectStrategy.sendRedirect(request, response, "/restful_login"); + } +} diff --git a/src/main/java/org/cbioportal/application/security/config/ApiSecurityConfig.java b/src/main/java/org/cbioportal/application/security/config/ApiSecurityConfig.java new file mode 100644 index 00000000000..60f96a5a242 --- /dev/null +++ b/src/main/java/org/cbioportal/application/security/config/ApiSecurityConfig.java @@ -0,0 +1,111 @@ +package org.cbioportal.application.security.config; + +import org.cbioportal.application.security.token.RestAuthenticationEntryPoint; +import org.cbioportal.application.security.token.TokenAuthenticationFilter; +import org.cbioportal.application.security.token.TokenAuthenticationSuccessHandler; +import org.cbioportal.legacy.service.DataAccessTokenService; +import org.cbioportal.legacy.utils.config.annotation.ConditionalOnProperty; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.Ordered; +import org.springframework.core.annotation.Order; +import org.springframework.http.HttpStatus; +import org.springframework.lang.Nullable; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.authentication.AuthenticationProvider; +import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer; +import org.springframework.security.web.SecurityFilterChain; +import org.springframework.security.web.authentication.HttpStatusEntryPoint; +import org.springframework.security.web.context.SecurityContextHolderFilter; +import org.springframework.security.web.util.matcher.AntPathRequestMatcher; + +@Configuration +@ConditionalOnProperty( + name = "authenticate", + havingValue = {"false", "optional_oauth2"}, + isNot = true) +public class ApiSecurityConfig { + + // Add security filter chains that handle calls to the API endpoints. + // Different chains are added for the '/api' and legacy '/webservice.do' paths. + // Both are able to handle API tokens provided in the request. + // see: "Creating and Customizing Filter Chains" @ + // https://spring.io/guides/topicals/spring-security-architecture + + @Bean + @Order(Ordered.HIGHEST_PRECEDENCE) + public SecurityFilterChain securityFilterChain( + HttpSecurity http, @Nullable DataAccessTokenService tokenService) throws Exception { + http.csrf(AbstractHttpConfigurer::disable) + // This filter chain only grabs requests to the '/api' path. + .securityMatcher("/api/**", "/webservice.do") + .authorizeHttpRequests( + authorize -> + authorize + .requestMatchers( + "/api/swagger-resources/**", + "/api/swagger-ui.html", + "/api/health", + "/api/public_virtual_studies/**", + "/api/cache/**") + .permitAll() + .anyRequest() + .authenticated()) + .sessionManagement( + sessionManagement -> sessionManagement.sessionFixation().migrateSession()) + .exceptionHandling( + eh -> + eh.defaultAuthenticationEntryPointFor( + new HttpStatusEntryPoint(HttpStatus.UNAUTHORIZED), + AntPathRequestMatcher.antMatcher("/api/**"))); + // When dat.method is not 'none' and a tokenService bean is present, + // the apiTokenAuthenticationFilter is added to the filter chain. + if (tokenService != null) { + http.apply(ApiTokenFilterDsl.tokenFilterDsl(tokenService)); + } + return http.build(); + } + + @Autowired + public void buildAuthenticationManager( + AuthenticationManagerBuilder authenticationManagerBuilder, + @Nullable AuthenticationProvider... authenticationProviders) { + if (authenticationProviders != null) { + for (AuthenticationProvider authenticationProvider : authenticationProviders) { + authenticationManagerBuilder.authenticationProvider(authenticationProvider); + } + } + } + + @Bean + public RestAuthenticationEntryPoint restAuthenticationEntryPoint() { + return new RestAuthenticationEntryPoint(); + } +} + +class ApiTokenFilterDsl extends AbstractHttpConfigurer { + + private final DataAccessTokenService tokenService; + + public ApiTokenFilterDsl(DataAccessTokenService tokenService) { + this.tokenService = tokenService; + } + + @Override + public void configure(HttpSecurity http) { + AuthenticationManager authenticationManager = http.getSharedObject(AuthenticationManager.class); + TokenAuthenticationSuccessHandler tokenAuthenticationSuccessHandler = + new TokenAuthenticationSuccessHandler(); + TokenAuthenticationFilter filter = + new TokenAuthenticationFilter("/**", authenticationManager, tokenService); + filter.setAuthenticationSuccessHandler(tokenAuthenticationSuccessHandler); + http.addFilterAfter(filter, SecurityContextHolderFilter.class); + } + + public static ApiTokenFilterDsl tokenFilterDsl(DataAccessTokenService tokenService) { + return new ApiTokenFilterDsl(tokenService); + } +} diff --git a/src/main/java/org/cbioportal/application/security/config/AutoconfigureExcludeConfig.java b/src/main/java/org/cbioportal/application/security/config/AutoconfigureExcludeConfig.java new file mode 100644 index 00000000000..fd405b6f0bc --- /dev/null +++ b/src/main/java/org/cbioportal/application/security/config/AutoconfigureExcludeConfig.java @@ -0,0 +1,40 @@ +package org.cbioportal.application.security.config; + +import org.cbioportal.legacy.utils.config.annotation.ConditionalOnProperty; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; +import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration; +import org.springframework.boot.autoconfigure.security.oauth2.client.servlet.OAuth2ClientAutoConfiguration; +import org.springframework.boot.autoconfigure.security.saml2.Saml2RelyingPartyAutoConfiguration; +import org.springframework.context.annotation.Configuration; + +// Conditionally disable autoconfguration for Spring Boot components. +public class AutoconfigureExcludeConfig { + + private AutoconfigureExcludeConfig() {} + + @Configuration + @ConditionalOnProperty( + name = "authenticate", + havingValue = {"saml", "oauth2", "optional_oauth2", "saml_plus_basic"}, + isNot = true) + @EnableAutoConfiguration( + exclude = {OAuth2ClientAutoConfiguration.class, Saml2RelyingPartyAutoConfiguration.class}) + public static class ExcludeAll {} + + @Configuration + @ConditionalOnExpression("{'saml','saml_plus_basic'}.contains('${authenticate}')") + @EnableAutoConfiguration(exclude = OAuth2ClientAutoConfiguration.class) + public static class Saml {} + + @Configuration + @ConditionalOnProperty(name = "authenticate", havingValue = "oauth2") + @EnableAutoConfiguration(exclude = Saml2RelyingPartyAutoConfiguration.class) + public static class OAuth2 {} + + @Configuration + @ConditionalOnExpression( + "T(org.apache.commons.lang3.StringUtils).isEmpty('${spring.session.store-type:}')") + @EnableAutoConfiguration(exclude = RedisAutoConfiguration.class) + public static class Redis {} +} diff --git a/src/main/java/org/cbioportal/application/security/config/CorsConfig.java b/src/main/java/org/cbioportal/application/security/config/CorsConfig.java new file mode 100644 index 00000000000..8c6dfb84fdf --- /dev/null +++ b/src/main/java/org/cbioportal/application/security/config/CorsConfig.java @@ -0,0 +1,45 @@ +package org.cbioportal.application.security.config; + +import java.util.List; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.web.cors.CorsConfiguration; +import org.springframework.web.cors.CorsConfigurationSource; +import org.springframework.web.cors.UrlBasedCorsConfigurationSource; + +@Configuration +@EnableWebSecurity +public class CorsConfig { + @Value("${security.cors.allowed-origins:}") + private String allowedOrigins; + + @Bean + CorsConfigurationSource corsConfigurationSource() { + List parsedAllowedOrigins = List.of(allowedOrigins.split(",")); + UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); + if (parsedAllowedOrigins.isEmpty()) { + return source; + } + + CorsConfiguration configuration = new CorsConfiguration(); + configuration.setAllowedOrigins(parsedAllowedOrigins); + configuration.setAllowedMethods(List.of("GET", "POST", "HEAD", "OPTIONS")); + configuration.setAllowedHeaders( + List.of( + "user-agent", + "Origin", + "Accept", + "X-Requested-With", + "Content-Type", + "Access-Control-Request-Method", + "Access-Control-Request-Headers", + "Content-Encoding", + "X-Proxy-User-Agreement", + "x-current-url")); + configuration.setExposedHeaders(List.of("total-count", "sample-count", "elapsed-time")); + source.registerCorsConfiguration("/**", configuration); + return source; + } +} diff --git a/src/main/java/org/cbioportal/application/security/config/CustomOAuth2AuthorizationConfig.java b/src/main/java/org/cbioportal/application/security/config/CustomOAuth2AuthorizationConfig.java new file mode 100644 index 00000000000..a2bd01eee8c --- /dev/null +++ b/src/main/java/org/cbioportal/application/security/config/CustomOAuth2AuthorizationConfig.java @@ -0,0 +1,77 @@ +package org.cbioportal.application.security.config; + +import java.util.HashSet; +import java.util.Objects; +import java.util.Set; +import org.cbioportal.legacy.model.User; +import org.cbioportal.legacy.model.UserAuthorities; +import org.cbioportal.legacy.persistence.SecurityRepository; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.authority.AuthorityUtils; +import org.springframework.security.oauth2.client.oidc.userinfo.OidcUserRequest; +import org.springframework.security.oauth2.client.oidc.userinfo.OidcUserService; +import org.springframework.security.oauth2.client.userinfo.OAuth2UserService; +import org.springframework.security.oauth2.core.OAuth2AuthenticationException; +import org.springframework.security.oauth2.core.oidc.user.DefaultOidcUser; +import org.springframework.security.oauth2.core.oidc.user.OidcUser; + +@Configuration +@EnableWebSecurity +@ConditionalOnProperty(value = "authorization", havingValue = "true") +public class CustomOAuth2AuthorizationConfig { + Logger log = LoggerFactory.getLogger(CustomOAuth2AuthorizationConfig.class); + + private final SecurityRepository securityRepository; + + private static final String NAME_ATTRIBUTE_KEY = "email"; + + @Autowired + public CustomOAuth2AuthorizationConfig(SecurityRepository securityRepository) { + this.securityRepository = securityRepository; + } + + @Bean + public OAuth2UserService oidcUserService() { + final OidcUserService delegate = new OidcUserService(); + + return userRequest -> { + log.debug("Custom OAuth2 Authorization Enabled"); + + // Delegate to the default implementation for loading a user + OidcUser oidcUser = delegate.loadUser(userRequest); + + var authenticatedPortalUser = loadPortalUser(oidcUser.getEmail()); + if (Objects.isNull(authenticatedPortalUser.cbioUser) + || !authenticatedPortalUser.cbioUser.isEnabled()) { + log.debug("User: {} either not in db or not authorized", oidcUser.getEmail()); + throw new OAuth2AuthenticationException("user not authorized"); + } + Set mappedAuthorities = authenticatedPortalUser.authorities; + oidcUser = + new DefaultOidcUser( + mappedAuthorities, oidcUser.getIdToken(), oidcUser.getUserInfo(), NAME_ATTRIBUTE_KEY); + return oidcUser; + }; + } + + private AuthenticatedPortalUser loadPortalUser(String email) { + Set mappedAuthorities = new HashSet<>(); + User cbioUser = securityRepository.getPortalUser(email); + if (!Objects.isNull(cbioUser)) { + UserAuthorities authorities = securityRepository.getPortalUserAuthorities(email); + if (!Objects.isNull(authorities)) { + mappedAuthorities.addAll(AuthorityUtils.createAuthorityList(authorities.getAuthorities())); + } + } + return new AuthenticatedPortalUser(cbioUser, mappedAuthorities); + } + + record AuthenticatedPortalUser(User cbioUser, Set authorities) {} +} diff --git a/src/main/java/org/cbioportal/application/security/config/MethodSecurityConfig.java b/src/main/java/org/cbioportal/application/security/config/MethodSecurityConfig.java new file mode 100644 index 00000000000..a58c96e32de --- /dev/null +++ b/src/main/java/org/cbioportal/application/security/config/MethodSecurityConfig.java @@ -0,0 +1,38 @@ +package org.cbioportal.application.security.config; + +import org.cbioportal.application.security.CancerStudyPermissionEvaluator; +import org.cbioportal.legacy.persistence.cachemaputil.CacheMapUtil; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler; +import org.springframework.security.access.expression.method.MethodSecurityExpressionHandler; +import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity; + +@Configuration +@EnableMethodSecurity(prePostEnabled = true) +// We are allowing users to enable method_authorization if optional_oauth2 is selected +@ConditionalOnExpression( + "{'oauth2','saml', 'saml_plus_basic'}.contains('${authenticate}') or ('optional_oauth2' eq '${authenticate}' and 'true' eq '${security.method_authorization_enabled}')") +public class MethodSecurityConfig { + + @Bean + public CancerStudyPermissionEvaluator cancerStudyPermissionEvaluator( + @Value("${app.name:}") String appName, + @Value("${filter_groups_by_appname:true}") String doFilterGroupsByAppName, + @Value("${always_show_study_group:}") String alwaysShowCancerStudyGroup, + CacheMapUtil cacheMapUtil) { + return new CancerStudyPermissionEvaluator( + appName, doFilterGroupsByAppName, alwaysShowCancerStudyGroup, cacheMapUtil); + } + + @Bean + public MethodSecurityExpressionHandler createExpressionHandler( + CancerStudyPermissionEvaluator cancerStudyPermissionEvaluator) { + DefaultMethodSecurityExpressionHandler expressionHandler = + new DefaultMethodSecurityExpressionHandler(); + expressionHandler.setPermissionEvaluator(cancerStudyPermissionEvaluator); + return expressionHandler; + } +} diff --git a/src/main/java/org/cbioportal/application/security/config/NoSecurityConfig.java b/src/main/java/org/cbioportal/application/security/config/NoSecurityConfig.java new file mode 100644 index 00000000000..61f39255469 --- /dev/null +++ b/src/main/java/org/cbioportal/application/security/config/NoSecurityConfig.java @@ -0,0 +1,24 @@ +package org.cbioportal.application.security.config; + +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.config.Customizer; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer; +import org.springframework.security.web.SecurityFilterChain; + +@Configuration +@EnableWebSecurity +@ConditionalOnProperty(value = "authenticate", havingValue = "false", matchIfMissing = true) +public class NoSecurityConfig { + @Bean + public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { + return http.cors(Customizer.withDefaults()) + .csrf(AbstractHttpConfigurer::disable) + .authorizeHttpRequests( + auth -> auth.requestMatchers("/").permitAll().anyRequest().permitAll()) + .build(); + } +} diff --git a/src/main/java/org/cbioportal/application/security/config/OAuth2SecurityConfig.java b/src/main/java/org/cbioportal/application/security/config/OAuth2SecurityConfig.java new file mode 100644 index 00000000000..9bac3ec7dda --- /dev/null +++ b/src/main/java/org/cbioportal/application/security/config/OAuth2SecurityConfig.java @@ -0,0 +1,120 @@ +package org.cbioportal.application.security.config; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Set; +import java.util.stream.Collectors; +import org.cbioportal.application.security.util.ClaimRoleExtractorUtil; +import org.cbioportal.application.security.util.GrantedAuthorityUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.boot.autoconfigure.security.SecurityProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.annotation.Order; +import org.springframework.security.config.Customizer; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.core.authority.mapping.GrantedAuthoritiesMapper; +import org.springframework.security.oauth2.client.oidc.web.logout.OidcClientInitiatedLogoutSuccessHandler; +import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository; +import org.springframework.security.oauth2.core.oidc.user.OidcUserAuthority; +import org.springframework.security.oauth2.core.user.OAuth2UserAuthority; +import org.springframework.security.web.SecurityFilterChain; +import org.springframework.security.web.authentication.logout.LogoutSuccessHandler; + +@Configuration +// add new chain after api-filter chain (at position -2), but before the default fallback chain +@Order(SecurityProperties.BASIC_AUTH_ORDER - 1) +@ConditionalOnProperty(value = "authenticate", havingValue = "oauth2") +public class OAuth2SecurityConfig { + + private static final Logger log = LoggerFactory.getLogger(OAuth2SecurityConfig.class); + + @Value("${spring.security.oauth2.client.jwt-roles-path:resource_access::cbioportal::roles}") + private String jwtRolesPath; + + private static final String LOGIN_URL = "/login"; + + @Bean + @Order(1) + public SecurityFilterChain filterChain( + HttpSecurity http, ClientRegistrationRepository clientRegistrationRepository) + throws Exception { + http.csrf(AbstractHttpConfigurer::disable) + .cors(Customizer.withDefaults()) + .authorizeHttpRequests( + authorize -> + authorize + .requestMatchers("/api/health", LOGIN_URL, "/images/**") + .permitAll() + .anyRequest() + .authenticated()) + .oauth2Login( + login -> + login + .loginPage(LOGIN_URL) + .userInfoEndpoint( + userInfo -> userInfo.userAuthoritiesMapper(userAuthoritiesMapper())) + .failureUrl(LOGIN_URL + "?logout_failure")) + .logout( + logout -> + logout.logoutSuccessHandler( + oidcLogoutSuccessHandler(clientRegistrationRepository))); + return http.build(); + } + + private GrantedAuthoritiesMapper userAuthoritiesMapper() { + return (authorities) -> { + Set mappedAuthorities = new HashSet<>(); + + authorities.forEach( + authority -> { + List> claims = new ArrayList<>(); + switch (authority) { + case OidcUserAuthority oidcUserAuthority -> { + if (!Objects.isNull(oidcUserAuthority.getUserInfo())) { + claims.add(oidcUserAuthority.getUserInfo().getClaims()); + } + claims.add(oidcUserAuthority.getIdToken().getClaims()); + } + case OAuth2UserAuthority oAuth2UserAuthority -> + claims.add(oAuth2UserAuthority.getAttributes()); + case SimpleGrantedAuthority simpleGrantedAuthority -> + mappedAuthorities.add(simpleGrantedAuthority); + default -> log.debug("Unsupported UserAuthority Type {}", authority); + } + if (!claims.isEmpty()) { + var roles = + claims.stream() + .filter(claim -> !Objects.isNull(claim)) + .map(claim -> ClaimRoleExtractorUtil.extractClientRoles(claim, jwtRolesPath)) + .flatMap(Collection::stream) + .collect(Collectors.toSet()); + + mappedAuthorities.addAll( + GrantedAuthorityUtil.generateGrantedAuthoritiesFromRoles(roles)); + } + }); + return mappedAuthorities; + }; + } + + // See: + // https://docs.spring.io/spring-security/reference/5.7-SNAPSHOT/servlet/oauth2/login/advanced.html#oauth2login-advanced-oidc-logout + private LogoutSuccessHandler oidcLogoutSuccessHandler( + ClientRegistrationRepository clientRegistrationRepository) { + OidcClientInitiatedLogoutSuccessHandler oidcLogoutSuccessHandler = + new OidcClientInitiatedLogoutSuccessHandler(clientRegistrationRepository); + oidcLogoutSuccessHandler.setPostLogoutRedirectUri("{baseUrl}"); + return oidcLogoutSuccessHandler; + } +} diff --git a/src/main/java/org/cbioportal/application/security/config/OptionalOAuth2SecurityConfig.java b/src/main/java/org/cbioportal/application/security/config/OptionalOAuth2SecurityConfig.java new file mode 100644 index 00000000000..76c3ed62f15 --- /dev/null +++ b/src/main/java/org/cbioportal/application/security/config/OptionalOAuth2SecurityConfig.java @@ -0,0 +1,31 @@ +package org.cbioportal.application.security.config; + +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.boot.autoconfigure.security.SecurityProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.annotation.Order; +import org.springframework.security.config.Customizer; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer; +import org.springframework.security.web.SecurityFilterChain; + +@Configuration +@EnableWebSecurity +// add new chain after api-filter chain (at position -2), but before the default fallback chain +@Order(SecurityProperties.BASIC_AUTH_ORDER - 1) +@ConditionalOnProperty(value = "authenticate", havingValue = "optional_oauth2") +public class OptionalOAuth2SecurityConfig { + + @Bean + public SecurityFilterChain optionalOAuth2filterChain(HttpSecurity http) throws Exception { + return http.oauth2Login(oauth -> oauth.loginPage("/login")) + .authorizeHttpRequests( + auth -> auth.requestMatchers("/").permitAll().anyRequest().permitAll()) + .cors(Customizer.withDefaults()) + .csrf(AbstractHttpConfigurer::disable) + .logout(logout -> logout.logoutSuccessUrl("/")) + .build(); + } +} diff --git a/src/main/java/org/cbioportal/application/security/config/Saml2AndBasicConfig.java b/src/main/java/org/cbioportal/application/security/config/Saml2AndBasicConfig.java new file mode 100644 index 00000000000..31abf4d8956 --- /dev/null +++ b/src/main/java/org/cbioportal/application/security/config/Saml2AndBasicConfig.java @@ -0,0 +1,156 @@ +package org.cbioportal.application.security.config; + +import static org.springframework.security.config.Customizer.withDefaults; + +import java.util.Objects; +import org.cbioportal.application.security.basic.BasicRestfulAuthenticationSuccessHandler; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.HttpStatus; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.authentication.dao.DaoAuthenticationProvider; +import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.core.userdetails.User; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.security.provisioning.InMemoryUserDetailsManager; +import org.springframework.security.web.SecurityFilterChain; +import org.springframework.security.web.authentication.HttpStatusEntryPoint; +import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; +import org.springframework.security.web.authentication.logout.LogoutFilter; +import org.springframework.security.web.authentication.logout.LogoutSuccessHandler; +import org.springframework.security.web.authentication.logout.SimpleUrlLogoutSuccessHandler; +import org.springframework.security.web.context.HttpSessionSecurityContextRepository; +import org.springframework.security.web.context.SecurityContextHolderFilter; +import org.springframework.security.web.util.matcher.AntPathRequestMatcher; + +@Configuration +@EnableWebSecurity +@ConditionalOnProperty(value = "authenticate", havingValue = "saml_plus_basic") +public class Saml2AndBasicConfig { + private static final String LOGOUT_URL = "/logout"; + private static final String BASIC_LOGOUT_URL = "/j_spring_security_logout"; + private static final String BASIC_LOGOUT_SUCCESS_URL = "/"; + + @Value("${basic.username:MOCK_USER}") + private String basicUsername; + + @Value("${basic.password:MOCK_PASSWORD}") + private String basicPassword; + + @Value("${basic.authorities:}") + private String basicAuthorities; + + @Bean + public SecurityFilterChain samlFilterChain( + HttpSecurity http, + AuthenticationManagerBuilder authenticationManagerBuilder, + LogoutSuccessHandler logoutSuccessHandler) + throws Exception { + buildAuthenticationManager(authenticationManagerBuilder, userDetailsService()); + http.csrf(AbstractHttpConfigurer::disable) + .cors(withDefaults()) + .authorizeHttpRequests( + auth -> + auth.requestMatchers("/api/health", "/images/**", "/js/**", "/login") + .permitAll() + .anyRequest() + .authenticated()) + .exceptionHandling( + eh -> + eh.defaultAuthenticationEntryPointFor( + new HttpStatusEntryPoint(HttpStatus.UNAUTHORIZED), + AntPathRequestMatcher.antMatcher("/api/**"))) + .securityContext( + securityContext -> + securityContext.securityContextRepository( + new HttpSessionSecurityContextRepository())) + .saml2Login(withDefaults()) + .sessionManagement( + sessionManagement -> sessionManagement.sessionFixation().migrateSession()) + // SAML logout configuration + // NOTE: I did not get the official .saml2Logout() DSL to work as + // described at + // https://docs.spring.io/spring-security/reference/6.1/servlet/saml2/logout.html + // Logout Service POST Binding URL: http://localhost:8080/logout/saml2/slo + .logout( + logout -> + logout + .logoutUrl(LOGOUT_URL) + .clearAuthentication(true) + .invalidateHttpSession(true) + .logoutSuccessHandler(logoutSuccessHandler)); + + // Add basic auth logout filter + SimpleUrlLogoutSuccessHandler basicLogoutSuccessHandler = new SimpleUrlLogoutSuccessHandler(); + basicLogoutSuccessHandler.setDefaultTargetUrl(BASIC_LOGOUT_SUCCESS_URL); + + LogoutFilter basicLogoutFilter = + new LogoutFilter( + basicLogoutSuccessHandler, + (request, response, authentication) -> { + if (authentication != null && authentication.getPrincipal() instanceof UserDetails) { + // Clear the authentication + SecurityContextHolder.clearContext(); + // Invalidate the session + request.getSession(false).invalidate(); + } + }); + basicLogoutFilter.setFilterProcessesUrl(BASIC_LOGOUT_URL); + basicLogoutFilter.setLogoutRequestMatcher(new AntPathRequestMatcher(BASIC_LOGOUT_URL, "GET")); + http.addFilterBefore(basicLogoutFilter, UsernamePasswordAuthenticationFilter.class); + + http.apply(new BasicFilterDsl()); + return http.build(); + } + + private class BasicFilterDsl extends AbstractHttpConfigurer { + @Override + public void configure(HttpSecurity http) { + AuthenticationManager authenticationManager = + http.getSharedObject(AuthenticationManager.class); + UsernamePasswordAuthenticationFilter filter = new UsernamePasswordAuthenticationFilter(); + filter.setPostOnly(false); + filter.setFilterProcessesUrl("/j_spring_security_check"); + filter.setUsernameParameter("j_username"); + filter.setPasswordParameter("j_password"); + filter.setAuthenticationManager(authenticationManager); + filter.setAuthenticationSuccessHandler(new BasicRestfulAuthenticationSuccessHandler()); + http.addFilterAfter(filter, SecurityContextHolderFilter.class); + } + } + + public void buildAuthenticationManager( + AuthenticationManagerBuilder authenticationManagerBuilder, + InMemoryUserDetailsManager userDetailsManager) { + DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider(); + authenticationProvider.setUserDetailsService(userDetailsManager); + authenticationProvider.setPasswordEncoder(bCryptPasswordEncoder()); + authenticationManagerBuilder.authenticationProvider(authenticationProvider); + } + + @Bean + public InMemoryUserDetailsManager userDetailsService() { + if (Objects.isNull(basicAuthorities)) { + basicAuthorities = "NOOP"; + } + + UserDetails user = + User.withUsername(this.basicUsername) + .password(this.basicPassword) + .roles(basicAuthorities.split(",")) + .build(); + return new InMemoryUserDetailsManager(user); + } + + @Bean + public BCryptPasswordEncoder bCryptPasswordEncoder() { + return new BCryptPasswordEncoder(10); + } +} diff --git a/src/main/java/org/cbioportal/application/security/config/Saml2SecurityConfig.java b/src/main/java/org/cbioportal/application/security/config/Saml2SecurityConfig.java new file mode 100644 index 00000000000..5adc94f1b42 --- /dev/null +++ b/src/main/java/org/cbioportal/application/security/config/Saml2SecurityConfig.java @@ -0,0 +1,115 @@ +package org.cbioportal.application.security.config; + +import static org.springframework.security.config.Customizer.withDefaults; + +import java.util.Collection; +import java.util.HashSet; +import java.util.Objects; +import java.util.Set; +import org.cbioportal.application.security.util.GrantedAuthorityUtil; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.convert.converter.Converter; +import org.springframework.http.HttpStatus; +import org.springframework.security.config.Customizer; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.saml2.provider.service.authentication.OpenSaml4AuthenticationProvider; +import org.springframework.security.saml2.provider.service.authentication.Saml2AuthenticatedPrincipal; +import org.springframework.security.saml2.provider.service.authentication.Saml2Authentication; +import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistrationRepository; +import org.springframework.security.saml2.provider.service.web.DefaultRelyingPartyRegistrationResolver; +import org.springframework.security.saml2.provider.service.web.authentication.logout.OpenSaml4LogoutRequestResolver; +import org.springframework.security.saml2.provider.service.web.authentication.logout.Saml2RelyingPartyInitiatedLogoutSuccessHandler; +import org.springframework.security.web.SecurityFilterChain; +import org.springframework.security.web.authentication.HttpStatusEntryPoint; +import org.springframework.security.web.authentication.logout.LogoutSuccessHandler; +import org.springframework.security.web.util.matcher.AntPathRequestMatcher; + +@Configuration +@EnableWebSecurity +@ConditionalOnExpression("{'saml','saml_plus_basic'}.contains('${authenticate}')") +public class Saml2SecurityConfig { + + private static final String LOGOUT_URL = "/logout"; + + @Value("${saml.idp.metadata.attribute.role:Role}") + private String roleAttributeName; + + @Bean + @ConditionalOnProperty(value = "authenticate", havingValue = "saml") + public SecurityFilterChain samlFilterChain( + HttpSecurity http, RelyingPartyRegistrationRepository relyingPartyRegistrationRepository) + throws Exception { + return http.csrf(AbstractHttpConfigurer::disable) + .cors(Customizer.withDefaults()) + .authorizeHttpRequests( + auth -> + auth.requestMatchers("/api/health", "/images/**", "/js/**", "/login") + .permitAll() + .anyRequest() + .authenticated()) + .exceptionHandling( + eh -> + eh.defaultAuthenticationEntryPointFor( + new HttpStatusEntryPoint(HttpStatus.UNAUTHORIZED), + AntPathRequestMatcher.antMatcher("/api/**"))) + .saml2Login(withDefaults()) + // NOTE: I did not get the official .saml2Logout() DSL to work as + // described at + // https://docs.spring.io/spring-security/reference/6.1/servlet/saml2/logout.html + // Logout Service POST Binding URL: http://localhost:8080/logout/saml2/slo + .logout( + logout -> + logout + .logoutUrl(LOGOUT_URL) + .logoutSuccessHandler(logoutSuccessHandler(relyingPartyRegistrationRepository))) + .build(); + } + + @Bean + public OpenSaml4AuthenticationProvider openSaml4AuthenticationProvider() { + OpenSaml4AuthenticationProvider authenticationProvider = new OpenSaml4AuthenticationProvider(); + authenticationProvider.setResponseAuthenticationConverter(rolesConverter()); + return authenticationProvider; + } + + private Converter + rolesConverter() { + + Converter delegate = + OpenSaml4AuthenticationProvider.createDefaultResponseAuthenticationConverter(); + + return (responseToken) -> { + Saml2Authentication authentication = delegate.convert(responseToken); + var principal = + (Saml2AuthenticatedPrincipal) Objects.requireNonNull(authentication).getPrincipal(); + Collection roles = principal.getAttribute(this.roleAttributeName); + Set mappedAuthorities = new HashSet<>(); + if (!Objects.isNull(roles)) { + mappedAuthorities.addAll(GrantedAuthorityUtil.generateGrantedAuthoritiesFromRoles(roles)); + } else { + mappedAuthorities.addAll(authentication.getAuthorities()); + } + return new Saml2Authentication( + principal, authentication.getSaml2Response(), mappedAuthorities); + }; + } + + @Bean + public LogoutSuccessHandler logoutSuccessHandler( + RelyingPartyRegistrationRepository relyingPartyRegistrationRepository) { + // Perform logout at the SAML2 IDP + DefaultRelyingPartyRegistrationResolver relyingPartyRegistrationResolver = + new DefaultRelyingPartyRegistrationResolver(relyingPartyRegistrationRepository); + OpenSaml4LogoutRequestResolver logoutRequestResolver = + new OpenSaml4LogoutRequestResolver(relyingPartyRegistrationResolver); + + return new Saml2RelyingPartyInitiatedLogoutSuccessHandler(logoutRequestResolver); + } +} diff --git a/src/main/java/org/cbioportal/application/security/token/RestAuthenticationEntryPoint.java b/src/main/java/org/cbioportal/application/security/token/RestAuthenticationEntryPoint.java new file mode 100644 index 00000000000..2252ac48185 --- /dev/null +++ b/src/main/java/org/cbioportal/application/security/token/RestAuthenticationEntryPoint.java @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2015 Memorial Sloan-Kettering Cancer Center. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS + * FOR A PARTICULAR PURPOSE. The software and documentation provided hereunder + * is on an "as is" basis, and Memorial Sloan-Kettering Cancer Center has no + * obligations to provide maintenance, support, updates, enhancements or + * modifications. In no event shall Memorial Sloan-Kettering Cancer Center be + * liable to any party for direct, indirect, special, incidental or + * consequential damages, including lost profits, arising out of the use of this + * software and its documentation, even if Memorial Sloan-Kettering Cancer + * Center has been advised of the possibility of such damage. + */ + +/* + * This file is part of cBioPortal. + * + * cBioPortal is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package org.cbioportal.application.security.token; + +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import java.io.IOException; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.web.AuthenticationEntryPoint; + +public class RestAuthenticationEntryPoint implements AuthenticationEntryPoint { + + @Override + public void commence( + HttpServletRequest request, + HttpServletResponse response, + AuthenticationException authException) + throws IOException { + response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized"); + } +} diff --git a/src/main/java/org/cbioportal/application/security/token/TokenAuthenticationFilter.java b/src/main/java/org/cbioportal/application/security/token/TokenAuthenticationFilter.java new file mode 100644 index 00000000000..05cd23253ac --- /dev/null +++ b/src/main/java/org/cbioportal/application/security/token/TokenAuthenticationFilter.java @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2018 Memorial Sloan-Kettering Cancer Center. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS + * FOR A PARTICULAR PURPOSE. The software and documentation provided hereunder + * is on an "as is" basis, and Memorial Sloan-Kettering Cancer Center has no + * obligations to provide maintenance, support, updates, enhancements or + * modifications. In no event shall Memorial Sloan-Kettering Cancer Center be + * liable to any party for direct, indirect, special, incidental or + * consequential damages, including lost profits, arising out of the use of this + * software and its documentation, even if Memorial Sloan-Kettering Cancer + * Center has been advised of the possibility of such damage. + */ + +/* + * This file is part of cBioPortal. + * + * cBioPortal is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package org.cbioportal.application.security.token; + +import static com.google.common.net.HttpHeaders.AUTHORIZATION; + +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import java.io.IOException; +import org.cbioportal.legacy.service.DataAccessTokenService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.authentication.BadCredentialsException; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter; + +/** + * @author Manda Wilson + */ +public class TokenAuthenticationFilter extends AbstractAuthenticationProcessingFilter { + + private DataAccessTokenService tokenService; + + private static final String BEARER = "Bearer"; + + private static final Logger LOG = LoggerFactory.getLogger(TokenAuthenticationFilter.class); + + public TokenAuthenticationFilter() { + // allow any request to contain an authorization header + super("/**"); + } + + public TokenAuthenticationFilter(String s, AuthenticationManager authenticationManagerBean) { + super(s, authenticationManagerBean); + } + + public TokenAuthenticationFilter( + String s, AuthenticationManager authenticationManager, DataAccessTokenService tokenService) { + super(s, authenticationManager); + this.tokenService = tokenService; + } + + @Override + protected boolean requiresAuthentication( + HttpServletRequest request, HttpServletResponse response) { + // only required if we do see an authorization header + String param = request.getHeader(AUTHORIZATION); + if (param == null) { + LOG.debug( + "attemptAuthentication(), authorization header is null, continue on to other security filters"); + return false; + } + return true; + } + + @Override + public Authentication attemptAuthentication( + HttpServletRequest request, HttpServletResponse response) + throws AuthenticationException, IOException, jakarta.servlet.ServletException { + + String token = extractHeaderToken(request); + + if (token == null) { + LOG.error("No token was found in request header."); + throw new BadCredentialsException("No token was found in request header."); + } + + Authentication auth = tokenService.createAuthenticationRequest(token); + + return getAuthenticationManager().authenticate(auth); + } + + @Override + protected void successfulAuthentication( + HttpServletRequest request, + HttpServletResponse response, + jakarta.servlet.FilterChain chain, + Authentication authResult) + throws IOException, ServletException { + super.successfulAuthentication(request, response, chain, authResult); + chain.doFilter(request, response); + } + + /** + * Extract the bearer token from a header. + * + * @param request + * @return The token, or null if no authorization header was supplied + */ + protected String extractHeaderToken(HttpServletRequest request) { + String authorizationHeader = request.getHeader(AUTHORIZATION); + if (authorizationHeader != null + && !authorizationHeader.isEmpty() + && authorizationHeader.toLowerCase().startsWith(BEARER.toLowerCase())) { + return authorizationHeader.substring(BEARER.length()).trim(); + } + return null; + } +} diff --git a/src/main/java/org/cbioportal/application/security/token/TokenAuthenticationSuccessHandler.java b/src/main/java/org/cbioportal/application/security/token/TokenAuthenticationSuccessHandler.java new file mode 100644 index 00000000000..01e37bc0121 --- /dev/null +++ b/src/main/java/org/cbioportal/application/security/token/TokenAuthenticationSuccessHandler.java @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2018 Memorial Sloan-Kettering Cancer Center. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS + * FOR A PARTICULAR PURPOSE. The software and documentation provided hereunder + * is on an "as is" basis, and Memorial Sloan-Kettering Cancer Center has no + * obligations to provide maintenance, support, updates, enhancements or + * modifications. In no event shall Memorial Sloan-Kettering Cancer Center be + * liable to any party for direct, indirect, special, incidental or + * consequential damages, including lost profits, arising out of the use of this + * software and its documentation, even if Memorial Sloan-Kettering Cancer + * Center has been advised of the possibility of such damage. + */ + +/* + * This file is part of cBioPortal. + * + * cBioPortal is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package org.cbioportal.application.security.token; + +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import java.io.IOException; +import org.springframework.security.core.Authentication; +import org.springframework.security.web.authentication.AuthenticationSuccessHandler; +import org.springframework.stereotype.Component; + +@Component +public class TokenAuthenticationSuccessHandler implements AuthenticationSuccessHandler { + + @Override + public void onAuthenticationSuccess( + HttpServletRequest request, HttpServletResponse response, Authentication authentication) + throws IOException, ServletException { + // We do not need to do anything extra on REST authentication success, because there is no page + // to redirect to + } +} diff --git a/src/main/java/org/cbioportal/application/security/token/config/DataAccessTokenConfig.java b/src/main/java/org/cbioportal/application/security/token/config/DataAccessTokenConfig.java new file mode 100644 index 00000000000..c8f96fcb459 --- /dev/null +++ b/src/main/java/org/cbioportal/application/security/token/config/DataAccessTokenConfig.java @@ -0,0 +1,51 @@ +package org.cbioportal.application.security.token.config; + +import org.cbioportal.application.security.token.oauth2.JwtTokenVerifierBuilder; +import org.cbioportal.application.security.token.oauth2.OAuth2DataAccessTokenServiceImpl; +import org.cbioportal.application.security.token.oauth2.OAuth2TokenAuthenticationProvider; +import org.cbioportal.application.security.token.oauth2.OAuth2TokenRefreshRestTemplate; +import org.cbioportal.application.security.token.uuid.UuidTokenAuthenticationProvider; +import org.cbioportal.legacy.persistence.SecurityRepository; +import org.cbioportal.legacy.service.impl.UnauthDataAccessTokenServiceImpl; +import org.cbioportal.legacy.utils.config.annotation.ConditionalOnProperty; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.client.RestTemplate; + +@Configuration +@ConditionalOnProperty( + name = "dat.method", + havingValue = {"", "none"}, + isNot = true) +public class DataAccessTokenConfig { + + // provider + @Bean("tokenAuthenticationProvider") + @ConditionalOnProperty(name = "dat.method", havingValue = "oauth2") + public OAuth2TokenAuthenticationProvider oauth2TokenAuthenticationProvider( + OAuth2TokenRefreshRestTemplate refreshRestTemplate) { + return new OAuth2TokenAuthenticationProvider(refreshRestTemplate); + } + + // TODO - implement jwt providers + @Bean("tokenAuthenticationProvider") + @ConditionalOnProperty(name = "dat.method", havingValue = "uuid") + public UuidTokenAuthenticationProvider uuidTokenAuthenticationProvider( + SecurityRepository repository) { + return new UuidTokenAuthenticationProvider(repository); + } + + // service + @Bean("dataAccessTokenService") + @ConditionalOnProperty(name = "dat.method", havingValue = "oauth2") + public OAuth2DataAccessTokenServiceImpl oauth2DataAccessTokenService( + RestTemplate template, JwtTokenVerifierBuilder jwtTokenVerifierBuilder) { + return new OAuth2DataAccessTokenServiceImpl(template, jwtTokenVerifierBuilder); + } + + @Bean("dataAccessTokenService") + @ConditionalOnProperty(name = "dat.method", havingValue = "none") + public UnauthDataAccessTokenServiceImpl unauthDataAccessTokenService() { + return new UnauthDataAccessTokenServiceImpl(); + } +} diff --git a/src/main/java/org/cbioportal/security/token/oauth2/JwtTokenVerifierBuilder.java b/src/main/java/org/cbioportal/application/security/token/oauth2/JwtTokenVerifierBuilder.java similarity index 80% rename from src/main/java/org/cbioportal/security/token/oauth2/JwtTokenVerifierBuilder.java rename to src/main/java/org/cbioportal/application/security/token/oauth2/JwtTokenVerifierBuilder.java index a14fba88b1e..572c897dfd4 100644 --- a/src/main/java/org/cbioportal/security/token/oauth2/JwtTokenVerifierBuilder.java +++ b/src/main/java/org/cbioportal/application/security/token/oauth2/JwtTokenVerifierBuilder.java @@ -28,18 +28,16 @@ * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . -*/ -package org.cbioportal.security.token.oauth2; - -import java.net.MalformedURLException; -import java.net.URL; -import java.security.interfaces.RSAPublicKey; + */ +package org.cbioportal.application.security.token.oauth2; import com.auth0.jwk.Jwk; import com.auth0.jwk.JwkException; import com.auth0.jwk.JwkProvider; import com.auth0.jwk.UrlJwkProvider; - +import java.net.MalformedURLException; +import java.net.URL; +import java.security.interfaces.RSAPublicKey; import org.springframework.beans.factory.annotation.Value; import org.springframework.security.jwt.crypto.sign.RsaVerifier; import org.springframework.stereotype.Component; @@ -47,14 +45,13 @@ @Component public class JwtTokenVerifierBuilder { - @Value("${dat.oauth2.jwkUrl:}") - private String jwkUrl; - - public RsaVerifier build(final String kid) throws MalformedURLException, JwkException { - final JwkProvider provider = new UrlJwkProvider(new URL(jwkUrl)); - final Jwk jwk = provider.get(kid); - final RSAPublicKey publicKey = (RSAPublicKey) jwk.getPublicKey(); - return new RsaVerifier(publicKey, "SHA512withRSA"); - } + @Value("${dat.oauth2.jwkUrl:}") + private String jwkUrl; -} \ No newline at end of file + public RsaVerifier build(final String kid) throws MalformedURLException, JwkException { + final JwkProvider provider = new UrlJwkProvider(new URL(jwkUrl)); + final Jwk jwk = provider.get(kid); + final RSAPublicKey publicKey = (RSAPublicKey) jwk.getPublicKey(); + return new RsaVerifier(publicKey, "SHA512withRSA"); + } +} diff --git a/src/main/java/org/cbioportal/application/security/token/oauth2/OAuth2BearerAuthenticationToken.java b/src/main/java/org/cbioportal/application/security/token/oauth2/OAuth2BearerAuthenticationToken.java new file mode 100644 index 00000000000..ef94e1f714b --- /dev/null +++ b/src/main/java/org/cbioportal/application/security/token/oauth2/OAuth2BearerAuthenticationToken.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2020 The Hyve B.V. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS + * FOR A PARTICULAR PURPOSE. The software and documentation provided hereunder + * is on an "as is" basis, and Memorial Sloan-Kettering Cancer Center has no + * obligations to provide maintenance, support, updates, enhancements or + * modifications. In no event shall Memorial Sloan-Kettering Cancer Center be + * liable to any party for direct, indirect, special, incidental or + * consequential damages, including lost profits, arising out of the use of this + * software and its documentation, even if Memorial Sloan-Kettering Cancer + * Center has been advised of the possibility of such damage. + */ + +/* + * This file is part of cBioPortal. + * + * cBioPortal is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package org.cbioportal.application.security.token.oauth2; + +import java.util.Collection; +import java.util.HashSet; +import org.springframework.security.authentication.AbstractAuthenticationToken; +import org.springframework.security.core.GrantedAuthority; + +/** OAuth2BearerAuthenticationToken */ +public class OAuth2BearerAuthenticationToken extends AbstractAuthenticationToken { + + private static final long serialVersionUID = 1L; + private final String accessToken; + private final Object principal; + + public OAuth2BearerAuthenticationToken(String accessToken) { + super(new HashSet<>()); + this.principal = null; + this.accessToken = accessToken; + } + + public OAuth2BearerAuthenticationToken(Object principal, String accessToken) { + super(new HashSet<>()); + this.accessToken = accessToken; + this.principal = principal; + } + + public OAuth2BearerAuthenticationToken( + Object principal, Collection authorities) { + super(authorities); + accessToken = null; + this.principal = principal; + setAuthenticated(true); + } + + @Override + public Object getCredentials() { + return accessToken; + } + + @Override + public Object getPrincipal() { + return principal; + } +} diff --git a/src/main/java/org/cbioportal/application/security/token/oauth2/OAuth2DataAccessTokenServiceImpl.java b/src/main/java/org/cbioportal/application/security/token/oauth2/OAuth2DataAccessTokenServiceImpl.java new file mode 100644 index 00000000000..6516099f40c --- /dev/null +++ b/src/main/java/org/cbioportal/application/security/token/oauth2/OAuth2DataAccessTokenServiceImpl.java @@ -0,0 +1,204 @@ +/* + * Copyright (c) 2020 The Hyve B.V. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS + * FOR A PARTICULAR PURPOSE. The software and documentation provided hereunder + * is on an "as is" basis, and Memorial Sloan-Kettering Cancer Center has no + * obligations to provide maintenance, support, updates, enhancements or + * modifications. In no event shall Memorial Sloan-Kettering Cancer Center be + * liable to any party for direct, indirect, special, incidental or + * consequential damages, including lost profits, arising out of the use of this + * software and its documentation, even if Memorial Sloan-Kettering Cancer + * Center has been advised of the possibility of such damage. + */ + +/* + * This file is part of cBioPortal. + * + * cBioPortal is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package org.cbioportal.application.security.token.oauth2; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import java.io.IOException; +import java.util.Date; +import java.util.List; +import org.cbioportal.legacy.model.DataAccessToken; +import org.cbioportal.legacy.service.DataAccessTokenService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.ResponseEntity; +import org.springframework.security.authentication.BadCredentialsException; +import org.springframework.security.core.Authentication; +import org.springframework.security.jwt.Jwt; +import org.springframework.security.jwt.JwtHelper; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; +import org.springframework.web.client.RestTemplate; + +public class OAuth2DataAccessTokenServiceImpl implements DataAccessTokenService { + @Value("${dat.oauth2.issuer}") + private String issuer; + + @Value("${dat.oauth2.clientId}") + private String clientId; + + @Value("${dat.oauth2.clientSecret}") + private String clientSecret; + + @Value("${dat.oauth2.accessTokenUri}") + private String accessTokenUri; + + @Value("${dat.oauth2.redirectUri}") + private String redirectUri; + + private final RestTemplate template; + + private final JwtTokenVerifierBuilder jwtTokenVerifierBuilder; + + @Autowired + public OAuth2DataAccessTokenServiceImpl( + RestTemplate template, JwtTokenVerifierBuilder jwtTokenVerifierBuilder) { + this.template = template; + this.jwtTokenVerifierBuilder = jwtTokenVerifierBuilder; + } + + @Override + // request offline token from authentication server via back channel + public DataAccessToken createDataAccessToken(final String accessCode) { + + HttpHeaders headers = new HttpHeaders(); + + MultiValueMap map = new LinkedMultiValueMap<>(); + map.add("grant_type", "authorization_code"); + map.add("code", accessCode); + map.add("client_id", clientId); + map.add("client_secret", clientSecret); + map.add("redirect_uri", redirectUri); + map.add( + "scope", "openid offline_access"); // `openid must be included according to OIDC standards + + HttpEntity> offlineRequest = new HttpEntity<>(map, headers); + + ResponseEntity response = + template.postForEntity(accessTokenUri, offlineRequest, String.class); + + String offlineToken = ""; + try { + JsonNode json = new ObjectMapper().readTree(response.getBody()); + offlineToken = json.get("refresh_token").asText(); + } catch (Exception e) { + throw new BadCredentialsException( + "Offline token could not be retrieved using access_code: " + accessCode); + } + + return new DataAccessToken(offlineToken); + } + + @Override + public List getAllDataAccessTokens(final String username) { + throw new UnsupportedOperationException( + "this implementation of (pure) JWT Data Access Tokens does not allow retrieval of stored tokens"); + } + + @Override + public DataAccessToken getDataAccessToken(final String username) { + throw new UnsupportedOperationException( + "this implementation of (pure) JWT Data Access Tokens does not allow retrieval of stored tokens"); + } + + @Override + public DataAccessToken getDataAccessTokenInfo(final String token) { + throw new UnsupportedOperationException( + "this implementation of (pure) JWT Data Access Tokens does not allow this operation"); + } + + @Override + public void revokeAllDataAccessTokens(final String username) { + throw new UnsupportedOperationException( + "this implementation of (pure) JWT Data Access Tokens does not allow revocation of tokens"); + } + + @Override + public void revokeDataAccessToken(final String token) { + throw new UnsupportedOperationException( + "this implementation of (pure) JWT Data Access Tokens does not allow revocation of tokens"); + } + + @Override + public Boolean isValid(final String token) { + final String kid = JwtHelper.headers(token).get("kid"); + try { + + final Jwt tokenDecoded = JwtHelper.decodeAndVerify(token, jwtTokenVerifierBuilder.build(kid)); + final String claims = tokenDecoded.getClaims(); + final JsonNode claimsMap = new ObjectMapper().readTree(claims); + + hasValidIssuer(claimsMap); + hasValidClientId(claimsMap); + + } catch (Exception e) { + throw new BadCredentialsException("Token is not valid (wrong key, issuer, or audience)."); + } + return true; + } + + @Override + public String getUsername(final String token) { + + final Jwt tokenDecoded = JwtHelper.decode(token); + + final String claims = tokenDecoded.getClaims(); + JsonNode claimsMap; + try { + claimsMap = new ObjectMapper().readTree(claims); + } catch (IOException e) { + throw new BadCredentialsException("User name could not be found in offline token."); + } + + if (!claimsMap.has("sub")) { + throw new BadCredentialsException("User name could not be found in offline token."); + } + + return claimsMap.get("sub").asText(); + } + + @Override + public Date getExpiration(final String token) { + return null; + } + + private void hasValidIssuer(final JsonNode claimsMap) throws BadCredentialsException { + if (!claimsMap.get("iss").asText().equals(issuer)) { + throw new BadCredentialsException("Wrong Issuer found in token"); + } + } + + private void hasValidClientId(final JsonNode claimsMap) throws BadCredentialsException { + if (!claimsMap.get("aud").asText().equals(clientId)) { + throw new BadCredentialsException("Wrong clientId found in token"); + } + } + + @Override + public Authentication createAuthenticationRequest(String offlineToken) { + // validity of the offline token is checked by the OAuth2 authentication server + return new OAuth2BearerAuthenticationToken(offlineToken); + } +} diff --git a/src/main/java/org/cbioportal/application/security/token/oauth2/OAuth2TokenAuthenticationProvider.java b/src/main/java/org/cbioportal/application/security/token/oauth2/OAuth2TokenAuthenticationProvider.java new file mode 100644 index 00000000000..bf5d6052e1f --- /dev/null +++ b/src/main/java/org/cbioportal/application/security/token/oauth2/OAuth2TokenAuthenticationProvider.java @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2020 The Hyve B.V. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS + * FOR A PARTICULAR PURPOSE. The software and documentation provided hereunder + * is on an "as is" basis, and Memorial Sloan-Kettering Cancer Center has no + * obligations to provide maintenance, support, updates, enhancements or + * modifications. In no event shall Memorial Sloan-Kettering Cancer Center be + * liable to any party for direct, indirect, special, incidental or + * consequential damages, including lost profits, arising out of the use of this + * software and its documentation, even if Memorial Sloan-Kettering Cancer + * Center has been advised of the possibility of such damage. + */ + +/* + * This file is part of cBioPortal. + * + * cBioPortal is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package org.cbioportal.application.security.token.oauth2; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import java.io.IOException; +import java.util.Collection; +import org.cbioportal.application.security.util.ClaimRoleExtractorUtil; +import org.cbioportal.application.security.util.GrantedAuthorityUtil; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.security.authentication.AuthenticationProvider; +import org.springframework.security.authentication.BadCredentialsException; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.jwt.Jwt; +import org.springframework.security.jwt.JwtHelper; + +public class OAuth2TokenAuthenticationProvider implements AuthenticationProvider { + + @Value("${dat.oauth2.jwtRolesPath:resource_access::cbioportal::roles}") + private String jwtRolesPath; + + private final OAuth2TokenRefreshRestTemplate tokenRefreshRestTemplate; + + public OAuth2TokenAuthenticationProvider( + OAuth2TokenRefreshRestTemplate tokenRefreshRestTemplate) { + this.tokenRefreshRestTemplate = tokenRefreshRestTemplate; + } + + @Override + public boolean supports(Class authentication) { + return authentication.isAssignableFrom(OAuth2BearerAuthenticationToken.class); + } + + @Override + public Authentication authenticate(Authentication authentication) throws AuthenticationException { + + String offlineToken = (String) authentication.getCredentials(); + + // Note: validity of the offline token is not checked in cBioPortal + // backend, is handeled by the OAuth2 authentication server. + + // request an access token from the OAuth2 identity provider + final String accessToken = tokenRefreshRestTemplate.getAccessToken(offlineToken); + + Collection authorities = extractAuthorities(accessToken); + String username = getUsername(accessToken); + + return new OAuth2BearerAuthenticationToken(username, authorities); + } + + // Read roles/authorities from JWT token. + private Collection extractAuthorities(final String token) + throws BadCredentialsException { + try { + final Jwt tokenDecoded = JwtHelper.decode(token); + final String claims = tokenDecoded.getClaims(); + return GrantedAuthorityUtil.generateGrantedAuthoritiesFromRoles( + ClaimRoleExtractorUtil.extractClientRoles(claims, jwtRolesPath)); + + } catch (Exception e) { + throw new BadCredentialsException("Authorities could not be extracted from access token."); + } + } + + private String getUsername(final String token) { + + final Jwt tokenDecoded = JwtHelper.decode(token); + + final String claims = tokenDecoded.getClaims(); + JsonNode claimsMap; + try { + claimsMap = new ObjectMapper().readTree(claims); + } catch (IOException e) { + throw new BadCredentialsException("User name could not be found in access token."); + } + + if (!claimsMap.has("sub")) { + throw new BadCredentialsException("User name could not be found in access token."); + } + + return claimsMap.get("sub").asText(); + } +} diff --git a/src/main/java/org/cbioportal/security/token/oauth2/OAuth2TokenDataAccessConfiguration.java b/src/main/java/org/cbioportal/application/security/token/oauth2/OAuth2TokenDataAccessConfiguration.java similarity index 88% rename from src/main/java/org/cbioportal/security/token/oauth2/OAuth2TokenDataAccessConfiguration.java rename to src/main/java/org/cbioportal/application/security/token/oauth2/OAuth2TokenDataAccessConfiguration.java index f9dc65c0889..a9382e44c8b 100644 --- a/src/main/java/org/cbioportal/security/token/oauth2/OAuth2TokenDataAccessConfiguration.java +++ b/src/main/java/org/cbioportal/application/security/token/oauth2/OAuth2TokenDataAccessConfiguration.java @@ -28,9 +28,9 @@ * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . -*/ + */ -package org.cbioportal.security.token.oauth2; +package org.cbioportal.application.security.token.oauth2; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -39,11 +39,10 @@ @Configuration public class OAuth2TokenDataAccessConfiguration { - @Bean - // This bean is defined here so - // that it can be stubbed in tests. - public RestTemplate restTemplate() { - return new RestTemplate(); - } - -} \ No newline at end of file + @Bean + // This bean is defined here so + // that it can be stubbed in tests. + public RestTemplate restTemplate() { + return new RestTemplate(); + } +} diff --git a/src/main/java/org/cbioportal/application/security/token/oauth2/OAuth2TokenRefreshRestTemplate.java b/src/main/java/org/cbioportal/application/security/token/oauth2/OAuth2TokenRefreshRestTemplate.java new file mode 100644 index 00000000000..3edb95904eb --- /dev/null +++ b/src/main/java/org/cbioportal/application/security/token/oauth2/OAuth2TokenRefreshRestTemplate.java @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2020 The Hyve B.V. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS + * FOR A PARTICULAR PURPOSE. The software and documentation provided hereunder + * is on an "as is" basis, and Memorial Sloan-Kettering Cancer Center has no + * obligations to provide maintenance, support, updates, enhancements or + * modifications. In no event shall Memorial Sloan-Kettering Cancer Center be + * liable to any party for direct, indirect, special, incidental or + * consequential damages, including lost profits, arising out of the use of this + * software and its documentation, even if Memorial Sloan-Kettering Cancer + * Center has been advised of the possibility of such damage. + */ + +/* + * This file is part of cBioPortal. + * + * cBioPortal is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package org.cbioportal.application.security.token.oauth2; + +import com.fasterxml.jackson.databind.ObjectMapper; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.security.authentication.BadCredentialsException; +import org.springframework.stereotype.Component; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; +import org.springframework.web.client.RestTemplate; + +@Component +public class OAuth2TokenRefreshRestTemplate { + + private final Logger logger = LoggerFactory.getLogger(getClass()); + + @Value("${dat.oauth2.clientId:}") + private String clientId; + + @Value("${dat.oauth2.clientSecret:}") + private String clientSecret; + + @Value("${dat.oauth2.accessTokenUri:}") + private String accessTokenUri; + + private final RestTemplate template; + + @Autowired + public OAuth2TokenRefreshRestTemplate(RestTemplate template) { + this.template = template; + } + + public String getAccessToken(String offlineToken) throws BadCredentialsException { + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); + + MultiValueMap map = new LinkedMultiValueMap<>(); + map.add("grant_type", "refresh_token"); + map.add("client_id", clientId); + map.add("client_secret", clientSecret); + map.add("refresh_token", offlineToken); + + HttpEntity> request = new HttpEntity<>(map, headers); + + ResponseEntity response = null; + try { + response = template.postForEntity(accessTokenUri, request, String.class); + String accessToken = + new ObjectMapper().readTree(response.getBody()).get("access_token").asText(); + logger.debug("Received access token from authentication server:\n{}", accessToken); + return accessToken; + } catch (Exception e) { + logger.error( + "Authentication server did not return an access token. Server response:\n{}", response); + throw new BadCredentialsException("Authentication server did not return an access token."); + } + } +} diff --git a/src/main/java/org/cbioportal/application/security/token/uuid/UuidTokenAuthenticationProvider.java b/src/main/java/org/cbioportal/application/security/token/uuid/UuidTokenAuthenticationProvider.java new file mode 100644 index 00000000000..12fce9f563d --- /dev/null +++ b/src/main/java/org/cbioportal/application/security/token/uuid/UuidTokenAuthenticationProvider.java @@ -0,0 +1,43 @@ +package org.cbioportal.application.security.token.uuid; + +import java.util.HashSet; +import java.util.Objects; +import java.util.Set; +import org.cbioportal.legacy.model.UserAuthorities; +import org.cbioportal.legacy.persistence.SecurityRepository; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.security.authentication.AuthenticationProvider; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.authority.AuthorityUtils; + +public class UuidTokenAuthenticationProvider implements AuthenticationProvider { + private static final Logger log = LoggerFactory.getLogger(UuidTokenAuthenticationProvider.class); + + private final SecurityRepository securityRepository; + + public UuidTokenAuthenticationProvider(final SecurityRepository securityRepository) { + this.securityRepository = securityRepository; + } + + @Override + public Authentication authenticate(Authentication authentication) throws AuthenticationException { + String user = (String) authentication.getPrincipal(); + log.debug("Attempt to grab user Authorities for user: {}", user); + UserAuthorities authorities = securityRepository.getPortalUserAuthorities(user); + Set mappedAuthorities = new HashSet<>(); + if (!Objects.isNull(authorities)) { + mappedAuthorities.addAll(AuthorityUtils.createAuthorityList(authorities.getAuthorities())); + } + return new UsernamePasswordAuthenticationToken( + user, "does not match unused", mappedAuthorities); + } + + @Override + public boolean supports(Class authentication) { + return authentication.isAssignableFrom(UsernamePasswordAuthenticationToken.class); + } +} diff --git a/src/main/java/org/cbioportal/application/security/util/CancerStudyExtractorUtil.java b/src/main/java/org/cbioportal/application/security/util/CancerStudyExtractorUtil.java new file mode 100644 index 00000000000..8b326669156 --- /dev/null +++ b/src/main/java/org/cbioportal/application/security/util/CancerStudyExtractorUtil.java @@ -0,0 +1,44 @@ +package org.cbioportal.application.security.util; + +import java.util.Collection; +import java.util.List; +import org.cbioportal.legacy.persistence.cachemaputil.CacheMapUtil; +import org.cbioportal.legacy.web.parameter.SampleFilter; +import org.cbioportal.legacy.web.parameter.SampleIdentifier; +import org.cbioportal.legacy.web.util.UniqueKeyExtractor; + +public class CancerStudyExtractorUtil { + + private CancerStudyExtractorUtil() {} + + public static Collection extractCancerStudyIdsFromSampleFilter( + SampleFilter sampleFilter, CacheMapUtil cacheMapUtil) { + Collection studyIds; + + if (sampleFilter.getSampleListIds() != null) { + studyIds = + extractCancerStudyIdsFromSampleListIds(sampleFilter.getSampleListIds(), cacheMapUtil); + } else if (sampleFilter.getSampleIdentifiers() != null) { + studyIds = extractCancerStudyIdsFromSampleIdentifiers(sampleFilter.getSampleIdentifiers()); + } else { + studyIds = UniqueKeyExtractor.extractUniqueKeys(sampleFilter.getUniqueSampleKeys()); + } + + return studyIds; + } + + public static Collection extractCancerStudyIdsFromSampleListIds( + List sampleListIds, CacheMapUtil cacheMapUtil) { + return sampleListIds.stream() + .map( + sampleListId -> + cacheMapUtil.getSampleListMap().get(sampleListId).getCancerStudyIdentifier()) + .distinct() + .toList(); + } + + public static Collection extractCancerStudyIdsFromSampleIdentifiers( + Collection sampleIdentifiers) { + return sampleIdentifiers.stream().map(SampleIdentifier::getStudyId).distinct().toList(); + } +} diff --git a/src/main/java/org/cbioportal/application/security/util/ClaimRoleExtractorUtil.java b/src/main/java/org/cbioportal/application/security/util/ClaimRoleExtractorUtil.java new file mode 100644 index 00000000000..225df2f09e2 --- /dev/null +++ b/src/main/java/org/cbioportal/application/security/util/ClaimRoleExtractorUtil.java @@ -0,0 +1,70 @@ +package org.cbioportal.application.security.util; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +import java.util.Collection; +import java.util.Collections; +import java.util.Map; +import java.util.stream.Collectors; +import java.util.stream.StreamSupport; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.security.authentication.BadCredentialsException; + +public class ClaimRoleExtractorUtil { + private static final Logger log = LoggerFactory.getLogger(ClaimRoleExtractorUtil.class); + + public static Collection extractClientRoles( + final Map claims, final String jwtRolesPath) { + try { + // Convert the map to a JSON string + ObjectMapper objectMapper = new ObjectMapper(); + objectMapper.registerModule(new JavaTimeModule()); + String jsonString = objectMapper.writeValueAsString(claims); + + JsonNode rolesCursor = new ObjectMapper().readTree(jsonString); + return extractClientRoles(rolesCursor, jwtRolesPath); + } catch (Exception e) { + log.error("Error extracting claims as a json string"); + } + return Collections.emptyList(); + } + + public static Collection extractClientRoles( + final String claims, final String jwtRolesPath) { + try { + JsonNode rolesCursor = new ObjectMapper().readTree(claims); + return extractClientRoles(rolesCursor, jwtRolesPath); + } catch (Exception e) { + log.error("Error converting Json String to JsonNode Object"); + } + return Collections.emptyList(); + } + + public static Collection extractClientRoles( + final JsonNode claims, final String jwtRolesPath) { + try { + + JsonNode rolesCursor = claims; + for (var keyName : jwtRolesPath.split("::")) { + if (rolesCursor.has(keyName)) { + rolesCursor = rolesCursor.get(keyName); + } else { + throw new BadCredentialsException("Cannot Find user Roles in JWT Access Token "); + } + } + if (rolesCursor.isTextual()) { + rolesCursor = new ObjectMapper().readTree(rolesCursor.asText()); + } + return StreamSupport.stream(rolesCursor.spliterator(), false) + .map(JsonNode::asText) + .collect(Collectors.toSet()); + } catch (Exception e) { + log.error( + "Error Grabbing Client Roles from OIDC User Info: Realm roles must follow the convention {}", + jwtRolesPath); + } + return Collections.emptyList(); + } +} diff --git a/src/main/java/org/cbioportal/application/security/util/GrantedAuthorityUtil.java b/src/main/java/org/cbioportal/application/security/util/GrantedAuthorityUtil.java new file mode 100644 index 00000000000..dbac4c39752 --- /dev/null +++ b/src/main/java/org/cbioportal/application/security/util/GrantedAuthorityUtil.java @@ -0,0 +1,17 @@ +package org.cbioportal.application.security.util; + +import java.util.Collection; +import java.util.stream.Collectors; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.authority.SimpleGrantedAuthority; + +public class GrantedAuthorityUtil { + private static final String PREFIX_RESOURCE_ROLE = "ROLE_"; + + public static Collection generateGrantedAuthoritiesFromRoles( + Collection roles) { + return roles.stream() + .map(role -> new SimpleGrantedAuthority(PREFIX_RESOURCE_ROLE + role)) + .collect(Collectors.toSet()); + } +} diff --git a/src/main/java/org/cbioportal/documentation/ExternalPageController.java b/src/main/java/org/cbioportal/documentation/ExternalPageController.java deleted file mode 100644 index c8a246d38ed..00000000000 --- a/src/main/java/org/cbioportal/documentation/ExternalPageController.java +++ /dev/null @@ -1,49 +0,0 @@ -package org.cbioportal.documentation; - -import org.springframework.stereotype.Controller; -import org.springframework.transaction.annotation.Transactional; -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.bind.annotation.ResponseBody; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.net.URL; -import java.net.URLConnection; -import java.net.URLDecoder; -import java.util.Collections; -import java.util.Map; - -// Retrieve the content of an external page -// Make it auto-scannable -@Controller -public class ExternalPageController { - - // service name: getexternalpage.json - // available via GET method - // sourceURL is required - @Transactional - @RequestMapping(value = "/api/getexternalpage.json", method = {RequestMethod.GET}) - public @ResponseBody Map getExternalPage(@RequestParam(required = true) String sourceURL) throws IOException { - String decodedString, pageText = ""; - - // decode the sourceURL and open a connection - sourceURL = URLDecoder.decode(sourceURL, "UTF-8"); - URL url = new URL(sourceURL); - URLConnection connection = url.openConnection(); - - // create a reader - BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream(), "UTF-8")); - - // read - while ((decodedString = in.readLine()) != null) { - pageText += decodedString + "\n"; - } - in.close(); - - // turn the pageText into a singletonMap for json and return - return Collections.singletonMap("response", pageText); - } -} \ No newline at end of file diff --git a/src/main/java/org/cbioportal/domain/alteration/repository/AlterationRepository.java b/src/main/java/org/cbioportal/domain/alteration/repository/AlterationRepository.java new file mode 100644 index 00000000000..d7a677163a6 --- /dev/null +++ b/src/main/java/org/cbioportal/domain/alteration/repository/AlterationRepository.java @@ -0,0 +1,93 @@ +package org.cbioportal.domain.alteration.repository; + +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.Set; +import org.cbioportal.domain.studyview.StudyViewFilterContext; +import org.cbioportal.legacy.model.AlterationCountByGene; +import org.cbioportal.legacy.model.AlterationFilter; +import org.cbioportal.legacy.model.CopyNumberCountByGene; +import org.cbioportal.legacy.model.MolecularProfile; + +public interface AlterationRepository { + /** + * Retrieves a list of mutated genes along with their alteration counts based on the given study + * view filter context. + * + * @param studyViewFilterContext The filter criteria for the study view. + * @return A list of {@link AlterationCountByGene} representing mutated genes and their counts. + */ + List getMutatedGenes(StudyViewFilterContext studyViewFilterContext); + + /** + * Retrieves a list of structural variant genes along with their alteration counts based on the + * given study view filter context. + * + * @param studyViewFilterContext The filter criteria for the study view. + * @return A list of {@link AlterationCountByGene} representing structural variant genes and their + * counts. + */ + List getStructuralVariantGenes( + StudyViewFilterContext studyViewFilterContext); + + /** + * Retrieves a list of copy number alteration (CNA) genes along with their alteration counts based + * on the given study view filter context. + * + * @param studyViewFilterContext The filter criteria for the study view. + * @return A list of {@link CopyNumberCountByGene} representing CNA genes and their counts. + */ + List getCnaGenes(StudyViewFilterContext studyViewFilterContext); + + /** + * Retrieves the total number of profiled samples categorized by molecular profile and alteration + * type. + * + * @param studyViewFilterContext The filter criteria for the study view. + * @param alterationType The type of alteration (e.g., MUTATION, CNA, SV). + * @param molecularProfiles A list of molecular profiles to consider. + * @return A map where the key is the molecular profile ID and the value is the total count of + * profiled samples. + */ + Map getTotalProfiledCounts( + StudyViewFilterContext studyViewFilterContext, + String alterationType, + List molecularProfiles); + + /** + * Retrieves a mapping of alteration types to the corresponding gene panel IDs that match the + * given study view filter context. + * + * @param studyViewFilterContext The filter criteria for the study view. + * @param alterationType The type of alteration (e.g., MUTATION, CNA, SV). + * @return A map where the key is the alteration type and the value is a set of matching gene + * panel IDs. + */ + Map> getMatchingGenePanelIds( + StudyViewFilterContext studyViewFilterContext, String alterationType); + + /** + * Retrieves the count of sample profiles that do not have associated gene panel data for a given + * alteration type. + * + * @param studyViewFilterContext The filter criteria for the study view. + * @param alterationType The type of alteration (e.g., MUTATION, CNA, SV). + * @return The number of sample profiles without gene panel data for the specified alteration + * type. + */ + int getSampleProfileCountWithoutPanelData( + StudyViewFilterContext studyViewFilterContext, String alterationType); + + List getAlterationCountByGeneGivenSamplesAndMolecularProfiles( + Collection samples, + Collection molecularProfiles, + AlterationFilter alterationFilter); + + List getAlterationCountByGeneGivenPatientsAndMolecularProfiles( + Collection samples, + Collection molecularProfiles, + AlterationFilter alterationFilter); + + List getAllMolecularProfiles(); +} diff --git a/src/main/java/org/cbioportal/domain/alteration/usecase/AbstractAlterationCountByGeneUseCase.java b/src/main/java/org/cbioportal/domain/alteration/usecase/AbstractAlterationCountByGeneUseCase.java new file mode 100644 index 00000000000..9738b4d89f0 --- /dev/null +++ b/src/main/java/org/cbioportal/domain/alteration/usecase/AbstractAlterationCountByGeneUseCase.java @@ -0,0 +1,105 @@ +package org.cbioportal.domain.alteration.usecase; + +import java.util.Collections; +import java.util.List; +import java.util.Set; +import java.util.function.Function; +import java.util.stream.Collectors; +import org.cbioportal.domain.alteration.repository.AlterationRepository; +import org.cbioportal.domain.generic_assay.usecase.GetFilteredMolecularProfilesByAlterationType; +import org.cbioportal.domain.studyview.StudyViewFilterContext; +import org.cbioportal.legacy.model.AlterationCountByGene; +import org.cbioportal.legacy.model.AlterationType; +import org.cbioportal.legacy.model.MolecularProfile; +import org.springframework.lang.NonNull; + +abstract class AbstractAlterationCountByGeneUseCase { + + private final AlterationRepository alterationRepository; + private final GetFilteredMolecularProfilesByAlterationType + getFilteredMolecularProfilesByAlterationType; + + AbstractAlterationCountByGeneUseCase( + AlterationRepository alterationRepository, + GetFilteredMolecularProfilesByAlterationType getFilteredMolecularProfilesByAlterationType) { + this.alterationRepository = alterationRepository; + this.getFilteredMolecularProfilesByAlterationType = + getFilteredMolecularProfilesByAlterationType; + } + + /** + * Populates alteration counts with profile data, including the total profiled count and matching + * gene panel IDs. + * + * @param alterationCounts List of alteration counts to enrich. + * @param studyViewFilterContext Context containing filter criteria. + * @param alterationType Type of alteration (e.g., mutation, CNA, structural variant). + * @param The type of alteration count. + * @return List of enriched alteration counts. + */ + List populateAlterationCounts( + @NonNull List alterationCounts, + @NonNull StudyViewFilterContext studyViewFilterContext, + @NonNull AlterationType alterationType) { + final var firstMolecularProfileForEachStudy = + getFirstMolecularProfileGroupedByStudy(studyViewFilterContext, alterationType); + var profiledCountsMap = + alterationRepository.getTotalProfiledCounts( + studyViewFilterContext, alterationType.toString(), firstMolecularProfileForEachStudy); + final var matchingGenePanelIdsMap = + alterationRepository.getMatchingGenePanelIds( + studyViewFilterContext, alterationType.toString()); + final int sampleProfileCountWithoutGenePanelData = + alterationRepository.getSampleProfileCountWithoutPanelData( + studyViewFilterContext, alterationType.toString()); + + alterationCounts.parallelStream() + .forEach( + alterationCountByGene -> { + String hugoGeneSymbol = alterationCountByGene.getHugoGeneSymbol(); + Set matchingGenePanelIds = + matchingGenePanelIdsMap.get(hugoGeneSymbol) != null + ? matchingGenePanelIdsMap.get(hugoGeneSymbol) + : Collections.emptySet(); + + // profiled count = non-WES count + WES count + int alterationTotalProfiledCount = + profiledCountsMap.getOrDefault(hugoGeneSymbol, 0) + + sampleProfileCountWithoutGenePanelData; + + alterationCountByGene.setNumberOfProfiledCases(alterationTotalProfiledCount); + + alterationCountByGene.setMatchingGenePanelIds(matchingGenePanelIds); + }); + return alterationCounts; + } + + /** + * Retrieves the first molecular profile for each study based on the alteration type. + * + * @param studyViewFilterContext Context containing filter criteria. + * @param alterationType Type of alteration (e.g., mutation, CNA, structural variant). + * @return List of MolecularProfile objects representing the first profile for each study. + */ + private List getFirstMolecularProfileGroupedByStudy( + StudyViewFilterContext studyViewFilterContext, AlterationType alterationType) { + final var molecularProfiles = + getFilteredMolecularProfilesByAlterationType.execute( + studyViewFilterContext, alterationType.toString()); + return getFirstMolecularProfileGroupedByStudy(molecularProfiles); + } + + private List getFirstMolecularProfileGroupedByStudy( + List molecularProfiles) { + return molecularProfiles.stream() + .collect( + Collectors.toMap( + MolecularProfile::getCancerStudyIdentifier, + Function.identity(), + (existing, replacement) -> existing // Keep the first occurrence + )) + .values() + .stream() + .toList(); + } +} diff --git a/src/main/java/org/cbioportal/domain/alteration/usecase/AlterationCountByGeneUseCases.java b/src/main/java/org/cbioportal/domain/alteration/usecase/AlterationCountByGeneUseCases.java new file mode 100644 index 00000000000..cde78c51fbb --- /dev/null +++ b/src/main/java/org/cbioportal/domain/alteration/usecase/AlterationCountByGeneUseCases.java @@ -0,0 +1,10 @@ +package org.cbioportal.domain.alteration.usecase; + +import org.springframework.context.annotation.Profile; +import org.springframework.stereotype.Service; + +@Service +@Profile("clickhouse") +public record AlterationCountByGeneUseCases( + GetAlterationCountByGeneUseCase getAlterationCountByGeneUseCase, + GetCnaAlterationCountByGeneUseCase getCnaAlterationCountByGeneUseCase) {} diff --git a/src/main/java/org/cbioportal/domain/alteration/usecase/GetAlterationCountByGeneUseCase.java b/src/main/java/org/cbioportal/domain/alteration/usecase/GetAlterationCountByGeneUseCase.java new file mode 100644 index 00000000000..dcd89871e8f --- /dev/null +++ b/src/main/java/org/cbioportal/domain/alteration/usecase/GetAlterationCountByGeneUseCase.java @@ -0,0 +1,167 @@ +package org.cbioportal.domain.alteration.usecase; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.function.Function; +import java.util.stream.Collectors; +import org.cbioportal.domain.alteration.repository.AlterationRepository; +import org.cbioportal.domain.cancerstudy.usecase.GetFilteredStudyIdsUseCase; +import org.cbioportal.domain.generic_assay.usecase.GetFilteredMolecularProfilesByAlterationType; +import org.cbioportal.domain.studyview.StudyViewFilterContext; +import org.cbioportal.legacy.model.AlterationCountByGene; +import org.cbioportal.legacy.model.AlterationType; +import org.cbioportal.legacy.model.MutSig; +import org.cbioportal.legacy.service.SignificantlyMutatedGeneService; +import org.cbioportal.legacy.service.exception.StudyNotFoundException; +import org.cbioportal.legacy.web.parameter.Projection; +import org.springframework.context.annotation.Profile; +import org.springframework.stereotype.Service; + +@Service +@Profile("clickhouse") +public class GetAlterationCountByGeneUseCase extends AbstractAlterationCountByGeneUseCase { + private final AlterationRepository alterationRepository; + private final GetFilteredStudyIdsUseCase getFilteredStudyIdsUseCase; + private final SignificantlyMutatedGeneService significantlyMutatedGeneService; + + public GetAlterationCountByGeneUseCase( + AlterationRepository alterationRepository, + GetFilteredMolecularProfilesByAlterationType getFilteredMolecularProfilesByAlterationType, + GetFilteredStudyIdsUseCase getFilteredStudyIdsUseCase, + SignificantlyMutatedGeneService significantlyMutatedGeneService) { + super(alterationRepository, getFilteredMolecularProfilesByAlterationType); + + this.alterationRepository = alterationRepository; + this.getFilteredStudyIdsUseCase = getFilteredStudyIdsUseCase; + this.significantlyMutatedGeneService = significantlyMutatedGeneService; + } + + /** + * Retrieves alteration counts by gene based on the given {@link AlterationType} and study filter + * context. Supports {@code MUTATION_EXTENDED} and {@code STRUCTURAL_VARIANT} alteration types. + * + * @param studyViewFilterContext the context containing study view filters + * @param alterationType the type of alteration to retrieve (must be either {@code + * MUTATION_EXTENDED} or {@code STRUCTURAL_VARIANT}) + * @return a list of {@link AlterationCountByGene} objects containing alteration counts + * @throws StudyNotFoundException if the study is not found + * @throws UnsupportedOperationException if the given {@code alterationType} is not supported + */ + public List execute( + StudyViewFilterContext studyViewFilterContext, AlterationType alterationType) + throws StudyNotFoundException { + + final List alterationCountByGenes = + switch (alterationType) { + case MUTATION_EXTENDED -> alterationRepository.getMutatedGenes(studyViewFilterContext); + case STRUCTURAL_VARIANT -> + alterationRepository.getStructuralVariantGenes(studyViewFilterContext); + default -> + throw new UnsupportedOperationException( + "AlterationType " + + alterationType + + " not supported.." + + ". For cna... use GetCnaAlterationCountByGeneUseCase"); + }; + + var combinedAlterationCountByGenes = + combineAlterationCountsWithConflictingHugoSymbols(alterationCountByGenes); + + return populateAlterationCountsWithMutSigQValue( + populateAlterationCounts( + combinedAlterationCountByGenes, studyViewFilterContext, alterationType), + studyViewFilterContext); + } + + /** + * Combines alteration counts by Hugo gene symbols. If multiple entries exist for the same gene + * symbol, their number of altered cases, on-panel cases, and total counts are summed up. Returns + * a list of unique AlterationCountByGene objects where each gene symbol is represented only once. + * + *

This appears in the Data where Genes have similar Hugo Gene Symbols but different Entrez Ids + * + * @param alterationCounts List of AlterationCountByGene objects, potentially with duplicate gene + * symbols + * @return List of AlterationCountByGene objects with unique gene symbols and combined counts + */ + private List combineAlterationCountsWithConflictingHugoSymbols( + List alterationCounts) { + Map alterationCountByGeneMap = new HashMap<>(); + for (var alterationCount : alterationCounts) { + if (alterationCountByGeneMap.containsKey(alterationCount.getHugoGeneSymbol())) { + AlterationCountByGene toUpdate = + alterationCountByGeneMap.get(alterationCount.getHugoGeneSymbol()); + + // Combine total altered cases (on-panel + off-panel) + toUpdate.setNumberOfAlteredCases( + toUpdate.getNumberOfAlteredCases() + alterationCount.getNumberOfAlteredCases()); + + // Combine on-panel counts + toUpdate.setNumberOfAlteredCasesOnPanel( + toUpdate.getNumberOfAlteredCasesOnPanel() + + alterationCount.getNumberOfAlteredCasesOnPanel()); + + // Combine total counts + toUpdate.setTotalCount(toUpdate.getTotalCount() + alterationCount.getTotalCount()); + } else { + alterationCountByGeneMap.put(alterationCount.getHugoGeneSymbol(), alterationCount); + } + } + return alterationCountByGeneMap.values().stream().toList(); + } + + /** + * Updates alteration counts with MutSig Q-value data for significance. + * + * @param alterationCountByGenes List of alteration counts to update. + * @param studyViewFilterContext Context containing filter criteria. + * @return List of alteration counts updated with MutSig Q-value. + * @throws StudyNotFoundException if the specified study is not found. + */ + private List populateAlterationCountsWithMutSigQValue( + List alterationCountByGenes, + StudyViewFilterContext studyViewFilterContext) + throws StudyNotFoundException { + final var mutSigs = getMutSigs(studyViewFilterContext); + // If MutSig is not empty update Mutated Genes + return updateAlterationCountsWithMutSigQValue(alterationCountByGenes, mutSigs); + } + + /** + * Retrieves MutSig data for significantly mutated genes in the specified studies. + * + * @param studyViewFilterContext Context containing filter criteria. + * @return Map of MutSig objects keyed by Hugo gene symbol. + * @throws StudyNotFoundException if the specified study is not found. + */ + private Map getMutSigs(StudyViewFilterContext studyViewFilterContext) + throws StudyNotFoundException { + var distinctStudyIds = getFilteredStudyIdsUseCase.execute(studyViewFilterContext); + Map mutSigs = new HashMap<>(); + if (distinctStudyIds.size() == 1) { + var studyId = distinctStudyIds.getFirst(); + mutSigs = + significantlyMutatedGeneService + .getSignificantlyMutatedGenes( + studyId, Projection.SUMMARY.name(), null, null, null, null) + .stream() + .collect(Collectors.toMap(MutSig::getHugoGeneSymbol, Function.identity())); + } + return mutSigs; + } + + private List updateAlterationCountsWithMutSigQValue( + List alterationCountByGenes, Map mutSigs) { + + if (!mutSigs.isEmpty()) { + alterationCountByGenes.parallelStream() + .filter(alterationCount -> mutSigs.containsKey(alterationCount.getHugoGeneSymbol())) + .forEach( + alterationCount -> + alterationCount.setqValue( + mutSigs.get(alterationCount.getHugoGeneSymbol()).getqValue())); + } + return alterationCountByGenes; + } +} diff --git a/src/main/java/org/cbioportal/domain/alteration/usecase/GetAlterationEnrichmentsUseCase.java b/src/main/java/org/cbioportal/domain/alteration/usecase/GetAlterationEnrichmentsUseCase.java new file mode 100644 index 00000000000..ccb0926472a --- /dev/null +++ b/src/main/java/org/cbioportal/domain/alteration/usecase/GetAlterationEnrichmentsUseCase.java @@ -0,0 +1,196 @@ +package org.cbioportal.domain.alteration.usecase; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ExecutionException; +import java.util.stream.Collectors; +import org.cbioportal.domain.alteration.repository.AlterationRepository; +import org.cbioportal.domain.alteration.util.AlterationEnrichmentScoreUtil; +import org.cbioportal.legacy.model.AlterationCountByGene; +import org.cbioportal.legacy.model.AlterationEnrichment; +import org.cbioportal.legacy.model.AlterationFilter; +import org.cbioportal.legacy.model.CountSummary; +import org.cbioportal.legacy.model.EnrichmentType; +import org.cbioportal.legacy.model.MolecularProfile; +import org.cbioportal.legacy.model.MolecularProfileCaseIdentifier; +import org.cbioportal.legacy.service.exception.MolecularProfileNotFoundException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.context.annotation.Profile; +import org.springframework.core.task.AsyncTaskExecutor; +import org.springframework.data.util.Pair; +import org.springframework.stereotype.Service; + +@Service +@Profile("clickhouse") +public class GetAlterationEnrichmentsUseCase { + + private static final Logger log = LoggerFactory.getLogger(GetAlterationEnrichmentsUseCase.class); + + private Map molecularProfilesMap; + + private final AlterationRepository alterationRepository; + private final AsyncTaskExecutor threadPoolTaskExecutor; + + public GetAlterationEnrichmentsUseCase( + AlterationRepository alterationRepository, AsyncTaskExecutor threadPoolTaskExecutor) { + this.alterationRepository = alterationRepository; + this.threadPoolTaskExecutor = threadPoolTaskExecutor; + } + + public Collection execute( + Map> molecularProfileCaseIdentifierByGroup, + EnrichmentType enrichmentType, + AlterationFilter alterationFilter) { + Map alterationEnrichmentByGene = new HashMap<>(); + + List>> results = + molecularProfileCaseIdentifierByGroup.entrySet().stream() + .map( + entry -> + threadPoolTaskExecutor.submit( + () -> + this.fetchAlterationCountByGeneByGroup( + entry.getKey(), + entry.getValue(), + enrichmentType, + alterationFilter))) + .map( + future -> { + try { + return future.get(); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); // Always good to restore interrupted flag + throw new RuntimeException("Thread was interrupted", e); + } catch (ExecutionException e) { + throw new RuntimeException("Unexpected exception during execution", e); + } + }) + .toList(); + + results.forEach( + alterationCountByGeneAndGroup -> { + var alterationCountByGenes = alterationCountByGeneAndGroup.getSecond(); + var group = alterationCountByGeneAndGroup.getFirst(); + + alterationCountByGenes.forEach( + alterationCountByGene -> { + AlterationEnrichment alterationEnrichment = + getOrCreateAlterationEnrichment( + alterationEnrichmentByGene, alterationCountByGene); + + var countSummary = new CountSummary(); + countSummary.setName(group); + countSummary.setAlteredCount(alterationCountByGene.getNumberOfAlteredCases()); + countSummary.setProfiledCount(alterationCountByGene.getNumberOfProfiledCases()); + alterationEnrichment.getCounts().add(countSummary); + }); + }); + + var groups = molecularProfileCaseIdentifierByGroup.keySet(); + + return alterationEnrichmentByGene.values().stream() + .map( + alterationEnrichment -> { + addMissingCountsToAlterationEnrichment(alterationEnrichment, groups); + var pValue = + AlterationEnrichmentScoreUtil.calculateEnrichmentScore(alterationEnrichment); + alterationEnrichment.setpValue(pValue); + return alterationEnrichment; + }) + .collect(Collectors.toSet()); + } + + private Pair> fetchAlterationCountByGeneByGroup( + String group, + List molecularProfileCaseIdentifiers, + EnrichmentType enrichmentType, + AlterationFilter alterationFilter) + throws MolecularProfileNotFoundException { + Pair, Set> caseIdsAndMolecularProfileIds = + this.extractCaseIdsAndMolecularProfiles(molecularProfileCaseIdentifiers); + + List alterationCountByGenes = + enrichmentType.equals(EnrichmentType.SAMPLE) + ? alterationRepository.getAlterationCountByGeneGivenSamplesAndMolecularProfiles( + caseIdsAndMolecularProfileIds.getFirst(), + caseIdsAndMolecularProfileIds.getSecond(), + alterationFilter) + : alterationRepository.getAlterationCountByGeneGivenPatientsAndMolecularProfiles( + caseIdsAndMolecularProfileIds.getFirst(), + caseIdsAndMolecularProfileIds.getSecond(), + alterationFilter); + return Pair.of(group, alterationCountByGenes); + } + + private Pair, Set> extractCaseIdsAndMolecularProfiles( + List molecularProfileCaseIdentifiers) + throws MolecularProfileNotFoundException { + Set caseIds = new HashSet<>(); + Set molecularProfileIds = new HashSet<>(); + for (var molecularProfileIdentifier : molecularProfileCaseIdentifiers) { + String studyId = + getStudyIdGivenMolecularProfileId(molecularProfileIdentifier.getMolecularProfileId()); + caseIds.add(studyId + "_" + molecularProfileIdentifier.getCaseId()); + molecularProfileIds.add(molecularProfileIdentifier.getMolecularProfileId()); + } + return Pair.of(caseIds, molecularProfileIds); + } + + private AlterationEnrichment getOrCreateAlterationEnrichment( + Map alterationEnrichmentByGene, + AlterationCountByGene alterationCountByGene) { + return alterationEnrichmentByGene.computeIfAbsent( + alterationCountByGene.getHugoGeneSymbol(), + key -> { + AlterationEnrichment enrichment = new AlterationEnrichment(); + enrichment.setEntrezGeneId(alterationCountByGene.getEntrezGeneId()); + enrichment.setHugoGeneSymbol(alterationCountByGene.getHugoGeneSymbol()); + enrichment.setCounts(new ArrayList<>()); + return enrichment; + }); + } + + private void addMissingCountsToAlterationEnrichment( + AlterationEnrichment alterationEnrichment, Collection groups) { + Set counts = + alterationEnrichment.getCounts().stream() + .map(CountSummary::getName) + .collect(Collectors.toSet()); + if (counts.size() == groups.size()) { + return; + } + Set groupsWithMissingCounts = new HashSet<>(groups); + groupsWithMissingCounts.removeAll(counts); + + for (String group : groupsWithMissingCounts) { + CountSummary countSummary = new CountSummary(); + countSummary.setName(group); + countSummary.setAlteredCount(0); + countSummary.setProfiledCount(0); + alterationEnrichment.getCounts().add(countSummary); + } + } + + private synchronized String getStudyIdGivenMolecularProfileId(String molecularProfileId) + throws MolecularProfileNotFoundException { + if (molecularProfilesMap == null) { + molecularProfilesMap = + alterationRepository.getAllMolecularProfiles().stream() + .collect( + Collectors.toMap( + MolecularProfile::getStableId, molecularProfile -> molecularProfile)); + } + var molecularProfile = molecularProfilesMap.get(molecularProfileId); + if (molecularProfile == null) { + log.debug("Molecular profile with id {} not found", molecularProfileId); + throw new MolecularProfileNotFoundException(molecularProfileId); + } + return molecularProfile.getCancerStudyIdentifier(); + } +} diff --git a/src/main/java/org/cbioportal/domain/alteration/usecase/GetCnaAlterationCountByGeneUseCase.java b/src/main/java/org/cbioportal/domain/alteration/usecase/GetCnaAlterationCountByGeneUseCase.java new file mode 100644 index 00000000000..ed8aa94c154 --- /dev/null +++ b/src/main/java/org/cbioportal/domain/alteration/usecase/GetCnaAlterationCountByGeneUseCase.java @@ -0,0 +1,153 @@ +package org.cbioportal.domain.alteration.usecase; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import org.apache.commons.math3.util.Pair; +import org.cbioportal.domain.alteration.repository.AlterationRepository; +import org.cbioportal.domain.cancerstudy.usecase.GetFilteredStudyIdsUseCase; +import org.cbioportal.domain.generic_assay.usecase.GetFilteredMolecularProfilesByAlterationType; +import org.cbioportal.domain.studyview.StudyViewFilterContext; +import org.cbioportal.legacy.model.AlterationType; +import org.cbioportal.legacy.model.CopyNumberCountByGene; +import org.cbioportal.legacy.model.Gistic; +import org.cbioportal.legacy.service.SignificantCopyNumberRegionService; +import org.cbioportal.legacy.service.exception.StudyNotFoundException; +import org.cbioportal.legacy.service.util.AlterationCountServiceUtil; +import org.cbioportal.legacy.web.parameter.Projection; +import org.springframework.context.annotation.Profile; +import org.springframework.stereotype.Service; + +@Service +@Profile("clickhouse") +public class GetCnaAlterationCountByGeneUseCase extends AbstractAlterationCountByGeneUseCase { + + private final AlterationRepository alterationRepository; + private final GetFilteredStudyIdsUseCase getFilteredStudyIdsUseCase; + private final SignificantCopyNumberRegionService significantCopyNumberRegionService; + + public GetCnaAlterationCountByGeneUseCase( + AlterationRepository alterationRepository, + GetFilteredMolecularProfilesByAlterationType getFilteredMolecularProfilesByAlterationType, + GetFilteredStudyIdsUseCase getFilteredStudyIdsUseCase, + SignificantCopyNumberRegionService significantCopyNumberRegionService) { + super(alterationRepository, getFilteredMolecularProfilesByAlterationType); + + this.alterationRepository = alterationRepository; + this.getFilteredStudyIdsUseCase = getFilteredStudyIdsUseCase; + this.significantCopyNumberRegionService = significantCopyNumberRegionService; + } + + /** + * Retrieves a list of genes with copy number alterations (CNA) and their alteration counts for a + * given filter context. + * + * @param studyViewFilterContext Context containing filter criteria. + * @return List of CopyNumberCountByGene objects representing genes with CNAs. + * @throws StudyNotFoundException if the specified study is not found. + */ + public List execute(StudyViewFilterContext studyViewFilterContext) + throws StudyNotFoundException { + var combinedCopyNumberCountByGene = + combineCopyNumberCountsWithConflictingHugoSymbols( + alterationRepository.getCnaGenes(studyViewFilterContext)); + return populateAlterationCountsWithCNASigQValue( + populateAlterationCounts( + combinedCopyNumberCountByGene, + studyViewFilterContext, + AlterationType.COPY_NUMBER_ALTERATION), + studyViewFilterContext); + } + + /** + * Combines alteration counts by Hugo gene symbols. If multiple entries exist for the same gene + * symbol, their number of altered cases and total counts are summed up. Returns a list of unique + * AlterationCountByGene objects where each gene symbol is represented only once. + * + *

This appears in the Data where Genes have similar Hugo Gene Symbols but different Entrez + * Ids. This is a special case to handle Copy Number Mutations where the Alteration type should be + * a part of the key + * + * @param alterationCounts List of CopyNumberCountByGene objects, potentially with duplicate gene + * symbols + * @return List of AlterationCountByGene objects with unique gene symbols and combined counts + */ + private List combineCopyNumberCountsWithConflictingHugoSymbols( + List alterationCounts) { + Map, CopyNumberCountByGene> alterationCountByGeneMap = new HashMap<>(); + for (var alterationCount : alterationCounts) { + var copyNumberKey = + Pair.create(alterationCount.getHugoGeneSymbol(), alterationCount.getAlteration()); + if (alterationCountByGeneMap.containsKey(copyNumberKey)) { + CopyNumberCountByGene toUpdate = alterationCountByGeneMap.get(copyNumberKey); + toUpdate.setNumberOfAlteredCases( + toUpdate.getNumberOfAlteredCases() + alterationCount.getNumberOfAlteredCases()); + toUpdate.setTotalCount(toUpdate.getTotalCount() + alterationCount.getTotalCount()); + } else { + alterationCountByGeneMap.put(copyNumberKey, alterationCount); + } + } + return alterationCountByGeneMap.values().stream().toList(); + } + + /** + * Updates copy number alteration counts with GISTIC significance data. + * + * @param alterationCountByGenes List of alteration counts to update. + * @param studyViewFilterContext Context containing filter criteria. + * @return List of alteration counts updated with GISTIC significance data. + * @throws StudyNotFoundException if the specified study is not found. + */ + private List populateAlterationCountsWithCNASigQValue( + List alterationCountByGenes, + StudyViewFilterContext studyViewFilterContext) + throws StudyNotFoundException { + final var gisticMap = getGisticMap(studyViewFilterContext); + return updateAlterationCountsWithCNASigQValue(alterationCountByGenes, gisticMap); + } + + /** + * Retrieves GISTIC data for significant copy number alterations in the specified studies. + * + * @param studyViewFilterContext Context containing filter criteria. + * @return Map of GISTIC objects keyed by gene and G-score rank. + * @throws StudyNotFoundException if the specified study is not found. + */ + private Map, Gistic> getGisticMap( + StudyViewFilterContext studyViewFilterContext) throws StudyNotFoundException { + var distinctStudyIds = getFilteredStudyIdsUseCase.execute(studyViewFilterContext); + Map, Gistic> gisticMap = new HashMap<>(); + if (distinctStudyIds.size() == 1) { + var studyId = distinctStudyIds.getFirst(); + List gisticList = + significantCopyNumberRegionService.getSignificantCopyNumberRegions( + studyId, Projection.SUMMARY.name(), null, null, null, null); + AlterationCountServiceUtil.setupGisticMap(gisticList, gisticMap); + } + return gisticMap; + } + + private List updateAlterationCountsWithCNASigQValue( + List alterationCountByGenes, + Map, Gistic> gisticMap) { + + if (!gisticMap.isEmpty()) { + alterationCountByGenes.parallelStream() + .filter( + alterationCount -> + gisticMap.containsKey( + Pair.create( + alterationCount.getHugoGeneSymbol(), alterationCount.getAlteration()))) + .forEach( + alterationCount -> + alterationCount.setqValue( + gisticMap + .get( + Pair.create( + alterationCount.getHugoGeneSymbol(), + alterationCount.getAlteration())) + .getqValue())); + } + return alterationCountByGenes; + } +} diff --git a/src/main/java/org/cbioportal/domain/alteration/util/AlterationEnrichmentScoreUtil.java b/src/main/java/org/cbioportal/domain/alteration/util/AlterationEnrichmentScoreUtil.java new file mode 100644 index 00000000000..52eb1f9b8fc --- /dev/null +++ b/src/main/java/org/cbioportal/domain/alteration/util/AlterationEnrichmentScoreUtil.java @@ -0,0 +1,69 @@ +package org.cbioportal.domain.alteration.util; + +import java.math.BigDecimal; +import java.util.List; +import org.apache.commons.math3.stat.inference.ChiSquareTest; +import org.cbioportal.legacy.model.AlterationEnrichment; +import org.cbioportal.legacy.model.CountSummary; +import org.cbioportal.legacy.service.util.FisherExactTestCalculator; + +public abstract class AlterationEnrichmentScoreUtil { + + private AlterationEnrichmentScoreUtil() {} + + public static BigDecimal calculateEnrichmentScore(AlterationEnrichment alterationEnrichment) { + double pValue = 0; + + List counts = alterationEnrichment.getCounts(); + List filteredCounts = + counts.stream().filter(groupCaseCount -> groupCaseCount.getProfiledCount() > 0).toList(); + + // groups where number of altered cases is greater than profiled cases. + // This is a temporary fix for https://github.com/cBioPortal/cbioportal/issues/7274 + // and https://github.com/cBioPortal/cbioportal/issues/7418 + long invalidDataGroups = + filteredCounts.stream() + .filter( + groupCasesCount -> + groupCasesCount.getAlteredCount() > groupCasesCount.getProfiledCount()) + .count(); + + // calculate p-value only if more than one group have profile cases count + // greater than 0 + if (filteredCounts.size() > 1 && invalidDataGroups == 0) { + // if groups size is two do Fisher Exact test else do Chi-Square test + if (counts.size() == 2) { + int alteredInNoneCount = counts.get(1).getProfiledCount() - counts.get(1).getAlteredCount(); + int alteredOnlyInQueryGenesCount = + counts.get(0).getProfiledCount() - counts.get(0).getAlteredCount(); + + var fisherExactTestCalculator = new FisherExactTestCalculator(); + pValue = + fisherExactTestCalculator.getTwoTailedPValue( + alteredInNoneCount, + counts.get(1).getAlteredCount(), + alteredOnlyInQueryGenesCount, + counts.get(0).getAlteredCount()); + } else { + long[][] array = + counts.stream() + .map( + count -> + new long[] { + count.getAlteredCount(), + count.getProfiledCount() - count.getAlteredCount(), + }) + .toArray(long[][]::new); + + ChiSquareTest chiSquareTest = new ChiSquareTest(); + pValue = chiSquareTest.chiSquareTest(array); + + // set p-value to 1 when the cases in all groups are altered + if (Double.isNaN(pValue)) { + pValue = 1; + } + } + } + return BigDecimal.valueOf(pValue); + } +} diff --git a/src/main/java/org/cbioportal/domain/alteration/util/AlterationUtil.java b/src/main/java/org/cbioportal/domain/alteration/util/AlterationUtil.java new file mode 100644 index 00000000000..f57e3e7aca4 --- /dev/null +++ b/src/main/java/org/cbioportal/domain/alteration/util/AlterationUtil.java @@ -0,0 +1,27 @@ +package org.cbioportal.domain.alteration.util; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import org.cbioportal.legacy.model.AlterationCountByGene; + +public abstract class AlterationUtil { + private AlterationUtil() {} + + public static List combineAlterationCountsWithConflictingHugoSymbols( + List alterationCounts) { + Map alterationCountByGeneMap = new HashMap<>(); + for (var alterationCount : alterationCounts) { + if (alterationCountByGeneMap.containsKey(alterationCount.getHugoGeneSymbol())) { + AlterationCountByGene toUpdate = + alterationCountByGeneMap.get(alterationCount.getHugoGeneSymbol()); + toUpdate.setNumberOfAlteredCases( + toUpdate.getNumberOfAlteredCases() + alterationCount.getNumberOfAlteredCases()); + toUpdate.setTotalCount(toUpdate.getTotalCount() + alterationCount.getTotalCount()); + } else { + alterationCountByGeneMap.put(alterationCount.getHugoGeneSymbol(), alterationCount); + } + } + return alterationCountByGeneMap.values().stream().toList(); + } +} diff --git a/src/main/java/org/cbioportal/domain/cancerstudy/CancerStudyMetadata.java b/src/main/java/org/cbioportal/domain/cancerstudy/CancerStudyMetadata.java new file mode 100644 index 00000000000..11b6ffe67ae --- /dev/null +++ b/src/main/java/org/cbioportal/domain/cancerstudy/CancerStudyMetadata.java @@ -0,0 +1,119 @@ +package org.cbioportal.domain.cancerstudy; + +import java.io.Serializable; +import java.util.Date; + +public record CancerStudyMetadata( + Integer cancerStudyId, + String cancerStudyIdentifier, + String typeOfCancerId, + String name, + String description, + Boolean publicStudy, + String pmid, + String citation, + String groups, + Integer status, + Date importDate, + Integer allSampleCount, + Integer sequencedSampleCount, + Integer cnaSampleCount, + Integer mrnaRnaSeqSampleCount, + Integer mrnaRnaSeqV2SampleCount, + Integer mrnaMicroarraySampleCount, + Integer miRnaSampleCount, + Integer methylationHm27SampleCount, + Integer rppaSampleCount, + Integer massSpectrometrySampleCount, + Integer completeSampleCount, + String referenceGenome, + Integer treatmentCount, + Integer structuralVariantCount, + TypeOfCancer typeOfCancer) + implements Serializable { + + public CancerStudyMetadata( + Integer cancerStudyId, + String cancerStudyIdentifier, + String typeOfCancerId, + String name, + String description, + Boolean publicStudy, + String pmid, + String citation, + String groups, + Integer status, + Date importDate, + String referenceGenome, + TypeOfCancer typeOfCancer) { + this( + cancerStudyId, + cancerStudyIdentifier, + typeOfCancerId, + name, + description, + publicStudy, + pmid, + citation, + groups, + status, + importDate, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + referenceGenome, + null, + null, + typeOfCancer); + } + + public CancerStudyMetadata( + Integer cancerStudyId, + String cancerStudyIdentifier, + String typeOfCancerId, + String name, + String description, + Boolean publicStudy, + String pmid, + String citation, + String groups, + Integer status, + Date importDate, + String referenceGenome) { + this( + cancerStudyId, + cancerStudyIdentifier, + typeOfCancerId, + name, + description, + publicStudy, + pmid, + citation, + groups, + status, + importDate, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + referenceGenome, + null, + null, + null); + } +} diff --git a/src/main/java/org/cbioportal/domain/cancerstudy/TypeOfCancer.java b/src/main/java/org/cbioportal/domain/cancerstudy/TypeOfCancer.java new file mode 100644 index 00000000000..71667699c88 --- /dev/null +++ b/src/main/java/org/cbioportal/domain/cancerstudy/TypeOfCancer.java @@ -0,0 +1,4 @@ +package org.cbioportal.domain.cancerstudy; + +public record TypeOfCancer( + String id, String name, String dedicatedColor, String shortName, String parent) {} diff --git a/src/main/java/org/cbioportal/domain/cancerstudy/repository/CancerStudyRepository.java b/src/main/java/org/cbioportal/domain/cancerstudy/repository/CancerStudyRepository.java new file mode 100644 index 00000000000..2f75e06091b --- /dev/null +++ b/src/main/java/org/cbioportal/domain/cancerstudy/repository/CancerStudyRepository.java @@ -0,0 +1,69 @@ +package org.cbioportal.domain.cancerstudy.repository; + +import java.util.List; +import org.cbioportal.domain.cancerstudy.CancerStudyMetadata; +import org.cbioportal.domain.studyview.StudyViewFilterContext; +import org.cbioportal.shared.SortAndSearchCriteria; + +/** + * Repository interface for accessing and managing cancer study data. + * + *

This repository provides methods to retrieve metadata and summary information about cancer + * studies. It serves as an abstraction layer between the domain logic and the data source, allowing + * for flexible and maintainable data access. + * + *

Usage Example: + * + *

{@code
+ * // Inject the repository into a service
+ * private final CancerStudyRepository cancerStudyRepository;
+ *
+ * public CancerStudyService(CancerStudyRepository cancerStudyRepository) {
+ *     this.cancerStudyRepository = cancerStudyRepository;
+ * }
+ *
+ * // Retrieve metadata for all cancer studies
+ * List metadata = cancerStudyRepository.getCancerStudiesMetadata();
+ *
+ * // Retrieve summary metadata for cancer studies
+ * List summaryMetadata = cancerStudyRepository.getCancerStudiesMetadataSummary();
+ * }
+ * + * @see CancerStudyMetadata + */ +public interface CancerStudyRepository { + + /** + * Retrieves a list of metadata for all cancer studies. + * + *

This method returns detailed metadata for all available cancer studies, including + * information such as study identifiers, descriptions, and associated data sources. The metadata + * can be used for comprehensive analysis or display purposes. + * + *

Note: The returned list may be large, depending on the number of cancer studies in + * the database. Consider using pagination or filtering if performance is a concern. + * + * @return a list of {@link CancerStudyMetadata} objects containing detailed metadata for all + * cancer studies. The list may be empty if no studies are found. + */ + List getCancerStudiesMetadata(SortAndSearchCriteria sortAndSearchCriteria); + + /** + * Retrieves a list of summary metadata for cancer studies. + * + *

This method returns a lightweight representation of cancer study metadata, containing only + * the most essential fields. It is suitable for scenarios where a high-level overview of the + * studies is sufficient, such as displaying a list of studies in a UI or performing quick + * lookups. + * + *

Note: The summary metadata typically excludes detailed information to reduce the size + * of the response and improve performance. + * + * @return a list of {@link CancerStudyMetadata} objects containing summary metadata for cancer + * studies. The list may be empty if no studies are found. + */ + List getCancerStudiesMetadataSummary( + SortAndSearchCriteria sortAndSearchCriteria); + + List getFilteredStudyIds(StudyViewFilterContext studyViewFilterContext); +} diff --git a/src/main/java/org/cbioportal/domain/cancerstudy/usecase/GetCancerStudyMetadataUseCase.java b/src/main/java/org/cbioportal/domain/cancerstudy/usecase/GetCancerStudyMetadataUseCase.java new file mode 100644 index 00000000000..f998077739b --- /dev/null +++ b/src/main/java/org/cbioportal/domain/cancerstudy/usecase/GetCancerStudyMetadataUseCase.java @@ -0,0 +1,86 @@ +package org.cbioportal.domain.cancerstudy.usecase; + +import java.util.Collections; +import java.util.List; +import org.cbioportal.domain.cancerstudy.CancerStudyMetadata; +import org.cbioportal.domain.cancerstudy.repository.CancerStudyRepository; +import org.cbioportal.shared.SortAndSearchCriteria; +import org.cbioportal.shared.enums.ProjectionType; +import org.springframework.context.annotation.Profile; +import org.springframework.stereotype.Service; + +/** + * Service class responsible for retrieving cancer study metadata based on the specified projection + * type. + * + *

This use case encapsulates the logic for fetching cancer study metadata from the repository + * and returning the appropriate data based on the requested level of detail (projection). It acts + * as an intermediary between the controller and the repository, ensuring that the domain logic is + * decoupled from the data access layer. + * + *

Usage Example: + * + *

{@code
+ * // Inject the use case into a controller or service
+ * private final GetCancerStudyMetadataUseCase getCancerStudyMetadataUseCase;
+ *
+ * public CancerStudyController(GetCancerStudyMetadataUseCase getCancerStudyMetadataUseCase) {
+ *     this.getCancerStudyMetadataUseCase = getCancerStudyMetadataUseCase;
+ * }
+ *
+ * // Retrieve detailed metadata for cancer studies
+ * List detailedMetadata = getCancerStudyMetadataUseCase.execute(ProjectionType.DETAILED);
+ *
+ * // Retrieve summary metadata for cancer studies
+ * List summaryMetadata = getCancerStudyMetadataUseCase.execute(ProjectionType.SUMMARY);
+ * }
+ * + * @see CancerStudyRepository + * @see ProjectionType + * @see CancerStudyMetadata + */ +@Service +@Profile("clickhouse") +public final class GetCancerStudyMetadataUseCase { + + private final CancerStudyRepository studyRepository; + + /** + * Constructs a new {@link GetCancerStudyMetadataUseCase} with the specified repository. + * + * @param studyRepository the repository used to access cancer study metadata. + */ + public GetCancerStudyMetadataUseCase(CancerStudyRepository studyRepository) { + this.studyRepository = studyRepository; + } + + /** + * Executes the use case to retrieve cancer study metadata based on the specified projection type. + * + *

This method determines the level of detail to fetch from the repository based on the + * provided {@link ProjectionType}. It supports the following projections: + * + *

    + *
  • {@link ProjectionType#DETAILED}: Fetches all available metadata for cancer studies. + *
  • {@link ProjectionType#SUMMARY}: Fetches a summarized version of the metadata. + *
  • Other projection types: Returns an empty list. + *
+ * + * @param projectionType the level of detail to fetch. Determines which repository method is + * called. + * @param sortAndSearchCriteria enables sorting and searching feature within persistence layer. + * {@link SortAndSearchCriteria} + * @return a list of {@link CancerStudyMetadata} objects based on the specified projection type. + * Returns an empty list if the projection type is not supported. + * @see ProjectionType + * @see CancerStudyMetadata + */ + public List execute( + ProjectionType projectionType, SortAndSearchCriteria sortAndSearchCriteria) { + return switch (projectionType) { + case DETAILED -> studyRepository.getCancerStudiesMetadata(sortAndSearchCriteria); + case SUMMARY -> studyRepository.getCancerStudiesMetadataSummary(sortAndSearchCriteria); + default -> Collections.emptyList(); + }; + } +} diff --git a/src/main/java/org/cbioportal/domain/cancerstudy/usecase/GetFilteredStudyIdsUseCase.java b/src/main/java/org/cbioportal/domain/cancerstudy/usecase/GetFilteredStudyIdsUseCase.java new file mode 100644 index 00000000000..682c6a46327 --- /dev/null +++ b/src/main/java/org/cbioportal/domain/cancerstudy/usecase/GetFilteredStudyIdsUseCase.java @@ -0,0 +1,22 @@ +package org.cbioportal.domain.cancerstudy.usecase; + +import java.util.List; +import org.cbioportal.domain.cancerstudy.repository.CancerStudyRepository; +import org.cbioportal.domain.studyview.StudyViewFilterContext; +import org.springframework.context.annotation.Profile; +import org.springframework.stereotype.Service; + +@Service +@Profile("clickhouse") +public class GetFilteredStudyIdsUseCase { + + private final CancerStudyRepository studyRepository; + + public GetFilteredStudyIdsUseCase(CancerStudyRepository studyRepository) { + this.studyRepository = studyRepository; + } + + public List execute(StudyViewFilterContext studyViewFilterContext) { + return this.studyRepository.getFilteredStudyIds(studyViewFilterContext); + } +} diff --git a/src/main/java/org/cbioportal/domain/clinical_attributes/repository/ClinicalAttributesRepository.java b/src/main/java/org/cbioportal/domain/clinical_attributes/repository/ClinicalAttributesRepository.java new file mode 100644 index 00000000000..7ee0a0bb877 --- /dev/null +++ b/src/main/java/org/cbioportal/domain/clinical_attributes/repository/ClinicalAttributesRepository.java @@ -0,0 +1,26 @@ +package org.cbioportal.domain.clinical_attributes.repository; + +import java.util.List; +import java.util.Map; +import org.cbioportal.legacy.model.ClinicalAttribute; +import org.cbioportal.legacy.web.parameter.ClinicalDataType; + +public interface ClinicalAttributesRepository { + + /** + * Retrieves a list of clinical attributes for the specified studies. + * + * @param studyIds A list of study IDs. + * @return A list of {@link ClinicalAttribute} representing the clinical attributes for the given + * studies. + */ + List getClinicalAttributesForStudies(List studyIds); + + /** + * Retrieves a mapping of clinical attribute names to their corresponding data types. + * + * @return A map where the key is the clinical attribute name and the value is the corresponding + * {@link ClinicalDataType}. + */ + Map getClinicalAttributeDatatypeMap(); +} diff --git a/src/main/java/org/cbioportal/domain/clinical_attributes/usecase/GetClinicalAttributesDataTypeMapUseCase.java b/src/main/java/org/cbioportal/domain/clinical_attributes/usecase/GetClinicalAttributesDataTypeMapUseCase.java new file mode 100644 index 00000000000..3965ed481bc --- /dev/null +++ b/src/main/java/org/cbioportal/domain/clinical_attributes/usecase/GetClinicalAttributesDataTypeMapUseCase.java @@ -0,0 +1,39 @@ +package org.cbioportal.domain.clinical_attributes.usecase; + +import java.util.Map; +import org.cbioportal.domain.clinical_attributes.repository.ClinicalAttributesRepository; +import org.cbioportal.legacy.web.parameter.ClinicalDataType; +import org.springframework.context.annotation.Profile; +import org.springframework.stereotype.Service; + +@Service +@Profile("clickhouse") +/** + * Use case for retrieving a mapping of clinical attribute names to their corresponding data types. + * This class interacts with the {@link ClinicalAttributesRepository} to fetch the required data. + */ +public class GetClinicalAttributesDataTypeMapUseCase { + + private final ClinicalAttributesRepository clinicalAttributesRepository; + + /** + * Constructs a use case for retrieving the clinical attribute data type map. + * + * @param clinicalAttributesRepository The repository used to fetch clinical attribute data types. + */ + public GetClinicalAttributesDataTypeMapUseCase( + ClinicalAttributesRepository clinicalAttributesRepository) { + this.clinicalAttributesRepository = clinicalAttributesRepository; + } + + /** + * Executes the use case to retrieve a mapping of clinical attribute names to their corresponding + * data types. + * + * @return A map where the key is the clinical attribute name and the value is the corresponding + * {@link ClinicalDataType}. + */ + public Map execute() { + return clinicalAttributesRepository.getClinicalAttributeDatatypeMap(); + } +} diff --git a/src/main/java/org/cbioportal/domain/clinical_attributes/usecase/GetClinicalAttributesForStudiesUseCase.java b/src/main/java/org/cbioportal/domain/clinical_attributes/usecase/GetClinicalAttributesForStudiesUseCase.java new file mode 100644 index 00000000000..2f568a63070 --- /dev/null +++ b/src/main/java/org/cbioportal/domain/clinical_attributes/usecase/GetClinicalAttributesForStudiesUseCase.java @@ -0,0 +1,39 @@ +package org.cbioportal.domain.clinical_attributes.usecase; + +import java.util.List; +import org.cbioportal.domain.clinical_attributes.repository.ClinicalAttributesRepository; +import org.cbioportal.legacy.model.ClinicalAttribute; +import org.springframework.context.annotation.Profile; +import org.springframework.stereotype.Service; + +@Service +@Profile("clickhouse") +/** + * Use case for retrieving clinical attributes for specified studies. This class interacts with the + * {@link ClinicalAttributesRepository} to fetch the required data. + */ +public class GetClinicalAttributesForStudiesUseCase { + + private final ClinicalAttributesRepository clinicalAttributesRepository; + + /** + * Constructs a use case for retrieving clinical attributes for studies. + * + * @param clinicalAttributesRepository The repository used to fetch clinical attributes. + */ + public GetClinicalAttributesForStudiesUseCase( + ClinicalAttributesRepository clinicalAttributesRepository) { + this.clinicalAttributesRepository = clinicalAttributesRepository; + } + + /** + * Executes the use case to retrieve clinical attributes for the given list of study IDs. + * + * @param studyIds A list of study IDs. + * @return A list of {@link ClinicalAttribute} representing the clinical attributes for the given + * studies. + */ + public List execute(List studyIds) { + return clinicalAttributesRepository.getClinicalAttributesForStudies(studyIds); + } +} diff --git a/src/main/java/org/cbioportal/domain/clinical_data/repository/ClinicalDataRepository.java b/src/main/java/org/cbioportal/domain/clinical_data/repository/ClinicalDataRepository.java new file mode 100644 index 00000000000..a7eb94d136f --- /dev/null +++ b/src/main/java/org/cbioportal/domain/clinical_data/repository/ClinicalDataRepository.java @@ -0,0 +1,43 @@ +package org.cbioportal.domain.clinical_data.repository; + +import java.util.List; +import org.cbioportal.domain.studyview.StudyViewFilterContext; +import org.cbioportal.legacy.model.ClinicalData; +import org.cbioportal.legacy.model.ClinicalDataCountItem; + +/** Repository interface for retrieving clinical data related to patients and samples. */ +public interface ClinicalDataRepository { + + /** + * Retrieves clinical data for patients based on the given study view filter context and filtered + * attributes. + * + * @param studyViewFilterContext The filter criteria for the study view. + * @param filteredAttributes A list of attributes to filter the clinical data. + * @return A list of {@link ClinicalData} representing patient clinical data. + */ + List getPatientClinicalData( + StudyViewFilterContext studyViewFilterContext, List filteredAttributes); + + /** + * Retrieves clinical data for samples based on the given study view filter context and filtered + * attributes. + * + * @param studyViewFilterContext The filter criteria for the study view. + * @param filteredAttributes A list of attributes to filter the clinical data. + * @return A list of {@link ClinicalData} representing sample clinical data. + */ + List getSampleClinicalData( + StudyViewFilterContext studyViewFilterContext, List filteredAttributes); + + /** + * Retrieves counts of clinical data records based on the given study view filter context and + * filtered attributes. + * + * @param studyViewFilterContext The filter criteria for the study view. + * @param filteredAttributes A list of attributes to filter the clinical data. + * @return A list of {@link ClinicalDataCountItem} representing clinical data counts. + */ + List getClinicalDataCounts( + StudyViewFilterContext studyViewFilterContext, List filteredAttributes); +} diff --git a/src/main/java/org/cbioportal/domain/clinical_data/usecase/ClinicalDataUseCases.java b/src/main/java/org/cbioportal/domain/clinical_data/usecase/ClinicalDataUseCases.java new file mode 100644 index 00000000000..df14da37881 --- /dev/null +++ b/src/main/java/org/cbioportal/domain/clinical_data/usecase/ClinicalDataUseCases.java @@ -0,0 +1,23 @@ +package org.cbioportal.domain.clinical_data.usecase; + +import org.springframework.context.annotation.Profile; +import org.springframework.stereotype.Service; + +@Service +@Profile("clickhouse") +/** + * A record representing a collection of use cases related to clinical data operations. This record + * encapsulates instances of various use case classes, providing a centralized way to access and + * manage clinical data-related operations. + * + * @param getClinicalDataCountsUseCase the use case for retrieving and processing clinical data + * counts + * @param getClinicalDataForXyPlotUseCase the use case for retrieving clinical data for XY plots + * @param getPatientClinicalDataUseCase the use case for retrieving clinical data for patients + * @param getSampleClinicalDataUseCase the use case for retrieving clinical data for samples + */ +public record ClinicalDataUseCases( + GetClinicalDataCountsUseCase getClinicalDataCountsUseCase, + GetClinicalDataForXyPlotUseCase getClinicalDataForXyPlotUseCase, + GetPatientClinicalDataUseCase getPatientClinicalDataUseCase, + GetSampleClinicalDataUseCase getSampleClinicalDataUseCase) {} diff --git a/src/main/java/org/cbioportal/domain/clinical_data/usecase/GetClinicalDataCountsUseCase.java b/src/main/java/org/cbioportal/domain/clinical_data/usecase/GetClinicalDataCountsUseCase.java new file mode 100644 index 00000000000..2c4cc69ec31 --- /dev/null +++ b/src/main/java/org/cbioportal/domain/clinical_data/usecase/GetClinicalDataCountsUseCase.java @@ -0,0 +1,89 @@ +package org.cbioportal.domain.clinical_data.usecase; + +import java.util.List; +import org.cbioportal.domain.clinical_attributes.usecase.GetClinicalAttributesForStudiesUseCase; +import org.cbioportal.domain.clinical_data.repository.ClinicalDataRepository; +import org.cbioportal.domain.patient.usecase.GetFilteredPatientCountUseCase; +import org.cbioportal.domain.sample.usecase.GetFilteredSamplesCountUseCase; +import org.cbioportal.domain.studyview.StudyViewFilterContext; +import org.cbioportal.legacy.model.ClinicalDataCountItem; +import org.cbioportal.legacy.service.util.StudyViewColumnarServiceUtil; +import org.springframework.context.annotation.Profile; +import org.springframework.stereotype.Service; + +@Service +@Profile("clickhouse") +/** + * Use case for retrieving and processing clinical data counts. This class orchestrates the + * retrieval of clinical data counts from the repository, normalizes the data, and ensures that + * missing attributes are accounted for in the result. + */ +public class GetClinicalDataCountsUseCase { + + private final ClinicalDataRepository clinicalDataRepository; + private final GetClinicalAttributesForStudiesUseCase getClinicalAttributesForStudiesUseCase; + private final GetFilteredSamplesCountUseCase getFilteredSamplesCountUseCase; + private final GetFilteredPatientCountUseCase getFilteredPatientCountUseCase; + + /** + * Constructs a {@code GetClinicalDataCountsUseCase} with the provided use cases and repository. + * + * @param clinicalDataRepository the repository to be used for retrieving clinical data counts + * @param getClinicalAttributesForStudiesUseCase the use case for retrieving clinical attributes + * for studies + * @param getFilteredSamplesCountUseCase the use case for retrieving filtered sample counts + * @param getFilteredPatientCountUseCase the use case for retrieving filtered patient counts + */ + public GetClinicalDataCountsUseCase( + ClinicalDataRepository clinicalDataRepository, + GetClinicalAttributesForStudiesUseCase getClinicalAttributesForStudiesUseCase, + GetFilteredSamplesCountUseCase getFilteredSamplesCountUseCase, + GetFilteredPatientCountUseCase getFilteredPatientCountUseCase) { + this.clinicalDataRepository = clinicalDataRepository; + this.getClinicalAttributesForStudiesUseCase = getClinicalAttributesForStudiesUseCase; + this.getFilteredSamplesCountUseCase = getFilteredSamplesCountUseCase; + this.getFilteredPatientCountUseCase = getFilteredPatientCountUseCase; + } + + /** + * Executes the use case to retrieve and process clinical data counts. It normalizes the data + * counts and ensures that missing attributes are restored. + * + * @param studyViewFilterContext the context of the study view filter to apply + * @param filteredAttributes a list of filtered clinical attribute IDs + * @return a list of {@link ClinicalDataCountItem} containing the normalized and complete clinical + * data counts + */ + public List execute( + StudyViewFilterContext studyViewFilterContext, List filteredAttributes) { + + List involvedCancerStudies = studyViewFilterContext.customDataFilterCancerStudies(); + + var result = + clinicalDataRepository.getClinicalDataCounts(studyViewFilterContext, filteredAttributes); + + // Normalize data counts so that values like TRUE, True, and true are all merged in one count + result.forEach( + item -> item.setCounts(StudyViewColumnarServiceUtil.normalizeDataCounts(item.getCounts()))); + + // attributes may be missing in result set because they have been filtered out + // e.g. if the filtered samples happen to have no SEX data, they will not appear in the list + // even though the inferred value of those attributes is NA + // the following code restores these counts for missing attributes + if (result.size() != filteredAttributes.size()) { + var attributes = + getClinicalAttributesForStudiesUseCase.execute(involvedCancerStudies).stream() + .filter(attribute -> filteredAttributes.contains(attribute.getAttrId())) + .toList(); + + Integer filteredSampleCount = getFilteredSamplesCountUseCase.execute(studyViewFilterContext); + Integer filteredPatientCount = getFilteredPatientCountUseCase.execute(studyViewFilterContext); + + result = + StudyViewColumnarServiceUtil.addClinicalDataCountsForMissingAttributes( + result, attributes, filteredSampleCount, filteredPatientCount); + } + + return StudyViewColumnarServiceUtil.mergeClinicalDataCounts(result); + } +} diff --git a/src/main/java/org/cbioportal/domain/clinical_data/usecase/GetClinicalDataForXyPlotUseCase.java b/src/main/java/org/cbioportal/domain/clinical_data/usecase/GetClinicalDataForXyPlotUseCase.java new file mode 100644 index 00000000000..709e824c73c --- /dev/null +++ b/src/main/java/org/cbioportal/domain/clinical_data/usecase/GetClinicalDataForXyPlotUseCase.java @@ -0,0 +1,168 @@ +package org.cbioportal.domain.clinical_data.usecase; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import org.cbioportal.domain.sample.Sample; +import org.cbioportal.domain.sample.usecase.GetFilteredSamplesUseCase; +import org.cbioportal.domain.studyview.StudyViewFilterContext; +import org.cbioportal.legacy.model.ClinicalData; +import org.springframework.context.annotation.Profile; +import org.springframework.stereotype.Service; + +@Service +@Profile("clickhouse") +/** + * Use case for retrieving and combining clinical data for an XY plot. This class orchestrates the + * fetching of clinical data for both patients and samples, then combines them based on the provided + * context and filter options, preparing them for XY plot visualization. + */ +public class GetClinicalDataForXyPlotUseCase { + + private final GetPatientClinicalDataUseCase getPatientClinicalDataUseCase; + private final GetSampleClinicalDataUseCase getSampleClinicalDataUseCase; + private final GetFilteredSamplesUseCase getFilteredSamplesUseCase; + + /** + * Constructs a {@code GetClinicalDataForXyPlotUseCase} with the provided use cases. + * + * @param getPatientClinicalDataUseCase the use case for retrieving patient clinical data + * @param getSampleClinicalDataUseCase the use case for retrieving sample clinical data + * @param getFilteredSamplesUseCase the use case for filtering samples + */ + public GetClinicalDataForXyPlotUseCase( + GetPatientClinicalDataUseCase getPatientClinicalDataUseCase, + GetSampleClinicalDataUseCase getSampleClinicalDataUseCase, + GetFilteredSamplesUseCase getFilteredSamplesUseCase) { + this.getPatientClinicalDataUseCase = getPatientClinicalDataUseCase; + this.getSampleClinicalDataUseCase = getSampleClinicalDataUseCase; + this.getFilteredSamplesUseCase = getFilteredSamplesUseCase; + } + + /** + * Executes the use case to retrieve and combine clinical data for an XY plot. + * + * @param studyViewFilterContext the context of the study view filter to apply + * @param attributeIds a list of attribute IDs to filter the clinical data + * @param shouldFilterNonEmptyClinicalData flag indicating whether to filter out clinical data + * with empty values + * @return a list of {@link ClinicalData} ready for XY plot visualization + */ + public List execute( + StudyViewFilterContext studyViewFilterContext, + List attributeIds, + boolean shouldFilterNonEmptyClinicalData) { + + List sampleClinicalDataList = + getSampleClinicalDataUseCase.execute(studyViewFilterContext, attributeIds); + List patientClinicalDataList = + getPatientClinicalDataUseCase.execute(studyViewFilterContext, attributeIds); + + List samples = List.of(); + + if (!patientClinicalDataList.isEmpty()) { + // fetch samples for the given study view filter. + // we need this to construct the complete patient to sample map. + samples = getFilteredSamplesUseCase.execute(studyViewFilterContext); + } + + return combineClinicalDataForXyPlot( + sampleClinicalDataList, patientClinicalDataList, samples, shouldFilterNonEmptyClinicalData); + } + + /** + * Combines the clinical data for samples and patients into a single list, optionally filtering + * non-empty data. + * + * @param sampleClinicalDataList a list of clinical data for samples + * @param patientClinicalDataList a list of clinical data for patients + * @param samples a list of samples to map patient data to + * @param shouldFilterNonEmptyClinicalData flag indicating whether to filter out clinical data + * with empty values + * @return a list of combined {@link ClinicalData} for XY plot visualization + */ + private List combineClinicalDataForXyPlot( + List sampleClinicalDataList, + List patientClinicalDataList, + List samples, + boolean shouldFilterNonEmptyClinicalData) { + + List combinedClinicalDataList; + + if (shouldFilterNonEmptyClinicalData) { + sampleClinicalDataList = filterNonEmptyClinicalData(sampleClinicalDataList); + patientClinicalDataList = filterNonEmptyClinicalData(patientClinicalDataList); + } + + if (patientClinicalDataList.isEmpty()) { + combinedClinicalDataList = sampleClinicalDataList; + } else { + combinedClinicalDataList = + Stream.concat( + sampleClinicalDataList.stream(), + convertPatientClinicalDataToSampleClinicalData(patientClinicalDataList, samples) + .stream()) + .toList(); + } + + return combinedClinicalDataList; + } + + /** + * Filters out clinical data items with empty attribute values. + * + * @param clinicalData the list of clinical data to filter + * @return a filtered list of {@link ClinicalData} containing only non-empty attribute values + */ + private List filterNonEmptyClinicalData(List clinicalData) { + return clinicalData.stream().filter(data -> !data.getAttrValue().isEmpty()).toList(); + } + + /** + * Converts patient clinical data into sample clinical data, mapping each patient to their + * corresponding samples. + * + * @param patientClinicalDataList a list of clinical data for patients + * @param samplesWithoutNumericalFilter a list of samples to map patient data to + * @return a list of {@link ClinicalData} representing the patient's clinical data in sample form + */ + private List convertPatientClinicalDataToSampleClinicalData( + List patientClinicalDataList, List samplesWithoutNumericalFilter) { + + List sampleClinicalDataList = new ArrayList<>(); + + Map>> patientToSamples = + samplesWithoutNumericalFilter.stream() + .collect( + Collectors.groupingBy( + Sample::patientStableId, Collectors.groupingBy(Sample::cancerStudyIdentifier))); + + // Put all clinical data into sample form + for (ClinicalData d : patientClinicalDataList) { + List samplesForPatient = patientToSamples.get(d.getPatientId()).get(d.getStudyId()); + if (samplesForPatient != null) { + for (Sample s : samplesForPatient) { + ClinicalData newData = new ClinicalData(); + + newData.setInternalId(s.internalId()); + newData.setAttrId(d.getAttrId()); + newData.setPatientId(d.getPatientId()); + newData.setStudyId(d.getStudyId()); + newData.setAttrValue(d.getAttrValue()); + newData.setSampleId(s.stableId()); + + sampleClinicalDataList.add(newData); + } + } else { + // TODO: Ignoring for now rather than throwing an error + // patient has no samples - this shouldn't happen and could affect the integrity + // of the data analysis + // return new ResponseEntity<>(null, HttpStatus.INTERNAL_SERVER_ERROR); + } + } + + return sampleClinicalDataList; + } +} diff --git a/src/main/java/org/cbioportal/domain/clinical_data/usecase/GetPatientClinicalDataUseCase.java b/src/main/java/org/cbioportal/domain/clinical_data/usecase/GetPatientClinicalDataUseCase.java new file mode 100644 index 00000000000..190602cdc36 --- /dev/null +++ b/src/main/java/org/cbioportal/domain/clinical_data/usecase/GetPatientClinicalDataUseCase.java @@ -0,0 +1,42 @@ +package org.cbioportal.domain.clinical_data.usecase; + +import java.util.List; +import org.cbioportal.domain.clinical_data.repository.ClinicalDataRepository; +import org.cbioportal.domain.studyview.StudyViewFilterContext; +import org.cbioportal.legacy.model.ClinicalData; +import org.springframework.context.annotation.Profile; +import org.springframework.stereotype.Service; + +@Service +@Profile("clickhouse") +/** + * Use case for retrieving clinical data for a patient from the repository. This class encapsulates + * the business logic for fetching clinical data based on the provided study view filter context and + * filtered attributes. + */ +public class GetPatientClinicalDataUseCase { + + private final ClinicalDataRepository clinicalDataRepository; + + /** + * Constructs a {@code GetPatientClinicalDataUseCase} with the provided repository. + * + * @param clinicalDataRepository the repository to be used for fetching patient clinical data + */ + public GetPatientClinicalDataUseCase(ClinicalDataRepository clinicalDataRepository) { + this.clinicalDataRepository = clinicalDataRepository; + } + + /** + * Executes the use case to retrieve clinical data for a patient. + * + * @param studyViewFilterContext the context of the study view filter to apply + * @param filteredAttributes a list of attributes to filter the clinical data + * @return a list of {@link ClinicalData} representing the patient's clinical data + */ + public List execute( + StudyViewFilterContext studyViewFilterContext, List filteredAttributes) { + return clinicalDataRepository.getPatientClinicalData( + studyViewFilterContext, filteredAttributes); + } +} diff --git a/src/main/java/org/cbioportal/domain/clinical_data/usecase/GetSampleClinicalDataUseCase.java b/src/main/java/org/cbioportal/domain/clinical_data/usecase/GetSampleClinicalDataUseCase.java new file mode 100644 index 00000000000..36e9bb65e33 --- /dev/null +++ b/src/main/java/org/cbioportal/domain/clinical_data/usecase/GetSampleClinicalDataUseCase.java @@ -0,0 +1,41 @@ +package org.cbioportal.domain.clinical_data.usecase; + +import java.util.List; +import org.cbioportal.domain.clinical_data.repository.ClinicalDataRepository; +import org.cbioportal.domain.studyview.StudyViewFilterContext; +import org.cbioportal.legacy.model.ClinicalData; +import org.springframework.context.annotation.Profile; +import org.springframework.stereotype.Service; + +@Service +@Profile("clickhouse") +/** + * Use case for retrieving clinical data for a sample from the repository. This class encapsulates + * the business logic for fetching clinical data based on the provided study view filter context and + * filtered attributes. + */ +public class GetSampleClinicalDataUseCase { + + private final ClinicalDataRepository clinicalDataRepository; + + /** + * Constructs a {@code GetSampleClinicalDataUseCase} with the provided repository. + * + * @param clinicalDataRepository the repository to be used for fetching sample clinical data + */ + public GetSampleClinicalDataUseCase(ClinicalDataRepository clinicalDataRepository) { + this.clinicalDataRepository = clinicalDataRepository; + } + + /** + * Executes the use case to retrieve clinical data for a sample. + * + * @param studyViewFilterContext the context of the study view filter to apply + * @param filteredAttributes a list of attributes to filter the clinical data + * @return a list of {@link ClinicalData} representing the sample's clinical data + */ + public List execute( + StudyViewFilterContext studyViewFilterContext, List filteredAttributes) { + return clinicalDataRepository.getSampleClinicalData(studyViewFilterContext, filteredAttributes); + } +} diff --git a/src/main/java/org/cbioportal/domain/clinical_event/repository/ClinicalEventRepository.java b/src/main/java/org/cbioportal/domain/clinical_event/repository/ClinicalEventRepository.java new file mode 100644 index 00000000000..e008fa690c0 --- /dev/null +++ b/src/main/java/org/cbioportal/domain/clinical_event/repository/ClinicalEventRepository.java @@ -0,0 +1,20 @@ +package org.cbioportal.domain.clinical_event.repository; + +import java.util.List; +import org.cbioportal.domain.studyview.StudyViewFilterContext; +import org.cbioportal.legacy.model.ClinicalEventTypeCount; + +/** Repository interface for retrieving clinical events and related data. */ +public interface ClinicalEventRepository { + + /** + * Retrieves counts of different clinical event types based on the given study view filter + * context. + * + * @param studyViewFilterContext The filter criteria for the study view. + * @return A list of {@link ClinicalEventTypeCount} representing the counts of clinical event + * types. + */ + List getClinicalEventTypeCounts( + StudyViewFilterContext studyViewFilterContext); +} diff --git a/src/main/java/org/cbioportal/domain/clinical_event/usecase/GetClinicalEventTypeCountsUseCase.java b/src/main/java/org/cbioportal/domain/clinical_event/usecase/GetClinicalEventTypeCountsUseCase.java new file mode 100644 index 00000000000..9e1742609cc --- /dev/null +++ b/src/main/java/org/cbioportal/domain/clinical_event/usecase/GetClinicalEventTypeCountsUseCase.java @@ -0,0 +1,40 @@ +package org.cbioportal.domain.clinical_event.usecase; + +import java.util.List; +import org.cbioportal.domain.clinical_event.repository.ClinicalEventRepository; +import org.cbioportal.domain.studyview.StudyViewFilterContext; +import org.cbioportal.legacy.model.ClinicalEventTypeCount; +import org.springframework.context.annotation.Profile; +import org.springframework.stereotype.Service; + +@Service +@Profile("clickhouse") +/** + * Use case for retrieving counts of different clinical event types. This class interacts with the + * {@link ClinicalEventRepository} to fetch the required data. + */ +public class GetClinicalEventTypeCountsUseCase { + + private final ClinicalEventRepository clinicalEventRepository; + + /** + * Constructs a use case for retrieving clinical event type counts. + * + * @param clinicalEventRepository The repository used to fetch clinical event type counts. + */ + public GetClinicalEventTypeCountsUseCase(ClinicalEventRepository clinicalEventRepository) { + this.clinicalEventRepository = clinicalEventRepository; + } + + /** + * Executes the use case to retrieve counts of different clinical event types based on the study + * view filter context. + * + * @param studyViewFilterContext The filter criteria for the study view. + * @return A list of {@link ClinicalEventTypeCount} representing the counts of clinical event + * types. + */ + public List execute(StudyViewFilterContext studyViewFilterContext) { + return this.clinicalEventRepository.getClinicalEventTypeCounts(studyViewFilterContext); + } +} diff --git a/src/main/java/org/cbioportal/domain/generic_assay/repository/GenericAssayRepository.java b/src/main/java/org/cbioportal/domain/generic_assay/repository/GenericAssayRepository.java new file mode 100644 index 00000000000..f28c093afba --- /dev/null +++ b/src/main/java/org/cbioportal/domain/generic_assay/repository/GenericAssayRepository.java @@ -0,0 +1,55 @@ +package org.cbioportal.domain.generic_assay.repository; + +import java.util.List; +import org.cbioportal.domain.studyview.StudyViewFilterContext; +import org.cbioportal.legacy.model.ClinicalDataCount; +import org.cbioportal.legacy.model.GenericAssayDataCountItem; +import org.cbioportal.legacy.model.MolecularProfile; +import org.cbioportal.legacy.web.parameter.GenericAssayDataBinFilter; +import org.cbioportal.legacy.web.parameter.GenericAssayDataFilter; + +/** Repository interface for retrieving molecular profiles and assay-related data. */ +public interface GenericAssayRepository { + + /** + * Retrieves all generic assay molecular profiles. + * + * @return A list of {@link MolecularProfile} representing generic assay profiles. + */ + List getGenericAssayProfiles(); + + /** + * Retrieves molecular profiles filtered by alteration type based on the study view filter + * context. + * + * @param studyViewFilterContext The filter criteria for the study view. + * @param alterationType The type of alteration to filter the molecular profiles. + * @return A list of {@link MolecularProfile} matching the criteria. + */ + List getFilteredMolecularProfilesByAlterationType( + StudyViewFilterContext studyViewFilterContext, String alterationType); + + /** + * Retrieves bin counts for generic assay data based on the study view filter context and + * specified bin filters. + * + * @param studyViewFilterContext The filter criteria for the study view. + * @param genericAssayDataBinFilters A list of bin filters to apply to the assay data. + * @return A list of {@link ClinicalDataCount} representing bin counts for the generic assay data. + */ + List getGenericAssayDataBinCounts( + StudyViewFilterContext studyViewFilterContext, + List genericAssayDataBinFilters); + + /** + * Retrieves counts for generic assay data based on the study view filter context and specified + * data filters. + * + * @param studyViewFilterContext The filter criteria for the study view. + * @param genericAssayDataFilters A list of data filters to apply to the assay data. + * @return A list of {@link GenericAssayDataCountItem} representing assay data counts. + */ + List getGenericAssayDataCounts( + StudyViewFilterContext studyViewFilterContext, + List genericAssayDataFilters); +} diff --git a/src/main/java/org/cbioportal/domain/generic_assay/usecase/GenericAssayUseCases.java b/src/main/java/org/cbioportal/domain/generic_assay/usecase/GenericAssayUseCases.java new file mode 100644 index 00000000000..c0cd907c2a1 --- /dev/null +++ b/src/main/java/org/cbioportal/domain/generic_assay/usecase/GenericAssayUseCases.java @@ -0,0 +1,24 @@ +package org.cbioportal.domain.generic_assay.usecase; + +import org.springframework.context.annotation.Profile; +import org.springframework.stereotype.Service; + +@Service +@Profile("clickhouse") +/** + * A record representing a collection of use cases related to generic assay data operations. This + * record encapsulates instances of various use case classes, providing a centralized way to access + * and manage them. + * + * @param getFilteredMolecularProfilesByAlterationType the use case for retrieving molecular + * profiles filtered by alteration type. + * @param getGenericAssayDataBinCounts the use case for retrieving binned counts of generic assay + * data. + * @param getGenericAssayDataCountsUseCase the use case for retrieving counts of generic assay data. + * @param getGenericAssayProfilesUseCase the use case for retrieving generic assay profiles. + */ +public record GenericAssayUseCases( + GetFilteredMolecularProfilesByAlterationType getFilteredMolecularProfilesByAlterationType, + GetGenericAssayDataBinCounts getGenericAssayDataBinCounts, + GetGenericAssayDataCountsUseCase getGenericAssayDataCountsUseCase, + GetGenericAssayProfilesUseCase getGenericAssayProfilesUseCase) {} diff --git a/src/main/java/org/cbioportal/domain/generic_assay/usecase/GetFilteredMolecularProfilesByAlterationType.java b/src/main/java/org/cbioportal/domain/generic_assay/usecase/GetFilteredMolecularProfilesByAlterationType.java new file mode 100644 index 00000000000..a039ecec4c9 --- /dev/null +++ b/src/main/java/org/cbioportal/domain/generic_assay/usecase/GetFilteredMolecularProfilesByAlterationType.java @@ -0,0 +1,47 @@ +package org.cbioportal.domain.generic_assay.usecase; + +import java.util.List; +import org.cbioportal.domain.generic_assay.repository.GenericAssayRepository; +import org.cbioportal.domain.studyview.StudyViewFilterContext; +import org.cbioportal.legacy.model.MolecularProfile; +import org.springframework.context.annotation.Profile; +import org.springframework.stereotype.Service; + +@Service +@Profile("clickhouse") +/** + * A use case class responsible for retrieving molecular profiles filtered by a specific alteration + * type. This class acts as an intermediary between the application logic and the data repository, + * delegating the data retrieval to the {@link GenericAssayRepository}. + */ +public class GetFilteredMolecularProfilesByAlterationType { + private final GenericAssayRepository genericAssayRepository; + + /** + * Constructs a new instance of {@link GetFilteredMolecularProfilesByAlterationType}. + * + * @param genericAssayRepository the repository used to access molecular profile data. Must not be + * {@code null}. + */ + public GetFilteredMolecularProfilesByAlterationType( + GenericAssayRepository genericAssayRepository) { + this.genericAssayRepository = genericAssayRepository; + } + + /** + * Executes the use case to retrieve molecular profiles filtered by a specific alteration type. + * + * @param studyViewFilterContext the context containing study view filter criteria. Must not be + * {@code null}. + * @param alterationType the type of alteration used to filter molecular profiles. Must not be + * {@code null}. + * @return a list of {@link MolecularProfile} objects representing the molecular profiles that + * match the provided alteration type. The list may be empty if no profiles match the + * criteria. + */ + public List execute( + StudyViewFilterContext studyViewFilterContext, String alterationType) { + return genericAssayRepository.getFilteredMolecularProfilesByAlterationType( + studyViewFilterContext, alterationType); + } +} diff --git a/src/main/java/org/cbioportal/domain/generic_assay/usecase/GetGenericAssayDataBinCounts.java b/src/main/java/org/cbioportal/domain/generic_assay/usecase/GetGenericAssayDataBinCounts.java new file mode 100644 index 00000000000..ba8adab8db0 --- /dev/null +++ b/src/main/java/org/cbioportal/domain/generic_assay/usecase/GetGenericAssayDataBinCounts.java @@ -0,0 +1,49 @@ +package org.cbioportal.domain.generic_assay.usecase; + +import java.util.List; +import org.cbioportal.domain.generic_assay.repository.GenericAssayRepository; +import org.cbioportal.domain.studyview.StudyViewFilterContext; +import org.cbioportal.legacy.model.ClinicalDataCount; +import org.cbioportal.legacy.web.parameter.GenericAssayDataBinFilter; +import org.springframework.context.annotation.Profile; +import org.springframework.stereotype.Service; + +@Service +@Profile("clickhouse") +/** + * A use case class responsible for retrieving binned counts of generic assay data based on the + * provided filters. This class acts as an intermediary between the application logic and the data + * repository, delegating the data retrieval to the {@link GenericAssayRepository}. + */ +public class GetGenericAssayDataBinCounts { + private final GenericAssayRepository genericAssayRepository; + + /** + * Constructs a new instance of {@link GetGenericAssayDataBinCounts}. + * + * @param genericAssayRepository the repository used to access generic assay data. Must not be + * {@code null}. + */ + public GetGenericAssayDataBinCounts(GenericAssayRepository genericAssayRepository) { + this.genericAssayRepository = genericAssayRepository; + } + + /** + * Executes the use case to retrieve binned counts of generic assay data based on the provided + * filters. + * + * @param studyViewFilterContext the context containing study view filter criteria. Must not be + * {@code null}. + * @param genericAssayDataBinFilters a list of filters to apply to the generic assay data for + * binning. Must not be {@code null}. + * @return a list of {@link ClinicalDataCount} objects representing the binned counts of generic + * assay data that match the provided filters. The list may be empty if no data matches the + * filters. + */ + public List execute( + StudyViewFilterContext studyViewFilterContext, + List genericAssayDataBinFilters) { + return genericAssayRepository.getGenericAssayDataBinCounts( + studyViewFilterContext, genericAssayDataBinFilters); + } +} diff --git a/src/main/java/org/cbioportal/domain/generic_assay/usecase/GetGenericAssayDataCountsUseCase.java b/src/main/java/org/cbioportal/domain/generic_assay/usecase/GetGenericAssayDataCountsUseCase.java new file mode 100644 index 00000000000..94cac7e9bbf --- /dev/null +++ b/src/main/java/org/cbioportal/domain/generic_assay/usecase/GetGenericAssayDataCountsUseCase.java @@ -0,0 +1,48 @@ +package org.cbioportal.domain.generic_assay.usecase; + +import java.util.List; +import org.cbioportal.domain.generic_assay.repository.GenericAssayRepository; +import org.cbioportal.domain.studyview.StudyViewFilterContext; +import org.cbioportal.legacy.model.GenericAssayDataCountItem; +import org.cbioportal.legacy.web.parameter.GenericAssayDataFilter; +import org.springframework.context.annotation.Profile; +import org.springframework.stereotype.Service; + +@Service +@Profile("clickhouse") +/** + * A use case class responsible for retrieving counts of generic assay data based on the provided + * filters. This class acts as an intermediary between the application logic and the data + * repository, delegating the data retrieval to the {@link GenericAssayRepository}. + */ +public class GetGenericAssayDataCountsUseCase { + private final GenericAssayRepository genericAssayRepository; + + /** + * Constructs a new instance of {@link GetGenericAssayDataCountsUseCase}. + * + * @param genericAssayRepository the repository used to access generic assay data. Must not be + * {@code null}. + */ + public GetGenericAssayDataCountsUseCase(GenericAssayRepository genericAssayRepository) { + this.genericAssayRepository = genericAssayRepository; + } + + /** + * Executes the use case to retrieve counts of generic assay data based on the provided filters. + * + * @param studyViewFilterContext the context containing study view filter criteria. Must not be + * {@code null}. + * @param genericAssayDataFilters a list of filters to apply to the generic assay data. Must not + * be {@code null}. + * @return a list of {@link GenericAssayDataCountItem} objects representing the counts of generic + * assay data that match the provided filters. The list may be empty if no data matches the + * filters. + */ + public List execute( + StudyViewFilterContext studyViewFilterContext, + List genericAssayDataFilters) { + return genericAssayRepository.getGenericAssayDataCounts( + studyViewFilterContext, genericAssayDataFilters); + } +} diff --git a/src/main/java/org/cbioportal/domain/generic_assay/usecase/GetGenericAssayProfilesUseCase.java b/src/main/java/org/cbioportal/domain/generic_assay/usecase/GetGenericAssayProfilesUseCase.java new file mode 100644 index 00000000000..f1d1c645782 --- /dev/null +++ b/src/main/java/org/cbioportal/domain/generic_assay/usecase/GetGenericAssayProfilesUseCase.java @@ -0,0 +1,36 @@ +package org.cbioportal.domain.generic_assay.usecase; + +import java.util.List; +import org.cbioportal.domain.generic_assay.repository.GenericAssayRepository; +import org.cbioportal.legacy.model.MolecularProfile; +import org.springframework.context.annotation.Profile; +import org.springframework.stereotype.Service; + +@Service +@Profile("clickhouse") +/** + * Use case for retrieving generic assay molecular profiles. This class interacts with the {@link + * GenericAssayRepository} to fetch the required data. + */ +public class GetGenericAssayProfilesUseCase { + + private final GenericAssayRepository repository; + + /** + * Constructs a use case for retrieving generic assay profiles. + * + * @param repository The repository used to fetch generic assay profiles. + */ + public GetGenericAssayProfilesUseCase(GenericAssayRepository repository) { + this.repository = repository; + } + + /** + * Executes the use case to retrieve all generic assay profiles. + * + * @return A list of {@link MolecularProfile} representing generic assay profiles. + */ + public List execute() { + return repository.getGenericAssayProfiles(); + } +} diff --git a/src/main/java/org/cbioportal/domain/genomic_data/repository/GenomicDataRepository.java b/src/main/java/org/cbioportal/domain/genomic_data/repository/GenomicDataRepository.java new file mode 100644 index 00000000000..0c7509ce104 --- /dev/null +++ b/src/main/java/org/cbioportal/domain/genomic_data/repository/GenomicDataRepository.java @@ -0,0 +1,83 @@ +package org.cbioportal.domain.genomic_data.repository; + +import java.util.List; +import java.util.Map; +import org.cbioportal.domain.studyview.StudyViewFilterContext; +import org.cbioportal.legacy.model.ClinicalDataCount; +import org.cbioportal.legacy.model.GenomicDataCount; +import org.cbioportal.legacy.model.GenomicDataCountItem; +import org.cbioportal.legacy.web.parameter.GenomicDataBinFilter; +import org.cbioportal.legacy.web.parameter.GenomicDataFilter; + +/** + * An interface defining the contract for a repository that provides access to genomic data. This + * repository is responsible for retrieving various types of genomic data counts and statistics. + */ +public interface GenomicDataRepository { + + /** + * Retrieves the sample counts for molecular profiles based on the provided study view filter + * context. + * + * @param studyViewFilterContext the context containing study view filter criteria. Must not be + * {@code null}. + * @return a list of {@link GenomicDataCount} objects representing the sample counts for molecular + * profiles. + */ + List getMolecularProfileSampleCounts( + StudyViewFilterContext studyViewFilterContext); + + /** + * Retrieves binned genomic data counts based on the provided study view filter context and bin + * filters. + * + * @param studyViewFilterContext the context containing study view filter criteria. Must not be + * {@code null}. + * @param genomicDataBinFilters a list of filters to apply to the genomic data for binning. Must + * not be {@code null}. + * @return a list of {@link ClinicalDataCount} objects representing the binned genomic data + * counts. + */ + List getGenomicDataBinCounts( + StudyViewFilterContext studyViewFilterContext, + List genomicDataBinFilters); + + /** + * Retrieves copy number alteration (CNA) counts based on the provided study view filter context + * and genomic data filters. + * + * @param studyViewFilterContext the context containing study view filter criteria. Must not be + * {@code null}. + * @param genomicDataFilters a list of filters to apply to the genomic data. Must not be {@code + * null}. + * @return a list of {@link GenomicDataCountItem} objects representing the CNA counts. + */ + List getCNACounts( + StudyViewFilterContext studyViewFilterContext, List genomicDataFilters); + + /** + * Retrieves mutation counts based on the provided study view filter context and mutation filters. + * + * @param studyViewFilterContext the context containing study view filter criteria. Must not be + * {@code null}. + * @param mutationFilters the filter to apply to the mutation data. Must not be {@code null}. + * @return a map where the key is a string representing a mutation type and the value is the count + * of mutations. + */ + Map getMutationCounts( + StudyViewFilterContext studyViewFilterContext, GenomicDataFilter mutationFilters); + + /** + * Retrieves mutation counts grouped by mutation type based on the provided study view filter + * context and genomic data filters. + * + * @param studyViewFilterContext the context containing study view filter criteria. Must not be + * {@code null}. + * @param genomicDataFilters a list of filters to apply to the genomic data. Must not be {@code + * null}. + * @return a list of {@link GenomicDataCountItem} objects representing the mutation counts by + * type. + */ + List getMutationCountsByType( + StudyViewFilterContext studyViewFilterContext, List genomicDataFilters); +} diff --git a/src/main/java/org/cbioportal/domain/genomic_data/usecase/GenomicDataUseCases.java b/src/main/java/org/cbioportal/domain/genomic_data/usecase/GenomicDataUseCases.java new file mode 100644 index 00000000000..5db8f7720e1 --- /dev/null +++ b/src/main/java/org/cbioportal/domain/genomic_data/usecase/GenomicDataUseCases.java @@ -0,0 +1,26 @@ +package org.cbioportal.domain.genomic_data.usecase; + +import org.springframework.context.annotation.Profile; +import org.springframework.stereotype.Service; + +@Service +@Profile("clickhouse") +/** + * A record representing a collection of use cases related to genomic data operations. This record + * encapsulates instances of various genomic data use cases, providing a centralized way to access + * and manage them. + * + * @param getCNACountsByGeneSpecificUseCase the use case for retrieving CNA counts by gene-specific + * data. + * @param getGenomicDataBinCountsUseCase the use case for retrieving genomic data bin counts. + * @param getMolecularProfileSampleCountsUseCase the use case for retrieving molecular profile + * sample counts. + * @param getMutationCountsByTypeUseCase the use case for retrieving mutation counts by type. + * @param getMutationCountsUseCase the use case for retrieving mutation counts. + */ +public record GenomicDataUseCases( + GetCNACountsByGeneSpecificUseCase getCNACountsByGeneSpecificUseCase, + GetGenomicDataBinCountsUseCase getGenomicDataBinCountsUseCase, + GetMolecularProfileSampleCountsUseCase getMolecularProfileSampleCountsUseCase, + GetMutationCountsByTypeUseCase getMutationCountsByTypeUseCase, + GetMutationCountsUseCase getMutationCountsUseCase) {} diff --git a/src/main/java/org/cbioportal/domain/genomic_data/usecase/GetCNACountsByGeneSpecificUseCase.java b/src/main/java/org/cbioportal/domain/genomic_data/usecase/GetCNACountsByGeneSpecificUseCase.java new file mode 100644 index 00000000000..d0c51f1e2b1 --- /dev/null +++ b/src/main/java/org/cbioportal/domain/genomic_data/usecase/GetCNACountsByGeneSpecificUseCase.java @@ -0,0 +1,42 @@ +package org.cbioportal.domain.genomic_data.usecase; + +import java.util.List; +import org.cbioportal.domain.genomic_data.repository.GenomicDataRepository; +import org.cbioportal.domain.studyview.StudyViewFilterContext; +import org.cbioportal.legacy.model.GenomicDataCountItem; +import org.cbioportal.legacy.web.parameter.GenomicDataFilter; +import org.springframework.context.annotation.Profile; +import org.springframework.stereotype.Service; + +@Service +@Profile("clickhouse") +/** + * Use case for retrieving CNA counts by gene-specific data from the repository. This class + * encapsulates the business logic for fetching CNA counts based on the provided study view filter + * context and genomic data filters. + */ +public class GetCNACountsByGeneSpecificUseCase { + + private final GenomicDataRepository repository; + + /** + * Constructs a {@code GetCNACountsByGeneSpecificUseCase} with the provided repository. + * + * @param repository the repository to be used for fetching CNA counts by gene-specific data + */ + public GetCNACountsByGeneSpecificUseCase(GenomicDataRepository repository) { + this.repository = repository; + } + + /** + * Executes the use case to retrieve CNA counts by gene-specific data. + * + * @param studyViewFilterContext the context of the study view filter to apply + * @param genomicDataFilters a list of genomic data filters to apply + * @return a list of {@link GenomicDataCountItem} representing the CNA counts by gene + */ + public List execute( + StudyViewFilterContext studyViewFilterContext, List genomicDataFilters) { + return repository.getCNACounts(studyViewFilterContext, genomicDataFilters); + } +} diff --git a/src/main/java/org/cbioportal/domain/genomic_data/usecase/GetGenomicDataBinCountsUseCase.java b/src/main/java/org/cbioportal/domain/genomic_data/usecase/GetGenomicDataBinCountsUseCase.java new file mode 100644 index 00000000000..1a35151e0ad --- /dev/null +++ b/src/main/java/org/cbioportal/domain/genomic_data/usecase/GetGenomicDataBinCountsUseCase.java @@ -0,0 +1,44 @@ +package org.cbioportal.domain.genomic_data.usecase; + +import java.util.List; +import org.cbioportal.domain.genomic_data.repository.GenomicDataRepository; +import org.cbioportal.domain.studyview.StudyViewFilterContext; +import org.cbioportal.legacy.model.ClinicalDataCount; +import org.cbioportal.legacy.web.parameter.GenomicDataBinFilter; +import org.springframework.context.annotation.Profile; +import org.springframework.stereotype.Service; + +@Service +@Profile("clickhouse") +/** + * Use case for retrieving genomic data bin counts from the repository. This class encapsulates the + * business logic for fetching genomic data bin counts based on the provided study view filter + * context and genomic data filters. + */ +public class GetGenomicDataBinCountsUseCase { + + private final GenomicDataRepository genomicDataRepository; + + /** + * Constructs a {@code GetGenomicDataBinCountsUseCase} with the provided repository. + * + * @param genomicDataRepository the repository to be used for fetching genomic data bin counts + */ + public GetGenomicDataBinCountsUseCase(GenomicDataRepository genomicDataRepository) { + this.genomicDataRepository = genomicDataRepository; + } + + /** + * Executes the use case to retrieve genomic data bin counts. + * + * @param studyViewFilterContext the context of the study view filter to apply + * @param genomicDataFilters a list of genomic data bin filters to apply + * @return a list of {@link ClinicalDataCount} representing the genomic data bin counts + */ + public List execute( + StudyViewFilterContext studyViewFilterContext, + List genomicDataFilters) { + return genomicDataRepository.getGenomicDataBinCounts( + studyViewFilterContext, genomicDataFilters); + } +} diff --git a/src/main/java/org/cbioportal/domain/genomic_data/usecase/GetMolecularProfileSampleCountsUseCase.java b/src/main/java/org/cbioportal/domain/genomic_data/usecase/GetMolecularProfileSampleCountsUseCase.java new file mode 100644 index 00000000000..0816b64f931 --- /dev/null +++ b/src/main/java/org/cbioportal/domain/genomic_data/usecase/GetMolecularProfileSampleCountsUseCase.java @@ -0,0 +1,42 @@ +package org.cbioportal.domain.genomic_data.usecase; + +import java.util.List; +import org.cbioportal.domain.genomic_data.repository.GenomicDataRepository; +import org.cbioportal.domain.studyview.StudyViewFilterContext; +import org.cbioportal.legacy.model.GenomicDataCount; +import org.cbioportal.legacy.service.util.StudyViewColumnarServiceUtil; +import org.springframework.context.annotation.Profile; +import org.springframework.stereotype.Service; + +@Service +@Profile("clickhouse") +/** + * Use case for retrieving molecular profile sample counts from the repository. This class + * encapsulates the business logic for fetching molecular profile sample counts and merging them + * into a final result. + */ +public class GetMolecularProfileSampleCountsUseCase { + + private final GenomicDataRepository genomicDataRepository; + + /** + * Constructs a {@code GetMolecularProfileSampleCountsUseCase} with the provided repository. + * + * @param genomicDataRepository the repository to be used for fetching molecular profile sample + * counts + */ + public GetMolecularProfileSampleCountsUseCase(GenomicDataRepository genomicDataRepository) { + this.genomicDataRepository = genomicDataRepository; + } + + /** + * Executes the use case to retrieve and merge molecular profile sample counts. + * + * @param studyViewFilterContext the context of the study view filter to apply + * @return a list of {@link GenomicDataCount} representing the molecular profile sample counts + */ + public List execute(StudyViewFilterContext studyViewFilterContext) { + return StudyViewColumnarServiceUtil.mergeGenomicDataCounts( + genomicDataRepository.getMolecularProfileSampleCounts(studyViewFilterContext)); + } +} diff --git a/src/main/java/org/cbioportal/domain/genomic_data/usecase/GetMutationCountsByTypeUseCase.java b/src/main/java/org/cbioportal/domain/genomic_data/usecase/GetMutationCountsByTypeUseCase.java new file mode 100644 index 00000000000..f6072ac0104 --- /dev/null +++ b/src/main/java/org/cbioportal/domain/genomic_data/usecase/GetMutationCountsByTypeUseCase.java @@ -0,0 +1,42 @@ +package org.cbioportal.domain.genomic_data.usecase; + +import java.util.List; +import org.cbioportal.domain.genomic_data.repository.GenomicDataRepository; +import org.cbioportal.domain.studyview.StudyViewFilterContext; +import org.cbioportal.legacy.model.GenomicDataCountItem; +import org.cbioportal.legacy.web.parameter.GenomicDataFilter; +import org.springframework.context.annotation.Profile; +import org.springframework.stereotype.Service; + +@Service +@Profile("clickhouse") +/** + * Use case for retrieving mutation counts by type from the repository. This class encapsulates the + * business logic for fetching mutation counts based on the provided study view filter context and + * genomic data filters. + */ +public class GetMutationCountsByTypeUseCase { + + private final GenomicDataRepository repository; + + /** + * Constructs a {@code GetMutationCountsByTypeUseCase} with the provided repository. + * + * @param repository the repository to be used for fetching mutation counts + */ + public GetMutationCountsByTypeUseCase(GenomicDataRepository repository) { + this.repository = repository; + } + + /** + * Executes the use case to retrieve mutation counts by type. + * + * @param studyViewFilterContext the context of the study view filter to apply + * @param genomicDataFilters a list of genomic data filters to apply + * @return a list of {@link GenomicDataCountItem} representing the mutation counts by type + */ + public List execute( + StudyViewFilterContext studyViewFilterContext, List genomicDataFilters) { + return repository.getMutationCountsByType(studyViewFilterContext, genomicDataFilters); + } +} diff --git a/src/main/java/org/cbioportal/domain/genomic_data/usecase/GetMutationCountsUseCase.java b/src/main/java/org/cbioportal/domain/genomic_data/usecase/GetMutationCountsUseCase.java new file mode 100644 index 00000000000..312316a85ff --- /dev/null +++ b/src/main/java/org/cbioportal/domain/genomic_data/usecase/GetMutationCountsUseCase.java @@ -0,0 +1,45 @@ +package org.cbioportal.domain.genomic_data.usecase; + +import java.util.Map; +import org.cbioportal.domain.genomic_data.repository.GenomicDataRepository; +import org.cbioportal.domain.studyview.StudyViewFilterContext; +import org.cbioportal.legacy.web.parameter.GenomicDataFilter; +import org.springframework.context.annotation.Profile; +import org.springframework.stereotype.Service; + +@Service +@Profile("clickhouse") +/** + * A use case class responsible for retrieving mutation counts based on the provided study view + * filter context and genomic data filter. This class acts as an intermediary between the + * application logic and the data repository, delegating the data retrieval to the {@link + * GenomicDataRepository}. + */ +public class GetMutationCountsUseCase { + private final GenomicDataRepository repository; + + /** + * Constructs a new instance of {@link GetMutationCountsUseCase}. + * + * @param repository the repository used to access genomic data. Must not be {@code null}. + */ + public GetMutationCountsUseCase(GenomicDataRepository repository) { + this.repository = repository; + } + + /** + * Executes the use case to retrieve mutation counts based on the provided study view filter + * context and genomic data filter. + * + * @param studyViewFilterContext the context containing study view filter criteria. Must not be + * {@code null}. + * @param genomicDataFilter the filter to apply to the genomic data for retrieving mutation + * counts. Must not be {@code null}. + * @return a map where the key is a string representing a mutation type and the value is the count + * of mutations. + */ + public Map execute( + StudyViewFilterContext studyViewFilterContext, GenomicDataFilter genomicDataFilter) { + return repository.getMutationCounts(studyViewFilterContext, genomicDataFilter); + } +} diff --git a/src/main/java/org/cbioportal/domain/patient/Patient.java b/src/main/java/org/cbioportal/domain/patient/Patient.java new file mode 100644 index 00000000000..f053fa4b950 --- /dev/null +++ b/src/main/java/org/cbioportal/domain/patient/Patient.java @@ -0,0 +1,12 @@ +package org.cbioportal.domain.patient; + +import java.io.Serializable; +import org.cbioportal.domain.cancerstudy.CancerStudyMetadata; + +public record Patient( + Integer internalId, + String stableId, + Integer cancerStudyId, + String cancerStudyIdentifier, + CancerStudyMetadata cancerStudy) + implements Serializable {} diff --git a/src/main/java/org/cbioportal/domain/patient/repository/PatientRepository.java b/src/main/java/org/cbioportal/domain/patient/repository/PatientRepository.java new file mode 100644 index 00000000000..f25cc19038b --- /dev/null +++ b/src/main/java/org/cbioportal/domain/patient/repository/PatientRepository.java @@ -0,0 +1,28 @@ +package org.cbioportal.domain.patient.repository; + +import java.util.List; +import org.cbioportal.domain.studyview.StudyViewFilterContext; +import org.cbioportal.legacy.model.CaseListDataCount; + +/** + * Repository interface for performing operations related to patient data. This interface defines + * methods for retrieving filtered patient counts and case list data counts. + */ +public interface PatientRepository { + + /** + * Retrieves the count of filtered patients based on the provided study view filter context. + * + * @param studyViewFilterContext the context containing the filter criteria for the study view + * @return the count of patients that match the filter criteria + */ + int getFilteredPatientCount(StudyViewFilterContext studyViewFilterContext); + + /** + * Retrieves the case list data counts based on the provided study view filter context. + * + * @param studyViewFilterContext the context containing the filter criteria for the study view + * @return a list of {@link CaseListDataCount} representing the counts of case list data + */ + List getCaseListDataCounts(StudyViewFilterContext studyViewFilterContext); +} diff --git a/src/main/java/org/cbioportal/domain/patient/usecase/GetCaseListDataCountsUseCase.java b/src/main/java/org/cbioportal/domain/patient/usecase/GetCaseListDataCountsUseCase.java new file mode 100644 index 00000000000..caad5e84950 --- /dev/null +++ b/src/main/java/org/cbioportal/domain/patient/usecase/GetCaseListDataCountsUseCase.java @@ -0,0 +1,40 @@ +package org.cbioportal.domain.patient.usecase; + +import java.util.List; +import org.cbioportal.domain.patient.repository.PatientRepository; +import org.cbioportal.domain.studyview.StudyViewFilterContext; +import org.cbioportal.legacy.model.CaseListDataCount; +import org.springframework.context.annotation.Profile; +import org.springframework.stereotype.Service; + +@Service +@Profile("clickhouse") +/** + * Use case for retrieving case list data counts. This class interacts with the {@link + * PatientRepository} to fetch the case list data counts based on the filter criteria specified in + * the study view filter context. + */ +public class GetCaseListDataCountsUseCase { + + private final PatientRepository patientRepository; + + /** + * Constructs a {@code GetCaseListDataCountsUseCase} with the provided {@link PatientRepository}. + * + * @param patientRepository the repository to be used for retrieving the case list data counts + */ + public GetCaseListDataCountsUseCase(PatientRepository patientRepository) { + this.patientRepository = patientRepository; + } + + /** + * Executes the use case to retrieve the case list data counts based on the given study view + * filter context. + * + * @param studyViewFilterContext the context of the study view filter to apply + * @return a list of {@link CaseListDataCount} representing the counts of case list data + */ + public List execute(StudyViewFilterContext studyViewFilterContext) { + return patientRepository.getCaseListDataCounts(studyViewFilterContext); + } +} diff --git a/src/main/java/org/cbioportal/domain/patient/usecase/GetFilteredPatientCountUseCase.java b/src/main/java/org/cbioportal/domain/patient/usecase/GetFilteredPatientCountUseCase.java new file mode 100644 index 00000000000..4e661f85209 --- /dev/null +++ b/src/main/java/org/cbioportal/domain/patient/usecase/GetFilteredPatientCountUseCase.java @@ -0,0 +1,39 @@ +package org.cbioportal.domain.patient.usecase; + +import org.cbioportal.domain.patient.repository.PatientRepository; +import org.cbioportal.domain.studyview.StudyViewFilterContext; +import org.springframework.context.annotation.Profile; +import org.springframework.stereotype.Service; + +@Service +@Profile("clickhouse") +/** + * Use case for retrieving the count of filtered patients. This class interacts with the {@link + * PatientRepository} to fetch the number of patients that match the given filter criteria specified + * in the study view filter context. + */ +public class GetFilteredPatientCountUseCase { + + private final PatientRepository patientRepository; + + /** + * Constructs a {@code GetFilteredPatientCountUseCase} with the provided {@link + * PatientRepository}. + * + * @param patientRepository the repository to be used for retrieving the filtered patient count + */ + public GetFilteredPatientCountUseCase(PatientRepository patientRepository) { + this.patientRepository = patientRepository; + } + + /** + * Executes the use case to retrieve the count of filtered patients based on the given study view + * filter context. + * + * @param studyViewFilterContext the context of the study view filter to apply + * @return the count of filtered patients + */ + public int execute(StudyViewFilterContext studyViewFilterContext) { + return patientRepository.getFilteredPatientCount(studyViewFilterContext); + } +} diff --git a/src/main/java/org/cbioportal/domain/sample/Sample.java b/src/main/java/org/cbioportal/domain/sample/Sample.java new file mode 100644 index 00000000000..b804c55128f --- /dev/null +++ b/src/main/java/org/cbioportal/domain/sample/Sample.java @@ -0,0 +1,102 @@ +package org.cbioportal.domain.sample; + +import java.io.Serializable; +import java.util.Objects; +import org.cbioportal.domain.patient.Patient; + +public record Sample( + Integer internalId, + String stableId, + SampleType sampleType, + Integer patientId, + String patientStableId, + Patient patient, + String cancerStudyIdentifier, + Boolean sequenced, + Boolean copyNumberSegmentPresent, + String uniqueSampleKey, + String uniquePatientKey) + implements Serializable { + + // This constructor is intended for the ID projection + public Sample( + Integer internalId, String stableId, String patientStableId, String cancerStudyIdentifier) { + this( + internalId, + stableId, + (SampleType) null, + null, + patientStableId, + null, + cancerStudyIdentifier, + null, + null, + null, + null); + } + + // This constructor is intended for the SUMMARY projection + public Sample( + Integer internalId, + String stableId, + String sampleType, + Integer patientId, + String patientStableId, + String cancerStudyIdentifier, + String uniqueSampleKey, + String uniquePatientKey) { + this( + internalId, + stableId, + SampleType.fromString(sampleType), + patientId, + patientStableId, + null, + cancerStudyIdentifier, + null, + null, + uniqueSampleKey, + uniquePatientKey); + } + + // This constructor is intended for the DETAILED projection + public Sample( + Integer internalId, + String stableId, + String sampleType, + Integer patientId, + String patientStableId, + Patient patient, + String cancerStudyIdentifier, + Boolean sequenced, + Boolean copyNumberSegmentPresent, + String uniqueSampleKey, + String uniquePatientKey) { + this( + internalId, + stableId, + SampleType.fromString(sampleType), + patientId, + patientStableId, + patient, + cancerStudyIdentifier, + sequenced, + copyNumberSegmentPresent, + uniqueSampleKey, + uniquePatientKey); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof Sample)) return false; + Sample sample = (Sample) o; + return stableId.equals(sample.stableId) + && cancerStudyIdentifier.equals(sample.cancerStudyIdentifier); + } + + @Override + public int hashCode() { + return Objects.hash(stableId, cancerStudyIdentifier); + } +} diff --git a/src/main/java/org/cbioportal/domain/sample/SampleType.java b/src/main/java/org/cbioportal/domain/sample/SampleType.java new file mode 100644 index 00000000000..38a8123742b --- /dev/null +++ b/src/main/java/org/cbioportal/domain/sample/SampleType.java @@ -0,0 +1,38 @@ +package org.cbioportal.domain.sample; + +public enum SampleType { + PRIMARY_SOLID_TUMOR("Primary Solid Tumor"), + RECURRENT_SOLID_TUMOR("Recurrent Solid Tumor"), + PRIMARY_BLOOD_TUMOR("Primary Blood Tumor"), + RECURRENT_BLOOD_TUMOR("Recurrent Blood Tumor"), + METASTATIC("Metastatic"), + BLOOD_NORMAL("Blood Derived Normal"), + SOLID_NORMAL("Solid Tissues Normal"); + + private String value; + + SampleType(String value) { + this.value = value; + } + + public String getValue() { + return value; + } + + public static SampleType fromString(String value) { + + if (value != null) { + for (SampleType sampleType : SampleType.values()) { + if (value.equalsIgnoreCase(sampleType.value)) { + return sampleType; + } + } + } + return null; + } + + @Override + public String toString() { + return value; + } +} diff --git a/src/main/java/org/cbioportal/domain/sample/repository/SampleRepository.java b/src/main/java/org/cbioportal/domain/sample/repository/SampleRepository.java new file mode 100644 index 00000000000..f7628e22754 --- /dev/null +++ b/src/main/java/org/cbioportal/domain/sample/repository/SampleRepository.java @@ -0,0 +1,76 @@ +package org.cbioportal.domain.sample.repository; + +import java.util.List; +import org.cbioportal.domain.sample.Sample; +import org.cbioportal.domain.studyview.StudyViewFilterContext; +import org.cbioportal.legacy.model.meta.BaseMeta; +import org.cbioportal.shared.enums.ProjectionType; + +/** + * Repository interface for performing operations related to sample data. This interface defines + * methods for retrieving filtered samples and their respective counts based on the filter criteria + * provided in the study view filter context. + */ +public interface SampleRepository { + + /** + * Retrieves the samples that match the filter criteria specified in the study view filter + * context. + * + * @param studyViewFilterContext the context containing the filter criteria for the study view + * @return a list of {@link Sample} representing the samples that match the filter criteria + */ + List getFilteredSamples(StudyViewFilterContext studyViewFilterContext); + + /** + * Retrieves the total count of samples that match the filter criteria specified in the study view + * filter context. + * + * @param studyViewFilterContext the context containing the filter criteria for the study view + * @return the total count of filtered samples + */ + int getFilteredSamplesCount(StudyViewFilterContext studyViewFilterContext); + + List fetchSamples( + List studyIds, List sampleIds, ProjectionType projection); + + List fetchSamplesBySampleListIds(List sampleListIds, ProjectionType projection); + + BaseMeta fetchMetaSamples(List studyIds, List sampleIds); + + BaseMeta fetchMetaSamplesBySampleListIds(List sampleListIds); + + List getAllSamplesInStudy( + String studyId, + ProjectionType projection, + Integer pageSize, + Integer pageNumber, + String sortBy, + String direction); + + BaseMeta getMetaSamplesInStudy(String studyId); + + Sample getSampleInStudy(String studyId, String sampleId); + + List getAllSamplesOfPatientInStudy( + String studyId, + String patientId, + ProjectionType projection, + Integer pageSize, + Integer pageNumber, + String sortBy, + String direction); + + BaseMeta getMetaSamplesOfPatientInStudy(String studyId, String patientId); + + List getAllSamples( + String keyword, + List studyIds, + ProjectionType projection, + Integer pageSize, + Integer pageNumber, + String sort, + String direction); + + BaseMeta getMetaSamples(String keyword, List studyIds); +} diff --git a/src/main/java/org/cbioportal/domain/sample/usecase/FetchMetaSamplesUseCase.java b/src/main/java/org/cbioportal/domain/sample/usecase/FetchMetaSamplesUseCase.java new file mode 100644 index 00000000000..6e9bcbf65bf --- /dev/null +++ b/src/main/java/org/cbioportal/domain/sample/usecase/FetchMetaSamplesUseCase.java @@ -0,0 +1,36 @@ +package org.cbioportal.domain.sample.usecase; + +import java.util.List; +import org.cbioportal.domain.sample.repository.SampleRepository; +import org.cbioportal.legacy.model.meta.BaseMeta; +import org.cbioportal.legacy.web.parameter.SampleFilter; +import org.cbioportal.shared.util.SampleDataFilterUtil; +import org.springframework.context.annotation.Profile; +import org.springframework.data.util.Pair; +import org.springframework.stereotype.Service; + +@Service +@Profile("clickhouse") +public class FetchMetaSamplesUseCase { + private final SampleRepository sampleRepository; + + public FetchMetaSamplesUseCase(SampleRepository sampleRepository) { + this.sampleRepository = sampleRepository; + } + + public BaseMeta execute(SampleFilter sampleFilter) { + BaseMeta baseMeta; + + if (sampleFilter.getSampleListIds() != null) { + baseMeta = sampleRepository.fetchMetaSamplesBySampleListIds(sampleFilter.getSampleListIds()); + } else { + Pair, List> studyAndSampleIds = + SampleDataFilterUtil.extractStudyAndSampleIds(sampleFilter); + baseMeta = + sampleRepository.fetchMetaSamples( + studyAndSampleIds.getFirst(), studyAndSampleIds.getSecond()); + } + + return baseMeta; + } +} diff --git a/src/main/java/org/cbioportal/domain/sample/usecase/FetchSamplesUseCase.java b/src/main/java/org/cbioportal/domain/sample/usecase/FetchSamplesUseCase.java new file mode 100644 index 00000000000..576bfaa4fe3 --- /dev/null +++ b/src/main/java/org/cbioportal/domain/sample/usecase/FetchSamplesUseCase.java @@ -0,0 +1,38 @@ +package org.cbioportal.domain.sample.usecase; + +import java.util.List; +import org.cbioportal.domain.sample.Sample; +import org.cbioportal.domain.sample.repository.SampleRepository; +import org.cbioportal.legacy.web.parameter.SampleFilter; +import org.cbioportal.shared.enums.ProjectionType; +import org.cbioportal.shared.util.SampleDataFilterUtil; +import org.springframework.context.annotation.Profile; +import org.springframework.data.util.Pair; +import org.springframework.stereotype.Service; + +@Service +@Profile("clickhouse") +public class FetchSamplesUseCase { + private final SampleRepository sampleRepository; + + public FetchSamplesUseCase(SampleRepository sampleRepository) { + this.sampleRepository = sampleRepository; + } + + public List execute(SampleFilter sampleFilter, ProjectionType projection) { + List samples; + + if (sampleFilter.getSampleListIds() != null) { + List sampleListIds = sampleFilter.getSampleListIds(); + samples = sampleRepository.fetchSamplesBySampleListIds(sampleListIds, projection); + } else { + Pair, List> studyAndSampleIds = + SampleDataFilterUtil.extractStudyAndSampleIds(sampleFilter); + samples = + sampleRepository.fetchSamples( + studyAndSampleIds.getFirst(), studyAndSampleIds.getSecond(), projection); + } + + return samples; + } +} diff --git a/src/main/java/org/cbioportal/domain/sample/usecase/GetAllSamplesInStudyUseCase.java b/src/main/java/org/cbioportal/domain/sample/usecase/GetAllSamplesInStudyUseCase.java new file mode 100644 index 00000000000..35f12b0a80b --- /dev/null +++ b/src/main/java/org/cbioportal/domain/sample/usecase/GetAllSamplesInStudyUseCase.java @@ -0,0 +1,36 @@ +package org.cbioportal.domain.sample.usecase; + +import java.util.List; +import org.cbioportal.domain.sample.Sample; +import org.cbioportal.domain.sample.repository.SampleRepository; +import org.cbioportal.legacy.service.StudyService; +import org.cbioportal.legacy.service.exception.StudyNotFoundException; +import org.cbioportal.shared.enums.ProjectionType; +import org.springframework.context.annotation.Profile; +import org.springframework.stereotype.Service; + +@Service +@Profile("clickhouse") +public class GetAllSamplesInStudyUseCase { + private final StudyService studyService; + private final SampleRepository sampleRepository; + + public GetAllSamplesInStudyUseCase(SampleRepository sampleRepository, StudyService studyService) { + this.sampleRepository = sampleRepository; + this.studyService = studyService; + } + + public List execute( + String studyId, + ProjectionType projection, + Integer pageSize, + Integer pageNumber, + String sortBy, + String direction) + throws StudyNotFoundException { + studyService.getStudy(studyId); + + return sampleRepository.getAllSamplesInStudy( + studyId, projection, pageSize, pageNumber, sortBy, direction); + } +} diff --git a/src/main/java/org/cbioportal/domain/sample/usecase/GetAllSamplesOfPatientInStudyUseCase.java b/src/main/java/org/cbioportal/domain/sample/usecase/GetAllSamplesOfPatientInStudyUseCase.java new file mode 100644 index 00000000000..254398eb1e6 --- /dev/null +++ b/src/main/java/org/cbioportal/domain/sample/usecase/GetAllSamplesOfPatientInStudyUseCase.java @@ -0,0 +1,39 @@ +package org.cbioportal.domain.sample.usecase; + +import java.util.List; +import org.cbioportal.domain.sample.Sample; +import org.cbioportal.domain.sample.repository.SampleRepository; +import org.cbioportal.legacy.service.PatientService; +import org.cbioportal.legacy.service.exception.PatientNotFoundException; +import org.cbioportal.legacy.service.exception.StudyNotFoundException; +import org.cbioportal.shared.enums.ProjectionType; +import org.springframework.context.annotation.Profile; +import org.springframework.stereotype.Service; + +@Service +@Profile("clickhouse") +public class GetAllSamplesOfPatientInStudyUseCase { + private final PatientService patientService; + private final SampleRepository sampleRepository; + + public GetAllSamplesOfPatientInStudyUseCase( + SampleRepository sampleRepository, PatientService patientService) { + this.sampleRepository = sampleRepository; + this.patientService = patientService; + } + + public List execute( + String studyId, + String patientId, + ProjectionType projection, + Integer pageSize, + Integer pageNumber, + String sortBy, + String direction) + throws StudyNotFoundException, PatientNotFoundException { + patientService.getPatientInStudy(studyId, patientId); + + return sampleRepository.getAllSamplesOfPatientInStudy( + studyId, patientId, projection, pageSize, pageNumber, sortBy, direction); + } +} diff --git a/src/main/java/org/cbioportal/domain/sample/usecase/GetAllSamplesUseCase.java b/src/main/java/org/cbioportal/domain/sample/usecase/GetAllSamplesUseCase.java new file mode 100644 index 00000000000..ca601a1af71 --- /dev/null +++ b/src/main/java/org/cbioportal/domain/sample/usecase/GetAllSamplesUseCase.java @@ -0,0 +1,30 @@ +package org.cbioportal.domain.sample.usecase; + +import java.util.List; +import org.cbioportal.domain.sample.Sample; +import org.cbioportal.domain.sample.repository.SampleRepository; +import org.cbioportal.shared.enums.ProjectionType; +import org.springframework.context.annotation.Profile; +import org.springframework.stereotype.Service; + +@Service +@Profile("clickhouse") +public class GetAllSamplesUseCase { + private final SampleRepository sampleRepository; + + public GetAllSamplesUseCase(SampleRepository sampleRepository) { + this.sampleRepository = sampleRepository; + } + + public List execute( + String keyword, + List studyIds, + ProjectionType projection, + Integer pageSize, + Integer pageNumber, + String sort, + String direction) { + return sampleRepository.getAllSamples( + keyword, studyIds, projection, pageSize, pageNumber, sort, direction); + } +} diff --git a/src/main/java/org/cbioportal/domain/sample/usecase/GetFilteredSamplesCountUseCase.java b/src/main/java/org/cbioportal/domain/sample/usecase/GetFilteredSamplesCountUseCase.java new file mode 100644 index 00000000000..6cdc18e7729 --- /dev/null +++ b/src/main/java/org/cbioportal/domain/sample/usecase/GetFilteredSamplesCountUseCase.java @@ -0,0 +1,38 @@ +package org.cbioportal.domain.sample.usecase; + +import org.cbioportal.domain.sample.repository.SampleRepository; +import org.cbioportal.domain.studyview.StudyViewFilterContext; +import org.springframework.context.annotation.Profile; +import org.springframework.stereotype.Service; + +@Service +@Profile("clickhouse") +/** + * Use case for retrieving the count of filtered samples. This class interacts with the {@link + * SampleRepository} to fetch the number of samples that match the given filter criteria specified + * in the study view filter context. + */ +public class GetFilteredSamplesCountUseCase { + + private final SampleRepository sampleRepository; + + /** + * Constructs a {@code GetFilteredSamplesCountUseCase} with the provided {@link SampleRepository}. + * + * @param sampleRepository the repository to be used for retrieving the filtered samples count + */ + public GetFilteredSamplesCountUseCase(SampleRepository sampleRepository) { + this.sampleRepository = sampleRepository; + } + + /** + * Executes the use case to retrieve the count of filtered samples based on the given study view + * filter context. + * + * @param studyViewFilterContext the context of the study view filter to apply + * @return the count of filtered samples + */ + public int execute(StudyViewFilterContext studyViewFilterContext) { + return sampleRepository.getFilteredSamplesCount(studyViewFilterContext); + } +} diff --git a/src/main/java/org/cbioportal/domain/sample/usecase/GetFilteredSamplesUseCase.java b/src/main/java/org/cbioportal/domain/sample/usecase/GetFilteredSamplesUseCase.java new file mode 100644 index 00000000000..52eb0ac5700 --- /dev/null +++ b/src/main/java/org/cbioportal/domain/sample/usecase/GetFilteredSamplesUseCase.java @@ -0,0 +1,23 @@ +package org.cbioportal.domain.sample.usecase; + +import java.util.List; +import org.cbioportal.domain.sample.Sample; +import org.cbioportal.domain.sample.repository.SampleRepository; +import org.cbioportal.domain.studyview.StudyViewFilterContext; +import org.springframework.context.annotation.Profile; +import org.springframework.stereotype.Service; + +@Service +@Profile("clickhouse") +public final class GetFilteredSamplesUseCase { + + private final SampleRepository sampleRepository; + + public GetFilteredSamplesUseCase(SampleRepository sampleRepository) { + this.sampleRepository = sampleRepository; + } + + public List execute(StudyViewFilterContext studyViewFilterContext) { + return this.sampleRepository.getFilteredSamples(studyViewFilterContext); + } +} diff --git a/src/main/java/org/cbioportal/domain/sample/usecase/GetMetaSamplesInStudyUseCase.java b/src/main/java/org/cbioportal/domain/sample/usecase/GetMetaSamplesInStudyUseCase.java new file mode 100644 index 00000000000..83931e1ceee --- /dev/null +++ b/src/main/java/org/cbioportal/domain/sample/usecase/GetMetaSamplesInStudyUseCase.java @@ -0,0 +1,27 @@ +package org.cbioportal.domain.sample.usecase; + +import org.cbioportal.domain.sample.repository.SampleRepository; +import org.cbioportal.legacy.model.meta.BaseMeta; +import org.cbioportal.legacy.service.StudyService; +import org.cbioportal.legacy.service.exception.StudyNotFoundException; +import org.springframework.context.annotation.Profile; +import org.springframework.stereotype.Service; + +@Service +@Profile("clickhouse") +public class GetMetaSamplesInStudyUseCase { + private final SampleRepository sampleRepository; + private final StudyService studyService; + + public GetMetaSamplesInStudyUseCase( + SampleRepository sampleRepository, StudyService studyService) { + this.sampleRepository = sampleRepository; + this.studyService = studyService; + } + + public BaseMeta execute(String studyId) throws StudyNotFoundException { + studyService.getStudy(studyId); + + return sampleRepository.getMetaSamplesInStudy(studyId); + } +} diff --git a/src/main/java/org/cbioportal/domain/sample/usecase/GetMetaSamplesOfPatientInStudyUseCase.java b/src/main/java/org/cbioportal/domain/sample/usecase/GetMetaSamplesOfPatientInStudyUseCase.java new file mode 100644 index 00000000000..7fe9a2c1158 --- /dev/null +++ b/src/main/java/org/cbioportal/domain/sample/usecase/GetMetaSamplesOfPatientInStudyUseCase.java @@ -0,0 +1,29 @@ +package org.cbioportal.domain.sample.usecase; + +import org.cbioportal.domain.sample.repository.SampleRepository; +import org.cbioportal.legacy.model.meta.BaseMeta; +import org.cbioportal.legacy.service.PatientService; +import org.cbioportal.legacy.service.exception.PatientNotFoundException; +import org.cbioportal.legacy.service.exception.StudyNotFoundException; +import org.springframework.context.annotation.Profile; +import org.springframework.stereotype.Service; + +@Service +@Profile("clickhouse") +public class GetMetaSamplesOfPatientInStudyUseCase { + private final SampleRepository sampleRepository; + private final PatientService patientService; + + public GetMetaSamplesOfPatientInStudyUseCase( + SampleRepository sampleRepository, PatientService patientService) { + this.sampleRepository = sampleRepository; + this.patientService = patientService; + } + + public BaseMeta execute(String studyId, String patientId) + throws StudyNotFoundException, PatientNotFoundException { + patientService.getPatientInStudy(studyId, patientId); + + return sampleRepository.getMetaSamplesOfPatientInStudy(studyId, patientId); + } +} diff --git a/src/main/java/org/cbioportal/domain/sample/usecase/GetMetaSamplesUseCase.java b/src/main/java/org/cbioportal/domain/sample/usecase/GetMetaSamplesUseCase.java new file mode 100644 index 00000000000..784620ee54a --- /dev/null +++ b/src/main/java/org/cbioportal/domain/sample/usecase/GetMetaSamplesUseCase.java @@ -0,0 +1,21 @@ +package org.cbioportal.domain.sample.usecase; + +import java.util.List; +import org.cbioportal.domain.sample.repository.SampleRepository; +import org.cbioportal.legacy.model.meta.BaseMeta; +import org.springframework.context.annotation.Profile; +import org.springframework.stereotype.Service; + +@Service +@Profile("clickhouse") +public class GetMetaSamplesUseCase { + private final SampleRepository sampleRepository; + + public GetMetaSamplesUseCase(SampleRepository sampleRepository) { + this.sampleRepository = sampleRepository; + } + + public BaseMeta execute(String keyword, List studyIds) { + return sampleRepository.getMetaSamples(keyword, studyIds); + } +} diff --git a/src/main/java/org/cbioportal/domain/sample/usecase/GetSampleInStudyUseCase.java b/src/main/java/org/cbioportal/domain/sample/usecase/GetSampleInStudyUseCase.java new file mode 100644 index 00000000000..6f7096c5537 --- /dev/null +++ b/src/main/java/org/cbioportal/domain/sample/usecase/GetSampleInStudyUseCase.java @@ -0,0 +1,33 @@ +package org.cbioportal.domain.sample.usecase; + +import org.cbioportal.domain.sample.Sample; +import org.cbioportal.domain.sample.repository.SampleRepository; +import org.cbioportal.legacy.service.StudyService; +import org.cbioportal.legacy.service.exception.SampleNotFoundException; +import org.cbioportal.legacy.service.exception.StudyNotFoundException; +import org.springframework.context.annotation.Profile; +import org.springframework.stereotype.Service; + +@Service +@Profile("clickhouse") +public class GetSampleInStudyUseCase { + private final StudyService studyService; + private final SampleRepository sampleRepository; + + public GetSampleInStudyUseCase(SampleRepository sampleRepository, StudyService studyService) { + this.sampleRepository = sampleRepository; + this.studyService = studyService; + } + + public Sample execute(String studyId, String sampleId) + throws SampleNotFoundException, StudyNotFoundException { + studyService.getStudy(studyId); + Sample sample = sampleRepository.getSampleInStudy(studyId, sampleId); + + if (sample == null) { + throw new SampleNotFoundException(studyId, sampleId); + } + + return sample; + } +} diff --git a/src/main/java/org/cbioportal/domain/sample/usecase/SampleUseCases.java b/src/main/java/org/cbioportal/domain/sample/usecase/SampleUseCases.java new file mode 100644 index 00000000000..fa1f8e9e81f --- /dev/null +++ b/src/main/java/org/cbioportal/domain/sample/usecase/SampleUseCases.java @@ -0,0 +1,19 @@ +package org.cbioportal.domain.sample.usecase; + +import org.springframework.context.annotation.Profile; +import org.springframework.stereotype.Service; + +@Service +@Profile("clickhouse") +public record SampleUseCases( + FetchMetaSamplesUseCase fetchMetaSamplesUseCase, + FetchSamplesUseCase fetchSamplesUseCase, + GetAllSamplesInStudyUseCase getAllSamplesInStudyUseCase, + GetAllSamplesOfPatientInStudyUseCase getAllSamplesOfPatientInStudyUseCase, + GetAllSamplesUseCase getAllSamplesUseCase, + GetFilteredSamplesCountUseCase getFilteredSamplesCountUseCase, + GetFilteredSamplesUseCase getFilteredSamplesUseCase, + GetMetaSamplesInStudyUseCase getMetaSamplesInStudyUseCase, + GetMetaSamplesOfPatientInStudyUseCase getMetaSamplesOfPatientInStudyUseCase, + GetMetaSamplesUseCase getMetaSamplesUseCase, + GetSampleInStudyUseCase getSampleInStudyUseCase) {} diff --git a/src/main/java/org/cbioportal/domain/studyview/StudyViewFilterContext.java b/src/main/java/org/cbioportal/domain/studyview/StudyViewFilterContext.java new file mode 100644 index 00000000000..2b2e4fc083d --- /dev/null +++ b/src/main/java/org/cbioportal/domain/studyview/StudyViewFilterContext.java @@ -0,0 +1,58 @@ +package org.cbioportal.domain.studyview; + +import java.util.List; +import org.cbioportal.legacy.model.AlterationFilter; +import org.cbioportal.legacy.model.GeneFilter; +import org.cbioportal.legacy.model.StudyViewStructuralVariantFilter; +import org.cbioportal.legacy.web.parameter.CategorizedGenericAssayDataCountFilter; +import org.cbioportal.legacy.web.parameter.ClinicalDataFilter; +import org.cbioportal.legacy.web.parameter.CustomSampleIdentifier; +import org.cbioportal.legacy.web.parameter.DataFilter; +import org.cbioportal.legacy.web.parameter.GenericAssayDataFilter; +import org.cbioportal.legacy.web.parameter.GenomicDataFilter; +import org.cbioportal.legacy.web.parameter.MutationDataFilter; +import org.cbioportal.legacy.web.parameter.SampleIdentifier; +import org.cbioportal.legacy.web.parameter.filter.AndedPatientTreatmentFilters; +import org.cbioportal.legacy.web.parameter.filter.AndedSampleTreatmentFilters; + +public record StudyViewFilterContext( + List sampleIdentifiers, + List studyIds, + List clinicalDataFilters, + List geneFilters, + List structuralVariantFilters, + AndedSampleTreatmentFilters sampleTreatmentFilters, + AndedSampleTreatmentFilters sampleTreatmentGroupFilters, + AndedSampleTreatmentFilters sampleTreatmentTargetFilters, + AndedPatientTreatmentFilters patientTreatmentFilters, + AndedPatientTreatmentFilters patientTreatmentGroupFilters, + AndedPatientTreatmentFilters patientTreatmentTargetFilters, + List> genomicProfiles, + List genomicDataFilters, + List genericAssayDataFilters, + List> caseLists, + List customDataFilters, + AlterationFilter alterationFilter, + List clinicalEventFilters, + List mutationDataFilters, + List customSampleIdentifiers, + List customDataFilterCancerStudies, + CategorizedGenericAssayDataCountFilter categorizedGenericAssayDataCountFilter) { + + public String[] filteredSampleIdentifiers() { + if (sampleIdentifiers != null) { + return sampleIdentifiers.stream() + .map( + sampleIdentifier -> + sampleIdentifier.getStudyId() + "_" + sampleIdentifier.getSampleId()) + .toArray(String[]::new); + } else { + return new String[0]; + } + } + + public boolean isCategoricalClinicalDataFilter(ClinicalDataFilter clinicalDataFilter) { + var filterValue = clinicalDataFilter.getValues().getFirst(); + return filterValue.getValue() != null; + } +} diff --git a/src/main/java/org/cbioportal/domain/studyview/StudyViewFilterFactory.java b/src/main/java/org/cbioportal/domain/studyview/StudyViewFilterFactory.java new file mode 100644 index 00000000000..dc252efd307 --- /dev/null +++ b/src/main/java/org/cbioportal/domain/studyview/StudyViewFilterFactory.java @@ -0,0 +1,82 @@ +package org.cbioportal.domain.studyview; + +import java.util.List; +import java.util.Map; +import org.cbioportal.legacy.model.MolecularProfile; +import org.cbioportal.legacy.persistence.enums.DataSource; +import org.cbioportal.legacy.web.columnar.util.CustomDataFilterUtil; +import org.cbioportal.legacy.web.parameter.CategorizedGenericAssayDataCountFilter; +import org.cbioportal.legacy.web.parameter.ClinicalDataFilter; +import org.cbioportal.legacy.web.parameter.CustomSampleIdentifier; +import org.cbioportal.legacy.web.parameter.GenericAssayDataFilter; +import org.cbioportal.legacy.web.parameter.GenomicDataFilter; +import org.cbioportal.legacy.web.parameter.StudyViewFilter; +import org.cbioportal.shared.DataFilterUtil; + +public abstract class StudyViewFilterFactory { + private StudyViewFilterFactory() {} + + public static StudyViewFilterContext make( + StudyViewFilter base, + CustomDataFilterUtil customDataFilterUtil, + Map> genericAssayProfilesMap) { + List customSampleIdentifiers = + customDataFilterUtil.extractCustomDataSamples(base); + List involvedCancerStudies = customDataFilterUtil.extractInvolvedCancerStudies(base); + CategorizedGenericAssayDataCountFilter categorizedGenericAssayDataCountFilter = + CategorizedGenericAssayDataCountFilter.getBuilder(genericAssayProfilesMap, base).build(); + + // Merge data filters + if (base.getGenomicDataFilters() != null && !base.getGenomicDataFilters().isEmpty()) { + List mergedGenomicDataFilters = + DataFilterUtil.mergeDataFilters(base.getGenomicDataFilters()); + base.setGenomicDataFilters(mergedGenomicDataFilters); + } + if (base.getClinicalDataFilters() != null && !base.getClinicalDataFilters().isEmpty()) { + List mergedClinicalDataFilters = + DataFilterUtil.mergeDataFilters(base.getClinicalDataFilters()); + base.setClinicalDataFilters(mergedClinicalDataFilters); + } + if (base.getGenericAssayDataFilters() != null && !base.getGenericAssayDataFilters().isEmpty()) { + List mergedGenericAssayDataFilters = + DataFilterUtil.mergeDataFilters(base.getGenericAssayDataFilters()); + base.setGenericAssayDataFilters(mergedGenericAssayDataFilters); + } + + return make( + base, + customSampleIdentifiers, + involvedCancerStudies, + categorizedGenericAssayDataCountFilter); + } + + public static StudyViewFilterContext make( + StudyViewFilter base, + List customSampleIdentifiers, + List involvedCancerStudies, + CategorizedGenericAssayDataCountFilter categorizedGenericAssayDataCountFilter) { + return new StudyViewFilterContext( + base.getSampleIdentifiers(), + base.getStudyIds(), + base.getClinicalDataFilters(), + base.getGeneFilters(), + base.getStructuralVariantFilters(), + base.getSampleTreatmentFilters(), + base.getSampleTreatmentGroupFilters(), + base.getSampleTreatmentTargetFilters(), + base.getPatientTreatmentFilters(), + base.getPatientTreatmentGroupFilters(), + base.getPatientTreatmentTargetFilters(), + base.getGenomicProfiles(), + base.getGenomicDataFilters(), + base.getGenericAssayDataFilters(), + base.getCaseLists(), + base.getCustomDataFilters(), + base.getAlterationFilter(), + base.getClinicalEventFilters(), + base.getMutationDataFilters(), + customSampleIdentifiers, + involvedCancerStudies, + categorizedGenericAssayDataCountFilter); + } +} diff --git a/src/main/java/org/cbioportal/domain/studyview/StudyViewService.java b/src/main/java/org/cbioportal/domain/studyview/StudyViewService.java new file mode 100644 index 00000000000..8264eb72d96 --- /dev/null +++ b/src/main/java/org/cbioportal/domain/studyview/StudyViewService.java @@ -0,0 +1,348 @@ +package org.cbioportal.domain.studyview; + +import java.util.ArrayList; +import java.util.EnumMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; +import org.cbioportal.domain.alteration.usecase.AlterationCountByGeneUseCases; +import org.cbioportal.domain.clinical_attributes.usecase.GetClinicalAttributesDataTypeMapUseCase; +import org.cbioportal.domain.clinical_attributes.usecase.GetClinicalAttributesForStudiesUseCase; +import org.cbioportal.domain.clinical_data.usecase.ClinicalDataUseCases; +import org.cbioportal.domain.clinical_event.usecase.GetClinicalEventTypeCountsUseCase; +import org.cbioportal.domain.generic_assay.usecase.GenericAssayUseCases; +import org.cbioportal.domain.genomic_data.usecase.GenomicDataUseCases; +import org.cbioportal.domain.patient.usecase.GetCaseListDataCountsUseCase; +import org.cbioportal.domain.sample.Sample; +import org.cbioportal.domain.sample.usecase.GetFilteredSamplesUseCase; +import org.cbioportal.domain.treatment.usecase.TreatmentCountReportUseCases; +import org.cbioportal.legacy.model.AlterationCountByGene; +import org.cbioportal.legacy.model.AlterationType; +import org.cbioportal.legacy.model.CaseListDataCount; +import org.cbioportal.legacy.model.ClinicalAttribute; +import org.cbioportal.legacy.model.ClinicalData; +import org.cbioportal.legacy.model.ClinicalDataCountItem; +import org.cbioportal.legacy.model.ClinicalEventTypeCount; +import org.cbioportal.legacy.model.CopyNumberCountByGene; +import org.cbioportal.legacy.model.GenericAssayDataCountItem; +import org.cbioportal.legacy.model.GenomicDataCount; +import org.cbioportal.legacy.model.GenomicDataCountItem; +import org.cbioportal.legacy.model.MolecularProfile; +import org.cbioportal.legacy.model.PatientTreatmentReport; +import org.cbioportal.legacy.model.SampleTreatmentReport; +import org.cbioportal.legacy.persistence.enums.DataSource; +import org.cbioportal.legacy.service.exception.StudyNotFoundException; +import org.cbioportal.legacy.service.util.StudyViewColumnarServiceUtil; +import org.cbioportal.legacy.web.columnar.util.CustomDataFilterUtil; +import org.cbioportal.legacy.web.parameter.ClinicalDataType; +import org.cbioportal.legacy.web.parameter.GenericAssayDataBinFilter; +import org.cbioportal.legacy.web.parameter.GenericAssayDataFilter; +import org.cbioportal.legacy.web.parameter.GenomicDataBinFilter; +import org.cbioportal.legacy.web.parameter.GenomicDataFilter; +import org.cbioportal.legacy.web.parameter.StudyViewFilter; +import org.cbioportal.shared.util.ClinicalDataCountItemUtil; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.context.annotation.Profile; +import org.springframework.stereotype.Service; + +@Service +@Profile("clickhouse") +/** + * A service class responsible for handling study view-related operations, including retrieving + * filtered samples, genomic data counts, clinical data, and other study-specific information. This + * class acts as a central hub for coordinating various use cases and delegating tasks to the + * appropriate repositories and utilities. + */ +public class StudyViewService { + + private final GetFilteredSamplesUseCase getFilteredSamplesUseCase; + private final AlterationCountByGeneUseCases alterationCountByGeneUseCase; + private final GetClinicalEventTypeCountsUseCase getClinicalEventTypeCountsUseCase; + private final TreatmentCountReportUseCases treatmentCountReportUseCases; + private final GetClinicalAttributesForStudiesUseCase getClinicalAttributesForStudiesUseCase; + private final GetCaseListDataCountsUseCase getCaseListDataCountsUseCase; + private final GetClinicalAttributesDataTypeMapUseCase getClinicalAttributesDataTypeMapUseCase; + private final ClinicalDataUseCases clinicalDataUseCases; + private final GenomicDataUseCases genomicDataUseCases; + private final GenericAssayUseCases genericAssayUseCases; + private final CustomDataFilterUtil customDataFilterUtil; + + private Map> genericAssayProfilesMap = + new EnumMap<>(DataSource.class); + + public StudyViewService( + GetFilteredSamplesUseCase getFilteredSamplesUseCase, + AlterationCountByGeneUseCases alterationCountByGeneUseCase, + GetClinicalEventTypeCountsUseCase getClinicalEventTypeCountsUseCase, + TreatmentCountReportUseCases treatmentCountReportUseCases, + GetClinicalAttributesForStudiesUseCase getClinicalAttributesForStudiesUseCase, + GetCaseListDataCountsUseCase getCaseListDataCountsUseCase, + GetClinicalAttributesDataTypeMapUseCase getClinicalAttributesDataTypeMapUseCase, + ClinicalDataUseCases clinicalDataUseCases, + GenomicDataUseCases genomicDataUseCases, + GenericAssayUseCases genericAssayUseCases, + CustomDataFilterUtil customDataFilterUtil) { + this.getFilteredSamplesUseCase = getFilteredSamplesUseCase; + this.alterationCountByGeneUseCase = alterationCountByGeneUseCase; + this.clinicalDataUseCases = clinicalDataUseCases; + this.genomicDataUseCases = genomicDataUseCases; + this.getClinicalEventTypeCountsUseCase = getClinicalEventTypeCountsUseCase; + this.treatmentCountReportUseCases = treatmentCountReportUseCases; + this.getClinicalAttributesForStudiesUseCase = getClinicalAttributesForStudiesUseCase; + this.getCaseListDataCountsUseCase = getCaseListDataCountsUseCase; + this.getClinicalAttributesDataTypeMapUseCase = getClinicalAttributesDataTypeMapUseCase; + this.genericAssayUseCases = genericAssayUseCases; + this.customDataFilterUtil = customDataFilterUtil; + } + + @Cacheable( + cacheResolver = "staticRepositoryCacheOneResolver", + condition = + "@cacheEnabledConfig.getEnabledClickhouse() && @studyViewFilterUtil.isUnfilteredQuery(#studyViewFilter)") + public List getFilteredSamples(StudyViewFilter studyViewFilter) { + return getFilteredSamplesUseCase.execute(buildStudyViewFilterContext(studyViewFilter)); + } + + @Cacheable( + cacheResolver = "staticRepositoryCacheOneResolver", + condition = + "@cacheEnabledConfig.getEnabledClickhouse() && @studyViewFilterUtil.isUnfilteredQuery(#studyViewFilter)") + public List getMutatedGenes(StudyViewFilter studyViewFilter) + throws StudyNotFoundException { + return alterationCountByGeneUseCase + .getAlterationCountByGeneUseCase() + .execute(buildStudyViewFilterContext(studyViewFilter), AlterationType.MUTATION_EXTENDED); + } + + @Cacheable( + cacheResolver = "staticRepositoryCacheOneResolver", + condition = + "@cacheEnabledConfig.getEnabledClickhouse() && @studyViewFilterUtil.isUnfilteredQuery(#studyViewFilter)") + public List getCnaGenes(StudyViewFilter studyViewFilter) + throws StudyNotFoundException { + return alterationCountByGeneUseCase + .getCnaAlterationCountByGeneUseCase() + .execute(buildStudyViewFilterContext(studyViewFilter)); + } + + @Cacheable( + cacheResolver = "staticRepositoryCacheOneResolver", + condition = + "@cacheEnabledConfig.getEnabledClickhouse() && @studyViewFilterUtil.isUnfilteredQuery(#studyViewFilter)") + public List getStructuralVariantGenes(StudyViewFilter studyViewFilter) + throws StudyNotFoundException { + return alterationCountByGeneUseCase + .getAlterationCountByGeneUseCase() + .execute(buildStudyViewFilterContext(studyViewFilter), AlterationType.STRUCTURAL_VARIANT); + } + + @Cacheable( + cacheResolver = "staticRepositoryCacheOneResolver", + condition = + "@cacheEnabledConfig.getEnabledClickhouse() && @studyViewFilterUtil.isUnfilteredQuery(#studyViewFilter)") + public List getMolecularProfileSampleCounts(StudyViewFilter studyViewFilter) + throws StudyNotFoundException { + return genomicDataUseCases + .getMolecularProfileSampleCountsUseCase() + .execute(buildStudyViewFilterContext(studyViewFilter)); + } + + @Cacheable( + cacheResolver = "staticRepositoryCacheOneResolver", + condition = + "@cacheEnabledConfig.getEnabledClickhouse() && @studyViewFilterUtil.isUnfilteredQuery(#studyViewFilter)") + public List getClinicalEventTypeCounts(StudyViewFilter studyViewFilter) { + return getClinicalEventTypeCountsUseCase.execute(buildStudyViewFilterContext(studyViewFilter)); + } + + @Cacheable( + cacheResolver = "staticRepositoryCacheOneResolver", + condition = + "@cacheEnabledConfig.getEnabledClickhouse() && @studyViewFilterUtil.isUnfilteredQuery(#studyViewFilter)") + public PatientTreatmentReport getPatientTreatmentReport(StudyViewFilter studyViewFilter) { + return treatmentCountReportUseCases + .getPatientTreatmentReportUseCase() + .execute(buildStudyViewFilterContext(studyViewFilter)); + } + + @Cacheable( + cacheResolver = "staticRepositoryCacheOneResolver", + condition = + "@cacheEnabledConfig.getEnabledClickhouse() && @studyViewFilterUtil.isUnfilteredQuery(#studyViewFilter)") + public SampleTreatmentReport getSampleTreatmentReport(StudyViewFilter studyViewFilter) { + return treatmentCountReportUseCases + .getSampleTreatmentReportUseCase() + .execute(buildStudyViewFilterContext(studyViewFilter)); + } + + @Cacheable( + cacheResolver = "staticRepositoryCacheOneResolver", + condition = + "@cacheEnabledConfig.getEnabledClickhouse() && @studyViewFilterUtil.isUnfilteredQuery(#studyViewFilter)") + public List getGenomicDataBinCounts( + StudyViewFilter studyViewFilter, List genomicDataBinFilters) { + return ClinicalDataCountItemUtil.generateDataCountItems( + genomicDataUseCases + .getGenomicDataBinCountsUseCase() + .execute(buildStudyViewFilterContext(studyViewFilter), genomicDataBinFilters)); + } + + @Cacheable( + cacheResolver = "staticRepositoryCacheOneResolver", + condition = + "@cacheEnabledConfig.getEnabledClickhouse() && @studyViewFilterUtil.isUnfilteredQuery(#studyViewFilter)") + public List getGenericAssayDataBinCounts( + StudyViewFilter studyViewFilter, List genericAssayDataBinFilters) { + return ClinicalDataCountItemUtil.generateDataCountItems( + genericAssayUseCases + .getGenericAssayDataBinCounts() + .execute(buildStudyViewFilterContext(studyViewFilter), genericAssayDataBinFilters)); + } + + @Cacheable( + cacheResolver = "staticRepositoryCacheOneResolver", + condition = + "@cacheEnabledConfig.getEnabledClickhouse() && @studyViewFilterUtil.isUnfilteredQuery(#studyViewFilter)") + public Map getClinicalAttributeDataTypeMap( + StudyViewFilter studyViewFilter) { + return getClinicalAttributesDataTypeMapUseCase.execute(); + } + + @Cacheable( + cacheResolver = "staticRepositoryCacheOneResolver", + condition = + "@cacheEnabledConfig.getEnabledClickhouse() && @studyViewFilterUtil.isUnfilteredQuery(#studyViewFilter)") + public List getClinicalDataCounts( + StudyViewFilter studyViewFilter, List filteredAttributes) { + return clinicalDataUseCases + .getClinicalDataCountsUseCase() + .execute(buildStudyViewFilterContext(studyViewFilter), filteredAttributes); + } + + @Cacheable( + cacheResolver = "staticRepositoryCacheOneResolver", + condition = + "@cacheEnabledConfig.getEnabledClickhouse() && @studyViewFilterUtil.isUnfilteredQuery(#studyViewFilter)") + public List getClinicalAttributesForStudies(List studyIds) { + return getClinicalAttributesForStudiesUseCase.execute(studyIds); + } + + @Cacheable( + cacheResolver = "staticRepositoryCacheOneResolver", + condition = + "@cacheEnabledConfig.getEnabledClickhouse() && @studyViewFilterUtil.isUnfilteredQuery(#studyViewFilter)") + public List getCaseListDataCounts(StudyViewFilter studyViewFilter) { + return StudyViewColumnarServiceUtil.mergeCaseListCounts( + getCaseListDataCountsUseCase.execute(buildStudyViewFilterContext(studyViewFilter))); + } + + @Cacheable( + cacheResolver = "staticRepositoryCacheOneResolver", + condition = + "@cacheEnabledConfig.getEnabledClickhouse() && @studyViewFilterUtil.isUnfilteredQuery(#studyViewFilter)") + public List getPatientClinicalData( + StudyViewFilter studyViewFilter, List attributeIds) { + return clinicalDataUseCases + .getPatientClinicalDataUseCase() + .execute(buildStudyViewFilterContext(studyViewFilter), attributeIds); + } + + @Cacheable( + cacheResolver = "staticRepositoryCacheOneResolver", + condition = + "@cacheEnabledConfig.getEnabledClickhouse() && @studyViewFilterUtil.isUnfilteredQuery(#studyViewFilter)") + public List getSampleClinicalData( + StudyViewFilter studyViewFilter, List attributeIds) { + return clinicalDataUseCases + .getSampleClinicalDataUseCase() + .execute(buildStudyViewFilterContext(studyViewFilter), attributeIds); + } + + @Cacheable( + cacheResolver = "staticRepositoryCacheOneResolver", + condition = + "@cacheEnabledConfig.getEnabledClickhouse() && @studyViewFilterUtil.isUnfilteredQuery(#studyViewFilter)") + public List getCNACountsByGeneSpecific( + StudyViewFilter studyViewFilter, List genomicDataFilters) { + return genomicDataUseCases + .getCNACountsByGeneSpecificUseCase() + .execute(buildStudyViewFilterContext(studyViewFilter), genomicDataFilters); + } + + @Cacheable( + cacheResolver = "staticRepositoryCacheOneResolver", + condition = + "@cacheEnabledConfig.getEnabledClickhouse() && @studyViewFilterUtil.isUnfilteredQuery(#studyViewFilter)") + public List getGenericAssayDataCounts( + StudyViewFilter studyViewFilter, List genericAssayDataFilters) { + return genericAssayUseCases + .getGenericAssayDataCountsUseCase() + .execute(buildStudyViewFilterContext(studyViewFilter), genericAssayDataFilters); + } + + @Cacheable( + cacheResolver = "staticRepositoryCacheOneResolver", + condition = + "@cacheEnabledConfig.getEnabledClickhouse() && @studyViewFilterUtil.isUnfilteredQuery(#studyViewFilter)") + public List getMutationCountsByGeneSpecific( + StudyViewFilter studyViewFilter, List genomicDataFilters) { + List genomicDataCountItemList = new ArrayList<>(); + for (GenomicDataFilter genomicDataFilter : genomicDataFilters) { + Map counts = + genomicDataUseCases + .getMutationCountsUseCase() + .execute(buildStudyViewFilterContext(studyViewFilter), genomicDataFilter); + genomicDataCountItemList.add( + StudyViewColumnarServiceUtil.createGenomicDataCountItemFromMutationCounts( + genomicDataFilter, counts)); + } + return genomicDataCountItemList; + } + + @Cacheable( + cacheResolver = "staticRepositoryCacheOneResolver", + condition = + "@cacheEnabledConfig.getEnabledClickhouse() && @studyViewFilterUtil.isUnfilteredQuery(#studyViewFilter)") + public List getMutationTypeCountsByGeneSpecific( + StudyViewFilter studyViewFilter, List genomicDataFilters) { + return genomicDataUseCases + .getMutationCountsByTypeUseCase() + .execute(buildStudyViewFilterContext(studyViewFilter), genomicDataFilters); + } + + @Cacheable( + cacheResolver = "staticRepositoryCacheOneResolver", + condition = + "@cacheEnabledConfig.getEnabledClickhouse() && @studyViewFilterUtil.isUnfilteredQuery(#studyViewFilter)") + public List getClinicalDataForXyPlot( + StudyViewFilter studyViewFilter, + List attributeIds, + boolean shouldFilterNonEmptyClinicalData) { + return clinicalDataUseCases + .getClinicalDataForXyPlotUseCase() + .execute( + buildStudyViewFilterContext(studyViewFilter), + attributeIds, + shouldFilterNonEmptyClinicalData); + } + + private StudyViewFilterContext buildStudyViewFilterContext(StudyViewFilter studyViewFilter) { + return StudyViewFilterFactory.make( + studyViewFilter, this.customDataFilterUtil, getGenericAssayProfilesMap()); + } + + private Map> getGenericAssayProfilesMap() { + if (genericAssayProfilesMap.isEmpty()) { + buildGenericAssayProfilesMap(); + } + return genericAssayProfilesMap; + } + + private void buildGenericAssayProfilesMap() { + genericAssayProfilesMap = + genericAssayUseCases.getGenericAssayProfilesUseCase().execute().stream() + .collect( + Collectors.groupingBy( + ca -> ca.getPatientLevel() ? DataSource.PATIENT : DataSource.SAMPLE)); + } +} diff --git a/src/main/java/org/cbioportal/domain/treatment/repository/TreatmentRepository.java b/src/main/java/org/cbioportal/domain/treatment/repository/TreatmentRepository.java new file mode 100644 index 00000000000..7aacc8f377d --- /dev/null +++ b/src/main/java/org/cbioportal/domain/treatment/repository/TreatmentRepository.java @@ -0,0 +1,49 @@ +package org.cbioportal.domain.treatment.repository; + +import java.util.List; +import org.cbioportal.domain.studyview.StudyViewFilterContext; +import org.cbioportal.legacy.model.PatientTreatment; +import org.cbioportal.legacy.model.SampleTreatment; + +/** + * Repository interface for performing operations related to patient and sample treatments. This + * interface defines methods for retrieving patient treatments, sample treatments, and their + * respective total counts based on the filter criteria provided in the study view filter context. + */ +public interface TreatmentRepository { + + /** + * Retrieves the treatments associated with patients based on the provided study view filter + * context. + * + * @param studyViewFilterContext the context containing the filter criteria for the study view + * @return a list of {@link PatientTreatment} representing the treatments for patients + */ + List getPatientTreatments(StudyViewFilterContext studyViewFilterContext); + + /** + * Retrieves the total count of patient treatments based on the provided study view filter + * context. + * + * @param studyViewFilterContext the context containing the filter criteria for the study view + * @return the total count of patient treatments + */ + int getTotalPatientTreatmentCount(StudyViewFilterContext studyViewFilterContext); + + /** + * Retrieves the treatments associated with samples based on the provided study view filter + * context. + * + * @param studyViewFilterContext the context containing the filter criteria for the study view + * @return a list of {@link SampleTreatment} representing the treatments for samples + */ + List getSampleTreatments(StudyViewFilterContext studyViewFilterContext); + + /** + * Retrieves the total count of sample treatments based on the provided study view filter context. + * + * @param studyViewFilterContext the context containing the filter criteria for the study view + * @return the total count of sample treatments + */ + int getTotalSampleTreatmentCount(StudyViewFilterContext studyViewFilterContext); +} diff --git a/src/main/java/org/cbioportal/domain/treatment/usecase/GetPatientTreatmentReportUseCase.java b/src/main/java/org/cbioportal/domain/treatment/usecase/GetPatientTreatmentReportUseCase.java new file mode 100644 index 00000000000..20caa681b38 --- /dev/null +++ b/src/main/java/org/cbioportal/domain/treatment/usecase/GetPatientTreatmentReportUseCase.java @@ -0,0 +1,35 @@ +package org.cbioportal.domain.treatment.usecase; + +import org.cbioportal.domain.studyview.StudyViewFilterContext; +import org.cbioportal.domain.treatment.repository.TreatmentRepository; +import org.cbioportal.legacy.model.PatientTreatmentReport; +import org.springframework.context.annotation.Profile; +import org.springframework.stereotype.Service; + +@Service +@Profile("clickhouse") +public class GetPatientTreatmentReportUseCase { + private final TreatmentRepository treatmentRepository; + + /** + * Constructs a new use case with the given treatment repository. + * + * @param treatmentRepository the repository used to fetch treatment data + */ + public GetPatientTreatmentReportUseCase(TreatmentRepository treatmentRepository) { + this.treatmentRepository = treatmentRepository; + } + + /** + * Executes the use case to retrieve a patient treatment report based on the given filter context. + * + * @param studyViewFilterContext the filtering criteria for retrieving patient treatments + * @return a {@link PatientTreatmentReport} containing treatment data for patients + */ + public PatientTreatmentReport execute(StudyViewFilterContext studyViewFilterContext) { + var patientTreatments = treatmentRepository.getPatientTreatments(studyViewFilterContext); + var totalPatientTreatmentCount = + treatmentRepository.getTotalPatientTreatmentCount(studyViewFilterContext); + return new PatientTreatmentReport(totalPatientTreatmentCount, 0, patientTreatments); + } +} diff --git a/src/main/java/org/cbioportal/domain/treatment/usecase/GetSampleTreatmentReportUseCase.java b/src/main/java/org/cbioportal/domain/treatment/usecase/GetSampleTreatmentReportUseCase.java new file mode 100644 index 00000000000..40245d37759 --- /dev/null +++ b/src/main/java/org/cbioportal/domain/treatment/usecase/GetSampleTreatmentReportUseCase.java @@ -0,0 +1,50 @@ +package org.cbioportal.domain.treatment.usecase; + +import java.util.Set; +import java.util.stream.Stream; +import org.cbioportal.domain.studyview.StudyViewFilterContext; +import org.cbioportal.domain.treatment.repository.TreatmentRepository; +import org.cbioportal.legacy.model.SampleTreatmentReport; +import org.cbioportal.legacy.model.SampleTreatmentRow; +import org.cbioportal.legacy.model.TemporalRelation; +import org.springframework.context.annotation.Profile; +import org.springframework.stereotype.Service; + +@Service +@Profile("clickhouse") +public class GetSampleTreatmentReportUseCase { + private final TreatmentRepository treatmentRepository; + + public GetSampleTreatmentReportUseCase(TreatmentRepository treatmentRepository) { + this.treatmentRepository = treatmentRepository; + } + + /** + * Executes the use case to retrieve a sample treatment report based on the given filter context. + * + * @param studyViewFilterContext the filtering criteria for retrieving sample treatments + * @return a {@link SampleTreatmentReport} containing treatment data for samples + */ + public SampleTreatmentReport execute(StudyViewFilterContext studyViewFilterContext) { + var sampleTreatments = + treatmentRepository.getSampleTreatments(studyViewFilterContext).stream() + .flatMap( + sampleTreatment -> + Stream.of( + new SampleTreatmentRow( + TemporalRelation.Pre, + sampleTreatment.treatment(), + sampleTreatment.preSampleCount(), + Set.of()), + new SampleTreatmentRow( + TemporalRelation.Post, + sampleTreatment.treatment(), + sampleTreatment.postSampleCount(), + Set.of()))) + .filter(sampleTreatment -> sampleTreatment.getCount() > 0) + .toList(); + var totalSampleTreatmentCount = + treatmentRepository.getTotalSampleTreatmentCount(studyViewFilterContext); + return new SampleTreatmentReport(totalSampleTreatmentCount, sampleTreatments); + } +} diff --git a/src/main/java/org/cbioportal/domain/treatment/usecase/TreatmentCountReportUseCases.java b/src/main/java/org/cbioportal/domain/treatment/usecase/TreatmentCountReportUseCases.java new file mode 100644 index 00000000000..104fb09075a --- /dev/null +++ b/src/main/java/org/cbioportal/domain/treatment/usecase/TreatmentCountReportUseCases.java @@ -0,0 +1,10 @@ +package org.cbioportal.domain.treatment.usecase; + +import org.springframework.context.annotation.Profile; +import org.springframework.stereotype.Service; + +@Service +@Profile("clickhouse") +public record TreatmentCountReportUseCases( + GetPatientTreatmentReportUseCase getPatientTreatmentReportUseCase, + GetSampleTreatmentReportUseCase getSampleTreatmentReportUseCase) {} diff --git a/src/main/java/org/cbioportal/infrastructure/config/ClickhouseMyBatisConfig.java b/src/main/java/org/cbioportal/infrastructure/config/ClickhouseMyBatisConfig.java new file mode 100644 index 00000000000..4cce50cb0c3 --- /dev/null +++ b/src/main/java/org/cbioportal/infrastructure/config/ClickhouseMyBatisConfig.java @@ -0,0 +1,34 @@ +package org.cbioportal.infrastructure.config; + +import java.io.IOException; +import javax.sql.DataSource; +import org.cbioportal.legacy.persistence.mybatis.typehandler.SampleTypeTypeHandler; +import org.mybatis.spring.SqlSessionFactoryBean; +import org.mybatis.spring.annotation.MapperScan; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.context.ApplicationContext; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Profile; + +@Configuration +@Profile("clickhouse") +@MapperScan( + value = "org.cbioportal.infrastructure.repository.clickhouse", + sqlSessionFactoryRef = "sqlColumnarSessionFactory") +public class ClickhouseMyBatisConfig { + + @Bean("sqlColumnarSessionFactory") + public SqlSessionFactoryBean sqlColumnarSessionFactory( + @Qualifier("clickhouseDataSource") DataSource dataSource, + ApplicationContext applicationContext) + throws IOException { + SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean(); + sessionFactory.setDataSource(dataSource); + sessionFactory.addMapperLocations( + applicationContext.getResources("classpath:mappers/clickhouse/**/*.xml")); + + sessionFactory.setTypeHandlers(new SampleTypeTypeHandler()); + return sessionFactory; + } +} diff --git a/src/main/java/org/cbioportal/infrastructure/repository/clickhouse/alteration/ClickhouseAlterationMapper.java b/src/main/java/org/cbioportal/infrastructure/repository/clickhouse/alteration/ClickhouseAlterationMapper.java new file mode 100644 index 00000000000..1ab839f6f51 --- /dev/null +++ b/src/main/java/org/cbioportal/infrastructure/repository/clickhouse/alteration/ClickhouseAlterationMapper.java @@ -0,0 +1,89 @@ +package org.cbioportal.infrastructure.repository.clickhouse.alteration; + +import java.util.List; +import org.cbioportal.domain.studyview.StudyViewFilterContext; +import org.cbioportal.legacy.model.AlterationCountByGene; +import org.cbioportal.legacy.model.CopyNumberCountByGene; +import org.cbioportal.legacy.model.GenePanelToGene; +import org.cbioportal.legacy.model.MolecularProfile; +import org.cbioportal.legacy.persistence.helper.AlterationFilterHelper; + +/** + * Mapper interface for retrieving alteration-related data from ClickHouse. This interface provides + * methods for fetching mutated gene counts, copy number alteration counts, structural variant gene + * counts, and more, based on the provided study view filter context and alteration filters. + */ +public interface ClickhouseAlterationMapper { + /** + * Retrieves mutated gene counts based on the study view filter context and alteration filter. + * + * @param studyViewFilterContext the context of the study view filter + * @param alterationFilterHelper the helper for applying alteration filters + * @return a list of mutated genes with their respective counts + */ + List getMutatedGenes( + StudyViewFilterContext studyViewFilterContext, AlterationFilterHelper alterationFilterHelper); + + /** + * Retrieves copy number alteration (CNA) gene counts based on the study view filter context and + * alteration filter. + * + * @param studyViewFilterContext the context of the study view filter + * @param alterationFilterHelper the helper for applying alteration filters + * @return a list of CNA genes with their respective counts + */ + List getCnaGenes( + StudyViewFilterContext studyViewFilterContext, AlterationFilterHelper alterationFilterHelper); + + /** + * Retrieves structural variant gene counts based on the study view filter context and alteration + * filter. + * + * @param studyViewFilterContext the context of the study view filter + * @param alterationFilterHelper the helper for applying alteration filters + * @return a list of structural variant genes with their respective counts + */ + List getStructuralVariantGenes( + StudyViewFilterContext studyViewFilterContext, AlterationFilterHelper alterationFilterHelper); + + /** + * Retrieves the matching gene panel IDs for a given alteration type. + * + * @param studyViewFilterContext the context of the study view filter + * @param alterationType the type of alteration (e.g., mutation, CNA, etc.) + * @return a list of matching gene panel IDs + */ + List getMatchingGenePanelIds( + StudyViewFilterContext studyViewFilterContext, String alterationType); + + /** + * Retrieves the total profiled counts for a given alteration type and molecular profiles. + * + * @param studyViewFilterContext the context of the study view filter + * @param alterationType the type of alteration (e.g., mutation, CNA, etc.) + * @param molecularProfiles the list of molecular profiles to be considered + * @return a list of alteration counts by gene + */ + List getTotalProfiledCounts( + StudyViewFilterContext studyViewFilterContext, + String alterationType, + List molecularProfiles); + + /** + * Retrieves the sample profile count without panel data for a given alteration type. + * + * @param studyViewFilterContext the context of the study view filter + * @param alterationType the type of alteration (e.g., mutation, CNA, etc.) + * @return the sample profile count without panel data + */ + int getSampleProfileCountWithoutPanelData( + StudyViewFilterContext studyViewFilterContext, String alterationType); + + List getAlterationCountByGeneGivenSamplesAndMolecularProfiles( + String[] samples, String[] molecularProfiles, AlterationFilterHelper alterationFilterHelper); + + List getAlterationCountByGeneGivenPatientsAndMolecularProfiles( + String[] samples, String[] molecularProfiles, AlterationFilterHelper alterationFilterHelper); + + List getAllMolecularProfiles(); +} diff --git a/src/main/java/org/cbioportal/infrastructure/repository/clickhouse/alteration/ClickhouseAlterationRepository.java b/src/main/java/org/cbioportal/infrastructure/repository/clickhouse/alteration/ClickhouseAlterationRepository.java new file mode 100644 index 00000000000..f0884b27d64 --- /dev/null +++ b/src/main/java/org/cbioportal/infrastructure/repository/clickhouse/alteration/ClickhouseAlterationRepository.java @@ -0,0 +1,123 @@ +package org.cbioportal.infrastructure.repository.clickhouse.alteration; + +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; +import org.cbioportal.domain.alteration.repository.AlterationRepository; +import org.cbioportal.domain.studyview.StudyViewFilterContext; +import org.cbioportal.legacy.model.AlterationCountByGene; +import org.cbioportal.legacy.model.AlterationFilter; +import org.cbioportal.legacy.model.CopyNumberCountByGene; +import org.cbioportal.legacy.model.GenePanelToGene; +import org.cbioportal.legacy.model.MolecularProfile; +import org.cbioportal.legacy.persistence.helper.AlterationFilterHelper; +import org.springframework.context.annotation.Profile; +import org.springframework.stereotype.Repository; + +@Repository +@Profile("clickhouse") +public class ClickhouseAlterationRepository implements AlterationRepository { + + private final ClickhouseAlterationMapper mapper; + + public ClickhouseAlterationRepository(ClickhouseAlterationMapper mapper) { + this.mapper = mapper; + } + + @Override + public List getMutatedGenes( + StudyViewFilterContext studyViewFilterContext) { + return mapper.getMutatedGenes( + studyViewFilterContext, + AlterationFilterHelper.build(studyViewFilterContext.alterationFilter())); + } + + @Override + public List getStructuralVariantGenes( + StudyViewFilterContext studyViewFilterContext) { + return mapper.getStructuralVariantGenes( + studyViewFilterContext, + AlterationFilterHelper.build(studyViewFilterContext.alterationFilter())); + } + + @Override + public List getCnaGenes(StudyViewFilterContext studyViewFilterContext) { + return mapper.getCnaGenes( + studyViewFilterContext, + AlterationFilterHelper.build(studyViewFilterContext.alterationFilter())); + } + + @Override + public Map getTotalProfiledCounts( + StudyViewFilterContext studyViewFilterContext, + String alterationType, + List molecularProfiles) { + return mapper + .getTotalProfiledCounts(studyViewFilterContext, alterationType, molecularProfiles) + .stream() + .collect( + Collectors.groupingBy( + AlterationCountByGene::getHugoGeneSymbol, + Collectors.mapping( + AlterationCountByGene::getNumberOfProfiledCases, + Collectors.summingInt(Integer::intValue)))); + } + + @Override + public Map> getMatchingGenePanelIds( + StudyViewFilterContext studyViewFilterContext, String alterationType) { + return mapper.getMatchingGenePanelIds(studyViewFilterContext, alterationType).stream() + .collect( + Collectors.groupingBy( + GenePanelToGene::getHugoGeneSymbol, + Collectors.mapping(GenePanelToGene::getGenePanelId, Collectors.toSet()))); + } + + @Override + public int getSampleProfileCountWithoutPanelData( + StudyViewFilterContext studyViewFilterContext, String alterationType) { + return mapper.getSampleProfileCountWithoutPanelData(studyViewFilterContext, alterationType); + } + + /** + * @param samples + * @param molecularProfiles + * @return + */ + @Override + public List getAlterationCountByGeneGivenSamplesAndMolecularProfiles( + Collection samples, + Collection molecularProfiles, + AlterationFilter alterationFilter) { + return mapper.getAlterationCountByGeneGivenSamplesAndMolecularProfiles( + samples.toArray(new String[0]), + molecularProfiles.toArray(molecularProfiles.toArray(new String[0])), + AlterationFilterHelper.build(alterationFilter)); + } + + /** + * @param samples + * @param molecularProfiles + * @return + */ + @Override + public List getAlterationCountByGeneGivenPatientsAndMolecularProfiles( + Collection samples, + Collection molecularProfiles, + AlterationFilter alterationFilter) { + return mapper.getAlterationCountByGeneGivenPatientsAndMolecularProfiles( + samples.toArray(new String[0]), + molecularProfiles.toArray(molecularProfiles.toArray(new String[0])), + AlterationFilterHelper.build(alterationFilter)); + } + + /** + * @return + */ + @Override + public List getAllMolecularProfiles() { + return mapper.getAllMolecularProfiles(); + } +} diff --git a/src/main/java/org/cbioportal/infrastructure/repository/clickhouse/cancerstudy/ClickhouseCancerStudyMapper.java b/src/main/java/org/cbioportal/infrastructure/repository/clickhouse/cancerstudy/ClickhouseCancerStudyMapper.java new file mode 100644 index 00000000000..282240fd864 --- /dev/null +++ b/src/main/java/org/cbioportal/infrastructure/repository/clickhouse/cancerstudy/ClickhouseCancerStudyMapper.java @@ -0,0 +1,51 @@ +package org.cbioportal.infrastructure.repository.clickhouse.cancerstudy; + +import java.util.List; +import org.apache.ibatis.annotations.Param; +import org.cbioportal.domain.cancerstudy.CancerStudyMetadata; +import org.cbioportal.domain.studyview.StudyViewFilterContext; +import org.cbioportal.shared.SortAndSearchCriteria; + +/** + * Provides methods for retrieving cancer study metadata from a ClickHouse database. This interface + * defines the contract for fetching detailed and summarized metadata for cancer studies based on + * specified criteria. + */ +public interface ClickhouseCancerStudyMapper { + /** + * Retrieves detailed metadata for cancer studies based on the provided sorting, search criteria, + * and a list of study IDs. This method is intended to return comprehensive information about each + * study. + * + * @param sortAndSearchCriteria the criteria used for sorting and searching the cancer study + * metadata. This includes parameters such as sort direction, sort by field, and search + * keywords. + * @param studyIds a list of study IDs to filter the results. If empty, all studies matching the + * criteria should be returned. + * @return a list of {@link CancerStudyMetadata} containing detailed metadata for each study that + * matches the provided criteria and study IDs. The list may be empty if no studies match the + * criteria. + */ + List getCancerStudiesMetadata( + SortAndSearchCriteria sortAndSearchCriteria, List studyIds); + + /** + * Retrieves a summarized version of cancer study metadata based on the provided sorting, search + * criteria, and a list of study IDs. This method is intended to return a concise overview of each + * study. + * + * @param sortAndSearchCriteria the criteria used for sorting and searching the cancer study + * metadata. This includes parameters such as sort direction, sort by field, and search + * keywords. + * @param studyIds a list of study IDs to filter the results. If empty, all studies matching the + * criteria should be returned. + * @return a list of {@link CancerStudyMetadata} containing summarized metadata for each study + * that matches the provided criteria and study IDs. The list may be empty if no studies match + * the criteria. + */ + List getCancerStudiesMetadataSummary( + SortAndSearchCriteria sortAndSearchCriteria, List studyIds); + + List getFilteredStudyIds( + @Param("studyViewFilterContext") StudyViewFilterContext studyViewFilterContext); +} diff --git a/src/main/java/org/cbioportal/infrastructure/repository/clickhouse/cancerstudy/ClickhouseCancerStudyRepository.java b/src/main/java/org/cbioportal/infrastructure/repository/clickhouse/cancerstudy/ClickhouseCancerStudyRepository.java new file mode 100644 index 00000000000..656d3922c10 --- /dev/null +++ b/src/main/java/org/cbioportal/infrastructure/repository/clickhouse/cancerstudy/ClickhouseCancerStudyRepository.java @@ -0,0 +1,66 @@ +package org.cbioportal.infrastructure.repository.clickhouse.cancerstudy; + +import java.util.List; +import org.cbioportal.domain.cancerstudy.CancerStudyMetadata; +import org.cbioportal.domain.cancerstudy.repository.CancerStudyRepository; +import org.cbioportal.domain.studyview.StudyViewFilterContext; +import org.cbioportal.shared.SortAndSearchCriteria; +import org.springframework.context.annotation.Profile; +import org.springframework.stereotype.Repository; + +/** + * Repository implementation for accessing cancer study metadata from ClickHouse. This class + * delegates database queries to {@link ClickhouseCancerStudyMapper}. + */ +@Repository +@Profile("clickhouse") +public class ClickhouseCancerStudyRepository implements CancerStudyRepository { + + private final ClickhouseCancerStudyMapper cancerStudyMapper; + + /** + * Constructs a new {@code ClickhouseCancerStudyRepository} with the required mapper. + * + * @param cancerStudyMapper the mapper responsible for executing ClickHouse queries + */ + public ClickhouseCancerStudyRepository(ClickhouseCancerStudyMapper cancerStudyMapper) { + this.cancerStudyMapper = cancerStudyMapper; + } + + /** + * Retrieves detailed metadata for all cancer studies. + * + * @param sortAndSearchCriteria the criteria used for sorting and searching the cancer study + * metadata. This includes parameters such as sort direction, sort by field, and search + * keywords. + * @return a list of {@link CancerStudyMetadata} containing detailed metadata for each study + */ + @Override + public List getCancerStudiesMetadata( + SortAndSearchCriteria sortAndSearchCriteria) { + return cancerStudyMapper.getCancerStudiesMetadata(sortAndSearchCriteria, List.of()); + } + + /** + * Retrieves a summarized version of cancer study metadata. + * + * @param sortAndSearchCriteria the criteria used for sorting and searching the cancer study + * metadata. This includes parameters such as sort direction, sort by field, and search + * keywords. + * @return a list of {@link CancerStudyMetadata} containing summarized metadata for each study + */ + @Override + public List getCancerStudiesMetadataSummary( + SortAndSearchCriteria sortAndSearchCriteria) { + return cancerStudyMapper.getCancerStudiesMetadataSummary(sortAndSearchCriteria, List.of()); + } + + /** + * @param studyViewFilterContext + * @return + */ + @Override + public List getFilteredStudyIds(StudyViewFilterContext studyViewFilterContext) { + return cancerStudyMapper.getFilteredStudyIds(studyViewFilterContext); + } +} diff --git a/src/main/java/org/cbioportal/infrastructure/repository/clickhouse/clinical_attributes/ClickhouseClinicalAttributesMapper.java b/src/main/java/org/cbioportal/infrastructure/repository/clickhouse/clinical_attributes/ClickhouseClinicalAttributesMapper.java new file mode 100644 index 00000000000..e16b7b388e4 --- /dev/null +++ b/src/main/java/org/cbioportal/infrastructure/repository/clickhouse/clinical_attributes/ClickhouseClinicalAttributesMapper.java @@ -0,0 +1,26 @@ +package org.cbioportal.infrastructure.repository.clickhouse.clinical_attributes; + +import java.util.List; +import org.cbioportal.legacy.model.ClinicalAttribute; + +/** + * Mapper interface for retrieving clinical attributes data from ClickHouse. This interface provides + * methods to fetch clinical attributes either globally or for specific studies. + */ +public interface ClickhouseClinicalAttributesMapper { + + /** + * Retrieves the list of all clinical attributes. + * + * @return a list of clinical attributes + */ + List getClinicalAttributes(); + + /** + * Retrieves the list of clinical attributes for the specified study IDs. + * + * @param studyIds the list of study IDs to filter by + * @return a list of clinical attributes for the given studies + */ + List getClinicalAttributesForStudies(List studyIds); +} diff --git a/src/main/java/org/cbioportal/infrastructure/repository/clickhouse/clinical_attributes/ClickhouseClinicalAttributesRepository.java b/src/main/java/org/cbioportal/infrastructure/repository/clickhouse/clinical_attributes/ClickhouseClinicalAttributesRepository.java new file mode 100644 index 00000000000..0bb601a91ca --- /dev/null +++ b/src/main/java/org/cbioportal/infrastructure/repository/clickhouse/clinical_attributes/ClickhouseClinicalAttributesRepository.java @@ -0,0 +1,64 @@ +package org.cbioportal.infrastructure.repository.clickhouse.clinical_attributes; + +import java.util.EnumMap; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; +import org.cbioportal.domain.clinical_attributes.repository.ClinicalAttributesRepository; +import org.cbioportal.legacy.model.ClinicalAttribute; +import org.cbioportal.legacy.persistence.enums.DataSource; +import org.cbioportal.legacy.web.parameter.ClinicalDataType; +import org.springframework.context.annotation.Profile; +import org.springframework.stereotype.Repository; + +@Repository +@Profile("clickhouse") +public class ClickhouseClinicalAttributesRepository implements ClinicalAttributesRepository { + + private Map> clinicalAttributesMap = + new EnumMap<>(DataSource.class); + + private final ClickhouseClinicalAttributesMapper mapper; + + public ClickhouseClinicalAttributesRepository(ClickhouseClinicalAttributesMapper mapper) { + this.mapper = mapper; + } + + @Override + public List getClinicalAttributesForStudies(List studyIds) { + return mapper.getClinicalAttributesForStudies(studyIds); + } + + @Override + public Map getClinicalAttributeDatatypeMap() { + if (clinicalAttributesMap.isEmpty()) { + buildClinicalAttributeNameMap(); + } + + Map attributeDatatypeMap = new HashMap<>(); + + clinicalAttributesMap + .get(DataSource.SAMPLE) + .forEach( + attribute -> attributeDatatypeMap.put(attribute.getAttrId(), ClinicalDataType.SAMPLE)); + + clinicalAttributesMap + .get(DataSource.PATIENT) + .forEach( + attribute -> attributeDatatypeMap.put(attribute.getAttrId(), ClinicalDataType.PATIENT)); + + return attributeDatatypeMap; + } + + private void buildClinicalAttributeNameMap() { + clinicalAttributesMap = + mapper.getClinicalAttributes().stream() + .collect( + Collectors.groupingBy( + ca -> + ca.getPatientAttribute().booleanValue() + ? DataSource.PATIENT + : DataSource.SAMPLE)); + } +} diff --git a/src/main/java/org/cbioportal/infrastructure/repository/clickhouse/clinical_data/ClickhouseClinicalDataMapper.java b/src/main/java/org/cbioportal/infrastructure/repository/clickhouse/clinical_data/ClickhouseClinicalDataMapper.java new file mode 100644 index 00000000000..5044cc485af --- /dev/null +++ b/src/main/java/org/cbioportal/infrastructure/repository/clickhouse/clinical_data/ClickhouseClinicalDataMapper.java @@ -0,0 +1,47 @@ +package org.cbioportal.infrastructure.repository.clickhouse.clinical_data; + +import java.util.List; +import org.cbioportal.domain.studyview.StudyViewFilterContext; +import org.cbioportal.legacy.model.ClinicalData; +import org.cbioportal.legacy.model.ClinicalDataCountItem; + +/** + * Mapper interface for retrieving clinical data from ClickHouse. This interface provides methods to + * fetch clinical data counts and clinical data for samples and patients. + */ +public interface ClickhouseClinicalDataMapper { + + /** + * Retrieves clinical data counts based on the study view filter context, attribute IDs, and + * filtered attribute values. + * + * @param studyViewFilterContext the context of the study view filter + * @param attributeIds the list of attribute IDs to filter by + * @param filteredAttributeValues the list of filtered attribute values + * @return a list of clinical data count items + */ + List getClinicalDataCounts( + StudyViewFilterContext studyViewFilterContext, + List attributeIds, + List filteredAttributeValues); + + /** + * Retrieves sample clinical data based on the study view filter context and attribute IDs. + * + * @param studyViewFilterContext the context of the study view filter + * @param attributeIds the list of attribute IDs to filter by + * @return a list of sample clinical data + */ + List getSampleClinicalDataFromStudyViewFilter( + StudyViewFilterContext studyViewFilterContext, List attributeIds); + + /** + * Retrieves patient clinical data based on the study view filter context and attribute IDs. + * + * @param studyViewFilterContext the context of the study view filter + * @param attributeIds the list of attribute IDs to filter by + * @return a list of patient clinical data + */ + List getPatientClinicalDataFromStudyViewFilter( + StudyViewFilterContext studyViewFilterContext, List attributeIds); +} diff --git a/src/main/java/org/cbioportal/infrastructure/repository/clickhouse/clinical_data/ClickhouseClinicalDataRepository.java b/src/main/java/org/cbioportal/infrastructure/repository/clickhouse/clinical_data/ClickhouseClinicalDataRepository.java new file mode 100644 index 00000000000..b0e1a691483 --- /dev/null +++ b/src/main/java/org/cbioportal/infrastructure/repository/clickhouse/clinical_data/ClickhouseClinicalDataRepository.java @@ -0,0 +1,44 @@ +package org.cbioportal.infrastructure.repository.clickhouse.clinical_data; + +import java.util.Collections; +import java.util.List; +import org.cbioportal.domain.clinical_data.repository.ClinicalDataRepository; +import org.cbioportal.domain.studyview.StudyViewFilterContext; +import org.cbioportal.legacy.model.ClinicalData; +import org.cbioportal.legacy.model.ClinicalDataCountItem; +import org.springframework.context.annotation.Profile; +import org.springframework.stereotype.Repository; + +@Repository +@Profile("clickhouse") +public class ClickhouseClinicalDataRepository implements ClinicalDataRepository { + + private static final List FILTERED_CLINICAL_ATTR_VALUES = Collections.emptyList(); + + private final ClickhouseClinicalDataMapper mapper; + + public ClickhouseClinicalDataRepository(ClickhouseClinicalDataMapper mapper) { + this.mapper = mapper; + } + + @Override + public List getPatientClinicalData( + StudyViewFilterContext studyViewFilterContext, List filteredAttributes) { + return mapper.getPatientClinicalDataFromStudyViewFilter( + studyViewFilterContext, filteredAttributes); + } + + @Override + public List getSampleClinicalData( + StudyViewFilterContext studyViewFilterContext, List filteredAttributes) { + return mapper.getSampleClinicalDataFromStudyViewFilter( + studyViewFilterContext, filteredAttributes); + } + + @Override + public List getClinicalDataCounts( + StudyViewFilterContext studyViewFilterContext, List filteredAttributes) { + return mapper.getClinicalDataCounts( + studyViewFilterContext, filteredAttributes, FILTERED_CLINICAL_ATTR_VALUES); + } +} diff --git a/src/main/java/org/cbioportal/infrastructure/repository/clickhouse/clinical_event/ClickhouseClinicalEventMapper.java b/src/main/java/org/cbioportal/infrastructure/repository/clickhouse/clinical_event/ClickhouseClinicalEventMapper.java new file mode 100644 index 00000000000..ce4b04040a9 --- /dev/null +++ b/src/main/java/org/cbioportal/infrastructure/repository/clickhouse/clinical_event/ClickhouseClinicalEventMapper.java @@ -0,0 +1,22 @@ +package org.cbioportal.infrastructure.repository.clickhouse.clinical_event; + +import java.util.List; +import org.apache.ibatis.annotations.Param; +import org.cbioportal.domain.studyview.StudyViewFilterContext; +import org.cbioportal.legacy.model.ClinicalEventTypeCount; + +/** + * Mapper interface for retrieving clinical event type data from ClickHouse. This interface provides + * a method to fetch clinical event type counts based on the study view filter context. + */ +public interface ClickhouseClinicalEventMapper { + + /** + * Retrieves the clinical event type counts based on the study view filter context. + * + * @param studyViewFilterContext the context of the study view filter + * @return a list of clinical event type counts + */ + List getClinicalEventTypeCounts( + @Param("studyViewFilterContext") StudyViewFilterContext studyViewFilterContext); +} diff --git a/src/main/java/org/cbioportal/infrastructure/repository/clickhouse/clinical_event/ClickhouseClinicalEventRepository.java b/src/main/java/org/cbioportal/infrastructure/repository/clickhouse/clinical_event/ClickhouseClinicalEventRepository.java new file mode 100644 index 00000000000..b7ff04fb03c --- /dev/null +++ b/src/main/java/org/cbioportal/infrastructure/repository/clickhouse/clinical_event/ClickhouseClinicalEventRepository.java @@ -0,0 +1,25 @@ +package org.cbioportal.infrastructure.repository.clickhouse.clinical_event; + +import java.util.List; +import org.cbioportal.domain.clinical_event.repository.ClinicalEventRepository; +import org.cbioportal.domain.studyview.StudyViewFilterContext; +import org.cbioportal.legacy.model.ClinicalEventTypeCount; +import org.springframework.context.annotation.Profile; +import org.springframework.stereotype.Repository; + +@Repository +@Profile("clickhouse") +public class ClickhouseClinicalEventRepository implements ClinicalEventRepository { + + private final ClickhouseClinicalEventMapper mapper; + + public ClickhouseClinicalEventRepository(ClickhouseClinicalEventMapper mapper) { + this.mapper = mapper; + } + + @Override + public List getClinicalEventTypeCounts( + StudyViewFilterContext studyViewFilterContext) { + return mapper.getClinicalEventTypeCounts(studyViewFilterContext); + } +} diff --git a/src/main/java/org/cbioportal/infrastructure/repository/clickhouse/generic_assay/ClickhouseGenericAssayMapper.java b/src/main/java/org/cbioportal/infrastructure/repository/clickhouse/generic_assay/ClickhouseGenericAssayMapper.java new file mode 100644 index 00000000000..e6df0801f9c --- /dev/null +++ b/src/main/java/org/cbioportal/infrastructure/repository/clickhouse/generic_assay/ClickhouseGenericAssayMapper.java @@ -0,0 +1,59 @@ +package org.cbioportal.infrastructure.repository.clickhouse.generic_assay; + +import java.util.List; +import org.cbioportal.domain.studyview.StudyViewFilterContext; +import org.cbioportal.legacy.model.ClinicalDataCount; +import org.cbioportal.legacy.model.GenericAssayDataCountItem; +import org.cbioportal.legacy.model.MolecularProfile; +import org.cbioportal.legacy.web.parameter.GenericAssayDataBinFilter; +import org.cbioportal.legacy.web.parameter.GenericAssayDataFilter; + +/** + * Mapper interface for retrieving generic assay data from ClickHouse. This interface provides + * methods to fetch molecular profiles and generic assay data counts, as well as filtered molecular + * profiles by alteration type. + */ +public interface ClickhouseGenericAssayMapper { + + /** + * Retrieves the list of molecular profiles from the generic assay data. + * + * @return a list of molecular profiles + */ + List getGenericAssayProfiles(); + + /** + * Retrieves the filtered molecular profiles based on the study view filter context and alteration + * type. + * + * @param studyViewFilterContext the context of the study view filter + * @param alterationType the alteration type (e.g., mutation, CNA) + * @return a list of filtered molecular profiles + */ + List getFilteredMolecularProfilesByAlterationType( + StudyViewFilterContext studyViewFilterContext, String alterationType); + + /** + * Retrieves the generic assay data bin counts based on the study view filter context and the + * provided bin filters. + * + * @param studyViewFilterContext the context of the study view filter + * @param genericAssayDataBinFilters the list of bin filters + * @return a list of generic assay data bin counts + */ + List getGenericAssayDataBinCounts( + StudyViewFilterContext studyViewFilterContext, + List genericAssayDataBinFilters); + + /** + * Retrieves the generic assay data counts based on the study view filter context and the provided + * data filters. + * + * @param studyViewFilterContext the context of the study view filter + * @param genericAssayDataFilters the list of data filters + * @return a list of generic assay data counts + */ + List getGenericAssayDataCounts( + StudyViewFilterContext studyViewFilterContext, + List genericAssayDataFilters); +} diff --git a/src/main/java/org/cbioportal/infrastructure/repository/clickhouse/generic_assay/ClickhouseGenericAssayRepository.java b/src/main/java/org/cbioportal/infrastructure/repository/clickhouse/generic_assay/ClickhouseGenericAssayRepository.java new file mode 100644 index 00000000000..57135cab69a --- /dev/null +++ b/src/main/java/org/cbioportal/infrastructure/repository/clickhouse/generic_assay/ClickhouseGenericAssayRepository.java @@ -0,0 +1,49 @@ +package org.cbioportal.infrastructure.repository.clickhouse.generic_assay; + +import java.util.List; +import org.cbioportal.domain.generic_assay.repository.GenericAssayRepository; +import org.cbioportal.domain.studyview.StudyViewFilterContext; +import org.cbioportal.legacy.model.ClinicalDataCount; +import org.cbioportal.legacy.model.GenericAssayDataCountItem; +import org.cbioportal.legacy.model.MolecularProfile; +import org.cbioportal.legacy.web.parameter.GenericAssayDataBinFilter; +import org.cbioportal.legacy.web.parameter.GenericAssayDataFilter; +import org.springframework.context.annotation.Profile; +import org.springframework.stereotype.Repository; + +@Repository +@Profile("clickhouse") +public class ClickhouseGenericAssayRepository implements GenericAssayRepository { + + private final ClickhouseGenericAssayMapper mapper; + + public ClickhouseGenericAssayRepository(ClickhouseGenericAssayMapper mapper) { + this.mapper = mapper; + } + + @Override + public List getGenericAssayProfiles() { + return mapper.getGenericAssayProfiles(); + } + + @Override + public List getFilteredMolecularProfilesByAlterationType( + StudyViewFilterContext studyViewFilterContext, String alterationType) { + return mapper.getFilteredMolecularProfilesByAlterationType( + studyViewFilterContext, alterationType); + } + + @Override + public List getGenericAssayDataBinCounts( + StudyViewFilterContext studyViewFilterContext, + List genericAssayDataBinFilters) { + return mapper.getGenericAssayDataBinCounts(studyViewFilterContext, genericAssayDataBinFilters); + } + + @Override + public List getGenericAssayDataCounts( + StudyViewFilterContext studyViewFilterContext, + List genericAssayDataFilters) { + return mapper.getGenericAssayDataCounts(studyViewFilterContext, genericAssayDataFilters); + } +} diff --git a/src/main/java/org/cbioportal/infrastructure/repository/clickhouse/genomic_data/ClickhouseGenomicDataMapper.java b/src/main/java/org/cbioportal/infrastructure/repository/clickhouse/genomic_data/ClickhouseGenomicDataMapper.java new file mode 100644 index 00000000000..dbdf59993fa --- /dev/null +++ b/src/main/java/org/cbioportal/infrastructure/repository/clickhouse/genomic_data/ClickhouseGenomicDataMapper.java @@ -0,0 +1,71 @@ +package org.cbioportal.infrastructure.repository.clickhouse.genomic_data; + +import java.util.List; +import java.util.Map; +import org.apache.ibatis.annotations.Param; +import org.cbioportal.domain.studyview.StudyViewFilterContext; +import org.cbioportal.legacy.model.ClinicalDataCount; +import org.cbioportal.legacy.model.GenomicDataCount; +import org.cbioportal.legacy.model.GenomicDataCountItem; +import org.cbioportal.legacy.web.parameter.GenomicDataBinFilter; +import org.cbioportal.legacy.web.parameter.GenomicDataFilter; + +/** + * Mapper interface for retrieving genomic data from ClickHouse. This interface provides methods to + * fetch genomic data counts, including mutation counts and CNAs, based on the study view filter + * context and genomic data filters. + */ +public interface ClickhouseGenomicDataMapper { + + /** + * Retrieves the molecular profile sample counts based on the study view filter context. + * + * @param studyViewFilterContext the context of the study view filter + * @return a list of genomic data counts by molecular profile + */ + List getMolecularProfileSampleCounts( + @Param("studyViewFilterContext") StudyViewFilterContext studyViewFilterContext); + + /** + * Retrieves the genomic data bin counts based on the study view filter context and genomic data + * bin filters. + * + * @param studyViewFilterContext the context of the study view filter + * @param genomicDataBinFilters the list of genomic data bin filters + * @return a list of genomic data bin counts + */ + List getGenomicDataBinCounts( + StudyViewFilterContext studyViewFilterContext, + List genomicDataBinFilters); + + /** + * Retrieves CNAs counts based on the study view filter context and genomic data filters. + * + * @param studyViewFilterContext the context of the study view filter + * @param genomicDataFilters the list of genomic data filters + * @return a list of CNA counts + */ + List getCNACounts( + StudyViewFilterContext studyViewFilterContext, List genomicDataFilters); + + /** + * Retrieves mutation counts based on the study view filter context and genomic data filter. + * + * @param studyViewFilterContext the context of the study view filter + * @param genomicDataFilter the genomic data filter + * @return a map of mutation counts by gene + */ + Map getMutationCounts( + StudyViewFilterContext studyViewFilterContext, GenomicDataFilter genomicDataFilter); + + /** + * Retrieves mutation counts by type based on the study view filter context and genomic data + * filters. + * + * @param studyViewFilterContext the context of the study view filter + * @param genomicDataFilters the list of genomic data filters + * @return a list of mutation counts by type + */ + List getMutationCountsByType( + StudyViewFilterContext studyViewFilterContext, List genomicDataFilters); +} diff --git a/src/main/java/org/cbioportal/infrastructure/repository/clickhouse/genomic_data/ClickhouseGenomicDataRepository.java b/src/main/java/org/cbioportal/infrastructure/repository/clickhouse/genomic_data/ClickhouseGenomicDataRepository.java new file mode 100644 index 00000000000..9a39f4196b1 --- /dev/null +++ b/src/main/java/org/cbioportal/infrastructure/repository/clickhouse/genomic_data/ClickhouseGenomicDataRepository.java @@ -0,0 +1,55 @@ +package org.cbioportal.infrastructure.repository.clickhouse.genomic_data; + +import java.util.List; +import java.util.Map; +import org.cbioportal.domain.genomic_data.repository.GenomicDataRepository; +import org.cbioportal.domain.studyview.StudyViewFilterContext; +import org.cbioportal.legacy.model.ClinicalDataCount; +import org.cbioportal.legacy.model.GenomicDataCount; +import org.cbioportal.legacy.model.GenomicDataCountItem; +import org.cbioportal.legacy.web.parameter.GenomicDataBinFilter; +import org.cbioportal.legacy.web.parameter.GenomicDataFilter; +import org.springframework.context.annotation.Profile; +import org.springframework.stereotype.Repository; + +@Repository +@Profile("clickhouse") +public class ClickhouseGenomicDataRepository implements GenomicDataRepository { + + private final ClickhouseGenomicDataMapper mapper; + + public ClickhouseGenomicDataRepository(ClickhouseGenomicDataMapper mapper) { + this.mapper = mapper; + } + + @Override + public List getMolecularProfileSampleCounts( + StudyViewFilterContext studyViewFilterContext) { + return mapper.getMolecularProfileSampleCounts(studyViewFilterContext); + } + + @Override + public List getGenomicDataBinCounts( + StudyViewFilterContext studyViewFilterContext, + List genomicDataBinFilters) { + return mapper.getGenomicDataBinCounts(studyViewFilterContext, genomicDataBinFilters); + } + + @Override + public List getCNACounts( + StudyViewFilterContext studyViewFilterContext, List genomicDataFilters) { + return mapper.getCNACounts(studyViewFilterContext, genomicDataFilters); + } + + @Override + public Map getMutationCounts( + StudyViewFilterContext studyViewFilterContext, GenomicDataFilter genomicDataFilter) { + return mapper.getMutationCounts(studyViewFilterContext, genomicDataFilter); + } + + @Override + public List getMutationCountsByType( + StudyViewFilterContext studyViewFilterContext, List genomicDataFilters) { + return mapper.getMutationCountsByType(studyViewFilterContext, genomicDataFilters); + } +} diff --git a/src/main/java/org/cbioportal/infrastructure/repository/clickhouse/patient/ClickhousePatientMapper.java b/src/main/java/org/cbioportal/infrastructure/repository/clickhouse/patient/ClickhousePatientMapper.java new file mode 100644 index 00000000000..265d0169fa6 --- /dev/null +++ b/src/main/java/org/cbioportal/infrastructure/repository/clickhouse/patient/ClickhousePatientMapper.java @@ -0,0 +1,31 @@ +package org.cbioportal.infrastructure.repository.clickhouse.patient; + +import java.util.List; +import org.apache.ibatis.annotations.Param; +import org.cbioportal.domain.studyview.StudyViewFilterContext; +import org.cbioportal.legacy.model.CaseListDataCount; + +/** + * Mapper interface for retrieving patient data from ClickHouse. This interface provides methods for + * fetching patient counts and case list data counts. + */ +public interface ClickhousePatientMapper { + + /** + * Retrieves the patient count based on the study view filter context. + * + * @param studyViewFilterContext the context of the study view filter + * @return the patient count + */ + int getPatientCount( + @Param("studyViewFilterContext") StudyViewFilterContext studyViewFilterContext); + + /** + * Retrieves case list data counts based on the study view filter context. + * + * @param studyViewFilterContext the context of the study view filter + * @return a list of case list data counts + */ + List getCaseListDataCounts( + @Param("studyViewFilterContext") StudyViewFilterContext studyViewFilterContext); +} diff --git a/src/main/java/org/cbioportal/infrastructure/repository/clickhouse/patient/ClickhousePatientRepository.java b/src/main/java/org/cbioportal/infrastructure/repository/clickhouse/patient/ClickhousePatientRepository.java new file mode 100644 index 00000000000..727568d49ca --- /dev/null +++ b/src/main/java/org/cbioportal/infrastructure/repository/clickhouse/patient/ClickhousePatientRepository.java @@ -0,0 +1,30 @@ +package org.cbioportal.infrastructure.repository.clickhouse.patient; + +import java.util.List; +import org.cbioportal.domain.patient.repository.PatientRepository; +import org.cbioportal.domain.studyview.StudyViewFilterContext; +import org.cbioportal.legacy.model.CaseListDataCount; +import org.springframework.context.annotation.Profile; +import org.springframework.stereotype.Repository; + +@Repository +@Profile("clickhouse") +public class ClickhousePatientRepository implements PatientRepository { + + private final ClickhousePatientMapper mapper; + + public ClickhousePatientRepository(ClickhousePatientMapper mapper) { + this.mapper = mapper; + } + + @Override + public int getFilteredPatientCount(StudyViewFilterContext studyViewFilterContext) { + return mapper.getPatientCount(studyViewFilterContext); + } + + @Override + public List getCaseListDataCounts( + StudyViewFilterContext studyViewFilterContext) { + return mapper.getCaseListDataCounts(studyViewFilterContext); + } +} diff --git a/src/main/java/org/cbioportal/infrastructure/repository/clickhouse/sample/ClickhouseSampleMapper.java b/src/main/java/org/cbioportal/infrastructure/repository/clickhouse/sample/ClickhouseSampleMapper.java new file mode 100644 index 00000000000..e100fb93475 --- /dev/null +++ b/src/main/java/org/cbioportal/infrastructure/repository/clickhouse/sample/ClickhouseSampleMapper.java @@ -0,0 +1,75 @@ +package org.cbioportal.infrastructure.repository.clickhouse.sample; + +import java.util.List; +import org.apache.ibatis.annotations.Param; +import org.cbioportal.domain.sample.Sample; +import org.cbioportal.domain.studyview.StudyViewFilterContext; +import org.cbioportal.legacy.model.meta.BaseMeta; + +/** + * Mapper interface for retrieving sample data from ClickHouse. This interface provides methods for + * fetching filtered samples and sample counts based on the study view filter context. + */ +public interface ClickhouseSampleMapper { + + /** + * Retrieves filtered samples based on the study view filter context. + * + * @param studyViewFilterContext the context of the study view filter + * @return a list of filtered samples + */ + List getFilteredSamples( + @Param("studyViewFilterContext") StudyViewFilterContext studyViewFilterContext); + + /** + * Retrieves the sample count based on the study view filter context. + * + * @param studyViewFilterContext the context of the study view filter + * @return the sample count + */ + int getSampleCount( + @Param("studyViewFilterContext") StudyViewFilterContext studyViewFilterContext); + + BaseMeta getMetaSamples( + List studyIds, String patientId, List sampleIds, String keyword); + + BaseMeta getMetaSamplesBySampleListIds(List sampleListIds); + + List getSamples( + List studyIds, + String patientId, + List sampleIds, + String keyword, + Integer limit, + Integer offset, + String sortBy, + String direction); + + List getSummarySamples( + List studyIds, + String patientId, + List sampleIds, + String keyword, + Integer limit, + Integer offset, + String sortBy, + String direction); + + List getDetailedSamples( + List studyIds, + String patientId, + List sampleIds, + String keyword, + Integer limit, + Integer offset, + String sortBy, + String direction); + + List getSamplesBySampleListIds(List sampleListIds); + + List getSummarySamplesBySampleListIds(List sampleListIds); + + List getDetailedSamplesBySampleListIds(List sampleListIds); + + Sample getSample(String studyId, String sampleId); +} diff --git a/src/main/java/org/cbioportal/infrastructure/repository/clickhouse/sample/ClickhouseSampleRepository.java b/src/main/java/org/cbioportal/infrastructure/repository/clickhouse/sample/ClickhouseSampleRepository.java new file mode 100644 index 00000000000..1d694076a3a --- /dev/null +++ b/src/main/java/org/cbioportal/infrastructure/repository/clickhouse/sample/ClickhouseSampleRepository.java @@ -0,0 +1,216 @@ +package org.cbioportal.infrastructure.repository.clickhouse.sample; + +import java.util.Collections; +import java.util.List; +import org.cbioportal.domain.sample.Sample; +import org.cbioportal.domain.sample.repository.SampleRepository; +import org.cbioportal.domain.studyview.StudyViewFilterContext; +import org.cbioportal.legacy.model.meta.BaseMeta; +import org.cbioportal.legacy.persistence.mybatis.util.PaginationCalculator; +import org.cbioportal.shared.enums.ProjectionType; +import org.springframework.context.annotation.Profile; +import org.springframework.stereotype.Repository; + +@Repository +@Profile("clickhouse") +public class ClickhouseSampleRepository implements SampleRepository { + + private final ClickhouseSampleMapper mapper; + + public ClickhouseSampleRepository(ClickhouseSampleMapper clickhouseSampleMapper) { + this.mapper = clickhouseSampleMapper; + } + + @Override + public List getFilteredSamples(StudyViewFilterContext studyViewFilterContext) { + return mapper.getFilteredSamples(studyViewFilterContext); + } + + @Override + public int getFilteredSamplesCount(StudyViewFilterContext studyViewFilterContext) { + return mapper.getSampleCount(studyViewFilterContext); + } + + @Override + public List fetchSamples( + List studyIds, List sampleIds, ProjectionType projection) { + return switch (projection) { + case ID -> mapper.getSamples(studyIds, null, sampleIds, null, 0, 0, null, null); + case SUMMARY -> mapper.getSummarySamples(studyIds, null, sampleIds, null, 0, 0, null, null); + case DETAILED -> mapper.getDetailedSamples(studyIds, null, sampleIds, null, 0, 0, null, null); + default -> Collections.emptyList(); + }; + } + + @Override + public List fetchSamplesBySampleListIds( + List sampleListIds, ProjectionType projection) { + return switch (projection) { + case ID -> mapper.getSamplesBySampleListIds(sampleListIds); + case SUMMARY -> mapper.getSummarySamplesBySampleListIds(sampleListIds); + case DETAILED -> mapper.getDetailedSamplesBySampleListIds(sampleListIds); + default -> Collections.emptyList(); + }; + } + + @Override + public BaseMeta fetchMetaSamples(List studyIds, List sampleIds) { + return mapper.getMetaSamples(studyIds, null, sampleIds, null); + } + + @Override + public BaseMeta fetchMetaSamplesBySampleListIds(List sampleListIds) { + return mapper.getMetaSamplesBySampleListIds(sampleListIds); + } + + @Override + public List getAllSamplesInStudy( + String studyId, + ProjectionType projection, + Integer pageSize, + Integer pageNumber, + String sortBy, + String direction) { + return switch (projection) { + case ID -> + mapper.getSamples( + Collections.singletonList(studyId), + null, + null, + null, + pageSize, + PaginationCalculator.offset(pageSize, pageNumber), + sortBy, + direction); + case SUMMARY -> + mapper.getSummarySamples( + Collections.singletonList(studyId), + null, + null, + null, + pageSize, + PaginationCalculator.offset(pageSize, pageNumber), + sortBy, + direction); + case DETAILED -> + mapper.getDetailedSamples( + Collections.singletonList(studyId), + null, + null, + null, + pageSize, + PaginationCalculator.offset(pageSize, pageNumber), + sortBy, + direction); + default -> Collections.emptyList(); + }; + } + + @Override + public BaseMeta getMetaSamplesInStudy(String studyId) { + return mapper.getMetaSamples(Collections.singletonList(studyId), null, null, null); + } + + @Override + public Sample getSampleInStudy(String studyId, String sampleId) { + return mapper.getSample(studyId, sampleId); + } + + @Override + public List getAllSamplesOfPatientInStudy( + String studyId, + String patientId, + ProjectionType projection, + Integer pageSize, + Integer pageNumber, + String sortBy, + String direction) { + return switch (projection) { + case ID -> + mapper.getSamples( + Collections.singletonList(studyId), + patientId, + null, + null, + pageSize, + PaginationCalculator.offset(pageSize, pageNumber), + sortBy, + direction); + case SUMMARY -> + mapper.getSummarySamples( + Collections.singletonList(studyId), + patientId, + null, + null, + pageSize, + PaginationCalculator.offset(pageSize, pageNumber), + sortBy, + direction); + case DETAILED -> + mapper.getDetailedSamples( + Collections.singletonList(studyId), + patientId, + null, + null, + pageSize, + PaginationCalculator.offset(pageSize, pageNumber), + sortBy, + direction); + default -> Collections.emptyList(); + }; + } + + @Override + public BaseMeta getMetaSamplesOfPatientInStudy(String studyId, String patientId) { + return mapper.getMetaSamples(Collections.singletonList(studyId), patientId, null, null); + } + + @Override + public List getAllSamples( + String keyword, + List studyIds, + ProjectionType projection, + Integer pageSize, + Integer pageNumber, + String sort, + String direction) { + return switch (projection) { + case ID -> + mapper.getSamples( + studyIds, + null, + null, + keyword, + pageSize, + PaginationCalculator.offset(pageSize, pageNumber), + sort, + direction); + case SUMMARY -> + mapper.getSummarySamples( + studyIds, + null, + null, + keyword, + pageSize, + PaginationCalculator.offset(pageSize, pageNumber), + sort, + direction); + case DETAILED -> + mapper.getDetailedSamples( + studyIds, + null, + null, + keyword, + pageSize, + PaginationCalculator.offset(pageSize, pageNumber), + sort, + direction); + default -> Collections.emptyList(); + }; + } + + @Override + public BaseMeta getMetaSamples(String keyword, List studyIds) { + return mapper.getMetaSamples(studyIds, null, null, keyword); + } +} diff --git a/src/main/java/org/cbioportal/infrastructure/repository/clickhouse/studyview/ClickhouseStudyViewFilterMapper.java b/src/main/java/org/cbioportal/infrastructure/repository/clickhouse/studyview/ClickhouseStudyViewFilterMapper.java new file mode 100644 index 00000000000..e93cce096b6 --- /dev/null +++ b/src/main/java/org/cbioportal/infrastructure/repository/clickhouse/studyview/ClickhouseStudyViewFilterMapper.java @@ -0,0 +1,3 @@ +package org.cbioportal.infrastructure.repository.clickhouse.studyview; + +public interface ClickhouseStudyViewFilterMapper {} diff --git a/src/main/java/org/cbioportal/infrastructure/repository/clickhouse/treatment/ClickhouseTreatmentMapper.java b/src/main/java/org/cbioportal/infrastructure/repository/clickhouse/treatment/ClickhouseTreatmentMapper.java new file mode 100644 index 00000000000..861d92a2216 --- /dev/null +++ b/src/main/java/org/cbioportal/infrastructure/repository/clickhouse/treatment/ClickhouseTreatmentMapper.java @@ -0,0 +1,50 @@ +package org.cbioportal.infrastructure.repository.clickhouse.treatment; + +import java.util.List; +import org.apache.ibatis.annotations.Param; +import org.cbioportal.domain.studyview.StudyViewFilterContext; +import org.cbioportal.legacy.model.PatientTreatment; +import org.cbioportal.legacy.model.SampleTreatment; + +/** + * Mapper interface for retrieving treatment-related data from ClickHouse. This interface provides + * methods to fetch patient treatments, sample treatment counts, and more. + */ +public interface ClickhouseTreatmentMapper { + + /** + * Retrieves patient treatments based on the study view filter context. + * + * @param studyViewFilterContext the context of the study view filter + * @return a list of patient treatments + */ + List getPatientTreatments( + @Param("studyViewFilterContext") StudyViewFilterContext studyViewFilterContext); + + /** + * Retrieves the patient treatment counts based on the study view filter context. + * + * @param studyViewFilterContext the context of the study view filter + * @return the patient treatment count + */ + int getPatientTreatmentCounts( + @Param("studyViewFilterContext") StudyViewFilterContext studyViewFilterContext); + + /** + * Retrieves sample treatment counts based on the study view filter context. + * + * @param studyViewFilterContext the context of the study view filter + * @return a list of sample treatment counts + */ + List getSampleTreatmentCounts( + @Param("studyViewFilterContext") StudyViewFilterContext studyViewFilterContext); + + /** + * Retrieves the total sample treatment counts based on the study view filter context. + * + * @param studyViewFilterContext the context of the study view filter + * @return the total sample treatment count + */ + int getTotalSampleTreatmentCounts( + @Param("studyViewFilterContext") StudyViewFilterContext studyViewFilterContext); +} diff --git a/src/main/java/org/cbioportal/infrastructure/repository/clickhouse/treatment/ClickhouseTreatmentRepository.java b/src/main/java/org/cbioportal/infrastructure/repository/clickhouse/treatment/ClickhouseTreatmentRepository.java new file mode 100644 index 00000000000..3797cc18d8b --- /dev/null +++ b/src/main/java/org/cbioportal/infrastructure/repository/clickhouse/treatment/ClickhouseTreatmentRepository.java @@ -0,0 +1,40 @@ +package org.cbioportal.infrastructure.repository.clickhouse.treatment; + +import java.util.List; +import org.cbioportal.domain.studyview.StudyViewFilterContext; +import org.cbioportal.domain.treatment.repository.TreatmentRepository; +import org.cbioportal.legacy.model.PatientTreatment; +import org.cbioportal.legacy.model.SampleTreatment; +import org.springframework.context.annotation.Profile; +import org.springframework.stereotype.Repository; + +@Repository +@Profile("clickhouse") +public class ClickhouseTreatmentRepository implements TreatmentRepository { + private final ClickhouseTreatmentMapper mapper; + + public ClickhouseTreatmentRepository(ClickhouseTreatmentMapper mapper) { + this.mapper = mapper; + } + + @Override + public List getPatientTreatments( + StudyViewFilterContext studyViewFilterContext) { + return mapper.getPatientTreatments(studyViewFilterContext); + } + + @Override + public int getTotalPatientTreatmentCount(StudyViewFilterContext studyViewFilterContext) { + return mapper.getPatientTreatmentCounts(studyViewFilterContext); + } + + @Override + public List getSampleTreatments(StudyViewFilterContext studyViewFilterContext) { + return mapper.getSampleTreatmentCounts(studyViewFilterContext); + } + + @Override + public int getTotalSampleTreatmentCount(StudyViewFilterContext studyViewFilterContext) { + return mapper.getTotalSampleTreatmentCounts(studyViewFilterContext); + } +} diff --git a/src/main/java/org/cbioportal/infrastructure/service/BasicDataBinner.java b/src/main/java/org/cbioportal/infrastructure/service/BasicDataBinner.java new file mode 100644 index 00000000000..a4e6a32a940 --- /dev/null +++ b/src/main/java/org/cbioportal/infrastructure/service/BasicDataBinner.java @@ -0,0 +1,423 @@ +package org.cbioportal.infrastructure.service; + +import static java.util.Collections.emptyList; +import static java.util.stream.Collectors.toMap; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; +import org.cbioportal.domain.studyview.StudyViewService; +import org.cbioportal.legacy.model.Binnable; +import org.cbioportal.legacy.model.ClinicalData; +import org.cbioportal.legacy.model.ClinicalDataBin; +import org.cbioportal.legacy.model.ClinicalDataCount; +import org.cbioportal.legacy.model.ClinicalDataCountItem; +import org.cbioportal.legacy.model.DataBin; +import org.cbioportal.legacy.model.GenericAssayDataBin; +import org.cbioportal.legacy.model.GenomicDataBin; +import org.cbioportal.legacy.service.CustomDataService; +import org.cbioportal.legacy.service.util.CustomDataSession; +import org.cbioportal.legacy.web.columnar.util.CustomDataFilterUtil; +import org.cbioportal.legacy.web.columnar.util.NewClinicalDataBinUtil; +import org.cbioportal.legacy.web.parameter.ClinicalDataBinCountFilter; +import org.cbioportal.legacy.web.parameter.ClinicalDataBinFilter; +import org.cbioportal.legacy.web.parameter.ClinicalDataType; +import org.cbioportal.legacy.web.parameter.DataBinCountFilter; +import org.cbioportal.legacy.web.parameter.DataBinFilter; +import org.cbioportal.legacy.web.parameter.DataBinMethod; +import org.cbioportal.legacy.web.parameter.GenericAssayDataBinCountFilter; +import org.cbioportal.legacy.web.parameter.GenericAssayDataBinFilter; +import org.cbioportal.legacy.web.parameter.GenomicDataBinCountFilter; +import org.cbioportal.legacy.web.parameter.GenomicDataBinFilter; +import org.cbioportal.legacy.web.parameter.SampleIdentifier; +import org.cbioportal.legacy.web.parameter.StudyViewFilter; +import org.cbioportal.legacy.web.util.DataBinner; +import org.cbioportal.legacy.web.util.StudyViewFilterUtil; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.context.annotation.Profile; +import org.springframework.stereotype.Component; + +// BasicDataBinner is a generalized class derived from ClinicalDataBinner +// BasicDataBinner should eventually deprecate ClinicalDataBinner +// we are using BasicDataBinner for genomic data, generic assay, and custom data bin counts now +// but BasicDataBinner can support clinical data counts too +// after we switched clinical data counts to use this, then We can remove ClinicalDataBinner +@Deprecated(forRemoval = true) +@Component +@Profile("clickhouse") +public class BasicDataBinner { + private final StudyViewService studyViewService; + private final DataBinner dataBinner; + private final CustomDataFilterUtil customDataFilterUtil; + private final CustomDataService customDataService; + private final StudyViewFilterUtil studyViewFilterUtil; + + @Autowired + public BasicDataBinner( + StudyViewService studyViewService, + DataBinner dataBinner, + CustomDataFilterUtil customDataFilterUtil, + CustomDataService customDataService, + StudyViewFilterUtil studyViewFilterUtil) { + this.studyViewService = studyViewService; + this.dataBinner = dataBinner; + this.customDataFilterUtil = customDataFilterUtil; + this.customDataService = customDataService; + this.studyViewFilterUtil = studyViewFilterUtil; + } + + // convert from counts to clinical data + private List convertCountsToData(List clinicalDataCounts) { + return clinicalDataCounts.stream() + .map(NewClinicalDataBinUtil::generateClinicalDataFromClinicalDataCount) + .flatMap(Collection::stream) + .toList(); + } + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + public + List getDataBins( + DataBinMethod dataBinMethod, T dataBinCountFilter, boolean shouldRemoveSelfFromFilter) { + // get data bin filters based on the type of the filter + // either Genomic data or Generic Assay data or custom data or clinical data + List dataBinFilters = fetchDataBinFilters(dataBinCountFilter); + StudyViewFilter studyViewFilter = dataBinCountFilter.getStudyViewFilter(); + // define result variables + List resultDataBins = Collections.emptyList(); + // if no data bin filters or no study view filer object is passed in + // return empty result + if (dataBinFilters.isEmpty() || studyViewFilter == null) { + return resultDataBins; + } + + if (shouldRemoveSelfFromFilter && dataBinFilters.size() == 1) { + removeSelfFromFilter(dataBinFilters.get(0), studyViewFilter); + } + + List uniqueKeys = dataBinFilters.stream().map(this::getDataBinFilterUniqueKey).toList(); + + // a new StudyView filter to partially filter by study and sample ids only + // we need this additional partial filter because we always need to know the bins generated for + // the initial state + // which allows us to keep the number of bins and bin ranges consistent even if there are + // additional data filters. + // we only want to update the counts for each bin, we don't want to regenerate the bins for the + // filtered data. + // NOTE: partial filter is only needed when dataBinMethod == DataBinMethod.STATIC but that's + // always the case + // for the frontend implementation. we can't really use dataBinMethod == DataBinMethod.DYNAMIC + // because of the + // complication it brings to the frontend visualization and filtering + StudyViewFilter partialFilter = new StudyViewFilter(); + partialFilter.setStudyIds(studyViewFilter.getStudyIds()); + partialFilter.setSampleIdentifiers(studyViewFilter.getSampleIdentifiers()); + + // we need to fetch data for the partial filter in order to generate the bins for initial state + // we use the filtered data to calculate the counts for each bin, we do not regenerate bins for + // the filtered data + List unfilteredClinicalDataCounts; + List filteredClinicalDataCounts; + Map attributeDatatypeMap; + switch (dataBinCountFilter) { + // TODO: first case is to support clinical data, but clinical data is not using this now. We + // should update controller to use this method later + case ClinicalDataBinCountFilter clinicalDataBinCountFilter + when !customDataService.getCustomDataSessions(uniqueKeys).isEmpty() -> { + Map customDataSessions = + customDataService.getCustomDataSessions(uniqueKeys); + List unfilteredSampleIdentifiers = + studyViewService.getFilteredSamples(partialFilter).stream() + .map( + sample -> + studyViewFilterUtil.buildSampleIdentifier( + sample.cancerStudyIdentifier(), sample.stableId())) + .toList(); + unfilteredClinicalDataCounts = + customDataFilterUtil.getCustomDataCounts( + unfilteredSampleIdentifiers, customDataSessions); + List filteredSampleIdentifiers = + studyViewService.getFilteredSamples(studyViewFilter).stream() + .map( + sample -> + studyViewFilterUtil.buildSampleIdentifier( + sample.cancerStudyIdentifier(), sample.stableId())) + .toList(); + filteredClinicalDataCounts = + customDataFilterUtil.getCustomDataCounts(filteredSampleIdentifiers, customDataSessions); + attributeDatatypeMap = + customDataSessions.entrySet().stream() + .collect(toMap(Map.Entry::getKey, NewClinicalDataBinUtil::getDataType)); + } + case ClinicalDataBinCountFilter clinicalDataBinCountFilter -> { + unfilteredClinicalDataCounts = + studyViewService.getClinicalDataCounts(partialFilter, uniqueKeys); + filteredClinicalDataCounts = + studyViewService.getClinicalDataCounts(studyViewFilter, uniqueKeys); + attributeDatatypeMap = studyViewService.getClinicalAttributeDataTypeMap(studyViewFilter); + } + case GenomicDataBinCountFilter genomicDataBinCountFilter -> { + unfilteredClinicalDataCounts = + studyViewService.getGenomicDataBinCounts( + partialFilter, genomicDataBinCountFilter.getGenomicDataBinFilters()); + filteredClinicalDataCounts = + studyViewService.getGenomicDataBinCounts( + studyViewFilter, genomicDataBinCountFilter.getGenomicDataBinFilters()); + attributeDatatypeMap = Collections.emptyMap(); + } + case GenericAssayDataBinCountFilter genericAssayDataBinCountFilter -> { + unfilteredClinicalDataCounts = + studyViewService.getGenericAssayDataBinCounts( + partialFilter, genericAssayDataBinCountFilter.getGenericAssayDataBinFilters()); + filteredClinicalDataCounts = + studyViewService.getGenericAssayDataBinCounts( + studyViewFilter, genericAssayDataBinCountFilter.getGenericAssayDataBinFilters()); + attributeDatatypeMap = Collections.emptyMap(); + } + default -> { + unfilteredClinicalDataCounts = Collections.emptyList(); + filteredClinicalDataCounts = Collections.emptyList(); + attributeDatatypeMap = Collections.emptyMap(); + } + } + + // TODO ignoring conflictingPatientAttributeIds for now + List unfilteredClinicalData = + convertCountsToData( + unfilteredClinicalDataCounts.stream().flatMap(c -> c.getCounts().stream()).toList()); + List filteredClinicalData = + convertCountsToData( + filteredClinicalDataCounts.stream().flatMap(c -> c.getCounts().stream()).toList()); + + Map> unfilteredClinicalDataByAttributeId = + unfilteredClinicalData.stream().collect(Collectors.groupingBy(Binnable::getAttrId)); + + Map> filteredClinicalDataByAttributeId = + filteredClinicalData.stream().collect(Collectors.groupingBy(Binnable::getAttrId)); + + // TODO: need to update attributeDatatypeMap to include patient level data for Generic Assay + // Profiles + if (dataBinMethod == DataBinMethod.STATIC) { + if (!unfilteredClinicalData.isEmpty()) { + resultDataBins = + calculateStaticDataBins( + dataBinner, + dataBinFilters, + attributeDatatypeMap, + unfilteredClinicalDataByAttributeId, + filteredClinicalDataByAttributeId); + } + } + // TODO: need to update attributeDatatypeMap to include patient level data for Generic Assay + // Profiles + else { // dataBinMethod == DataBinMethod.DYNAMIC + // TODO we should consider removing dynamic binning support + // we never use dynamic binning in the frontend because number of bins and the bin ranges can + // change + // each time there is a new filter which makes the frontend implementation complicated + if (!filteredClinicalData.isEmpty()) { + resultDataBins = + calculateDynamicDataBins( + dataBinner, + dataBinFilters, + attributeDatatypeMap, + filteredClinicalDataByAttributeId); + } + } + + return resultDataBins; + } + + private void removeSelfFromFilter( + S dataBinFilter, StudyViewFilter studyViewFilter) { + switch (dataBinFilter) { + case ClinicalDataBinFilter clinicalDataBinFilter -> { + if (studyViewFilter.getClinicalDataFilters() != null) { + studyViewFilter + .getClinicalDataFilters() + .removeIf(f -> f.getAttributeId().equals(clinicalDataBinFilter.getAttributeId())); + } + if (studyViewFilter.getCustomDataFilters() != null) { + studyViewFilter + .getCustomDataFilters() + .removeIf(f -> f.getAttributeId().equals(clinicalDataBinFilter.getAttributeId())); + } + } + case GenomicDataBinFilter genomicDataBinFilter + when studyViewFilter.getGenomicDataFilters() != null -> + studyViewFilter + .getGenomicDataFilters() + .removeIf( + f -> + f.getHugoGeneSymbol().equals(genomicDataBinFilter.getHugoGeneSymbol()) + && f.getProfileType().equals(genomicDataBinFilter.getProfileType())); + case GenericAssayDataBinFilter genericAssayDataBinFilter + when studyViewFilter.getGenericAssayDataFilters() != null -> + studyViewFilter + .getGenericAssayDataFilters() + .removeIf( + f -> + f.getStableId().equals(genericAssayDataBinFilter.getStableId()) + && f.getProfileType().equals(genericAssayDataBinFilter.getProfileType())); + default -> { + // Do not remove any filters + } + } + } + + private List fetchDataBinFilters( + T dataBinCountFilter) { + switch (dataBinCountFilter) { + case ClinicalDataBinCountFilter clinicalDataBinCountFilter -> { + return (List) clinicalDataBinCountFilter.getAttributes(); + } + case GenomicDataBinCountFilter genomicDataBinCountFilter -> { + return (List) genomicDataBinCountFilter.getGenomicDataBinFilters(); + } + case GenericAssayDataBinCountFilter genericAssayDataBinCountFilter -> { + return (List) genericAssayDataBinCountFilter.getGenericAssayDataBinFilters(); + } + default -> { + return new ArrayList<>(); + } + } + } + + private String getDataBinFilterUniqueKey(S dataBinFilter) { + switch (dataBinFilter) { + case ClinicalDataBinFilter clinicalDataBinFilter -> { + return clinicalDataBinFilter.getAttributeId(); + } + case GenomicDataBinFilter genomicDataBinFilter -> { + return genomicDataBinFilter.getHugoGeneSymbol() + genomicDataBinFilter.getProfileType(); + } + case GenericAssayDataBinFilter genericAssayDataBinFilter -> { + return genericAssayDataBinFilter.getStableId() + genericAssayDataBinFilter.getProfileType(); + } + default -> { + return null; + } + } + } + + private List calculateStaticDataBins( + DataBinner dataBinner, + List dataBinFilters, + Map attributeDatatypeMap, + Map> unfilteredClinicalDataByAttributeId, + Map> filteredClinicalDataByAttributeId) { + List result = new ArrayList<>(); + + for (T dataBinFilter : dataBinFilters) { + // if there is data for requested attribute + if (attributeDatatypeMap.isEmpty() + || attributeDatatypeMap.containsKey(getDataBinFilterUniqueKey(dataBinFilter))) { + List dataBins = + dataBinner + .calculateClinicalDataBins( + dataBinFilter, + filteredClinicalDataByAttributeId.getOrDefault( + getDataBinFilterUniqueKey(dataBinFilter), emptyList()), + unfilteredClinicalDataByAttributeId.getOrDefault( + getDataBinFilterUniqueKey(dataBinFilter), emptyList())) + .stream() + .map(dataBin -> (U) transform(dataBinFilter, dataBin)) + .toList(); + + result.addAll(dataBins); + } + } + + return result; + } + + private List calculateDynamicDataBins( + DataBinner dataBinner, + List dataBinFilters, + Map attributeDatatypeMap, + Map> filteredClinicalDataByAttributeId) { + List result = new ArrayList<>(); + + for (T dataBinFilter : dataBinFilters) { + // if there is data for requested attribute + if (attributeDatatypeMap.isEmpty() + || attributeDatatypeMap.containsKey(getDataBinFilterUniqueKey(dataBinFilter))) { + List dataBins = + dataBinner + .calculateDataBins( + dataBinFilter, + filteredClinicalDataByAttributeId.getOrDefault( + getDataBinFilterUniqueKey(dataBinFilter), emptyList())) + .stream() + .map(dataBin -> (U) transform(dataBinFilter, dataBin)) + .toList(); + result.addAll(dataBins); + } + } + + return result; + } + + private T transform( + S dataBinFilter, DataBin dataBin) { + switch (dataBinFilter) { + case ClinicalDataBinFilter clinicalDataBinFilter -> { + return (T) dataBinToClinicalDataBin(clinicalDataBinFilter, dataBin); + } + case GenomicDataBinFilter genomicDataBinFilter -> { + return (T) dataBintoGenomicDataBin(genomicDataBinFilter, dataBin); + } + case GenericAssayDataBinFilter genericAssayDataBinFilter -> { + return (T) dataBintoGenericAssayDataBin(genericAssayDataBinFilter, dataBin); + } + default -> { + return null; + } + } + } + + private ClinicalDataBin dataBinToClinicalDataBin( + ClinicalDataBinFilter attribute, DataBin dataBin) { + ClinicalDataBin clinicalDataBin = new ClinicalDataBin(); + clinicalDataBin.setAttributeId(attribute.getAttributeId()); + setCommonDataBinProperties(dataBin, clinicalDataBin); + return clinicalDataBin; + } + + private GenomicDataBin dataBintoGenomicDataBin( + GenomicDataBinFilter genomicDataBinFilter, DataBin dataBin) { + GenomicDataBin genomicDataBin = new GenomicDataBin(); + genomicDataBin.setHugoGeneSymbol(genomicDataBinFilter.getHugoGeneSymbol()); + genomicDataBin.setProfileType(genomicDataBinFilter.getProfileType()); + setCommonDataBinProperties(dataBin, genomicDataBin); + return genomicDataBin; + } + + private GenericAssayDataBin dataBintoGenericAssayDataBin( + GenericAssayDataBinFilter genericAssayDataBinFilter, DataBin dataBin) { + GenericAssayDataBin genericAssayDataBin = new GenericAssayDataBin(); + genericAssayDataBin.setStableId(genericAssayDataBinFilter.getStableId()); + genericAssayDataBin.setProfileType(genericAssayDataBinFilter.getProfileType()); + setCommonDataBinProperties(dataBin, genericAssayDataBin); + return genericAssayDataBin; + } + + private void setCommonDataBinProperties( + DataBin originalDataBin, U targetDatabin) { + targetDatabin.setCount(originalDataBin.getCount()); + if (originalDataBin.getSpecialValue() != null) { + targetDatabin.setSpecialValue(originalDataBin.getSpecialValue()); + } + if (originalDataBin.getStart() != null) { + targetDatabin.setStart(originalDataBin.getStart()); + } + if (originalDataBin.getEnd() != null) { + targetDatabin.setEnd(originalDataBin.getEnd()); + } + } +} diff --git a/src/main/java/org/cbioportal/infrastructure/service/ClinicalDataBinner.java b/src/main/java/org/cbioportal/infrastructure/service/ClinicalDataBinner.java new file mode 100644 index 00000000000..a0f187eda03 --- /dev/null +++ b/src/main/java/org/cbioportal/infrastructure/service/ClinicalDataBinner.java @@ -0,0 +1,131 @@ +package org.cbioportal.infrastructure.service; + +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; +import org.cbioportal.domain.studyview.StudyViewService; +import org.cbioportal.legacy.model.Binnable; +import org.cbioportal.legacy.model.ClinicalData; +import org.cbioportal.legacy.model.ClinicalDataBin; +import org.cbioportal.legacy.model.ClinicalDataCount; +import org.cbioportal.legacy.model.ClinicalDataCountItem; +import org.cbioportal.legacy.web.columnar.util.NewClinicalDataBinUtil; +import org.cbioportal.legacy.web.parameter.ClinicalDataBinCountFilter; +import org.cbioportal.legacy.web.parameter.ClinicalDataBinFilter; +import org.cbioportal.legacy.web.parameter.ClinicalDataType; +import org.cbioportal.legacy.web.parameter.DataBinMethod; +import org.cbioportal.legacy.web.parameter.StudyViewFilter; +import org.cbioportal.legacy.web.util.DataBinner; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.context.annotation.Profile; +import org.springframework.stereotype.Component; + +@Deprecated(forRemoval = true) +@Component +@Profile("clickhouse") +public class ClinicalDataBinner { + private final StudyViewService studyViewService; + private final DataBinner dataBinner; + + @Autowired + public ClinicalDataBinner(StudyViewService studyViewService, DataBinner dataBinner) { + this.studyViewService = studyViewService; + this.dataBinner = dataBinner; + } + + private List convertCountsToData(List clinicalDataCounts) { + return clinicalDataCounts.stream() + .map(NewClinicalDataBinUtil::generateClinicalDataFromClinicalDataCount) + .flatMap(Collection::stream) + .toList(); + } + + @Cacheable( + cacheResolver = "staticRepositoryCacheOneResolver", + condition = "@cacheEnabledConfig.getEnabled()") + public List fetchClinicalDataBinCounts( + DataBinMethod dataBinMethod, + ClinicalDataBinCountFilter dataBinCountFilter, + boolean shouldRemoveSelfFromFilter) { + List attributes = dataBinCountFilter.getAttributes(); + StudyViewFilter studyViewFilter = dataBinCountFilter.getStudyViewFilter(); + + if (shouldRemoveSelfFromFilter) { + studyViewFilter = NewClinicalDataBinUtil.removeSelfFromFilter(dataBinCountFilter); + } + + List attributeIds = + attributes.stream().map(ClinicalDataBinFilter::getAttributeId).toList(); + + // a new StudyView filter to partially filter by study and sample ids only + // we need this additional partial filter because we always need to know the bins generated for + // the initial state + // which allows us to keep the number of bins and bin ranges consistent even if there are + // additional data filters. + // we only want to update the counts for each bin, we don't want to regenerate the bins for the + // filtered data. + // NOTE: partial filter is only needed when dataBinMethod == DataBinMethod.STATIC but that's + // always the case + // for the frontend implementation. we can't really use dataBinMethod == DataBinMethod.DYNAMIC + // because of the + // complication it brings to the frontend visualization and filtering + StudyViewFilter partialFilter = new StudyViewFilter(); + partialFilter.setStudyIds(studyViewFilter.getStudyIds()); + partialFilter.setSampleIdentifiers(studyViewFilter.getSampleIdentifiers()); + + // we need the clinical data for the partial filter in order to generate the bins for initial + // state + // we use the filtered data to calculate the counts for each bin, we do not regenerate bins for + // the filtered data + List unfilteredClinicalDataCounts = + studyViewService.getClinicalDataCounts(partialFilter, attributeIds); + List filteredClinicalDataCounts = + studyViewService.getClinicalDataCounts(studyViewFilter, attributeIds); + + // TODO ignoring conflictingPatientAttributeIds for now + List unfilteredClinicalData = + convertCountsToData( + unfilteredClinicalDataCounts.stream().flatMap(c -> c.getCounts().stream()).toList()); + List filteredClinicalData = + convertCountsToData( + filteredClinicalDataCounts.stream().flatMap(c -> c.getCounts().stream()).toList()); + + Map attributeDatatypeMap = + studyViewService.getClinicalAttributeDataTypeMap(studyViewFilter); + + Map> unfilteredClinicalDataByAttributeId = + unfilteredClinicalData.stream().collect(Collectors.groupingBy(Binnable::getAttrId)); + + Map> filteredClinicalDataByAttributeId = + filteredClinicalData.stream().collect(Collectors.groupingBy(Binnable::getAttrId)); + + List clinicalDataBins = Collections.emptyList(); + + if (dataBinMethod == DataBinMethod.STATIC) { + if (!unfilteredClinicalData.isEmpty()) { + clinicalDataBins = + NewClinicalDataBinUtil.calculateStaticDataBins( + dataBinner, + attributes, + attributeDatatypeMap, + unfilteredClinicalDataByAttributeId, + filteredClinicalDataByAttributeId); + } + } else { // dataBinMethod == DataBinMethod.DYNAMIC + // TODO we should consider removing dynamic binning support + // we never use dynamic binning in the frontend because number of bins and the bin ranges can + // change + // each time there is a new filter which makes the frontend implementation complicated + if (!filteredClinicalData.isEmpty()) { + clinicalDataBins = + NewClinicalDataBinUtil.calculateDynamicDataBins( + dataBinner, attributes, attributeDatatypeMap, filteredClinicalDataByAttributeId); + } + } + + return clinicalDataBins; + } +} diff --git a/src/main/java/org/cbioportal/legacy/model/AlleleSpecificCopyNumber.java b/src/main/java/org/cbioportal/legacy/model/AlleleSpecificCopyNumber.java new file mode 100644 index 00000000000..af401ac0a40 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/AlleleSpecificCopyNumber.java @@ -0,0 +1,79 @@ +package org.cbioportal.legacy.model; + +import java.io.Serializable; + +public class AlleleSpecificCopyNumber implements Serializable { + + private Integer ascnIntegerCopyNumber; + private String ascnMethod; + private Float ccfExpectedCopiesUpper; + private Float ccfExpectedCopies; + private String clonal; + private Integer minorCopyNumber; + private Integer expectedAltCopies; + private Integer totalCopyNumber; + + public Integer getAscnIntegerCopyNumber() { + return ascnIntegerCopyNumber; + } + + public void setAscnIntegerCopyNumber(Integer ascnIntegerCopyNumber) { + this.ascnIntegerCopyNumber = ascnIntegerCopyNumber; + } + + public String getAscnMethod() { + return ascnMethod; + } + + public void setAscnMethod(String ascnMethod) { + this.ascnMethod = ascnMethod; + } + + public Float getCcfExpectedCopiesUpper() { + return ccfExpectedCopiesUpper; + } + + public void setCcfExpectedCopiesUpper(Float ccfExpectedCopiesUpper) { + this.ccfExpectedCopiesUpper = ccfExpectedCopiesUpper; + } + + public Float getCcfExpectedCopies() { + return ccfExpectedCopies; + } + + public void setCcfExpectedCopies(Float ccfExpectedCopies) { + this.ccfExpectedCopies = ccfExpectedCopies; + } + + public String getClonal() { + return clonal; + } + + public void setClonal(String clonal) { + this.clonal = clonal; + } + + public Integer getMinorCopyNumber() { + return minorCopyNumber; + } + + public void setMinorCopyNumber(Integer minorCopyNumber) { + this.minorCopyNumber = minorCopyNumber; + } + + public Integer getExpectedAltCopies() { + return expectedAltCopies; + } + + public void setExpectedAltCopies(Integer expectedAltCopies) { + this.expectedAltCopies = expectedAltCopies; + } + + public Integer getTotalCopyNumber() { + return totalCopyNumber; + } + + public void setTotalCopyNumber(Integer totalCopyNumber) { + this.totalCopyNumber = totalCopyNumber; + } +} diff --git a/src/main/java/org/cbioportal/legacy/model/Alteration.java b/src/main/java/org/cbioportal/legacy/model/Alteration.java new file mode 100644 index 00000000000..1a5dde05b94 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/Alteration.java @@ -0,0 +1,97 @@ +package org.cbioportal.legacy.model; + +import jakarta.validation.constraints.NotNull; + +public class Alteration extends UniqueKeyBase { + + @NotNull private String molecularProfileId; + @NotNull private String sampleId; + @NotNull private String patientId; + @NotNull private Integer entrezGeneId; + private Gene gene; + @NotNull private String studyId; + private String driverFilter; + private String driverFilterAnnotation; + private String driverTiersFilter; + private String driverTiersFilterAnnotation; + + public String getMolecularProfileId() { + return molecularProfileId; + } + + public void setMolecularProfileId(String molecularProfileId) { + this.molecularProfileId = molecularProfileId; + } + + public String getSampleId() { + return sampleId; + } + + public void setSampleId(String sampleId) { + this.sampleId = sampleId; + } + + public String getPatientId() { + return patientId; + } + + public void setPatientId(String patientId) { + this.patientId = patientId; + } + + public Integer getEntrezGeneId() { + return entrezGeneId; + } + + public void setEntrezGeneId(Integer entrezGeneId) { + this.entrezGeneId = entrezGeneId; + } + + public Gene getGene() { + return gene; + } + + public void setGene(Gene gene) { + this.gene = gene; + } + + public String getStudyId() { + return studyId; + } + + public void setStudyId(String studyId) { + this.studyId = studyId; + } + + public String getDriverFilter() { + return driverFilter; + } + + public void setDriverFilter(String driverFilter) { + this.driverFilter = driverFilter; + } + + public String getDriverFilterAnnotation() { + return driverFilterAnnotation; + } + + public void setDriverFilterAnnotation(String driverFilterAnnotation) { + this.driverFilterAnnotation = driverFilterAnnotation; + } + + public String getDriverTiersFilter() { + return driverTiersFilter; + } + + public void setDriverTiersFilter(String driverTiersFilter) { + this.driverTiersFilter = driverTiersFilter; + } + + public String getDriverTiersFilterAnnotation() { + return driverTiersFilterAnnotation; + } + + public void setDriverTiersFilterAnnotation(String driverTiersFilterAnnotation) { + this.driverTiersFilterAnnotation = driverTiersFilterAnnotation; + } +} diff --git a/src/main/java/org/cbioportal/legacy/model/AlterationCountBase.java b/src/main/java/org/cbioportal/legacy/model/AlterationCountBase.java new file mode 100644 index 00000000000..01ff171dab3 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/AlterationCountBase.java @@ -0,0 +1,59 @@ +package org.cbioportal.legacy.model; + +import java.io.Serializable; +import java.util.Set; + +public abstract class AlterationCountBase implements Serializable { + + private Integer numberOfAlteredCases; + private Integer numberOfAlteredCasesOnPanel; + private Integer totalCount; + private Integer numberOfProfiledCases; + private Set matchingGenePanelIds; + + public Integer getNumberOfAlteredCases() { + return numberOfAlteredCases; + } + + public void setNumberOfAlteredCases(Integer numberOfAlteredCases) { + this.numberOfAlteredCases = numberOfAlteredCases; + } + + public Integer getNumberOfAlteredCasesOnPanel() { + return numberOfAlteredCasesOnPanel; + } + + public void setNumberOfAlteredCasesOnPanel(Integer numberOfAlteredCasesOnPanel) { + this.numberOfAlteredCasesOnPanel = numberOfAlteredCasesOnPanel; + } + + public Integer getTotalCount() { + return totalCount; + } + + public void setTotalCount(Integer totalCount) { + this.totalCount = totalCount; + } + + public Integer getNumberOfProfiledCases() { + return numberOfProfiledCases; + } + + public void setNumberOfProfiledCases(Integer numberOfProfiledCases) { + this.numberOfProfiledCases = numberOfProfiledCases; + } + + public Set getMatchingGenePanelIds() { + return matchingGenePanelIds; + } + + public void setMatchingGenePanelIds(Set matchingGenePanelIds) { + this.matchingGenePanelIds = matchingGenePanelIds; + } + + public abstract String getUniqueEventKey(); + + public abstract String[] getHugoGeneSymbols(); + + public abstract Integer[] getEntrezGeneIds(); +} diff --git a/src/main/java/org/cbioportal/legacy/model/AlterationCountByGene.java b/src/main/java/org/cbioportal/legacy/model/AlterationCountByGene.java new file mode 100644 index 00000000000..d006ced7f73 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/AlterationCountByGene.java @@ -0,0 +1,51 @@ +package org.cbioportal.legacy.model; + +import com.fasterxml.jackson.annotation.JsonProperty; +import java.math.BigDecimal; + +public class AlterationCountByGene extends AlterationCountBase { + + private Integer entrezGeneId; + private String hugoGeneSymbol; + private BigDecimal qValue; + + public Integer getEntrezGeneId() { + return entrezGeneId; + } + + public void setEntrezGeneId(Integer entrezGeneId) { + this.entrezGeneId = entrezGeneId; + } + + public String getHugoGeneSymbol() { + return hugoGeneSymbol; + } + + public void setHugoGeneSymbol(String hugoGeneSymbol) { + this.hugoGeneSymbol = hugoGeneSymbol; + } + + @JsonProperty("qValue") + public BigDecimal getqValue() { + return qValue; + } + + public void setqValue(BigDecimal qValue) { + this.qValue = qValue; + } + + @Override + public String getUniqueEventKey() { + return hugoGeneSymbol; + } + + @Override + public String[] getHugoGeneSymbols() { + return new String[] {hugoGeneSymbol}; + } + + @Override + public Integer[] getEntrezGeneIds() { + return new Integer[] {entrezGeneId}; + } +} diff --git a/src/main/java/org/cbioportal/legacy/model/AlterationCountByStructuralVariant.java b/src/main/java/org/cbioportal/legacy/model/AlterationCountByStructuralVariant.java new file mode 100644 index 00000000000..8d7e1ed5db2 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/AlterationCountByStructuralVariant.java @@ -0,0 +1,56 @@ +package org.cbioportal.legacy.model; + +public class AlterationCountByStructuralVariant extends AlterationCountBase { + + private Integer gene1EntrezGeneId; + private String gene1HugoGeneSymbol; + private Integer gene2EntrezGeneId; + private String gene2HugoGeneSymbol; + + public Integer getGene1EntrezGeneId() { + return gene1EntrezGeneId; + } + + public void setGene1EntrezGeneId(Integer gene1EntrezGeneId) { + this.gene1EntrezGeneId = gene1EntrezGeneId; + } + + public String getGene1HugoGeneSymbol() { + return gene1HugoGeneSymbol; + } + + public void setGene1HugoGeneSymbol(String gene1HugoGeneSymbol) { + this.gene1HugoGeneSymbol = gene1HugoGeneSymbol; + } + + public Integer getGene2EntrezGeneId() { + return gene2EntrezGeneId; + } + + public void setGene2EntrezGeneId(Integer gene2EntrezGeneId) { + this.gene2EntrezGeneId = gene2EntrezGeneId; + } + + public String getGene2HugoGeneSymbol() { + return gene2HugoGeneSymbol; + } + + public void setGene2HugoGeneSymbol(String gene2HugoGeneSymbol) { + this.gene2HugoGeneSymbol = gene2HugoGeneSymbol; + } + + @Override + public String getUniqueEventKey() { + return gene1HugoGeneSymbol + "::" + gene2HugoGeneSymbol; + } + + @Override + public String[] getHugoGeneSymbols() { + return new String[] {gene1HugoGeneSymbol, gene2HugoGeneSymbol}; + } + + @Override + public Integer[] getEntrezGeneIds() { + return new Integer[] {gene1EntrezGeneId, gene2EntrezGeneId}; + } +} diff --git a/src/main/java/org/cbioportal/legacy/model/AlterationDriverAnnotation.java b/src/main/java/org/cbioportal/legacy/model/AlterationDriverAnnotation.java new file mode 100644 index 00000000000..51db64b9e5d --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/AlterationDriverAnnotation.java @@ -0,0 +1,70 @@ +package org.cbioportal.legacy.model; + +import java.io.Serializable; + +public class AlterationDriverAnnotation implements Serializable { + + private Integer alterationEventId; + private Integer geneticProfileId; + private Integer sampleId; + private String driverFilter; + private String driverFilterAnnotation; + private String driverTiersFilter; + private String driverTiersFilterAnnotation; + + public Integer getAlterationEventId() { + return alterationEventId; + } + + public void setAlterationEventId(Integer alterationEventId) { + this.alterationEventId = alterationEventId; + } + + public Integer getGeneticProfileId() { + return geneticProfileId; + } + + public void setGeneticProfileId(Integer geneticProfileId) { + this.geneticProfileId = geneticProfileId; + } + + public Integer getSampleId() { + return sampleId; + } + + public void setSampleId(Integer sampleId) { + this.sampleId = sampleId; + } + + public String getDriverFilter() { + return driverFilter; + } + + public void setDriverFilter(String driverFilter) { + this.driverFilter = driverFilter; + } + + public String getDriverFilterAnnotation() { + return driverFilterAnnotation; + } + + public void setDriverFilterAnnotation(String driverFilterAnnotation) { + this.driverFilterAnnotation = driverFilterAnnotation; + } + + public String getDriverTiersFilter() { + return driverTiersFilter; + } + + public void setDriverTiersFilter(String driverTiersFilter) { + this.driverTiersFilter = driverTiersFilter; + } + + public String getDriverTiersFilterAnnotation() { + return driverTiersFilterAnnotation; + } + + public void setDriverTiersFilterAnnotation(String driverTiersFilterAnnotation) { + this.driverTiersFilterAnnotation = driverTiersFilterAnnotation; + } +} diff --git a/src/main/java/org/cbioportal/legacy/model/AlterationEnrichment.java b/src/main/java/org/cbioportal/legacy/model/AlterationEnrichment.java new file mode 100644 index 00000000000..b0556022ae2 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/AlterationEnrichment.java @@ -0,0 +1,57 @@ +package org.cbioportal.legacy.model; + +import com.fasterxml.jackson.annotation.JsonProperty; +import jakarta.validation.constraints.NotNull; +import java.io.Serializable; +import java.math.BigDecimal; +import java.util.List; + +public class AlterationEnrichment implements Serializable { + + @NotNull private Integer entrezGeneId; + @NotNull private String hugoGeneSymbol; + private String cytoband; + private BigDecimal pValue; + @NotNull private List counts; + + public Integer getEntrezGeneId() { + return entrezGeneId; + } + + public void setEntrezGeneId(Integer entrezGeneId) { + this.entrezGeneId = entrezGeneId; + } + + public String getHugoGeneSymbol() { + return hugoGeneSymbol; + } + + public void setHugoGeneSymbol(String hugoGeneSymbol) { + this.hugoGeneSymbol = hugoGeneSymbol; + } + + public String getCytoband() { + return cytoband; + } + + public void setCytoband(String cytoband) { + this.cytoband = cytoband; + } + + @JsonProperty("pValue") + public BigDecimal getpValue() { + return pValue; + } + + public void setpValue(BigDecimal pValue) { + this.pValue = pValue; + } + + public List getCounts() { + return counts; + } + + public void setCounts(List counts) { + this.counts = counts; + } +} diff --git a/src/main/java/org/cbioportal/legacy/model/AlterationFilter.java b/src/main/java/org/cbioportal/legacy/model/AlterationFilter.java new file mode 100644 index 00000000000..d2b37131002 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/AlterationFilter.java @@ -0,0 +1,148 @@ +package org.cbioportal.legacy.model; + +import static com.fasterxml.jackson.annotation.JsonInclude.Include.*; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import java.io.Serializable; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.stream.Collectors; +import org.cbioportal.legacy.model.util.Select; + +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(NON_NULL) +public class AlterationFilter extends BaseAlterationFilter implements Serializable { + + private Map mutationEventTypes = new HashMap<>(); + private Map copyNumberAlterationEventTypes = new HashMap<>(); + private Boolean structuralVariants; + + @JsonIgnore private Select mutationTypeSelect; + @JsonIgnore private Select cnaTypeSelect; + + public AlterationFilter() {} + + public AlterationFilter( + Select mutationTypesMap, + Select cnaEventTypes, + boolean includeDriver, + boolean includeVUS, + boolean includeUnknownOncogenicity, + boolean includeGermline, + boolean includeSomatic, + boolean includeUnknownStatus, + Select tiersSelect, + boolean includeUnknownTier) { + this.mutationTypeSelect = mutationTypesMap; + this.cnaTypeSelect = cnaEventTypes; + this.includeDriver = includeDriver; + this.includeVUS = includeVUS; + this.includeUnknownOncogenicity = includeUnknownOncogenicity; + this.includeGermline = includeGermline; + this.includeSomatic = includeSomatic; + this.includeUnknownStatus = includeUnknownStatus; + this.tiersSelect = tiersSelect; + this.includeUnknownTier = includeUnknownTier; + } + + public Map getMutationEventTypes() { + return mutationEventTypes; + } + + public void setMutationEventTypes(Map mutationEventTypes) { + if (mutationEventTypes == null) { + throw new IllegalArgumentException("null value is not allowed for mutationEventTypes"); + } + this.mutationEventTypes = mutationEventTypes; + } + + public Map getCopyNumberAlterationEventTypes() { + return copyNumberAlterationEventTypes; + } + + public void setCopyNumberAlterationEventTypes(Map copyNumberAlterationEventTypes) { + if (copyNumberAlterationEventTypes == null) { + throw new IllegalArgumentException( + "null value is not allowed for copyNumberAlterationEventTypes"); + } + this.copyNumberAlterationEventTypes = copyNumberAlterationEventTypes; + } + + public Boolean getStructuralVariants() { + return structuralVariants; + } + + public void setStructuralVariants(Boolean structuralVariants) { + this.structuralVariants = structuralVariants; + } + + @JsonIgnore + public Select getMutationTypeSelect() { + if (mutationTypeSelect != null) return mutationTypeSelect; + + if (mutationEventTypes == null + || mutationEventTypes.getOrDefault(MutationEventType.any, false) + || allOptionsSelected( + mutationEventTypes, Arrays.asList(MutationEventType.any.toString()))) { + return Select.all(); + } + + // if MutationEventType.other is true and not allOptionsSelected + if (mutationEventTypes.getOrDefault(MutationEventType.other, false)) { + List unSelected = + mutationEventTypes.entrySet().stream() + .filter(e -> !e.getValue()) + .map(Entry::getKey) + .collect(Collectors.toList()); + Select select = Select.byValues(unSelected); + // setting this would execute NOT IN clause in sql query + select.inverse(true); + return select; + } else { + List selected = + mutationEventTypes.entrySet().stream() + .filter(Entry::getValue) + .map(Entry::getKey) + .collect(Collectors.toList()); + return Select.byValues(selected); + } + } + + @JsonIgnore + public Select getCNAEventTypeSelect() { + if (cnaTypeSelect != null) return cnaTypeSelect; + if (allOptionsSelected(copyNumberAlterationEventTypes, null)) { + return Select.all(); + } + return Select.byValues( + copyNumberAlterationEventTypes.entrySet().stream() + .filter(Entry::getValue) + .map(Entry::getKey)); + } + + @JsonIgnore + public void setMutationTypeSelect(Select mutationTypeSelect) { + this.mutationTypeSelect = mutationTypeSelect; + } + + @JsonIgnore + public void setCnaTypeSelect(Select cnaTypeSelect) { + this.cnaTypeSelect = cnaTypeSelect; + } + + @JsonIgnore + private boolean allOptionsSelected(Map options, List excludeKeys) { + return options.entrySet().stream() + .allMatch( + e -> { + return excludeKeys == null || !excludeKeys.contains(e.getKey().toString()) + ? e.getValue() + : true; + }); + } +} diff --git a/src/main/java/org/cbioportal/legacy/model/AlterationType.java b/src/main/java/org/cbioportal/legacy/model/AlterationType.java new file mode 100644 index 00000000000..d5addabc117 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/AlterationType.java @@ -0,0 +1,8 @@ +package org.cbioportal.legacy.model; + +public enum AlterationType { + MUTATION_EXTENDED, + COPY_NUMBER_ALTERATION, + STRUCTURAL_VARIANT, + GENERIC_ASSAY; +} diff --git a/src/main/java/org/cbioportal/legacy/model/BaseAlterationFilter.java b/src/main/java/org/cbioportal/legacy/model/BaseAlterationFilter.java new file mode 100644 index 00000000000..5f1a713bbf9 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/BaseAlterationFilter.java @@ -0,0 +1,132 @@ +package org.cbioportal.legacy.model; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonInclude.Include; +import java.io.Serializable; +import java.util.HashMap; +import java.util.Map; +import org.cbioportal.legacy.model.util.Select; + +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(Include.NON_NULL) +public class BaseAlterationFilter implements Serializable { + + protected boolean includeGermline = true; + protected boolean includeSomatic = true; + protected boolean includeUnknownStatus = true; + protected boolean includeDriver = true; + protected boolean includeVUS = true; + protected boolean includeUnknownOncogenicity = true; + protected Map tiersBooleanMap = new HashMap<>(); + protected boolean includeUnknownTier = true; + + @JsonIgnore protected Select tiersSelect = Select.all(); + + // When default constructor is called, the filter is inactive (excludes nothing) + public BaseAlterationFilter() {} + + public BaseAlterationFilter( + boolean includeDriver, + boolean includeVUS, + boolean includeUnknownOncogenicity, + boolean includeGermline, + boolean includeSomatic, + boolean includeUnknownStatus, + Select tiersSelect, + boolean includeUnknownTier) { + this.includeGermline = includeGermline; + this.includeSomatic = includeSomatic; + this.includeUnknownStatus = includeUnknownStatus; + this.includeDriver = includeDriver; + this.includeVUS = includeVUS; + this.includeUnknownOncogenicity = includeUnknownOncogenicity; + this.tiersSelect = tiersSelect; + this.includeUnknownTier = includeUnknownTier; + } + + public boolean getIncludeGermline() { + return includeGermline; + } + + public void setIncludeGermline(boolean includeGermline) { + this.includeGermline = includeGermline; + } + + public boolean getIncludeSomatic() { + return includeSomatic; + } + + public void setIncludeSomatic(boolean includeSomatic) { + this.includeSomatic = includeSomatic; + } + + public boolean getIncludeUnknownStatus() { + return includeUnknownStatus; + } + + public void setIncludeUnknownStatus(boolean includeUnknownStatus) { + this.includeUnknownStatus = includeUnknownStatus; + } + + public boolean getIncludeDriver() { + return includeDriver; + } + + public void setIncludeDriver(boolean includeDriver) { + this.includeDriver = includeDriver; + } + + public boolean getIncludeVUS() { + return includeVUS; + } + + public void setIncludeVUS(boolean includeVUS) { + this.includeVUS = includeVUS; + } + + public boolean getIncludeUnknownOncogenicity() { + return includeUnknownOncogenicity; + } + + public void setIncludeUnknownOncogenicity(boolean includeUnknownOncogenicity) { + this.includeUnknownOncogenicity = includeUnknownOncogenicity; + } + + public boolean getIncludeUnknownTier() { + return includeUnknownTier; + } + + public void setIncludeUnknownTier(boolean includeUnknownTier) { + this.includeUnknownTier = includeUnknownTier; + } + + public void setTiersBooleanMap(Map tiersBooleanMap) { + if (tiersBooleanMap == null) { + this.tiersSelect = Select.none(); + } else { + this.tiersSelect = + Select.byValues( + tiersBooleanMap.entrySet().stream().filter(e -> e.getValue()).map(e -> e.getKey())); + // Empty map '{}' is interpreted as hasAll(). + if (tiersBooleanMap.entrySet().stream().allMatch(e -> e.getValue())) + this.tiersSelect.hasAll(true); + } + } + + public Map getTiersBooleanMap() { + return tiersBooleanMap; + } + + @JsonIgnore + public Select getSelectedTiers() { + if (tiersSelect == null) return Select.none(); + return tiersSelect; + } + + @JsonIgnore + public void setSelectedTiers(Select tiersSelect) { + this.tiersSelect = tiersSelect; + } +} diff --git a/src/main/java/org/cbioportal/legacy/model/Binnable.java b/src/main/java/org/cbioportal/legacy/model/Binnable.java new file mode 100644 index 00000000000..4864fdcfe31 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/Binnable.java @@ -0,0 +1,16 @@ +package org.cbioportal.legacy.model; + +/** Data that can be binned, clinical or custom */ +public interface Binnable { + String getAttrId(); + + String getAttrValue(); + + String getSampleId(); + + String getPatientId(); + + String getStudyId(); + + Boolean isPatientAttribute(); +} diff --git a/src/main/java/org/cbioportal/legacy/model/CNA.java b/src/main/java/org/cbioportal/legacy/model/CNA.java new file mode 100644 index 00000000000..98c75733fae --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/CNA.java @@ -0,0 +1,40 @@ +package org.cbioportal.legacy.model; + +import java.util.HashMap; +import java.util.Map; + +public enum CNA { + AMP((short) 2, "Amplified"), + GAIN((short) 1, "Gained"), + DIPLOID((short) 0, "Diploid"), + HETLOSS((short) -1, "Heterozygously deleted"), + HOMDEL((short) -2, "Homozygously deleted"); + + private short code; + private String desc; + + private CNA(short code, String desc) { + this.code = code; + this.desc = desc; + } + + private static final Map cache = new HashMap(); + + static { + for (CNA cna : CNA.values()) { + cache.put(cna.code, cna); + } + } + + public static CNA getByCode(short code) { + return cache.get(code); + } + + public short getCode() { + return code; + } + + public String getDescription() { + return desc; + } +} diff --git a/src/main/java/org/cbioportal/legacy/model/CancerStudy.java b/src/main/java/org/cbioportal/legacy/model/CancerStudy.java new file mode 100644 index 00000000000..ff0ace593f0 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/CancerStudy.java @@ -0,0 +1,254 @@ +package org.cbioportal.legacy.model; + +import jakarta.validation.constraints.NotNull; +import java.io.Serializable; +import java.util.Date; + +public class CancerStudy implements ReadPermission, Serializable { + + private Integer cancerStudyId; + @NotNull private String cancerStudyIdentifier; + private String typeOfCancerId; + private String name; + private String description; + private Boolean publicStudy; + private String pmid; + private String citation; + private String groups; + private Integer status; + private Date importDate; + private TypeOfCancer typeOfCancer; + private Integer allSampleCount; + private Integer sequencedSampleCount; + private Integer cnaSampleCount; + private Integer mrnaRnaSeqSampleCount; + private Integer mrnaRnaSeqV2SampleCount; + private Integer mrnaMicroarraySampleCount; + private Integer miRnaSampleCount; + private Integer methylationHm27SampleCount; + private Integer rppaSampleCount; + private Integer massSpectrometrySampleCount; + private Integer completeSampleCount; + private String referenceGenome; + private Boolean readPermission = true; + private Integer treatmentCount; + private Integer structuralVariantCount; + + public Integer getCancerStudyId() { + return cancerStudyId; + } + + public void setCancerStudyId(Integer cancerStudyId) { + this.cancerStudyId = cancerStudyId; + } + + public String getCancerStudyIdentifier() { + return cancerStudyIdentifier; + } + + public void setCancerStudyIdentifier(String cancerStudyIdentifier) { + this.cancerStudyIdentifier = cancerStudyIdentifier; + } + + public String getTypeOfCancerId() { + return typeOfCancerId; + } + + public void setTypeOfCancerId(String typeOfCancerId) { + this.typeOfCancerId = typeOfCancerId; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public Boolean getPublicStudy() { + return publicStudy; + } + + public void setPublicStudy(Boolean publicStudy) { + this.publicStudy = publicStudy; + } + + public String getPmid() { + return pmid; + } + + public void setPmid(String pmid) { + this.pmid = pmid; + } + + public String getCitation() { + return citation; + } + + public void setCitation(String citation) { + this.citation = citation; + } + + public String getGroups() { + return groups; + } + + public void setGroups(String groups) { + this.groups = groups; + } + + public Integer getStatus() { + return status; + } + + public void setStatus(Integer status) { + this.status = status; + } + + public Date getImportDate() { + return importDate; + } + + public void setImportDate(Date importDate) { + this.importDate = importDate; + } + + public TypeOfCancer getTypeOfCancer() { + return typeOfCancer; + } + + public void setTypeOfCancer(TypeOfCancer typeOfCancer) { + this.typeOfCancer = typeOfCancer; + } + + public Integer getAllSampleCount() { + return allSampleCount; + } + + public void setAllSampleCount(Integer allSampleCount) { + this.allSampleCount = allSampleCount; + } + + public Integer getSequencedSampleCount() { + return sequencedSampleCount; + } + + public void setSequencedSampleCount(Integer sequencedSampleCount) { + this.sequencedSampleCount = sequencedSampleCount; + } + + public Integer getCnaSampleCount() { + return cnaSampleCount; + } + + public void setCnaSampleCount(Integer cnaSampleCount) { + this.cnaSampleCount = cnaSampleCount; + } + + public Integer getMrnaRnaSeqSampleCount() { + return mrnaRnaSeqSampleCount; + } + + public void setMrnaRnaSeqSampleCount(Integer mrnaRnaSeqSampleCount) { + this.mrnaRnaSeqSampleCount = mrnaRnaSeqSampleCount; + } + + public Integer getMrnaRnaSeqV2SampleCount() { + return mrnaRnaSeqV2SampleCount; + } + + public void setMrnaRnaSeqV2SampleCount(Integer mrnaRnaSeqV2SampleCount) { + this.mrnaRnaSeqV2SampleCount = mrnaRnaSeqV2SampleCount; + } + + public Integer getMrnaMicroarraySampleCount() { + return mrnaMicroarraySampleCount; + } + + public void setMrnaMicroarraySampleCount(Integer mrnaMicroarraySampleCount) { + this.mrnaMicroarraySampleCount = mrnaMicroarraySampleCount; + } + + public Integer getMiRnaSampleCount() { + return miRnaSampleCount; + } + + public void setMiRnaSampleCount(Integer miRnaSampleCount) { + this.miRnaSampleCount = miRnaSampleCount; + } + + public Integer getMethylationHm27SampleCount() { + return methylationHm27SampleCount; + } + + public void setMethylationHm27SampleCount(Integer methylationHm27SampleCount) { + this.methylationHm27SampleCount = methylationHm27SampleCount; + } + + public Integer getRppaSampleCount() { + return rppaSampleCount; + } + + public void setRppaSampleCount(Integer rppaSampleCount) { + this.rppaSampleCount = rppaSampleCount; + } + + public Integer getCompleteSampleCount() { + return completeSampleCount; + } + + public void setCompleteSampleCount(Integer completeSampleCount) { + this.completeSampleCount = completeSampleCount; + } + + public Integer getMassSpectrometrySampleCount() { + return massSpectrometrySampleCount; + } + + public void setMassSpectrometrySampleCount(Integer massSpectrometrySampleCount) { + this.massSpectrometrySampleCount = massSpectrometrySampleCount; + } + + public String getReferenceGenome() { + return referenceGenome; + } + + public void setReferenceGenome(String referenceGenome) { + this.referenceGenome = referenceGenome; + } + + @Override + public void setReadPermission(Boolean permission) { + this.readPermission = permission; + } + + @Override + public Boolean getReadPermission() { + return readPermission; + } + + public Integer getTreatmentCount() { + return treatmentCount; + } + + public void setTreatmentCount(Integer treatmentCount) { + this.treatmentCount = treatmentCount; + } + + public Integer getStructuralVariantCount() { + return structuralVariantCount; + } + + public void setStructuralVariantCount(Integer structuralVariantCount) { + this.structuralVariantCount = structuralVariantCount; + } +} diff --git a/src/main/java/org/cbioportal/legacy/model/CancerStudyTags.java b/src/main/java/org/cbioportal/legacy/model/CancerStudyTags.java new file mode 100644 index 00000000000..9aef7ac13aa --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/CancerStudyTags.java @@ -0,0 +1,34 @@ +package org.cbioportal.legacy.model; + +import java.io.Serializable; + +public class CancerStudyTags implements Serializable { + + private Integer cancerStudyId; + private String studyId; + private String tags; + + public Integer getCancerStudyId() { + return cancerStudyId; + } + + public void setCancerStudyId(Integer cancerStudyId) { + this.cancerStudyId = cancerStudyId; + } + + public String getTags() { + return tags; + } + + public void setTags(String tags) { + this.tags = tags; + } + + public String getStudyId() { + return studyId; + } + + public void setStudyId(String studyId) { + this.studyId = studyId; + } +} diff --git a/src/main/java/org/cbioportal/legacy/model/CaseListDataCount.java b/src/main/java/org/cbioportal/legacy/model/CaseListDataCount.java new file mode 100644 index 00000000000..b47cf85610c --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/CaseListDataCount.java @@ -0,0 +1,34 @@ +package org.cbioportal.legacy.model; + +import java.io.Serializable; + +public class CaseListDataCount implements Serializable { + + private String label; + private String value; + private Integer count; + + public String getLabel() { + return label; + } + + public void setLabel(String label) { + this.label = label; + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + + public Integer getCount() { + return count; + } + + public void setCount(Integer count) { + this.count = count; + } +} diff --git a/src/main/java/org/cbioportal/legacy/model/ClinicalAttribute.java b/src/main/java/org/cbioportal/legacy/model/ClinicalAttribute.java new file mode 100644 index 00000000000..9410d0f9705 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/ClinicalAttribute.java @@ -0,0 +1,80 @@ +package org.cbioportal.legacy.model; + +import jakarta.validation.constraints.NotNull; +import java.io.Serializable; + +public class ClinicalAttribute implements Serializable { + + @NotNull private String attrId; + @NotNull private String displayName; + private String description; + private String datatype; + @NotNull private Boolean patientAttribute; + private String priority; + private Integer cancerStudyId; + @NotNull private String cancerStudyIdentifier; + + public String getAttrId() { + return attrId; + } + + public void setAttrId(String attrId) { + this.attrId = attrId; + } + + public String getDisplayName() { + return displayName; + } + + public void setDisplayName(String displayName) { + this.displayName = displayName; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public String getDatatype() { + return datatype; + } + + public void setDatatype(String datatype) { + this.datatype = datatype; + } + + public Boolean getPatientAttribute() { + return patientAttribute; + } + + public void setPatientAttribute(Boolean patientAttribute) { + this.patientAttribute = patientAttribute; + } + + public String getPriority() { + return priority; + } + + public void setPriority(String priority) { + this.priority = priority; + } + + public Integer getCancerStudyId() { + return cancerStudyId; + } + + public void setCancerStudyId(Integer cancerStudyId) { + this.cancerStudyId = cancerStudyId; + } + + public String getCancerStudyIdentifier() { + return cancerStudyIdentifier; + } + + public void setCancerStudyIdentifier(String cancerStudyIdentifier) { + this.cancerStudyIdentifier = cancerStudyIdentifier; + } +} diff --git a/src/main/java/org/cbioportal/legacy/model/ClinicalAttributeCount.java b/src/main/java/org/cbioportal/legacy/model/ClinicalAttributeCount.java new file mode 100644 index 00000000000..d5cf428758b --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/ClinicalAttributeCount.java @@ -0,0 +1,25 @@ +package org.cbioportal.legacy.model; + +import java.io.Serializable; + +public class ClinicalAttributeCount implements Serializable { + + private String attrId; + private Integer count; + + public String getAttrId() { + return attrId; + } + + public void setAttrId(String attrId) { + this.attrId = attrId; + } + + public Integer getCount() { + return count; + } + + public void setCount(Integer count) { + this.count = count; + } +} diff --git a/src/main/java/org/cbioportal/legacy/model/ClinicalData.java b/src/main/java/org/cbioportal/legacy/model/ClinicalData.java new file mode 100644 index 00000000000..547cfffceaa --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/ClinicalData.java @@ -0,0 +1,77 @@ +package org.cbioportal.legacy.model; + +import jakarta.validation.constraints.NotNull; + +public class ClinicalData extends UniqueKeyBase implements Binnable { + + private Integer internalId; + private String sampleId; + @NotNull private String patientId; + @NotNull private String studyId; + @NotNull private String attrId; + private String attrValue; + private ClinicalAttribute clinicalAttribute; + + public Integer getInternalId() { + return internalId; + } + + public void setInternalId(Integer internalId) { + this.internalId = internalId; + } + + public String getSampleId() { + return sampleId; + } + + public void setSampleId(String sampleId) { + this.sampleId = sampleId; + } + + public String getPatientId() { + return patientId; + } + + public void setPatientId(String patientId) { + this.patientId = patientId; + } + + public String getStudyId() { + return studyId; + } + + public void setStudyId(String studyId) { + this.studyId = studyId; + } + + public String getAttrId() { + return attrId; + } + + public Boolean isPatientAttribute() { + if (clinicalAttribute == null) { + return null; + } + return this.clinicalAttribute.getPatientAttribute(); + } + + public void setAttrId(String attrId) { + this.attrId = attrId; + } + + public String getAttrValue() { + return attrValue; + } + + public void setAttrValue(String attrValue) { + this.attrValue = attrValue; + } + + public ClinicalAttribute getClinicalAttribute() { + return clinicalAttribute; + } + + public void setClinicalAttribute(ClinicalAttribute clinicalAttribute) { + this.clinicalAttribute = clinicalAttribute; + } +} diff --git a/src/main/java/org/cbioportal/legacy/model/ClinicalDataBin.java b/src/main/java/org/cbioportal/legacy/model/ClinicalDataBin.java new file mode 100644 index 00000000000..08cff7fedff --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/ClinicalDataBin.java @@ -0,0 +1,15 @@ +package org.cbioportal.legacy.model; + +import java.io.Serializable; + +public class ClinicalDataBin extends DataBin implements Serializable { + private String attributeId; + + public String getAttributeId() { + return attributeId; + } + + public void setAttributeId(String attributeId) { + this.attributeId = attributeId; + } +} diff --git a/src/main/java/org/cbioportal/legacy/model/ClinicalDataCount.java b/src/main/java/org/cbioportal/legacy/model/ClinicalDataCount.java new file mode 100644 index 00000000000..86e76dc7cf0 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/ClinicalDataCount.java @@ -0,0 +1,34 @@ +package org.cbioportal.legacy.model; + +import java.io.Serializable; + +public class ClinicalDataCount implements Serializable { + + private String attributeId; + private String value; + private Integer count; + + public String getAttributeId() { + return attributeId; + } + + public void setAttributeId(String attributeId) { + this.attributeId = attributeId; + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + + public Integer getCount() { + return count; + } + + public void setCount(Integer count) { + this.count = count; + } +} diff --git a/src/main/java/org/cbioportal/legacy/model/ClinicalDataCountItem.java b/src/main/java/org/cbioportal/legacy/model/ClinicalDataCountItem.java new file mode 100644 index 00000000000..bb3e9e91f3a --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/ClinicalDataCountItem.java @@ -0,0 +1,26 @@ +package org.cbioportal.legacy.model; + +import java.io.Serializable; +import java.util.List; + +public class ClinicalDataCountItem implements Serializable { + + private String attributeId; + private List counts; + + public String getAttributeId() { + return attributeId; + } + + public void setAttributeId(String attributeId) { + this.attributeId = attributeId; + } + + public List getCounts() { + return counts; + } + + public void setCounts(List counts) { + this.counts = counts; + } +} diff --git a/src/main/java/org/cbioportal/legacy/model/ClinicalDataEnrichment.java b/src/main/java/org/cbioportal/legacy/model/ClinicalDataEnrichment.java new file mode 100644 index 00000000000..b2fff5ef4c0 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/ClinicalDataEnrichment.java @@ -0,0 +1,47 @@ +package org.cbioportal.legacy.model; + +import com.fasterxml.jackson.annotation.JsonProperty; +import jakarta.validation.constraints.NotNull; +import java.io.Serializable; +import java.math.BigDecimal; + +public class ClinicalDataEnrichment implements Serializable { + + @NotNull private ClinicalAttribute clinicalAttribute; + @NotNull private BigDecimal score; + @NotNull private String method; + @NotNull private BigDecimal pValue; + + public ClinicalAttribute getClinicalAttribute() { + return clinicalAttribute; + } + + public void setClinicalAttribute(ClinicalAttribute clinicalAttribute) { + this.clinicalAttribute = clinicalAttribute; + } + + public BigDecimal getScore() { + return score; + } + + public void setScore(BigDecimal score) { + this.score = score; + } + + public String getMethod() { + return method; + } + + public void setMethod(String method) { + this.method = method; + } + + @JsonProperty("pValue") + public BigDecimal getpValue() { + return pValue; + } + + public void setpValue(BigDecimal pValue) { + this.pValue = pValue; + } +} diff --git a/src/main/java/org/cbioportal/legacy/model/ClinicalEvent.java b/src/main/java/org/cbioportal/legacy/model/ClinicalEvent.java new file mode 100644 index 00000000000..dce2a3984c3 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/ClinicalEvent.java @@ -0,0 +1,92 @@ +package org.cbioportal.legacy.model; + +import jakarta.validation.constraints.NotNull; +import java.util.List; +import java.util.Objects; + +public class ClinicalEvent extends UniqueKeyBase { + + private Long clinicalEventId; + @NotNull private String studyId; + @NotNull private String patientId; + @NotNull private String eventType; + private Integer startDate; + private Integer stopDate; + private List attributes; + + public Long getClinicalEventId() { + return clinicalEventId; + } + + public void setClinicalEventId(Long clinicalEventId) { + this.clinicalEventId = clinicalEventId; + } + + public String getStudyId() { + return studyId; + } + + public void setStudyId(String studyId) { + this.studyId = studyId; + } + + public String getPatientId() { + return patientId; + } + + public void setPatientId(String patientId) { + this.patientId = patientId; + } + + public String getEventType() { + return eventType; + } + + public void setEventType(String eventType) { + this.eventType = eventType; + } + + public Integer getStartDate() { + return startDate; + } + + public void setStartDate(Integer startDate) { + this.startDate = startDate; + } + + public Integer getStopDate() { + return stopDate; + } + + public void setStopDate(Integer stopDate) { + this.stopDate = stopDate; + } + + public List getAttributes() { + return attributes; + } + + public void setAttributes(List attributes) { + this.attributes = attributes; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + ClinicalEvent that = (ClinicalEvent) o; + return Objects.equals(clinicalEventId, that.clinicalEventId) + && Objects.equals(studyId, that.studyId) + && Objects.equals(patientId, that.patientId) + && Objects.equals(eventType, that.eventType) + && Objects.equals(startDate, that.startDate) + && Objects.equals(stopDate, that.stopDate) + && Objects.equals(attributes, that.attributes); + } + + @Override + public int hashCode() { + return Objects.hash( + clinicalEventId, studyId, patientId, eventType, startDate, stopDate, attributes); + } +} diff --git a/src/main/java/org/cbioportal/legacy/model/ClinicalEventData.java b/src/main/java/org/cbioportal/legacy/model/ClinicalEventData.java new file mode 100644 index 00000000000..195c6c79ea1 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/ClinicalEventData.java @@ -0,0 +1,35 @@ +package org.cbioportal.legacy.model; + +import jakarta.validation.constraints.NotNull; +import java.io.Serializable; + +public class ClinicalEventData implements Serializable { + + private Long clinicalEventId; + @NotNull private String key; + @NotNull private String value; + + public Long getClinicalEventId() { + return clinicalEventId; + } + + public void setClinicalEventId(Long clinicalEventId) { + this.clinicalEventId = clinicalEventId; + } + + public String getKey() { + return key; + } + + public void setKey(String key) { + this.key = key; + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } +} diff --git a/src/main/java/org/cbioportal/legacy/model/ClinicalEventKeyCode.java b/src/main/java/org/cbioportal/legacy/model/ClinicalEventKeyCode.java new file mode 100644 index 00000000000..f5ecc165fa0 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/ClinicalEventKeyCode.java @@ -0,0 +1,35 @@ +package org.cbioportal.legacy.model; + +/** + * Clinical event data objects are key value pairs. Lots of different services consume specific + * keys. This is an attempt to keep those key constants in one enum. + */ +public enum ClinicalEventKeyCode { + Agent("AGENT", null), + AgentClass("AGENT_CLASS", null), + AgentTarget("AGENT_TARGET", ", *"); + + private final String key; + private final String delimiter; + + ClinicalEventKeyCode(String key, String delimiter) { + this.key = key; + this.delimiter = delimiter; + } + + public String getKey() { + return key; + } + + public String getPropertyReference() { + return name().toLowerCase(); + } + + public String getDelimiter() { + return delimiter; + } + + public boolean isDelimited() { + return delimiter != null; + } +} diff --git a/src/main/java/org/cbioportal/legacy/model/ClinicalEventSample.java b/src/main/java/org/cbioportal/legacy/model/ClinicalEventSample.java new file mode 100644 index 00000000000..95dc9689291 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/ClinicalEventSample.java @@ -0,0 +1,62 @@ +package org.cbioportal.legacy.model; + +import java.io.Serializable; +import java.util.Objects; + +public class ClinicalEventSample implements Serializable { + private String patientId; + private String sampleId; + private String studyId; + private Integer timeTaken; + + public String getPatientId() { + return patientId; + } + + public void setPatientId(String patientId) { + this.patientId = patientId; + } + + public String getSampleId() { + return sampleId; + } + + public void setSampleId(String sampleId) { + this.sampleId = sampleId; + } + + public Integer getTimeTaken() { + return timeTaken; + } + + public void setTimeTaken(Integer timeTaken) { + this.timeTaken = timeTaken; + } + + public String getStudyId() { + return studyId; + } + + public void setStudyId(String studyId) { + this.studyId = studyId; + } + + public String key() { + return getSampleId() + getStudyId(); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + ClinicalEventSample that = (ClinicalEventSample) o; + return getPatientId().equals(that.getPatientId()) + && getSampleId().equals(that.getSampleId()) + && getStudyId().equals(that.getStudyId()); + } + + @Override + public int hashCode() { + return Objects.hash(getPatientId(), getSampleId(), getStudyId()); + } +} diff --git a/src/main/java/org/cbioportal/legacy/model/ClinicalEventTypeCount.java b/src/main/java/org/cbioportal/legacy/model/ClinicalEventTypeCount.java new file mode 100644 index 00000000000..621168495f5 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/ClinicalEventTypeCount.java @@ -0,0 +1,29 @@ +package org.cbioportal.legacy.model; + +import java.io.Serializable; + +public class ClinicalEventTypeCount implements Serializable { + private String eventType; + private Integer count; + + public ClinicalEventTypeCount(String eventType, Integer count) { + this.eventType = eventType; + this.count = count; + } + + public String getEventType() { + return eventType; + } + + public void setEventType(String eventType) { + this.eventType = eventType; + } + + public Integer getCount() { + return count; + } + + public void setCount(Integer count) { + this.count = count; + } +} diff --git a/src/main/java/org/cbioportal/legacy/model/ClinicalViolinPlotBoxData.java b/src/main/java/org/cbioportal/legacy/model/ClinicalViolinPlotBoxData.java new file mode 100644 index 00000000000..0f2caababd2 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/ClinicalViolinPlotBoxData.java @@ -0,0 +1,73 @@ +package org.cbioportal.legacy.model; + +import java.io.Serializable; + +public class ClinicalViolinPlotBoxData implements Serializable { + private double whiskerLower; + private double whiskerUpper; + private double median; + private double q1; + private double q3; + + @Override + public String toString() { + return "ClinicalViolinPlotBoxData{" + + "whiskerLower=" + + whiskerLower + + ", whiskerUpper=" + + whiskerUpper + + ", median=" + + median + + ", q1=" + + q1 + + ", q3=" + + q3 + + '}'; + } + + public double getWhiskerLower() { + return whiskerLower; + } + + public void setWhiskerLower(double whiskerLower) { + this.whiskerLower = whiskerLower; + } + + public double getWhiskerUpper() { + return whiskerUpper; + } + + public void setWhiskerUpper(double whiskerUpper) { + this.whiskerUpper = whiskerUpper; + } + + public double getMedian() { + return median; + } + + public void setMedian(double median) { + this.median = median; + } + + public double getQ1() { + return q1; + } + + public void setQ1(double q1) { + this.q1 = q1; + } + + public double getQ3() { + return q3; + } + + public void setQ3(double q3) { + this.q3 = q3; + } + + public ClinicalViolinPlotBoxData limitWhiskers(ClinicalViolinPlotData d) { + this.setWhiskerLower(Math.max(this.getWhiskerLower(), d.getAxisStart())); + this.setWhiskerUpper(Math.min(this.getWhiskerUpper(), d.getAxisEnd())); + return this; + } +} diff --git a/src/main/java/org/cbioportal/legacy/model/ClinicalViolinPlotData.java b/src/main/java/org/cbioportal/legacy/model/ClinicalViolinPlotData.java new file mode 100644 index 00000000000..4aa0ba775b4 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/ClinicalViolinPlotData.java @@ -0,0 +1,46 @@ +package org.cbioportal.legacy.model; + +import java.io.Serializable; +import java.util.List; + +public class ClinicalViolinPlotData implements Serializable { + private List rows; + private Double axisStart; + private Double axisEnd; + + @Override + public String toString() { + return "ClinicalViolinPlotData{" + + "rows=" + + rows + + ", axisStart=" + + axisStart + + ", axisEnd=" + + axisEnd + + '}'; + } + + public List getRows() { + return rows; + } + + public void setRows(List rows) { + this.rows = rows; + } + + public Double getAxisStart() { + return axisStart; + } + + public void setAxisStart(Double axisStart) { + this.axisStart = axisStart; + } + + public Double getAxisEnd() { + return axisEnd; + } + + public void setAxisEnd(Double axisEnd) { + this.axisEnd = axisEnd; + } +} diff --git a/src/main/java/org/cbioportal/legacy/model/ClinicalViolinPlotIndividualPoint.java b/src/main/java/org/cbioportal/legacy/model/ClinicalViolinPlotIndividualPoint.java new file mode 100644 index 00000000000..4b2c791dd19 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/ClinicalViolinPlotIndividualPoint.java @@ -0,0 +1,47 @@ +package org.cbioportal.legacy.model; + +import java.io.Serializable; + +public class ClinicalViolinPlotIndividualPoint implements Serializable { + private String sampleId; + private String studyId; + private double value; + + @Override + public String toString() { + return "ClinicalViolinPlotIndividualPoint{" + + "sampleId='" + + sampleId + + '\'' + + ", studyId='" + + studyId + + '\'' + + ", value=" + + value + + '}'; + } + + public String getSampleId() { + return sampleId; + } + + public void setSampleId(String sampleId) { + this.sampleId = sampleId; + } + + public String getStudyId() { + return studyId; + } + + public void setStudyId(String studyId) { + this.studyId = studyId; + } + + public double getValue() { + return value; + } + + public void setValue(double value) { + this.value = value; + } +} diff --git a/src/main/java/org/cbioportal/legacy/model/ClinicalViolinPlotRowData.java b/src/main/java/org/cbioportal/legacy/model/ClinicalViolinPlotRowData.java new file mode 100644 index 00000000000..39892ca6070 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/ClinicalViolinPlotRowData.java @@ -0,0 +1,69 @@ +package org.cbioportal.legacy.model; + +import java.io.Serializable; +import java.util.List; + +public class ClinicalViolinPlotRowData implements Serializable { + private String category; + private Integer numSamples; + private List curveData; + private ClinicalViolinPlotBoxData boxData; + private List individualPoints; + + @Override + public String toString() { + return "ClinicalViolinPlotRowData{" + + "category='" + + category + + '\'' + + ", numSamples=" + + numSamples + + ", curveData=" + + curveData + + ", boxData=" + + boxData + + ", individualPoints=" + + individualPoints + + '}'; + } + + public String getCategory() { + return category; + } + + public void setCategory(String category) { + this.category = category; + } + + public Integer getNumSamples() { + return numSamples; + } + + public void setNumSamples(Integer numSamples) { + this.numSamples = numSamples; + } + + public List getCurveData() { + return curveData; + } + + public void setCurveData(List curveData) { + this.curveData = curveData; + } + + public ClinicalViolinPlotBoxData getBoxData() { + return boxData; + } + + public void setBoxData(ClinicalViolinPlotBoxData boxData) { + this.boxData = boxData; + } + + public List getIndividualPoints() { + return individualPoints; + } + + public void setIndividualPoints(List individualPoints) { + this.individualPoints = individualPoints; + } +} diff --git a/src/main/java/org/cbioportal/legacy/model/CoExpression.java b/src/main/java/org/cbioportal/legacy/model/CoExpression.java new file mode 100644 index 00000000000..31f41b39984 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/CoExpression.java @@ -0,0 +1,47 @@ +package org.cbioportal.legacy.model; + +import com.fasterxml.jackson.annotation.JsonProperty; +import jakarta.validation.constraints.NotNull; +import java.io.Serializable; +import java.math.BigDecimal; + +public class CoExpression implements Serializable { + + @NotNull private String geneticEntityId; + @NotNull private EntityType geneticEntityType; + @NotNull private BigDecimal spearmansCorrelation; + @NotNull private BigDecimal pValue; + + public String getGeneticEntityId() { + return geneticEntityId; + } + + public void setGeneticEntityId(String geneticEntityId) { + this.geneticEntityId = geneticEntityId; + } + + public EntityType getGeneticEntityType() { + return geneticEntityType; + } + + public void setGeneticEntityType(EntityType geneticEntityType) { + this.geneticEntityType = geneticEntityType; + } + + public BigDecimal getSpearmansCorrelation() { + return spearmansCorrelation; + } + + public void setSpearmansCorrelation(BigDecimal spearmansCorrelation) { + this.spearmansCorrelation = spearmansCorrelation; + } + + @JsonProperty("pValue") + public BigDecimal getpValue() { + return pValue; + } + + public void setpValue(BigDecimal pValue) { + this.pValue = pValue; + } +} diff --git a/src/main/java/org/cbioportal/legacy/model/CopyNumberCount.java b/src/main/java/org/cbioportal/legacy/model/CopyNumberCount.java new file mode 100644 index 00000000000..aa4c6c82e44 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/CopyNumberCount.java @@ -0,0 +1,53 @@ +package org.cbioportal.legacy.model; + +import jakarta.validation.constraints.NotNull; +import java.io.Serializable; + +public class CopyNumberCount implements Serializable { + + @NotNull private String molecularProfileId; + @NotNull private Integer entrezGeneId; + @NotNull private Integer alteration; + @NotNull private Integer numberOfSamples; + @NotNull private Integer numberOfSamplesWithAlterationInGene; + + public String getMolecularProfileId() { + return molecularProfileId; + } + + public void setMolecularProfileId(String molecularProfileId) { + this.molecularProfileId = molecularProfileId; + } + + public Integer getEntrezGeneId() { + return entrezGeneId; + } + + public void setEntrezGeneId(Integer entrezGeneId) { + this.entrezGeneId = entrezGeneId; + } + + public Integer getAlteration() { + return alteration; + } + + public void setAlteration(Integer alteration) { + this.alteration = alteration; + } + + public Integer getNumberOfSamples() { + return numberOfSamples; + } + + public void setNumberOfSamples(Integer numberOfSamples) { + this.numberOfSamples = numberOfSamples; + } + + public Integer getNumberOfSamplesWithAlterationInGene() { + return numberOfSamplesWithAlterationInGene; + } + + public void setNumberOfSamplesWithAlterationInGene(Integer numberOfSamplesWithAlterationInGene) { + this.numberOfSamplesWithAlterationInGene = numberOfSamplesWithAlterationInGene; + } +} diff --git a/src/main/java/org/cbioportal/legacy/model/CopyNumberCountByGene.java b/src/main/java/org/cbioportal/legacy/model/CopyNumberCountByGene.java new file mode 100644 index 00000000000..d6f0830ed18 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/CopyNumberCountByGene.java @@ -0,0 +1,30 @@ +package org.cbioportal.legacy.model; + +import java.io.Serializable; + +public class CopyNumberCountByGene extends AlterationCountByGene implements Serializable { + + private Integer alteration; + private String cytoband; + + public Integer getAlteration() { + return alteration; + } + + public void setAlteration(Integer alteration) { + this.alteration = alteration; + } + + public String getCytoband() { + return cytoband; + } + + public void setCytoband(String cytoband) { + this.cytoband = cytoband; + } + + @Override + public String getUniqueEventKey() { + return getEntrezGeneId().toString() + getAlteration().toString(); + } +} diff --git a/src/main/java/org/cbioportal/legacy/model/CopyNumberSeg.java b/src/main/java/org/cbioportal/legacy/model/CopyNumberSeg.java new file mode 100644 index 00000000000..0819853777f --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/CopyNumberSeg.java @@ -0,0 +1,107 @@ +package org.cbioportal.legacy.model; + +import jakarta.validation.constraints.NotNull; +import java.math.BigDecimal; + +public class CopyNumberSeg extends UniqueKeyBase { + + private Long segId; + private Integer cancerStudyId; + @NotNull private String cancerStudyIdentifier; + private Integer sampleId; + @NotNull private String sampleStableId; + @NotNull private String patientId; + @NotNull private String chr; + @NotNull private Integer start; + @NotNull private Integer end; + @NotNull private Integer numProbes; + @NotNull private BigDecimal segmentMean; + + public Long getSegId() { + return segId; + } + + public void setSegId(Long segId) { + this.segId = segId; + } + + public Integer getCancerStudyId() { + return cancerStudyId; + } + + public void setCancerStudyId(Integer cancerStudyId) { + this.cancerStudyId = cancerStudyId; + } + + public String getCancerStudyIdentifier() { + return cancerStudyIdentifier; + } + + public void setCancerStudyIdentifier(String cancerStudyIdentifier) { + this.cancerStudyIdentifier = cancerStudyIdentifier; + } + + public Integer getSampleId() { + return sampleId; + } + + public void setSampleId(Integer sampleId) { + this.sampleId = sampleId; + } + + public String getSampleStableId() { + return sampleStableId; + } + + public void setSampleStableId(String sampleStableId) { + this.sampleStableId = sampleStableId; + } + + public String getPatientId() { + return patientId; + } + + public void setPatientId(String patientId) { + this.patientId = patientId; + } + + public String getChr() { + return chr; + } + + public void setChr(String chr) { + this.chr = chr; + } + + public Integer getStart() { + return start; + } + + public void setStart(Integer start) { + this.start = start; + } + + public Integer getEnd() { + return end; + } + + public void setEnd(Integer end) { + this.end = end; + } + + public Integer getNumProbes() { + return numProbes; + } + + public void setNumProbes(Integer numProbes) { + this.numProbes = numProbes; + } + + public BigDecimal getSegmentMean() { + return segmentMean; + } + + public void setSegmentMean(BigDecimal segmentMean) { + this.segmentMean = segmentMean; + } +} diff --git a/src/main/java/org/cbioportal/legacy/model/CosmicMutation.java b/src/main/java/org/cbioportal/legacy/model/CosmicMutation.java new file mode 100644 index 00000000000..cfe952064a6 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/CosmicMutation.java @@ -0,0 +1,44 @@ +package org.cbioportal.legacy.model; + +import jakarta.validation.constraints.NotNull; +import java.io.Serializable; + +public class CosmicMutation implements Serializable { + + @NotNull private String cosmicMutationId; + @NotNull private String proteinChange; + private String keyword; + @NotNull private Integer count; + + public String getCosmicMutationId() { + return cosmicMutationId; + } + + public void setCosmicMutationId(String cosmicMutationId) { + this.cosmicMutationId = cosmicMutationId; + } + + public String getProteinChange() { + return proteinChange; + } + + public void setProteinChange(String proteinChange) { + this.proteinChange = proteinChange; + } + + public String getKeyword() { + return keyword; + } + + public void setKeyword(String keyword) { + this.keyword = keyword; + } + + public Integer getCount() { + return count; + } + + public void setCount(Integer count) { + this.count = count; + } +} diff --git a/src/main/java/org/cbioportal/legacy/model/CountSummary.java b/src/main/java/org/cbioportal/legacy/model/CountSummary.java new file mode 100644 index 00000000000..f3f6de7dc3f --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/CountSummary.java @@ -0,0 +1,38 @@ +package org.cbioportal.legacy.model; + +import jakarta.validation.constraints.NotNull; +import java.io.Serializable; + +/** + * @author ochoaa + */ +public class CountSummary implements Serializable { + + @NotNull private String name; + @NotNull private Integer alteredCount; + @NotNull private Integer profiledCount; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Integer getAlteredCount() { + return alteredCount; + } + + public void setAlteredCount(Integer alteredCount) { + this.alteredCount = alteredCount; + } + + public Integer getProfiledCount() { + return profiledCount; + } + + public void setProfiledCount(Integer profiledCount) { + this.profiledCount = profiledCount; + } +} diff --git a/src/main/java/org/cbioportal/legacy/model/CustomDriverAnnotationReport.java b/src/main/java/org/cbioportal/legacy/model/CustomDriverAnnotationReport.java new file mode 100644 index 00000000000..d2853c8d332 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/CustomDriverAnnotationReport.java @@ -0,0 +1,24 @@ +package org.cbioportal.legacy.model; + +import java.io.Serializable; +import java.util.Set; + +public class CustomDriverAnnotationReport implements Serializable { + private static final long serialVersionUID = 1L; + + private final boolean hasBinary; + private final Set tiers; + + public CustomDriverAnnotationReport(boolean hasBinary, Set tiers) { + this.hasBinary = hasBinary; + this.tiers = tiers; + } + + public boolean getHasBinary() { + return hasBinary; + } + + public Set getTiers() { + return tiers; + } +} diff --git a/src/main/java/org/cbioportal/legacy/model/DataAccessToken.java b/src/main/java/org/cbioportal/legacy/model/DataAccessToken.java new file mode 100644 index 00000000000..10494711e81 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/DataAccessToken.java @@ -0,0 +1,75 @@ +package org.cbioportal.legacy.model; + +import java.io.Serializable; +import java.util.Date; + +public class DataAccessToken implements Serializable { + + private static final long serialVersionUID = 1L; + + private String token; + private String username; + private Date expiration; + private Date creation; + + public DataAccessToken() {} + + public DataAccessToken(String token) { + this.token = token; + } + + public DataAccessToken(String token, String username, Date expiration, Date creation) { + this.token = token; + this.username = username; + this.expiration = expiration; + this.creation = creation; + } + + public String getToken() { + return token; + } + + public void setToken(String token) { + this.token = token; + } + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public Date getExpiration() { + return expiration; + } + + public void setExpiration(Date expiration) { + this.expiration = expiration; + } + + public Date getCreation() { + return creation; + } + + public void setCreation(Date creation) { + this.creation = creation; + } + + public boolean hasEarlierExpirationThanToken(DataAccessToken dataAccessToken) { + return (this.expiration != null && this.expiration.before(dataAccessToken.getExpiration())); + } + + @Override + public String toString() { + StringBuilder b = new StringBuilder().append("token: ").append(token).append("\n"); + if (creation != null) { + b.append("creation_date: ").append(creation.toString()).append("\n"); + } + if (expiration != null) { + b.append("expiration_date: ").append(expiration.toString()).append("\n"); + } + return b.toString(); + } +} diff --git a/src/main/java/org/cbioportal/legacy/model/DataBin.java b/src/main/java/org/cbioportal/legacy/model/DataBin.java new file mode 100644 index 00000000000..cb7b30e371a --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/DataBin.java @@ -0,0 +1,44 @@ +package org.cbioportal.legacy.model; + +import java.io.Serializable; +import java.math.BigDecimal; + +public class DataBin implements Serializable { + + private String specialValue; + private BigDecimal start; + private BigDecimal end; + private Integer count; + + public String getSpecialValue() { + return specialValue; + } + + public void setSpecialValue(String specialValue) { + this.specialValue = specialValue; + } + + public BigDecimal getStart() { + return start; + } + + public void setStart(BigDecimal start) { + this.start = start; + } + + public BigDecimal getEnd() { + return end; + } + + public void setEnd(BigDecimal end) { + this.end = end; + } + + public Integer getCount() { + return count; + } + + public void setCount(Integer count) { + this.count = count; + } +} diff --git a/src/main/java/org/cbioportal/legacy/model/DensityPlotBin.java b/src/main/java/org/cbioportal/legacy/model/DensityPlotBin.java new file mode 100644 index 00000000000..1dfce1c6a11 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/DensityPlotBin.java @@ -0,0 +1,71 @@ +package org.cbioportal.legacy.model; + +import java.io.Serializable; +import java.math.BigDecimal; + +public class DensityPlotBin implements Serializable { + + private Integer count; + private BigDecimal binX; + private BigDecimal binY; + private BigDecimal minX; + private BigDecimal maxX; + private BigDecimal minY; + private BigDecimal maxY; + + public Integer getCount() { + return count; + } + + public void setCount(Integer count) { + this.count = count; + } + + public BigDecimal getBinX() { + return binX; + } + + public void setBinX(BigDecimal binX) { + this.binX = binX; + } + + public BigDecimal getBinY() { + return binY; + } + + public void setBinY(BigDecimal binY) { + this.binY = binY; + } + + public BigDecimal getMinX() { + return minX; + } + + public void setMinX(BigDecimal minX) { + this.minX = minX; + } + + public BigDecimal getMaxX() { + return maxX; + } + + public void setMaxX(BigDecimal maxX) { + this.maxX = maxX; + } + + public BigDecimal getMinY() { + return minY; + } + + public void setMinY(BigDecimal minY) { + this.minY = minY; + } + + public BigDecimal getMaxY() { + return maxY; + } + + public void setMaxY(BigDecimal maxY) { + this.maxY = maxY; + } +} diff --git a/src/main/java/org/cbioportal/legacy/model/DensityPlotData.java b/src/main/java/org/cbioportal/legacy/model/DensityPlotData.java new file mode 100644 index 00000000000..5bc93f6a5e2 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/DensityPlotData.java @@ -0,0 +1,38 @@ +package org.cbioportal.legacy.model; + +import jakarta.validation.constraints.NotNull; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + +public class DensityPlotData implements Serializable { + @NotNull private List bins = new ArrayList<>(); + + private Double pearsonCorr; + + private Double spearmanCorr; + + public List getBins() { + return bins; + } + + public void setBins(List bins) { + this.bins = bins; + } + + public Double getPearsonCorr() { + return pearsonCorr; + } + + public void setPearsonCorr(Double pearsonCorr) { + this.pearsonCorr = pearsonCorr; + } + + public Double getSpearmanCorr() { + return spearmanCorr; + } + + public void setSpearmanCorr(Double spearmanCorr) { + this.spearmanCorr = spearmanCorr; + } +} diff --git a/src/main/java/org/cbioportal/legacy/model/DiscreteCopyNumberData.java b/src/main/java/org/cbioportal/legacy/model/DiscreteCopyNumberData.java new file mode 100644 index 00000000000..22438d0bff2 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/DiscreteCopyNumberData.java @@ -0,0 +1,30 @@ +package org.cbioportal.legacy.model; + +import com.fasterxml.jackson.annotation.JsonRawValue; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import java.io.Serializable; + +public class DiscreteCopyNumberData extends Alteration implements Serializable { + @NotNull private Integer alteration; + + @JsonRawValue + @Schema(type = "java.util.Map") + private Object annotationJson; + + public Integer getAlteration() { + return alteration; + } + + public void setAlteration(Integer alteration) { + this.alteration = alteration; + } + + public Object getAnnotationJson() { + return annotationJson; + } + + public void setAnnotationJson(String annotationJson) { + this.annotationJson = annotationJson; + } +} diff --git a/src/main/java/org/cbioportal/legacy/model/EnrichmentType.java b/src/main/java/org/cbioportal/legacy/model/EnrichmentType.java new file mode 100644 index 00000000000..e5198fdf1b4 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/EnrichmentType.java @@ -0,0 +1,6 @@ +package org.cbioportal.legacy.model; + +public enum EnrichmentType { + SAMPLE, + PATIENT +} diff --git a/src/main/java/org/cbioportal/legacy/model/EntityType.java b/src/main/java/org/cbioportal/legacy/model/EntityType.java new file mode 100644 index 00000000000..4ebc0346c1b --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/EntityType.java @@ -0,0 +1,8 @@ +package org.cbioportal.legacy.model; + +public enum EntityType { + GENE, + GENESET, + PHOSPHOPROTEIN, + GENERIC_ASSAY +} diff --git a/src/main/java/org/cbioportal/legacy/model/ExpressionEnrichment.java b/src/main/java/org/cbioportal/legacy/model/ExpressionEnrichment.java new file mode 100644 index 00000000000..36e64cf1977 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/ExpressionEnrichment.java @@ -0,0 +1,30 @@ +package org.cbioportal.legacy.model; + +import com.fasterxml.jackson.annotation.JsonProperty; +import jakarta.validation.constraints.NotNull; +import java.io.Serializable; +import java.math.BigDecimal; +import java.util.List; + +public class ExpressionEnrichment implements Serializable { + + @NotNull private List groupsStatistics; + @NotNull private BigDecimal pValue; + + public List getGroupsStatistics() { + return groupsStatistics; + } + + public void setGroupsStatistics(List groupsStatistics) { + this.groupsStatistics = groupsStatistics; + } + + @JsonProperty("pValue") + public BigDecimal getpValue() { + return pValue; + } + + public void setpValue(BigDecimal pValue) { + this.pValue = pValue; + } +} diff --git a/src/main/java/org/cbioportal/legacy/model/FractionGenomeAltered.java b/src/main/java/org/cbioportal/legacy/model/FractionGenomeAltered.java new file mode 100644 index 00000000000..a04394e47a0 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/FractionGenomeAltered.java @@ -0,0 +1,44 @@ +package org.cbioportal.legacy.model; + +import jakarta.validation.constraints.NotNull; +import java.math.BigDecimal; + +public class FractionGenomeAltered extends UniqueKeyBase { + + @NotNull private String studyId; + @NotNull private String sampleId; + @NotNull private String patientId; + @NotNull private BigDecimal value; + + public String getStudyId() { + return studyId; + } + + public void setStudyId(String studyId) { + this.studyId = studyId; + } + + public String getSampleId() { + return sampleId; + } + + public void setSampleId(String sampleId) { + this.sampleId = sampleId; + } + + public String getPatientId() { + return patientId; + } + + public void setPatientId(String patientId) { + this.patientId = patientId; + } + + public BigDecimal getValue() { + return value; + } + + public void setValue(BigDecimal value) { + this.value = value; + } +} diff --git a/src/main/java/org/cbioportal/legacy/model/Gene.java b/src/main/java/org/cbioportal/legacy/model/Gene.java new file mode 100644 index 00000000000..749d31a6d43 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/Gene.java @@ -0,0 +1,44 @@ +package org.cbioportal.legacy.model; + +import jakarta.validation.constraints.NotNull; +import java.io.Serializable; + +public class Gene implements Serializable { + + @NotNull private Integer geneticEntityId; + @NotNull private Integer entrezGeneId; + @NotNull private String hugoGeneSymbol; + private String type; + + public Integer getGeneticEntityId() { + return geneticEntityId; + } + + public void setGeneticEntityId(Integer geneticEntityId) { + this.geneticEntityId = geneticEntityId; + } + + public Integer getEntrezGeneId() { + return entrezGeneId; + } + + public void setEntrezGeneId(Integer entrezGeneId) { + this.entrezGeneId = entrezGeneId; + } + + public String getHugoGeneSymbol() { + return hugoGeneSymbol; + } + + public void setHugoGeneSymbol(String hugoGeneSymbol) { + this.hugoGeneSymbol = hugoGeneSymbol; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } +} diff --git a/src/main/java/org/cbioportal/legacy/model/GeneAlias.java b/src/main/java/org/cbioportal/legacy/model/GeneAlias.java new file mode 100644 index 00000000000..45ea31344ad --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/GeneAlias.java @@ -0,0 +1,25 @@ +package org.cbioportal.legacy.model; + +import java.io.Serializable; + +public class GeneAlias implements Serializable { + + private Integer entrezGeneId; + private String geneAlias; + + public Integer getEntrezGeneId() { + return entrezGeneId; + } + + public void setEntrezGeneId(Integer entrezGeneId) { + this.entrezGeneId = entrezGeneId; + } + + public String getGeneAlias() { + return geneAlias; + } + + public void setGeneAlias(String geneAlias) { + this.geneAlias = geneAlias; + } +} diff --git a/src/main/java/org/cbioportal/legacy/model/GeneFilter.java b/src/main/java/org/cbioportal/legacy/model/GeneFilter.java new file mode 100644 index 00000000000..e3d02dd8205 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/GeneFilter.java @@ -0,0 +1,27 @@ +package org.cbioportal.legacy.model; + +import java.io.Serializable; +import java.util.List; +import java.util.Set; + +public class GeneFilter implements Serializable { + + private Set molecularProfileIds; + private List> geneQueries; + + public Set getMolecularProfileIds() { + return molecularProfileIds; + } + + public void setMolecularProfileIds(Set molecularProfileIds) { + this.molecularProfileIds = molecularProfileIds; + } + + public List> getGeneQueries() { + return geneQueries; + } + + public void setGeneQueries(List> geneQueries) { + this.geneQueries = geneQueries; + } +} diff --git a/src/main/java/org/cbioportal/legacy/model/GeneFilterQuery.java b/src/main/java/org/cbioportal/legacy/model/GeneFilterQuery.java new file mode 100644 index 00000000000..8c55a1b3cad --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/GeneFilterQuery.java @@ -0,0 +1,64 @@ +package org.cbioportal.legacy.model; + +import java.io.Serializable; +import java.util.List; +import org.cbioportal.legacy.model.util.Select; + +public class GeneFilterQuery extends BaseAlterationFilter implements Serializable { + + private String hugoGeneSymbol; + private Integer entrezGeneId; + private List alterations; + + public GeneFilterQuery() {} + + public GeneFilterQuery( + String hugoGeneSymbol, + Integer entrezGeneId, + List alterations, + boolean includeDriver, + boolean includeVUS, + boolean includeUnknownOncogenicity, + Select tiersSelect, + boolean includeUnknownTier, + boolean includeGermline, + boolean includeSomatic, + boolean includeUnknownStatus) { + super( + includeDriver, + includeVUS, + includeUnknownOncogenicity, + includeGermline, + includeSomatic, + includeUnknownStatus, + tiersSelect, + includeUnknownTier); + this.hugoGeneSymbol = hugoGeneSymbol; + this.entrezGeneId = entrezGeneId; + this.alterations = alterations; + } + + public String getHugoGeneSymbol() { + return hugoGeneSymbol; + } + + public void setHugoGeneSymbol(String hugoGeneSymbol) { + this.hugoGeneSymbol = hugoGeneSymbol; + } + + public Integer getEntrezGeneId() { + return entrezGeneId; + } + + public void setEntrezGeneId(int entrezGeneId) { + this.entrezGeneId = entrezGeneId; + } + + public List getAlterations() { + return alterations; + } + + public void setAlterations(List alterations) { + this.alterations = alterations; + } +} diff --git a/src/main/java/org/cbioportal/legacy/model/GeneMolecularAlteration.java b/src/main/java/org/cbioportal/legacy/model/GeneMolecularAlteration.java new file mode 100644 index 00000000000..06b81b0c933 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/GeneMolecularAlteration.java @@ -0,0 +1,39 @@ +package org.cbioportal.legacy.model; + +import java.io.Serializable; + +public class GeneMolecularAlteration extends MolecularAlteration implements Serializable { + + private String molecularProfileId; + private Integer entrezGeneId; + private Gene gene; + + public String getMolecularProfileId() { + return molecularProfileId; + } + + public void setMolecularProfileId(String molecularProfileId) { + this.molecularProfileId = molecularProfileId; + } + + public Integer getEntrezGeneId() { + return entrezGeneId; + } + + public void setEntrezGeneId(Integer entrezGeneId) { + this.entrezGeneId = entrezGeneId; + } + + public Gene getGene() { + return gene; + } + + public void setGene(Gene gene) { + this.gene = gene; + } + + @Override + public String getStableId() { + return entrezGeneId.toString(); + } +} diff --git a/src/main/java/org/cbioportal/legacy/model/GeneMolecularData.java b/src/main/java/org/cbioportal/legacy/model/GeneMolecularData.java new file mode 100644 index 00000000000..0a7312db918 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/GeneMolecularData.java @@ -0,0 +1,31 @@ +package org.cbioportal.legacy.model; + +import jakarta.validation.constraints.NotNull; +import java.io.Serializable; + +public class GeneMolecularData extends MolecularData implements Serializable { + + @NotNull private Integer entrezGeneId; + private Gene gene; + + public Integer getEntrezGeneId() { + return entrezGeneId; + } + + public void setEntrezGeneId(Integer entrezGeneId) { + this.entrezGeneId = entrezGeneId; + } + + public Gene getGene() { + return gene; + } + + public void setGene(Gene gene) { + this.gene = gene; + } + + @Override + public String getStableId() { + return entrezGeneId.toString(); + } +} diff --git a/src/main/java/org/cbioportal/legacy/model/GenePanel.java b/src/main/java/org/cbioportal/legacy/model/GenePanel.java new file mode 100644 index 00000000000..1a1ea109ba1 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/GenePanel.java @@ -0,0 +1,45 @@ +package org.cbioportal.legacy.model; + +import jakarta.validation.constraints.NotNull; +import java.io.Serializable; +import java.util.List; + +public class GenePanel implements Serializable { + + private Integer internalId; + @NotNull private String stableId; + private String description; + private List genes; + + public Integer getInternalId() { + return internalId; + } + + public void setInternalId(Integer internalId) { + this.internalId = internalId; + } + + public String getStableId() { + return stableId; + } + + public void setStableId(String stableId) { + this.stableId = stableId; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public List getGenes() { + return genes; + } + + public void setGenes(List genes) { + this.genes = genes; + } +} diff --git a/src/main/java/org/cbioportal/legacy/model/GenePanelData.java b/src/main/java/org/cbioportal/legacy/model/GenePanelData.java new file mode 100644 index 00000000000..8ce5db6051b --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/GenePanelData.java @@ -0,0 +1,61 @@ +package org.cbioportal.legacy.model; + +import jakarta.validation.constraints.NotNull; + +public class GenePanelData extends UniqueKeyBase { + + @NotNull private String molecularProfileId; + @NotNull private String sampleId; + @NotNull private String patientId; + @NotNull private String studyId; + private String genePanelId; + @NotNull private Boolean profiled; + + public String getMolecularProfileId() { + return molecularProfileId; + } + + public void setMolecularProfileId(String molecularProfileId) { + this.molecularProfileId = molecularProfileId; + } + + public String getSampleId() { + return sampleId; + } + + public void setSampleId(String sampleId) { + this.sampleId = sampleId; + } + + public String getPatientId() { + return patientId; + } + + public void setPatientId(String patientId) { + this.patientId = patientId; + } + + public String getStudyId() { + return studyId; + } + + public void setStudyId(String studyId) { + this.studyId = studyId; + } + + public String getGenePanelId() { + return genePanelId; + } + + public void setGenePanelId(String genePanelId) { + this.genePanelId = genePanelId; + } + + public Boolean getProfiled() { + return profiled; + } + + public void setProfiled(Boolean profiled) { + this.profiled = profiled; + } +} diff --git a/src/main/java/org/cbioportal/legacy/model/GenePanelToGene.java b/src/main/java/org/cbioportal/legacy/model/GenePanelToGene.java new file mode 100644 index 00000000000..ea1971170aa --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/GenePanelToGene.java @@ -0,0 +1,35 @@ +package org.cbioportal.legacy.model; + +import jakarta.validation.constraints.NotNull; +import java.io.Serializable; + +public class GenePanelToGene implements Serializable { + + private String genePanelId; + @NotNull private Integer entrezGeneId; + @NotNull private String hugoGeneSymbol; + + public String getGenePanelId() { + return genePanelId; + } + + public void setGenePanelId(String genePanelId) { + this.genePanelId = genePanelId; + } + + public Integer getEntrezGeneId() { + return entrezGeneId; + } + + public void setEntrezGeneId(Integer entrezGeneId) { + this.entrezGeneId = entrezGeneId; + } + + public String getHugoGeneSymbol() { + return hugoGeneSymbol; + } + + public void setHugoGeneSymbol(String hugoGeneSymbol) { + this.hugoGeneSymbol = hugoGeneSymbol; + } +} diff --git a/src/main/java/org/cbioportal/legacy/model/GenericAssayAdditionalProperty.java b/src/main/java/org/cbioportal/legacy/model/GenericAssayAdditionalProperty.java new file mode 100644 index 00000000000..ce243c7a0d0 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/GenericAssayAdditionalProperty.java @@ -0,0 +1,39 @@ +package org.cbioportal.legacy.model; + +import java.io.Serializable; + +public class GenericAssayAdditionalProperty implements Serializable { + private String name; + private String value; + private String stableId; + + public GenericAssayAdditionalProperty(String name, String value, String stableId) { + this.name = name; + this.value = value; + this.stableId = stableId; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + + public String getStableId() { + return stableId; + } + + public void setStableId(String stableId) { + this.stableId = stableId; + } +} diff --git a/src/main/java/org/cbioportal/legacy/model/GenericAssayBinaryEnrichment.java b/src/main/java/org/cbioportal/legacy/model/GenericAssayBinaryEnrichment.java new file mode 100644 index 00000000000..e205db1bb30 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/GenericAssayBinaryEnrichment.java @@ -0,0 +1,16 @@ +package org.cbioportal.legacy.model; + +import jakarta.validation.constraints.NotNull; +import java.util.List; + +public class GenericAssayBinaryEnrichment extends GenericAssayEnrichment { + @NotNull private List counts; + + public List getCounts() { + return counts; + } + + public void setCounts(List counts) { + this.counts = counts; + } +} diff --git a/src/main/java/org/cbioportal/legacy/model/GenericAssayCategoricalEnrichment.java b/src/main/java/org/cbioportal/legacy/model/GenericAssayCategoricalEnrichment.java new file mode 100644 index 00000000000..9bc7419df7c --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/GenericAssayCategoricalEnrichment.java @@ -0,0 +1,18 @@ +package org.cbioportal.legacy.model; + +import com.fasterxml.jackson.annotation.JsonProperty; +import jakarta.validation.constraints.NotNull; +import java.math.BigDecimal; + +public class GenericAssayCategoricalEnrichment extends GenericAssayEnrichment { + @NotNull private BigDecimal qValue; + + @JsonProperty("qValue") + public BigDecimal getqValue() { + return qValue; + } + + public void setqValue(BigDecimal qValue) { + this.qValue = qValue; + } +} diff --git a/src/main/java/org/cbioportal/legacy/model/GenericAssayCountSummary.java b/src/main/java/org/cbioportal/legacy/model/GenericAssayCountSummary.java new file mode 100644 index 00000000000..c05e0ffb9bc --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/GenericAssayCountSummary.java @@ -0,0 +1,35 @@ +package org.cbioportal.legacy.model; + +import jakarta.validation.constraints.NotNull; +import java.io.Serializable; + +public class GenericAssayCountSummary implements Serializable { + + @NotNull private String name; + @NotNull private Integer count; + @NotNull private Integer totalCount; + + public Integer getCount() { + return count; + } + + public void setCount(Integer count) { + this.count = count; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Integer getTotalCount() { + return totalCount; + } + + public void setTotalCount(Integer totalCount) { + this.totalCount = totalCount; + } +} diff --git a/src/main/java/org/cbioportal/legacy/model/GenericAssayData.java b/src/main/java/org/cbioportal/legacy/model/GenericAssayData.java new file mode 100644 index 00000000000..c35949a89e0 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/GenericAssayData.java @@ -0,0 +1,38 @@ +package org.cbioportal.legacy.model; + +import jakarta.validation.constraints.NotNull; +import java.io.Serializable; + +public class GenericAssayData extends MolecularData implements Serializable { + + @NotNull private String genericAssayStableId; + + private boolean patientLevel; + + /** + * @return the genericAssayStableId + */ + public String getGenericAssayStableId() { + return genericAssayStableId; + } + + /** + * @param genericAssayStableId the genericAssayStableId to set + */ + public void setGenericAssayStableId(String genericAssayStableId) { + this.genericAssayStableId = genericAssayStableId; + } + + @Override + public String getStableId() { + return genericAssayStableId; + } + + public void setPatientLevel(boolean patientLevel) { + this.patientLevel = patientLevel; + } + + public boolean getPatientLevel() { + return patientLevel; + } +} diff --git a/src/main/java/org/cbioportal/legacy/model/GenericAssayDataBin.java b/src/main/java/org/cbioportal/legacy/model/GenericAssayDataBin.java new file mode 100644 index 00000000000..f476d244934 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/GenericAssayDataBin.java @@ -0,0 +1,24 @@ +package org.cbioportal.legacy.model; + +import java.io.Serializable; + +public class GenericAssayDataBin extends DataBin implements Serializable { + private String stableId; + private String profileType; + + public String getStableId() { + return stableId; + } + + public void setStableId(String stableId) { + this.stableId = stableId; + } + + public String getProfileType() { + return profileType; + } + + public void setProfileType(String profileType) { + this.profileType = profileType; + } +} diff --git a/src/main/java/org/cbioportal/legacy/model/GenericAssayDataCount.java b/src/main/java/org/cbioportal/legacy/model/GenericAssayDataCount.java new file mode 100644 index 00000000000..b7c30ad2d5d --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/GenericAssayDataCount.java @@ -0,0 +1,32 @@ +package org.cbioportal.legacy.model; + +import java.io.Serializable; + +public class GenericAssayDataCount implements Serializable { + + private String value; + private Integer count; + + public GenericAssayDataCount() {} + + public GenericAssayDataCount(String value, Integer count) { + this.value = value; + this.count = count; + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + + public Integer getCount() { + return count; + } + + public void setCount(Integer count) { + this.count = count; + } +} diff --git a/src/main/java/org/cbioportal/legacy/model/GenericAssayDataCountItem.java b/src/main/java/org/cbioportal/legacy/model/GenericAssayDataCountItem.java new file mode 100644 index 00000000000..bfaa6439c1a --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/GenericAssayDataCountItem.java @@ -0,0 +1,32 @@ +package org.cbioportal.legacy.model; + +import java.io.Serializable; +import java.util.List; + +public class GenericAssayDataCountItem implements Serializable { + private String stableId; + private List counts; + + public GenericAssayDataCountItem() {} + + public GenericAssayDataCountItem(String stableId, List counts) { + this.stableId = stableId; + this.counts = counts; + } + + public String getStableId() { + return stableId; + } + + public void setStableId(String stableId) { + this.stableId = stableId; + } + + public List getCounts() { + return counts; + } + + public void setCounts(List counts) { + this.counts = counts; + } +} diff --git a/src/main/java/org/cbioportal/legacy/model/GenericAssayEnrichment.java b/src/main/java/org/cbioportal/legacy/model/GenericAssayEnrichment.java new file mode 100644 index 00000000000..85bdcce177e --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/GenericAssayEnrichment.java @@ -0,0 +1,52 @@ +package org.cbioportal.legacy.model; + +import com.fasterxml.jackson.annotation.JsonProperty; +import jakarta.validation.constraints.NotNull; +import java.io.Serializable; +import java.math.BigDecimal; +import java.util.HashMap; + +public class GenericAssayEnrichment extends ExpressionEnrichment implements Serializable { + + @NotNull private String stableId; + @NotNull private String name; + @NotNull private BigDecimal qValue; + @NotNull private HashMap genericEntityMetaProperties; + + public String getStableId() { + return stableId; + } + + public void setStableId(String stableId) { + this.stableId = stableId; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public HashMap getGenericEntityMetaProperties() { + return genericEntityMetaProperties; + } + + public void setGenericEntityMetaProperties(HashMap genericEntityMetaProperties) { + this.genericEntityMetaProperties = genericEntityMetaProperties; + } + + @JsonProperty("qValue") + public BigDecimal getqValue() { + return qValue; + } + + public void setqValue(BigDecimal qValue) { + this.qValue = qValue; + } + + public static int compare(GenericAssayEnrichment c1, GenericAssayEnrichment c2) { + return c1.getpValue().compareTo(c2.getpValue()); + } +} diff --git a/src/main/java/org/cbioportal/legacy/model/GenericAssayMolecularAlteration.java b/src/main/java/org/cbioportal/legacy/model/GenericAssayMolecularAlteration.java new file mode 100644 index 00000000000..94494cfe5e7 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/GenericAssayMolecularAlteration.java @@ -0,0 +1,42 @@ +package org.cbioportal.legacy.model; + +import java.io.Serializable; + +public class GenericAssayMolecularAlteration extends MolecularAlteration implements Serializable { + + private String molecularProfileId; + private String genericAssayStableId; + + /** + * @return the genericAssayStableId + */ + public String getGenericAssayStableId() { + return genericAssayStableId; + } + + /** + * @param genericAssayStableId the genericAssayStableId to set + */ + public void setGenericAssayStableId(String genericAssayStableId) { + this.genericAssayStableId = genericAssayStableId; + } + + /** + * @return the molecularProfileId + */ + public String getMolecularProfileId() { + return molecularProfileId; + } + + /** + * @param molecularProfileId the molecularProfileId to set + */ + public void setMolecularProfileId(String molecularProfileId) { + this.molecularProfileId = molecularProfileId; + } + + @Override + public String getStableId() { + return genericAssayStableId; + } +} diff --git a/src/main/java/org/cbioportal/legacy/model/GenericEntityProperty.java b/src/main/java/org/cbioportal/legacy/model/GenericEntityProperty.java new file mode 100644 index 00000000000..ef9962fae80 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/GenericEntityProperty.java @@ -0,0 +1,39 @@ +package org.cbioportal.legacy.model; + +import java.io.Serializable; + +public class GenericEntityProperty implements Serializable { + private String name; + private String value; + private Integer entityId; + + public GenericEntityProperty(String name, String value, Integer entityId) { + this.name = name; + this.value = value; + this.entityId = entityId; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + + public Integer getEntityId() { + return entityId; + } + + public void setEntityId(Integer entityId) { + this.entityId = entityId; + } +} diff --git a/src/main/java/org/cbioportal/legacy/model/Geneset.java b/src/main/java/org/cbioportal/legacy/model/Geneset.java new file mode 100644 index 00000000000..de59a7cd6a0 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/Geneset.java @@ -0,0 +1,71 @@ +package org.cbioportal.legacy.model; + +import java.io.Serializable; + +public class Geneset implements Serializable { + + private Integer internalId; + private String genesetId; + private String name; + private String description; + private String refLink; + // representative score (can be set when retrieved in study context): + private Double representativeScore; + private Double representativePvalue; + + public Integer getInternalId() { + return internalId; + } + + public void setInternalId(Integer internalId) { + this.internalId = internalId; + } + + public String getGenesetId() { + return genesetId; + } + + public void setGenesetId(String genesetId) { + this.genesetId = genesetId; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public String getRefLink() { + return refLink; + } + + public void setRefLink(String refLink) { + this.refLink = refLink; + } + + public Double getRepresentativeScore() { + return representativeScore; + } + + public void setRepresentativeScore(Double representativeScore) { + this.representativeScore = representativeScore; + } + + public Double getRepresentativePvalue() { + return representativePvalue; + } + + public void setRepresentativePvalue(Double representativePvalue) { + this.representativePvalue = representativePvalue; + } +} diff --git a/src/main/java/org/cbioportal/legacy/model/GenesetCorrelation.java b/src/main/java/org/cbioportal/legacy/model/GenesetCorrelation.java new file mode 100644 index 00000000000..e097a99e00b --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/GenesetCorrelation.java @@ -0,0 +1,52 @@ +package org.cbioportal.legacy.model; + +import java.io.Serializable; + +public class GenesetCorrelation implements Serializable { + + private Integer entrezGeneId; + private String hugoGeneSymbol; + private Double correlationValue; + private String expressionMolecularProfileId; + private String zScoreMolecularProfileId; + + public Integer getEntrezGeneId() { + return entrezGeneId; + } + + public void setEntrezGeneId(Integer entrezGeneId) { + this.entrezGeneId = entrezGeneId; + } + + public String getHugoGeneSymbol() { + return hugoGeneSymbol; + } + + public void setHugoGeneSymbol(String hugoGeneSymbol) { + this.hugoGeneSymbol = hugoGeneSymbol; + } + + public Double getCorrelationValue() { + return correlationValue; + } + + public void setCorrelationValue(Double correlationValue) { + this.correlationValue = correlationValue; + } + + public String getExpressionMolecularProfileId() { + return expressionMolecularProfileId; + } + + public void setExpressionMolecularProfileId(String expressionMolecularProfileId) { + this.expressionMolecularProfileId = expressionMolecularProfileId; + } + + public String getzScoreMolecularProfileId() { + return zScoreMolecularProfileId; + } + + public void setzScoreMolecularProfileId(String zScoreMolecularProfileId) { + this.zScoreMolecularProfileId = zScoreMolecularProfileId; + } +} diff --git a/src/main/java/org/cbioportal/legacy/model/GenesetHierarchyInfo.java b/src/main/java/org/cbioportal/legacy/model/GenesetHierarchyInfo.java new file mode 100644 index 00000000000..af81c8f1570 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/GenesetHierarchyInfo.java @@ -0,0 +1,53 @@ +package org.cbioportal.legacy.model; + +import java.io.Serializable; +import java.util.List; + +public class GenesetHierarchyInfo implements Serializable { + + private Integer nodeId; + private String nodeName; + private Integer parentId; + private String parentNodeName; + private List genesets; + + public Integer getNodeId() { + return nodeId; + } + + public void setNodeId(Integer nodeId) { + this.nodeId = nodeId; + } + + public Integer getParentId() { + return parentId; + } + + public void setParentId(Integer parentId) { + this.parentId = parentId; + } + + public String getNodeName() { + return nodeName; + } + + public void setNodeName(String nodeName) { + this.nodeName = nodeName; + } + + public String getParentNodeName() { + return parentNodeName; + } + + public void setParentNodeName(String parentNodeName) { + this.parentNodeName = parentNodeName; + } + + public List getGenesets() { + return genesets; + } + + public void setGenesets(List genesets) { + this.genesets = genesets; + } +} diff --git a/src/main/java/org/cbioportal/legacy/model/GenesetMolecularAlteration.java b/src/main/java/org/cbioportal/legacy/model/GenesetMolecularAlteration.java new file mode 100644 index 00000000000..d1db791740c --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/GenesetMolecularAlteration.java @@ -0,0 +1,30 @@ +package org.cbioportal.legacy.model; + +import java.io.Serializable; + +public class GenesetMolecularAlteration extends MolecularAlteration implements Serializable { + + private String genesetId; + private Geneset geneset; + + public String getGenesetId() { + return genesetId; + } + + public void setGenesetId(String genesetId) { + this.genesetId = genesetId; + } + + public Geneset getGeneset() { + return geneset; + } + + public void setGeneset(Geneset geneset) { + this.geneset = geneset; + } + + @Override + public String getStableId() { + return genesetId; + } +} diff --git a/src/main/java/org/cbioportal/legacy/model/GenesetMolecularData.java b/src/main/java/org/cbioportal/legacy/model/GenesetMolecularData.java new file mode 100644 index 00000000000..5868c02297a --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/GenesetMolecularData.java @@ -0,0 +1,30 @@ +package org.cbioportal.legacy.model; + +import java.io.Serializable; + +public class GenesetMolecularData extends MolecularData implements Serializable { + + private String genesetId; + private Geneset geneset; + + public String getGenesetId() { + return genesetId; + } + + public void setGenesetId(String genesetId) { + this.genesetId = genesetId; + } + + public Geneset getGeneset() { + return geneset; + } + + public void setGeneset(Geneset geneset) { + this.geneset = geneset; + } + + @Override + public String getStableId() { + return genesetId; + } +} diff --git a/src/main/java/org/cbioportal/legacy/model/GeneticEntity.java b/src/main/java/org/cbioportal/legacy/model/GeneticEntity.java new file mode 100644 index 00000000000..f3abbe3964c --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/GeneticEntity.java @@ -0,0 +1,80 @@ +package org.cbioportal.legacy.model; + +import java.io.Serializable; + +public class GeneticEntity implements Serializable { + + private int id; + private String stableId; + private String entityType; + + /** + * Create a GeneticEntity object from fields + * + * @param id Internal Id + * @param entityType Type of the genetic entity + * @param stableId Stable identifier + */ + public GeneticEntity(Integer id, String entityType, String stableId) { + this.id = id; + this.entityType = entityType; + this.stableId = stableId; + } + + /** + * Create a GeneticEntity object from fields + * + * @param entityType Type of the genetic entity + * @param stableId Stable identifier + */ + public GeneticEntity(String entityType, String stableId) { + this.entityType = entityType; + this.stableId = stableId; + } + + public GeneticEntity(String entityType) { + this.entityType = entityType; + } + + /** + * @return the id + */ + public int getId() { + return id; + } + + /** + * @param id the id to set + */ + public void setId(Integer id) { + this.id = id; + } + + /** + * @return the stableId + */ + public String getStableId() { + return stableId; + } + + /** + * @param stableId the stableId to set + */ + public void setStableId(String stableId) { + this.stableId = stableId; + } + + /** + * @return the entity type + */ + public String getEntityType() { + return entityType; + } + + /** + * @param entityType the entityType to set + */ + public void setEntityType(String entityType) { + this.entityType = entityType; + } +} diff --git a/src/main/java/org/cbioportal/legacy/model/GenomicDataBin.java b/src/main/java/org/cbioportal/legacy/model/GenomicDataBin.java new file mode 100644 index 00000000000..95c4e0afdea --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/GenomicDataBin.java @@ -0,0 +1,24 @@ +package org.cbioportal.legacy.model; + +import java.io.Serializable; + +public class GenomicDataBin extends DataBin implements Serializable { + private String hugoGeneSymbol; + private String profileType; + + public String getHugoGeneSymbol() { + return hugoGeneSymbol; + } + + public void setHugoGeneSymbol(String hugoGeneSymbol) { + this.hugoGeneSymbol = hugoGeneSymbol; + } + + public String getProfileType() { + return profileType; + } + + public void setProfileType(String profileType) { + this.profileType = profileType; + } +} diff --git a/src/main/java/org/cbioportal/legacy/model/GenomicDataCount.java b/src/main/java/org/cbioportal/legacy/model/GenomicDataCount.java new file mode 100644 index 00000000000..dac607fd950 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/GenomicDataCount.java @@ -0,0 +1,75 @@ +package org.cbioportal.legacy.model; + +import java.io.Serializable; +import java.util.Objects; + +public class GenomicDataCount implements Serializable { + + private String label; + private String value; + private Integer count; + private Integer uniqueCount; + + public GenomicDataCount() {} + + public GenomicDataCount(String label, String value, Integer count) { + this.label = label; + this.value = value; + this.count = count; + } + + public GenomicDataCount(String label, String value, Integer count, Integer uniqueCount) { + this.label = label; + this.value = value; + this.count = count; + this.uniqueCount = uniqueCount; + } + + public String getLabel() { + return label; + } + + public void setLabel(String label) { + this.label = label; + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + + public Integer getCount() { + return count; + } + + public void setCount(Integer count) { + this.count = count; + } + + public Integer getUniqueCount() { + return uniqueCount; + } + + public void setUniqueCount(Integer uniqueCount) { + this.uniqueCount = uniqueCount; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + GenomicDataCount that = (GenomicDataCount) o; + return Objects.equals(label, that.label) + && Objects.equals(value, that.value) + && Objects.equals(count, that.count) + && Objects.equals(uniqueCount, that.uniqueCount); + } + + @Override + public int hashCode() { + return Objects.hash(label, value, count, uniqueCount); + } +} diff --git a/src/main/java/org/cbioportal/legacy/model/GenomicDataCountItem.java b/src/main/java/org/cbioportal/legacy/model/GenomicDataCountItem.java new file mode 100644 index 00000000000..8d2d7a5bb22 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/GenomicDataCountItem.java @@ -0,0 +1,44 @@ +package org.cbioportal.legacy.model; + +import java.io.Serializable; +import java.util.List; + +public class GenomicDataCountItem implements Serializable { + + private String hugoGeneSymbol; + private String profileType; + private List counts; + + public GenomicDataCountItem() {} + + public GenomicDataCountItem( + String hugoGeneSymbol, String profileType, List counts) { + this.hugoGeneSymbol = hugoGeneSymbol; + this.profileType = profileType; + this.counts = counts; + } + + public String getHugoGeneSymbol() { + return hugoGeneSymbol; + } + + public void setHugoGeneSymbol(String hugoGeneSymbol) { + this.hugoGeneSymbol = hugoGeneSymbol; + } + + public String getProfileType() { + return profileType; + } + + public void setProfileType(String profileType) { + this.profileType = profileType; + } + + public List getCounts() { + return counts; + } + + public void setCounts(List counts) { + this.counts = counts; + } +} diff --git a/src/main/java/org/cbioportal/legacy/model/GenomicEnrichment.java b/src/main/java/org/cbioportal/legacy/model/GenomicEnrichment.java new file mode 100644 index 00000000000..e5f583eeacd --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/GenomicEnrichment.java @@ -0,0 +1,35 @@ +package org.cbioportal.legacy.model; + +import jakarta.validation.constraints.NotNull; +import java.io.Serializable; + +public class GenomicEnrichment extends ExpressionEnrichment implements Serializable { + + @NotNull private Integer entrezGeneId; + @NotNull private String hugoGeneSymbol; + private String cytoband; + + public Integer getEntrezGeneId() { + return entrezGeneId; + } + + public void setEntrezGeneId(Integer entrezGeneId) { + this.entrezGeneId = entrezGeneId; + } + + public String getHugoGeneSymbol() { + return hugoGeneSymbol; + } + + public void setHugoGeneSymbol(String hugoGeneSymbol) { + this.hugoGeneSymbol = hugoGeneSymbol; + } + + public String getCytoband() { + return cytoband; + } + + public void setCytoband(String cytoband) { + this.cytoband = cytoband; + } +} diff --git a/src/main/java/org/cbioportal/legacy/model/Gistic.java b/src/main/java/org/cbioportal/legacy/model/Gistic.java new file mode 100644 index 00000000000..3f4ff9efe54 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/Gistic.java @@ -0,0 +1,93 @@ +package org.cbioportal.legacy.model; + +import com.fasterxml.jackson.annotation.JsonProperty; +import jakarta.validation.constraints.NotNull; +import java.io.Serializable; +import java.math.BigDecimal; +import java.util.List; + +public class Gistic implements Serializable { + + private Long gisticRoiId; + @NotNull private String cancerStudyId; + @NotNull private Integer chromosome; + @NotNull private String cytoband; + @NotNull private Integer widePeakStart; + @NotNull private Integer widePeakEnd; + @NotNull private BigDecimal qValue; + @NotNull private Boolean amp; + private List genes; + + public Long getGisticRoiId() { + return gisticRoiId; + } + + public void setGisticRoiId(Long gisticRoiId) { + this.gisticRoiId = gisticRoiId; + } + + public String getCancerStudyId() { + return cancerStudyId; + } + + public void setCancerStudyId(String cancerStudyId) { + this.cancerStudyId = cancerStudyId; + } + + public Integer getChromosome() { + return chromosome; + } + + public void setChromosome(Integer chromosome) { + this.chromosome = chromosome; + } + + public String getCytoband() { + return cytoband; + } + + public void setCytoband(String cytoband) { + this.cytoband = cytoband; + } + + public Integer getWidePeakStart() { + return widePeakStart; + } + + public void setWidePeakStart(Integer widePeakStart) { + this.widePeakStart = widePeakStart; + } + + public Integer getWidePeakEnd() { + return widePeakEnd; + } + + public void setWidePeakEnd(Integer widePeakEnd) { + this.widePeakEnd = widePeakEnd; + } + + @JsonProperty("qValue") + public BigDecimal getqValue() { + return qValue; + } + + public void setqValue(BigDecimal qValue) { + this.qValue = qValue; + } + + public Boolean getAmp() { + return amp; + } + + public void setAmp(Boolean amp) { + this.amp = amp; + } + + public List getGenes() { + return genes; + } + + public void setGenes(List genes) { + this.genes = genes; + } +} diff --git a/src/main/java/org/cbioportal/legacy/model/GisticToGene.java b/src/main/java/org/cbioportal/legacy/model/GisticToGene.java new file mode 100644 index 00000000000..1221195db8c --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/GisticToGene.java @@ -0,0 +1,35 @@ +package org.cbioportal.legacy.model; + +import jakarta.validation.constraints.NotNull; +import java.io.Serializable; + +public class GisticToGene implements Serializable { + + private Long gisticRoiId; + @NotNull private Integer entrezGeneId; + @NotNull private String hugoGeneSymbol; + + public Long getGisticRoiId() { + return gisticRoiId; + } + + public void setGisticRoiId(Long gisticRoiId) { + this.gisticRoiId = gisticRoiId; + } + + public Integer getEntrezGeneId() { + return entrezGeneId; + } + + public void setEntrezGeneId(Integer entrezGeneId) { + this.entrezGeneId = entrezGeneId; + } + + public String getHugoGeneSymbol() { + return hugoGeneSymbol; + } + + public void setHugoGeneSymbol(String hugoGeneSymbol) { + this.hugoGeneSymbol = hugoGeneSymbol; + } +} diff --git a/src/main/java/org/cbioportal/legacy/model/GroupStatistics.java b/src/main/java/org/cbioportal/legacy/model/GroupStatistics.java new file mode 100644 index 00000000000..e1150b875cd --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/GroupStatistics.java @@ -0,0 +1,36 @@ +package org.cbioportal.legacy.model; + +import jakarta.validation.constraints.NotNull; +import java.io.Serializable; +import java.math.BigDecimal; + +public class GroupStatistics implements Serializable { + + @NotNull private String name; + @NotNull private BigDecimal meanExpression; + @NotNull private BigDecimal standardDeviation; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public BigDecimal getMeanExpression() { + return meanExpression; + } + + public void setMeanExpression(BigDecimal meanExpression) { + this.meanExpression = meanExpression; + } + + public BigDecimal getStandardDeviation() { + return standardDeviation; + } + + public void setStandardDeviation(BigDecimal standardDeviation) { + this.standardDeviation = standardDeviation; + } +} diff --git a/src/main/java/org/cbioportal/legacy/model/Info.java b/src/main/java/org/cbioportal/legacy/model/Info.java new file mode 100644 index 00000000000..8bc11240d42 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/Info.java @@ -0,0 +1,124 @@ +package org.cbioportal.legacy.model; + +import jakarta.validation.constraints.NotNull; +import java.io.Serializable; + +public class Info implements Serializable { + @NotNull private String portalVersion; + @NotNull private String dbVersion; + @NotNull private String derivedTableVersion; + @NotNull private String gitBranch; + @NotNull private String gitCommitId; + @NotNull private String gitCommitIdAbbrev; + @NotNull private String gitCommitIdDescribe; + @NotNull private String gitCommitIdDescribeShort; + @NotNull private String gitCommitMessageFull; + @NotNull private String gitCommitMessageShort; + @NotNull private String gitCommitMessageUserEmail; + @NotNull private String gitCommitMessageUserName; + @NotNull private Boolean gitDirty; + + public String getGitBranch() { + return this.gitBranch; + } + + public void setGitBranch(String gitBranch) { + this.gitBranch = gitBranch; + } + + public String getGitCommitId() { + return this.gitCommitId; + } + + public void setGitCommitId(String gitCommitId) { + this.gitCommitId = gitCommitId; + } + + public String getGitCommitIdAbbrev() { + return this.gitCommitIdAbbrev; + } + + public void setGitCommitIdAbbrev(String gitCommitIdAbbrev) { + this.gitCommitIdAbbrev = gitCommitIdAbbrev; + } + + public String getGitCommitIdDescribe() { + return this.gitCommitIdDescribe; + } + + public void setGitCommitIdDescribe(String gitCommitIdDescribe) { + this.gitCommitIdDescribe = gitCommitIdDescribe; + } + + public String getGitCommitIdDescribeShort() { + return this.gitCommitIdDescribeShort; + } + + public void setGitCommitIdDescribeShort(String gitCommitIdDescribeShort) { + this.gitCommitIdDescribeShort = gitCommitIdDescribeShort; + } + + public String getGitCommitMessageFull() { + return this.gitCommitMessageFull; + } + + public void setGitCommitMessageFull(String gitCommitMessageFull) { + this.gitCommitMessageFull = gitCommitMessageFull; + } + + public String getGitCommitMessageShort() { + return this.gitCommitMessageShort; + } + + public void setGitCommitMessageShort(String gitCommitMessageShort) { + this.gitCommitMessageShort = gitCommitMessageShort; + } + + public String getGitCommitMessageUserEmail() { + return this.gitCommitMessageUserEmail; + } + + public void setGitCommitMessageUserEmail(String gitCommitMessageUserEmail) { + this.gitCommitMessageUserEmail = gitCommitMessageUserEmail; + } + + public String getGitCommitMessageUserName() { + return this.gitCommitMessageUserName; + } + + public void setGitCommitMessageUserName(String gitCommitMessageUserName) { + this.gitCommitMessageUserName = gitCommitMessageUserName; + } + + public Boolean getGitDirty() { + return this.gitDirty; + } + + public void isGitDirty(Boolean gitDirty) { + this.gitDirty = gitDirty; + } + + public String getPortalVersion() { + return portalVersion; + } + + public void setPortalVersion(String portalVersion) { + this.portalVersion = portalVersion; + } + + public String getDbVersion() { + return dbVersion; + } + + public void setDbVersion(String dbVersion) { + this.dbVersion = dbVersion; + } + + public String getDerivedTableVersion() { + return derivedTableVersion; + } + + public void setDerivedTableVersion(String derivedTableVersion) { + this.derivedTableVersion = derivedTableVersion; + } +} diff --git a/src/main/java/org/cbioportal/legacy/model/MolecularAlteration.java b/src/main/java/org/cbioportal/legacy/model/MolecularAlteration.java new file mode 100644 index 00000000000..5c15221e7b6 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/MolecularAlteration.java @@ -0,0 +1,36 @@ +package org.cbioportal.legacy.model; + +import java.io.Serializable; + +public abstract class MolecularAlteration implements Serializable { + + private String values; + private String[] splitValues = null; + + /** + * Set the values for all samples. + * + * @param values: string with list of values, comma (,) separated + */ + public void setValues(String values) { + this.values = values; + } + + /** + * Returns the values attribute split on (,). + * + *

Remembers last .split to avoid repeating this costly operation. + * + * @return list of values for all samples + */ + public String[] getSplitValues() { + if (splitValues == null) { + // Use Integer.MIN_VALUE to return empty string for empty when + // trailing ,,,, + splitValues = values.split(",", Integer.MIN_VALUE); + } + return splitValues; + } + + public abstract String getStableId(); +} diff --git a/src/main/java/org/cbioportal/legacy/model/MolecularData.java b/src/main/java/org/cbioportal/legacy/model/MolecularData.java new file mode 100644 index 00000000000..cb5768c7adf --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/MolecularData.java @@ -0,0 +1,54 @@ +package org.cbioportal.legacy.model; + +import jakarta.validation.constraints.NotNull; + +public abstract class MolecularData extends UniqueKeyBase { + + @NotNull private String molecularProfileId; + @NotNull private String sampleId; + @NotNull private String patientId; + @NotNull private String studyId; + @NotNull private String value; + + public String getMolecularProfileId() { + return molecularProfileId; + } + + public void setMolecularProfileId(String molecularProfileId) { + this.molecularProfileId = molecularProfileId; + } + + public String getSampleId() { + return sampleId; + } + + public void setSampleId(String sampleId) { + this.sampleId = sampleId; + } + + public abstract String getStableId(); + + public String getPatientId() { + return patientId; + } + + public void setPatientId(String patientId) { + this.patientId = patientId; + } + + public String getStudyId() { + return studyId; + } + + public void setStudyId(String studyId) { + this.studyId = studyId; + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } +} diff --git a/src/main/java/org/cbioportal/legacy/model/MolecularProfile.java b/src/main/java/org/cbioportal/legacy/model/MolecularProfile.java new file mode 100644 index 00000000000..769f55743ca --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/MolecularProfile.java @@ -0,0 +1,165 @@ +package org.cbioportal.legacy.model; + +import jakarta.validation.constraints.NotNull; +import java.io.Serializable; + +public class MolecularProfile implements Serializable { + + // Copied from org.mskcc.cbio.portal.model.GeneticAlterationType, if you alter this, + // don't forget to change the original one too + public enum MolecularAlterationType { + MUTATION_EXTENDED, + // uncalled mutations (mskcc internal) for showing read counts even if + // mutation wasn't called + MUTATION_UNCALLED, + STRUCTURAL_VARIANT, + COPY_NUMBER_ALTERATION, + MICRO_RNA_EXPRESSION, + MRNA_EXPRESSION, + MRNA_EXPRESSION_NORMALS, + RNA_EXPRESSION, + METHYLATION, + METHYLATION_BINARY, + PHOSPHORYLATION, + PROTEIN_LEVEL, + PROTEIN_ARRAY_PROTEIN_LEVEL, + PROTEIN_ARRAY_PHOSPHORYLATION, + GENESET_SCORE, + GENERIC_ASSAY + } + + public enum DataType { + DISCRETE; + } + + public enum ImportType { + DISCRETE_LONG; + } + + private Integer molecularProfileId; + @NotNull private String stableId; + private Integer cancerStudyId; + @NotNull private String cancerStudyIdentifier; + private MolecularAlterationType molecularAlterationType; + private String genericAssayType; + private String datatype; + private String name; + private String description; + private Boolean showProfileInAnalysisTab; + private CancerStudy cancerStudy; + private Float pivotThreshold; + private String sortOrder; + @NotNull private Boolean patientLevel; + + public Integer getMolecularProfileId() { + return molecularProfileId; + } + + public void setMolecularProfileId(Integer molecularProfileId) { + this.molecularProfileId = molecularProfileId; + } + + public String getStableId() { + return stableId; + } + + public void setStableId(String stableId) { + this.stableId = stableId; + } + + public Integer getCancerStudyId() { + return cancerStudyId; + } + + public void setCancerStudyId(Integer cancerStudyId) { + this.cancerStudyId = cancerStudyId; + } + + public String getCancerStudyIdentifier() { + return cancerStudyIdentifier; + } + + public void setCancerStudyIdentifier(String cancerStudyIdentifier) { + this.cancerStudyIdentifier = cancerStudyIdentifier; + } + + public MolecularAlterationType getMolecularAlterationType() { + return molecularAlterationType; + } + + public void setMolecularAlterationType(MolecularAlterationType molecularAlterationType) { + this.molecularAlterationType = molecularAlterationType; + } + + public String getDatatype() { + return datatype; + } + + public void setDatatype(String datatype) { + this.datatype = datatype; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public Boolean getShowProfileInAnalysisTab() { + return showProfileInAnalysisTab; + } + + public void setShowProfileInAnalysisTab(Boolean showProfileInAnalysisTab) { + this.showProfileInAnalysisTab = showProfileInAnalysisTab; + } + + public CancerStudy getCancerStudy() { + return cancerStudy; + } + + public void setCancerStudy(CancerStudy cancerStudy) { + this.cancerStudy = cancerStudy; + } + + public Float getPivotThreshold() { + return this.pivotThreshold; + } + + public void setPivotThreshold(Float pivotThreshold) { + this.pivotThreshold = pivotThreshold; + } + + public String getSortOrder() { + return this.sortOrder; + } + + public void setSortOrder(String sortOrder) { + this.sortOrder = sortOrder; + } + + public String getGenericAssayType() { + return genericAssayType; + } + + public void setGenericAssayType(String genericAssayType) { + this.genericAssayType = genericAssayType; + } + + public Boolean getPatientLevel() { + return patientLevel; + } + + public void setPatientLevel(Boolean patientLevel) { + this.patientLevel = patientLevel; + } +} diff --git a/src/main/java/org/cbioportal/legacy/model/MolecularProfileCaseIdentifier.java b/src/main/java/org/cbioportal/legacy/model/MolecularProfileCaseIdentifier.java new file mode 100644 index 00000000000..766187634f9 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/MolecularProfileCaseIdentifier.java @@ -0,0 +1,67 @@ +package org.cbioportal.legacy.model; + +import jakarta.validation.constraints.NotNull; +import java.io.Serializable; + +public class MolecularProfileCaseIdentifier + implements Serializable, Comparable { + + @NotNull private String molecularProfileId; + @NotNull private String caseId; + + public MolecularProfileCaseIdentifier() {} + + public MolecularProfileCaseIdentifier(String caseId, String molecularProfileId) { + this.molecularProfileId = molecularProfileId; + this.caseId = caseId; + } + + public String getMolecularProfileId() { + return molecularProfileId; + } + + public void setMolecularProfileId(String molecularProfileId) { + this.molecularProfileId = molecularProfileId; + } + + public String getCaseId() { + return caseId; + } + + public void setCaseId(String caseId) { + this.caseId = caseId; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((caseId == null) ? 0 : caseId.hashCode()); + result = prime * result + ((molecularProfileId == null) ? 0 : molecularProfileId.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) return true; + if (obj == null) return false; + if (getClass() != obj.getClass()) return false; + MolecularProfileCaseIdentifier other = (MolecularProfileCaseIdentifier) obj; + if (caseId == null) { + if (other.caseId != null) return false; + } else if (!caseId.equals(other.caseId)) return false; + if (molecularProfileId == null) { + if (other.molecularProfileId != null) return false; + } else if (!molecularProfileId.equals(other.molecularProfileId)) return false; + return true; + } + + @Override + public int compareTo(MolecularProfileCaseIdentifier o) { + if (molecularProfileId.compareTo(o.molecularProfileId) == 0) { + return caseId.compareTo(o.caseId); + } else { + return molecularProfileId.compareTo(o.molecularProfileId); + } + } +} diff --git a/src/main/java/org/cbioportal/legacy/model/MolecularProfileSamples.java b/src/main/java/org/cbioportal/legacy/model/MolecularProfileSamples.java new file mode 100644 index 00000000000..308d02b712b --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/MolecularProfileSamples.java @@ -0,0 +1,45 @@ +package org.cbioportal.legacy.model; + +import java.io.Serializable; + +public class MolecularProfileSamples implements Serializable { + + private String molecularProfileId; + private String commaSeparatedSampleIds; + private String[] splitSampleIds = null; + + public String getMolecularProfileId() { + return molecularProfileId; + } + + public void setMolecularProfileId(String molecularProfileId) { + this.molecularProfileId = molecularProfileId; + } + + public String getCommaSeparatedSampleIds() { + return commaSeparatedSampleIds; + } + + /** + * Set the values for all samples. + * + * @param values: string with list of values, comma (,) separated + */ + public void setCommaSeparatedSampleIds(String commaSeparatedSampleIds) { + this.commaSeparatedSampleIds = commaSeparatedSampleIds; + } + + /** + * Returns the values attribute split on (,). + * + *

Remembers last .split to avoid repeating this costly operation. + * + * @return list of values for all samples + */ + public String[] getSplitSampleIds() { + if (splitSampleIds == null) { + splitSampleIds = commaSeparatedSampleIds.split(","); + } + return splitSampleIds; + } +} diff --git a/src/main/java/org/cbioportal/legacy/model/MrnaPercentile.java b/src/main/java/org/cbioportal/legacy/model/MrnaPercentile.java new file mode 100644 index 00000000000..87509603b25 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/MrnaPercentile.java @@ -0,0 +1,73 @@ +package org.cbioportal.legacy.model; + +import com.fasterxml.jackson.annotation.JsonProperty; +import jakarta.validation.constraints.NotNull; +import java.math.BigDecimal; + +public class MrnaPercentile extends UniqueKeyBase { + + @NotNull private String molecularProfileId; + @NotNull private String sampleId; + @NotNull private String patientId; + @NotNull private String studyId; + @NotNull private Integer entrezGeneId; + @NotNull private BigDecimal percentile; + @NotNull private BigDecimal zScore; + + public String getMolecularProfileId() { + return molecularProfileId; + } + + public void setMolecularProfileId(String molecularProfileId) { + this.molecularProfileId = molecularProfileId; + } + + public String getSampleId() { + return sampleId; + } + + public void setSampleId(String sampleId) { + this.sampleId = sampleId; + } + + public String getPatientId() { + return patientId; + } + + public void setPatientId(String patientId) { + this.patientId = patientId; + } + + public String getStudyId() { + return studyId; + } + + public void setStudyId(String studyId) { + this.studyId = studyId; + } + + public Integer getEntrezGeneId() { + return entrezGeneId; + } + + public void setEntrezGeneId(Integer entrezGeneId) { + this.entrezGeneId = entrezGeneId; + } + + public BigDecimal getPercentile() { + return percentile; + } + + public void setPercentile(BigDecimal percentile) { + this.percentile = percentile; + } + + @JsonProperty("zScore") + public BigDecimal getzScore() { + return zScore; + } + + public void setzScore(BigDecimal zScore) { + this.zScore = zScore; + } +} diff --git a/src/main/java/org/cbioportal/legacy/model/MutSig.java b/src/main/java/org/cbioportal/legacy/model/MutSig.java new file mode 100644 index 00000000000..53aa0932965 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/MutSig.java @@ -0,0 +1,93 @@ +package org.cbioportal.legacy.model; + +import com.fasterxml.jackson.annotation.JsonProperty; +import jakarta.validation.constraints.NotNull; +import java.io.Serializable; +import java.math.BigDecimal; + +public class MutSig implements Serializable { + + private Integer cancerStudyId; + @NotNull private String cancerStudyIdentifier; + @NotNull private Integer entrezGeneId; + @NotNull private String hugoGeneSymbol; + @NotNull private Integer rank; + private Integer numbasescovered; + @NotNull private Integer nummutations; + @NotNull private BigDecimal pValue; + @NotNull private BigDecimal qValue; + + public Integer getCancerStudyId() { + return cancerStudyId; + } + + public void setCancerStudyId(Integer cancerStudyId) { + this.cancerStudyId = cancerStudyId; + } + + public String getCancerStudyIdentifier() { + return cancerStudyIdentifier; + } + + public void setCancerStudyIdentifier(String cancerStudyIdentifier) { + this.cancerStudyIdentifier = cancerStudyIdentifier; + } + + public Integer getEntrezGeneId() { + return entrezGeneId; + } + + public void setEntrezGeneId(Integer entrezGeneId) { + this.entrezGeneId = entrezGeneId; + } + + public String getHugoGeneSymbol() { + return hugoGeneSymbol; + } + + public void setHugoGeneSymbol(String hugoGeneSymbol) { + this.hugoGeneSymbol = hugoGeneSymbol; + } + + public Integer getRank() { + return rank; + } + + public void setRank(Integer rank) { + this.rank = rank; + } + + public Integer getNumbasescovered() { + return numbasescovered; + } + + public void setNumbasescovered(Integer numbasescovered) { + this.numbasescovered = numbasescovered; + } + + public Integer getNummutations() { + return nummutations; + } + + public void setNummutations(Integer nummutations) { + this.nummutations = nummutations; + } + + @JsonProperty("pValue") + public BigDecimal getpValue() { + return pValue; + } + + public void setpValue(BigDecimal pValue) { + this.pValue = pValue; + } + + @JsonProperty("qValue") + public BigDecimal getqValue() { + return qValue; + } + + public void setqValue(BigDecimal qValue) { + this.qValue = qValue; + } +} diff --git a/src/main/java/org/cbioportal/legacy/model/Mutation.java b/src/main/java/org/cbioportal/legacy/model/Mutation.java new file mode 100644 index 00000000000..11c54184cc8 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/Mutation.java @@ -0,0 +1,219 @@ +package org.cbioportal.legacy.model; + +import com.fasterxml.jackson.annotation.JsonRawValue; +import io.swagger.v3.oas.annotations.media.Schema; +import java.io.Serializable; + +public class Mutation extends Alteration implements Serializable { + + private String center; + private String mutationStatus; + private String validationStatus; + private Integer tumorAltCount; + private Integer tumorRefCount; + private Integer normalAltCount; + private Integer normalRefCount; + private String aminoAcidChange; + private String chr; + private Long startPosition; + private Long endPosition; + private String referenceAllele; + private String tumorSeqAllele; + private String proteinChange; + private String mutationType; + private String ncbiBuild; + private String variantType; + private String refseqMrnaId; + private Integer proteinPosStart; + private Integer proteinPosEnd; + private String keyword; + private AlleleSpecificCopyNumber alleleSpecificCopyNumber; + + @JsonRawValue + @Schema(type = "java.util.Map") + private Object annotationJSON; + + public String getCenter() { + return center; + } + + public void setCenter(String center) { + this.center = center; + } + + public String getMutationStatus() { + return mutationStatus; + } + + public void setMutationStatus(String mutationStatus) { + this.mutationStatus = mutationStatus; + } + + public String getValidationStatus() { + return validationStatus; + } + + public void setValidationStatus(String validationStatus) { + this.validationStatus = validationStatus; + } + + public Integer getTumorAltCount() { + return tumorAltCount; + } + + public void setTumorAltCount(Integer tumorAltCount) { + this.tumorAltCount = tumorAltCount; + } + + public Integer getTumorRefCount() { + return tumorRefCount; + } + + public void setTumorRefCount(Integer tumorRefCount) { + this.tumorRefCount = tumorRefCount; + } + + public Integer getNormalAltCount() { + return normalAltCount; + } + + public void setNormalAltCount(Integer normalAltCount) { + this.normalAltCount = normalAltCount; + } + + public Integer getNormalRefCount() { + return normalRefCount; + } + + public void setNormalRefCount(Integer normalRefCount) { + this.normalRefCount = normalRefCount; + } + + public String getAminoAcidChange() { + return aminoAcidChange; + } + + public void setAminoAcidChange(String aminoAcidChange) { + this.aminoAcidChange = aminoAcidChange; + } + + public String getChr() { + return chr; + } + + public void setChr(String chr) { + this.chr = chr; + } + + public Long getStartPosition() { + return startPosition; + } + + public void setStartPosition(Long startPosition) { + this.startPosition = startPosition; + } + + public Long getEndPosition() { + return endPosition; + } + + public void setEndPosition(Long endPosition) { + this.endPosition = endPosition; + } + + public String getReferenceAllele() { + return referenceAllele; + } + + public void setReferenceAllele(String referenceAllele) { + this.referenceAllele = referenceAllele; + } + + public String getTumorSeqAllele() { + return tumorSeqAllele; + } + + public void setTumorSeqAllele(String tumorSeqAllele) { + this.tumorSeqAllele = tumorSeqAllele; + } + + public String getProteinChange() { + return proteinChange; + } + + public void setProteinChange(String proteinChange) { + this.proteinChange = proteinChange; + } + + public String getMutationType() { + return mutationType; + } + + public void setMutationType(String mutationType) { + this.mutationType = mutationType; + } + + public String getNcbiBuild() { + return ncbiBuild; + } + + public void setNcbiBuild(String ncbiBuild) { + this.ncbiBuild = ncbiBuild; + } + + public String getVariantType() { + return variantType; + } + + public void setVariantType(String variantType) { + this.variantType = variantType; + } + + public String getRefseqMrnaId() { + return refseqMrnaId; + } + + public void setRefseqMrnaId(String refseqMrnaId) { + this.refseqMrnaId = refseqMrnaId; + } + + public Integer getProteinPosStart() { + return proteinPosStart; + } + + public void setProteinPosStart(Integer proteinPosStart) { + this.proteinPosStart = proteinPosStart; + } + + public Integer getProteinPosEnd() { + return proteinPosEnd; + } + + public void setProteinPosEnd(Integer proteinPosEnd) { + this.proteinPosEnd = proteinPosEnd; + } + + public String getKeyword() { + return keyword; + } + + public void setKeyword(String keyword) { + this.keyword = keyword; + } + + public AlleleSpecificCopyNumber getAlleleSpecificCopyNumber() { + return alleleSpecificCopyNumber; + } + + public void setAlleleSpecificCopyNumber(AlleleSpecificCopyNumber alleleSpecificCopyNumber) { + this.alleleSpecificCopyNumber = alleleSpecificCopyNumber; + } + + public Object getAnnotationJSON() { + return annotationJSON; + } + + public void setAnnotationJSON(String annotationJSON) { + this.annotationJSON = annotationJSON; + } +} diff --git a/src/main/java/org/cbioportal/legacy/model/MutationCountByGene.java b/src/main/java/org/cbioportal/legacy/model/MutationCountByGene.java new file mode 100644 index 00000000000..703585409f9 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/MutationCountByGene.java @@ -0,0 +1,5 @@ +package org.cbioportal.legacy.model; + +import java.io.Serializable; + +public class MutationCountByGene extends AlterationCountByGene implements Serializable {} diff --git a/src/main/java/org/cbioportal/legacy/model/MutationCountByPosition.java b/src/main/java/org/cbioportal/legacy/model/MutationCountByPosition.java new file mode 100644 index 00000000000..96c0009cb2e --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/MutationCountByPosition.java @@ -0,0 +1,44 @@ +package org.cbioportal.legacy.model; + +import jakarta.validation.constraints.NotNull; +import java.io.Serializable; + +public class MutationCountByPosition implements Serializable { + + @NotNull private Integer entrezGeneId; + @NotNull private Integer proteinPosStart; + @NotNull private Integer proteinPosEnd; + @NotNull private Integer count; + + public Integer getEntrezGeneId() { + return entrezGeneId; + } + + public void setEntrezGeneId(Integer entrezGeneId) { + this.entrezGeneId = entrezGeneId; + } + + public Integer getProteinPosStart() { + return proteinPosStart; + } + + public void setProteinPosStart(Integer proteinPosStart) { + this.proteinPosStart = proteinPosStart; + } + + public Integer getProteinPosEnd() { + return proteinPosEnd; + } + + public void setProteinPosEnd(Integer proteinPosEnd) { + this.proteinPosEnd = proteinPosEnd; + } + + public Integer getCount() { + return count; + } + + public void setCount(Integer count) { + this.count = count; + } +} diff --git a/src/main/java/org/cbioportal/legacy/model/MutationEventType.java b/src/main/java/org/cbioportal/legacy/model/MutationEventType.java new file mode 100644 index 00000000000..73fbf8add6f --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/MutationEventType.java @@ -0,0 +1,62 @@ +package org.cbioportal.legacy.model; + +public enum MutationEventType { + missense_mutation("missense_mutation"), + missense("missense"), + missense_variant("missense_variant"), + frame_shift_ins("frame_shift_ins"), + frame_shift_del("frame_shift_del"), + frameshift("frameshift"), + frameshift_deletion("frameshift_deletion"), + frameshift_insertion("frameshift_insertion"), + de_novo_start_outofframe("de_novo_start_outofframe"), + frameshift_variant("frameshift_variant"), + nonsense_mutation("nonsense_mutation"), + nonsense("nonsense"), + stopgain_snv("stopgain_snv"), + stop_gained("stop_gained"), + splice_site("splice_site"), + splice("splice"), + splicing("splicing"), + splice_site_snp("splice_site_snp"), + splice_site_del("splice_site_del"), + splice_site_indel("splice_site_indel"), + splice_region_variant("splice_region_variant"), + splice_region("splice_region"), + translation_start_site("translation_start_site"), + initiator_codon_variant("initiator_codon_variant"), + start_codon_snp("start_codon_snp"), + start_codon_del("start_codon_del"), + nonstop_mutation("nonstop_mutation"), + stop_lost("stop_lost"), + inframe_del("inframe_del"), + inframe_deletion("inframe_deletion"), + in_frame_del("in_frame_del"), + in_frame_deletion("in_frame_deletion"), + inframe_ins("inframe_ins"), + inframe_insertion("inframe_insertion"), + in_frame_ins("in_frame_ins"), + in_frame_insertion("in_frame_insertion"), + indel("indel"), + nonframeshift_deletion("nonframeshift_deletion"), + nonframeshift("nonframeshift"), + nonframeshift_insertion("nonframeshift_insertion"), + targeted_region("targeted_region"), + inframe("inframe"), + truncating("truncating"), + feature_truncation("feature_truncation"), + silent("silent"), + synonymous_variant("synonymous_variant"), + any("any"), + other("other"); + + private final String mutationType; + + MutationEventType(String mutationType) { + this.mutationType = mutationType; + } + + public String getMutationType() { + return mutationType; + } +} diff --git a/src/main/java/org/cbioportal/legacy/model/MutationFilterOption.java b/src/main/java/org/cbioportal/legacy/model/MutationFilterOption.java new file mode 100644 index 00000000000..03729d178df --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/MutationFilterOption.java @@ -0,0 +1,18 @@ +package org.cbioportal.legacy.model; + +public enum MutationFilterOption { + MUTATED("Mutated"), // Samples that have mutations + NOT_MUTATED("Not Mutated"), // Samples that are profiled and not mutated + NOT_PROFILED("Not Profiled"), // Samples that are not profiled + ; + + private final String selectedOption; + + MutationFilterOption(String selectedOption) { + this.selectedOption = selectedOption; + } + + public String getSelectedOption() { + return selectedOption; + } +} diff --git a/src/main/java/org/cbioportal/legacy/model/MutationSpectrum.java b/src/main/java/org/cbioportal/legacy/model/MutationSpectrum.java new file mode 100644 index 00000000000..31f18fa6568 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/MutationSpectrum.java @@ -0,0 +1,97 @@ +package org.cbioportal.legacy.model; + +import jakarta.validation.constraints.NotNull; + +public class MutationSpectrum extends UniqueKeyBase { + + @NotNull private String molecularProfileId; + @NotNull private String sampleId; + @NotNull private String patientId; + @NotNull private String studyId; + @NotNull private Integer ctoA; + @NotNull private Integer ctoG; + @NotNull private Integer ctoT; + @NotNull private Integer ttoA; + @NotNull private Integer ttoC; + @NotNull private Integer ttoG; + + public String getMolecularProfileId() { + return molecularProfileId; + } + + public void setMolecularProfileId(String molecularProfileId) { + this.molecularProfileId = molecularProfileId; + } + + public String getSampleId() { + return sampleId; + } + + public void setSampleId(String sampleId) { + this.sampleId = sampleId; + } + + public String getPatientId() { + return patientId; + } + + public void setPatientId(String patientId) { + this.patientId = patientId; + } + + public String getStudyId() { + return studyId; + } + + public void setStudyId(String studyId) { + this.studyId = studyId; + } + + public Integer getCtoA() { + return ctoA; + } + + public void setCtoA(Integer ctoA) { + this.ctoA = ctoA; + } + + public Integer getCtoG() { + return ctoG; + } + + public void setCtoG(Integer ctoG) { + this.ctoG = ctoG; + } + + public Integer getCtoT() { + return ctoT; + } + + public void setCtoT(Integer ctoT) { + this.ctoT = ctoT; + } + + public Integer getTtoA() { + return ttoA; + } + + public void setTtoA(Integer ttoA) { + this.ttoA = ttoA; + } + + public Integer getTtoC() { + return ttoC; + } + + public void setTtoC(Integer ttoC) { + this.ttoC = ttoC; + } + + public Integer getTtoG() { + return ttoG; + } + + public void setTtoG(Integer ttoG) { + this.ttoG = ttoG; + } +} diff --git a/src/main/java/org/cbioportal/legacy/model/NamespaceAttribute.java b/src/main/java/org/cbioportal/legacy/model/NamespaceAttribute.java new file mode 100644 index 00000000000..6761e7b2660 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/NamespaceAttribute.java @@ -0,0 +1,32 @@ +package org.cbioportal.legacy.model; + +import java.io.Serializable; + +public class NamespaceAttribute implements Serializable { + + private String outerKey; + private String innerKey; + + public NamespaceAttribute() {} + + public NamespaceAttribute(String outerKey, String innerKey) { + this.outerKey = outerKey; + this.innerKey = innerKey; + } + + public String getOuterKey() { + return outerKey; + } + + public void setOuterKey(String outerKey) { + this.outerKey = outerKey; + } + + public String getInnerKey() { + return innerKey; + } + + public void setInnerKey(String innerKey) { + this.innerKey = innerKey; + } +} diff --git a/src/main/java/org/cbioportal/legacy/model/NamespaceAttributeCount.java b/src/main/java/org/cbioportal/legacy/model/NamespaceAttributeCount.java new file mode 100644 index 00000000000..e33dc5ec0e7 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/NamespaceAttributeCount.java @@ -0,0 +1,14 @@ +package org.cbioportal.legacy.model; + +public class NamespaceAttributeCount extends NamespaceAttribute { + + private Integer count; + + public Integer getCount() { + return count; + } + + public void setCount(Integer count) { + this.count = count; + } +} diff --git a/src/main/java/org/cbioportal/legacy/model/NamespaceData.java b/src/main/java/org/cbioportal/legacy/model/NamespaceData.java new file mode 100644 index 00000000000..f5f9b77fb96 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/NamespaceData.java @@ -0,0 +1,61 @@ +package org.cbioportal.legacy.model; + +import jakarta.validation.constraints.NotNull; + +public class NamespaceData extends UniqueKeyBase { + + @NotNull private String outerKey; + @NotNull private String innerKey; + @NotNull private String sampleId; + @NotNull private String studyId; + private String patientId; + private String attrValue; + + public String getOuterKey() { + return outerKey; + } + + public void setOuterKey(String outerKey) { + this.outerKey = outerKey; + } + + public String getInnerKey() { + return innerKey; + } + + public void setInnerKey(String innerKey) { + this.innerKey = innerKey; + } + + public String getSampleId() { + return sampleId; + } + + public void setSampleId(String sampleId) { + this.sampleId = sampleId; + } + + public String getPatientId() { + return patientId; + } + + public void setPatientId(String patientId) { + this.patientId = patientId; + } + + public String getStudyId() { + return studyId; + } + + public void setStudyId(String studyId) { + this.studyId = studyId; + } + + public String getAttrValue() { + return attrValue; + } + + public void setAttrValue(String attrValue) { + this.attrValue = attrValue; + } +} diff --git a/src/main/java/org/cbioportal/legacy/model/NamespaceDataCount.java b/src/main/java/org/cbioportal/legacy/model/NamespaceDataCount.java new file mode 100644 index 00000000000..a9f3220248e --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/NamespaceDataCount.java @@ -0,0 +1,34 @@ +package org.cbioportal.legacy.model; + +import java.io.Serializable; + +public class NamespaceDataCount implements Serializable { + + private String value; + private Integer count; + private Integer totalCount; + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + + public Integer getCount() { + return count; + } + + public void setCount(Integer count) { + this.count = count; + } + + public Integer getTotalCount() { + return totalCount; + } + + public void setTotalCount(Integer totalCount) { + this.totalCount = totalCount; + } +} diff --git a/src/main/java/org/cbioportal/legacy/model/NamespaceDataCountItem.java b/src/main/java/org/cbioportal/legacy/model/NamespaceDataCountItem.java new file mode 100644 index 00000000000..fc3b8e34191 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/NamespaceDataCountItem.java @@ -0,0 +1,16 @@ +package org.cbioportal.legacy.model; + +import java.util.List; + +public class NamespaceDataCountItem extends NamespaceAttribute { + + private List counts; + + public List getCounts() { + return counts; + } + + public void setCounts(List counts) { + this.counts = counts; + } +} diff --git a/src/main/java/org/cbioportal/legacy/model/NumericGeneMolecularData.java b/src/main/java/org/cbioportal/legacy/model/NumericGeneMolecularData.java new file mode 100644 index 00000000000..df9984ce939 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/NumericGeneMolecularData.java @@ -0,0 +1,71 @@ +package org.cbioportal.legacy.model; + +import jakarta.validation.constraints.NotNull; +import java.math.BigDecimal; + +public class NumericGeneMolecularData extends UniqueKeyBase { + + @NotNull private Integer entrezGeneId; + private Gene gene; + @NotNull private String molecularProfileId; + @NotNull private String sampleId; + @NotNull private String patientId; + @NotNull private String studyId; + @NotNull private BigDecimal value; + + public Integer getEntrezGeneId() { + return entrezGeneId; + } + + public void setEntrezGeneId(Integer entrezGeneId) { + this.entrezGeneId = entrezGeneId; + } + + public Gene getGene() { + return gene; + } + + public void setGene(Gene gene) { + this.gene = gene; + } + + public String getMolecularProfileId() { + return molecularProfileId; + } + + public void setMolecularProfileId(String molecularProfileId) { + this.molecularProfileId = molecularProfileId; + } + + public String getSampleId() { + return sampleId; + } + + public void setSampleId(String sampleId) { + this.sampleId = sampleId; + } + + public String getPatientId() { + return patientId; + } + + public void setPatientId(String patientId) { + this.patientId = patientId; + } + + public String getStudyId() { + return studyId; + } + + public void setStudyId(String studyId) { + this.studyId = studyId; + } + + public BigDecimal getValue() { + return value; + } + + public void setValue(BigDecimal value) { + this.value = value; + } +} diff --git a/src/main/java/org/cbioportal/legacy/model/Patient.java b/src/main/java/org/cbioportal/legacy/model/Patient.java new file mode 100644 index 00000000000..2b6a536d9ab --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/Patient.java @@ -0,0 +1,52 @@ +package org.cbioportal.legacy.model; + +import jakarta.validation.constraints.NotNull; + +public class Patient extends UniqueKeyBase { + + private Integer internalId; + @NotNull private String stableId; + private Integer cancerStudyId; + @NotNull private String cancerStudyIdentifier; + private CancerStudy cancerStudy; + + public Integer getInternalId() { + return internalId; + } + + public void setInternalId(Integer internalId) { + this.internalId = internalId; + } + + public String getStableId() { + return stableId; + } + + public void setStableId(String stableId) { + this.stableId = stableId; + } + + public Integer getCancerStudyId() { + return cancerStudyId; + } + + public void setCancerStudyId(Integer cancerStudyId) { + this.cancerStudyId = cancerStudyId; + } + + public String getCancerStudyIdentifier() { + return cancerStudyIdentifier; + } + + public void setCancerStudyIdentifier(String cancerStudyIdentifier) { + this.cancerStudyIdentifier = cancerStudyIdentifier; + } + + public CancerStudy getCancerStudy() { + return cancerStudy; + } + + public void setCancerStudy(CancerStudy cancerStudy) { + this.cancerStudy = cancerStudy; + } +} diff --git a/src/main/java/org/cbioportal/legacy/model/PatientTreatment.java b/src/main/java/org/cbioportal/legacy/model/PatientTreatment.java new file mode 100644 index 00000000000..7b3999a2cbc --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/PatientTreatment.java @@ -0,0 +1,5 @@ +package org.cbioportal.legacy.model; + +import java.io.Serializable; + +public record PatientTreatment(String treatment, int count) implements Serializable {} diff --git a/src/main/java/org/cbioportal/legacy/model/PatientTreatmentReport.java b/src/main/java/org/cbioportal/legacy/model/PatientTreatmentReport.java new file mode 100644 index 00000000000..e60b6a94cb9 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/PatientTreatmentReport.java @@ -0,0 +1,13 @@ +package org.cbioportal.legacy.model; + +import java.io.Serializable; +import java.util.Collections; +import java.util.List; + +public record PatientTreatmentReport( + int totalPatients, int totalSamples, List patientTreatments) + implements Serializable { + public PatientTreatmentReport(int totalPatients, int totalSamples) { + this(totalPatients, totalSamples, Collections.emptyList()); + } +} diff --git a/src/main/java/org/cbioportal/legacy/model/PatientTreatmentRow.java b/src/main/java/org/cbioportal/legacy/model/PatientTreatmentRow.java new file mode 100644 index 00000000000..b398c3df6cb --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/PatientTreatmentRow.java @@ -0,0 +1,64 @@ +package org.cbioportal.legacy.model; + +import java.io.Serializable; +import java.util.Objects; +import java.util.Set; + +public class PatientTreatmentRow implements TreatmentRow, Serializable { + private String treatment; + private int count; + private Set samples; + + public PatientTreatmentRow() {} + + public PatientTreatmentRow(String treatment, int count, Set samples) { + this.treatment = treatment; + this.count = count; + this.samples = samples; + } + + public String getTreatment() { + return treatment; + } + + public void setTreatment(String treatment) { + this.treatment = treatment; + } + + public int getCount() { + return count; + } + + public void setCount(int count) { + this.count = count; + } + + @Override + public Set getSamples() { + return samples; + } + + public void setSamples(Set samples) { + this.samples = samples; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + PatientTreatmentRow that = (PatientTreatmentRow) o; + return getCount() == that.getCount() + && getTreatment().equals(that.getTreatment()) + && Objects.equals(getSamples(), that.getSamples()); + } + + @Override + public int hashCode() { + return Objects.hash(getTreatment(), getCount(), getSamples()); + } + + public void add(SampleTreatmentRow toAdd) { + setCount(getCount() + toAdd.getCount()); + getSamples().addAll(toAdd.getSamples()); + } +} diff --git a/src/main/java/org/cbioportal/legacy/model/QueryElement.java b/src/main/java/org/cbioportal/legacy/model/QueryElement.java new file mode 100644 index 00000000000..2017492eccb --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/QueryElement.java @@ -0,0 +1,15 @@ +package org.cbioportal.legacy.model; + +/* + QueryElement represents three types of behavior for a SQL statement in MyBatis mappers + - INACTIVE: exclude Query element from results + - ACTIVE: include Query element in results + - PASS: do not apply on Query element + Note: the specific behavior the represented by the three states + of QueryElement is determined by the mapper-xml. +*/ +public enum QueryElement { + INACTIVE, + ACTIVE, + PASS +} diff --git a/src/main/java/org/cbioportal/legacy/model/ReadPermission.java b/src/main/java/org/cbioportal/legacy/model/ReadPermission.java new file mode 100644 index 00000000000..2a2202831a8 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/ReadPermission.java @@ -0,0 +1,7 @@ +package org.cbioportal.legacy.model; + +public interface ReadPermission { + public void setReadPermission(Boolean permission); + + public Boolean getReadPermission(); +} diff --git a/src/main/java/org/cbioportal/legacy/model/ReferenceGenome.java b/src/main/java/org/cbioportal/legacy/model/ReferenceGenome.java new file mode 100644 index 00000000000..8cd937917b2 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/ReferenceGenome.java @@ -0,0 +1,189 @@ +/* + * This file is part of cBioPortal. + * + * cBioPortal is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package org.cbioportal.legacy.model; + +import java.util.Date; + +/** + * This represents the reference genome used by molecular profiling + * + * @author Kelsey Zhu + */ +public class ReferenceGenome { + + private int referenceGenomeId; // assigned by DB, auto increment sequence number + private String genomeName; + private String species; + private String buildName; // genome assembly name + private long genomeSize; // non-N bases + private String url; + private Date releaseDate; + public static String HOMO_SAPIENS = "human"; + public static String MUS_MUSCULUS = "mouse"; + public static String HOMO_SAPIENS_DEFAULT_GENOME_BUILD = "GRCh37"; + public static String HOMO_SAPIENS_DEFAULT_GENOME_NAME = "hg19"; + public static String MUS_MUSCULUS_DEFAULT_GENOME_BUILD = "GRCm38"; + public static String HOMO_SAPIENS_DEFAULT_GENOME_BUILD_PREFIX = "GRCh"; + public static String MUS_MUSCULUS_DEFAULT_GENOME_BUILD_PREFIX = "GRCm"; + + /** + * Constructor. + * + * @param genomeName Name of the reference genome. + * @param species Species of the reference genome. + * @param buildName Name of genome assembly + */ + public ReferenceGenome(String genomeName, String species, String buildName) { + super(); + this.genomeName = genomeName; + this.species = species; + this.buildName = buildName; + } + + /** + * Constructor. + * + * @param genomeName Name of the reference genome. + * @param species Species of the reference genome. + * @param buildName Name of genome assembly + * @param genomeSize Effective genome size + * @param url URL to download reference genome + * @param releaseDate Date genome assembly released + */ + public ReferenceGenome( + String genomeName, + String species, + String buildName, + Long genomeSize, + String url, + Date releaseDate) { + super(); + this.genomeName = genomeName; + this.species = species; + this.buildName = buildName; + this.genomeSize = genomeSize; + this.url = url; + this.releaseDate = releaseDate; + } + + public void setReferenceGenomeId(int referenceGenomeId) { + this.referenceGenomeId = referenceGenomeId; + } + + public int getReferenceGenomeId() { + return referenceGenomeId; + } + + public void setGenomeName(String genomeName) { + this.genomeName = genomeName; + } + + public String getGenomeName() { + return this.genomeName; + } + + public void setSpecies(String species) { + this.species = species; + } + + public String getSpecies() { + return this.species; + } + + public void setBuildName(String buildName) { + this.buildName = buildName; + } + + public String getBuildName() { + return this.buildName; + } + + public void setGenomeSize(long genomeSize) { + this.genomeSize = genomeSize; + } + + public long getGenomeSize() { + return this.genomeSize; + } + + public void setUrl(String url) { + this.url = url; + } + + public String getUrl() { + return this.url; + } + + public void setReleaseDate(Date releaseDate) { + this.releaseDate = releaseDate; + } + + public Date getReleaseDate() { + return this.releaseDate; + } + + /** + * Equals. + * + * @param otherReferenceGenome Other Reference Genome. + * @return true of false. + */ + @Override + public boolean equals(Object otherReferenceGenome) { + if (this == otherReferenceGenome) { + return true; + } + + if (!(otherReferenceGenome instanceof ReferenceGenome)) { + return false; + } + + ReferenceGenome that = (ReferenceGenome) otherReferenceGenome; + return (this.genomeName).equals(that.genomeName) + && (this.species).equals(that.species) + && (this.buildName).equals(that.buildName); + } + + @Override + public int hashCode() { + int result = 3; + result = 31 * result + this.referenceGenomeId; + result = 31 * result + (this.genomeName != null ? this.genomeName.hashCode() : 0); + result = 31 * result + (this.buildName != null ? this.buildName.hashCode() : 0); + result = 31 * result + (this.species != null ? this.species.hashCode() : 0); + return result; + } + + /** + * toString() Override. + * + * @return string summary of reference genome + */ + @Override + public String toString() { + return "Reference Genome [referenceGenomeID=" + + referenceGenomeId + + ", genomeName=" + + genomeName + + ", species=" + + species + + ", buildName=" + + buildName + + "]"; + } +} diff --git a/src/main/java/org/cbioportal/legacy/model/ReferenceGenomeGene.java b/src/main/java/org/cbioportal/legacy/model/ReferenceGenomeGene.java new file mode 100644 index 00000000000..db5d1ea53f3 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/ReferenceGenomeGene.java @@ -0,0 +1,92 @@ +/* + * This file is part of cBioPortal. + * + * cBioPortal is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package org.cbioportal.legacy.model; + +import jakarta.validation.constraints.NotNull; +import java.io.Serializable; + +/** + * Class to wrap Reference Genome Gene. + * + * @author Kelsey Zhu + */ +public class ReferenceGenomeGene implements Serializable { + @NotNull private Integer referenceGenomeId; + @NotNull private Integer entrezGeneId; + private String hugoGeneSymbol; + private String chromosome; + private String cytoband; + private Long start; + private Long end; + + public void setReferenceGenomeId(Integer referenceGenomeId) { + this.referenceGenomeId = referenceGenomeId; + } + + public Integer getReferenceGenomeId() { + return referenceGenomeId; + } + + public Integer getEntrezGeneId() { + return entrezGeneId; + } + + public void setEntrezGeneId(Integer entrezGeneId) { + this.entrezGeneId = entrezGeneId; + } + + public String getHugoGeneSymbol() { + return hugoGeneSymbol; + } + + public void setHugoGeneSymbol(String hugoGeneSymbol) { + this.hugoGeneSymbol = hugoGeneSymbol; + } + + public String getChromosome() { + return chromosome; + } + + public void setChromosome(String chromosome) { + this.chromosome = chromosome; + } + + public String getCytoband() { + return cytoband; + } + + public void setCytoband(String cytoband) { + this.cytoband = cytoband; + } + + public Long getStart() { + return this.start; + } + + public void setStart(Long start) { + this.start = start; + } + + public Long getEnd() { + return this.end; + } + + public void setEnd(Long end) { + this.end = end; + } +} diff --git a/src/main/java/org/cbioportal/legacy/model/ResourceData.java b/src/main/java/org/cbioportal/legacy/model/ResourceData.java new file mode 100644 index 00000000000..447c5146663 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/ResourceData.java @@ -0,0 +1,62 @@ +package org.cbioportal.legacy.model; + +import jakarta.validation.constraints.NotNull; +import java.io.Serializable; + +public class ResourceData extends UniqueKeyBase implements Serializable { + + private String sampleId; + private String patientId; + @NotNull private String studyId; + @NotNull private String resourceId; + @NotNull private String url; + private ResourceDefinition resourceDefinition; + + public String getSampleId() { + return sampleId; + } + + public void setSampleId(String sampleId) { + this.sampleId = sampleId; + } + + public String getPatientId() { + return patientId; + } + + public void setPatientId(String patientId) { + this.patientId = patientId; + } + + public String getStudyId() { + return studyId; + } + + public void setStudyId(String studyId) { + this.studyId = studyId; + } + + public String getResourceId() { + return resourceId; + } + + public void setResourceId(String resourceId) { + this.resourceId = resourceId; + } + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + + public ResourceDefinition getResourceDefinition() { + return resourceDefinition; + } + + public void setResourceDefinition(ResourceDefinition resourceDefinition) { + this.resourceDefinition = resourceDefinition; + } +} diff --git a/src/main/java/org/cbioportal/legacy/model/ResourceDefinition.java b/src/main/java/org/cbioportal/legacy/model/ResourceDefinition.java new file mode 100644 index 00000000000..a4860738921 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/ResourceDefinition.java @@ -0,0 +1,80 @@ +package org.cbioportal.legacy.model; + +import jakarta.validation.constraints.NotNull; +import java.io.Serializable; + +public class ResourceDefinition implements Serializable { + + @NotNull private String resourceId; + @NotNull private String displayName; + private String description; + @NotNull private ResourceType resourceType; + private String priority; + private Boolean openByDefault; + @NotNull private String cancerStudyIdentifier; + private String customMetaData; + + public String getResourceId() { + return resourceId; + } + + public void setResourceId(String resourceId) { + this.resourceId = resourceId; + } + + public String getDisplayName() { + return displayName; + } + + public void setDisplayName(String displayName) { + this.displayName = displayName; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public ResourceType getResourceType() { + return resourceType; + } + + public void setResourceType(ResourceType resourceType) { + this.resourceType = resourceType; + } + + public String getPriority() { + return priority; + } + + public void setPriority(String priority) { + this.priority = priority; + } + + public Boolean getOpenByDefault() { + return openByDefault; + } + + public void setOpenByDefault(Boolean openByDefault) { + this.openByDefault = openByDefault; + } + + public String getCancerStudyIdentifier() { + return cancerStudyIdentifier; + } + + public void setCancerStudyIdentifier(String cancerStudyIdentifier) { + this.cancerStudyIdentifier = cancerStudyIdentifier; + } + + public String getCustomMetaData() { + return customMetaData; + } + + public void setCustomMetaData(String customMetaData) { + this.customMetaData = customMetaData; + } +} diff --git a/src/main/java/org/cbioportal/legacy/model/ResourceType.java b/src/main/java/org/cbioportal/legacy/model/ResourceType.java new file mode 100644 index 00000000000..b660bf14542 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/ResourceType.java @@ -0,0 +1,7 @@ +package org.cbioportal.legacy.model; + +public enum ResourceType { + STUDY, + SAMPLE, + PATIENT +} diff --git a/src/main/java/org/cbioportal/legacy/model/Sample.java b/src/main/java/org/cbioportal/legacy/model/Sample.java new file mode 100644 index 00000000000..c0317f136e8 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/Sample.java @@ -0,0 +1,140 @@ +package org.cbioportal.legacy.model; + +import jakarta.validation.constraints.NotNull; +import java.util.Objects; + +public class Sample extends UniqueKeyBase { + + public enum SampleType { + PRIMARY_SOLID_TUMOR("Primary Solid Tumor"), + RECURRENT_SOLID_TUMOR("Recurrent Solid Tumor"), + PRIMARY_BLOOD_TUMOR("Primary Blood Tumor"), + RECURRENT_BLOOD_TUMOR("Recurrent Blood Tumor"), + METASTATIC("Metastatic"), + BLOOD_NORMAL("Blood Derived Normal"), + SOLID_NORMAL("Solid Tissues Normal"); + + private String value; + + SampleType(String value) { + this.value = value; + } + + public String getValue() { + return value; + } + + public static SampleType fromString(String value) { + + if (value != null) { + for (SampleType sampleType : SampleType.values()) { + if (value.equalsIgnoreCase(sampleType.value)) { + return sampleType; + } + } + } + return null; + } + + @Override + public String toString() { + return value; + } + } + + private Integer internalId; + @NotNull private String stableId; + private SampleType sampleType; + private Integer patientId; + @NotNull private String patientStableId; + private Patient patient; + @NotNull private String cancerStudyIdentifier; + private Boolean sequenced; + private Boolean copyNumberSegmentPresent; + + public Integer getInternalId() { + return internalId; + } + + public void setInternalId(Integer internalId) { + this.internalId = internalId; + } + + public String getStableId() { + return stableId; + } + + public void setStableId(String stableId) { + this.stableId = stableId; + } + + public SampleType getSampleType() { + return sampleType; + } + + public void setSampleType(SampleType sampleType) { + this.sampleType = sampleType; + } + + public Integer getPatientId() { + return patientId; + } + + public void setPatientId(Integer patientId) { + this.patientId = patientId; + } + + public String getPatientStableId() { + return patientStableId; + } + + public void setPatientStableId(String patientStableId) { + this.patientStableId = patientStableId; + } + + public Patient getPatient() { + return patient; + } + + public void setPatient(Patient patient) { + this.patient = patient; + } + + public String getCancerStudyIdentifier() { + return cancerStudyIdentifier; + } + + public void setCancerStudyIdentifier(String cancerStudyIdentifier) { + this.cancerStudyIdentifier = cancerStudyIdentifier; + } + + public Boolean getSequenced() { + return sequenced; + } + + public void setSequenced(Boolean sequenced) { + this.sequenced = sequenced; + } + + public Boolean getCopyNumberSegmentPresent() { + return copyNumberSegmentPresent; + } + + public void setCopyNumberSegmentPresent(Boolean copyNumberSegmentPresent) { + this.copyNumberSegmentPresent = copyNumberSegmentPresent; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof Sample)) return false; + Sample sample = (Sample) o; + return getStableId().equals(sample.getStableId()) + && getCancerStudyIdentifier().equals(sample.getCancerStudyIdentifier()); + } + + @Override + public int hashCode() { + return Objects.hash(getStableId(), getCancerStudyIdentifier()); + } +} diff --git a/src/main/java/org/cbioportal/legacy/model/SampleClinicalDataCollection.java b/src/main/java/org/cbioportal/legacy/model/SampleClinicalDataCollection.java new file mode 100644 index 00000000000..d13dac40209 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/SampleClinicalDataCollection.java @@ -0,0 +1,36 @@ +package org.cbioportal.legacy.model; + +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public final class SampleClinicalDataCollection { + + private final Map> byUniqueSampleKey; + + private SampleClinicalDataCollection(Builder builder) { + this.byUniqueSampleKey = Collections.unmodifiableMap(new HashMap<>(builder.byUniqueSampleKey)); + } + + public Map> getByUniqueSampleKey() { + return byUniqueSampleKey; + } + + public static Builder builder() { + return new Builder(); + } + + public static class Builder { + private final Map> byUniqueSampleKey = new HashMap<>(); + + public Builder withByUniqueSampleKey(Map> byUniqueSampleKey) { + this.byUniqueSampleKey.putAll(byUniqueSampleKey); + return this; + } + + public SampleClinicalDataCollection build() { + return new SampleClinicalDataCollection(this); + } + } +} diff --git a/src/main/java/org/cbioportal/legacy/model/SampleList.java b/src/main/java/org/cbioportal/legacy/model/SampleList.java new file mode 100644 index 00000000000..6f713ad8f09 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/SampleList.java @@ -0,0 +1,99 @@ +package org.cbioportal.legacy.model; + +import jakarta.validation.constraints.NotNull; +import java.io.Serializable; +import java.util.List; + +public class SampleList implements Serializable { + + private Integer listId; + @NotNull private String stableId; + private String category; + private Integer cancerStudyId; + private String cancerStudyIdentifier; + private CancerStudy cancerStudy; + private String name; + private String description; + private Integer sampleCount; + private List sampleIds; + + public Integer getListId() { + return listId; + } + + public void setListId(Integer listId) { + this.listId = listId; + } + + public String getStableId() { + return stableId; + } + + public void setStableId(String stableId) { + this.stableId = stableId; + } + + public String getCategory() { + return category; + } + + public void setCategory(String category) { + this.category = category; + } + + public Integer getCancerStudyId() { + return cancerStudyId; + } + + public void setCancerStudyId(Integer cancerStudyId) { + this.cancerStudyId = cancerStudyId; + } + + public String getCancerStudyIdentifier() { + return cancerStudyIdentifier; + } + + public void setCancerStudyIdentifier(String cancerStudyIdentifier) { + this.cancerStudyIdentifier = cancerStudyIdentifier; + } + + public CancerStudy getCancerStudy() { + return cancerStudy; + } + + public void setCancerStudy(CancerStudy cancerStudy) { + this.cancerStudy = cancerStudy; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public Integer getSampleCount() { + return sampleCount; + } + + public void setSampleCount(Integer sampleCount) { + this.sampleCount = sampleCount; + } + + public List getSampleIds() { + return sampleIds; + } + + public void setSampleIds(List sampleIds) { + this.sampleIds = sampleIds; + } +} diff --git a/src/main/java/org/cbioportal/legacy/model/SampleListToSampleId.java b/src/main/java/org/cbioportal/legacy/model/SampleListToSampleId.java new file mode 100644 index 00000000000..d1656921336 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/SampleListToSampleId.java @@ -0,0 +1,26 @@ +package org.cbioportal.legacy.model; + +import jakarta.validation.constraints.NotNull; +import java.io.Serializable; + +public class SampleListToSampleId implements Serializable { + + private Integer sampleListId; + @NotNull private String sampleId; + + public Integer getSampleListId() { + return sampleListId; + } + + public void setSampleListId(Integer sampleListId) { + this.sampleListId = sampleListId; + } + + public String getSampleId() { + return sampleId; + } + + public void setSampleId(String sampleId) { + this.sampleId = sampleId; + } +} diff --git a/src/main/java/org/cbioportal/legacy/model/SampleTreatment.java b/src/main/java/org/cbioportal/legacy/model/SampleTreatment.java new file mode 100644 index 00000000000..799318e20b3 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/SampleTreatment.java @@ -0,0 +1,3 @@ +package org.cbioportal.legacy.model; + +public record SampleTreatment(String treatment, int preSampleCount, int postSampleCount) {} diff --git a/src/main/java/org/cbioportal/legacy/model/SampleTreatmentReport.java b/src/main/java/org/cbioportal/legacy/model/SampleTreatmentReport.java new file mode 100644 index 00000000000..9cc1b858061 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/SampleTreatmentReport.java @@ -0,0 +1,7 @@ +package org.cbioportal.legacy.model; + +import java.io.Serializable; +import java.util.Collection; + +public record SampleTreatmentReport(int totalSamples, Collection treatments) + implements Serializable {} diff --git a/src/main/java/org/cbioportal/legacy/model/SampleTreatmentRow.java b/src/main/java/org/cbioportal/legacy/model/SampleTreatmentRow.java new file mode 100644 index 00000000000..78a0d649134 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/SampleTreatmentRow.java @@ -0,0 +1,80 @@ +package org.cbioportal.legacy.model; + +import java.io.Serializable; +import java.util.Objects; +import java.util.Set; + +public class SampleTreatmentRow implements TreatmentRow, Serializable { + private TemporalRelation time; + private String treatment; + private int count; + private Set samples; + + public SampleTreatmentRow() {} + + public SampleTreatmentRow( + TemporalRelation time, String treatment, int count, Set samples) { + this.time = time; + this.treatment = treatment; + this.count = count; + this.samples = samples; + } + + public TemporalRelation getTime() { + return time; + } + + public void setTime(TemporalRelation time) { + this.time = time; + } + + public String getTreatment() { + return treatment; + } + + public void setTreatment(String treatment) { + this.treatment = treatment; + } + + public int getCount() { + return count; + } + + public void setCount(int count) { + this.count = count; + } + + @Override + public Set getSamples() { + return samples; + } + + public void setSamples(Set samples) { + this.samples = samples; + } + + public String key() { + return getTreatment() + getTime().name(); + } + + public void add(SampleTreatmentRow toAdd) { + getSamples().addAll(toAdd.getSamples()); + setCount(getSamples().size()); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + SampleTreatmentRow that = (SampleTreatmentRow) o; + return getCount() == that.getCount() + && getTime() == that.getTime() + && getTreatment().equals(that.getTreatment()) + && Objects.equals(getSamples(), that.getSamples()); + } + + @Override + public int hashCode() { + return Objects.hash(getTime(), getTreatment(), getCount(), getSamples()); + } +} diff --git a/src/main/java/org/cbioportal/legacy/model/StructuralVariant.java b/src/main/java/org/cbioportal/legacy/model/StructuralVariant.java new file mode 100644 index 00000000000..1b15a4064be --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/StructuralVariant.java @@ -0,0 +1,458 @@ +/* + * Copyright (c) 2018 - 2022 The Hyve B.V. + * This code is licensed under the GNU Affero General Public License (AGPL), + * version 3, or (at your option) any later version. + */ + +/* + * This file is part of cBioPortal. + * + * cBioPortal is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package org.cbioportal.legacy.model; + +import com.fasterxml.jackson.annotation.*; +import io.swagger.v3.oas.annotations.media.Schema; +import java.io.Serializable; + +public class StructuralVariant extends UniqueKeyBase implements Serializable { + + private String molecularProfileId; + private String sampleId; + private String patientId; + private String studyId; + private Integer site1EntrezGeneId; + private String site1HugoSymbol; + private String site1EnsemblTranscriptId; + private String site1Chromosome; + private Integer site1Position; + private String site1Contig; + private String site1Region; + private Integer site1RegionNumber; + private String site1Description; + private Integer site2EntrezGeneId; + private String site2HugoSymbol; + private String site2EnsemblTranscriptId; + private String site2Chromosome; + private Integer site2Position; + private String site2Contig; + private String site2Region; + private Integer site2RegionNumber; + private String site2Description; + private String site2EffectOnFrame; + private String ncbiBuild; + private String dnaSupport; + private String rnaSupport; + private Integer normalReadCount; + private Integer tumorReadCount; + private Integer normalVariantCount; + private Integer tumorVariantCount; + private Integer normalPairedEndReadCount; + private Integer tumorPairedEndReadCount; + private Integer normalSplitReadCount; + private Integer tumorSplitReadCount; + private String annotation; + private String breakpointType; + private String connectionType; + private String eventInfo; + private String variantClass; + private Integer length; + private String comments; + private String driverFilter; + private String driverFilterAnn; + private String driverTiersFilter; + private String driverTiersFilterAnn; + private String svStatus; + + @JsonRawValue + @Schema(type = "java.util.Map") + private Object annotationJson; + + public String getMolecularProfileId() { + return molecularProfileId; + } + + public void setMolecularProfileId(String molecularProfileId) { + this.molecularProfileId = molecularProfileId; + } + + public String getSampleId() { + return sampleId; + } + + public void setSampleId(String tumorSampleBarcode) { + this.sampleId = tumorSampleBarcode; + } + + public String getPatientId() { + return patientId; + } + + public void setPatientId(String patientId) { + this.patientId = patientId; + } + + public String getStudyId() { + return studyId; + } + + public void setStudyId(String studyId) { + this.studyId = studyId; + } + + public Integer getSite1EntrezGeneId() { + return site1EntrezGeneId; + } + + public void setSite1EntrezGeneId(Integer site1EntrezGeneId) { + this.site1EntrezGeneId = site1EntrezGeneId; + } + + public String getSite1HugoSymbol() { + return site1HugoSymbol; + } + + public void setSite1HugoSymbol(String site1HugoSymbol) { + this.site1HugoSymbol = site1HugoSymbol; + } + + public String getSite1EnsemblTranscriptId() { + return site1EnsemblTranscriptId; + } + + public void setSite1EnsemblTranscriptId(String site1TranscriptId) { + this.site1EnsemblTranscriptId = site1TranscriptId; + } + + public String getSite1Chromosome() { + return site1Chromosome; + } + + public void setSite1Chromosome(String site1Chrom) { + this.site1Chromosome = site1Chrom; + } + + public Integer getSite1Position() { + return site1Position; + } + + public void setSite1Position(Integer site1Pos) { + this.site1Position = site1Pos; + } + + public String getSite1Description() { + return site1Description; + } + + public void setSite1Description(String site1Desc) { + this.site1Description = site1Desc; + } + + public Integer getSite2EntrezGeneId() { + return site2EntrezGeneId; + } + + public void setSite2EntrezGeneId(Integer site2EntrezGeneId) { + this.site2EntrezGeneId = site2EntrezGeneId; + } + + public String getSite2HugoSymbol() { + return site2HugoSymbol; + } + + public void setSite2HugoSymbol(String site2HugoSymbol) { + this.site2HugoSymbol = site2HugoSymbol; + } + + public String getSite2EnsemblTranscriptId() { + return site2EnsemblTranscriptId; + } + + public void setSite2EnsemblTranscriptId(String site2TranscriptId) { + this.site2EnsemblTranscriptId = site2TranscriptId; + } + + public String getSite2Chromosome() { + return site2Chromosome; + } + + public void setSite2Chromosome(String site2Chrom) { + this.site2Chromosome = site2Chrom; + } + + public Integer getSite2Position() { + return site2Position; + } + + public void setSite2Position(Integer site2Pos) { + this.site2Position = site2Pos; + } + + public String getSite2Description() { + return site2Description; + } + + public void setSite2Description(String site2Desc) { + this.site2Description = site2Desc; + } + + public String getSite2EffectOnFrame() { + return site2EffectOnFrame; + } + + public void setSite2EffectOnFrame(String site2EffectOnFrame) { + this.site2EffectOnFrame = site2EffectOnFrame; + } + + public String getNcbiBuild() { + return ncbiBuild; + } + + public void setNcbiBuild(String ncbiBuild) { + this.ncbiBuild = ncbiBuild; + } + + public String getDnaSupport() { + return dnaSupport; + } + + public void setDnaSupport(String dnaSupport) { + this.dnaSupport = dnaSupport; + } + + public String getRnaSupport() { + return rnaSupport; + } + + public void setRnaSupport(String rnaSupport) { + this.rnaSupport = rnaSupport; + } + + public Integer getNormalReadCount() { + return normalReadCount; + } + + public void setNormalReadCount(Integer normalReadCount) { + this.normalReadCount = normalReadCount; + } + + public Integer getTumorReadCount() { + return tumorReadCount; + } + + public void setTumorReadCount(Integer tumorReadCount) { + this.tumorReadCount = tumorReadCount; + } + + public Integer getNormalVariantCount() { + return normalVariantCount; + } + + public void setNormalVariantCount(Integer normalVariantCount) { + this.normalVariantCount = normalVariantCount; + } + + public Integer getTumorVariantCount() { + return tumorVariantCount; + } + + public void setTumorVariantCount(Integer tumorVariantCount) { + this.tumorVariantCount = tumorVariantCount; + } + + public Integer getNormalPairedEndReadCount() { + return normalPairedEndReadCount; + } + + public void setNormalPairedEndReadCount(Integer normalPairedEndReadCount) { + this.normalPairedEndReadCount = normalPairedEndReadCount; + } + + public Integer getTumorPairedEndReadCount() { + return tumorPairedEndReadCount; + } + + public void setTumorPairedEndReadCount(Integer tumorPairedEndReadCount) { + this.tumorPairedEndReadCount = tumorPairedEndReadCount; + } + + public Integer getNormalSplitReadCount() { + return normalSplitReadCount; + } + + public void setNormalSplitReadCount(Integer normalSplitReadCount) { + this.normalSplitReadCount = normalSplitReadCount; + } + + public Integer getTumorSplitReadCount() { + return tumorSplitReadCount; + } + + public void setTumorSplitReadCount(Integer tumorSplitReadCount) { + this.tumorSplitReadCount = tumorSplitReadCount; + } + + public String getAnnotation() { + return annotation; + } + + public void setAnnotation(String annotation) { + this.annotation = annotation; + } + + public String getBreakpointType() { + return breakpointType; + } + + public void setBreakpointType(String breakpointType) { + this.breakpointType = breakpointType; + } + + public String getConnectionType() { + return connectionType; + } + + public void setConnectionType(String connectionType) { + this.connectionType = connectionType; + } + + public String getEventInfo() { + return eventInfo; + } + + public void setEventInfo(String eventInfo) { + this.eventInfo = eventInfo; + } + + public String getVariantClass() { + return variantClass; + } + + public void setVariantClass(String variantClass) { + this.variantClass = variantClass; + } + + public Integer getLength() { + return length; + } + + public void setLength(Integer length) { + this.length = length; + } + + public String getComments() { + return comments; + } + + public void setComments(String comments) { + this.comments = comments; + } + + public String getDriverFilter() { + return driverFilter; + } + + public void setDriverFilter(String driverFilter) { + this.driverFilter = driverFilter; + } + + public String getDriverFilterAnn() { + return driverFilterAnn; + } + + public void setDriverFilterAnn(String driverFilterAnn) { + this.driverFilterAnn = driverFilterAnn; + } + + public String getDriverTiersFilter() { + return driverTiersFilter; + } + + public void setDriverTiersFilter(String driverTiersFilter) { + this.driverTiersFilter = driverTiersFilter; + } + + public String getDriverTiersFilterAnn() { + return driverTiersFilterAnn; + } + + public void setDriverTiersFilterAnn(String driverTiersFilterAnn) { + this.driverTiersFilterAnn = driverTiersFilterAnn; + } + + public String getSvStatus() { + return svStatus; + } + + public void setSvStatus(String svStatus) { + this.svStatus = svStatus; + } + + public String getSite1Contig() { + return site1Contig; + } + + public void setSite1Contig(String site1Contig) { + this.site1Contig = site1Contig; + } + + public String getSite1Region() { + return site1Region; + } + + public void setSite1Region(String site1Region) { + this.site1Region = site1Region; + } + + public Integer getSite1RegionNumber() { + return site1RegionNumber; + } + + public void setSite1RegionNumber(Integer site1RegionNumber) { + this.site1RegionNumber = site1RegionNumber; + } + + public String getSite2Contig() { + return site2Contig; + } + + public void setSite2Contig(String site2Contig) { + this.site2Contig = site2Contig; + } + + public String getSite2Region() { + return site2Region; + } + + public void setSite2Region(String site2Region) { + this.site2Region = site2Region; + } + + public Integer getSite2RegionNumber() { + return site2RegionNumber; + } + + public void setSite2RegionNumber(Integer site2RegionNumber) { + this.site2RegionNumber = site2RegionNumber; + } + + public Object getAnnotationJson() { + return annotationJson; + } + + public void setAnnotationJson(String annotationJson) { + this.annotationJson = annotationJson; + } +} diff --git a/src/main/java/org/cbioportal/legacy/model/StructuralVariantFilterQuery.java b/src/main/java/org/cbioportal/legacy/model/StructuralVariantFilterQuery.java new file mode 100644 index 00000000000..3ba61eab458 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/StructuralVariantFilterQuery.java @@ -0,0 +1,55 @@ +package org.cbioportal.legacy.model; + +import java.io.Serializable; +import org.cbioportal.legacy.model.util.Select; +import org.springframework.lang.Nullable; + +public class StructuralVariantFilterQuery extends BaseAlterationFilter implements Serializable { + + private StructuralVariantGeneSubQuery gene1Query; + private StructuralVariantGeneSubQuery gene2Query; + + public StructuralVariantFilterQuery() {} + + public StructuralVariantFilterQuery( + String gene1HugoSymbol, + @Nullable Integer gene1EntrezId, + String gene2HugoSymbol, + @Nullable Integer gene2EntrezId, + boolean includeDriver, + boolean includeVUS, + boolean includeUnknownOncogenicity, + Select tiersSelect, + boolean includeUnknownTier, + boolean includeGermline, + boolean includeSomatic, + boolean includeUnknownStatus) { + super( + includeDriver, + includeVUS, + includeUnknownOncogenicity, + includeGermline, + includeSomatic, + includeUnknownStatus, + tiersSelect, + includeUnknownTier); + this.gene1Query = new StructuralVariantGeneSubQuery(gene1HugoSymbol, gene1EntrezId); + this.gene2Query = new StructuralVariantGeneSubQuery(gene2HugoSymbol, gene2EntrezId); + } + + public StructuralVariantGeneSubQuery getGene1Query() { + return gene1Query; + } + + public void setGene1Query(StructuralVariantGeneSubQuery gene1Query) { + this.gene1Query = gene1Query; + } + + public StructuralVariantGeneSubQuery getGene2Query() { + return gene2Query; + } + + public void setGene2Query(StructuralVariantGeneSubQuery gene2Query) { + this.gene2Query = gene2Query; + } +} diff --git a/src/main/java/org/cbioportal/legacy/model/StructuralVariantGeneSubQuery.java b/src/main/java/org/cbioportal/legacy/model/StructuralVariantGeneSubQuery.java new file mode 100644 index 00000000000..ec0c33556d7 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/StructuralVariantGeneSubQuery.java @@ -0,0 +1,80 @@ +package org.cbioportal.legacy.model; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import jakarta.validation.constraints.AssertTrue; +import java.io.Serializable; +import org.springframework.lang.Nullable; + +public class StructuralVariantGeneSubQuery implements Serializable { + + @Nullable protected String hugoSymbol; + + @Nullable protected Integer entrezId; + + @Nullable protected StructuralVariantSpecialValue specialValue; + + @JsonIgnore + @AssertTrue(message = "Should contain only one EntrezId, hugoSymbol or specialValue.") + public boolean isContainingOnlyOneIdentifierOrSpecialValue() { + int fieldCount = 0; + if (entrezId != null) { + fieldCount++; + } + if (hugoSymbol != null) { + fieldCount++; + } + if (specialValue != null) { + fieldCount++; + } + return fieldCount == 1; + } + + public StructuralVariantGeneSubQuery() {} + + public StructuralVariantGeneSubQuery(String hugoSymbol) { + this.hugoSymbol = hugoSymbol; + } + + public StructuralVariantGeneSubQuery(Integer entrezId) { + this.entrezId = entrezId; + } + + public StructuralVariantGeneSubQuery(StructuralVariantSpecialValue specialValue) { + this.specialValue = specialValue; + } + + public StructuralVariantGeneSubQuery(String hugoSymbol, Integer entrezId) { + this.entrezId = entrezId; + this.hugoSymbol = hugoSymbol; + if (hugoSymbol == null && entrezId == null) { + this.specialValue = StructuralVariantSpecialValue.NO_GENE; + } + } + + @Nullable + public String getHugoSymbol() { + return hugoSymbol; + } + + public void setHugoSymbol(@Nullable String hugoSymbol) { + this.hugoSymbol = hugoSymbol; + } + + @Nullable + public StructuralVariantSpecialValue getSpecialValue() { + return specialValue; + } + + public void setSpecialValue(@Nullable StructuralVariantSpecialValue specialValue) { + this.specialValue = specialValue; + } + + @Nullable + public Integer getEntrezId() { + return entrezId; + } + + public void setEntrezId(@Nullable Integer entrezId) { + this.entrezId = entrezId; + } +} diff --git a/src/main/java/org/cbioportal/legacy/model/StructuralVariantQuery.java b/src/main/java/org/cbioportal/legacy/model/StructuralVariantQuery.java new file mode 100644 index 00000000000..51505736672 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/StructuralVariantQuery.java @@ -0,0 +1,37 @@ +package org.cbioportal.legacy.model; + +import jakarta.validation.Valid; +import java.io.Serializable; + +public class StructuralVariantQuery implements Serializable { + + @Valid private StructuralVariantGeneSubQuery gene1; + + @Valid private StructuralVariantGeneSubQuery gene2; + + public StructuralVariantQuery( + StructuralVariantGeneSubQuery gene1, StructuralVariantGeneSubQuery gene2) { + this.gene1 = gene1; + this.gene2 = gene2; + } + + public StructuralVariantQuery() { + // Needed by jackson + } + + public StructuralVariantGeneSubQuery getGene1() { + return gene1; + } + + public void setGene1(StructuralVariantGeneSubQuery gene1) { + this.gene1 = gene1; + } + + public StructuralVariantGeneSubQuery getGene2() { + return gene2; + } + + public void setGene2(StructuralVariantGeneSubQuery gene2) { + this.gene2 = gene2; + } +} diff --git a/src/main/java/org/cbioportal/legacy/model/StructuralVariantSpecialValue.java b/src/main/java/org/cbioportal/legacy/model/StructuralVariantSpecialValue.java new file mode 100644 index 00000000000..173f8413844 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/StructuralVariantSpecialValue.java @@ -0,0 +1,10 @@ +package org.cbioportal.legacy.model; + +public enum StructuralVariantSpecialValue { + + /** Match any gene */ + ANY_GENE, + + /** Match gene IS NULL */ + NO_GENE; +} diff --git a/src/main/java/org/cbioportal/legacy/model/StudyViewFilterContext.java b/src/main/java/org/cbioportal/legacy/model/StudyViewFilterContext.java new file mode 100644 index 00000000000..0cd91ed24b9 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/StudyViewFilterContext.java @@ -0,0 +1,10 @@ +package org.cbioportal.legacy.model; + +import java.util.List; +import org.cbioportal.legacy.web.parameter.CustomSampleIdentifier; +import org.cbioportal.legacy.web.parameter.StudyViewFilter; + +public record StudyViewFilterContext( + StudyViewFilter studyViewFilter, + List customDataFilterSamples, + List involvedCancerStudies) {} diff --git a/src/main/java/org/cbioportal/legacy/model/StudyViewStructuralVariantFilter.java b/src/main/java/org/cbioportal/legacy/model/StudyViewStructuralVariantFilter.java new file mode 100644 index 00000000000..b3d09422388 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/StudyViewStructuralVariantFilter.java @@ -0,0 +1,69 @@ +package org.cbioportal.legacy.model; + +import jakarta.validation.constraints.AssertTrue; +import java.io.Serializable; +import java.util.List; +import java.util.Set; + +public class StudyViewStructuralVariantFilter implements Serializable { + + private Set molecularProfileIds; + private List> structVarQueries; + + @AssertTrue( + message = + "'specialValue' field of gene1/gene2 StructVarGeneSubQueries cannot be both ANY_GENE or NO_GENE.") + private boolean isGeneQueriesSpecialValueCorrect() { + return structVarQueries.stream() + .flatMap(queryList -> queryList.stream()) + .filter( + structVarFilterQuery -> + structVarFilterQuery.getGene1Query().getSpecialValue() != null + && structVarFilterQuery.getGene2Query().getSpecialValue() != null) + .noneMatch( + structVarFilterQuery -> + structVarFilterQuery.getGene1Query().getSpecialValue() + == structVarFilterQuery.getGene2Query().getSpecialValue()); + } + + @AssertTrue( + message = "'geneId' field of gene1/gene2 StructVarGeneSubQueries cannot be both null.") + private boolean isGeneQueriesGeneIdCorrect() { + return structVarQueries.stream() + .flatMap(queryList -> queryList.stream()) + .noneMatch( + structVarFilterQuery -> + structVarFilterQuery.getGene1Query().getHugoSymbol() == null + && structVarFilterQuery.getGene2Query().getHugoSymbol() == null); + } + + @AssertTrue( + message = + "'geneId' field of gene1/gene2 StructVarGeneSubQueries cannot be null when no specialValue set.") + private boolean isGeneQueriesHasGeneIdWhenSpecialValueNull() { + return structVarQueries.stream() + .flatMap(queryList -> queryList.stream()) + .noneMatch( + structVarFilterQuery -> + (structVarFilterQuery.getGene1Query().getHugoSymbol() == null + && structVarFilterQuery.getGene1Query().getSpecialValue() == null) + || (structVarFilterQuery.getGene2Query().getHugoSymbol() == null + && structVarFilterQuery.getGene2Query().getSpecialValue() == null)); + } + + public Set getMolecularProfileIds() { + return molecularProfileIds; + } + + public void setMolecularProfileIds(Set molecularProfileIds) { + this.molecularProfileIds = molecularProfileIds; + } + + public List> getStructVarQueries() { + return structVarQueries; + } + + public void setStructVarQueries(List> structVarQueries) { + this.structVarQueries = structVarQueries; + } +} diff --git a/src/main/java/org/cbioportal/legacy/model/TableTimestampPair.java b/src/main/java/org/cbioportal/legacy/model/TableTimestampPair.java new file mode 100644 index 00000000000..c091c5e9a67 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/TableTimestampPair.java @@ -0,0 +1,25 @@ +package org.cbioportal.legacy.model; + +import jakarta.validation.constraints.NotNull; +import java.io.Serializable; + +public class TableTimestampPair implements Serializable { + @NotNull private String tableName; + private String updateTime; + + public String getUpdateTime() { + return updateTime; + } + + public void setUpdateTime(String updateTime) { + this.updateTime = updateTime; + } + + public String getTableName() { + return tableName; + } + + public void setTableName(String tableName) { + this.tableName = tableName; + } +} diff --git a/src/main/java/org/cbioportal/legacy/model/TemporalRelation.java b/src/main/java/org/cbioportal/legacy/model/TemporalRelation.java new file mode 100644 index 00000000000..5d4ac85cdab --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/TemporalRelation.java @@ -0,0 +1,6 @@ +package org.cbioportal.legacy.model; + +public enum TemporalRelation { + Pre, + Post +} diff --git a/src/main/java/org/cbioportal/legacy/model/Treatment.java b/src/main/java/org/cbioportal/legacy/model/Treatment.java new file mode 100644 index 00000000000..e3f6bd4c65c --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/Treatment.java @@ -0,0 +1,69 @@ +package org.cbioportal.legacy.model; + +import java.io.Serializable; +import java.util.Objects; + +public class Treatment implements Serializable { + private String treatment; + private String studyId; + private String patientId; + private Integer start; + private Integer stop; + + public String getTreatment() { + return treatment; + } + + public void setTreatment(String treatment) { + this.treatment = treatment; + } + + public String getStudyId() { + return studyId; + } + + public void setStudyId(String studyId) { + this.studyId = studyId; + } + + public String getPatientId() { + return patientId; + } + + public void setPatientId(String patientId) { + this.patientId = patientId; + } + + public Integer getStart() { + return start; + } + + public void setStart(Integer start) { + this.start = start; + } + + public Integer getStop() { + return stop; + } + + public void setStop(Integer stop) { + this.stop = stop; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof Treatment)) return false; + Treatment treatment1 = (Treatment) o; + return getTreatment().equals(treatment1.getTreatment()) + && getStudyId().equals(treatment1.getStudyId()) + && getPatientId().equals(treatment1.getPatientId()) + && Objects.equals(getStart(), treatment1.getStart()) + && Objects.equals(getStop(), treatment1.getStop()); + } + + @Override + public int hashCode() { + return Objects.hash(getTreatment(), getStudyId(), getPatientId(), getStart(), getStop()); + } +} diff --git a/src/main/java/org/cbioportal/legacy/model/TreatmentRow.java b/src/main/java/org/cbioportal/legacy/model/TreatmentRow.java new file mode 100644 index 00000000000..2e020b9a0b4 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/TreatmentRow.java @@ -0,0 +1,7 @@ +package org.cbioportal.legacy.model; + +import java.util.Set; + +public interface TreatmentRow { + public Set getSamples(); +} diff --git a/src/main/java/org/cbioportal/legacy/model/TypeOfCancer.java b/src/main/java/org/cbioportal/legacy/model/TypeOfCancer.java new file mode 100644 index 00000000000..82d7628f72c --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/TypeOfCancer.java @@ -0,0 +1,53 @@ +package org.cbioportal.legacy.model; + +import jakarta.validation.constraints.NotNull; +import java.io.Serializable; + +public class TypeOfCancer implements Serializable { + + @NotNull private String typeOfCancerId; + private String name; + private String dedicatedColor; + private String shortName; + private String parent; + + public String getTypeOfCancerId() { + return typeOfCancerId; + } + + public void setTypeOfCancerId(String typeOfCancerId) { + this.typeOfCancerId = typeOfCancerId; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getDedicatedColor() { + return dedicatedColor; + } + + public void setDedicatedColor(String dedicatedColor) { + this.dedicatedColor = dedicatedColor; + } + + public String getShortName() { + return shortName; + } + + public void setShortName(String shortName) { + this.shortName = shortName; + } + + public String getParent() { + return parent; + } + + public void setParent(String parent) { + this.parent = parent; + } +} diff --git a/src/main/java/org/cbioportal/legacy/model/UniqueKeyBase.java b/src/main/java/org/cbioportal/legacy/model/UniqueKeyBase.java new file mode 100644 index 00000000000..a44d4ffbf3d --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/UniqueKeyBase.java @@ -0,0 +1,25 @@ +package org.cbioportal.legacy.model; + +import java.io.Serializable; + +public abstract class UniqueKeyBase implements Serializable { + + private String uniqueSampleKey; + private String uniquePatientKey; + + public String getUniqueSampleKey() { + return uniqueSampleKey; + } + + public void setUniqueSampleKey(String uniqueSampleKey) { + this.uniqueSampleKey = uniqueSampleKey; + } + + public String getUniquePatientKey() { + return uniquePatientKey; + } + + public void setUniquePatientKey(String uniquePatientKey) { + this.uniquePatientKey = uniquePatientKey; + } +} diff --git a/src/main/java/org/cbioportal/legacy/model/User.java b/src/main/java/org/cbioportal/legacy/model/User.java new file mode 100644 index 00000000000..0c89450633d --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/User.java @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2015 Memorial Sloan-Kettering Cancer Center. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS + * FOR A PARTICULAR PURPOSE. The software and documentation provided hereunder + * is on an "as is" basis, and Memorial Sloan-Kettering Cancer Center has no + * obligations to provide maintenance, support, updates, enhancements or + * modifications. In no event shall Memorial Sloan-Kettering Cancer Center be + * liable to any party for direct, indirect, special, incidental or + * consequential damages, including lost profits, arising out of the use of this + * software and its documentation, even if Memorial Sloan-Kettering Cancer + * Center has been advised of the possibility of such damage. + */ + +/* + * This file is part of cBioPortal. + * + * cBioPortal is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package org.cbioportal.legacy.model; + +import java.io.Serializable; + +/** + * This represents a user, identified by an email address. + * + * @author Arthur Goldberg goldberg@cbio.mskcc.org + * @author Benjamin Gross + */ +public class User implements Serializable { + private String email; + private String name; + private boolean enabled; + + public User(String email, String name, boolean enabled) { + if (null == email) { + throw new IllegalArgumentException("email is null."); + } + this.email = email; + if (null == name) { + throw new IllegalArgumentException("name is null."); + } + this.name = name; + this.enabled = enabled; + } + + public User(String email, String name, Boolean enabled) { + this(email, name, enabled != null ? enabled.booleanValue() : false); + } + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email.toLowerCase(); + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public boolean isEnabled() { + return enabled; + } + + public void setEnabled(boolean enabled) { + this.enabled = enabled; + } + + @Override + public boolean equals(Object otherUser) { + if (this == otherUser) { + return true; + } + + if (!(otherUser instanceof User)) { + return false; + } + + User that = (User) otherUser; + return this.email == that.email && this.name == that.name; + } + + @Override + public int hashCode() { + int hash = 7; + hash = 67 * hash + (this.email != null ? this.email.hashCode() : 0); + hash = 67 * hash + (this.name != null ? this.name.hashCode() : 0); + return hash; + } +} diff --git a/src/main/java/org/cbioportal/legacy/model/UserAuthorities.java b/src/main/java/org/cbioportal/legacy/model/UserAuthorities.java new file mode 100644 index 00000000000..8e2ee7816ec --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/UserAuthorities.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2015 Memorial Sloan-Kettering Cancer Center. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS + * FOR A PARTICULAR PURPOSE. The software and documentation provided hereunder + * is on an "as is" basis, and Memorial Sloan-Kettering Cancer Center has no + * obligations to provide maintenance, support, updates, enhancements or + * modifications. In no event shall Memorial Sloan-Kettering Cancer Center be + * liable to any party for direct, indirect, special, incidental or + * consequential damages, including lost profits, arising out of the use of this + * software and its documentation, even if Memorial Sloan-Kettering Cancer + * Center has been advised of the possibility of such damage. + */ + +/* + * This file is part of cBioPortal. + * + * cBioPortal is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package org.cbioportal.legacy.model; + +// imports +import java.io.Serializable; +import java.util.List; + +/** + * User authorites bean. + * + * @author Benjamin Gross + */ +public class UserAuthorities implements Serializable { + + private String email; + private List authorities; + + public UserAuthorities() {} + + /** Constructor. */ + public UserAuthorities(String email, List authorities) { + this.email = email; + this.authorities = authorities; + } + + // accessors + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email.toLowerCase(); + } + + public List getAuthorities() { + return authorities; + } + + public void setAuthorities(List authorities) { + this.authorities = authorities; + } +} diff --git a/src/main/java/org/cbioportal/legacy/model/VariantCount.java b/src/main/java/org/cbioportal/legacy/model/VariantCount.java new file mode 100644 index 00000000000..545ea993e74 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/VariantCount.java @@ -0,0 +1,62 @@ +package org.cbioportal.legacy.model; + +import jakarta.validation.constraints.NotNull; +import java.io.Serializable; + +public class VariantCount implements Serializable { + + @NotNull private String molecularProfileId; + @NotNull private Integer entrezGeneId; + private String keyword; + @NotNull private Integer numberOfSamples; + @NotNull private Integer numberOfSamplesWithMutationInGene; + @NotNull private Integer numberOfSamplesWithKeyword; + + public String getMolecularProfileId() { + return molecularProfileId; + } + + public void setMolecularProfileId(String molecularProfileId) { + this.molecularProfileId = molecularProfileId; + } + + public Integer getEntrezGeneId() { + return entrezGeneId; + } + + public void setEntrezGeneId(Integer entrezGeneId) { + this.entrezGeneId = entrezGeneId; + } + + public String getKeyword() { + return keyword; + } + + public void setKeyword(String keyword) { + this.keyword = keyword; + } + + public Integer getNumberOfSamples() { + return numberOfSamples; + } + + public void setNumberOfSamples(Integer numberOfSamples) { + this.numberOfSamples = numberOfSamples; + } + + public Integer getNumberOfSamplesWithMutationInGene() { + return numberOfSamplesWithMutationInGene; + } + + public void setNumberOfSamplesWithMutationInGene(Integer numberOfSamplesWithMutationInGene) { + this.numberOfSamplesWithMutationInGene = numberOfSamplesWithMutationInGene; + } + + public Integer getNumberOfSamplesWithKeyword() { + return numberOfSamplesWithKeyword; + } + + public void setNumberOfSamplesWithKeyword(Integer numberOfSamplesWithKeyword) { + this.numberOfSamplesWithKeyword = numberOfSamplesWithKeyword; + } +} diff --git a/src/main/java/org/cbioportal/legacy/model/meta/BaseMeta.java b/src/main/java/org/cbioportal/legacy/model/meta/BaseMeta.java new file mode 100644 index 00000000000..07feb043517 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/meta/BaseMeta.java @@ -0,0 +1,16 @@ +package org.cbioportal.legacy.model.meta; + +import java.io.Serializable; + +public class BaseMeta implements Serializable { + + private Integer totalCount; + + public Integer getTotalCount() { + return totalCount; + } + + public void setTotalCount(Integer totalCount) { + this.totalCount = totalCount; + } +} diff --git a/src/main/java/org/cbioportal/legacy/model/meta/GenericAssayMeta.java b/src/main/java/org/cbioportal/legacy/model/meta/GenericAssayMeta.java new file mode 100644 index 00000000000..095b60d06db --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/meta/GenericAssayMeta.java @@ -0,0 +1,78 @@ +package org.cbioportal.legacy.model.meta; + +import java.io.Serializable; +import java.util.HashMap; + +public class GenericAssayMeta implements Serializable { + + private String stableId; + private String entityType; + private HashMap genericEntityMetaProperties; + + /** + * Create a generic assay meta object from fields + * + * @param entityType Type of the generic assay meta + * @param stableId Stable identifier of the generic assay meta used in the cBioPortal instance + * @param genericEntityMetaProperties generic entity meta properties are the additional + * properties, may differ between different generic assay data + */ + public GenericAssayMeta(String stableId) { + this.stableId = stableId; + } + + public GenericAssayMeta(String entityType, String stableId) { + this.entityType = entityType; + this.stableId = stableId; + this.genericEntityMetaProperties = new HashMap<>(); + } + + public GenericAssayMeta( + String entityType, String stableId, HashMap genericEntityMetaProperties) { + this.entityType = entityType; + this.stableId = stableId; + this.genericEntityMetaProperties = genericEntityMetaProperties; + } + + /** + * @return the stableId + */ + public String getStableId() { + return stableId; + } + + /** + * @param stableId the stableId to set + */ + public void setStableId(String stableId) { + this.stableId = stableId; + } + + /** + * @return the entity type + */ + public String getEntityType() { + return entityType; + } + + /** + * @param entityType the entityType to set + */ + public void setEntityType(String entityType) { + this.entityType = entityType; + } + + /** + * @return the generic entity meta properties + */ + public HashMap getGenericEntityMetaProperties() { + return genericEntityMetaProperties; + } + + /** + * @param genericEntityMetaProperties the genericEntityMetaProperties to set + */ + public void setGenericEntityMetaProperties(HashMap genericEntityMetaProperties) { + this.genericEntityMetaProperties = genericEntityMetaProperties; + } +} diff --git a/src/main/java/org/cbioportal/legacy/model/meta/MutationMeta.java b/src/main/java/org/cbioportal/legacy/model/meta/MutationMeta.java new file mode 100644 index 00000000000..f06030c2e18 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/meta/MutationMeta.java @@ -0,0 +1,14 @@ +package org.cbioportal.legacy.model.meta; + +public class MutationMeta extends BaseMeta { + + private Integer sampleCount; + + public Integer getSampleCount() { + return sampleCount; + } + + public void setSampleCount(Integer sampleCount) { + this.sampleCount = sampleCount; + } +} diff --git a/src/main/java/org/cbioportal/legacy/model/util/QueryElement.java b/src/main/java/org/cbioportal/legacy/model/util/QueryElement.java new file mode 100644 index 00000000000..42c289ab71d --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/util/QueryElement.java @@ -0,0 +1,7 @@ +package org.cbioportal.legacy.model.util; + +public enum QueryElement { + INACTIVE, + ACTIVE, + PASS +} diff --git a/src/main/java/org/cbioportal/legacy/model/util/Select.java b/src/main/java/org/cbioportal/legacy/model/util/Select.java new file mode 100644 index 00000000000..1cadae2721d --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/model/util/Select.java @@ -0,0 +1,88 @@ +package org.cbioportal.legacy.model.util; + +import java.util.*; +import java.util.function.Function; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import java.util.stream.StreamSupport; + +/** + * Used to distinguish selecting all items (no filtering) from select none (filter all). Basically + * it is Iterable that implements the Null Object pattern. + * + * @param + */ +public class Select implements Iterable { + + private final Iterable iterable; + private boolean hasAllExternal = false; + private boolean inverse = false; + + private static final Select ALL = new Select<>(null); + + @SuppressWarnings("unchecked") + public static Select all() { + return (Select) ALL; + } + + private static final Select NONE = new Select<>(Collections.emptyList()); + + @SuppressWarnings("unchecked") + public static Select none() { + return (Select) NONE; + } + + public static Select byValues(Iterable iterable) { + return new Select<>(iterable); + } + + public static Select byValues(Stream stream) { + return stream == null ? all() : new Select<>(stream.collect(Collectors.toList())); + } + + public Select map(Function function) { + if (hasAll()) { + return all(); + } + if (hasNone()) { + return none(); + } + return Select.byValues(StreamSupport.stream(this.spliterator(), false).map(function)); + } + + private Select(Iterable iterable) { + this.iterable = iterable; + } + + public final boolean hasAll() { + return null == iterable || hasAllExternal; + } + + public final boolean hasNone() { + return !hasAllExternal && !hasAll() && !hasValues(); + } + + public final boolean hasValues() { + return null != iterable && iterable.iterator().hasNext(); + } + + public void hasAll(boolean value) { + this.hasAllExternal = value; + } + + public void inverse(boolean inverse) { + this.inverse = inverse; + } + + public boolean inverse() { + return this.inverse; + } + + @Override + public Iterator iterator() { + if (null == iterable) { + throw new UnsupportedOperationException("Iteration over Select.ALL is not defined."); + } + return iterable.iterator(); + } +} diff --git a/src/main/java/org/cbioportal/legacy/persistence/AlterationDriverAnnotationRepository.java b/src/main/java/org/cbioportal/legacy/persistence/AlterationDriverAnnotationRepository.java new file mode 100644 index 00000000000..ac3a310d7e9 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/persistence/AlterationDriverAnnotationRepository.java @@ -0,0 +1,14 @@ +package org.cbioportal.legacy.persistence; + +import java.util.List; +import org.cbioportal.legacy.model.AlterationDriverAnnotation; +import org.springframework.cache.annotation.Cacheable; + +public interface AlterationDriverAnnotationRepository { + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + List getAlterationDriverAnnotations( + List molecularProfileCaseIdentifiers); +} diff --git a/src/main/java/org/cbioportal/legacy/persistence/AlterationRepository.java b/src/main/java/org/cbioportal/legacy/persistence/AlterationRepository.java new file mode 100644 index 00000000000..ccca77f1c9c --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/persistence/AlterationRepository.java @@ -0,0 +1,60 @@ +package org.cbioportal.legacy.persistence; + +import java.util.List; +import java.util.Set; +import org.cbioportal.legacy.model.AlterationCountByGene; +import org.cbioportal.legacy.model.AlterationCountByStructuralVariant; +import org.cbioportal.legacy.model.AlterationFilter; +import org.cbioportal.legacy.model.CopyNumberCountByGene; +import org.cbioportal.legacy.model.MolecularProfileCaseIdentifier; +import org.cbioportal.legacy.model.util.Select; +import org.springframework.cache.annotation.Cacheable; + +public interface AlterationRepository { + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + List getSampleAlterationGeneCounts( + Set molecularProfileCaseIdentifiers, + Select entrezGeneIds, + AlterationFilter alterationFilter); + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + List getPatientAlterationGeneCounts( + Set molecularProfileCaseIdentifiers, + Select entrezGeneIds, + AlterationFilter alterationFilter); + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + List getSampleCnaGeneCounts( + Set molecularProfileCaseIdentifiers, + Select entrezGeneIds, + AlterationFilter alterationFilter); + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + List getPatientCnaGeneCounts( + Set molecularProfileCaseIdentifiers, + Select entrezGeneIds, + AlterationFilter alterationFilter); + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + List getSampleStructuralVariantCounts( + Set molecularProfileCaseIdentifiers, + AlterationFilter alterationFilter); + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + List getPatientStructuralVariantCounts( + Set molecularProfileCaseIdentifiers, + AlterationFilter alterationFilter); +} diff --git a/src/main/java/org/cbioportal/legacy/persistence/CacheEnabledConfig.java b/src/main/java/org/cbioportal/legacy/persistence/CacheEnabledConfig.java new file mode 100644 index 00000000000..cc9d7119064 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/persistence/CacheEnabledConfig.java @@ -0,0 +1,73 @@ +package org.cbioportal.legacy.persistence; + +import jakarta.annotation.PostConstruct; +import java.util.ArrayList; +import java.util.Arrays; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +@Component +public class CacheEnabledConfig { + + private static final Logger LOG = LoggerFactory.getLogger(CacheEnabledConfig.class); + + @Value("${persistence.cache_type:no-cache}") + private String cacheType; + + @Value("${persistence.cache_type_clickhouse:no-cache}") + private String cacheTypeClickhouse; + + private boolean enabled; + private boolean enabledClickhouse; + + public static final String EHCACHE_DISK = "ehcache-disk"; + public static final String EHCACHE_HEAP = "ehcache-heap"; + public static final String EHCACHE_HYBRID = "ehcache-hybrid"; + public static final String REDIS = "redis"; + + public static ArrayList validCacheTypes = + new ArrayList(Arrays.asList(EHCACHE_DISK, EHCACHE_HEAP, EHCACHE_HYBRID, REDIS)); + + @PostConstruct + public void init() { + this.enabled = enableCache(cacheType); + LOG.info("Cache is enabled: " + this.enabled); + this.enabledClickhouse = enableCache(cacheTypeClickhouse); + LOG.info("Cache is enabled for clickhouse: " + this.enabledClickhouse); + } + + public static boolean enableCache(String cacheType) { + for (String validCacheType : validCacheTypes) { + if (validCacheType.equalsIgnoreCase(cacheType)) { + return true; + } + } + return false; + } + + public String getEnabled() { + if (enabled) { + return "true"; + } else { + return "false"; + } + } + + public boolean isEnabled() { + return enabled; + } + + public String getEnabledClickhouse() { + if (enabledClickhouse) { + return "true"; + } else { + return "false"; + } + } + + public boolean isEnabledClickhouse() { + return enabledClickhouse; + } +} diff --git a/src/main/java/org/cbioportal/legacy/persistence/CancerTypeRepository.java b/src/main/java/org/cbioportal/legacy/persistence/CancerTypeRepository.java new file mode 100644 index 00000000000..88c8f1cca85 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/persistence/CancerTypeRepository.java @@ -0,0 +1,25 @@ +package org.cbioportal.legacy.persistence; + +import java.util.List; +import org.cbioportal.legacy.model.TypeOfCancer; +import org.cbioportal.legacy.model.meta.BaseMeta; +import org.springframework.cache.annotation.Cacheable; + +public interface CancerTypeRepository { + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + List getAllCancerTypes( + String projection, Integer pageSize, Integer pageNumber, String sortBy, String direction); + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + BaseMeta getMetaCancerTypes(); + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + TypeOfCancer getCancerType(String cancerTypeId); +} diff --git a/src/main/java/org/cbioportal/legacy/persistence/ClinicalAttributeRepository.java b/src/main/java/org/cbioportal/legacy/persistence/ClinicalAttributeRepository.java new file mode 100644 index 00000000000..03d89f01aa2 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/persistence/ClinicalAttributeRepository.java @@ -0,0 +1,69 @@ +package org.cbioportal.legacy.persistence; + +import java.util.List; +import org.cbioportal.legacy.model.ClinicalAttribute; +import org.cbioportal.legacy.model.ClinicalAttributeCount; +import org.cbioportal.legacy.model.meta.BaseMeta; +import org.springframework.cache.annotation.Cacheable; + +public interface ClinicalAttributeRepository { + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + List getAllClinicalAttributes( + String projection, Integer pageSize, Integer pageNumber, String sortBy, String direction); + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + BaseMeta getMetaClinicalAttributes(); + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + ClinicalAttribute getClinicalAttribute(String studyId, String clinicalAttributeId); + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + List getAllClinicalAttributesInStudy( + String studyId, + String projection, + Integer pageSize, + Integer pageNumber, + String sortBy, + String direction); + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + BaseMeta getMetaClinicalAttributesInStudy(String studyId); + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + List fetchClinicalAttributes(List studyIds, String projection); + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + BaseMeta fetchMetaClinicalAttributes(List studyIds); + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + List getClinicalAttributeCountsBySampleIds( + List studyIds, List sampleIds); + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + List getClinicalAttributeCountsBySampleListId(String sampleListId); + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + List getClinicalAttributesByStudyIdsAndAttributeIds( + List studyIds, List attributeIds); +} diff --git a/src/main/java/org/cbioportal/legacy/persistence/ClinicalDataRepository.java b/src/main/java/org/cbioportal/legacy/persistence/ClinicalDataRepository.java new file mode 100644 index 00000000000..b9e3ab5880b --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/persistence/ClinicalDataRepository.java @@ -0,0 +1,127 @@ +package org.cbioportal.legacy.persistence; + +import java.util.List; +import org.cbioportal.legacy.model.ClinicalData; +import org.cbioportal.legacy.model.ClinicalDataCount; +import org.cbioportal.legacy.model.meta.BaseMeta; +import org.springframework.cache.annotation.Cacheable; + +public interface ClinicalDataRepository { + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + List getAllClinicalDataOfSampleInStudy( + String studyId, + String sampleId, + String attributeId, + String projection, + Integer pageSize, + Integer pageNumber, + String sortBy, + String direction); + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + BaseMeta getMetaSampleClinicalData(String studyId, String sampleId, String attributeId); + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + List getAllClinicalDataOfPatientInStudy( + String studyId, + String patientId, + String attributeId, + String projection, + Integer pageSize, + Integer pageNumber, + String sortBy, + String direction); + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + BaseMeta getMetaPatientClinicalData(String studyId, String patientId, String attributeId); + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + List getAllClinicalDataInStudy( + String studyId, + String attributeId, + String clinicalDataType, + String projection, + Integer pageSize, + Integer pageNumber, + String sortBy, + String direction); + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + BaseMeta getMetaAllClinicalData(String studyId, String attributeId, String clinicalDataType); + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + List fetchAllClinicalDataInStudy( + String studyId, + List ids, + List attributeIds, + String clinicalDataType, + String projection); + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + BaseMeta fetchMetaClinicalDataInStudy( + String studyId, List ids, List attributeIds, String clinicalDataType); + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + List fetchClinicalData( + List studyIds, + List ids, + List attributeIds, + String clinicalDataType, + String projection); + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + BaseMeta fetchMetaClinicalData( + List studyIds, List ids, List attributeIds, String clinicalDataType); + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + List fetchClinicalDataCounts( + List studyIds, + List sampleIds, + List attributeIds, + String clinicalDataType, + String projection); + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + List getPatientClinicalDataDetailedToSample( + List studyIds, List patientIds, List attributeIds); + + List getVisibleSampleInternalIdsForClinicalTable( + List studyIds, + List sampleIds, + Integer pageSize, + Integer pageNumber, + String searchTerm, + String sortBy, + String direction); + + List getSampleClinicalDataBySampleInternalIds( + List visibleSampleInternalIds); + + List getPatientClinicalDataBySampleInternalIds( + List visibleSampleInternalIds); +} diff --git a/src/main/java/org/cbioportal/legacy/persistence/ClinicalEventRepository.java b/src/main/java/org/cbioportal/legacy/persistence/ClinicalEventRepository.java new file mode 100644 index 00000000000..444004c578b --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/persistence/ClinicalEventRepository.java @@ -0,0 +1,74 @@ +package org.cbioportal.legacy.persistence; + +import java.util.List; +import java.util.Map; +import java.util.Set; +import org.cbioportal.legacy.model.ClinicalEvent; +import org.cbioportal.legacy.model.ClinicalEventData; +import org.cbioportal.legacy.model.meta.BaseMeta; +import org.springframework.cache.annotation.Cacheable; + +public interface ClinicalEventRepository { + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + List getAllClinicalEventsOfPatientInStudy( + String studyId, + String patientId, + String projection, + Integer pageSize, + Integer pageNumber, + String sortBy, + String direction); + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + BaseMeta getMetaPatientClinicalEvents(String studyId, String patientId); + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + List getDataOfClinicalEvents(List clinicalEventIds); + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + List getAllClinicalEventsInStudy( + String studyId, + String projection, + Integer pageSize, + Integer pageNumber, + String sortBy, + String direction); + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + BaseMeta getMetaClinicalEvents(String studyId); + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + Map> getSamplesOfPatientsPerEventTypeInStudy( + List studyIds, List sampleIds); + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + List getPatientsDistinctClinicalEventInStudies( + List studyIds, List patientIds); + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + List getTimelineEvents( + List studyIds, List patientIds, List clinicalEvents); + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + List getClinicalEventsMeta( + List studyIds, List patientIds, List clinicalEvents); +} diff --git a/src/main/java/org/cbioportal/legacy/persistence/CopyNumberSegmentRepository.java b/src/main/java/org/cbioportal/legacy/persistence/CopyNumberSegmentRepository.java new file mode 100644 index 00000000000..d8fc7fb2ac4 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/persistence/CopyNumberSegmentRepository.java @@ -0,0 +1,52 @@ +package org.cbioportal.legacy.persistence; + +import java.util.List; +import org.cbioportal.legacy.model.CopyNumberSeg; +import org.cbioportal.legacy.model.meta.BaseMeta; +import org.springframework.cache.annotation.Cacheable; + +public interface CopyNumberSegmentRepository { + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + List getCopyNumberSegmentsInSampleInStudy( + String studyId, + String sampleId, + String chromosome, + String projection, + Integer pageSize, + Integer pageNumber, + String sortBy, + String direction); + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + BaseMeta getMetaCopyNumberSegmentsInSampleInStudy( + String studyId, String sampleId, String chromosome); + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + List fetchSamplesWithCopyNumberSegments( + List studyIds, List sampleIds, String chromosome); + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + List fetchCopyNumberSegments( + List studyIds, List sampleIds, String chromosome, String projection); + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + BaseMeta fetchMetaCopyNumberSegments( + List studyIds, List sampleIds, String chromosome); + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + List getCopyNumberSegmentsBySampleListId( + String studyId, String sampleListId, String chromosome, String projection); +} diff --git a/src/main/java/org/cbioportal/legacy/persistence/CosmicCountRepository.java b/src/main/java/org/cbioportal/legacy/persistence/CosmicCountRepository.java new file mode 100644 index 00000000000..1e6f51ffe78 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/persistence/CosmicCountRepository.java @@ -0,0 +1,13 @@ +package org.cbioportal.legacy.persistence; + +import java.util.List; +import org.cbioportal.legacy.model.CosmicMutation; +import org.springframework.cache.annotation.Cacheable; + +public interface CosmicCountRepository { + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + List fetchCosmicCountsByKeywords(List keywords); +} diff --git a/src/main/java/org/cbioportal/legacy/persistence/DataAccessTokenRepository.java b/src/main/java/org/cbioportal/legacy/persistence/DataAccessTokenRepository.java new file mode 100644 index 00000000000..c6fb98d7957 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/persistence/DataAccessTokenRepository.java @@ -0,0 +1,17 @@ +package org.cbioportal.legacy.persistence; + +import java.util.List; +import org.cbioportal.legacy.model.DataAccessToken; + +public interface DataAccessTokenRepository { + + List getAllDataAccessTokensForUsername(String username); + + DataAccessToken getDataAccessToken(String token); + + void addDataAccessToken(DataAccessToken token); + + void removeDataAccessToken(String token); + + void removeAllDataAccessTokensForUsername(String username); +} diff --git a/src/main/java/org/cbioportal/legacy/persistence/DiscreteCopyNumberRepository.java b/src/main/java/org/cbioportal/legacy/persistence/DiscreteCopyNumberRepository.java new file mode 100644 index 00000000000..d41ca797f24 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/persistence/DiscreteCopyNumberRepository.java @@ -0,0 +1,77 @@ +package org.cbioportal.legacy.persistence; + +import java.util.List; +import org.cbioportal.legacy.model.CopyNumberCountByGene; +import org.cbioportal.legacy.model.DiscreteCopyNumberData; +import org.cbioportal.legacy.model.GeneFilterQuery; +import org.cbioportal.legacy.model.meta.BaseMeta; +import org.springframework.cache.annotation.Cacheable; + +public interface DiscreteCopyNumberRepository { + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + List getDiscreteCopyNumbersInMolecularProfileBySampleListId( + String molecularProfileId, + String sampleListId, + List entrezGeneIds, + List alterationTypes, + String projection); + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + BaseMeta getMetaDiscreteCopyNumbersInMolecularProfileBySampleListId( + String molecularProfileId, + String sampleListId, + List entrezGeneIds, + List alterationTypes); + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + List fetchDiscreteCopyNumbersInMolecularProfile( + String molecularProfileId, + List sampleIds, + List entrezGeneIds, + List alterationTypes, + String projection); + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + List getDiscreteCopyNumbersInMultipleMolecularProfiles( + List molecularProfileIds, + List sampleIds, + List entrezGeneIds, + List alterationTypes, + String projection); + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + List getDiscreteCopyNumbersInMultipleMolecularProfilesByGeneQueries( + List molecularProfileIds, + List sampleIds, + List geneFilterQuery, + String projection); + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + BaseMeta fetchMetaDiscreteCopyNumbersInMolecularProfile( + String molecularProfileId, + List sampleIds, + List entrezGeneIds, + List alterationTypes); + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + List getSampleCountByGeneAndAlterationAndSampleIds( + String molecularProfileId, + List sampleIds, + List entrezGeneIds, + List alterations); +} diff --git a/src/main/java/org/cbioportal/legacy/persistence/GenePanelRepository.java b/src/main/java/org/cbioportal/legacy/persistence/GenePanelRepository.java new file mode 100644 index 00000000000..0cdc38294b1 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/persistence/GenePanelRepository.java @@ -0,0 +1,63 @@ +package org.cbioportal.legacy.persistence; + +import java.util.List; +import java.util.Set; +import org.cbioportal.legacy.model.GenePanel; +import org.cbioportal.legacy.model.GenePanelData; +import org.cbioportal.legacy.model.GenePanelToGene; +import org.cbioportal.legacy.model.MolecularProfileCaseIdentifier; +import org.cbioportal.legacy.model.meta.BaseMeta; +import org.springframework.cache.annotation.Cacheable; + +public interface GenePanelRepository { + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + List getAllGenePanels( + String projection, Integer pageSize, Integer pageNumber, String sortBy, String direction); + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + BaseMeta getMetaGenePanels(); + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + GenePanel getGenePanel(String genePanelId); + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + List fetchGenePanels(List genePanelIds, String projection); + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + List getGenePanelDataBySampleListId( + String molecularProfileId, String sampleListId); + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + List fetchGenePanelData(String molecularProfileId, List sampleIds); + + List fetchGenePanelDataByMolecularProfileIds(Set molecularProfileIds); + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + List fetchGenePanelDataByMolecularProfileId(String molecularProfileId); + + List fetchGenePanelDataInMultipleMolecularProfiles( + List molecularProfileSampleIdentifiers); + + List fetchGenePanelDataInMultipleMolecularProfilesByPatientIds( + List molecularProfileSampleIdentifiers); + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + List getGenesOfPanels(List genePanelIds); +} diff --git a/src/main/java/org/cbioportal/legacy/persistence/GeneRepository.java b/src/main/java/org/cbioportal/legacy/persistence/GeneRepository.java new file mode 100644 index 00000000000..7bbcc2d3878 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/persistence/GeneRepository.java @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2016 - 2019 Memorial Sloan Kettering Cancer Center. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS + * FOR A PARTICULAR PURPOSE. The software and documentation provided hereunder + * is on an "as is" basis, and Memorial Sloan-Kettering Cancer Center has no + * obligations to provide maintenance, support, updates, enhancements or + * modifications. In no event shall Memorial Sloan-Kettering Cancer Center be + * liable to any party for direct, indirect, special, incidental or + * consequential damages, including lost profits, arising out of the use of this + * software and its documentation, even if Memorial Sloan-Kettering Cancer + * Center has been advised of the possibility of such damage. + */ + +/* + * This file is part of cBioPortal. + * + * cBioPortal is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +package org.cbioportal.legacy.persistence; + +import java.util.List; +import org.cbioportal.legacy.model.Gene; +import org.cbioportal.legacy.model.GeneAlias; +import org.cbioportal.legacy.model.meta.BaseMeta; +import org.springframework.cache.annotation.Cacheable; + +public interface GeneRepository { + + @Cacheable( + cacheResolver = "staticRepositoryCacheOneResolver", + condition = "@cacheEnabledConfig.getEnabled()") + List getAllGenes( + String keyword, + String alias, + String projection, + Integer pageSize, + Integer pageNumber, + String sortBy, + String direction); + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + BaseMeta getMetaGenes(String keyword, String alias); + + Gene getGeneByGeneticEntityId(Integer geneticEntityId); + + @Cacheable( + cacheResolver = "staticRepositoryCacheOneResolver", + condition = "@cacheEnabledConfig.getEnabled()") + Gene getGeneByEntrezGeneId(Integer entrezGeneId); + + @Cacheable( + cacheResolver = "staticRepositoryCacheOneResolver", + condition = "@cacheEnabledConfig.getEnabled()") + Gene getGeneByHugoGeneSymbol(String hugoGeneSymbol); + + @Cacheable( + cacheResolver = "staticRepositoryCacheOneResolver", + condition = "@cacheEnabledConfig.getEnabled()") + List getAliasesOfGeneByEntrezGeneId(Integer entrezGeneId); + + @Cacheable( + cacheResolver = "staticRepositoryCacheOneResolver", + condition = "@cacheEnabledConfig.getEnabled()") + List getAliasesOfGeneByHugoGeneSymbol(String hugoGeneSymbol); + + // not cached because this is called only a single time, during @PostConstruct method of + // GeneServiceImpl + List getAllAliases(); + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + List fetchGenesByEntrezGeneIds(List entrezGeneIds, String projection); + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + List fetchGenesByHugoGeneSymbols(List hugoGeneSymbols, String projection); + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + BaseMeta fetchMetaGenesByEntrezGeneIds(List entrezGeneIds); + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + BaseMeta fetchMetaGenesByHugoGeneSymbols(List hugoGeneSymbols); +} diff --git a/src/main/java/org/cbioportal/legacy/persistence/GenericAssayRepository.java b/src/main/java/org/cbioportal/legacy/persistence/GenericAssayRepository.java new file mode 100644 index 00000000000..fa56f17eb59 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/persistence/GenericAssayRepository.java @@ -0,0 +1,24 @@ +package org.cbioportal.legacy.persistence; + +import java.util.List; +import org.cbioportal.legacy.model.GenericAssayAdditionalProperty; +import org.cbioportal.legacy.model.meta.GenericAssayMeta; +import org.springframework.cache.annotation.Cacheable; + +public interface GenericAssayRepository { + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + List getGenericAssayMeta(List stableIds); + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + List getGenericAssayAdditionalproperties(List stableIds); + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + List getGenericAssayStableIdsByMolecularIds(List molecularProfileIds); +} diff --git a/src/main/java/org/cbioportal/legacy/persistence/GenesetHierarchyRepository.java b/src/main/java/org/cbioportal/legacy/persistence/GenesetHierarchyRepository.java new file mode 100644 index 00000000000..b40d34c4fb4 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/persistence/GenesetHierarchyRepository.java @@ -0,0 +1,24 @@ +package org.cbioportal.legacy.persistence; + +import java.util.List; +import org.cbioportal.legacy.model.Geneset; +import org.cbioportal.legacy.model.GenesetHierarchyInfo; +import org.springframework.cache.annotation.Cacheable; + +public interface GenesetHierarchyRepository { + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + List getGenesetHierarchyParents(List genesetIds); + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + List getGenesetHierarchyGenesets(Integer nodeId); + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + List getGenesetHierarchySuperNodes(List genesetIds); +} diff --git a/src/main/java/org/cbioportal/legacy/persistence/GenesetRepository.java b/src/main/java/org/cbioportal/legacy/persistence/GenesetRepository.java new file mode 100644 index 00000000000..46958be247e --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/persistence/GenesetRepository.java @@ -0,0 +1,40 @@ +package org.cbioportal.legacy.persistence; + +import java.util.List; +import org.cbioportal.legacy.model.Gene; +import org.cbioportal.legacy.model.Geneset; +import org.cbioportal.legacy.model.meta.BaseMeta; +import org.springframework.cache.annotation.Cacheable; + +public interface GenesetRepository { + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + List getAllGenesets(String projection, Integer pageSize, Integer pageNumber); + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + BaseMeta getMetaGenesets(); + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + Geneset getGeneset(String genesetId); + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + List fetchGenesets(List genesetIds); + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + List getGenesByGenesetId(String genesetId); + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + String getGenesetVersion(); +} diff --git a/src/main/java/org/cbioportal/legacy/persistence/MolecularDataRepository.java b/src/main/java/org/cbioportal/legacy/persistence/MolecularDataRepository.java new file mode 100644 index 00000000000..7967ec31487 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/persistence/MolecularDataRepository.java @@ -0,0 +1,62 @@ +package org.cbioportal.legacy.persistence; + +import java.util.List; +import java.util.Map; +import java.util.Set; +import org.cbioportal.legacy.model.GeneMolecularAlteration; +import org.cbioportal.legacy.model.GenericAssayMolecularAlteration; +import org.cbioportal.legacy.model.GenesetMolecularAlteration; +import org.cbioportal.legacy.model.MolecularProfileSamples; +import org.springframework.cache.annotation.Cacheable; + +public interface MolecularDataRepository { + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + MolecularProfileSamples getCommaSeparatedSampleIdsOfMolecularProfile(String molecularProfileId); + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + Map commaSeparatedSampleIdsOfMolecularProfilesMap( + Set molecularProfileIds); + + // Not caching when entrezGeneIds is null or empty because the large response size sometimes + // crashes the cache + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = + "@cacheEnabledConfig.getEnabled() && #entrezGeneIds != null && #entrezGeneIds.size() != 0") + List getGeneMolecularAlterations( + String molecularProfileId, List entrezGeneIds, String projection); + + Iterable getGeneMolecularAlterationsIterable( + String molecularProfileId, List entrezGeneIds, String projection); + + // Same as getGeneMolecularAlterationsIterable above, except assumes that + // entrezGeneIds is null or empty AND projection is "SUMMARY" + Iterable getGeneMolecularAlterationsIterableFast( + String molecularProfileId); + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + List getGeneMolecularAlterationsInMultipleMolecularProfiles( + Set molecularProfileIds, List entrezGeneIds, String projection); + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + List getGenesetMolecularAlterations( + String molecularProfileId, List genesetIds, String projection); + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + List getGenericAssayMolecularAlterations( + String molecularProfileId, List stableIds, String projection); + + Iterable getGenericAssayMolecularAlterationsIterable( + String molecularProfileId, List stableIds, String projection); +} diff --git a/src/main/java/org/cbioportal/legacy/persistence/MolecularProfileRepository.java b/src/main/java/org/cbioportal/legacy/persistence/MolecularProfileRepository.java new file mode 100644 index 00000000000..8402961f7eb --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/persistence/MolecularProfileRepository.java @@ -0,0 +1,72 @@ +package org.cbioportal.legacy.persistence; + +import java.util.List; +import java.util.Set; +import org.cbioportal.legacy.model.MolecularProfile; +import org.cbioportal.legacy.model.meta.BaseMeta; +import org.springframework.cache.annotation.Cacheable; + +public interface MolecularProfileRepository { + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + List getAllMolecularProfiles( + String projection, Integer pageSize, Integer pageNumber, String sortBy, String direction); + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + BaseMeta getMetaMolecularProfiles(); + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + MolecularProfile getMolecularProfile(String molecularProfileId); + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + List getMolecularProfiles(Set molecularProfileIds, String projection); + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + BaseMeta getMetaMolecularProfiles(Set molecularProfileIds); + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + List getAllMolecularProfilesInStudy( + String studyId, + String projection, + Integer pageSize, + Integer pageNumber, + String sortBy, + String direction); + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + BaseMeta getMetaMolecularProfilesInStudy(String studyId); + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + List getMolecularProfilesInStudies(List studyIds, String projection); + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + BaseMeta getMetaMolecularProfilesInStudies(List studyIds); + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + List getMolecularProfilesReferredBy(String referringMolecularProfileId); + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + List getMolecularProfilesReferringTo(String referredMolecularProfileId); +} diff --git a/src/main/java/org/cbioportal/legacy/persistence/MutationRepository.java b/src/main/java/org/cbioportal/legacy/persistence/MutationRepository.java new file mode 100644 index 00000000000..f7944d42566 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/persistence/MutationRepository.java @@ -0,0 +1,99 @@ +package org.cbioportal.legacy.persistence; + +import java.util.List; +import org.cbioportal.legacy.model.GeneFilterQuery; +import org.cbioportal.legacy.model.GenomicDataCountItem; +import org.cbioportal.legacy.model.Mutation; +import org.cbioportal.legacy.model.MutationCountByPosition; +import org.cbioportal.legacy.model.meta.MutationMeta; +import org.springframework.cache.annotation.Cacheable; + +public interface MutationRepository { + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + List getMutationsInMolecularProfileBySampleListId( + String molecularProfileId, + String sampleListId, + List entrezGeneIds, + boolean snpOnly, + String projection, + Integer pageSize, + Integer pageNumber, + String sortBy, + String direction); + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + MutationMeta getMetaMutationsInMolecularProfileBySampleListId( + String molecularProfileId, String sampleListId, List entrezGeneIds); + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + List getMutationsInMultipleMolecularProfiles( + List molecularProfileIds, + List sampleIds, + List entrezGeneIds, + String projection, + Integer pageSize, + Integer pageNumber, + String sortBy, + String direction); + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + List getMutationsInMultipleMolecularProfilesByGeneQueries( + List molecularProfileIds, + List sampleIds, + List geneQueries, + String projection, + Integer pageSize, + Integer pageNumber, + String sortBy, + String direction); + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + MutationMeta getMetaMutationsInMultipleMolecularProfiles( + List molecularProfileIds, List sampleIds, List entrezGeneIds); + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + List fetchMutationsInMolecularProfile( + String molecularProfileId, + List sampleIds, + List entrezGeneIds, + boolean snpOnly, + String projection, + Integer pageSize, + Integer pageNumber, + String sortBy, + String direction); + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + MutationMeta fetchMetaMutationsInMolecularProfile( + String molecularProfileId, List sampleIds, List entrezGeneIds); + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + MutationCountByPosition getMutationCountByPosition( + Integer entrezGeneId, Integer proteinPosStart, Integer proteinPosEnd); + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + GenomicDataCountItem getMutationCountsByType( + List molecularProfileIds, + List sampleIds, + List entrezGeneIds, + String profileType); +} diff --git a/src/main/java/org/cbioportal/legacy/persistence/NamespaceRepository.java b/src/main/java/org/cbioportal/legacy/persistence/NamespaceRepository.java new file mode 100644 index 00000000000..4ab102adcff --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/persistence/NamespaceRepository.java @@ -0,0 +1,30 @@ +package org.cbioportal.legacy.persistence; + +import java.util.List; +import org.cbioportal.legacy.model.NamespaceAttribute; +import org.cbioportal.legacy.model.NamespaceAttributeCount; +import org.cbioportal.legacy.model.NamespaceData; +import org.cbioportal.legacy.model.NamespaceDataCount; + +public interface NamespaceRepository { + + List getNamespaceOuterKey(List studyIds); + + List getNamespaceInnerKey(String outerKey, List studyIds); + + List getNamespaceAttributeCountsBySampleIds( + List studyIds, List sampleIds, List namespaceAttributes); + + List getNamespaceDataCounts( + List studyIds, List sampleIds, String outerKey, String innerKey); + + List getNamespaceData( + List studyIds, List sampleIds, String outerKey, String innerKey); + + List getNamespaceDataForComparison( + List studyIds, + List sampleIds, + String outerKey, + String innerKey, + String value); +} diff --git a/src/main/java/org/cbioportal/legacy/persistence/PatientRepository.java b/src/main/java/org/cbioportal/legacy/persistence/PatientRepository.java new file mode 100644 index 00000000000..ea83447a793 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/persistence/PatientRepository.java @@ -0,0 +1,61 @@ +package org.cbioportal.legacy.persistence; + +import java.util.List; +import org.cbioportal.legacy.model.Patient; +import org.cbioportal.legacy.model.meta.BaseMeta; +import org.springframework.cache.annotation.Cacheable; + +public interface PatientRepository { + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + List getAllPatients( + String keyword, + String projection, + Integer pageSize, + Integer pageNumber, + String sortBy, + String direction); + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + BaseMeta getMetaPatients(String keyword); + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + List getAllPatientsInStudy( + String studyId, + String projection, + Integer pageSize, + Integer pageNumber, + String sortBy, + String direction); + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + BaseMeta getMetaPatientsInStudy(String studyId); + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + Patient getPatientInStudy(String studyId, String patientId); + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + List fetchPatients(List studyIds, List patientIds, String projection); + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + BaseMeta fetchMetaPatients(List studyIds, List patientIds); + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + List getPatientsOfSamples(List studyIds, List sampleIds); +} diff --git a/src/main/java/org/cbioportal/legacy/persistence/PersistenceConstants.java b/src/main/java/org/cbioportal/legacy/persistence/PersistenceConstants.java new file mode 100644 index 00000000000..6d2f8dc1b37 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/persistence/PersistenceConstants.java @@ -0,0 +1,9 @@ +package org.cbioportal.legacy.persistence; + +public class PersistenceConstants { + + public static final String DETAILED_PROJECTION = "DETAILED"; + public static final String SUMMARY_PROJECTION = "SUMMARY"; + public static final String ID_PROJECTION = "ID"; + public static final String SAMPLE_CLINICAL_DATA_TYPE = "SAMPLE"; +} diff --git a/src/main/java/org/cbioportal/legacy/persistence/ReferenceGenomeGeneRepository.java b/src/main/java/org/cbioportal/legacy/persistence/ReferenceGenomeGeneRepository.java new file mode 100644 index 00000000000..2a906843ea9 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/persistence/ReferenceGenomeGeneRepository.java @@ -0,0 +1,33 @@ +package org.cbioportal.legacy.persistence; + +import java.util.List; +import org.cbioportal.legacy.model.ReferenceGenomeGene; +import org.springframework.cache.annotation.Cacheable; + +public interface ReferenceGenomeGeneRepository { + @Cacheable( + cacheResolver = "staticRepositoryCacheOneResolver", + condition = "@cacheEnabledConfig.getEnabled()") + List getAllGenesByGenomeName(String genomeName); + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + List getGenesByHugoGeneSymbolsAndGenomeName( + List geneIds, String genomeName); + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + List getGenesByGenomeName(List geneIds, String genomeName); + + @Cacheable( + cacheResolver = "staticRepositoryCacheOneResolver", + condition = "@cacheEnabledConfig.getEnabled()") + ReferenceGenomeGene getReferenceGenomeGene(Integer geneId, String genomeName); + + @Cacheable( + cacheResolver = "staticRepositoryCacheOneResolver", + condition = "@cacheEnabledConfig.getEnabled()") + ReferenceGenomeGene getReferenceGenomeGeneByEntityId(Integer geneticEntityId, String genomeName); +} diff --git a/src/main/java/org/cbioportal/legacy/persistence/ResourceDataRepository.java b/src/main/java/org/cbioportal/legacy/persistence/ResourceDataRepository.java new file mode 100644 index 00000000000..19786e362d5 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/persistence/ResourceDataRepository.java @@ -0,0 +1,70 @@ +package org.cbioportal.legacy.persistence; + +import java.util.List; +import org.cbioportal.legacy.model.ResourceData; +import org.springframework.cache.annotation.Cacheable; + +public interface ResourceDataRepository { + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + List getAllResourceDataOfSampleInStudy( + String studyId, + String sampleId, + String resourceId, + String projection, + Integer pageSize, + Integer pageNumber, + String sortBy, + String direction); + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + List getAllResourceDataOfPatientInStudy( + String studyId, + String patientId, + String resourceId, + String projection, + Integer pageSize, + Integer pageNumber, + String sortBy, + String direction); + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + List getAllResourceDataForStudy( + String studyId, + String resourceId, + String projection, + Integer pageSize, + Integer pageNumber, + String sortBy, + String direction); + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + List getResourceDataForAllPatientsInStudy( + String studyId, + String resourceId, + String projection, + Integer pageSize, + Integer pageNumber, + String sortBy, + String direction); + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + List getResourceDataForAllSamplesInStudy( + String studyId, + String resourceId, + String projection, + Integer pageSize, + Integer pageNumber, + String sortBy, + String direction); +} diff --git a/src/main/java/org/cbioportal/legacy/persistence/ResourceDefinitionRepository.java b/src/main/java/org/cbioportal/legacy/persistence/ResourceDefinitionRepository.java new file mode 100644 index 00000000000..c6a210fe106 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/persistence/ResourceDefinitionRepository.java @@ -0,0 +1,24 @@ +package org.cbioportal.legacy.persistence; + +import java.util.List; +import org.cbioportal.legacy.model.ResourceDefinition; +import org.springframework.cache.annotation.Cacheable; + +public interface ResourceDefinitionRepository { + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + ResourceDefinition getResourceDefinition(String studyId, String resourceId); + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + List fetchResourceDefinitions( + List studyIds, + String projection, + Integer pageSize, + Integer pageNumber, + String sortBy, + String direction); +} diff --git a/src/main/java/org/cbioportal/legacy/persistence/SampleListRepository.java b/src/main/java/org/cbioportal/legacy/persistence/SampleListRepository.java new file mode 100644 index 00000000000..fa955582739 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/persistence/SampleListRepository.java @@ -0,0 +1,57 @@ +package org.cbioportal.legacy.persistence; + +import java.util.List; +import org.cbioportal.legacy.model.SampleList; +import org.cbioportal.legacy.model.SampleListToSampleId; +import org.cbioportal.legacy.model.meta.BaseMeta; +import org.springframework.cache.annotation.Cacheable; + +public interface SampleListRepository { + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + List getAllSampleLists( + String projection, Integer pageSize, Integer pageNumber, String sortBy, String direction); + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + BaseMeta getMetaSampleLists(); + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + SampleList getSampleList(String sampleListId); + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + List getSampleLists(List sampleListIds, String projection); + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + List getAllSampleListsInStudies( + List studyIds, + String projection, + Integer pageSize, + Integer pageNumber, + String sortBy, + String direction); + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + BaseMeta getMetaSampleListsInStudy(String studyId); + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + List getAllSampleIdsInSampleList(String sampleListId); + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + List getSampleListSampleIds(List sampleListIds); +} diff --git a/src/main/java/org/cbioportal/legacy/persistence/SampleRepository.java b/src/main/java/org/cbioportal/legacy/persistence/SampleRepository.java new file mode 100644 index 00000000000..8c79fb2ee82 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/persistence/SampleRepository.java @@ -0,0 +1,110 @@ +package org.cbioportal.legacy.persistence; + +import java.util.List; +import org.cbioportal.legacy.model.Sample; +import org.cbioportal.legacy.model.meta.BaseMeta; +import org.springframework.cache.annotation.Cacheable; + +public interface SampleRepository { + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + List getAllSamples( + String keyword, + List studyIds, + String projection, + Integer pageSize, + Integer pageNumber, + String sort, + String direction); + + BaseMeta getMetaSamples(String keyword, List studyIds); + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + List getAllSamplesInStudy( + String studyId, + String projection, + Integer pageSize, + Integer pageNumber, + String sortBy, + String direction); + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + BaseMeta getMetaSamplesInStudy(String studyId); + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + List getAllSamplesInStudies( + List studyIds, + String projection, + Integer pageSize, + Integer pageNumber, + String sortBy, + String direction); + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + Sample getSampleInStudy(String studyId, String sampleId); + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + List getAllSamplesOfPatientInStudy( + String studyId, + String patientId, + String projection, + Integer pageSize, + Integer pageNumber, + String sortBy, + String direction); + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + BaseMeta getMetaSamplesOfPatientInStudy(String studyId, String patientId); + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + List getAllSamplesOfPatientsInStudy( + String studyId, List patientIds, String projection); + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + List getSamplesOfPatientsInMultipleStudies( + List studyIds, List patientIds, String projection); + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + List fetchSamples(List studyIds, List sampleIds, String projection); + + List fetchSamplesBySampleListIds(List sampleListIds, String projection); + + @Cacheable( + cacheResolver = "staticRepositoryCacheOneResolver", + condition = "@cacheEnabledConfig.getEnabled()") + List fetchSampleBySampleListId(String sampleListIds, String projection); + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + BaseMeta fetchMetaSamples(List studyIds, List sampleIds); + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + BaseMeta fetchMetaSamples(List sampleListIds); + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + List getSamplesByInternalIds(List internalIds); +} diff --git a/src/main/java/org/cbioportal/legacy/persistence/SecurityRepository.java b/src/main/java/org/cbioportal/legacy/persistence/SecurityRepository.java new file mode 100644 index 00000000000..0fc405e9b9e --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/persistence/SecurityRepository.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2015 Memorial Sloan-Kettering Cancer Center. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS + * FOR A PARTICULAR PURPOSE. The software and documentation provided hereunder + * is on an "as is" basis, and Memorial Sloan-Kettering Cancer Center has no + * obligations to provide maintenance, support, updates, enhancements or + * modifications. In no event shall Memorial Sloan-Kettering Cancer Center be + * liable to any party for direct, indirect, special, incidental or + * consequential damages, including lost profits, arising out of the use of this + * software and its documentation, even if Memorial Sloan-Kettering Cancer + * Center has been advised of the possibility of such damage. + */ + +/* + * This file is part of cBioPortal. + * + * cBioPortal is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package org.cbioportal.legacy.persistence; + +// imports +import java.util.Set; +import org.cbioportal.legacy.model.User; +import org.cbioportal.legacy.model.UserAuthorities; + +/** Interface to use to retrieve portal user information. */ +public interface SecurityRepository { + + /** + * Given a user id, returns a user instance. If username does not exist in db, returns null. + * + * @param username String + * @return User + */ + User getPortalUser(String username); + + /** + * Given a user id, returns a UserAuthorities instance. If username does not exist in db, returns + * null. + * + * @param username String + * @return UserAuthorities + */ + UserAuthorities getPortalUserAuthorities(String username); + + void addPortalUser(User user); + + void addPortalUserAuthorities(UserAuthorities userAuthorities); + + /** + * Given an internal cancer study id, returns a set of upper case cancer study group strings. + * Returns empty set if cancer study does not exist or there are no groups. + * + * @param internalCancerStudyId Integer + * @return Set cancer study group strings in upper case + */ + Set getCancerStudyGroups(Integer internalCancerStudyId); +} diff --git a/src/main/java/org/cbioportal/legacy/persistence/SignificantCopyNumberRegionRepository.java b/src/main/java/org/cbioportal/legacy/persistence/SignificantCopyNumberRegionRepository.java new file mode 100644 index 00000000000..0d418cf0298 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/persistence/SignificantCopyNumberRegionRepository.java @@ -0,0 +1,31 @@ +package org.cbioportal.legacy.persistence; + +import java.util.List; +import org.cbioportal.legacy.model.Gistic; +import org.cbioportal.legacy.model.GisticToGene; +import org.cbioportal.legacy.model.meta.BaseMeta; +import org.springframework.cache.annotation.Cacheable; + +public interface SignificantCopyNumberRegionRepository { + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + List getSignificantCopyNumberRegions( + String studyId, + String projection, + Integer pageSize, + Integer pageNumber, + String sortBy, + String direction); + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + BaseMeta getMetaSignificantCopyNumberRegions(String studyId); + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + List getGenesOfRegions(List gisticRoiIds); +} diff --git a/src/main/java/org/cbioportal/legacy/persistence/SignificantlyMutatedGeneRepository.java b/src/main/java/org/cbioportal/legacy/persistence/SignificantlyMutatedGeneRepository.java new file mode 100644 index 00000000000..9d549904670 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/persistence/SignificantlyMutatedGeneRepository.java @@ -0,0 +1,25 @@ +package org.cbioportal.legacy.persistence; + +import java.util.List; +import org.cbioportal.legacy.model.MutSig; +import org.cbioportal.legacy.model.meta.BaseMeta; +import org.springframework.cache.annotation.Cacheable; + +public interface SignificantlyMutatedGeneRepository { + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + List getSignificantlyMutatedGenes( + String studyId, + String projection, + Integer pageSize, + Integer pageNumber, + String sortBy, + String direction); + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + BaseMeta getMetaSignificantlyMutatedGenes(String studyId); +} diff --git a/src/main/java/org/cbioportal/legacy/persistence/StaticDataTimeStampRepository.java b/src/main/java/org/cbioportal/legacy/persistence/StaticDataTimeStampRepository.java new file mode 100644 index 00000000000..1fc80e2c48d --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/persistence/StaticDataTimeStampRepository.java @@ -0,0 +1,8 @@ +package org.cbioportal.legacy.persistence; + +import java.util.List; +import org.cbioportal.legacy.model.TableTimestampPair; + +public interface StaticDataTimeStampRepository { + List getTimestamps(List tables); +} diff --git a/src/main/java/org/cbioportal/legacy/persistence/StructuralVariantRepository.java b/src/main/java/org/cbioportal/legacy/persistence/StructuralVariantRepository.java new file mode 100644 index 00000000000..54c38ce6c36 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/persistence/StructuralVariantRepository.java @@ -0,0 +1,34 @@ +package org.cbioportal.legacy.persistence; + +import java.util.List; +import org.cbioportal.legacy.model.GeneFilterQuery; +import org.cbioportal.legacy.model.StructuralVariant; +import org.cbioportal.legacy.model.StructuralVariantFilterQuery; +import org.cbioportal.legacy.model.StructuralVariantQuery; +import org.springframework.cache.annotation.Cacheable; + +public interface StructuralVariantRepository { + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + List fetchStructuralVariants( + List molecularProfileIds, + List sampleIds, + List entrezGeneIds, + List structuralVariantQueries); + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + List fetchStructuralVariantsByGeneQueries( + List molecularProfileIds, List sampleIds, List geneQueries); + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + List fetchStructuralVariantsByStructVarQueries( + List molecularProfileIds, + List sampleIds, + List structVarQueries); +} diff --git a/src/main/java/org/cbioportal/legacy/persistence/StudyRepository.java b/src/main/java/org/cbioportal/legacy/persistence/StudyRepository.java new file mode 100644 index 00000000000..b25dddea99f --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/persistence/StudyRepository.java @@ -0,0 +1,51 @@ +package org.cbioportal.legacy.persistence; + +import java.util.List; +import org.cbioportal.legacy.model.CancerStudy; +import org.cbioportal.legacy.model.CancerStudyTags; +import org.cbioportal.legacy.model.meta.BaseMeta; +import org.springframework.cache.annotation.Cacheable; + +public interface StudyRepository { + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + List getAllStudies( + String keyword, + String projection, + Integer pageSize, + Integer pageNumber, + String sortBy, + String direction); + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + BaseMeta getMetaStudies(String keyword); + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + CancerStudy getStudy(String studyId, String projection); + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + List fetchStudies(List studyIds, String projection); + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + BaseMeta fetchMetaStudies(List studyIds); + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + CancerStudyTags getTags(String studyId); + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + List getTagsForMultipleStudies(List studyIds); +} diff --git a/src/main/java/org/cbioportal/legacy/persistence/StudyViewRepository.java b/src/main/java/org/cbioportal/legacy/persistence/StudyViewRepository.java new file mode 100644 index 00000000000..83cbf64ba9e --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/persistence/StudyViewRepository.java @@ -0,0 +1,115 @@ +package org.cbioportal.legacy.persistence; + +import java.util.List; +import java.util.Map; +import java.util.Set; +import org.cbioportal.legacy.model.AlterationCountByGene; +import org.cbioportal.legacy.model.CaseListDataCount; +import org.cbioportal.legacy.model.ClinicalAttribute; +import org.cbioportal.legacy.model.ClinicalData; +import org.cbioportal.legacy.model.ClinicalDataCount; +import org.cbioportal.legacy.model.ClinicalDataCountItem; +import org.cbioportal.legacy.model.ClinicalEventTypeCount; +import org.cbioportal.legacy.model.CopyNumberCountByGene; +import org.cbioportal.legacy.model.GenericAssayDataCountItem; +import org.cbioportal.legacy.model.GenomicDataCount; +import org.cbioportal.legacy.model.GenomicDataCountItem; +import org.cbioportal.legacy.model.MolecularProfile; +import org.cbioportal.legacy.model.PatientTreatment; +import org.cbioportal.legacy.model.Sample; +import org.cbioportal.legacy.model.SampleTreatment; +import org.cbioportal.legacy.model.StudyViewFilterContext; +import org.cbioportal.legacy.web.parameter.ClinicalDataType; +import org.cbioportal.legacy.web.parameter.GenericAssayDataBinFilter; +import org.cbioportal.legacy.web.parameter.GenericAssayDataFilter; +import org.cbioportal.legacy.web.parameter.GenomicDataBinFilter; +import org.cbioportal.legacy.web.parameter.GenomicDataFilter; + +public interface StudyViewRepository { + List getFilteredSamples(StudyViewFilterContext studyViewFilterContext); + + List getFilteredStudyIds(StudyViewFilterContext studyViewFilterContext); + + List getSampleClinicalData( + StudyViewFilterContext studyViewFilterContext, List attributeIds); + + List getPatientClinicalData( + StudyViewFilterContext studyViewFilterContext, List attributeIds); + + List getMutatedGenes(StudyViewFilterContext studyViewFilterContext); + + List getStructuralVariantGenes( + StudyViewFilterContext studyViewFilterContext); + + List getCnaGenes(StudyViewFilterContext studyViewFilterContext); + + List getClinicalDataCounts( + StudyViewFilterContext studyViewFilterContext, List filteredAttributes); + + List getMolecularProfileSampleCounts( + StudyViewFilterContext studyViewFilterContext); + + Map getClinicalAttributeDatatypeMap(); + + List getCaseListDataCountsPerStudy( + StudyViewFilterContext studyViewFilterContext); + + Map getTotalProfiledCounts( + StudyViewFilterContext studyViewFilterContext, + String alterationType, + List molecularProfiles); + + List getClinicalAttributes(); + + List getClinicalAttributesForStudies(List studyIds); + + int getFilteredSamplesCount(StudyViewFilterContext studyViewFilterContext); + + int getFilteredPatientCount(StudyViewFilterContext studyViewFilterContext); + + Map> getMatchingGenePanelIds( + StudyViewFilterContext studyViewFilterContext, String alterationType); + + int getTotalProfiledCountsByAlterationType( + StudyViewFilterContext studyViewFilterContext, String alterationType); + + int getSampleProfileCountWithoutPanelData( + StudyViewFilterContext studyViewFilterContext, String alterationType); + + List getClinicalEventTypeCounts( + StudyViewFilterContext studyViewFilterContext); + + List getPatientTreatments(StudyViewFilterContext studyViewFilterContext); + + int getTotalPatientTreatmentCount(StudyViewFilterContext studyViewFilterContext); + + List getSampleTreatments(StudyViewFilterContext studyViewFilterContext); + + int getTotalSampleTreatmentCount(StudyViewFilterContext studyViewFilterContext); + + List getCNACounts( + StudyViewFilterContext studyViewFilterContext, List genomicDataFilters); + + List getGenericAssayDataCounts( + StudyViewFilterContext studyViewFilterContext, + List genericAssayDataFilters); + + Map getMutationCounts( + StudyViewFilterContext studyViewFilterContext, GenomicDataFilter genomicDataFilter); + + List getMutationCountsByType( + StudyViewFilterContext studyViewFilterContext, List genomicDataFilters); + + List getGenomicDataBinCounts( + StudyViewFilterContext studyViewFilterContext, + List genomicDataBinFilters); + + List getGenericAssayDataBinCounts( + StudyViewFilterContext studyViewFilterContext, + List genericAssayDataBinFilters); + + List getGenericAssayProfiles(); + + List getFilteredMolecularProfilesByAlterationType( + StudyViewFilterContext studyViewFilterContext, String alterationType); +} diff --git a/src/main/java/org/cbioportal/legacy/persistence/TreatmentRepository.java b/src/main/java/org/cbioportal/legacy/persistence/TreatmentRepository.java new file mode 100644 index 00000000000..6efe3b9ce44 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/persistence/TreatmentRepository.java @@ -0,0 +1,44 @@ +package org.cbioportal.legacy.persistence; + +import java.util.List; +import java.util.Map; +import org.cbioportal.legacy.model.ClinicalEventKeyCode; +import org.cbioportal.legacy.model.ClinicalEventSample; +import org.cbioportal.legacy.model.Treatment; +import org.springframework.cache.annotation.Cacheable; + +public interface TreatmentRepository { + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + public Map> getTreatmentsByPatientId( + List sampleIds, List studyIds, ClinicalEventKeyCode key); + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + public List getTreatments( + List sampleIds, List studyIds, ClinicalEventKeyCode key); + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + public Map> getSamplesByPatientId( + List sampleIds, List studyIds); + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + public Map> getShallowSamplesByPatientId( + List sampleIds, List studyIds); + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + public Boolean hasTreatmentData(List studies, ClinicalEventKeyCode key); + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + public Boolean hasSampleTimelineData(List studies); +} diff --git a/src/main/java/org/cbioportal/legacy/persistence/VariantCountRepository.java b/src/main/java/org/cbioportal/legacy/persistence/VariantCountRepository.java new file mode 100644 index 00000000000..292ffc9c1f6 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/persistence/VariantCountRepository.java @@ -0,0 +1,14 @@ +package org.cbioportal.legacy.persistence; + +import java.util.List; +import org.cbioportal.legacy.model.VariantCount; +import org.springframework.cache.annotation.Cacheable; + +public interface VariantCountRepository { + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + List fetchVariantCounts( + String molecularProfileId, List entrezGeneIds, List keywords); +} diff --git a/src/main/java/org/cbioportal/legacy/persistence/cachemaputil/CacheMapBuilder.java b/src/main/java/org/cbioportal/legacy/persistence/cachemaputil/CacheMapBuilder.java new file mode 100644 index 00000000000..ae92e667ad3 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/persistence/cachemaputil/CacheMapBuilder.java @@ -0,0 +1,67 @@ +package org.cbioportal.legacy.persistence.cachemaputil; + +import java.util.Map; +import java.util.function.Function; +import java.util.stream.Collectors; +import org.cbioportal.legacy.model.CancerStudy; +import org.cbioportal.legacy.model.MolecularProfile; +import org.cbioportal.legacy.model.SampleList; +import org.cbioportal.legacy.persistence.GenericAssayRepository; +import org.cbioportal.legacy.persistence.MolecularProfileRepository; +import org.cbioportal.legacy.persistence.SampleListRepository; +import org.cbioportal.legacy.persistence.StudyRepository; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +@Component +public class CacheMapBuilder { + + private static final Logger LOG = LoggerFactory.getLogger(CacheMapBuilder.class); + + @Autowired private StudyRepository studyRepository; + + @Autowired private MolecularProfileRepository molecularProfileRepository; + + @Autowired private SampleListRepository sampleListRepository; + + @Autowired private GenericAssayRepository genericAssayRepository; + + private static final int REPOSITORY_RESULT_LIMIT = + Integer.MAX_VALUE; // retrieve all entries (no limit to return size) + private static final int REPOSITORY_RESULT_OFFSET = 0; // retrieve all entries (do not skip any) + + public Map buildMolecularProfileMap() { + Map molecularProfileMap = + molecularProfileRepository + .getAllMolecularProfiles( + "SUMMARY", REPOSITORY_RESULT_LIMIT, REPOSITORY_RESULT_OFFSET, null, "ASC") + .stream() + .collect(Collectors.toMap(MolecularProfile::getStableId, Function.identity())); + LOG.debug(" molecular profile map size: " + molecularProfileMap.size()); + return molecularProfileMap; + } + + public Map buildSampleListMap() { + Map sampleListMap = + sampleListRepository + .getAllSampleLists( + "SUMMARY", REPOSITORY_RESULT_LIMIT, REPOSITORY_RESULT_OFFSET, null, "ASC") + .stream() + .collect(Collectors.toMap(SampleList::getStableId, Function.identity())); + LOG.debug(" sample list map size: " + sampleListMap.size()); + return sampleListMap; + } + + public Map buildCancerStudyMap() { + Map cancerStudyMap = + studyRepository + .getAllStudies( + null, "SUMMARY", REPOSITORY_RESULT_LIMIT, REPOSITORY_RESULT_OFFSET, null, "ASC") + .stream() + .collect(Collectors.toMap(CancerStudy::getCancerStudyIdentifier, Function.identity())); + LOG.debug(" cancer study map size: " + cancerStudyMap.size()); + return cancerStudyMap; + } +} diff --git a/src/main/java/org/cbioportal/legacy/persistence/cachemaputil/CacheMapUtil.java b/src/main/java/org/cbioportal/legacy/persistence/cachemaputil/CacheMapUtil.java new file mode 100644 index 00000000000..b3f1d7d8577 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/persistence/cachemaputil/CacheMapUtil.java @@ -0,0 +1,16 @@ +package org.cbioportal.legacy.persistence.cachemaputil; + +import java.util.Map; +import org.cbioportal.legacy.model.CancerStudy; +import org.cbioportal.legacy.model.MolecularProfile; +import org.cbioportal.legacy.model.SampleList; + +public interface CacheMapUtil { + Map getMolecularProfileMap(); + + Map getSampleListMap(); + + Map getCancerStudyMap(); + + boolean hasCacheEnabled(); +} diff --git a/src/main/java/org/cbioportal/legacy/persistence/cachemaputil/InactiveCacheMapUtil.java b/src/main/java/org/cbioportal/legacy/persistence/cachemaputil/InactiveCacheMapUtil.java new file mode 100644 index 00000000000..789e4561d8b --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/persistence/cachemaputil/InactiveCacheMapUtil.java @@ -0,0 +1,43 @@ +package org.cbioportal.legacy.persistence.cachemaputil; + +import java.util.Map; +import org.cbioportal.legacy.model.CancerStudy; +import org.cbioportal.legacy.model.MolecularProfile; +import org.cbioportal.legacy.model.SampleList; +import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; +import org.springframework.stereotype.Component; + +@Component +// This implementation of the CacheMapUtils is instantiated on portals where all uses can access any +// study. +@ConditionalOnExpression( + "'false' eq '${authenticate}' or ('optional_oauth2' eq '${authenticate}' and 'true' ne '${security.method_authorization_enabled}')") +public class InactiveCacheMapUtil implements CacheMapUtil { + + // Since user-permission evaluation is not needed when this bean is present, throw an error when + // it is accessed. + + @Override + public Map getMolecularProfileMap() { + throw new RuntimeException( + "A CacheMapUtils method was called on a portal where studies are accessible to all users."); + } + + @Override + public Map getSampleListMap() { + throw new RuntimeException( + "A CacheMapUtils method was called on a portal where studies are accessible to all users."); + } + + @Override + public Map getCancerStudyMap() { + throw new RuntimeException( + "A CacheMapUtils method was called on a portal where studies are accessible to all users."); + } + + // bean is only instantiated when there is no user authorization + @Override + public boolean hasCacheEnabled() { + return false; + } +} diff --git a/src/main/java/org/cbioportal/legacy/persistence/cachemaputil/SpringManagedCacheMapUtil.java b/src/main/java/org/cbioportal/legacy/persistence/cachemaputil/SpringManagedCacheMapUtil.java new file mode 100644 index 00000000000..b1f95eb3047 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/persistence/cachemaputil/SpringManagedCacheMapUtil.java @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2018 - 2019 Memorial Sloan-Kettering Cancer Center. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS + * FOR A PARTICULAR PURPOSE. The software and documentation provided hereunder + * is on an "as is" basis, and Memorial Sloan-Kettering Cancer Center has no + * obligations to provide maintenance, support, updates, enhancements or + * modifications. In no event shall Memorial Sloan-Kettering Cancer Center be + * liable to any party for direct, indirect, special, incidental or + * consequential damages, including lost profits, arising out of the use of this + * software and its documentation, even if Memorial Sloan-Kettering Cancer + * Center has been advised of the possibility of such damage. + */ + +/* + * This file is part of cBioPortal. + * + * cBioPortal is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package org.cbioportal.legacy.persistence.cachemaputil; + +import jakarta.annotation.PostConstruct; +import java.util.Map; +import org.cbioportal.legacy.model.CancerStudy; +import org.cbioportal.legacy.model.MolecularProfile; +import org.cbioportal.legacy.model.SampleList; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Component; + +@Component +// Instantiate when user authorization is active and spring-managed implementation is needed +@ConditionalOnExpression( + "{'oauth2','saml','saml_plus_basic'}.contains('${authenticate}') or ('optional_oauth2' eq '${authenticate}' and 'true' eq '${security.method_authorization_enabled}')") +@ConditionalOnProperty(value = "cache.cache-map-utils.spring-managed", havingValue = "true") +public class SpringManagedCacheMapUtil implements CacheMapUtil { + + private static final Logger LOG = LoggerFactory.getLogger(SpringManagedCacheMapUtil.class); + + @Value("${persistence.cache_type:no-cache}") + private String cacheType; + + @Value("${persistence.cache_type_clickhouse:no-cache}") + private String cacheTypeClickhouse; + + @Value("${cache.cache-map-utils.spring-managed}") + private boolean springManagedCacheMapUtils; + + @Autowired private CacheMapBuilder cacheMapBuilder; + + @PostConstruct + public void init() { + // Make sure the user does not have a conflicting configuration. Explode if there is. + if (cacheType.equals("no-cache") + && cacheTypeClickhouse.equals("no-cache") + && springManagedCacheMapUtils) { + throw new RuntimeException( + "cache.cache-map-utils.spring-managed property is set to 'true' but the portal is not " + + "configured with a cache-implementation (persistence.cache_type property is 'no-cache'). Please set to 'false'" + + " or configure the cache."); + } + } + + // This implementation of the CacheMapUtils does not keep a locally cached/referenced HashMap + // but retrieves the HashMaps from the active Spring caching solution. + + @Override + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + public Map getMolecularProfileMap() { + LOG.debug("Building molecularProfileMap (cache miss)"); + return cacheMapBuilder.buildMolecularProfileMap(); + } + + @Override + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + public Map getSampleListMap() { + LOG.debug("Building sampleListMap (cache miss)"); + return cacheMapBuilder.buildSampleListMap(); + } + + @Override + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + public Map getCancerStudyMap() { + LOG.debug("Building cancerStudyMap (cache miss)"); + return cacheMapBuilder.buildCancerStudyMap(); + } + + // bean is only instantiated when there is user authorization + @Override + public boolean hasCacheEnabled() { + return true; + } +} diff --git a/src/main/java/org/cbioportal/legacy/persistence/cachemaputil/StaticRefCacheMapUtil.java b/src/main/java/org/cbioportal/legacy/persistence/cachemaputil/StaticRefCacheMapUtil.java new file mode 100644 index 00000000000..2702dfd65c3 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/persistence/cachemaputil/StaticRefCacheMapUtil.java @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2018 - 2019 Memorial Sloan-Kettering Cancer Center. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS + * FOR A PARTICULAR PURPOSE. The software and documentation provided hereunder + * is on an "as is" basis, and Memorial Sloan-Kettering Cancer Center has no + * obligations to provide maintenance, support, updates, enhancements or + * modifications. In no event shall Memorial Sloan-Kettering Cancer Center be + * liable to any party for direct, indirect, special, incidental or + * consequential damages, including lost profits, arising out of the use of this + * software and its documentation, even if Memorial Sloan-Kettering Cancer + * Center has been advised of the possibility of such damage. + */ + +/* + * This file is part of cBioPortal. + * + * cBioPortal is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package org.cbioportal.legacy.persistence.cachemaputil; + +import jakarta.annotation.PostConstruct; +import java.util.Map; +import org.cbioportal.legacy.model.CancerStudy; +import org.cbioportal.legacy.model.MolecularProfile; +import org.cbioportal.legacy.model.SampleList; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.stereotype.Component; + +@Component +// Instantiate when user authorization is active and spring-managed implementation is not needed +@ConditionalOnExpression( + "{'oauth2','saml','saml_plus_basic'}.contains('${authenticate}') or ('optional_oauth2' eq '${authenticate}' and 'true' eq '${security.method_authorization_enabled}')") +@ConditionalOnProperty( + value = "cache.cache-map-utils.spring-managed", + havingValue = "false", + matchIfMissing = true) +public class StaticRefCacheMapUtil implements CacheMapUtil { + + private static final Logger LOG = LoggerFactory.getLogger(StaticRefCacheMapUtil.class); + + @Autowired private CacheMapBuilder cacheMapBuilder; + + // This implementation of the CacheMapUtils keeps a locally cached/referenced HashMap and does + // not defer to any Spring managed caching solution. + + // maps used to cache required relationships - in all maps stable ids are key + // Fields are static because the proxying mechanism of the CancerStudyPermissionEvaluator + // appears to perturb the Singleton scope of the CacheMapUtils bean. When debugging + // two version appeared to exist in context. A mechanism with bean injection did not work here. + static Map molecularProfileCache; + static Map sampleListCache; + static Map cancerStudyCache; + + @PostConstruct + private void init() { + initializeCacheMemory(); + } + + public synchronized void initializeCacheMemory() { + LOG.debug("creating cache maps for authorization"); + molecularProfileCache = cacheMapBuilder.buildMolecularProfileMap(); + sampleListCache = cacheMapBuilder.buildSampleListMap(); + cancerStudyCache = cacheMapBuilder.buildCancerStudyMap(); + } + + @Override + public Map getMolecularProfileMap() { + return molecularProfileCache; + } + + @Override + public Map getSampleListMap() { + return sampleListCache; + } + + @Override + public Map getCancerStudyMap() { + return cancerStudyCache; + } + + @Override + public boolean hasCacheEnabled() { + return true; + } +} diff --git a/src/main/java/org/cbioportal/legacy/persistence/config/EhCacheConfig.java b/src/main/java/org/cbioportal/legacy/persistence/config/EhCacheConfig.java new file mode 100644 index 00000000000..63ba9819d77 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/persistence/config/EhCacheConfig.java @@ -0,0 +1,48 @@ +package org.cbioportal.legacy.persistence.config; + +import org.cbioportal.legacy.persistence.util.CustomEhcachingProvider; +import org.cbioportal.legacy.persistence.util.CustomKeyGenerator; +import org.cbioportal.legacy.utils.config.annotation.ConditionalOnProperty; +import org.springframework.cache.CacheManager; +import org.springframework.cache.annotation.CachingConfigurerSupport; +import org.springframework.cache.annotation.EnableCaching; +import org.springframework.cache.interceptor.KeyGenerator; +import org.springframework.cache.interceptor.NamedCacheResolver; +import org.springframework.cache.jcache.JCacheCacheManager; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +@EnableCaching +@ConditionalOnProperty( + name = "persistence.cache_type", + havingValue = {"ehcache-heap", "ehcache-disk", "ehcache-hybrid"}) +public class EhCacheConfig extends CachingConfigurerSupport { + + @Bean + @Override + public CacheManager cacheManager() { + return new JCacheCacheManager(customEhcachingProvider().getCacheManager()); + } + + @Bean + @Override + public KeyGenerator keyGenerator() { + return new CustomKeyGenerator(); + } + + @Bean + public CustomEhcachingProvider customEhcachingProvider() { + return new CustomEhcachingProvider(); + } + + @Bean + public NamedCacheResolver generalRepositoryCacheResolver() { + return new NamedCacheResolver(cacheManager(), "GeneralRepositoryCache"); + } + + @Bean + public NamedCacheResolver staticRepositoryCacheOneResolver() { + return new NamedCacheResolver(cacheManager(), "StaticRepositoryCacheOne"); + } +} diff --git a/src/main/java/org/cbioportal/legacy/persistence/config/RedisConfig.java b/src/main/java/org/cbioportal/legacy/persistence/config/RedisConfig.java new file mode 100644 index 00000000000..34d9846e1d5 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/persistence/config/RedisConfig.java @@ -0,0 +1,59 @@ +package org.cbioportal.legacy.persistence.config; + +import org.cbioportal.legacy.persistence.util.CustomKeyGenerator; +import org.cbioportal.legacy.persistence.util.CustomRedisCachingProvider; +import org.cbioportal.legacy.persistence.util.LoggingCacheErrorHandler; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; +import org.springframework.cache.CacheManager; +import org.springframework.cache.annotation.CachingConfigurerSupport; +import org.springframework.cache.annotation.EnableCaching; +import org.springframework.cache.interceptor.CacheErrorHandler; +import org.springframework.cache.interceptor.CacheResolver; +import org.springframework.cache.interceptor.KeyGenerator; +import org.springframework.cache.interceptor.NamedCacheResolver; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +@EnableCaching +@ConditionalOnExpression( + "#{environment['persistence.cache_type'] == 'redis' or environment['persistence.cache_type_clickhouse'] == 'redis'}") +public class RedisConfig extends CachingConfigurerSupport { + + @Value("${redis.name:cbioportal}") + private String redisName; + + @Bean + @Override + public CacheManager cacheManager() { + return customRedisCachingProvider() + .getCacheManager(customRedisCachingProvider().getRedissonClient()); + } + + @Override + public CacheErrorHandler errorHandler() { + return new LoggingCacheErrorHandler(); + } + + @Bean + @Override + public KeyGenerator keyGenerator() { + return new CustomKeyGenerator(); + } + + @Bean + public CustomRedisCachingProvider customRedisCachingProvider() { + return new CustomRedisCachingProvider(); + } + + @Bean + public CacheResolver generalRepositoryCacheResolver() { + return new NamedCacheResolver(cacheManager(), redisName + "GeneralRepositoryCache"); + } + + @Bean + public CacheResolver staticRepositoryCacheOneResolver() { + return new NamedCacheResolver(cacheManager(), redisName + "StaticRepositoryCacheOne"); + } +} diff --git a/src/main/java/org/cbioportal/legacy/persistence/enums/ClinicalAttributeDataType.java b/src/main/java/org/cbioportal/legacy/persistence/enums/ClinicalAttributeDataType.java new file mode 100644 index 00000000000..56f76ad3fee --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/persistence/enums/ClinicalAttributeDataType.java @@ -0,0 +1,16 @@ +package org.cbioportal.legacy.persistence.enums; + +public enum ClinicalAttributeDataType { + CATEGORICAL("CATEGORICAL"), + NUMERIC("NUMERIC"); + + private final String value; + + ClinicalAttributeDataType(String value) { + this.value = value; + } + + public String getValue() { + return this.value; + } +} diff --git a/src/main/java/org/cbioportal/legacy/persistence/enums/DataSource.java b/src/main/java/org/cbioportal/legacy/persistence/enums/DataSource.java new file mode 100644 index 00000000000..6bebe8ea2dd --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/persistence/enums/DataSource.java @@ -0,0 +1,16 @@ +package org.cbioportal.legacy.persistence.enums; + +public enum DataSource { + PATIENT("PATIENT"), + SAMPLE("SAMPLE"); + + private final String value; + + DataSource(String value) { + this.value = value; + } + + public String getValue() { + return this.value; + } +} diff --git a/src/main/java/org/cbioportal/legacy/persistence/helper/AlterationFilterHelper.java b/src/main/java/org/cbioportal/legacy/persistence/helper/AlterationFilterHelper.java new file mode 100644 index 00000000000..6692e9dae8a --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/persistence/helper/AlterationFilterHelper.java @@ -0,0 +1,161 @@ +package org.cbioportal.legacy.persistence.helper; + +import java.util.Objects; +import org.cbioportal.legacy.model.AlterationFilter; +import org.cbioportal.legacy.model.CNA; +import org.cbioportal.legacy.model.MutationEventType; +import org.cbioportal.legacy.model.util.Select; +import org.springframework.lang.NonNull; +import org.springframework.lang.Nullable; + +public final class AlterationFilterHelper { + + public static AlterationFilterHelper build(@Nullable AlterationFilter alterationFilter) { + if (Objects.isNull(alterationFilter)) { + alterationFilter = new AlterationFilter(); + } + return new AlterationFilterHelper(alterationFilter); + } + + private final AlterationFilter alterationFilter; + private final Select mappedMutationTypes; + + private final Select mappedCnaTypes; + + private AlterationFilterHelper(@NonNull AlterationFilter alterationFilter) { + this.alterationFilter = alterationFilter; + this.mappedMutationTypes = buildMutationTypeList(); + this.mappedCnaTypes = buildCnaTypeList(); + } + + private Select buildMutationTypeList() { + if (alterationFilter.getMutationTypeSelect().hasNone()) { + return Select.none(); + } + if (alterationFilter.getMutationTypeSelect().hasAll()) { + return Select.all(); + } + Select typeSelects = + alterationFilter.getMutationTypeSelect().map(MutationEventType::getMutationType); + typeSelects.inverse(alterationFilter.getMutationTypeSelect().inverse()); + + return typeSelects; + } + + public Select getMutationTypeList() { + return mappedMutationTypes; + } + + public Select getCnaTypeList() { + return mappedCnaTypes; + } + + public Select buildCnaTypeList() { + if (alterationFilter.getCNAEventTypeSelect().hasNone()) { + return Select.none(); + } + if (alterationFilter.getCNAEventTypeSelect().hasAll()) { + return Select.all(); + } + return alterationFilter.getCNAEventTypeSelect().map(CNA::getCode); + } + + public boolean hasDriver() { + return alterationFilter.getIncludeDriver(); + } + + public boolean hasVUSDriver() { + return alterationFilter.getIncludeVUS(); + } + + public boolean hasUnknownOncogenicity() { + return alterationFilter.getIncludeUnknownOncogenicity(); + } + + public boolean hasGermline() { + return alterationFilter.getIncludeGermline(); + } + + public boolean hasSomatic() { + return alterationFilter.getIncludeSomatic(); + } + + public boolean hasUnknownMutationStatus() { + return alterationFilter.getIncludeUnknownStatus(); + } + + public Select getSelectedTiers() { + return alterationFilter.getSelectedTiers(); + } + + public boolean hasUnknownTier() { + return alterationFilter.getIncludeUnknownTier(); + } + + public boolean isAllDriverAnnotationSelected() { + return alterationFilter.getIncludeDriver() + && alterationFilter.getIncludeVUS() + && alterationFilter.getIncludeUnknownOncogenicity(); + } + + public boolean isNoDriverAnnotationSelected() { + return !alterationFilter.getIncludeDriver() + && !alterationFilter.getIncludeVUS() + && !alterationFilter.getIncludeUnknownOncogenicity(); + } + + public boolean isSomeDriverAnnotationsSelected() { + return !isAllDriverAnnotationSelected() && !isNoDriverAnnotationSelected(); + } + + public boolean isAllMutationStatusSelected() { + return alterationFilter.getIncludeGermline() + && alterationFilter.getIncludeSomatic() + && alterationFilter.getIncludeUnknownStatus(); + } + + public boolean isNoMutationStatusSelected() { + return !alterationFilter.getIncludeGermline() + && !alterationFilter.getIncludeSomatic() + && !alterationFilter.getIncludeUnknownStatus(); + } + + public boolean isSomeMutationStatusSelected() { + return !isAllMutationStatusSelected() && !isNoMutationStatusSelected(); + } + + public boolean isAllTierOptionsSelected() { + return !Objects.isNull(alterationFilter.getSelectedTiers()) + && alterationFilter.getSelectedTiers().hasAll() + && alterationFilter.getIncludeUnknownTier(); + } + + public boolean isNoTierOptionsSelected() { + return (Objects.isNull(alterationFilter.getSelectedTiers()) + || alterationFilter.getSelectedTiers().hasNone()) + && !alterationFilter.getIncludeUnknownTier(); + } + + public boolean isSomeTierOptionsSelected() { + return !isAllTierOptionsSelected() && !isNoTierOptionsSelected(); + } + + public boolean shouldApplyMutationAlterationFilter() { + return isSomeDriverAnnotationsSelected() + || isSomeMutationStatusSelected() + || isSomeTierOptionsSelected() + || mappedMutationTypes.hasNone() + || (!mappedMutationTypes.hasNone() && !mappedMutationTypes.hasAll()); + } + + public boolean shouldApplyCnaAlterationFilter() { + return isSomeDriverAnnotationsSelected() + || mappedCnaTypes.hasNone() + || (!mappedCnaTypes.hasNone() && !mappedCnaTypes.hasAll()); + } + + public boolean disableStructuralVariants() { + return !Objects.isNull(alterationFilter.getStructuralVariants()) + && !alterationFilter.getStructuralVariants(); + } +} diff --git a/src/main/java/org/cbioportal/legacy/persistence/helper/StudyViewFilterHelper.java b/src/main/java/org/cbioportal/legacy/persistence/helper/StudyViewFilterHelper.java new file mode 100644 index 00000000000..93b8e20d8d0 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/persistence/helper/StudyViewFilterHelper.java @@ -0,0 +1,301 @@ +package org.cbioportal.legacy.persistence.helper; + +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.EnumMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import org.cbioportal.legacy.model.MolecularProfile; +import org.cbioportal.legacy.persistence.enums.DataSource; +import org.cbioportal.legacy.web.parameter.CategorizedGenericAssayDataCountFilter; +import org.cbioportal.legacy.web.parameter.ClinicalDataFilter; +import org.cbioportal.legacy.web.parameter.CustomSampleIdentifier; +import org.cbioportal.legacy.web.parameter.DataFilter; +import org.cbioportal.legacy.web.parameter.DataFilterValue; +import org.cbioportal.legacy.web.parameter.GenericAssayDataFilter; +import org.cbioportal.legacy.web.parameter.GenomicDataFilter; +import org.cbioportal.legacy.web.parameter.StudyViewFilter; +import org.springframework.lang.NonNull; +import org.springframework.lang.Nullable; + +public final class StudyViewFilterHelper { + public static StudyViewFilterHelper build( + @Nullable StudyViewFilter studyViewFilter, + @Nullable Map> genericAssayProfilesMap, + @Nullable List customDataSamples, + @Nullable List involvedCancerStudies) { + if (Objects.isNull(studyViewFilter)) { + studyViewFilter = new StudyViewFilter(); + } + if (Objects.isNull(genericAssayProfilesMap)) { + genericAssayProfilesMap = new EnumMap<>(DataSource.class); + } + if (Objects.isNull(customDataSamples)) { + customDataSamples = new ArrayList<>(); + } + if (Objects.isNull(involvedCancerStudies)) { + involvedCancerStudies = new ArrayList<>(); + } + if (studyViewFilter.getGenomicDataFilters() != null + && !studyViewFilter.getGenomicDataFilters().isEmpty()) { + List mergedGenomicDataFilters = + mergeDataFilters(studyViewFilter.getGenomicDataFilters()); + studyViewFilter.setGenomicDataFilters(mergedGenomicDataFilters); + } + if (studyViewFilter.getClinicalDataFilters() != null + && !studyViewFilter.getClinicalDataFilters().isEmpty()) { + List mergedClinicalDataFilters = + mergeDataFilters(studyViewFilter.getClinicalDataFilters()); + studyViewFilter.setClinicalDataFilters(mergedClinicalDataFilters); + } + if (studyViewFilter.getGenericAssayDataFilters() != null + && !studyViewFilter.getGenericAssayDataFilters().isEmpty()) { + List mergedGenericAssayDataFilters = + mergeDataFilters(studyViewFilter.getGenericAssayDataFilters()); + studyViewFilter.setGenericAssayDataFilters(mergedGenericAssayDataFilters); + } + return new StudyViewFilterHelper( + studyViewFilter, genericAssayProfilesMap, customDataSamples, involvedCancerStudies); + } + + private final StudyViewFilter studyViewFilter; + private final CategorizedGenericAssayDataCountFilter categorizedGenericAssayDataCountFilter; + private final List customDataSamples; + private final List involvedCancerStudies; + + private StudyViewFilterHelper( + @NonNull StudyViewFilter studyViewFilter, + @NonNull Map> genericAssayProfilesMap, + @NonNull List customDataSamples, + @NonNull List involvedCancerStudies) { + this.studyViewFilter = studyViewFilter; + this.categorizedGenericAssayDataCountFilter = + extractGenericAssayDataCountFilters(studyViewFilter, genericAssayProfilesMap); + this.customDataSamples = customDataSamples; + this.involvedCancerStudies = involvedCancerStudies; + } + + public StudyViewFilter studyViewFilter() { + return studyViewFilter; + } + + public CategorizedGenericAssayDataCountFilter categorizedGenericAssayDataCountFilter() { + return categorizedGenericAssayDataCountFilter; + } + + public List customDataSamples() { + return this.customDataSamples; + } + + public String[] filteredSampleIdentifiers() { + if (studyViewFilter != null && studyViewFilter.getSampleIdentifiers() != null) { + return studyViewFilter.getSampleIdentifiers().stream() + .map( + sampleIdentifier -> + sampleIdentifier.getStudyId() + "_" + sampleIdentifier.getSampleId()) + .toArray(String[]::new); + } else { + return new String[0]; + } + } + + public List involvedCancerStudies() { + return involvedCancerStudies; + } + + private CategorizedGenericAssayDataCountFilter extractGenericAssayDataCountFilters( + final StudyViewFilter studyViewFilter, + Map> genericAssayProfilesMap) { + if ((studyViewFilter.getGenericAssayDataFilters() == null + || genericAssayProfilesMap.isEmpty())) { + return CategorizedGenericAssayDataCountFilter.getBuilder().build(); + } + + CategorizedGenericAssayDataCountFilter.Builder builder = + CategorizedGenericAssayDataCountFilter.getBuilder(); + + // No BINARY in the database yet + if (genericAssayProfilesMap.containsKey(DataSource.SAMPLE)) { + List sampleNumericalProfileTypes = + genericAssayProfilesMap.get(DataSource.SAMPLE).stream() + .filter(profile -> profile.getDatatype().equals("LIMIT-VALUE")) + .map( + profile -> + profile.getStableId().replace(profile.getCancerStudyIdentifier() + "_", "")) + .toList(); + builder.setSampleNumericalGenericAssayDataFilters( + studyViewFilter.getGenericAssayDataFilters().stream() + .filter( + genericAssayDataFilter -> + sampleNumericalProfileTypes.contains(genericAssayDataFilter.getProfileType())) + .toList()); + List sampleCategoricalProfileTypes = + genericAssayProfilesMap.get(DataSource.SAMPLE).stream() + .filter( + profile -> + profile.getDatatype().equals("CATEGORICAL") + || profile.getDatatype().equals("BINARY")) + .map( + profile -> + profile.getStableId().replace(profile.getCancerStudyIdentifier() + "_", "")) + .toList(); + builder.setSampleCategoricalGenericAssayDataFilters( + studyViewFilter.getGenericAssayDataFilters().stream() + .filter( + genericAssayDataFilter -> + sampleCategoricalProfileTypes.contains( + genericAssayDataFilter.getProfileType())) + .toList()); + } + // patient level profile only have categorical for now + if (genericAssayProfilesMap.containsKey(DataSource.PATIENT)) { + List patientCategoricalProfileTypes = + genericAssayProfilesMap.get(DataSource.PATIENT).stream() + .filter( + profile -> + profile.getDatatype().equals("CATEGORICAL") + || profile.getDatatype().equals("BINARY")) + .map( + profile -> + profile.getStableId().replace(profile.getCancerStudyIdentifier() + "_", "")) + .toList(); + builder.setPatientCategoricalGenericAssayDataFilters( + studyViewFilter.getGenericAssayDataFilters().stream() + .filter( + genericAssayDataFilter -> + patientCategoricalProfileTypes.contains( + genericAssayDataFilter.getProfileType())) + .toList()); + } + return builder.build(); + } + + public boolean isCategoricalClinicalDataFilter(ClinicalDataFilter clinicalDataFilter) { + var filterValue = clinicalDataFilter.getValues().getFirst(); + return filterValue.getValue() != null; + } + + /** + * Merge the range of numerical bins in DataFilters to reduce the number of scans that runs on the + * database when filtering. + */ + public static List mergeDataFilters(List filters) { + // this should throw error or move to all binning endpoints in the future for input validation + if (!areValidFilters(filters)) { + return filters; + } + + boolean hasNumericalValue = false; + List mergedDataFilters = new ArrayList<>(); + + for (T filter : filters) { + List mergedValues = new ArrayList<>(); + List nonNumericalValues = new ArrayList<>(); + + // record the start and end of current merging range + BigDecimal mergedStart = null; + BigDecimal mergedEnd = null; + // for each value + for (DataFilterValue dataFilterValue : filter.getValues()) { + // if it is non-numerical, leave it as is + if (dataFilterValue.getValue() != null) { + nonNumericalValues.add(dataFilterValue); + continue; + } + // else it is numerical so start merging process + hasNumericalValue = true; + BigDecimal start = dataFilterValue.getStart(); + BigDecimal end = dataFilterValue.getEnd(); + + // if current merging range is null, we take current bin's range + if (mergedStart == null && mergedEnd == null) { + mergedStart = start; + mergedEnd = end; + } + // else we already has a merging range, we check if this one is consecutive of our range + else if (mergedEnd.equals(start)) { + // if true, we expand our range + mergedEnd = end; + } else { + // otherwise it's a gap, so we save our current range first, and then use current bin to + // start the next range + mergedValues.add(new DataFilterValue(mergedStart, mergedEnd)); + mergedStart = start; + mergedEnd = end; + } + } + + // in the end we need to save the final range, but if everything is non-numerical then no need + // to + if (hasNumericalValue) { + mergedValues.add(new DataFilterValue(mergedStart, mergedEnd)); + } + mergedValues.addAll(nonNumericalValues); + filter.setValues(mergedValues); + mergedDataFilters.add(filter); + } + + return mergedDataFilters; + } + + public static boolean areValidFilters(List filters) { + if (filters == null || filters.isEmpty()) { + return false; + } + + for (T filter : filters) { + if (!isValidFilter(filter)) { + return false; + } + } + return true; + } + + private static boolean isValidFilter(T filter) { + if (filter == null || filter.getValues() == null || filter.getValues().isEmpty()) { + return false; + } + + BigDecimal start = null; + BigDecimal end = null; + for (DataFilterValue value : filter.getValues()) { + if (!validateDataFilterValue(value, start, end)) { + return false; + } + // update start and end values to check next bin range + if (value.getStart() != null) { + start = value.getStart(); + } + if (value.getEnd() != null) { + end = value.getEnd(); + } + } + return true; + } + + private static boolean validateDataFilterValue( + DataFilterValue value, BigDecimal lastStart, BigDecimal lastEnd) { + // non-numerical value should not have numerical value + if (value.getValue() != null) { + return value.getStart() == null && value.getEnd() == null; + } + + // check if start < end + if (value.getStart() != null + && value.getEnd() != null + && value.getStart().compareTo(value.getEnd()) >= 0) { + return false; + } + + // check if start stays increasing and no overlapping + if (value.getStart() != null + && ((lastStart != null && lastStart.compareTo(value.getStart()) >= 0) + || (lastEnd != null && value.getStart().compareTo(lastEnd) < 0))) { + return false; + } + + // check if end stays increasing + return value.getEnd() == null || lastEnd == null || lastEnd.compareTo(value.getEnd()) < 0; + } +} diff --git a/src/main/java/org/cbioportal/legacy/persistence/model/SampleAcquisitionEventRecord.java b/src/main/java/org/cbioportal/legacy/persistence/model/SampleAcquisitionEventRecord.java new file mode 100644 index 00000000000..240e750e202 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/persistence/model/SampleAcquisitionEventRecord.java @@ -0,0 +1,4 @@ +package org.cbioportal.legacy.persistence.model; + +public record SampleAcquisitionEventRecord( + String sampleId, String patientUniqueId, String cancerStudyId, int timeTaken) {} diff --git a/src/main/java/org/cbioportal/legacy/persistence/model/TreatmentRecord.java b/src/main/java/org/cbioportal/legacy/persistence/model/TreatmentRecord.java new file mode 100644 index 00000000000..efcff2c3aed --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/persistence/model/TreatmentRecord.java @@ -0,0 +1,4 @@ +package org.cbioportal.legacy.persistence.model; + +public record TreatmentRecord( + String patientUniqueId, String treatment, int startTime, int stopTime) {} diff --git a/src/main/java/org/cbioportal/legacy/persistence/mybatis/AlterationCountsMapper.java b/src/main/java/org/cbioportal/legacy/persistence/mybatis/AlterationCountsMapper.java new file mode 100644 index 00000000000..cae484a13a1 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/persistence/mybatis/AlterationCountsMapper.java @@ -0,0 +1,170 @@ +package org.cbioportal.legacy.persistence.mybatis; + +import java.util.List; +import org.cbioportal.legacy.model.AlterationCountByGene; +import org.cbioportal.legacy.model.AlterationCountByStructuralVariant; +import org.cbioportal.legacy.model.CopyNumberCountByGene; +import org.cbioportal.legacy.model.MolecularProfileCaseIdentifier; +import org.cbioportal.legacy.model.util.Select; + +public interface AlterationCountsMapper { + + /** + * Calculate sample-level counts of mutation and discrete CNA alteration events in genes. + * + * @param entrezGeneIds Gene ids to get counts for. + * @param mutationTypes Types of mutations to include in alteration counts. + * @param cnaTypes Types of discrete copy number alteration types to include in alteration counts. + * @param includeDriver Include Variants of Unknown significance. Uses annotations loaded as + * 'custom driver annotations'. + * @param includeVUS Include Variants of Unknown significance. Uses annotations loaded as 'custom + * driver annotations'. + * @param includeUnknownOncogenicity Include variants that are not annotated as driver or VUS. + * Uses annotations loaded as 'custom driver annotations'. + * @param selectedTiers Force alterations assigned to a tier to be interpreted as driver events. + * Uses tier annotations loaded as 'custom driver annotation tiers'. + * @param includeUnknownTier Include mutations that have unspecified tier, or tiers with '', 'NA' + * or 'unknown' in alteration counts + * @param includeGermline Include germline mutations in alteration counts + * @param includeSomatic Include somatic mutations in alteration counts + * @return Gene-level counts of (1) the total number of alterations and (2) the number of altered + * samples. + */ + List getSampleAlterationGeneCounts( + List mutationMolecularProfileCaseIdentifiers, + List cnaMolecularProfileCaseIdentifiers, + List structuralVariantMolecularProfileCaseIdentifiers, + Select entrezGeneIds, + Select mutationTypes, + Select cnaTypes, + boolean includeDriver, + boolean includeVUS, + boolean includeUnknownOncogenicity, + Select selectedTiers, + boolean includeUnknownTier, + boolean includeGermline, + boolean includeSomatic, + boolean includeUnknownStatus); + + /** + * Calculate patient-level counts of mutation and discrete CNA alteration events in genes. + * + * @param entrezGeneIds Gene ids to get counts for. + * @param mutationTypes Types of mutations to include in alteration counts. + * @param cnaTypes Types of discrete copy number alteration types to include in alteration counts. + * @param includeDriver Include Variants of Unknown significance. Uses annotations loaded as + * 'custom driver annotations'. + * @param includeVUS Include Variants of Unknown significance. Uses annotations loaded as 'custom + * driver annotations'. + * @param includeUnknownOncogenicity Include variants that are not annotated as driver or VUS. + * Uses annotations loaded as 'custom driver annotations'. + * @param selectedTiers Force alterations assigned to a tier to be interpreted as driver events. + * Uses tier annotations loaded as 'custom driver annotation tiers'. + * @param includeUnknownTier Include mutations that have unspecified tier, or tiers with '', 'NA' + * or 'unknown' in alteration counts + * @param includeGermline Include germline mutations in alteration counts + * @param includeSomatic Include somatic mutations in alteration counts + * @param includeUnknownStatus Include mutations that have mutation status 'unknown' in alteration + * counts + * @return Gene-level counts of (1) the total number of alterations and (2) the number of altered + * patients. + */ + List getPatientAlterationGeneCounts( + List mutationMolecularProfileCaseIdentifiers, + List cnaMolecularProfileCaseIdentifiers, + List structuralVariantMolecularProfileCaseIdentifiers, + Select entrezGeneIds, + Select mutationTypes, + Select cnaTypes, + boolean includeDriver, + boolean includeVUS, + boolean includeUnknownOncogenicity, + Select selectedTiers, + boolean includeUnknownTier, + boolean includeGermline, + boolean includeSomatic, + boolean includeUnknownStatus); + + // legacy method that returns CopyNumberCountByGene + List getSampleCnaGeneCounts( + List cnaMolecularProfileCaseIdentifiers, + Select entrezGeneIds, + Select cnaTypes, + boolean includeDriver, + boolean includeVUS, + boolean includeUnknownOncogenicity, + Select selectedTiers, + boolean includeUnknownTier); + + // legacy method that returns CopyNumberCountByGene + List getPatientCnaGeneCounts( + List cnaMolecularProfileCaseIdentifiers, + Select entrezGeneIds, + Select cnaTypes, + boolean includeDriver, + boolean includeVUS, + boolean includeUnknownOncogenicity, + Select selectedTiers, + boolean includeUnknownTier); + + List getMolecularProfileCaseInternalIdentifier( + List molecularProfileSampleIdentifiers, String caseType); + + /** + * Calculate sample-level counts of structural variant events. + * + * @param includeDriver Include Variants of Unknown significance. Uses annotations loaded as + * 'custom driver annotations'. + * @param includeVUS Include Variants of Unknown significance. Uses annotations loaded as 'custom + * driver annotations'. + * @param includeUnknownOncogenicity Include variants that are not annotated as driver or VUS. + * Uses annotations loaded as 'custom driver annotations'. + * @param selectedTiers Force alterations assigned to a tier to be interpreted as driver events. + * Uses tier annotations loaded as 'custom driver annotation tiers'. + * @param includeUnknownTier Include mutations that have unspecified tier, or tiers with '', 'NA' + * or 'unknown' in alteration counts + * @param includeGermline Include germline mutations in alteration counts + * @param includeSomatic Include somatic mutations in alteration counts + * @return StructVar-level counts (GeneA::GeneB) of (1) the total number of alterations and (2) + * the number of altered samples. + */ + List getSampleStructuralVariantCounts( + List structuralVariantMolecularProfileCaseIdentifiers, + boolean includeDriver, + boolean includeVUS, + boolean includeUnknownOncogenicity, + Select selectedTiers, + boolean includeUnknownTier, + boolean includeGermline, + boolean includeSomatic, + boolean includeUnknownStatus); + + /** + * Calculate patient-level counts of structural variant events. + * + * @param includeDriver Include Variants of Unknown significance. Uses annotations loaded as + * 'custom driver annotations'. + * @param includeVUS Include Variants of Unknown significance. Uses annotations loaded as 'custom + * driver annotations'. + * @param includeUnknownOncogenicity Include variants that are not annotated as driver or VUS. + * Uses annotations loaded as 'custom driver annotations'. + * @param selectedTiers Force alterations assigned to a tier to be interpreted as driver events. + * Uses tier annotations loaded as 'custom driver annotation tiers'. + * @param includeUnknownTier Include mutations that have unspecified tier, or tiers with '', 'NA' + * or 'unknown' in alteration counts + * @param includeGermline Include germline mutations in alteration counts + * @param includeSomatic Include somatic mutations in alteration counts + * @return StructVar-level counts (GeneA::GeneB) of (1) the total number of alterations and (2) + * the number of altered patients. + */ + List getPatientStructuralVariantCounts( + List structuralVariantMolecularProfileCaseIdentifiers, + boolean includeDriver, + boolean includeVUS, + boolean includeUnknownOncogenicity, + Select selectedTiers, + boolean includeUnknownTier, + boolean includeGermline, + boolean includeSomatic, + boolean includeUnknownStatus); +} diff --git a/src/main/java/org/cbioportal/legacy/persistence/mybatis/AlterationDriverAnnotationMapper.java b/src/main/java/org/cbioportal/legacy/persistence/mybatis/AlterationDriverAnnotationMapper.java new file mode 100644 index 00000000000..c0a7bf54e39 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/persistence/mybatis/AlterationDriverAnnotationMapper.java @@ -0,0 +1,11 @@ +package org.cbioportal.legacy.persistence.mybatis; + +import java.util.List; +import org.apache.ibatis.annotations.Param; +import org.cbioportal.legacy.model.AlterationDriverAnnotation; + +public interface AlterationDriverAnnotationMapper { + + List getAlterationDriverAnnotations( + @Param("molecularProfileIds") List molecularProfileIds); +} diff --git a/src/main/java/org/cbioportal/legacy/persistence/mybatis/AlterationDriverAnnotationMyBatisRepository.java b/src/main/java/org/cbioportal/legacy/persistence/mybatis/AlterationDriverAnnotationMyBatisRepository.java new file mode 100644 index 00000000000..d117de98f84 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/persistence/mybatis/AlterationDriverAnnotationMyBatisRepository.java @@ -0,0 +1,26 @@ +package org.cbioportal.legacy.persistence.mybatis; + +import java.util.Collections; +import java.util.List; +import org.cbioportal.legacy.model.AlterationDriverAnnotation; +import org.cbioportal.legacy.persistence.AlterationDriverAnnotationRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Repository; + +@Repository +public class AlterationDriverAnnotationMyBatisRepository + implements AlterationDriverAnnotationRepository { + + @Autowired private AlterationDriverAnnotationMapper alterationDriverAnnotationMapper; + + @Override + public List getAlterationDriverAnnotations( + List molecularProfileIds) { + + if (molecularProfileIds == null || molecularProfileIds.isEmpty()) { + return Collections.emptyList(); + } + + return alterationDriverAnnotationMapper.getAlterationDriverAnnotations(molecularProfileIds); + } +} diff --git a/src/main/java/org/cbioportal/legacy/persistence/mybatis/AlterationMyBatisRepository.java b/src/main/java/org/cbioportal/legacy/persistence/mybatis/AlterationMyBatisRepository.java new file mode 100644 index 00000000000..4882f2bdc36 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/persistence/mybatis/AlterationMyBatisRepository.java @@ -0,0 +1,267 @@ +package org.cbioportal.legacy.persistence.mybatis; + +import java.util.*; +import java.util.stream.Collectors; +import org.cbioportal.legacy.model.AlterationCountByGene; +import org.cbioportal.legacy.model.AlterationCountByStructuralVariant; +import org.cbioportal.legacy.model.AlterationFilter; +import org.cbioportal.legacy.model.CNA; +import org.cbioportal.legacy.model.CopyNumberCountByGene; +import org.cbioportal.legacy.model.MolecularProfile; +import org.cbioportal.legacy.model.MolecularProfile.MolecularAlterationType; +import org.cbioportal.legacy.model.MolecularProfileCaseIdentifier; +import org.cbioportal.legacy.model.MutationEventType; +import org.cbioportal.legacy.model.util.Select; +import org.cbioportal.legacy.persistence.AlterationRepository; +import org.cbioportal.legacy.persistence.MolecularProfileRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Repository; + +@Repository +public class AlterationMyBatisRepository implements AlterationRepository { + + @Autowired private AlterationCountsMapper alterationCountsMapper; + @Autowired private MolecularProfileRepository molecularProfileRepository; + + @Override + public List getSampleAlterationGeneCounts( + Set molecularProfileCaseIdentifiers, + Select entrezGeneIds, + AlterationFilter alterationFilter) { + + if ((alterationFilter.getMutationTypeSelect().hasNone() + && alterationFilter.getCNAEventTypeSelect().hasNone() + && !alterationFilter.getStructuralVariants()) + || (molecularProfileCaseIdentifiers == null || molecularProfileCaseIdentifiers.isEmpty()) + || allAlterationsExcludedDriverAnnotation(alterationFilter) + || allAlterationsExcludedMutationStatus(alterationFilter) + || allAlterationsExcludedDriverTierAnnotation(alterationFilter)) { + // We want a mutable empty list: + return new ArrayList<>(); + } + + Set molecularProfileIds = + molecularProfileCaseIdentifiers.stream() + .map(MolecularProfileCaseIdentifier::getMolecularProfileId) + .collect(Collectors.toSet()); + Map profileTypeByProfileId = + molecularProfileRepository.getMolecularProfiles(molecularProfileIds, "SUMMARY").stream() + .collect( + Collectors.toMap( + datum -> datum.getMolecularProfileId().toString(), + MolecularProfile::getMolecularAlterationType)); + Map> + groupedIdentifiersByProfileType = + alterationCountsMapper + .getMolecularProfileCaseInternalIdentifier( + new ArrayList<>(molecularProfileCaseIdentifiers), "SAMPLE_ID") + .stream() + .collect( + Collectors.groupingBy( + e -> profileTypeByProfileId.getOrDefault(e.getMolecularProfileId(), null))); + return alterationCountsMapper.getSampleAlterationGeneCounts( + groupedIdentifiersByProfileType.get(MolecularAlterationType.MUTATION_EXTENDED), + groupedIdentifiersByProfileType.get(MolecularAlterationType.COPY_NUMBER_ALTERATION), + groupedIdentifiersByProfileType.get(MolecularAlterationType.STRUCTURAL_VARIANT), + entrezGeneIds, + createMutationTypeList(alterationFilter), + createCnaTypeList(alterationFilter), + alterationFilter.getIncludeDriver(), + alterationFilter.getIncludeVUS(), + alterationFilter.getIncludeUnknownOncogenicity(), + alterationFilter.getSelectedTiers(), + alterationFilter.getIncludeUnknownTier(), + alterationFilter.getIncludeGermline(), + alterationFilter.getIncludeSomatic(), + alterationFilter.getIncludeUnknownStatus()); + } + + @Override + public List getPatientAlterationGeneCounts( + Set molecularProfileCaseIdentifiers, + Select entrezGeneIds, + AlterationFilter alterationFilter) { + + if ((alterationFilter.getMutationTypeSelect().hasNone() + && alterationFilter.getCNAEventTypeSelect().hasNone() + && !alterationFilter.getStructuralVariants()) + || (molecularProfileCaseIdentifiers == null || molecularProfileCaseIdentifiers.isEmpty()) + || allAlterationsExcludedDriverAnnotation(alterationFilter) + || allAlterationsExcludedMutationStatus(alterationFilter) + || allAlterationsExcludedDriverTierAnnotation(alterationFilter)) { + return Collections.emptyList(); + } + + Set molecularProfileIds = + molecularProfileCaseIdentifiers.stream() + .map(MolecularProfileCaseIdentifier::getMolecularProfileId) + .collect(Collectors.toSet()); + + Map profileTypeByProfileId = + molecularProfileRepository.getMolecularProfiles(molecularProfileIds, "SUMMARY").stream() + .collect( + Collectors.toMap( + datum -> datum.getMolecularProfileId().toString(), + MolecularProfile::getMolecularAlterationType)); + + Map> + groupedIdentifiersByProfileType = + alterationCountsMapper + .getMolecularProfileCaseInternalIdentifier( + new ArrayList<>(molecularProfileCaseIdentifiers), "PATIENT_ID") + .stream() + .collect( + Collectors.groupingBy( + e -> profileTypeByProfileId.getOrDefault(e.getMolecularProfileId(), null))); + + return alterationCountsMapper.getPatientAlterationGeneCounts( + groupedIdentifiersByProfileType.get(MolecularAlterationType.MUTATION_EXTENDED), + groupedIdentifiersByProfileType.get(MolecularAlterationType.COPY_NUMBER_ALTERATION), + groupedIdentifiersByProfileType.get(MolecularAlterationType.STRUCTURAL_VARIANT), + entrezGeneIds, + createMutationTypeList(alterationFilter), + createCnaTypeList(alterationFilter), + alterationFilter.getIncludeDriver(), + alterationFilter.getIncludeVUS(), + alterationFilter.getIncludeUnknownOncogenicity(), + alterationFilter.getSelectedTiers(), + alterationFilter.getIncludeUnknownTier(), + alterationFilter.getIncludeGermline(), + alterationFilter.getIncludeSomatic(), + alterationFilter.getIncludeUnknownStatus()); + } + + @Override + public List getSampleCnaGeneCounts( + Set molecularProfileCaseIdentifiers, + Select entrezGeneIds, + AlterationFilter alterationFilter) { + + if (alterationFilter.getCNAEventTypeSelect().hasNone() + || molecularProfileCaseIdentifiers == null + || allAlterationsExcludedDriverAnnotation(alterationFilter) + || allAlterationsExcludedDriverTierAnnotation(alterationFilter)) { + return Collections.emptyList(); + } + + List molecularProfileCaseInternalIdentifiers = + alterationCountsMapper.getMolecularProfileCaseInternalIdentifier( + new ArrayList<>(molecularProfileCaseIdentifiers), "SAMPLE_ID"); + + return alterationCountsMapper.getSampleCnaGeneCounts( + molecularProfileCaseInternalIdentifiers, + entrezGeneIds, + createCnaTypeList(alterationFilter), + alterationFilter.getIncludeDriver(), + alterationFilter.getIncludeVUS(), + alterationFilter.getIncludeUnknownOncogenicity(), + alterationFilter.getSelectedTiers(), + alterationFilter.getIncludeUnknownTier()); + } + + @Override + public List getPatientCnaGeneCounts( + Set molecularProfileCaseIdentifiers, + Select entrezGeneIds, + AlterationFilter alterationFilter) { + + if (alterationFilter.getCNAEventTypeSelect().hasNone() + || molecularProfileCaseIdentifiers == null + || allAlterationsExcludedDriverAnnotation(alterationFilter) + || allAlterationsExcludedDriverTierAnnotation(alterationFilter)) { + return Collections.emptyList(); + } + List molecularProfileCaseInternalIdentifiers = + alterationCountsMapper.getMolecularProfileCaseInternalIdentifier( + new ArrayList<>(molecularProfileCaseIdentifiers), "PATIENT_ID"); + + return alterationCountsMapper.getPatientCnaGeneCounts( + molecularProfileCaseInternalIdentifiers, + entrezGeneIds, + createCnaTypeList(alterationFilter), + alterationFilter.getIncludeDriver(), + alterationFilter.getIncludeVUS(), + alterationFilter.getIncludeUnknownOncogenicity(), + alterationFilter.getSelectedTiers(), + alterationFilter.getIncludeUnknownTier()); + } + + @Override + public List getSampleStructuralVariantCounts( + Set molecularProfileCaseIdentifiers, + AlterationFilter alterationFilter) { + + if (molecularProfileCaseIdentifiers == null + || molecularProfileCaseIdentifiers.isEmpty() + || allAlterationsExcludedMutationStatus(alterationFilter)) { + return Collections.emptyList(); + } + + return alterationCountsMapper.getSampleStructuralVariantCounts( + new ArrayList<>(molecularProfileCaseIdentifiers), + alterationFilter.getIncludeDriver(), + alterationFilter.getIncludeVUS(), + alterationFilter.getIncludeUnknownOncogenicity(), + alterationFilter.getSelectedTiers(), + alterationFilter.getIncludeUnknownTier(), + alterationFilter.getIncludeGermline(), + alterationFilter.getIncludeSomatic(), + alterationFilter.getIncludeUnknownStatus()); + } + + @Override + public List getPatientStructuralVariantCounts( + Set molecularProfileCaseIdentifiers, + AlterationFilter alterationFilter) { + + if (molecularProfileCaseIdentifiers == null + || molecularProfileCaseIdentifiers.isEmpty() + || allAlterationsExcludedMutationStatus(alterationFilter)) { + return Collections.emptyList(); + } + + return alterationCountsMapper.getPatientStructuralVariantCounts( + new ArrayList<>(molecularProfileCaseIdentifiers), + alterationFilter.getIncludeDriver(), + alterationFilter.getIncludeVUS(), + alterationFilter.getIncludeUnknownOncogenicity(), + alterationFilter.getSelectedTiers(), + alterationFilter.getIncludeUnknownTier(), + alterationFilter.getIncludeGermline(), + alterationFilter.getIncludeSomatic(), + alterationFilter.getIncludeUnknownStatus()); + } + + private Select createCnaTypeList(final AlterationFilter alterationFilter) { + if (alterationFilter.getCNAEventTypeSelect().hasNone()) return Select.none(); + if (alterationFilter.getCNAEventTypeSelect().hasAll()) return Select.all(); + return alterationFilter.getCNAEventTypeSelect().map(CNA::getCode); + } + + private Select createMutationTypeList(final AlterationFilter alterationFilter) { + if (alterationFilter.getMutationTypeSelect().hasNone()) return Select.none(); + if (alterationFilter.getMutationTypeSelect().hasAll()) return Select.all(); + Select mappedMutationTypes = + alterationFilter.getMutationTypeSelect().map(MutationEventType::getMutationType); + mappedMutationTypes.inverse(alterationFilter.getMutationTypeSelect().inverse()); + + return mappedMutationTypes; + } + + private boolean allAlterationsExcludedMutationStatus(AlterationFilter alterationFilter) { + return !alterationFilter.getIncludeGermline() + && !alterationFilter.getIncludeSomatic() + && !alterationFilter.getIncludeUnknownStatus(); + } + + private boolean allAlterationsExcludedDriverAnnotation(AlterationFilter alterationFilter) { + return !alterationFilter.getIncludeDriver() + && !alterationFilter.getIncludeVUS() + && !alterationFilter.getIncludeUnknownOncogenicity(); + } + + private boolean allAlterationsExcludedDriverTierAnnotation(AlterationFilter alterationFilter) { + return alterationFilter.getSelectedTiers().hasNone() + && !alterationFilter.getIncludeUnknownTier(); + } +} diff --git a/src/main/java/org/cbioportal/legacy/persistence/mybatis/CancerTypeMapper.java b/src/main/java/org/cbioportal/legacy/persistence/mybatis/CancerTypeMapper.java new file mode 100644 index 00000000000..9241f1e3678 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/persistence/mybatis/CancerTypeMapper.java @@ -0,0 +1,15 @@ +package org.cbioportal.legacy.persistence.mybatis; + +import java.util.List; +import org.cbioportal.legacy.model.TypeOfCancer; +import org.cbioportal.legacy.model.meta.BaseMeta; + +public interface CancerTypeMapper { + + List getAllCancerTypes( + String projection, Integer limit, Integer offset, String sortBy, String direction); + + BaseMeta getMetaCancerTypes(); + + TypeOfCancer getCancerType(String cancerTypeId, String projection); +} diff --git a/src/main/java/org/cbioportal/legacy/persistence/mybatis/CancerTypeMyBatisRepository.java b/src/main/java/org/cbioportal/legacy/persistence/mybatis/CancerTypeMyBatisRepository.java new file mode 100644 index 00000000000..1493c93e5e3 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/persistence/mybatis/CancerTypeMyBatisRepository.java @@ -0,0 +1,34 @@ +package org.cbioportal.legacy.persistence.mybatis; + +import java.util.List; +import org.cbioportal.legacy.model.TypeOfCancer; +import org.cbioportal.legacy.model.meta.BaseMeta; +import org.cbioportal.legacy.persistence.CancerTypeRepository; +import org.cbioportal.legacy.persistence.PersistenceConstants; +import org.cbioportal.legacy.persistence.mybatis.util.PaginationCalculator; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Repository; + +@Repository +public class CancerTypeMyBatisRepository implements CancerTypeRepository { + + @Autowired private CancerTypeMapper cancerTypeMapper; + + @Override + public List getAllCancerTypes( + String projection, Integer pageSize, Integer pageNumber, String sortBy, String direction) { + + return cancerTypeMapper.getAllCancerTypes( + projection, pageSize, PaginationCalculator.offset(pageSize, pageNumber), sortBy, direction); + } + + @Override + public BaseMeta getMetaCancerTypes() { + return cancerTypeMapper.getMetaCancerTypes(); + } + + @Override + public TypeOfCancer getCancerType(String cancerTypeId) { + return cancerTypeMapper.getCancerType(cancerTypeId, PersistenceConstants.DETAILED_PROJECTION); + } +} diff --git a/src/main/java/org/cbioportal/legacy/persistence/mybatis/ClinicalAttributeMapper.java b/src/main/java/org/cbioportal/legacy/persistence/mybatis/ClinicalAttributeMapper.java new file mode 100644 index 00000000000..29396a09d58 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/persistence/mybatis/ClinicalAttributeMapper.java @@ -0,0 +1,30 @@ +package org.cbioportal.legacy.persistence.mybatis; + +import java.util.List; +import org.cbioportal.legacy.model.ClinicalAttribute; +import org.cbioportal.legacy.model.ClinicalAttributeCount; +import org.cbioportal.legacy.model.meta.BaseMeta; + +public interface ClinicalAttributeMapper { + + List getClinicalAttributes( + List studyIds, + String projection, + Integer limit, + Integer offset, + String sortBy, + String direction); + + BaseMeta getMetaClinicalAttributes(List studyIds); + + ClinicalAttribute getClinicalAttribute( + String studyId, String clinicalAttributeId, String projection); + + List getClinicalAttributeCountsBySampleIds( + List studyIds, List sampleIds); + + List getClinicalAttributeCountsBySampleListId(String sampleListId); + + List getClinicalAttributesByStudyIdsAndAttributeIds( + List studyIds, List attributeIds); +} diff --git a/src/main/java/org/cbioportal/legacy/persistence/mybatis/ClinicalAttributeMyBatisRepository.java b/src/main/java/org/cbioportal/legacy/persistence/mybatis/ClinicalAttributeMyBatisRepository.java new file mode 100644 index 00000000000..c00597282e0 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/persistence/mybatis/ClinicalAttributeMyBatisRepository.java @@ -0,0 +1,101 @@ +package org.cbioportal.legacy.persistence.mybatis; + +import java.util.Arrays; +import java.util.List; +import org.cbioportal.legacy.model.ClinicalAttribute; +import org.cbioportal.legacy.model.ClinicalAttributeCount; +import org.cbioportal.legacy.model.meta.BaseMeta; +import org.cbioportal.legacy.persistence.ClinicalAttributeRepository; +import org.cbioportal.legacy.persistence.PersistenceConstants; +import org.cbioportal.legacy.persistence.mybatis.util.PaginationCalculator; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Repository; + +@Repository +public class ClinicalAttributeMyBatisRepository implements ClinicalAttributeRepository { + + @Autowired private ClinicalAttributeMapper clinicalAttributeMapper; + + @Override + public List getAllClinicalAttributes( + String projection, Integer pageSize, Integer pageNumber, String sortBy, String direction) { + + return clinicalAttributeMapper.getClinicalAttributes( + null, + projection, + pageSize, + PaginationCalculator.offset(pageSize, pageNumber), + sortBy, + direction); + } + + @Override + public BaseMeta getMetaClinicalAttributes() { + + return clinicalAttributeMapper.getMetaClinicalAttributes(null); + } + + @Override + public ClinicalAttribute getClinicalAttribute(String studyId, String clinicalAttributeId) { + + return clinicalAttributeMapper.getClinicalAttribute( + studyId, clinicalAttributeId, PersistenceConstants.DETAILED_PROJECTION); + } + + @Override + public List getAllClinicalAttributesInStudy( + String studyId, + String projection, + Integer pageSize, + Integer pageNumber, + String sortBy, + String direction) { + + return clinicalAttributeMapper.getClinicalAttributes( + Arrays.asList(studyId), + projection, + pageSize, + PaginationCalculator.offset(pageSize, pageNumber), + sortBy, + direction); + } + + @Override + public BaseMeta getMetaClinicalAttributesInStudy(String studyId) { + + return clinicalAttributeMapper.getMetaClinicalAttributes(Arrays.asList(studyId)); + } + + @Override + public List fetchClinicalAttributes(List studyIds, String projection) { + + return clinicalAttributeMapper.getClinicalAttributes(studyIds, projection, 0, 0, null, null); + } + + @Override + public BaseMeta fetchMetaClinicalAttributes(List studyIds) { + + return clinicalAttributeMapper.getMetaClinicalAttributes(studyIds); + } + + @Override + public List getClinicalAttributeCountsBySampleIds( + List studyIds, List sampleIds) { + + return clinicalAttributeMapper.getClinicalAttributeCountsBySampleIds(studyIds, sampleIds); + } + + @Override + public List getClinicalAttributeCountsBySampleListId( + String sampleListId) { + + return clinicalAttributeMapper.getClinicalAttributeCountsBySampleListId(sampleListId); + } + + @Override + public List getClinicalAttributesByStudyIdsAndAttributeIds( + List studyIds, List attributeIds) { + return clinicalAttributeMapper.getClinicalAttributesByStudyIdsAndAttributeIds( + studyIds, attributeIds); + } +} diff --git a/src/main/java/org/cbioportal/legacy/persistence/mybatis/ClinicalDataMapper.java b/src/main/java/org/cbioportal/legacy/persistence/mybatis/ClinicalDataMapper.java new file mode 100644 index 00000000000..7f3ff097236 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/persistence/mybatis/ClinicalDataMapper.java @@ -0,0 +1,87 @@ +package org.cbioportal.legacy.persistence.mybatis; + +import java.util.List; +import org.cbioportal.legacy.model.ClinicalData; +import org.cbioportal.legacy.model.ClinicalDataCount; +import org.cbioportal.legacy.model.meta.BaseMeta; + +public interface ClinicalDataMapper { + + List getSampleClinicalData( + List studyIds, + List sampleIds, + List attributeIds, + String projection, + Integer limit, + Integer offset, + String sortBy, + String direction); + + BaseMeta getMetaSampleClinicalData( + List studyIds, List sampleIds, List attributeIds); + + List getPatientClinicalData( + List studyIds, + List patientIds, + List attributeIds, + String projection, + Integer limit, + Integer offset, + String sortBy, + String direction); + + List getSampleClinicalTable( + List studyIds, + List sampleIds, + String projection, + Integer limit, + Integer offset, + String searchTerm, + String sortByAttrId, + Boolean sortAttrIsNumber, + Boolean sortIsPatientAttr, + String direction); + + Integer getSampleClinicalTableCount( + List studyIds, + List sampleIds, + String projection, + String searchTerm, + String sortBy, + String direction); + + BaseMeta getMetaPatientClinicalData( + List studyIds, List patientIds, List attributeIds); + + List fetchSampleClinicalDataCounts( + List studyIds, List sampleIds, List attributeIds); + + List fetchPatientClinicalDataCounts( + List studyIds, List patientIds, List attributeIds, String projection); + + List getPatientClinicalDataDetailedToSample( + List studyIds, + List patientIds, + List attributeIds, + String projection, + Integer limit, + Integer offset, + String sortBy, + String direction); + + List getVisibleSampleInternalIdsForClinicalTable( + List studyIds, + List sampleIds, + String projection, + Integer limit, + Integer offset, + String searchTerm, + String sortAttrId, + Boolean sortAttrIsNumber, + Boolean sortIsPatientAttr, + String direction); + + List getSampleClinicalDataBySampleInternalIds(List sampleInternalIds); + + List getPatientClinicalDataBySampleInternalIds(List sampleInternalIds); +} diff --git a/src/main/java/org/cbioportal/legacy/persistence/mybatis/ClinicalDataMyBatisRepository.java b/src/main/java/org/cbioportal/legacy/persistence/mybatis/ClinicalDataMyBatisRepository.java new file mode 100644 index 00000000000..ee8882e8c3c --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/persistence/mybatis/ClinicalDataMyBatisRepository.java @@ -0,0 +1,330 @@ +package org.cbioportal.legacy.persistence.mybatis; + +import java.util.*; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import org.cbioportal.legacy.model.ClinicalAttribute; +import org.cbioportal.legacy.model.ClinicalData; +import org.cbioportal.legacy.model.ClinicalDataCount; +import org.cbioportal.legacy.model.Patient; +import org.cbioportal.legacy.model.meta.BaseMeta; +import org.cbioportal.legacy.persistence.ClinicalAttributeRepository; +import org.cbioportal.legacy.persistence.ClinicalDataRepository; +import org.cbioportal.legacy.persistence.PatientRepository; +import org.cbioportal.legacy.persistence.PersistenceConstants; +import org.cbioportal.legacy.persistence.mybatis.util.PaginationCalculator; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Repository; +import org.springframework.util.Assert; + +@Repository +public class ClinicalDataMyBatisRepository implements ClinicalDataRepository { + + @Autowired private ClinicalDataMapper clinicalDataMapper; + @Autowired private PatientRepository patientRepository; + @Autowired private ClinicalAttributeRepository clinicalAttributeRepository; + + @Override + public List getAllClinicalDataOfSampleInStudy( + String studyId, + String sampleId, + String attributeId, + String projection, + Integer pageSize, + Integer pageNumber, + String sortBy, + String direction) { + + return clinicalDataMapper.getSampleClinicalData( + Arrays.asList(studyId), + Arrays.asList(sampleId), + attributeId != null ? Arrays.asList(attributeId) : null, + projection, + pageSize, + PaginationCalculator.offset(pageSize, pageNumber), + sortBy, + direction); + } + + @Override + public BaseMeta getMetaSampleClinicalData(String studyId, String sampleId, String attributeId) { + return clinicalDataMapper.getMetaSampleClinicalData( + Arrays.asList(studyId), + Arrays.asList(sampleId), + attributeId != null ? Arrays.asList(attributeId) : null); + } + + @Override + public List getAllClinicalDataOfPatientInStudy( + String studyId, + String patientId, + String attributeId, + String projection, + Integer pageSize, + Integer pageNumber, + String sortBy, + String direction) { + + return clinicalDataMapper.getPatientClinicalData( + Arrays.asList(studyId), + Arrays.asList(patientId), + attributeId != null ? Arrays.asList(attributeId) : null, + projection, + pageSize, + PaginationCalculator.offset(pageSize, pageNumber), + sortBy, + direction); + } + + @Override + public BaseMeta getMetaPatientClinicalData(String studyId, String patientId, String attributeId) { + return clinicalDataMapper.getMetaPatientClinicalData( + Arrays.asList(studyId), + Arrays.asList(patientId), + attributeId != null ? Arrays.asList(attributeId) : null); + } + + @Override + public List getAllClinicalDataInStudy( + String studyId, + String attributeId, + String clinicalDataType, + String projection, + Integer pageSize, + Integer pageNumber, + String sortBy, + String direction) { + + if (clinicalDataType.equals(PersistenceConstants.SAMPLE_CLINICAL_DATA_TYPE)) { + return clinicalDataMapper.getSampleClinicalData( + Arrays.asList(studyId), + null, + attributeId != null ? Arrays.asList(attributeId) : null, + projection, + pageSize, + PaginationCalculator.offset(pageSize, pageNumber), + sortBy, + direction); + } else { + return clinicalDataMapper.getPatientClinicalData( + Arrays.asList(studyId), + null, + attributeId != null ? Arrays.asList(attributeId) : null, + projection, + pageSize, + PaginationCalculator.offset(pageSize, pageNumber), + sortBy, + direction); + } + } + + @Override + public BaseMeta getMetaAllClinicalData( + String studyId, String attributeId, String clinicalDataType) { + + BaseMeta baseMeta = new BaseMeta(); + + if (clinicalDataType.equals(PersistenceConstants.SAMPLE_CLINICAL_DATA_TYPE)) { + baseMeta.setTotalCount( + clinicalDataMapper + .getMetaSampleClinicalData( + Arrays.asList(studyId), + null, + attributeId != null ? Arrays.asList(attributeId) : null) + .getTotalCount()); + } else { + baseMeta.setTotalCount( + clinicalDataMapper + .getMetaPatientClinicalData( + Arrays.asList(studyId), + null, + attributeId != null ? Arrays.asList(attributeId) : null) + .getTotalCount()); + } + + return baseMeta; + } + + @Override + public List fetchAllClinicalDataInStudy( + String studyId, + List ids, + List attributeIds, + String clinicalDataType, + String projection) { + + if (clinicalDataType.equals(PersistenceConstants.SAMPLE_CLINICAL_DATA_TYPE)) { + return clinicalDataMapper.getSampleClinicalData( + Arrays.asList(studyId), ids, attributeIds, projection, 0, 0, null, null); + } else { + return clinicalDataMapper.getPatientClinicalData( + Arrays.asList(studyId), ids, attributeIds, projection, 0, 0, null, null); + } + } + + @Override + public BaseMeta fetchMetaClinicalDataInStudy( + String studyId, List ids, List attributeIds, String clinicalDataType) { + + BaseMeta baseMeta = new BaseMeta(); + + if (clinicalDataType.equals(PersistenceConstants.SAMPLE_CLINICAL_DATA_TYPE)) { + baseMeta.setTotalCount( + clinicalDataMapper + .getMetaSampleClinicalData(Arrays.asList(studyId), ids, attributeIds) + .getTotalCount()); + } else { + baseMeta.setTotalCount( + clinicalDataMapper + .getMetaPatientClinicalData(Arrays.asList(studyId), ids, attributeIds) + .getTotalCount()); + } + + return baseMeta; + } + + @Override + public List fetchClinicalData( + List studyIds, + List ids, + List attributeIds, + String clinicalDataType, + String projection) { + if (ids.isEmpty()) { + return new ArrayList<>(); + } + if (clinicalDataType.equals(PersistenceConstants.SAMPLE_CLINICAL_DATA_TYPE)) { + return clinicalDataMapper.getSampleClinicalData( + studyIds, ids, attributeIds, projection, 0, 0, null, null); + } else { + return clinicalDataMapper.getPatientClinicalData( + studyIds, ids, attributeIds, projection, 0, 0, null, null); + } + } + + public List getVisibleSampleInternalIdsForClinicalTable( + List studyIds, + List sampleIds, + Integer pageSize, + Integer pageNumber, + String searchTerm, + String sortAttrId, + String direction) { + if (sampleIds.isEmpty()) { + return new ArrayList<>(); + } + Integer offset = PaginationCalculator.offset(pageSize, pageNumber); + Boolean sortAttrIsNumber = null; + Boolean sortIsPatientAttr = null; + + if (sortAttrId != null) { + if (sortAttrId.equals("patientId") || sortAttrId.equals("sampleId")) { + // these are both false because patientId and sampleId are actually not + // clinical attributes and are never numbers + sortAttrIsNumber = false; + sortIsPatientAttr = false; + } else { + ClinicalAttribute clinicalAttributeMeta = getClinicalAttributeMeta(studyIds, sortAttrId); + sortAttrIsNumber = clinicalAttributeMeta.getDatatype().equals("NUMBER"); + sortIsPatientAttr = clinicalAttributeMeta.getPatientAttribute(); + } + } + + return clinicalDataMapper.getVisibleSampleInternalIdsForClinicalTable( + studyIds, + sampleIds, + "SUMMARY", + pageSize, + offset, + searchTerm, + sortAttrId, + sortAttrIsNumber, + sortIsPatientAttr, + direction); + } + + private ClinicalAttribute getClinicalAttributeMeta(List studyIds, String attrId) { + Assert.notNull(studyIds, "Arguments may not be null"); + Assert.notNull(attrId, "Arguments may not be null"); + Stream uniqueStudyIds = studyIds.stream().distinct(); + Optional clinicalAttributeMeta = + uniqueStudyIds + .map(studyId -> clinicalAttributeRepository.getClinicalAttribute(studyId, attrId)) + .filter(Objects::nonNull) + .findFirst(); + Assert.isTrue( + clinicalAttributeMeta.isPresent(), + "Clinical Attribute " + + attrId + + " was not found in studies " + + studyIds.stream().collect(Collectors.joining(", "))); + return clinicalAttributeMeta.get(); + } + + @Override + public BaseMeta fetchMetaClinicalData( + List studyIds, List ids, List attributeIds, String clinicalDataType) { + + BaseMeta baseMeta = new BaseMeta(); + + if (clinicalDataType.equals(PersistenceConstants.SAMPLE_CLINICAL_DATA_TYPE)) { + baseMeta.setTotalCount( + clinicalDataMapper + .getMetaSampleClinicalData(studyIds, ids, attributeIds) + .getTotalCount()); + } else { + baseMeta.setTotalCount( + clinicalDataMapper + .getMetaPatientClinicalData(studyIds, ids, attributeIds) + .getTotalCount()); + } + + return baseMeta; + } + + @Override + public List fetchClinicalDataCounts( + List studyIds, + List sampleIds, + List attributeIds, + String clinicalDataType, + String projection) { + + if (clinicalDataType.equals(PersistenceConstants.SAMPLE_CLINICAL_DATA_TYPE)) { + return clinicalDataMapper.fetchSampleClinicalDataCounts(studyIds, sampleIds, attributeIds); + } else { + List patients = patientRepository.getPatientsOfSamples(studyIds, sampleIds); + List patientStudyIds = new ArrayList<>(); + patients.forEach(p -> patientStudyIds.add(p.getCancerStudyIdentifier())); + return clinicalDataMapper.fetchPatientClinicalDataCounts( + patientStudyIds, + patients.stream().map(Patient::getStableId).collect(Collectors.toList()), + attributeIds, + projection); + } + } + + @Override + public List getPatientClinicalDataDetailedToSample( + List studyIds, List patientIds, List attributeIds) { + + return clinicalDataMapper.getPatientClinicalDataDetailedToSample( + studyIds, patientIds, attributeIds, "SUMMARY", 0, 0, null, null); + } + + @Override + public List getSampleClinicalDataBySampleInternalIds( + List sampleInternalIds) { + return sampleInternalIds == null || sampleInternalIds.isEmpty() + ? new ArrayList<>() + : clinicalDataMapper.getSampleClinicalDataBySampleInternalIds(sampleInternalIds); + } + + @Override + public List getPatientClinicalDataBySampleInternalIds( + List sampleInternalIds) { + return sampleInternalIds == null || sampleInternalIds.isEmpty() + ? new ArrayList<>() + : clinicalDataMapper.getPatientClinicalDataBySampleInternalIds(sampleInternalIds); + } +} diff --git a/src/main/java/org/cbioportal/legacy/persistence/mybatis/ClinicalEventMapper.java b/src/main/java/org/cbioportal/legacy/persistence/mybatis/ClinicalEventMapper.java new file mode 100644 index 00000000000..e72c62d5168 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/persistence/mybatis/ClinicalEventMapper.java @@ -0,0 +1,44 @@ +package org.cbioportal.legacy.persistence.mybatis; + +import java.util.List; +import org.cbioportal.legacy.model.ClinicalEvent; +import org.cbioportal.legacy.model.ClinicalEventData; +import org.cbioportal.legacy.model.meta.BaseMeta; + +public interface ClinicalEventMapper { + + List getPatientClinicalEvent( + String studyId, + String patientId, + String projection, + Integer limit, + Integer offset, + String sortBy, + String direction); + + BaseMeta getMetaPatientClinicalEvent(String studyId, String patientId); + + List getDataOfClinicalEvents(List clinicalEventIds); + + List getStudyClinicalEvent( + String studyId, + String projection, + Integer limit, + Integer offset, + String sortBy, + String direction); + + BaseMeta getMetaClinicalEvent(String studyId); + + List getSamplesOfPatientsPerEventType( + List studyIds, List sampleIds); + + List getPatientsDistinctClinicalEventInStudies( + List studyIds, List patientIds); + + List getTimelineEvents( + List studyIds, List patientIds, List clinicalEvents); + + List getClinicalEventsMeta( + List studyIds, List patientIds, List clinicalEvents); +} diff --git a/src/main/java/org/cbioportal/legacy/persistence/mybatis/ClinicalEventMyBatisRepository.java b/src/main/java/org/cbioportal/legacy/persistence/mybatis/ClinicalEventMyBatisRepository.java new file mode 100644 index 00000000000..2c0491fdda7 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/persistence/mybatis/ClinicalEventMyBatisRepository.java @@ -0,0 +1,103 @@ +package org.cbioportal.legacy.persistence.mybatis; + +import static java.util.stream.Collectors.groupingBy; + +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; +import org.cbioportal.legacy.model.ClinicalEvent; +import org.cbioportal.legacy.model.ClinicalEventData; +import org.cbioportal.legacy.model.meta.BaseMeta; +import org.cbioportal.legacy.persistence.ClinicalEventRepository; +import org.cbioportal.legacy.persistence.mybatis.util.PaginationCalculator; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Repository; + +@Repository +public class ClinicalEventMyBatisRepository implements ClinicalEventRepository { + + @Autowired private ClinicalEventMapper clinicalEventMapper; + + @Override + public List getAllClinicalEventsOfPatientInStudy( + String studyId, + String patientId, + String projection, + Integer pageSize, + Integer pageNumber, + String sortBy, + String direction) { + return clinicalEventMapper.getPatientClinicalEvent( + studyId, + patientId, + projection, + pageSize, + PaginationCalculator.offset(pageSize, pageNumber), + sortBy, + direction); + } + + @Override + public BaseMeta getMetaPatientClinicalEvents(String studyId, String patientId) { + + return clinicalEventMapper.getMetaPatientClinicalEvent(studyId, patientId); + } + + @Override + public List getDataOfClinicalEvents(List clinicalEventIds) { + + return clinicalEventMapper.getDataOfClinicalEvents(clinicalEventIds); + } + + @Override + public List getAllClinicalEventsInStudy( + String studyId, + String projection, + Integer pageSize, + Integer pageNumber, + String sortBy, + String direction) { + return clinicalEventMapper.getStudyClinicalEvent( + studyId, + projection, + pageSize, + PaginationCalculator.offset(pageSize, pageNumber), + sortBy, + direction); + } + + @Override + public BaseMeta getMetaClinicalEvents(String studyId) { + + return clinicalEventMapper.getMetaClinicalEvent(studyId); + } + + @Override + public Map> getSamplesOfPatientsPerEventTypeInStudy( + List studyIds, List sampleIds) { + return clinicalEventMapper.getSamplesOfPatientsPerEventType(studyIds, sampleIds).stream() + .collect( + groupingBy( + ClinicalEvent::getEventType, + Collectors.mapping(ClinicalEvent::getUniqueSampleKey, Collectors.toSet()))); + } + + @Override + public List getPatientsDistinctClinicalEventInStudies( + List studyIds, List patientIds) { + return clinicalEventMapper.getPatientsDistinctClinicalEventInStudies(studyIds, patientIds); + } + + @Override + public List getTimelineEvents( + List studyIds, List patientIds, List clinicalEvents) { + return clinicalEventMapper.getTimelineEvents(studyIds, patientIds, clinicalEvents); + } + + @Override + public List getClinicalEventsMeta( + List studyIds, List patientIds, List clinicalEvents) { + return clinicalEventMapper.getClinicalEventsMeta(studyIds, patientIds, clinicalEvents); + } +} diff --git a/src/main/java/org/cbioportal/legacy/persistence/mybatis/CopyNumberSegmentMapper.java b/src/main/java/org/cbioportal/legacy/persistence/mybatis/CopyNumberSegmentMapper.java new file mode 100644 index 00000000000..e2448868ee2 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/persistence/mybatis/CopyNumberSegmentMapper.java @@ -0,0 +1,27 @@ +package org.cbioportal.legacy.persistence.mybatis; + +import java.util.List; +import org.cbioportal.legacy.model.CopyNumberSeg; +import org.cbioportal.legacy.model.meta.BaseMeta; + +public interface CopyNumberSegmentMapper { + + List getCopyNumberSegments( + List studyIds, + List sampleIds, + String chromosome, + String projection, + Integer limit, + Integer offset, + String sortBy, + String direction); + + List getSamplesWithCopyNumberSegments( + List studyIds, List sampleIds, String chromosome); + + BaseMeta getMetaCopyNumberSegments( + List studyIds, List sampleIds, String chromosome); + + List getCopyNumberSegmentsBySampleListId( + String studyId, String sampleListId, String chromosome, String projection); +} diff --git a/src/main/java/org/cbioportal/legacy/persistence/mybatis/CopyNumberSegmentMyBatisRepository.java b/src/main/java/org/cbioportal/legacy/persistence/mybatis/CopyNumberSegmentMyBatisRepository.java new file mode 100644 index 00000000000..4409dc09d7e --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/persistence/mybatis/CopyNumberSegmentMyBatisRepository.java @@ -0,0 +1,76 @@ +package org.cbioportal.legacy.persistence.mybatis; + +import java.util.Arrays; +import java.util.List; +import org.cbioportal.legacy.model.CopyNumberSeg; +import org.cbioportal.legacy.model.meta.BaseMeta; +import org.cbioportal.legacy.persistence.CopyNumberSegmentRepository; +import org.cbioportal.legacy.persistence.mybatis.util.PaginationCalculator; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Repository; + +@Repository +public class CopyNumberSegmentMyBatisRepository implements CopyNumberSegmentRepository { + + @Autowired private CopyNumberSegmentMapper copyNumberSegmentMapper; + + @Override + public List getCopyNumberSegmentsInSampleInStudy( + String studyId, + String sampleId, + String chromosome, + String projection, + Integer pageSize, + Integer pageNumber, + String sortBy, + String direction) { + + return copyNumberSegmentMapper.getCopyNumberSegments( + Arrays.asList(studyId), + Arrays.asList(sampleId), + chromosome, + projection, + pageSize, + PaginationCalculator.offset(pageSize, pageNumber), + sortBy, + direction); + } + + @Override + public BaseMeta getMetaCopyNumberSegmentsInSampleInStudy( + String studyId, String sampleId, String chromosome) { + + return copyNumberSegmentMapper.getMetaCopyNumberSegments( + Arrays.asList(studyId), Arrays.asList(sampleId), chromosome); + } + + @Override + public List fetchSamplesWithCopyNumberSegments( + List studyIds, List sampleIds, String chromosome) { + return copyNumberSegmentMapper.getSamplesWithCopyNumberSegments( + studyIds, sampleIds, chromosome); + } + + @Override + public List fetchCopyNumberSegments( + List studyIds, List sampleIds, String chromosome, String projection) { + + return copyNumberSegmentMapper.getCopyNumberSegments( + studyIds, sampleIds, chromosome, projection, 0, 0, null, null); + } + + @Override + public BaseMeta fetchMetaCopyNumberSegments( + List studyIds, List sampleIds, String chromosome) { + + return copyNumberSegmentMapper.getMetaCopyNumberSegments(studyIds, sampleIds, chromosome); + } + + @Override + public List getCopyNumberSegmentsBySampleListId( + String studyId, String sampleListId, String chromosome, String projection) { + + return copyNumberSegmentMapper.getCopyNumberSegmentsBySampleListId( + studyId, sampleListId, chromosome, projection); + } +} diff --git a/src/main/java/org/cbioportal/legacy/persistence/mybatis/CosmicCountMapper.java b/src/main/java/org/cbioportal/legacy/persistence/mybatis/CosmicCountMapper.java new file mode 100644 index 00000000000..df8aa1fce9b --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/persistence/mybatis/CosmicCountMapper.java @@ -0,0 +1,9 @@ +package org.cbioportal.legacy.persistence.mybatis; + +import java.util.List; +import org.cbioportal.legacy.model.CosmicMutation; + +public interface CosmicCountMapper { + + List getCosmicCountsByKeywords(List keywords); +} diff --git a/src/main/java/org/cbioportal/legacy/persistence/mybatis/CosmicCountMyBatisRepository.java b/src/main/java/org/cbioportal/legacy/persistence/mybatis/CosmicCountMyBatisRepository.java new file mode 100644 index 00000000000..4f2daaccfe8 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/persistence/mybatis/CosmicCountMyBatisRepository.java @@ -0,0 +1,18 @@ +package org.cbioportal.legacy.persistence.mybatis; + +import java.util.List; +import org.cbioportal.legacy.model.CosmicMutation; +import org.cbioportal.legacy.persistence.CosmicCountRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Repository; + +@Repository +public class CosmicCountMyBatisRepository implements CosmicCountRepository { + + @Autowired private CosmicCountMapper cosmicCountMapper; + + public List fetchCosmicCountsByKeywords(List keywords) { + + return cosmicCountMapper.getCosmicCountsByKeywords(keywords); + } +} diff --git a/src/main/java/org/cbioportal/legacy/persistence/mybatis/DataAccessTokenMapper.java b/src/main/java/org/cbioportal/legacy/persistence/mybatis/DataAccessTokenMapper.java new file mode 100644 index 00000000000..ffd0bac0621 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/persistence/mybatis/DataAccessTokenMapper.java @@ -0,0 +1,17 @@ +package org.cbioportal.legacy.persistence.mybatis; + +import java.util.List; +import org.cbioportal.legacy.model.DataAccessToken; + +public interface DataAccessTokenMapper { + + List getAllDataAccessTokensForUsername(String username); + + DataAccessToken getDataAccessToken(String token); + + void addDataAccessToken(DataAccessToken token); + + void removeDataAccessToken(String token); + + void removeAllDataAccessTokensForUsername(String username); +} diff --git a/src/main/java/org/cbioportal/legacy/persistence/mybatis/DataAccessTokenMyBatisRepository.java b/src/main/java/org/cbioportal/legacy/persistence/mybatis/DataAccessTokenMyBatisRepository.java new file mode 100644 index 00000000000..e493b4df80c --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/persistence/mybatis/DataAccessTokenMyBatisRepository.java @@ -0,0 +1,38 @@ +package org.cbioportal.legacy.persistence.mybatis; + +import java.util.List; +import org.cbioportal.legacy.model.DataAccessToken; +import org.cbioportal.legacy.persistence.DataAccessTokenRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Repository; + +@Repository +public class DataAccessTokenMyBatisRepository implements DataAccessTokenRepository { + + @Autowired private DataAccessTokenMapper dataAccessTokenMapper; + + @Override + public List getAllDataAccessTokensForUsername(String username) { + return dataAccessTokenMapper.getAllDataAccessTokensForUsername(username); + } + + @Override + public DataAccessToken getDataAccessToken(String token) { + return dataAccessTokenMapper.getDataAccessToken(token); + } + + @Override + public void addDataAccessToken(DataAccessToken token) { + dataAccessTokenMapper.addDataAccessToken(token); + } + + @Override + public void removeDataAccessToken(String token) { + dataAccessTokenMapper.removeDataAccessToken(token); + } + + @Override + public void removeAllDataAccessTokensForUsername(String username) { + dataAccessTokenMapper.removeAllDataAccessTokensForUsername(username); + } +} diff --git a/src/main/java/org/cbioportal/legacy/persistence/mybatis/DiscreteCopyNumberMapper.java b/src/main/java/org/cbioportal/legacy/persistence/mybatis/DiscreteCopyNumberMapper.java new file mode 100644 index 00000000000..b1cd7a14e68 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/persistence/mybatis/DiscreteCopyNumberMapper.java @@ -0,0 +1,55 @@ +package org.cbioportal.legacy.persistence.mybatis; + +import java.util.List; +import org.cbioportal.legacy.model.CopyNumberCountByGene; +import org.cbioportal.legacy.model.DiscreteCopyNumberData; +import org.cbioportal.legacy.model.GeneFilterQuery; +import org.cbioportal.legacy.model.meta.BaseMeta; + +public interface DiscreteCopyNumberMapper { + + List getDiscreteCopyNumbersBySampleListId( + String molecularProfileId, + String sampleListId, + List entrezGeneIds, + List alterationTypes, + String projection); + + BaseMeta getMetaDiscreteCopyNumbersBySampleListId( + String molecularProfileId, + String sampleListId, + List entrezGeneIds, + List alterationTypes); + + List getDiscreteCopyNumbersBySampleIds( + String molecularProfileId, + List sampleIds, + List entrezGeneIds, + List alterationTypes, + String projection); + + List getDiscreteCopyNumbersInMultipleMolecularProfiles( + List molecularProfileIds, + List sampleIds, + List entrezGeneIds, + List alterationTypes, + String projection); + + List getDiscreteCopyNumbersInMultipleMolecularProfilesByGeneQueries( + List molecularProfileIds, + List sampleIds, + String projection, + List geneQueries); + + BaseMeta getMetaDiscreteCopyNumbersBySampleIds( + String molecularProfileId, + List sampleIds, + List entrezGeneIds, + List alterationTypes); + + List getSampleCountByGeneAndAlterationAndSampleIds( + String molecularProfileId, + List sampleIds, + List entrezGeneIds, + List alterations); +} diff --git a/src/main/java/org/cbioportal/legacy/persistence/mybatis/DiscreteCopyNumberMyBatisRepository.java b/src/main/java/org/cbioportal/legacy/persistence/mybatis/DiscreteCopyNumberMyBatisRepository.java new file mode 100644 index 00000000000..9338a9d77e4 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/persistence/mybatis/DiscreteCopyNumberMyBatisRepository.java @@ -0,0 +1,96 @@ +package org.cbioportal.legacy.persistence.mybatis; + +import java.util.List; +import org.cbioportal.legacy.model.CopyNumberCountByGene; +import org.cbioportal.legacy.model.DiscreteCopyNumberData; +import org.cbioportal.legacy.model.GeneFilterQuery; +import org.cbioportal.legacy.model.meta.BaseMeta; +import org.cbioportal.legacy.persistence.DiscreteCopyNumberRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Repository; + +@Repository +public class DiscreteCopyNumberMyBatisRepository implements DiscreteCopyNumberRepository { + + @Autowired private DiscreteCopyNumberMapper discreteCopyNumberMapper; + + @Override + public List getDiscreteCopyNumbersInMolecularProfileBySampleListId( + String molecularProfileId, + String sampleListId, + List entrezGeneIds, + List alterationTypes, + String projection) { + + return discreteCopyNumberMapper.getDiscreteCopyNumbersBySampleListId( + molecularProfileId, sampleListId, entrezGeneIds, alterationTypes, projection); + } + + @Override + public BaseMeta getMetaDiscreteCopyNumbersInMolecularProfileBySampleListId( + String molecularProfileId, + String sampleListId, + List entrezGeneIds, + List alterationTypes) { + + return discreteCopyNumberMapper.getMetaDiscreteCopyNumbersBySampleListId( + molecularProfileId, sampleListId, entrezGeneIds, alterationTypes); + } + + @Override + public List fetchDiscreteCopyNumbersInMolecularProfile( + String molecularProfileId, + List sampleIds, + List entrezGeneIds, + List alterationTypes, + String projection) { + + return discreteCopyNumberMapper.getDiscreteCopyNumbersBySampleIds( + molecularProfileId, sampleIds, entrezGeneIds, alterationTypes, projection); + } + + @Override + public List getDiscreteCopyNumbersInMultipleMolecularProfiles( + List molecularProfileIds, + List sampleIds, + List entrezGeneIds, + List alterationTypes, + String projection) { + return discreteCopyNumberMapper.getDiscreteCopyNumbersInMultipleMolecularProfiles( + molecularProfileIds, sampleIds, entrezGeneIds, alterationTypes, projection); + } + + @Override + public List + getDiscreteCopyNumbersInMultipleMolecularProfilesByGeneQueries( + List molecularProfileIds, + List sampleIds, + List geneQueries, + String projection) { + + return discreteCopyNumberMapper.getDiscreteCopyNumbersInMultipleMolecularProfilesByGeneQueries( + molecularProfileIds, sampleIds, projection, geneQueries); + } + + @Override + public BaseMeta fetchMetaDiscreteCopyNumbersInMolecularProfile( + String molecularProfileId, + List sampleIds, + List entrezGeneIds, + List alterationTypes) { + + return discreteCopyNumberMapper.getMetaDiscreteCopyNumbersBySampleIds( + molecularProfileId, sampleIds, entrezGeneIds, alterationTypes); + } + + @Override + public List getSampleCountByGeneAndAlterationAndSampleIds( + String molecularProfileId, + List sampleIds, + List entrezGeneIds, + List alterations) { + + return discreteCopyNumberMapper.getSampleCountByGeneAndAlterationAndSampleIds( + molecularProfileId, sampleIds, entrezGeneIds, alterations); + } +} diff --git a/src/main/java/org/cbioportal/legacy/persistence/mybatis/GeneMapper.java b/src/main/java/org/cbioportal/legacy/persistence/mybatis/GeneMapper.java new file mode 100644 index 00000000000..c0cfdfa1901 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/persistence/mybatis/GeneMapper.java @@ -0,0 +1,40 @@ +package org.cbioportal.legacy.persistence.mybatis; + +import java.util.List; +import org.cbioportal.legacy.model.Gene; +import org.cbioportal.legacy.model.GeneAlias; +import org.cbioportal.legacy.model.meta.BaseMeta; + +public interface GeneMapper { + + List getGenes( + String keyword, + String alias, + String projection, + Integer limit, + Integer offset, + String sortBy, + String direction); + + BaseMeta getMetaGenes(String keyword, String alias); + + Gene getGeneByGeneticEntityId(Integer geneticEntityId, String projection); + + Gene getGeneByEntrezGeneId(Integer entrezGeneId, String projection); + + Gene getGeneByHugoGeneSymbol(String hugoGeneSymbol, String projection); + + List getAliasesOfGeneByEntrezGeneId(Integer entrezGeneId); + + List getAliasesOfGeneByHugoGeneSymbol(String hugoGeneSymbol); + + List getAllAliases(); + + List getGenesByEntrezGeneIds(List entrezGeneIds, String projection); + + List getGenesByHugoGeneSymbols(List hugoGeneSymbols, String projection); + + BaseMeta getMetaGenesByEntrezGeneIds(List entrezGeneIds); + + BaseMeta getMetaGenesByHugoGeneSymbols(List hugoGeneSymbols); +} diff --git a/src/main/java/org/cbioportal/legacy/persistence/mybatis/GeneMyBatisRepository.java b/src/main/java/org/cbioportal/legacy/persistence/mybatis/GeneMyBatisRepository.java new file mode 100644 index 00000000000..a0c867e757c --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/persistence/mybatis/GeneMyBatisRepository.java @@ -0,0 +1,103 @@ +package org.cbioportal.legacy.persistence.mybatis; + +import java.util.List; +import org.cbioportal.legacy.model.Gene; +import org.cbioportal.legacy.model.GeneAlias; +import org.cbioportal.legacy.model.meta.BaseMeta; +import org.cbioportal.legacy.persistence.GeneRepository; +import org.cbioportal.legacy.persistence.PersistenceConstants; +import org.cbioportal.legacy.persistence.mybatis.util.PaginationCalculator; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Repository; + +@Repository +public class GeneMyBatisRepository implements GeneRepository { + + @Autowired private GeneMapper geneMapper; + + @Override + public List getAllGenes( + String keyword, + String alias, + String projection, + Integer pageSize, + Integer pageNumber, + String sortBy, + String direction) { + + return geneMapper.getGenes( + keyword, + alias, + projection, + pageSize, + PaginationCalculator.offset(pageSize, pageNumber), + sortBy, + direction); + } + + @Override + public BaseMeta getMetaGenes(String keyword, String alias) { + + return geneMapper.getMetaGenes(keyword, alias); + } + + @Override + public Gene getGeneByGeneticEntityId(Integer geneticEntityId) { + return geneMapper.getGeneByGeneticEntityId( + geneticEntityId, PersistenceConstants.DETAILED_PROJECTION); + } + + @Override + public Gene getGeneByEntrezGeneId(Integer entrezGeneId) { + + return geneMapper.getGeneByEntrezGeneId(entrezGeneId, PersistenceConstants.DETAILED_PROJECTION); + } + + @Override + public Gene getGeneByHugoGeneSymbol(String hugoGeneSymbol) { + + return geneMapper.getGeneByHugoGeneSymbol( + hugoGeneSymbol, PersistenceConstants.DETAILED_PROJECTION); + } + + @Override + public List getAliasesOfGeneByEntrezGeneId(Integer entrezGeneId) { + + return geneMapper.getAliasesOfGeneByEntrezGeneId(entrezGeneId); + } + + @Override + public List getAliasesOfGeneByHugoGeneSymbol(String hugoGeneSymbol) { + + return geneMapper.getAliasesOfGeneByHugoGeneSymbol(hugoGeneSymbol); + } + + @Override + public List getAllAliases() { + return geneMapper.getAllAliases(); + } + + @Override + public List fetchGenesByEntrezGeneIds(List entrezGeneIds, String projection) { + + return geneMapper.getGenesByEntrezGeneIds(entrezGeneIds, projection); + } + + @Override + public List fetchGenesByHugoGeneSymbols(List hugoGeneSymbols, String projection) { + + return geneMapper.getGenesByHugoGeneSymbols(hugoGeneSymbols, projection); + } + + @Override + public BaseMeta fetchMetaGenesByEntrezGeneIds(List entrezGeneIds) { + + return geneMapper.getMetaGenesByEntrezGeneIds(entrezGeneIds); + } + + @Override + public BaseMeta fetchMetaGenesByHugoGeneSymbols(List hugoGeneSymbols) { + + return geneMapper.getMetaGenesByHugoGeneSymbols(hugoGeneSymbols); + } +} diff --git a/src/main/java/org/cbioportal/legacy/persistence/mybatis/GenePanelMapper.java b/src/main/java/org/cbioportal/legacy/persistence/mybatis/GenePanelMapper.java new file mode 100644 index 00000000000..9aad5a777a5 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/persistence/mybatis/GenePanelMapper.java @@ -0,0 +1,37 @@ +package org.cbioportal.legacy.persistence.mybatis; + +import java.util.List; +import java.util.Set; +import org.cbioportal.legacy.model.GenePanel; +import org.cbioportal.legacy.model.GenePanelData; +import org.cbioportal.legacy.model.GenePanelToGene; +import org.cbioportal.legacy.model.MolecularProfileCaseIdentifier; +import org.cbioportal.legacy.model.meta.BaseMeta; + +public interface GenePanelMapper { + + List getAllGenePanels( + String projection, Integer limit, Integer offset, String sortBy, String direction); + + BaseMeta getMetaGenePanels(); + + GenePanel getGenePanel(String genePanelId, String projection); + + List fetchGenePanels(List genePanelIds, String projection); + + List getGenePanelDataBySampleListId( + String molecularProfileId, String sampleListId); + + List getGenePanelDataBySampleIds( + String molecularProfileId, List sampleIds); + + List fetchGenePanelDataByMolecularProfileIds(Set molecularProfileIds); + + List fetchGenePanelDataInMultipleMolecularProfiles( + List molecularProfileSampleIdentifiers); + + List fetchGenePanelDataInMultipleMolecularProfilesByPatientIds( + List molecularProfileSampleIdentifiers); + + List getGenesOfPanels(List genePanelIds); +} diff --git a/src/main/java/org/cbioportal/legacy/persistence/mybatis/GenePanelMyBatisRepository.java b/src/main/java/org/cbioportal/legacy/persistence/mybatis/GenePanelMyBatisRepository.java new file mode 100644 index 00000000000..1c0764ab155 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/persistence/mybatis/GenePanelMyBatisRepository.java @@ -0,0 +1,85 @@ +package org.cbioportal.legacy.persistence.mybatis; + +import java.util.Collections; +import java.util.List; +import java.util.Set; +import org.cbioportal.legacy.model.GenePanel; +import org.cbioportal.legacy.model.GenePanelData; +import org.cbioportal.legacy.model.GenePanelToGene; +import org.cbioportal.legacy.model.MolecularProfileCaseIdentifier; +import org.cbioportal.legacy.model.meta.BaseMeta; +import org.cbioportal.legacy.persistence.GenePanelRepository; +import org.cbioportal.legacy.persistence.PersistenceConstants; +import org.cbioportal.legacy.persistence.mybatis.util.PaginationCalculator; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Repository; + +@Repository +public class GenePanelMyBatisRepository implements GenePanelRepository { + + @Autowired private GenePanelMapper genePanelMapper; + + @Override + public List getAllGenePanels( + String projection, Integer pageSize, Integer pageNumber, String sortBy, String direction) { + return genePanelMapper.getAllGenePanels( + projection, pageSize, PaginationCalculator.offset(pageSize, pageNumber), sortBy, direction); + } + + @Override + public BaseMeta getMetaGenePanels() { + return genePanelMapper.getMetaGenePanels(); + } + + @Override + public GenePanel getGenePanel(String genePanelId) { + return genePanelMapper.getGenePanel(genePanelId, PersistenceConstants.DETAILED_PROJECTION); + } + + @Override + public List fetchGenePanels(List genePanelIds, String projection) { + return genePanelMapper.fetchGenePanels(genePanelIds, projection); + } + + @Override + public List getGenePanelDataBySampleListId( + String molecularProfileId, String sampleListId) { + return genePanelMapper.getGenePanelDataBySampleListId(molecularProfileId, sampleListId); + } + + @Override + public List fetchGenePanelData(String molecularProfileId, List sampleIds) { + return genePanelMapper.getGenePanelDataBySampleIds(molecularProfileId, sampleIds); + } + + @Override + public List fetchGenePanelDataByMolecularProfileIds( + Set molecularProfileIds) { + return genePanelMapper.fetchGenePanelDataByMolecularProfileIds(molecularProfileIds); + } + + @Override + public List fetchGenePanelDataByMolecularProfileId(String molecularProfileId) { + return genePanelMapper.fetchGenePanelDataByMolecularProfileIds( + Collections.singleton(molecularProfileId)); + } + + @Override + public List fetchGenePanelDataInMultipleMolecularProfiles( + List molecularProfileSampleIdentifiers) { + return genePanelMapper.fetchGenePanelDataInMultipleMolecularProfiles( + molecularProfileSampleIdentifiers); + } + + @Override + public List fetchGenePanelDataInMultipleMolecularProfilesByPatientIds( + List molecularProfileSampleIdentifiers) { + return genePanelMapper.fetchGenePanelDataInMultipleMolecularProfilesByPatientIds( + molecularProfileSampleIdentifiers); + } + + @Override + public List getGenesOfPanels(List genePanelIds) { + return genePanelMapper.getGenesOfPanels(genePanelIds); + } +} diff --git a/src/main/java/org/cbioportal/legacy/persistence/mybatis/GenericAssayMapper.java b/src/main/java/org/cbioportal/legacy/persistence/mybatis/GenericAssayMapper.java new file mode 100644 index 00000000000..8f40af94871 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/persistence/mybatis/GenericAssayMapper.java @@ -0,0 +1,20 @@ +package org.cbioportal.legacy.persistence.mybatis; + +import java.util.List; +import org.cbioportal.legacy.model.GenericAssayAdditionalProperty; +import org.cbioportal.legacy.model.meta.GenericAssayMeta; + +public interface GenericAssayMapper { + + List getGenericAssayMeta(List stableIds); + + List getGenericAssayAdditionalproperties(List stableIds); + + List getMolecularProfileInternalIdsByMolecularProfileIds( + List molecularProfileIds); + + List getGeneticEntityIdsByMolecularProfileInternalIds( + List molecularProfileInternalIds); + + List getGenericAssayStableIdsByGeneticEntityIds(List geneticEntityIds); +} diff --git a/src/main/java/org/cbioportal/legacy/persistence/mybatis/GenericAssayMyBatisRepository.java b/src/main/java/org/cbioportal/legacy/persistence/mybatis/GenericAssayMyBatisRepository.java new file mode 100644 index 00000000000..2ebcc652936 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/persistence/mybatis/GenericAssayMyBatisRepository.java @@ -0,0 +1,67 @@ +package org.cbioportal.legacy.persistence.mybatis; + +import java.util.ArrayList; +import java.util.List; +import org.cbioportal.legacy.model.GenericAssayAdditionalProperty; +import org.cbioportal.legacy.model.meta.GenericAssayMeta; +import org.cbioportal.legacy.persistence.GenericAssayRepository; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Repository; + +@Repository +public class GenericAssayMyBatisRepository implements GenericAssayRepository { + + @Autowired private GenericAssayMapper genericAssayMapper; + + private static final Logger LOG = LoggerFactory.getLogger(GenericAssayMyBatisRepository.class); + + @Override + @Cacheable( + cacheResolver = "staticRepositoryCacheOneResolver", + condition = "@cacheEnabledConfig.getEnabled()") + public List getGenericAssayMeta(List stableIds) { + + return genericAssayMapper.getGenericAssayMeta(stableIds); + } + + @Override + @Cacheable( + cacheResolver = "staticRepositoryCacheOneResolver", + condition = "@cacheEnabledConfig.getEnabled()") + public List getGenericAssayAdditionalproperties( + List stableIds) { + return genericAssayMapper.getGenericAssayAdditionalproperties(stableIds); + } + + @Override + @Cacheable( + cacheResolver = "staticRepositoryCacheOneResolver", + condition = "@cacheEnabledConfig.getEnabled()") + public List getGenericAssayStableIdsByMolecularIds(List molecularProfileIds) { + + List molecularProfileInternalIds = + genericAssayMapper.getMolecularProfileInternalIdsByMolecularProfileIds(molecularProfileIds); + if (molecularProfileInternalIds.size() > 0) { + List geneticEntityIds = + genericAssayMapper.getGeneticEntityIdsByMolecularProfileInternalIds( + molecularProfileInternalIds); + if (geneticEntityIds.size() > 0) { + // return result + return genericAssayMapper.getGenericAssayStableIdsByGeneticEntityIds(geneticEntityIds); + } else { + LOG.error( + "Returned an Empty list. Cannot find accociate entity ids for molecular profiles: " + + molecularProfileIds.toString()); + } + } else { + LOG.error( + "Returned an Empty list. Cannot find internal ids for molecular profiles: " + + molecularProfileIds.toString()); + } + // log error and return empty list if something went wrong + return new ArrayList(); + } +} diff --git a/src/main/java/org/cbioportal/legacy/persistence/mybatis/GenesetHierarchyMapper.java b/src/main/java/org/cbioportal/legacy/persistence/mybatis/GenesetHierarchyMapper.java new file mode 100644 index 00000000000..ea1e3a5cf19 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/persistence/mybatis/GenesetHierarchyMapper.java @@ -0,0 +1,17 @@ +package org.cbioportal.legacy.persistence.mybatis; + +import java.util.List; +import org.apache.ibatis.annotations.Param; +import org.cbioportal.legacy.model.Geneset; +import org.cbioportal.legacy.model.GenesetHierarchyInfo; + +public interface GenesetHierarchyMapper { + + List getGenesetHierarchyParents( + @Param("genesetIds") List genesetIds); + + List getGenesetHierarchyGenesets(Integer nodeId); + + List getGenesetHierarchySuperNodes( + @Param("genesetIds") List genesetIds); +} diff --git a/src/main/java/org/cbioportal/legacy/persistence/mybatis/GenesetHierarchyMyBatisRepository.java b/src/main/java/org/cbioportal/legacy/persistence/mybatis/GenesetHierarchyMyBatisRepository.java new file mode 100644 index 00000000000..8fc13b8808c --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/persistence/mybatis/GenesetHierarchyMyBatisRepository.java @@ -0,0 +1,32 @@ +package org.cbioportal.legacy.persistence.mybatis; + +import java.util.List; +import org.cbioportal.legacy.model.Geneset; +import org.cbioportal.legacy.model.GenesetHierarchyInfo; +import org.cbioportal.legacy.persistence.GenesetHierarchyRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Repository; + +@Repository +public class GenesetHierarchyMyBatisRepository implements GenesetHierarchyRepository { + + @Autowired private GenesetHierarchyMapper genesetHierarchyMapper; + + @Override + public List getGenesetHierarchyParents(List genesetIds) { + + return genesetHierarchyMapper.getGenesetHierarchyParents(genesetIds); + } + + @Override + public List getGenesetHierarchyGenesets(Integer nodeId) { + + return genesetHierarchyMapper.getGenesetHierarchyGenesets(nodeId); + } + + @Override + public List getGenesetHierarchySuperNodes(List genesetIds) { + + return genesetHierarchyMapper.getGenesetHierarchySuperNodes(genesetIds); + } +} diff --git a/src/main/java/org/cbioportal/legacy/persistence/mybatis/GenesetMapper.java b/src/main/java/org/cbioportal/legacy/persistence/mybatis/GenesetMapper.java new file mode 100644 index 00000000000..317f61cbdea --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/persistence/mybatis/GenesetMapper.java @@ -0,0 +1,26 @@ +package org.cbioportal.legacy.persistence.mybatis; + +import java.util.List; +import org.cbioportal.legacy.model.Gene; +import org.cbioportal.legacy.model.Geneset; +import org.cbioportal.legacy.model.meta.BaseMeta; + +public interface GenesetMapper { + + List getGenesets( + String projection, Integer limit, Integer offset, String sortBy, String direction); + + BaseMeta getMetaGenesets(); + + Geneset getGenesetByInternalId(Integer internalId, String projection); + + Geneset getGenesetByGenesetId(String genesetId, String projection); + + Geneset getGenesetByGeneticEntityId(Integer geneticEntityId, String projection); + + List fetchGenesets(List genesetIds); + + List getGenesByGenesetId(String genesetId, String projection); + + String getGenesetVersion(); +} diff --git a/src/main/java/org/cbioportal/legacy/persistence/mybatis/GenesetMyBatisRepository.java b/src/main/java/org/cbioportal/legacy/persistence/mybatis/GenesetMyBatisRepository.java new file mode 100644 index 00000000000..4d594f6804f --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/persistence/mybatis/GenesetMyBatisRepository.java @@ -0,0 +1,58 @@ +package org.cbioportal.legacy.persistence.mybatis; + +import java.util.List; +import org.cbioportal.legacy.model.Gene; +import org.cbioportal.legacy.model.Geneset; +import org.cbioportal.legacy.model.meta.BaseMeta; +import org.cbioportal.legacy.persistence.GenesetRepository; +import org.cbioportal.legacy.persistence.PersistenceConstants; +import org.cbioportal.legacy.persistence.mybatis.util.PaginationCalculator; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Repository; + +@Repository +public class GenesetMyBatisRepository implements GenesetRepository { + + @Autowired GenesetMapper genesetMapper; + + @Override + public List getAllGenesets(String projection, Integer pageSize, Integer pageNumber) { + + return genesetMapper.getGenesets( + projection, + pageSize, + PaginationCalculator.offset(pageSize, pageNumber), + "EXTERNAL_ID", + "ASC"); + } + + @Override + public BaseMeta getMetaGenesets() { + + return genesetMapper.getMetaGenesets(); + } + + @Override + public Geneset getGeneset(String genesetId) { + + return genesetMapper.getGenesetByGenesetId(genesetId, PersistenceConstants.DETAILED_PROJECTION); + } + + @Override + public List fetchGenesets(List genesetIds) { + + return genesetMapper.fetchGenesets(genesetIds); + } + + @Override + public List getGenesByGenesetId(String genesetId) { + + return genesetMapper.getGenesByGenesetId(genesetId, PersistenceConstants.SUMMARY_PROJECTION); + } + + @Override + public String getGenesetVersion() { + + return genesetMapper.getGenesetVersion(); + } +} diff --git a/src/main/java/org/cbioportal/legacy/persistence/mybatis/MolecularDataMapper.java b/src/main/java/org/cbioportal/legacy/persistence/mybatis/MolecularDataMapper.java new file mode 100644 index 00000000000..2ca29931c35 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/persistence/mybatis/MolecularDataMapper.java @@ -0,0 +1,37 @@ +package org.cbioportal.legacy.persistence.mybatis; + +import java.util.List; +import java.util.Set; +import org.apache.ibatis.cursor.Cursor; +import org.cbioportal.legacy.model.GeneMolecularAlteration; +import org.cbioportal.legacy.model.GenericAssayMolecularAlteration; +import org.cbioportal.legacy.model.GenesetMolecularAlteration; +import org.cbioportal.legacy.model.MolecularProfileSamples; + +public interface MolecularDataMapper { + + List getCommaSeparatedSampleIdsOfMolecularProfiles( + Set molecularProfileIds); + + List getGeneMolecularAlterations( + String molecularProfileId, List entrezGeneIds, String projection); + + Cursor getGeneMolecularAlterationsIter( + String molecularProfileId, List entrezGeneIds, String projection); + + // Same as getGeneMolecularAlterationsIter above, except assumes that + // entrezGeneIds is null or empty AND projection is "SUMMARY" + Cursor getGeneMolecularAlterationsIterFast(String molecularProfileId); + + List getGeneMolecularAlterationsInMultipleMolecularProfiles( + Set molecularProfileIds, List entrezGeneIds, String projection); + + List getGenesetMolecularAlterations( + String molecularProfileId, List genesetIds, String projection); + + List getGenericAssayMolecularAlterations( + String molecularProfileId, List stableIds, String projection); + + Cursor getGenericAssayMolecularAlterationsIter( + String molecularProfileId, List stableIds, String projection); +} diff --git a/src/main/java/org/cbioportal/legacy/persistence/mybatis/MolecularDataMyBatisRepository.java b/src/main/java/org/cbioportal/legacy/persistence/mybatis/MolecularDataMyBatisRepository.java new file mode 100644 index 00000000000..a133562ea2c --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/persistence/mybatis/MolecularDataMyBatisRepository.java @@ -0,0 +1,99 @@ +package org.cbioportal.legacy.persistence.mybatis; + +import java.util.*; +import java.util.function.Function; +import java.util.stream.Collectors; +import org.cbioportal.legacy.model.GeneMolecularAlteration; +import org.cbioportal.legacy.model.GenericAssayMolecularAlteration; +import org.cbioportal.legacy.model.GenesetMolecularAlteration; +import org.cbioportal.legacy.model.MolecularProfileSamples; +import org.cbioportal.legacy.persistence.MolecularDataRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Repository; + +@Repository +public class MolecularDataMyBatisRepository implements MolecularDataRepository { + + @Autowired private MolecularDataMapper molecularDataMapper; + + @Override + public MolecularProfileSamples getCommaSeparatedSampleIdsOfMolecularProfile( + String molecularProfileId) { + try { + return molecularDataMapper + .getCommaSeparatedSampleIdsOfMolecularProfiles(Collections.singleton(molecularProfileId)) + .get(0); + } catch (IndexOutOfBoundsException e) { + return null; + } + } + + @Override + public Map commaSeparatedSampleIdsOfMolecularProfilesMap( + Set molecularProfileIds) { + + return molecularDataMapper + .getCommaSeparatedSampleIdsOfMolecularProfiles(molecularProfileIds) + .stream() + .collect( + Collectors.toMap(MolecularProfileSamples::getMolecularProfileId, Function.identity())); + } + + @Override + public List getGeneMolecularAlterations( + String molecularProfileId, List entrezGeneIds, String projection) { + + return molecularDataMapper.getGeneMolecularAlterations( + molecularProfileId, entrezGeneIds, projection); + } + + @Override + // In order to return a cursor/iterator to the service layer, we need a transaction setup in the + // service + // layer. Currently, the bottom stackframe is CoExpressionService:getCoExpressions. It is there + // where + // you will find the transaction created. + public Iterable getGeneMolecularAlterationsIterable( + String molecularProfileId, List entrezGeneIds, String projection) { + + return molecularDataMapper.getGeneMolecularAlterationsIter( + molecularProfileId, entrezGeneIds, projection); + } + + @Override + public Iterable getGeneMolecularAlterationsIterableFast( + String molecularProfileId) { + + return molecularDataMapper.getGeneMolecularAlterationsIterFast(molecularProfileId); + } + + @Override + public List getGeneMolecularAlterationsInMultipleMolecularProfiles( + Set molecularProfileIds, List entrezGeneIds, String projection) { + + return molecularDataMapper.getGeneMolecularAlterationsInMultipleMolecularProfiles( + molecularProfileIds, entrezGeneIds, projection); + } + + @Override + public List getGenesetMolecularAlterations( + String molecularProfileId, List genesetIds, String projection) { + + return molecularDataMapper.getGenesetMolecularAlterations( + molecularProfileId, genesetIds, projection); + } + + @Override + public List getGenericAssayMolecularAlterations( + String molecularProfileId, List stableIds, String projection) { + return molecularDataMapper.getGenericAssayMolecularAlterations( + molecularProfileId, stableIds, projection); + } + + @Override + public Iterable getGenericAssayMolecularAlterationsIterable( + String molecularProfileId, List stableIds, String projection) { + return molecularDataMapper.getGenericAssayMolecularAlterationsIter( + molecularProfileId, stableIds, projection); + } +} diff --git a/src/main/java/org/cbioportal/legacy/persistence/mybatis/MolecularProfileMapper.java b/src/main/java/org/cbioportal/legacy/persistence/mybatis/MolecularProfileMapper.java new file mode 100644 index 00000000000..5b821255076 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/persistence/mybatis/MolecularProfileMapper.java @@ -0,0 +1,31 @@ +package org.cbioportal.legacy.persistence.mybatis; + +import java.util.List; +import java.util.Set; +import org.cbioportal.legacy.model.MolecularProfile; +import org.cbioportal.legacy.model.meta.BaseMeta; + +public interface MolecularProfileMapper { + + List getAllMolecularProfilesInStudies( + List studyIds, + String projection, + Integer limit, + Integer offset, + String sortBy, + String direction); + + BaseMeta getMetaMolecularProfilesInStudies(List studyIds); + + MolecularProfile getMolecularProfile(String molecularProfileId, String projection); + + List getMolecularProfiles(Set molecularProfileIds, String projection); + + BaseMeta getMetaMolecularProfiles(Set molecularProfileIds); + + List getMolecularProfilesReferredBy( + String referringMolecularProfileId, String projection); + + List getMolecularProfilesReferringTo( + String referredMolecularProfileId, String projection); +} diff --git a/src/main/java/org/cbioportal/legacy/persistence/mybatis/MolecularProfileMyBatisRepository.java b/src/main/java/org/cbioportal/legacy/persistence/mybatis/MolecularProfileMyBatisRepository.java new file mode 100644 index 00000000000..77f626abc93 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/persistence/mybatis/MolecularProfileMyBatisRepository.java @@ -0,0 +1,108 @@ +package org.cbioportal.legacy.persistence.mybatis; + +import java.util.Arrays; +import java.util.List; +import java.util.Set; +import org.cbioportal.legacy.model.MolecularProfile; +import org.cbioportal.legacy.model.meta.BaseMeta; +import org.cbioportal.legacy.persistence.MolecularProfileRepository; +import org.cbioportal.legacy.persistence.PersistenceConstants; +import org.cbioportal.legacy.persistence.mybatis.util.PaginationCalculator; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Repository; + +@Repository +public class MolecularProfileMyBatisRepository implements MolecularProfileRepository { + + @Autowired private MolecularProfileMapper molecularProfileMapper; + + @Override + public List getAllMolecularProfiles( + String projection, Integer pageSize, Integer pageNumber, String sortBy, String direction) { + + return molecularProfileMapper.getAllMolecularProfilesInStudies( + null, + projection, + pageSize, + PaginationCalculator.offset(pageSize, pageNumber), + sortBy, + direction); + } + + @Override + public BaseMeta getMetaMolecularProfiles() { + + return molecularProfileMapper.getMetaMolecularProfilesInStudies(null); + } + + @Override + public MolecularProfile getMolecularProfile(String molecularProfileId) { + return molecularProfileMapper.getMolecularProfile( + molecularProfileId, PersistenceConstants.DETAILED_PROJECTION); + } + + @Override + public List getMolecularProfiles( + Set molecularProfileIds, String projection) { + + return molecularProfileMapper.getMolecularProfiles(molecularProfileIds, projection); + } + + @Override + public BaseMeta getMetaMolecularProfiles(Set molecularProfileIds) { + + return molecularProfileMapper.getMetaMolecularProfiles(molecularProfileIds); + } + + @Override + public List getAllMolecularProfilesInStudy( + String studyId, + String projection, + Integer pageSize, + Integer pageNumber, + String sortBy, + String direction) { + + return molecularProfileMapper.getAllMolecularProfilesInStudies( + Arrays.asList(studyId), + projection, + pageSize, + PaginationCalculator.offset(pageSize, pageNumber), + sortBy, + direction); + } + + @Override + public BaseMeta getMetaMolecularProfilesInStudy(String studyId) { + + return molecularProfileMapper.getMetaMolecularProfilesInStudies(Arrays.asList(studyId)); + } + + @Override + public List getMolecularProfilesInStudies( + List studyIds, String projection) { + + return molecularProfileMapper.getAllMolecularProfilesInStudies( + studyIds, projection, 0, 0, null, null); + } + + @Override + public BaseMeta getMetaMolecularProfilesInStudies(List studyIds) { + + return molecularProfileMapper.getMetaMolecularProfilesInStudies(studyIds); + } + + @Override + public List getMolecularProfilesReferredBy(String referringMolecularProfileId) { + + return molecularProfileMapper.getMolecularProfilesReferredBy( + referringMolecularProfileId, PersistenceConstants.DETAILED_PROJECTION); + } + + @Override + public List getMolecularProfilesReferringTo(String referredMolecularProfileId) { + + return molecularProfileMapper.getMolecularProfilesReferringTo( + referredMolecularProfileId, PersistenceConstants.DETAILED_PROJECTION); + } +} diff --git a/src/main/java/org/cbioportal/legacy/persistence/mybatis/MutationMapper.java b/src/main/java/org/cbioportal/legacy/persistence/mybatis/MutationMapper.java new file mode 100644 index 00000000000..c72b859966f --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/persistence/mybatis/MutationMapper.java @@ -0,0 +1,69 @@ +package org.cbioportal.legacy.persistence.mybatis; + +import java.util.List; +import org.cbioportal.legacy.model.GeneFilterQuery; +import org.cbioportal.legacy.model.GenomicDataCountItem; +import org.cbioportal.legacy.model.Mutation; +import org.cbioportal.legacy.model.MutationCountByPosition; +import org.cbioportal.legacy.model.meta.MutationMeta; + +public interface MutationMapper { + + List getMutationsBySampleListId( + String molecularProfileId, + String sampleListId, + List entrezGeneIds, + boolean snpOnly, + String projection, + Integer limit, + Integer offset, + String sortBy, + String direction); + + MutationMeta getMetaMutationsBySampleListId( + String molecularProfileId, String sampleListId, List entrezGeneIds, boolean snpOnly); + + List getMutationsInMultipleMolecularProfiles( + List molecularProfileIds, + List sampleIds, + List entrezGeneIds, + boolean snpOnly, + String projection, + Integer limit, + Integer offset, + String sortBy, + String direction); + + List getMutationsInMultipleMolecularProfilesByGeneQueries( + List molecularProfileIds, + List sampleIds, + boolean snpOnly, + String projection, + Integer limit, + Integer offset, + String sortBy, + String direction, + List geneQueries); + + MutationMeta getMetaMutationsInMultipleMolecularProfiles( + List molecularProfileIds, + List sampleIds, + List entrezGeneIds, + boolean snpOnly); + + MutationMeta getMetaMutationsBySampleIds( + String molecularProfileId, + List sampleIds, + List entrezGeneIds, + boolean snpOnly); + + MutationCountByPosition getMutationCountByPosition( + Integer entrezGeneId, Integer proteinPosStart, Integer proteinPosEnd); + + GenomicDataCountItem getMutationCountsByType( + List molecularProfileIds, + List sampleIds, + List entrezGeneIds, + boolean snpOnly, + String profileType); +} diff --git a/src/main/java/org/cbioportal/legacy/persistence/mybatis/MutationMyBatisRepository.java b/src/main/java/org/cbioportal/legacy/persistence/mybatis/MutationMyBatisRepository.java new file mode 100644 index 00000000000..97258be697e --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/persistence/mybatis/MutationMyBatisRepository.java @@ -0,0 +1,175 @@ +package org.cbioportal.legacy.persistence.mybatis; + +import java.util.*; +import java.util.stream.Collectors; +import org.cbioportal.legacy.model.GeneFilterQuery; +import org.cbioportal.legacy.model.GenomicDataCountItem; +import org.cbioportal.legacy.model.Mutation; +import org.cbioportal.legacy.model.MutationCountByPosition; +import org.cbioportal.legacy.model.meta.MutationMeta; +import org.cbioportal.legacy.persistence.MutationRepository; +import org.cbioportal.legacy.persistence.mybatis.util.MolecularProfileCaseIdentifierUtil; +import org.cbioportal.legacy.persistence.mybatis.util.PaginationCalculator; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Repository; + +@Repository +public class MutationMyBatisRepository implements MutationRepository { + + @Autowired private MutationMapper mutationMapper; + @Autowired private MolecularProfileCaseIdentifierUtil molecularProfileCaseIdentifierUtil; + + @Override + public List getMutationsInMolecularProfileBySampleListId( + String molecularProfileId, + String sampleListId, + List entrezGeneIds, + boolean snpOnly, + String projection, + Integer pageSize, + Integer pageNumber, + String sortBy, + String direction) { + + return mutationMapper.getMutationsBySampleListId( + molecularProfileId, + sampleListId, + entrezGeneIds, + snpOnly, + projection, + pageSize, + PaginationCalculator.offset(pageSize, pageNumber), + sortBy, + direction); + } + + @Override + public MutationMeta getMetaMutationsInMolecularProfileBySampleListId( + String molecularProfileId, String sampleListId, List entrezGeneIds) { + + return mutationMapper.getMetaMutationsBySampleListId( + molecularProfileId, sampleListId, entrezGeneIds, false); + } + + @Override + public List getMutationsInMultipleMolecularProfiles( + List molecularProfileIds, + List sampleIds, + List entrezGeneIds, + String projection, + Integer pageSize, + Integer pageNumber, + String sortBy, + String direction) { + + return molecularProfileCaseIdentifierUtil + .getGroupedCasesByMolecularProfileId(molecularProfileIds, sampleIds) + .entrySet() + .stream() + .flatMap( + entry -> + mutationMapper + .getMutationsInMultipleMolecularProfiles( + Arrays.asList(entry.getKey()), + new ArrayList<>(entry.getValue()), + entrezGeneIds, + false, + projection, + pageSize, + PaginationCalculator.offset(pageSize, pageNumber), + sortBy, + direction) + .stream()) + .collect(Collectors.toList()); + } + + @Override + public List getMutationsInMultipleMolecularProfilesByGeneQueries( + List molecularProfileIds, + List sampleIds, + List geneQueries, + String projection, + Integer pageSize, + Integer pageNumber, + String sortBy, + String direction) { + if (geneQueries.isEmpty()) return Collections.emptyList(); + + return molecularProfileCaseIdentifierUtil + .getGroupedCasesByMolecularProfileId(molecularProfileIds, sampleIds) + .entrySet() + .stream() + .flatMap( + entry -> + mutationMapper + .getMutationsInMultipleMolecularProfilesByGeneQueries( + Arrays.asList(entry.getKey()), + new ArrayList<>(entry.getValue()), + false, + projection, + pageSize, + PaginationCalculator.offset(pageSize, pageNumber), + sortBy, + direction, + geneQueries) + .stream()) + .collect(Collectors.toList()); + } + + @Override + public MutationMeta getMetaMutationsInMultipleMolecularProfiles( + List molecularProfileIds, List sampleIds, List entrezGeneIds) { + + return mutationMapper.getMetaMutationsInMultipleMolecularProfiles( + molecularProfileIds, sampleIds, entrezGeneIds, false); + } + + @Override + public List fetchMutationsInMolecularProfile( + String molecularProfileId, + List sampleIds, + List entrezGeneIds, + boolean snpOnly, + String projection, + Integer pageSize, + Integer pageNumber, + String sortBy, + String direction) { + + return mutationMapper.getMutationsInMultipleMolecularProfiles( + Arrays.asList(molecularProfileId), + new ArrayList<>(sampleIds), + entrezGeneIds, + snpOnly, + projection, + pageSize, + PaginationCalculator.offset(pageSize, pageNumber), + sortBy, + direction); + } + + @Override + public MutationMeta fetchMetaMutationsInMolecularProfile( + String molecularProfileId, List sampleIds, List entrezGeneIds) { + + return mutationMapper.getMetaMutationsBySampleIds( + molecularProfileId, sampleIds, entrezGeneIds, false); + } + + @Override + public MutationCountByPosition getMutationCountByPosition( + Integer entrezGeneId, Integer proteinPosStart, Integer proteinPosEnd) { + + return mutationMapper.getMutationCountByPosition(entrezGeneId, proteinPosStart, proteinPosEnd); + } + + @Override + public GenomicDataCountItem getMutationCountsByType( + List molecularProfileIds, + List sampleIds, + List entrezGeneIds, + String profileType) { + return mutationMapper.getMutationCountsByType( + molecularProfileIds, sampleIds, entrezGeneIds, false, profileType); + } +} diff --git a/src/main/java/org/cbioportal/legacy/persistence/mybatis/NamespaceMapper.java b/src/main/java/org/cbioportal/legacy/persistence/mybatis/NamespaceMapper.java new file mode 100644 index 00000000000..827940b5718 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/persistence/mybatis/NamespaceMapper.java @@ -0,0 +1,30 @@ +package org.cbioportal.legacy.persistence.mybatis; + +import java.util.List; +import org.cbioportal.legacy.model.NamespaceAttribute; +import org.cbioportal.legacy.model.NamespaceAttributeCount; +import org.cbioportal.legacy.model.NamespaceData; +import org.cbioportal.legacy.model.NamespaceDataCount; + +public interface NamespaceMapper { + + List getNamespaceOuterKey(List studyIds); + + List getNamespaceInnerKey(String outerKey, List studyIds); + + List getNamespaceAttributeCountsBySampleIds( + List studyIds, List sampleIds, List namespaceAttributes); + + List getNamespaceDataCounts( + List studyIds, List sampleIds, String outerKey, String innerKey); + + List getNamespaceData( + List studyIds, List sampleIds, String outerKey, String innerKey); + + List getNamespaceDataForComparison( + List studyIds, + List sampleIds, + String outerKey, + String innerKey, + String value); +} diff --git a/src/main/java/org/cbioportal/legacy/persistence/mybatis/NamespaceMyBatisRepository.java b/src/main/java/org/cbioportal/legacy/persistence/mybatis/NamespaceMyBatisRepository.java new file mode 100644 index 00000000000..cc9d0b265a2 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/persistence/mybatis/NamespaceMyBatisRepository.java @@ -0,0 +1,67 @@ +package org.cbioportal.legacy.persistence.mybatis; + +import java.util.*; +import org.cbioportal.legacy.model.NamespaceAttribute; +import org.cbioportal.legacy.model.NamespaceAttributeCount; +import org.cbioportal.legacy.model.NamespaceData; +import org.cbioportal.legacy.model.NamespaceDataCount; +import org.cbioportal.legacy.persistence.NamespaceRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Repository; + +@Repository +public class NamespaceMyBatisRepository implements NamespaceRepository { + + private final NamespaceMapper namespaceMapper; + + @Autowired + public NamespaceMyBatisRepository(NamespaceMapper namespaceMapper) { + this.namespaceMapper = namespaceMapper; + } + + @Override + public List getNamespaceOuterKey(List studyIds) { + + return namespaceMapper.getNamespaceOuterKey(studyIds); + } + + @Override + public List getNamespaceInnerKey(String outerKey, List studyIds) { + + return namespaceMapper.getNamespaceInnerKey(outerKey, studyIds); + } + + @Override + public List getNamespaceAttributeCountsBySampleIds( + List studyIds, List sampleIds, List namespaceAttributes) { + + return namespaceMapper.getNamespaceAttributeCountsBySampleIds( + studyIds, sampleIds, namespaceAttributes); + } + + @Override + public List getNamespaceDataCounts( + List studyIds, List sampleIds, String outerKey, String innerKey) { + + return namespaceMapper.getNamespaceDataCounts(studyIds, sampleIds, outerKey, innerKey); + } + + @Override + public List getNamespaceData( + List studyIds, List sampleIds, String outerKey, String innerKey) { + + return namespaceMapper.getNamespaceData(studyIds, sampleIds, outerKey, innerKey); + } + + @Override + public List getNamespaceDataForComparison( + List studyIds, + List sampleIds, + String outerKey, + String innerKey, + String value) { + + return namespaceMapper.getNamespaceDataForComparison( + studyIds, sampleIds, outerKey, innerKey, value); + } +} diff --git a/src/main/java/org/cbioportal/legacy/persistence/mybatis/PatientMapper.java b/src/main/java/org/cbioportal/legacy/persistence/mybatis/PatientMapper.java new file mode 100644 index 00000000000..6ed80b08519 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/persistence/mybatis/PatientMapper.java @@ -0,0 +1,24 @@ +package org.cbioportal.legacy.persistence.mybatis; + +import java.util.List; +import org.cbioportal.legacy.model.Patient; +import org.cbioportal.legacy.model.meta.BaseMeta; + +public interface PatientMapper { + + List getPatients( + List studyIds, + List patientIds, + String keyword, + String projection, + Integer limit, + Integer offset, + String sortBy, + String direction); + + BaseMeta getMetaPatients(List studyIds, List patientIds, String keyword); + + Patient getPatient(String studyId, String patientId, String projection); + + List getPatientsOfSamples(List studyIds, List sampleIds); +} diff --git a/src/main/java/org/cbioportal/legacy/persistence/mybatis/PatientMyBatisRepository.java b/src/main/java/org/cbioportal/legacy/persistence/mybatis/PatientMyBatisRepository.java new file mode 100644 index 00000000000..2d28c12935f --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/persistence/mybatis/PatientMyBatisRepository.java @@ -0,0 +1,93 @@ +package org.cbioportal.legacy.persistence.mybatis; + +import java.util.Arrays; +import java.util.List; +import org.cbioportal.legacy.model.Patient; +import org.cbioportal.legacy.model.meta.BaseMeta; +import org.cbioportal.legacy.persistence.PatientRepository; +import org.cbioportal.legacy.persistence.PersistenceConstants; +import org.cbioportal.legacy.persistence.mybatis.util.PaginationCalculator; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Repository; + +@Repository +public class PatientMyBatisRepository implements PatientRepository { + + @Autowired private PatientMapper patientMapper; + + @Override + public List getAllPatients( + String keyword, + String projection, + Integer pageSize, + Integer pageNumber, + String sortBy, + String direction) { + return patientMapper.getPatients( + null, + null, + keyword, + projection, + pageSize, + PaginationCalculator.offset(pageSize, pageNumber), + sortBy, + direction); + } + + @Override + public BaseMeta getMetaPatients(String keyword) { + + return patientMapper.getMetaPatients(null, null, keyword); + } + + @Override + public List getAllPatientsInStudy( + String studyId, + String projection, + Integer pageSize, + Integer pageNumber, + String sortBy, + String direction) { + + return patientMapper.getPatients( + Arrays.asList(studyId), + null, + null, + projection, + pageSize, + PaginationCalculator.offset(pageSize, pageNumber), + sortBy, + direction); + } + + @Override + public BaseMeta getMetaPatientsInStudy(String studyId) { + + return patientMapper.getMetaPatients(Arrays.asList(studyId), null, null); + } + + @Override + public Patient getPatientInStudy(String studyId, String patientId) { + + return patientMapper.getPatient(studyId, patientId, PersistenceConstants.DETAILED_PROJECTION); + } + + @Override + public List fetchPatients( + List studyIds, List patientIds, String projection) { + + return patientMapper.getPatients(studyIds, patientIds, null, projection, 0, 0, null, null); + } + + @Override + public BaseMeta fetchMetaPatients(List studyIds, List patientIds) { + + return patientMapper.getMetaPatients(studyIds, patientIds, null); + } + + @Override + public List getPatientsOfSamples(List studyIds, List sampleIds) { + + return patientMapper.getPatientsOfSamples(studyIds, sampleIds); + } +} diff --git a/src/main/java/org/cbioportal/legacy/persistence/mybatis/ReferenceGenomeGeneMapper.java b/src/main/java/org/cbioportal/legacy/persistence/mybatis/ReferenceGenomeGeneMapper.java new file mode 100644 index 00000000000..0af5adc564a --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/persistence/mybatis/ReferenceGenomeGeneMapper.java @@ -0,0 +1,19 @@ +package org.cbioportal.legacy.persistence.mybatis; + +import java.util.List; +import org.cbioportal.legacy.model.ReferenceGenomeGene; + +public interface ReferenceGenomeGeneMapper { + List getAllGenesByGenomeName(String genomeName, String projection); + + List getGenesByHugoGeneSymbolsAndGenomeName( + List geneIds, String genomeName, String projection); + + List getGenesByGenomeName( + List geneIds, String genomeName, String projection); + + ReferenceGenomeGene getReferenceGenomeGene(Integer geneId, String genomeName, String projection); + + ReferenceGenomeGene getReferenceGenomeGeneByEntityId( + Integer geneticEntityId, String genomeName, String projection); +} diff --git a/src/main/java/org/cbioportal/legacy/persistence/mybatis/ReferenceGenomeGeneMyBatisRepository.java b/src/main/java/org/cbioportal/legacy/persistence/mybatis/ReferenceGenomeGeneMyBatisRepository.java new file mode 100644 index 00000000000..c8e46a51e34 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/persistence/mybatis/ReferenceGenomeGeneMyBatisRepository.java @@ -0,0 +1,50 @@ +package org.cbioportal.legacy.persistence.mybatis; + +import java.util.List; +import org.cbioportal.legacy.model.ReferenceGenomeGene; +import org.cbioportal.legacy.persistence.PersistenceConstants; +import org.cbioportal.legacy.persistence.ReferenceGenomeGeneRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Repository; + +@Repository +public class ReferenceGenomeGeneMyBatisRepository implements ReferenceGenomeGeneRepository { + + @Autowired private ReferenceGenomeGeneMapper referenceGenomeGeneMapper; + + @Override + public List getAllGenesByGenomeName(String genomeName) { + + return referenceGenomeGeneMapper.getAllGenesByGenomeName( + genomeName, PersistenceConstants.SUMMARY_PROJECTION); + } + + @Override + public List getGenesByHugoGeneSymbolsAndGenomeName( + List geneIds, String genomeName) { + + return referenceGenomeGeneMapper.getGenesByHugoGeneSymbolsAndGenomeName( + geneIds, genomeName, PersistenceConstants.SUMMARY_PROJECTION); + } + + @Override + public List getGenesByGenomeName(List geneIds, String genomeName) { + + return referenceGenomeGeneMapper.getGenesByGenomeName( + geneIds, genomeName, PersistenceConstants.SUMMARY_PROJECTION); + } + + @Override + public ReferenceGenomeGene getReferenceGenomeGene(Integer geneId, String genomeName) { + + return referenceGenomeGeneMapper.getReferenceGenomeGene( + geneId, genomeName, PersistenceConstants.SUMMARY_PROJECTION); + } + + @Override + public ReferenceGenomeGene getReferenceGenomeGeneByEntityId( + Integer geneticEntityId, String genomeName) { + return referenceGenomeGeneMapper.getReferenceGenomeGeneByEntityId( + geneticEntityId, genomeName, PersistenceConstants.SUMMARY_PROJECTION); + } +} diff --git a/src/main/java/org/cbioportal/legacy/persistence/mybatis/ResourceDataMapper.java b/src/main/java/org/cbioportal/legacy/persistence/mybatis/ResourceDataMapper.java new file mode 100644 index 00000000000..a712646c9ea --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/persistence/mybatis/ResourceDataMapper.java @@ -0,0 +1,54 @@ +package org.cbioportal.legacy.persistence.mybatis; + +import java.util.List; +import org.cbioportal.legacy.model.ResourceData; + +public interface ResourceDataMapper { + + List getResourceDataOfSampleInStudy( + String studyId, + String sampleId, + String resourceId, + String projection, + Integer limit, + Integer offset, + String sortBy, + String direction); + + List getResourceDataOfPatientInStudy( + String studyId, + String patientId, + String resourceId, + String projection, + Integer limit, + Integer offset, + String sortBy, + String direction); + + List getResourceDataForStudy( + String studyId, + String resourceId, + String projection, + Integer limit, + Integer offset, + String sortBy, + String direction); + + List getResourceDataForAllPatientsInStudy( + String studyId, + String resourceId, + String projection, + Integer limit, + Integer offset, + String sortBy, + String direction); + + List getResourceDataForAllSamplesInStudy( + String studyId, + String resourceId, + String projection, + Integer limit, + Integer offset, + String sortBy, + String direction); +} diff --git a/src/main/java/org/cbioportal/legacy/persistence/mybatis/ResourceDataMyBatisRepository.java b/src/main/java/org/cbioportal/legacy/persistence/mybatis/ResourceDataMyBatisRepository.java new file mode 100644 index 00000000000..ed0088ae731 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/persistence/mybatis/ResourceDataMyBatisRepository.java @@ -0,0 +1,118 @@ +package org.cbioportal.legacy.persistence.mybatis; + +import java.util.List; +import org.cbioportal.legacy.model.ResourceData; +import org.cbioportal.legacy.persistence.ResourceDataRepository; +import org.cbioportal.legacy.persistence.mybatis.util.PaginationCalculator; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Repository; + +@Repository +public class ResourceDataMyBatisRepository implements ResourceDataRepository { + + @Autowired private ResourceDataMapper resourceDataMapper; + + @Override + public List getAllResourceDataOfSampleInStudy( + String studyId, + String sampleId, + String resourceId, + String projection, + Integer pageSize, + Integer pageNumber, + String sortBy, + String direction) { + + return resourceDataMapper.getResourceDataOfSampleInStudy( + studyId, + sampleId, + resourceId, + projection, + pageSize, + PaginationCalculator.offset(pageSize, pageNumber), + sortBy, + direction); + } + + @Override + public List getAllResourceDataOfPatientInStudy( + String studyId, + String patientId, + String resourceId, + String projection, + Integer pageSize, + Integer pageNumber, + String sortBy, + String direction) { + + return resourceDataMapper.getResourceDataOfPatientInStudy( + studyId, + patientId, + resourceId, + projection, + pageSize, + PaginationCalculator.offset(pageSize, pageNumber), + sortBy, + direction); + } + + @Override + public List getAllResourceDataForStudy( + String studyId, + String resourceId, + String projection, + Integer pageSize, + Integer pageNumber, + String sortBy, + String direction) { + + return resourceDataMapper.getResourceDataForStudy( + studyId, + resourceId, + projection, + pageSize, + PaginationCalculator.offset(pageSize, pageNumber), + sortBy, + direction); + } + + @Override + public List getResourceDataForAllPatientsInStudy( + String studyId, + String resourceId, + String projection, + Integer pageSize, + Integer pageNumber, + String sortBy, + String direction) { + + return resourceDataMapper.getResourceDataForAllPatientsInStudy( + studyId, + resourceId, + projection, + pageSize, + PaginationCalculator.offset(pageSize, pageNumber), + sortBy, + direction); + } + + @Override + public List getResourceDataForAllSamplesInStudy( + String studyId, + String resourceId, + String projection, + Integer pageSize, + Integer pageNumber, + String sortBy, + String direction) { + + return resourceDataMapper.getResourceDataForAllSamplesInStudy( + studyId, + resourceId, + projection, + pageSize, + PaginationCalculator.offset(pageSize, pageNumber), + sortBy, + direction); + } +} diff --git a/src/main/java/org/cbioportal/legacy/persistence/mybatis/ResourceDefinitionMapper.java b/src/main/java/org/cbioportal/legacy/persistence/mybatis/ResourceDefinitionMapper.java new file mode 100644 index 00000000000..97fc15f6e53 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/persistence/mybatis/ResourceDefinitionMapper.java @@ -0,0 +1,17 @@ +package org.cbioportal.legacy.persistence.mybatis; + +import java.util.List; +import org.cbioportal.legacy.model.ResourceDefinition; + +public interface ResourceDefinitionMapper { + + ResourceDefinition getResourceDefinition(String studyId, String resourceId, String projection); + + List getResourceDefinitions( + List studyIds, + String projection, + Integer limit, + Integer offset, + String sortBy, + String direction); +} diff --git a/src/main/java/org/cbioportal/legacy/persistence/mybatis/ResourceDefinitionMyBatisRepository.java b/src/main/java/org/cbioportal/legacy/persistence/mybatis/ResourceDefinitionMyBatisRepository.java new file mode 100644 index 00000000000..a6174a2c4b4 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/persistence/mybatis/ResourceDefinitionMyBatisRepository.java @@ -0,0 +1,38 @@ +package org.cbioportal.legacy.persistence.mybatis; + +import java.util.List; +import org.cbioportal.legacy.model.ResourceDefinition; +import org.cbioportal.legacy.persistence.PersistenceConstants; +import org.cbioportal.legacy.persistence.ResourceDefinitionRepository; +import org.cbioportal.legacy.persistence.mybatis.util.PaginationCalculator; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Repository; + +@Repository +public class ResourceDefinitionMyBatisRepository implements ResourceDefinitionRepository { + + @Autowired private ResourceDefinitionMapper resourceDefinitionMapper; + + @Override + public ResourceDefinition getResourceDefinition(String studyId, String resourceId) { + return resourceDefinitionMapper.getResourceDefinition( + studyId, resourceId, PersistenceConstants.DETAILED_PROJECTION); + } + + @Override + public List fetchResourceDefinitions( + List studyIds, + String projection, + Integer pageSize, + Integer pageNumber, + String sortBy, + String direction) { + return resourceDefinitionMapper.getResourceDefinitions( + studyIds, + projection, + pageSize, + PaginationCalculator.offset(pageSize, pageNumber), + sortBy, + direction); + } +} diff --git a/src/main/java/org/cbioportal/legacy/persistence/mybatis/SampleListMapper.java b/src/main/java/org/cbioportal/legacy/persistence/mybatis/SampleListMapper.java new file mode 100644 index 00000000000..c900e909f67 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/persistence/mybatis/SampleListMapper.java @@ -0,0 +1,27 @@ +package org.cbioportal.legacy.persistence.mybatis; + +import java.util.List; +import org.cbioportal.legacy.model.SampleList; +import org.cbioportal.legacy.model.SampleListToSampleId; +import org.cbioportal.legacy.model.meta.BaseMeta; + +public interface SampleListMapper { + + List getAllSampleLists( + List studyIds, + String projection, + Integer limit, + Integer offset, + String sortBy, + String direction); + + BaseMeta getMetaSampleLists(String studyId); + + SampleList getSampleList(String sampleListId, String projection); + + List getSampleLists(List sampleListIds, String projection); + + List getAllSampleIdsInSampleList(String sampleListId); + + List getSampleListSampleIds(List sampleListIds); +} diff --git a/src/main/java/org/cbioportal/legacy/persistence/mybatis/SampleListMyBatisRepository.java b/src/main/java/org/cbioportal/legacy/persistence/mybatis/SampleListMyBatisRepository.java new file mode 100644 index 00000000000..cec6e3cc7ac --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/persistence/mybatis/SampleListMyBatisRepository.java @@ -0,0 +1,88 @@ +package org.cbioportal.legacy.persistence.mybatis; + +import java.util.List; +import org.cbioportal.legacy.model.SampleList; +import org.cbioportal.legacy.model.SampleListToSampleId; +import org.cbioportal.legacy.model.meta.BaseMeta; +import org.cbioportal.legacy.persistence.PersistenceConstants; +import org.cbioportal.legacy.persistence.SampleListRepository; +import org.cbioportal.legacy.persistence.mybatis.util.PaginationCalculator; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Repository; + +@Repository +public class SampleListMyBatisRepository implements SampleListRepository { + + @Autowired private SampleListMapper sampleListMapper; + + @Override + public List getAllSampleLists( + String projection, Integer pageSize, Integer pageNumber, String sortBy, String direction) { + + return sampleListMapper.getAllSampleLists( + null, + projection, + pageSize, + PaginationCalculator.offset(pageSize, pageNumber), + sortBy, + direction); + } + + @Override + public BaseMeta getMetaSampleLists() { + + return sampleListMapper.getMetaSampleLists(null); + } + + @Override + public SampleList getSampleList(String sampleListId) { + + return sampleListMapper.getSampleList(sampleListId, PersistenceConstants.DETAILED_PROJECTION); + } + + @Override + public List getSampleLists(List sampleListIds, String projection) { + + return sampleListMapper.getSampleLists(sampleListIds, projection); + } + + @Override + public List getAllSampleListsInStudies( + List studyIds, + String projection, + Integer pageSize, + Integer pageNumber, + String sortBy, + String direction) { + + return sampleListMapper.getAllSampleLists( + studyIds, + projection, + pageSize, + PaginationCalculator.offset(pageSize, pageNumber), + sortBy, + direction); + } + + @Override + public BaseMeta getMetaSampleListsInStudy(String studyId) { + + return sampleListMapper.getMetaSampleLists(studyId); + } + + @Override + public List getAllSampleIdsInSampleList(String sampleListId) { + + return sampleListMapper.getAllSampleIdsInSampleList(sampleListId); + } + + @Override + @Cacheable( + cacheResolver = "staticRepositoryCacheOneResolver", + condition = "@cacheEnabledConfig.getEnabled()") + public List getSampleListSampleIds(List sampleListIds) { + + return sampleListMapper.getSampleListSampleIds(sampleListIds); + } +} diff --git a/src/main/java/org/cbioportal/legacy/persistence/mybatis/SampleMapper.java b/src/main/java/org/cbioportal/legacy/persistence/mybatis/SampleMapper.java new file mode 100644 index 00000000000..b68a34778fa --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/persistence/mybatis/SampleMapper.java @@ -0,0 +1,35 @@ +package org.cbioportal.legacy.persistence.mybatis; + +import java.util.List; +import org.cbioportal.legacy.model.Sample; +import org.cbioportal.legacy.model.meta.BaseMeta; + +public interface SampleMapper { + + List getSamples( + List studyIds, + String patientId, + List sampleIds, + String keyword, + String projection, + Integer limit, + Integer offset, + String sortBy, + String direction); + + List getSamplesBySampleListIds(List sampleListIds, String projection); + + BaseMeta getMetaSamples( + List studyIds, String patientId, List sampleIds, String keyword); + + BaseMeta getMetaSamplesBySampleListIds(List sampleListIds); + + Sample getSample(String studyId, String sampleId, String projection); + + List getSamplesByInternalIds(List internalIds, String projection); + + List getSamplesOfPatients(String studyId, List patientIds, String projection); + + List getSamplesOfPatientsInMultipleStudies( + List studyIds, List patientIds, String projection); +} diff --git a/src/main/java/org/cbioportal/legacy/persistence/mybatis/SampleMyBatisRepository.java b/src/main/java/org/cbioportal/legacy/persistence/mybatis/SampleMyBatisRepository.java new file mode 100644 index 00000000000..37a79c0df11 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/persistence/mybatis/SampleMyBatisRepository.java @@ -0,0 +1,184 @@ +package org.cbioportal.legacy.persistence.mybatis; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; +import org.cbioportal.legacy.model.Sample; +import org.cbioportal.legacy.model.meta.BaseMeta; +import org.cbioportal.legacy.persistence.PersistenceConstants; +import org.cbioportal.legacy.persistence.SampleRepository; +import org.cbioportal.legacy.persistence.mybatis.util.PaginationCalculator; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Repository; + +@Repository +public class SampleMyBatisRepository implements SampleRepository { + + @Autowired private SampleMapper sampleMapper; + + @Override + public List getAllSamples( + String keyword, + List studyIds, + String projection, + Integer pageSize, + Integer pageNumber, + String sort, + String direction) { + return sampleMapper.getSamples( + studyIds, + null, + null, + keyword, + projection, + pageSize, + PaginationCalculator.offset(pageSize, pageNumber), + sort, + direction); + } + + @Override + public BaseMeta getMetaSamples(String keyword, List studyIds) { + return sampleMapper.getMetaSamples(studyIds, null, null, keyword); + } + + @Override + public List getAllSamplesInStudy( + String studyId, + String projection, + Integer pageSize, + Integer pageNumber, + String sortBy, + String direction) { + + return sampleMapper.getSamples( + Arrays.asList(studyId), + null, + null, + null, + projection, + pageSize, + PaginationCalculator.offset(pageSize, pageNumber), + sortBy, + direction); + } + + @Override + public BaseMeta getMetaSamplesInStudy(String studyId) { + + return sampleMapper.getMetaSamples(Arrays.asList(studyId), null, null, null); + } + + @Override + public List getAllSamplesInStudies( + List studyIds, + String projection, + Integer pageSize, + Integer pageNumber, + String sortBy, + String direction) { + return sampleMapper.getSamples( + studyIds, + null, + null, + null, + projection, + pageSize, + PaginationCalculator.offset(pageSize, pageNumber), + sortBy, + direction); + } + + @Override + public Sample getSampleInStudy(String studyId, String sampleId) { + + return sampleMapper.getSample(studyId, sampleId, PersistenceConstants.DETAILED_PROJECTION); + } + + @Override + public List getAllSamplesOfPatientInStudy( + String studyId, + String patientId, + String projection, + Integer pageSize, + Integer pageNumber, + String sortBy, + String direction) { + + return sampleMapper.getSamples( + Arrays.asList(studyId), + patientId, + null, + null, + projection, + pageSize, + PaginationCalculator.offset(pageSize, pageNumber), + sortBy, + direction); + } + + @Override + public BaseMeta getMetaSamplesOfPatientInStudy(String studyId, String patientId) { + + return sampleMapper.getMetaSamples(Arrays.asList(studyId), patientId, null, null); + } + + @Override + public List getAllSamplesOfPatientsInStudy( + String studyId, List patientIds, String projection) { + + return sampleMapper.getSamplesOfPatients(studyId, patientIds, projection); + } + + @Override + public List getSamplesOfPatientsInMultipleStudies( + List studyIds, List patientIds, String projection) { + + return sampleMapper.getSamplesOfPatientsInMultipleStudies(studyIds, patientIds, projection); + } + + @Override + public List fetchSamples( + List studyIds, List sampleIds, String projection) { + + return sampleMapper.getSamples(studyIds, null, sampleIds, null, projection, 0, 0, null, null); + } + + @Override + public List fetchSamplesBySampleListIds(List sampleListIds, String projection) { + // Rather than get all the samples for all the sample list IDs all at once, + // we get them 1 sample list ID at a time. This allows for more efficient caching, since + // the samples associated with each sample list are only cached once. + // We also need to remove duplicates samples because samples from multiple sample list IDs can + // have overlapping + return sampleListIds.stream() + .flatMap(id -> fetchSampleBySampleListId(id, projection).stream()) + .distinct() + .collect(Collectors.toList()); + } + + @Override + public List fetchSampleBySampleListId(String sampleListId, String projection) { + return sampleMapper.getSamplesBySampleListIds( + Collections.singletonList(sampleListId), projection); + } + + @Override + public BaseMeta fetchMetaSamples(List studyIds, List sampleIds) { + + return sampleMapper.getMetaSamples(studyIds, null, sampleIds, null); + } + + @Override + public BaseMeta fetchMetaSamples(List sampleListIds) { + + return sampleMapper.getMetaSamplesBySampleListIds(sampleListIds); + } + + @Override + public List getSamplesByInternalIds(List internalIds) { + + return sampleMapper.getSamplesByInternalIds(internalIds, PersistenceConstants.ID_PROJECTION); + } +} diff --git a/src/main/java/org/cbioportal/legacy/persistence/mybatis/SecurityMapper.java b/src/main/java/org/cbioportal/legacy/persistence/mybatis/SecurityMapper.java new file mode 100644 index 00000000000..ce7d120e4e7 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/persistence/mybatis/SecurityMapper.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2015 Memorial Sloan-Kettering Cancer Center. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS + * FOR A PARTICULAR PURPOSE. The software and documentation provided hereunder + * is on an "as is" basis, and Memorial Sloan-Kettering Cancer Center has no + * obligations to provide maintenance, support, updates, enhancements or + * modifications. In no event shall Memorial Sloan-Kettering Cancer Center be + * liable to any party for direct, indirect, special, incidental or + * consequential damages, including lost profits, arising out of the use of this + * software and its documentation, even if Memorial Sloan-Kettering Cancer + * Center has been advised of the possibility of such damage. + */ + +/* + * This file is part of cBioPortal. + * + * cBioPortal is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package org.cbioportal.legacy.persistence.mybatis; + +// imports +import org.apache.ibatis.annotations.Param; +import org.cbioportal.legacy.model.User; +import org.cbioportal.legacy.model.UserAuthorities; + +/** Interface to use to retrieve portal user information. */ +public interface SecurityMapper { + + /** + * Given a user id, returns a user instance. If username does not exist in db, returns null. + * + * @param username String + * @return User + */ + User getPortalUser(@Param("username") String username); + + /** + * Given a user id, returns a UserAuthorities instance. If username does not exist in db, returns + * null. + * + * @param username String + * @return User + */ + UserAuthorities getPortalUserAuthorities(@Param("username") String username); + + void addPortalUser(User user); + + void addPortalUserAuthority(@Param("email") String email, @Param("authority") String authority); + + /** + * Given an internal cancer study id, returns groups string. Returns null if cancer study does not + * exist. + * + * @param internalCancerStudyId Integer + * @return String groups + */ + String getCancerStudyGroups(Integer internalCancerStudyId); +} diff --git a/src/main/java/org/cbioportal/legacy/persistence/mybatis/SecurityMyBatisRepository.java b/src/main/java/org/cbioportal/legacy/persistence/mybatis/SecurityMyBatisRepository.java new file mode 100644 index 00000000000..fb0b073a4f2 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/persistence/mybatis/SecurityMyBatisRepository.java @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2015 Memorial Sloan-Kettering Cancer Center. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS + * FOR A PARTICULAR PURPOSE. The software and documentation provided hereunder + * is on an "as is" basis, and Memorial Sloan-Kettering Cancer Center has no + * obligations to provide maintenance, support, updates, enhancements or + * modifications. In no event shall Memorial Sloan-Kettering Cancer Center be + * liable to any party for direct, indirect, special, incidental or + * consequential damages, including lost profits, arising out of the use of this + * software and its documentation, even if Memorial Sloan-Kettering Cancer + * Center has been advised of the possibility of such damage. + */ + +/* + * This file is part of cBioPortal. + * + * cBioPortal is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package org.cbioportal.legacy.persistence.mybatis; + +// imports +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; +import org.cbioportal.legacy.model.User; +import org.cbioportal.legacy.model.UserAuthorities; +import org.cbioportal.legacy.persistence.SecurityRepository; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Repository; + +@Repository +public class SecurityMyBatisRepository implements SecurityRepository { + + private static final Logger log = LoggerFactory.getLogger(SecurityMyBatisRepository.class); + + @Autowired private SecurityMapper securityMapper; + + /** + * Given a user id, returns a user instance. If username does not exist in db, returns null. + * + * @param username String + * @return User + */ + @Override + public User getPortalUser(String username) { + User user = securityMapper.getPortalUser(username); + if (user != null) { + log.debug("User " + username + " was found in the users table, email is " + user.getEmail()); + } else { + log.debug("User " + username + " is null"); + } + return user; + } + + /** + * Given a user id, returns a UserAuthorities instance. If username does not exist in db, returns + * null. + * + * @param username String + * @return UserAuthorities + */ + @Override + public UserAuthorities getPortalUserAuthorities(String username) { + return securityMapper.getPortalUserAuthorities(username); + } + + @Override + public void addPortalUser(User user) { + securityMapper.addPortalUser(user); + } + + @Override + public void addPortalUserAuthorities(UserAuthorities userAuthorities) { + for (String authority : userAuthorities.getAuthorities()) { + securityMapper.addPortalUserAuthority(userAuthorities.getEmail(), authority); + } + } + + /** + * Given an internal cancer study id, returns a set of upper case cancer study group strings. + * Returns empty set if cancer study does not exist or there are no groups. + * + * @param internalCancerStudyId Integer + * @return Set cancer study group strings in upper case + */ + @Override + public Set getCancerStudyGroups(Integer internalCancerStudyId) { + String groups = securityMapper.getCancerStudyGroups(internalCancerStudyId); + if (groups == null) { + return Collections.emptySet(); + } + return new HashSet(Arrays.asList(groups.toUpperCase().split(";"))); + } +} diff --git a/src/main/java/org/cbioportal/legacy/persistence/mybatis/SignificantCopyNumberRegionMapper.java b/src/main/java/org/cbioportal/legacy/persistence/mybatis/SignificantCopyNumberRegionMapper.java new file mode 100644 index 00000000000..a64fc96f767 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/persistence/mybatis/SignificantCopyNumberRegionMapper.java @@ -0,0 +1,21 @@ +package org.cbioportal.legacy.persistence.mybatis; + +import java.util.List; +import org.cbioportal.legacy.model.Gistic; +import org.cbioportal.legacy.model.GisticToGene; +import org.cbioportal.legacy.model.meta.BaseMeta; + +public interface SignificantCopyNumberRegionMapper { + + List getSignificantCopyNumberRegions( + String studyId, + String projection, + Integer limit, + Integer offset, + String sortBy, + String direction); + + BaseMeta getMetaSignificantCopyNumberRegions(String studyId); + + List getGenesOfRegions(List gisticRoiIds); +} diff --git a/src/main/java/org/cbioportal/legacy/persistence/mybatis/SignificantCopyNumberRegionMyBatisRepository.java b/src/main/java/org/cbioportal/legacy/persistence/mybatis/SignificantCopyNumberRegionMyBatisRepository.java new file mode 100644 index 00000000000..cb546c7ddc2 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/persistence/mybatis/SignificantCopyNumberRegionMyBatisRepository.java @@ -0,0 +1,47 @@ +package org.cbioportal.legacy.persistence.mybatis; + +import java.util.List; +import org.cbioportal.legacy.model.Gistic; +import org.cbioportal.legacy.model.GisticToGene; +import org.cbioportal.legacy.model.meta.BaseMeta; +import org.cbioportal.legacy.persistence.SignificantCopyNumberRegionRepository; +import org.cbioportal.legacy.persistence.mybatis.util.PaginationCalculator; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Repository; + +@Repository +public class SignificantCopyNumberRegionMyBatisRepository + implements SignificantCopyNumberRegionRepository { + + @Autowired private SignificantCopyNumberRegionMapper significantCopyNumberRegionMapper; + + @Override + public List getSignificantCopyNumberRegions( + String studyId, + String projection, + Integer pageSize, + Integer pageNumber, + String sortBy, + String direction) { + + return significantCopyNumberRegionMapper.getSignificantCopyNumberRegions( + studyId, + projection, + pageSize, + PaginationCalculator.offset(pageSize, pageNumber), + sortBy, + direction); + } + + @Override + public BaseMeta getMetaSignificantCopyNumberRegions(String studyId) { + + return significantCopyNumberRegionMapper.getMetaSignificantCopyNumberRegions(studyId); + } + + @Override + public List getGenesOfRegions(List gisticRoiIds) { + + return significantCopyNumberRegionMapper.getGenesOfRegions(gisticRoiIds); + } +} diff --git a/src/main/java/org/cbioportal/legacy/persistence/mybatis/SignificantlyMutatedGeneMapper.java b/src/main/java/org/cbioportal/legacy/persistence/mybatis/SignificantlyMutatedGeneMapper.java new file mode 100644 index 00000000000..b9fdfb877bf --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/persistence/mybatis/SignificantlyMutatedGeneMapper.java @@ -0,0 +1,18 @@ +package org.cbioportal.legacy.persistence.mybatis; + +import java.util.List; +import org.cbioportal.legacy.model.MutSig; +import org.cbioportal.legacy.model.meta.BaseMeta; + +public interface SignificantlyMutatedGeneMapper { + + List getSignificantlyMutatedGenes( + String studyId, + String projection, + Integer limit, + Integer offset, + String sortBy, + String direction); + + BaseMeta getMetaSignificantlyMutatedGenes(String studyId); +} diff --git a/src/main/java/org/cbioportal/legacy/persistence/mybatis/SignificantlyMutatedGeneMyBatisRepository.java b/src/main/java/org/cbioportal/legacy/persistence/mybatis/SignificantlyMutatedGeneMyBatisRepository.java new file mode 100644 index 00000000000..505ba663fad --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/persistence/mybatis/SignificantlyMutatedGeneMyBatisRepository.java @@ -0,0 +1,40 @@ +package org.cbioportal.legacy.persistence.mybatis; + +import java.util.List; +import org.cbioportal.legacy.model.MutSig; +import org.cbioportal.legacy.model.meta.BaseMeta; +import org.cbioportal.legacy.persistence.SignificantlyMutatedGeneRepository; +import org.cbioportal.legacy.persistence.mybatis.util.PaginationCalculator; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Repository; + +@Repository +public class SignificantlyMutatedGeneMyBatisRepository + implements SignificantlyMutatedGeneRepository { + + @Autowired private SignificantlyMutatedGeneMapper significantlyMutatedGeneMapper; + + @Override + public List getSignificantlyMutatedGenes( + String studyId, + String projection, + Integer pageSize, + Integer pageNumber, + String sortBy, + String direction) { + + return significantlyMutatedGeneMapper.getSignificantlyMutatedGenes( + studyId, + projection, + pageSize, + PaginationCalculator.offset(pageSize, pageNumber), + sortBy, + direction); + } + + @Override + public BaseMeta getMetaSignificantlyMutatedGenes(String studyId) { + + return significantlyMutatedGeneMapper.getMetaSignificantlyMutatedGenes(studyId); + } +} diff --git a/src/main/java/org/cbioportal/legacy/persistence/mybatis/StaticDataTimeStampMyBatisRepository.java b/src/main/java/org/cbioportal/legacy/persistence/mybatis/StaticDataTimeStampMyBatisRepository.java new file mode 100644 index 00000000000..066eafd21e8 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/persistence/mybatis/StaticDataTimeStampMyBatisRepository.java @@ -0,0 +1,21 @@ +package org.cbioportal.legacy.persistence.mybatis; + +import java.util.List; +import org.cbioportal.legacy.model.TableTimestampPair; +import org.cbioportal.legacy.persistence.StaticDataTimeStampRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Repository; + +@Repository +public class StaticDataTimeStampMyBatisRepository implements StaticDataTimeStampRepository { + @Value("${db.portal_db_name:}") + private String dbName; + + @Autowired private StaticDataTimestampMapper staticDataTimestampMapper; + + @Override + public List getTimestamps(List tableNames) { + return staticDataTimestampMapper.getTimestamps(tableNames, dbName); + } +} diff --git a/src/main/java/org/cbioportal/legacy/persistence/mybatis/StaticDataTimestampMapper.java b/src/main/java/org/cbioportal/legacy/persistence/mybatis/StaticDataTimestampMapper.java new file mode 100644 index 00000000000..13a604c28e9 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/persistence/mybatis/StaticDataTimestampMapper.java @@ -0,0 +1,8 @@ +package org.cbioportal.legacy.persistence.mybatis; + +import java.util.List; +import org.cbioportal.legacy.model.TableTimestampPair; + +public interface StaticDataTimestampMapper { + List getTimestamps(List tables, String dbName); +} diff --git a/src/main/java/org/cbioportal/legacy/persistence/mybatis/StructuralVariantMapper.java b/src/main/java/org/cbioportal/legacy/persistence/mybatis/StructuralVariantMapper.java new file mode 100644 index 00000000000..26c5aa373b7 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/persistence/mybatis/StructuralVariantMapper.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2018 The Hyve B.V. + * This code is licensed under the GNU Affero General Public License (AGPL), + * version 3, or (at your option) any later version. + */ + +/* + * This file is part of cBioPortal. + * + * cBioPortal is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package org.cbioportal.legacy.persistence.mybatis; + +import java.util.List; +import org.cbioportal.legacy.model.GeneFilterQuery; +import org.cbioportal.legacy.model.StructuralVariant; +import org.cbioportal.legacy.model.StructuralVariantFilterQuery; +import org.cbioportal.legacy.model.StructuralVariantQuery; + +public interface StructuralVariantMapper { + + List fetchStructuralVariants( + List molecularProfileIds, + List sampleIds, + List entrezGeneIds, + List structuralVariantQueries); + + List fetchStructuralVariantsByGeneQueries( + List molecularProfileIds, List sampleIds, List geneQueries); + + List fetchStructuralVariantsByStructVarQueries( + List molecularProfileIds, + List sampleIds, + List structVarQueries); +} diff --git a/src/main/java/org/cbioportal/legacy/persistence/mybatis/StructuralVariantMyBatisRepository.java b/src/main/java/org/cbioportal/legacy/persistence/mybatis/StructuralVariantMyBatisRepository.java new file mode 100644 index 00000000000..f7dbe4ae3aa --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/persistence/mybatis/StructuralVariantMyBatisRepository.java @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2018 The Hyve B.V. + * This code is licensed under the GNU Affero General Public License (AGPL), + * version 3, or (at your option) any later version. + */ + +/* + * This file is part of cBioPortal. + * + * cBioPortal is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package org.cbioportal.legacy.persistence.mybatis; + +import static java.util.Arrays.asList; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; +import org.cbioportal.legacy.model.GeneFilterQuery; +import org.cbioportal.legacy.model.StructuralVariant; +import org.cbioportal.legacy.model.StructuralVariantFilterQuery; +import org.cbioportal.legacy.model.StructuralVariantQuery; +import org.cbioportal.legacy.persistence.StructuralVariantRepository; +import org.cbioportal.legacy.persistence.mybatis.util.MolecularProfileCaseIdentifierUtil; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Repository; + +@Repository +public class StructuralVariantMyBatisRepository implements StructuralVariantRepository { + + @Autowired private StructuralVariantMapper structuralVariantMapper; + @Autowired private MolecularProfileCaseIdentifierUtil molecularProfileCaseIdentifierUtil; + + @Override + public List fetchStructuralVariants( + List molecularProfileIds, + List sampleIds, + List entrezGeneIds, + List structuralVariantQueries) { + if (molecularProfileIds == null || molecularProfileIds.isEmpty()) { + return new ArrayList<>(); + } + return molecularProfileCaseIdentifierUtil + .getGroupedCasesByMolecularProfileId(molecularProfileIds, sampleIds) + .entrySet() + .stream() + .flatMap( + entry -> + structuralVariantMapper + .fetchStructuralVariants( + asList(entry.getKey()), + new ArrayList<>(entry.getValue()), + entrezGeneIds, + structuralVariantQueries) + .stream()) + .collect(Collectors.toList()); + } + + @Override + public List fetchStructuralVariantsByGeneQueries( + List molecularProfileIds, List sampleIds, List geneQueries) { + if (geneQueries == null + || geneQueries.isEmpty() + || molecularProfileIds == null + || molecularProfileIds.isEmpty()) { + return new ArrayList<>(); + } + return structuralVariantMapper.fetchStructuralVariantsByGeneQueries( + molecularProfileIds, sampleIds, geneQueries); + } + + @Override + public List fetchStructuralVariantsByStructVarQueries( + List molecularProfileIds, + List sampleIds, + List structVarQueries) { + if (structVarQueries == null + || structVarQueries.isEmpty() + || molecularProfileIds == null + || molecularProfileIds.isEmpty()) { + return new ArrayList<>(); + } + return structuralVariantMapper.fetchStructuralVariantsByStructVarQueries( + molecularProfileIds, sampleIds, structVarQueries); + } +} diff --git a/src/main/java/org/cbioportal/legacy/persistence/mybatis/StudyMapper.java b/src/main/java/org/cbioportal/legacy/persistence/mybatis/StudyMapper.java new file mode 100644 index 00000000000..9d8ce6d74fb --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/persistence/mybatis/StudyMapper.java @@ -0,0 +1,26 @@ +package org.cbioportal.legacy.persistence.mybatis; + +import java.util.List; +import org.cbioportal.legacy.model.CancerStudy; +import org.cbioportal.legacy.model.CancerStudyTags; +import org.cbioportal.legacy.model.meta.BaseMeta; + +public interface StudyMapper { + + List getStudies( + List studyIds, + String keyword, + String projection, + Integer limit, + Integer offset, + String sortBy, + String direction); + + BaseMeta getMetaStudies(List studyIds, String keyword); + + CancerStudy getStudy(String studyId, String projection); + + CancerStudyTags getTags(String studyId); + + List getTagsForMultipleStudies(List studyIds); +} diff --git a/src/main/java/org/cbioportal/legacy/persistence/mybatis/StudyMyBatisRepository.java b/src/main/java/org/cbioportal/legacy/persistence/mybatis/StudyMyBatisRepository.java new file mode 100644 index 00000000000..3128ecbc2e7 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/persistence/mybatis/StudyMyBatisRepository.java @@ -0,0 +1,71 @@ +package org.cbioportal.legacy.persistence.mybatis; + +import java.util.ArrayList; +import java.util.List; +import org.cbioportal.legacy.model.CancerStudy; +import org.cbioportal.legacy.model.CancerStudyTags; +import org.cbioportal.legacy.model.meta.BaseMeta; +import org.cbioportal.legacy.persistence.StudyRepository; +import org.cbioportal.legacy.persistence.mybatis.util.PaginationCalculator; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Repository; + +@Repository +public class StudyMyBatisRepository implements StudyRepository { + + @Autowired private StudyMapper studyMapper; + + @Override + public List getAllStudies( + String keyword, + String projection, + Integer pageSize, + Integer pageNumber, + String sortBy, + String direction) { + + return studyMapper.getStudies( + null, + keyword, + projection, + pageSize, + PaginationCalculator.offset(pageSize, pageNumber), + sortBy, + direction); + } + + @Override + public BaseMeta getMetaStudies(String keyword) { + return studyMapper.getMetaStudies(null, keyword); + } + + @Override + public CancerStudy getStudy(String studyId, String projection) { + return studyMapper.getStudy(studyId, projection); + } + + @Override + public List fetchStudies(List studyIds, String projection) { + + return studyMapper.getStudies(studyIds, null, projection, 0, 0, null, null); + } + + @Override + public BaseMeta fetchMetaStudies(List studyIds) { + + return studyMapper.getMetaStudies(studyIds, null); + } + + @Override + public CancerStudyTags getTags(String studyId) { + return studyMapper.getTags(studyId); + } + + @Override + public List getTagsForMultipleStudies(List studyIds) { + if (studyIds == null || studyIds.isEmpty()) { + return new ArrayList<>(); + } + return studyMapper.getTagsForMultipleStudies(studyIds); + } +} diff --git a/src/main/java/org/cbioportal/legacy/persistence/mybatis/TreatmentMapper.java b/src/main/java/org/cbioportal/legacy/persistence/mybatis/TreatmentMapper.java new file mode 100644 index 00000000000..4e71db476bf --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/persistence/mybatis/TreatmentMapper.java @@ -0,0 +1,17 @@ +package org.cbioportal.legacy.persistence.mybatis; + +import java.util.List; +import org.cbioportal.legacy.model.ClinicalEventSample; +import org.cbioportal.legacy.model.Treatment; + +public interface TreatmentMapper { + List getAllTreatments(List sampleIds, List studyIds, String key); + + List getAllSamples(List sampleIds, List studyIds); + + List getAllShallowSamples(List sampleIds, List studyIds); + + Boolean hasTreatmentData(List sampleIds, List studyIds, String key); + + Boolean hasSampleTimelineData(List sampleIds, List studyIds); +} diff --git a/src/main/java/org/cbioportal/legacy/persistence/mybatis/TreatmentMyBatisRepository.java b/src/main/java/org/cbioportal/legacy/persistence/mybatis/TreatmentMyBatisRepository.java new file mode 100644 index 00000000000..bd87b950b92 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/persistence/mybatis/TreatmentMyBatisRepository.java @@ -0,0 +1,80 @@ +package org.cbioportal.legacy.persistence.mybatis; + +import static java.util.stream.Collectors.groupingBy; + +import java.util.*; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import org.cbioportal.legacy.model.ClinicalEventKeyCode; +import org.cbioportal.legacy.model.ClinicalEventSample; +import org.cbioportal.legacy.model.Treatment; +import org.cbioportal.legacy.persistence.TreatmentRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Repository; + +@Repository +public class TreatmentMyBatisRepository implements TreatmentRepository { + @Autowired private TreatmentMapper treatmentMapper; + + @Override + public Map> getTreatmentsByPatientId( + List sampleIds, List studyIds, ClinicalEventKeyCode key) { + return getTreatments(sampleIds, studyIds, key).stream() + .collect(groupingBy(Treatment::getPatientId)); + } + + @Override + public List getTreatments( + List sampleIds, List studyIds, ClinicalEventKeyCode key) { + return treatmentMapper.getAllTreatments(sampleIds, studyIds, key.getKey()).stream() + .flatMap(treatment -> splitIfDelimited(treatment, key)) + .collect(Collectors.toList()); + } + + private Stream splitIfDelimited(Treatment unsplitTreatment, ClinicalEventKeyCode key) { + if (key.isDelimited()) { + return Arrays.stream(unsplitTreatment.getTreatment().split(key.getDelimiter())) + .map( + treatmentName -> { + Treatment treatment = new Treatment(); + treatment.setTreatment(treatmentName); + treatment.setStudyId(unsplitTreatment.getStudyId()); + treatment.setPatientId(unsplitTreatment.getPatientId()); + treatment.setStart(unsplitTreatment.getStart()); + treatment.setStop(unsplitTreatment.getStop()); + treatment.setPatientId(unsplitTreatment.getPatientId()); + return treatment; + }); + } + return Stream.of(unsplitTreatment); + } + + @Override + public Map> getSamplesByPatientId( + List sampleIds, List studyIds) { + return treatmentMapper.getAllSamples(sampleIds, studyIds).stream() + .sorted( + Comparator.comparing(ClinicalEventSample::getTimeTaken)) // put earliest events first + .distinct() // uniqueness determined by sample id, patient id, and study id + // combined, the sort and distinct produce the earliest clinical event row for each unique + // sample + .collect(groupingBy(ClinicalEventSample::getPatientId)); + } + + public Map> getShallowSamplesByPatientId( + List sampleIds, List studyIds) { + return treatmentMapper.getAllShallowSamples(sampleIds, studyIds).stream() + .distinct() + .collect(groupingBy(ClinicalEventSample::getPatientId)); + } + + @Override + public Boolean hasTreatmentData(List studies, ClinicalEventKeyCode key) { + return treatmentMapper.hasTreatmentData(null, studies, key.getKey()); + } + + @Override + public Boolean hasSampleTimelineData(List studies) { + return treatmentMapper.hasSampleTimelineData(null, studies); + } +} diff --git a/src/main/java/org/cbioportal/legacy/persistence/mybatis/VariantCountMapper.java b/src/main/java/org/cbioportal/legacy/persistence/mybatis/VariantCountMapper.java new file mode 100644 index 00000000000..2097b2936d5 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/persistence/mybatis/VariantCountMapper.java @@ -0,0 +1,10 @@ +package org.cbioportal.legacy.persistence.mybatis; + +import java.util.List; +import org.cbioportal.legacy.model.VariantCount; + +public interface VariantCountMapper { + + List fetchVariantCounts( + String molecularProfileId, List entrezGeneIds, List keywords); +} diff --git a/src/main/java/org/cbioportal/legacy/persistence/mybatis/VariantCountMyBatisRepository.java b/src/main/java/org/cbioportal/legacy/persistence/mybatis/VariantCountMyBatisRepository.java new file mode 100644 index 00000000000..4762d26df99 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/persistence/mybatis/VariantCountMyBatisRepository.java @@ -0,0 +1,20 @@ +package org.cbioportal.legacy.persistence.mybatis; + +import java.util.List; +import org.cbioportal.legacy.model.VariantCount; +import org.cbioportal.legacy.persistence.VariantCountRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Repository; + +@Repository +public class VariantCountMyBatisRepository implements VariantCountRepository { + + @Autowired private VariantCountMapper variantCountMapper; + + @Override + public List fetchVariantCounts( + String molecularProfileId, List entrezGeneIds, List keywords) { + + return variantCountMapper.fetchVariantCounts(molecularProfileId, entrezGeneIds, keywords); + } +} diff --git a/src/main/java/org/cbioportal/legacy/persistence/mybatis/config/PersistenceConfig.java b/src/main/java/org/cbioportal/legacy/persistence/mybatis/config/PersistenceConfig.java new file mode 100644 index 00000000000..6fb2216baad --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/persistence/mybatis/config/PersistenceConfig.java @@ -0,0 +1,73 @@ +package org.cbioportal.legacy.persistence.mybatis.config; + +import java.io.IOException; +import javax.sql.DataSource; +import org.cbioportal.legacy.model.Sample; +import org.cbioportal.legacy.persistence.mybatis.typehandler.SampleTypeTypeHandler; +import org.cbioportal.legacy.utils.config.annotation.ConditionalOnProperty; +import org.mybatis.spring.SqlSessionFactoryBean; +import org.mybatis.spring.annotation.MapperScan; +import org.mybatis.spring.boot.autoconfigure.ConfigurationCustomizer; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.context.ApplicationContext; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Profile; +import org.springframework.jdbc.datasource.DataSourceTransactionManager; + +@Configuration +@MapperScan( + value = "org.cbioportal.legacy.persistence.mybatis", + sqlSessionFactoryRef = "sqlSessionFactory") +public class PersistenceConfig { + + // This is the only way I was able to register the SampleType TypeHandler to MyBatis. + // The bean-based approach described in the MyBatis docs for mybatis-spring-boot-autoconfigure + // did not work in my hands (See: + // https://mybatis.org/spring-boot-starter/mybatis-spring-boot-autoconfigure#Detecting_MyBatis_components). + @Bean + ConfigurationCustomizer mybatisConfigurationCustomizer() { + return new ConfigurationCustomizer() { + @Override + public void customize(org.apache.ibatis.session.Configuration configuration) { + configuration + .getTypeHandlerRegistry() + .register(Sample.SampleType.class, new SampleTypeTypeHandler()); + } + }; + } + + @Bean("sqlSessionFactory") + @Profile("clickhouse") + public SqlSessionFactoryBean sqlSessionFactorySpecifyDataSource( + @Qualifier("mysqlDataSource") DataSource dataSource, ApplicationContext applicationContext) + throws IOException { + return sqlSessionFactory(dataSource, applicationContext); + } + + @Bean("sqlSessionFactory") + @Profile("default") + @ConditionalOnProperty(name = "clickhouse_mode", havingValue = "false", matchIfMissing = true) + public SqlSessionFactoryBean sqlSessionFactoryDefault( + DataSource dataSource, ApplicationContext applicationContext) throws IOException { + return sqlSessionFactory(dataSource, applicationContext); + } + + private SqlSessionFactoryBean sqlSessionFactory( + DataSource dataSource, ApplicationContext applicationContext) throws IOException { + SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean(); + sessionFactory.setDataSource(dataSource); + sessionFactory.setMapperLocations( + applicationContext.getResources( + "classpath:org/cbioportal/legacy/persistence/mybatis/*.xml")); + sessionFactory.setTypeHandlers(new SampleTypeTypeHandler()); + return sessionFactory; + } + + @Bean + @Profile("clickhouse") + public DataSourceTransactionManager transactionManager( + @Qualifier("mysqlDataSource") DataSource dataSource) { + return new DataSourceTransactionManager(dataSource); + } +} diff --git a/src/main/java/org/cbioportal/legacy/persistence/mybatis/typehandler/SampleTypeTypeHandler.java b/src/main/java/org/cbioportal/legacy/persistence/mybatis/typehandler/SampleTypeTypeHandler.java new file mode 100644 index 00000000000..1fda5a1882c --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/persistence/mybatis/typehandler/SampleTypeTypeHandler.java @@ -0,0 +1,37 @@ +package org.cbioportal.legacy.persistence.mybatis.typehandler; + +import java.sql.CallableStatement; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import org.apache.ibatis.type.JdbcType; +import org.apache.ibatis.type.MappedTypes; +import org.apache.ibatis.type.TypeHandler; +import org.cbioportal.legacy.model.Sample; + +@MappedTypes(Sample.SampleType.class) +public class SampleTypeTypeHandler implements TypeHandler { + + @Override + public void setParameter( + PreparedStatement preparedStatement, int i, Sample.SampleType sampleType, JdbcType jdbcType) + throws SQLException { + preparedStatement.setString(i, sampleType.getValue()); + } + + @Override + public Sample.SampleType getResult(ResultSet resultSet, String s) throws SQLException { + return Sample.SampleType.fromString(resultSet.getString(s)); + } + + @Override + public Sample.SampleType getResult(ResultSet resultSet, int i) throws SQLException { + return Sample.SampleType.fromString(resultSet.getString(i)); + } + + @Override + public Sample.SampleType getResult(CallableStatement callableStatement, int i) + throws SQLException { + return Sample.SampleType.fromString(callableStatement.getString(i)); + } +} diff --git a/src/main/java/org/cbioportal/legacy/persistence/mybatis/util/CustomMyBatisObjectFactory.java b/src/main/java/org/cbioportal/legacy/persistence/mybatis/util/CustomMyBatisObjectFactory.java new file mode 100644 index 00000000000..709e6d25b29 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/persistence/mybatis/util/CustomMyBatisObjectFactory.java @@ -0,0 +1,20 @@ +package org.cbioportal.legacy.persistence.mybatis.util; + +import java.util.*; +import org.apache.ibatis.reflection.factory.DefaultObjectFactory; + +public class CustomMyBatisObjectFactory extends DefaultObjectFactory { + + public T create(Class type) { + String typeName = type.getName(); + T toReturn = (T) super.create(type); + return (toReturn instanceof List) ? (T) new LimitedPermissionArrayList() : toReturn; + } + + public T create( + Class type, List> constructorArgTypes, List constructorArgs) { + String typeName = type.getName(); + T toReturn = (T) super.create(type, constructorArgTypes, constructorArgs); + return (toReturn instanceof List) ? (T) new LimitedPermissionArrayList() : toReturn; + } +} diff --git a/src/main/java/org/cbioportal/legacy/persistence/mybatis/util/LimitedPermissionArrayList.java b/src/main/java/org/cbioportal/legacy/persistence/mybatis/util/LimitedPermissionArrayList.java new file mode 100644 index 00000000000..ec1793f2b9e --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/persistence/mybatis/util/LimitedPermissionArrayList.java @@ -0,0 +1,69 @@ +package org.cbioportal.legacy.persistence.mybatis.util; + +import java.util.*; +import java.util.function.*; + +public class LimitedPermissionArrayList extends ArrayList { + + public boolean addAll(Collection c) { + System.out.println("addAll called"); + throw new UnsupportedOperationException(); + } + + public boolean addAll(int index, Collection c) { + System.out.println("addAll called"); + throw new UnsupportedOperationException(); + } + + public void clear() { + System.out.println("clear called"); + throw new UnsupportedOperationException(); + } + + public T remove(int index) { + System.out.println("remove called"); + throw new UnsupportedOperationException(); + } + + public boolean remove(Object o) { + System.out.println( + "LimitedPermissionArrayList:remove() called, throwing UnsupportedOperationException()"); + throw new UnsupportedOperationException(); + } + + public boolean removeAll(Collection c) { + System.out.println( + "LimitedPermissionArrayList:removeAll() called, throwing UnsupportedOperationException()"); + throw new UnsupportedOperationException(); + } + + public boolean removeIf(Predicate filter) { + System.out.println( + "LimitedPermissionArrayList:removeIF() called, throwing UnsupportedOperationException()"); + throw new UnsupportedOperationException(); + } + + protected void removeRange(int fromIndex, int toIndex) { + System.out.println( + "LimitedPermissionArrayList:removeRange() called, throwing UnsupportedOperationException()"); + throw new UnsupportedOperationException(); + } + + public void replaceAll(UnaryOperator operator) { + System.out.println( + "LimitedPermissionArrayList:replaceAll() called, throwing UnsupportedOperationException()"); + throw new UnsupportedOperationException(); + } + + public boolean retainAll(Collection c) { + System.out.println( + "LimitedPermissionArrayList:retainAlll() called, throwing UnsupportedOperationException()"); + throw new UnsupportedOperationException(); + } + + public T set(int index, T element) { + System.out.println( + "LimitedPermissionArrayList:set() called, throwing UnsupportedOperationException()"); + throw new UnsupportedOperationException(); + } +} diff --git a/src/main/java/org/cbioportal/legacy/persistence/mybatis/util/MolecularProfileCaseIdentifierUtil.java b/src/main/java/org/cbioportal/legacy/persistence/mybatis/util/MolecularProfileCaseIdentifierUtil.java new file mode 100644 index 00000000000..bd7df2751f9 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/persistence/mybatis/util/MolecularProfileCaseIdentifierUtil.java @@ -0,0 +1,33 @@ +package org.cbioportal.legacy.persistence.mybatis.util; + +import static java.util.stream.Collectors.*; + +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.function.Function; +import java.util.stream.Collectors; +import java.util.stream.IntStream; +import org.apache.commons.math3.util.Pair; +import org.springframework.stereotype.Component; +import org.springframework.util.CollectionUtils; + +@Component +public class MolecularProfileCaseIdentifierUtil { + + public Map> getGroupedCasesByMolecularProfileId( + List molecularProfileIds, List caseIds) { + + if (CollectionUtils.isEmpty(caseIds)) { + return molecularProfileIds.stream() + .collect(Collectors.toMap(Function.identity(), e -> new HashSet<>())); + } + + return IntStream.range(0, molecularProfileIds.size()) + .mapToObj(i -> new Pair<>(molecularProfileIds.get(i), caseIds.get(i))) + .collect( + groupingBy( + Pair::getFirst, mapping(Pair::getSecond, toSet()))); + } +} diff --git a/src/main/java/org/cbioportal/legacy/persistence/mybatis/util/PaginationCalculator.java b/src/main/java/org/cbioportal/legacy/persistence/mybatis/util/PaginationCalculator.java new file mode 100644 index 00000000000..316aea734c8 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/persistence/mybatis/util/PaginationCalculator.java @@ -0,0 +1,21 @@ +package org.cbioportal.legacy.persistence.mybatis.util; + +public class PaginationCalculator { + + private PaginationCalculator() {} + + /** PageNumber '0' represents the first page (no offset). */ + public static Integer offset(Integer pageSize, Integer pageNumber) { + return pageSize == null || pageNumber == null ? null : pageSize * pageNumber; + } + + /** + * Returns 'lastIndex' as used by the subList command; position of the last element (exclusive). + */ + public static Integer lastIndex(Integer offset, Integer pageSize, Integer listLength) { + if (offset == null || pageSize == null || listLength == null) { + return null; + } + return (offset + pageSize) <= listLength ? (offset + pageSize) : listLength; + } +} diff --git a/src/main/java/org/cbioportal/legacy/persistence/mybatisclickhouse/StudyViewMapper.java b/src/main/java/org/cbioportal/legacy/persistence/mybatisclickhouse/StudyViewMapper.java new file mode 100644 index 00000000000..d757f0a1c6d --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/persistence/mybatisclickhouse/StudyViewMapper.java @@ -0,0 +1,127 @@ +package org.cbioportal.legacy.persistence.mybatisclickhouse; + +import java.util.List; +import java.util.Map; +import org.apache.ibatis.annotations.Param; +import org.cbioportal.legacy.model.AlterationCountByGene; +import org.cbioportal.legacy.model.CaseListDataCount; +import org.cbioportal.legacy.model.ClinicalAttribute; +import org.cbioportal.legacy.model.ClinicalData; +import org.cbioportal.legacy.model.ClinicalDataCount; +import org.cbioportal.legacy.model.ClinicalDataCountItem; +import org.cbioportal.legacy.model.ClinicalEventTypeCount; +import org.cbioportal.legacy.model.CopyNumberCountByGene; +import org.cbioportal.legacy.model.GenePanelToGene; +import org.cbioportal.legacy.model.GenericAssayDataCountItem; +import org.cbioportal.legacy.model.GenomicDataCount; +import org.cbioportal.legacy.model.GenomicDataCountItem; +import org.cbioportal.legacy.model.MolecularProfile; +import org.cbioportal.legacy.model.PatientTreatment; +import org.cbioportal.legacy.model.Sample; +import org.cbioportal.legacy.model.SampleTreatment; +import org.cbioportal.legacy.persistence.helper.AlterationFilterHelper; +import org.cbioportal.legacy.persistence.helper.StudyViewFilterHelper; +import org.cbioportal.legacy.web.parameter.GenericAssayDataBinFilter; +import org.cbioportal.legacy.web.parameter.GenericAssayDataFilter; +import org.cbioportal.legacy.web.parameter.GenomicDataBinFilter; +import org.cbioportal.legacy.web.parameter.GenomicDataFilter; + +@Deprecated(forRemoval = true) +public interface StudyViewMapper { + List getFilteredSamples( + @Param("studyViewFilterHelper") StudyViewFilterHelper studyViewFilterHelper); + + List getFilteredStudyIds( + @Param("studyViewFilterHelper") StudyViewFilterHelper studyViewFilterHelper); + + List getMolecularProfileSampleCounts( + @Param("studyViewFilterHelper") StudyViewFilterHelper studyViewFilterHelper); + + List getMutatedGenes( + StudyViewFilterHelper studyViewFilterHelper, AlterationFilterHelper alterationFilterHelper); + + List getCnaGenes( + StudyViewFilterHelper studyViewFilterHelper, AlterationFilterHelper alterationFilterHelper); + + List getStructuralVariantGenes( + StudyViewFilterHelper studyViewFilterHelper, AlterationFilterHelper alterationFilterHelper); + + List getClinicalDataCounts( + StudyViewFilterHelper studyViewFilterHelper, + List attributeIds, + List filteredAttributeValues); + + List getCaseListDataCountsPerStudy( + @Param("studyViewFilterHelper") StudyViewFilterHelper studyViewFilterHelper); + + List getClinicalAttributes(); + + List getClinicalAttributesForStudies(List studyIds); + + List getSampleClinicalDataFromStudyViewFilter( + StudyViewFilterHelper studyViewFilterHelper, List attributeIds); + + List getPatientClinicalDataFromStudyViewFilter( + StudyViewFilterHelper studyViewFilterHelper, List attributeIds); + + List getTotalProfiledCounts( + StudyViewFilterHelper studyViewFilterHelper, + String alterationType, + List molecularProfiles); + + int getFilteredSamplesCount( + @Param("studyViewFilterHelper") StudyViewFilterHelper studyViewFilterHelper); + + int getFilteredPatientsCount( + @Param("studyViewFilterHelper") StudyViewFilterHelper studyViewFilterHelper); + + List getMatchingGenePanelIds( + StudyViewFilterHelper studyViewFilterHelper, String alterationType); + + int getTotalProfiledCountByAlterationType( + StudyViewFilterHelper studyViewFilterHelper, String alterationType); + + int getSampleProfileCountWithoutPanelData( + StudyViewFilterHelper studyViewFilterHelper, String alterationType); + + List getClinicalEventTypeCounts( + @Param("studyViewFilterHelper") StudyViewFilterHelper studyViewFilterHelper); + + List getPatientTreatments( + @Param("studyViewFilterHelper") StudyViewFilterHelper studyViewFilterHelper); + + int getPatientTreatmentCounts( + @Param("studyViewFilterHelper") StudyViewFilterHelper studyViewFilterHelper); + + List getSampleTreatmentCounts( + @Param("studyViewFilterHelper") StudyViewFilterHelper studyViewFilterHelper); + + int getTotalSampleTreatmentCounts( + @Param("studyViewFilterHelper") StudyViewFilterHelper studyViewFilterHelper); + + List getCNACounts( + StudyViewFilterHelper studyViewFilterHelper, List genomicDataFilters); + + List getGenericAssayDataCounts( + StudyViewFilterHelper studyViewFilterHelper, + List genericAssayDataFilters); + + Map getMutationCounts( + StudyViewFilterHelper studyViewFilterHelper, GenomicDataFilter genomicDataFilter); + + List getMutationCountsByType( + StudyViewFilterHelper studyViewFilterHelper, List genomicDataFilters); + + List getGenomicDataBinCounts( + StudyViewFilterHelper studyViewFilterHelper, + List genomicDataBinFilters); + + List getGenericAssayDataBinCounts( + StudyViewFilterHelper studyViewFilterHelper, + List genericAssayDataBinFilters); + + List getGenericAssayProfiles(); + + List getFilteredMolecularProfilesByAlterationType( + StudyViewFilterHelper studyViewFilterHelper, String alterationType); +} diff --git a/src/main/java/org/cbioportal/legacy/persistence/mybatisclickhouse/StudyViewMyBatisRepository.java b/src/main/java/org/cbioportal/legacy/persistence/mybatisclickhouse/StudyViewMyBatisRepository.java new file mode 100644 index 00000000000..4bab55e4cfd --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/persistence/mybatisclickhouse/StudyViewMyBatisRepository.java @@ -0,0 +1,340 @@ +package org.cbioportal.legacy.persistence.mybatisclickhouse; + +import java.util.Collections; +import java.util.EnumMap; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; +import org.cbioportal.legacy.model.AlterationCountByGene; +import org.cbioportal.legacy.model.CaseListDataCount; +import org.cbioportal.legacy.model.ClinicalAttribute; +import org.cbioportal.legacy.model.ClinicalData; +import org.cbioportal.legacy.model.ClinicalDataCount; +import org.cbioportal.legacy.model.ClinicalDataCountItem; +import org.cbioportal.legacy.model.ClinicalEventTypeCount; +import org.cbioportal.legacy.model.CopyNumberCountByGene; +import org.cbioportal.legacy.model.GenePanelToGene; +import org.cbioportal.legacy.model.GenericAssayDataCountItem; +import org.cbioportal.legacy.model.GenomicDataCount; +import org.cbioportal.legacy.model.GenomicDataCountItem; +import org.cbioportal.legacy.model.MolecularProfile; +import org.cbioportal.legacy.model.PatientTreatment; +import org.cbioportal.legacy.model.Sample; +import org.cbioportal.legacy.model.SampleTreatment; +import org.cbioportal.legacy.model.StudyViewFilterContext; +import org.cbioportal.legacy.persistence.StudyViewRepository; +import org.cbioportal.legacy.persistence.enums.DataSource; +import org.cbioportal.legacy.persistence.helper.AlterationFilterHelper; +import org.cbioportal.legacy.persistence.helper.StudyViewFilterHelper; +import org.cbioportal.legacy.service.util.StudyViewColumnarServiceUtil; +import org.cbioportal.legacy.utils.config.annotation.ConditionalOnProperty; +import org.cbioportal.legacy.web.parameter.ClinicalDataType; +import org.cbioportal.legacy.web.parameter.GenericAssayDataBinFilter; +import org.cbioportal.legacy.web.parameter.GenericAssayDataFilter; +import org.cbioportal.legacy.web.parameter.GenomicDataBinFilter; +import org.cbioportal.legacy.web.parameter.GenomicDataFilter; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Repository; + +@Repository +@Deprecated(forRemoval = true) +@ConditionalOnProperty(name = "clickhouse_mode", havingValue = "test") +public class StudyViewMyBatisRepository implements StudyViewRepository { + + private final StudyViewMapper studyViewMapper; + private Map> clinicalAttributesMap = + new EnumMap<>(DataSource.class); + private Map> genericAssayProfilesMap = + new EnumMap<>(DataSource.class); + + private static final List FILTERED_CLINICAL_ATTR_VALUES = Collections.emptyList(); + private final StudyViewMapper mapper; + + @Autowired + public StudyViewMyBatisRepository(StudyViewMapper mapper, StudyViewMapper studyViewMapper) { + this.mapper = mapper; + this.studyViewMapper = studyViewMapper; + } + + @Override + public List getFilteredSamples(StudyViewFilterContext studyViewFilterContext) { + return mapper.getFilteredSamples(createStudyViewFilterHelper(studyViewFilterContext)); + } + + @Override + public List getFilteredStudyIds(StudyViewFilterContext studyViewFilterContext) { + return mapper.getFilteredStudyIds(createStudyViewFilterHelper(studyViewFilterContext)); + } + + @Override + public List getMutatedGenes( + StudyViewFilterContext studyViewFilterContext) { + return mapper.getMutatedGenes( + createStudyViewFilterHelper(studyViewFilterContext), + AlterationFilterHelper.build( + studyViewFilterContext.studyViewFilter().getAlterationFilter())); + } + + @Override + public List getCnaGenes(StudyViewFilterContext studyViewFilterContext) { + return mapper.getCnaGenes( + createStudyViewFilterHelper(studyViewFilterContext), + AlterationFilterHelper.build( + studyViewFilterContext.studyViewFilter().getAlterationFilter())); + } + + @Override + public List getStructuralVariantGenes( + StudyViewFilterContext studyViewFilterContext) { + return mapper.getStructuralVariantGenes( + createStudyViewFilterHelper(studyViewFilterContext), + AlterationFilterHelper.build( + studyViewFilterContext.studyViewFilter().getAlterationFilter())); + } + + @Override + public List getClinicalDataCounts( + StudyViewFilterContext studyViewFilterContext, List filteredAttributes) { + return mapper.getClinicalDataCounts( + createStudyViewFilterHelper(studyViewFilterContext), + filteredAttributes, + FILTERED_CLINICAL_ATTR_VALUES); + } + + @Override + public List getMolecularProfileSampleCounts( + StudyViewFilterContext studyViewFilterContext) { + var sampleCounts = + mapper.getMolecularProfileSampleCounts(createStudyViewFilterHelper(studyViewFilterContext)); + return StudyViewColumnarServiceUtil.mergeGenomicDataCounts(sampleCounts); + } + + public StudyViewFilterHelper createStudyViewFilterHelper( + StudyViewFilterContext studyViewFilterContext) { + return StudyViewFilterHelper.build( + studyViewFilterContext.studyViewFilter(), + getGenericAssayProfilesMap(), + studyViewFilterContext.customDataFilterSamples(), + studyViewFilterContext.involvedCancerStudies()); + } + + @Override + public List getClinicalAttributes() { + return mapper.getClinicalAttributes(); + } + + @Override + public List getGenericAssayProfiles() { + return mapper.getGenericAssayProfiles(); + } + + @Override + public List getFilteredMolecularProfilesByAlterationType( + StudyViewFilterContext studyViewFilterContext, String alterationType) { + return studyViewMapper.getFilteredMolecularProfilesByAlterationType( + createStudyViewFilterHelper(studyViewFilterContext), alterationType); + } + + @Override + public Map getClinicalAttributeDatatypeMap() { + if (clinicalAttributesMap.isEmpty()) { + buildClinicalAttributeNameMap(); + } + + Map attributeDatatypeMap = new HashMap<>(); + + clinicalAttributesMap + .get(DataSource.SAMPLE) + .forEach( + attribute -> attributeDatatypeMap.put(attribute.getAttrId(), ClinicalDataType.SAMPLE)); + + clinicalAttributesMap + .get(DataSource.PATIENT) + .forEach( + attribute -> attributeDatatypeMap.put(attribute.getAttrId(), ClinicalDataType.PATIENT)); + + return attributeDatatypeMap; + } + + @Override + public List getClinicalAttributesForStudies(List studyIds) { + return mapper.getClinicalAttributesForStudies(studyIds); + } + + @Override + public List getCaseListDataCountsPerStudy( + StudyViewFilterContext studyViewFilterContext) { + return mapper.getCaseListDataCountsPerStudy( + createStudyViewFilterHelper(studyViewFilterContext)); + } + + @Override + public List getSampleClinicalData( + StudyViewFilterContext studyViewFilterContext, List attributeIds) { + return mapper.getSampleClinicalDataFromStudyViewFilter( + createStudyViewFilterHelper(studyViewFilterContext), attributeIds); + } + + @Override + public List getPatientClinicalData( + StudyViewFilterContext studyViewFilterContext, List attributeIds) { + return mapper.getPatientClinicalDataFromStudyViewFilter( + createStudyViewFilterHelper(studyViewFilterContext), attributeIds); + } + + @Override + public Map getTotalProfiledCounts( + StudyViewFilterContext studyViewFilterContext, + String alterationType, + List molecularProfiles) { + return mapper + .getTotalProfiledCounts( + createStudyViewFilterHelper(studyViewFilterContext), alterationType, molecularProfiles) + .stream() + .collect( + Collectors.groupingBy( + AlterationCountByGene::getHugoGeneSymbol, + Collectors.mapping( + AlterationCountByGene::getNumberOfProfiledCases, + Collectors.summingInt(Integer::intValue)))); + } + + @Override + public int getFilteredSamplesCount(StudyViewFilterContext studyViewFilterContext) { + return mapper.getFilteredSamplesCount(createStudyViewFilterHelper(studyViewFilterContext)); + } + + @Override + public int getFilteredPatientCount(StudyViewFilterContext studyViewFilterContext) { + return mapper.getFilteredPatientsCount(createStudyViewFilterHelper(studyViewFilterContext)); + } + + @Override + public Map> getMatchingGenePanelIds( + StudyViewFilterContext studyViewFilterContext, String alterationType) { + return mapper + .getMatchingGenePanelIds( + createStudyViewFilterHelper(studyViewFilterContext), alterationType) + .stream() + .collect( + Collectors.groupingBy( + GenePanelToGene::getHugoGeneSymbol, + Collectors.mapping(GenePanelToGene::getGenePanelId, Collectors.toSet()))); + } + + @Override + public int getTotalProfiledCountsByAlterationType( + StudyViewFilterContext studyViewFilterContext, String alterationType) { + return mapper.getTotalProfiledCountByAlterationType( + createStudyViewFilterHelper(studyViewFilterContext), alterationType); + } + + @Override + public int getSampleProfileCountWithoutPanelData( + StudyViewFilterContext studyViewFilterContext, String alterationType) { + return mapper.getSampleProfileCountWithoutPanelData( + createStudyViewFilterHelper(studyViewFilterContext), alterationType); + } + + @Override + public List getClinicalEventTypeCounts( + StudyViewFilterContext studyViewFilterContext) { + return mapper.getClinicalEventTypeCounts(createStudyViewFilterHelper(studyViewFilterContext)); + } + + @Override + public List getPatientTreatments( + StudyViewFilterContext studyViewFilterContext) { + return mapper.getPatientTreatments(createStudyViewFilterHelper(studyViewFilterContext)); + } + + @Override + public int getTotalPatientTreatmentCount(StudyViewFilterContext studyViewFilterContext) { + return mapper.getPatientTreatmentCounts(createStudyViewFilterHelper(studyViewFilterContext)); + } + + @Override + public List getSampleTreatments(StudyViewFilterContext studyViewFilterContext) { + return mapper.getSampleTreatmentCounts(createStudyViewFilterHelper(studyViewFilterContext)); + } + + @Override + public int getTotalSampleTreatmentCount(StudyViewFilterContext studyViewFilterContext) { + return mapper.getTotalSampleTreatmentCounts( + createStudyViewFilterHelper(studyViewFilterContext)); + } + + @Override + public List getGenomicDataBinCounts( + StudyViewFilterContext studyViewFilterContext, + List genomicDataBinFilters) { + return mapper.getGenomicDataBinCounts( + createStudyViewFilterHelper(studyViewFilterContext), genomicDataBinFilters); + } + + @Override + public List getGenericAssayDataBinCounts( + StudyViewFilterContext studyViewFilterContext, + List genericAssayDataBinFilters) { + return mapper.getGenericAssayDataBinCounts( + createStudyViewFilterHelper(studyViewFilterContext), genericAssayDataBinFilters); + } + + private void buildClinicalAttributeNameMap() { + clinicalAttributesMap = + this.getClinicalAttributes().stream() + .collect( + Collectors.groupingBy( + ca -> + ca.getPatientAttribute().booleanValue() + ? DataSource.PATIENT + : DataSource.SAMPLE)); + } + + private void buildGenericAssayProfilesMap() { + genericAssayProfilesMap = + this.getGenericAssayProfiles().stream() + .collect( + Collectors.groupingBy( + ca -> + ca.getPatientLevel().booleanValue() + ? DataSource.PATIENT + : DataSource.SAMPLE)); + } + + private Map> getGenericAssayProfilesMap() { + if (genericAssayProfilesMap.isEmpty()) { + buildGenericAssayProfilesMap(); + } + return genericAssayProfilesMap; + } + + @Override + public List getCNACounts( + StudyViewFilterContext studyViewFilterContext, List genomicDataFilters) { + return mapper.getCNACounts( + createStudyViewFilterHelper(studyViewFilterContext), genomicDataFilters); + } + + @Override + public List getGenericAssayDataCounts( + StudyViewFilterContext studyViewFilterContext, + List genericAssayDataFilters) { + return mapper.getGenericAssayDataCounts( + createStudyViewFilterHelper(studyViewFilterContext), genericAssayDataFilters); + } + + public Map getMutationCounts( + StudyViewFilterContext studyViewFilterContext, GenomicDataFilter genomicDataFilter) { + return mapper.getMutationCounts( + createStudyViewFilterHelper(studyViewFilterContext), genomicDataFilter); + } + + public List getMutationCountsByType( + StudyViewFilterContext studyViewFilterContext, List genomicDataFilters) { + return mapper.getMutationCountsByType( + createStudyViewFilterHelper(studyViewFilterContext), genomicDataFilters); + } +} diff --git a/src/main/java/org/cbioportal/legacy/persistence/util/CacheEventLogger.java b/src/main/java/org/cbioportal/legacy/persistence/util/CacheEventLogger.java new file mode 100644 index 00000000000..0972ceeab07 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/persistence/util/CacheEventLogger.java @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2019 Memorial Sloan-Kettering Cancer Center. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS + * FOR A PARTICULAR PURPOSE. The software and documentation provided hereunder + * is on an "as is" basis, and Memorial Sloan-Kettering Cancer Center has no + * obligations to provide maintenance, support, updates, enhancements or + * modifications. In no event shall Memorial Sloan-Kettering Cancer Center be + * liable to any party for direct, indirect, special, incidental or + * consequential damages, including lost profits, arising out of the use of this + * software and its documentation, even if Memorial Sloan-Kettering Cancer + * Center has been advised of the possibility of such damage. + */ + +/* + * This file is part of cBioPortal. + * + * cBioPortal is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package org.cbioportal.legacy.persistence.util; + +import org.ehcache.event.*; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class CacheEventLogger implements CacheEventListener { + + private static final Logger log = LoggerFactory.getLogger(CacheEventLogger.class); + + // this is to allow spring to inject EhcacheStatistics via MethodInvokingFactoryBean + private static EhcacheStatistics ehcacheStatistics; + + public static void setCacheStatistics(EhcacheStatistics ecs) { + ehcacheStatistics = ecs; + } + + @Override + public void onEvent(CacheEvent cacheEvent) { + if (log.isDebugEnabled()) { + log.debug( + "CACHE_EVENT:\n" + + "\tTYPE: " + + cacheEvent.getType() + + "\n" + + "\tKEY: " + + cacheEvent.getKey() + + "\n" + + "\tVALUE: " + + cacheEvent.getNewValue() + + "\n" + + "CACHE_EVENT<>\n"); + log.debug(ehcacheStatistics.getCacheStatistics()); + } + } +} diff --git a/src/main/java/org/cbioportal/legacy/persistence/util/CacheUtils.java b/src/main/java/org/cbioportal/legacy/persistence/util/CacheUtils.java new file mode 100644 index 00000000000..64d2f298f69 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/persistence/util/CacheUtils.java @@ -0,0 +1,9 @@ +package org.cbioportal.legacy.persistence.util; + +import java.util.List; + +public interface CacheUtils { + List getKeys(String cacheName); + + void evictByPattern(String cacheName, String pattern); +} diff --git a/src/main/java/org/cbioportal/legacy/persistence/util/CustomEhcachingProvider.java b/src/main/java/org/cbioportal/legacy/persistence/util/CustomEhcachingProvider.java new file mode 100644 index 00000000000..12677f187d2 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/persistence/util/CustomEhcachingProvider.java @@ -0,0 +1,348 @@ +/* + * Copyright (c) 2019 Memorial Sloan-Kettering Cancer Center. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS + * FOR A PARTICULAR PURPOSE. The software and documentation provided hereunder + * is on an "as is" basis, and Memorial Sloan-Kettering Cancer Center has no + * obligations to provide maintenance, support, updates, enhancements or + * modifications. In no event shall Memorial Sloan-Kettering Cancer Center be + * liable to any party for direct, indirect, special, incidental or + * consequential damages, including lost profits, arising out of the use of this + * software and its documentation, even if Memorial Sloan-Kettering Cancer + * Center has been advised of the possibility of such damage. + */ + +/* + * This file is part of cBioPortal. + * + * cBioPortal is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package org.cbioportal.legacy.persistence.util; + +import java.io.*; +import java.net.URL; +import java.util.*; +import javax.cache.CacheManager; +import org.cbioportal.legacy.persistence.CacheEnabledConfig; +import org.ehcache.config.CacheConfiguration; +import org.ehcache.config.Configuration; +import org.ehcache.config.builders.CacheConfigurationBuilder; +import org.ehcache.config.builders.ResourcePoolsBuilder; +import org.ehcache.config.units.MemoryUnit; +import org.ehcache.core.config.DefaultConfiguration; +import org.ehcache.impl.config.persistence.DefaultPersistenceConfiguration; +import org.ehcache.jsr107.EhcacheCachingProvider; +import org.ehcache.xml.XmlConfiguration; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; + +public class CustomEhcachingProvider extends EhcacheCachingProvider { + + private static final Logger LOG = LoggerFactory.getLogger(CustomEhcachingProvider.class); + + @Value("${ehcache.xml_configuration:/ehcache.xml}") + private String xmlConfigurationFile; + + @Value("${persistence.cache_type:no-cache}") + private String cacheType; + + @Value("${ehcache.general_repository_cache.max_mega_bytes_heap:1024}") + private Integer generalRepositoryCacheMaxMegaBytes; + + @Value("${ehcache.static_repository_cache_one.max_mega_bytes_heap:30}") + private Integer staticRepositoryCacheOneMaxMegaBytes; + + @Value("${ehcache.persistence_path:/tmp/}") + private String persistencePath; + + @Value("${ehcache.general_repository_cache.max_mega_bytes_local_disk:4096}") + private Integer generalRepositoryCacheMaxMegaBytesLocalDisk; + + @Value("${ehcache.static_repository_cache_one.max_mega_bytes_local_disk:32}") + private Integer staticRepositoryCacheOneMaxMegaBytesLocalDisk; + + @Autowired private CacheEnabledConfig cacheEnabledConfig; + + @Override + public CacheManager getCacheManager() { + + CacheManager toReturn = null; + try { + if (cacheEnabledConfig.enableCache(cacheType)) { + detectCacheConfigurationErrorsAndLog(); + LOG.info("Caching is enabled, using '" + xmlConfigurationFile + "' for configuration"); + XmlConfiguration xmlConfiguration = + new XmlConfiguration(getClass().getResource(xmlConfigurationFile)); + + // initilize configurations specific to each individual cache (by template) + // to add new cache - create cache configuration with its own resource pool + template + ResourcePoolsBuilder generalRepositoryCacheResourcePoolsBuilder = + ResourcePoolsBuilder.newResourcePoolsBuilder(); + ResourcePoolsBuilder staticRepositoryCacheOneResourcePoolsBuilder = + ResourcePoolsBuilder.newResourcePoolsBuilder(); + + // Set up heap resources as long as not disk-only + if (!cacheType.equalsIgnoreCase(CacheEnabledConfig.EHCACHE_DISK)) { + generalRepositoryCacheResourcePoolsBuilder = + generalRepositoryCacheResourcePoolsBuilder.heap( + generalRepositoryCacheMaxMegaBytes, MemoryUnit.MB); + staticRepositoryCacheOneResourcePoolsBuilder = + staticRepositoryCacheOneResourcePoolsBuilder.heap( + staticRepositoryCacheOneMaxMegaBytes, MemoryUnit.MB); + } + // Set up disk resources as long as not heap-only + // will default to using /tmp -- let Ehcache throw exception if persistence path is invalid + // (locked or otherwise) + if (!cacheType.equalsIgnoreCase(CacheEnabledConfig.EHCACHE_HEAP)) { + generalRepositoryCacheResourcePoolsBuilder = + generalRepositoryCacheResourcePoolsBuilder.disk( + generalRepositoryCacheMaxMegaBytesLocalDisk, MemoryUnit.MB); + staticRepositoryCacheOneResourcePoolsBuilder = + staticRepositoryCacheOneResourcePoolsBuilder.disk( + staticRepositoryCacheOneMaxMegaBytesLocalDisk, MemoryUnit.MB); + } + + CacheConfiguration generalRepositoryCacheConfiguration = + xmlConfiguration + .newCacheConfigurationBuilderFromTemplate( + "RepositoryCacheTemplate", + Object.class, + Object.class, + generalRepositoryCacheResourcePoolsBuilder) + .withSizeOfMaxObjectGraph(Long.MAX_VALUE) + .withSizeOfMaxObjectSize(Long.MAX_VALUE, MemoryUnit.B) + .build(); + CacheConfiguration staticRepositoryCacheOneConfiguration = + xmlConfiguration + .newCacheConfigurationBuilderFromTemplate( + "RepositoryCacheTemplate", + Object.class, + Object.class, + staticRepositoryCacheOneResourcePoolsBuilder) + .withSizeOfMaxObjectGraph(Long.MAX_VALUE) + .withSizeOfMaxObjectSize(Long.MAX_VALUE, MemoryUnit.B) + .build(); + + // places caches in a map which will be used to create cache manager + Map> caches = new HashMap<>(); + caches.put("GeneralRepositoryCache", generalRepositoryCacheConfiguration); + caches.put("StaticRepositoryCacheOne", staticRepositoryCacheOneConfiguration); + + Configuration configuration = null; + if (cacheType.equalsIgnoreCase(CacheEnabledConfig.EHCACHE_HEAP)) { + configuration = new DefaultConfiguration(caches, this.getDefaultClassLoader()); + } else { // add persistence configuration if cacheType is either disk-only or hybrid + File persistenceFile = new File(persistencePath); + configuration = + new DefaultConfiguration( + caches, + this.getDefaultClassLoader(), + new DefaultPersistenceConfiguration(persistenceFile)); + } + + toReturn = this.getCacheManager(this.getDefaultURI(), configuration); + } else { + LOG.info("Caching is disabled"); + // we can not really disable caching, + // we can not make a cache of 0 objects, + // and we can not make a heap of memory size 0, so make a tiny heap + CacheConfiguration generalRepositoryCacheConfiguration = + CacheConfigurationBuilder.newCacheConfigurationBuilder( + Object.class, + Object.class, + ResourcePoolsBuilder.newResourcePoolsBuilder().heap(1, MemoryUnit.B)) + .build(); + CacheConfiguration staticRepositoryCacheOneConfiguration = + CacheConfigurationBuilder.newCacheConfigurationBuilder( + Object.class, + Object.class, + ResourcePoolsBuilder.newResourcePoolsBuilder().heap(1, MemoryUnit.B)) + .build(); + + Map> caches = new HashMap<>(); + caches.put("GeneralRepositoryCache", generalRepositoryCacheConfiguration); + caches.put("StaticRepositoryCacheOne", staticRepositoryCacheOneConfiguration); + + Configuration configuration = + new DefaultConfiguration(caches, this.getDefaultClassLoader()); + + toReturn = this.getCacheManager(this.getDefaultURI(), configuration); + } + } catch (Exception e) { + LOG.error(e.getClass().getName() + ": " + e.getMessage()); + StringWriter stackTrace = new StringWriter(); + e.printStackTrace(new PrintWriter(stackTrace)); + LOG.error(stackTrace.toString()); + } + return toReturn; + } + + public void detectCacheConfigurationErrorsAndLog() { + String MESSAGE_PREFIX = "Errors detected during configuration of Ehcache:"; + StringBuffer messages = new StringBuffer(MESSAGE_PREFIX); + boolean usesHeap = false; + boolean usesDisk = false; + switch (this.cacheType.trim().toLowerCase()) { + case "no-cache": + break; + case "ehcache-heap": + usesHeap = true; + break; + case "ehcache-disk": + usesDisk = true; + break; + case "ehcache-hybrid": + usesHeap = true; + usesDisk = true; + break; + case "redis": + break; // we should not be in here in this case + default: + messages + .append("\n property persistence.cache_type has value (") + .append(cacheType) + .append(") which is not a recognized value"); + } + if (usesDisk || usesHeap) { + if (xmlConfigurationFile == null || xmlConfigurationFile.trim().length() == 0) { + messages.append("\n property ehcache.xml_configuration is required but is unset"); + } else { + URL configFileURL = getClass().getResource(xmlConfigurationFile); + if (configFileURL == null) { + messages + .append("\n property ehcache.xml_configuration has value (") + .append(xmlConfigurationFile) + .append(") but this resource is not available to the classloader"); + } else { + boolean readable = false; + InputStream configFileInputStream = null; + try { + configFileInputStream = configFileURL.openStream(); + configFileInputStream.read(); + configFileInputStream.close(); + readable = true; + } catch (IOException e) { + } finally { + try { + configFileInputStream.close(); + } catch (IOException e) { + LOG.error("UNABLE TO CLOSE configFileURLInputStream"); + } + } + + if (!readable) { + messages + .append("\n property ehcache.xml_configuration has value (") + .append(xmlConfigurationFile) + .append(") but an attempt to read from this resource failed"); + } + } + } + } + if (usesDisk) { + if (generalRepositoryCacheMaxMegaBytesLocalDisk == null) { + messages.append( + "\n property ehcache.general_repository_cache.max_mega_bytes_local_disk is required to be set, but has no value"); + } else { + if (generalRepositoryCacheMaxMegaBytesLocalDisk <= 0) { + messages.append( + "\n property ehcache.general_repository_cache.max_mega_bytes_local_disk must be greater than zero but is not"); + } + } + if (staticRepositoryCacheOneMaxMegaBytesLocalDisk == null) { + messages.append( + "\n property ehcache.static_repository_cache_one.max_mega_bytes_local_disk is required to be set, but has no value"); + } else { + if (staticRepositoryCacheOneMaxMegaBytesLocalDisk <= 0) { + messages.append( + "\n property ehcache.static_repository_cache_one.max_mega_bytes_local_disk must be greater than zero but is not"); + } + } + if (persistencePath == null || persistencePath.trim().length() == 0) { + messages.append( + "\n property ehcache.persistence_path is required when using a disk resource but is unset"); + } else { + File persistenceDirectory = new File(persistencePath); + boolean accessible = false; + try { + if (persistenceDirectory.isDirectory() && persistenceDirectory.canWrite()) { + accessible = true; + } + } catch (SecurityException e) { + } + if (!accessible) { + messages + .append("\n property ehcache.persistence_path has value (") + .append(persistencePath) + .append(") but this path does not exist or is not an accessible directory"); + } + } + } + if (usesHeap) { + if (generalRepositoryCacheMaxMegaBytes == null) { + messages.append( + "\n property ehcache.general_repository_cache.max_mega_bytes_heap is required to be set, but has no value"); + } else { + if (generalRepositoryCacheMaxMegaBytes <= 0) { + messages.append( + "\n property ehcache.general_repository_cache.max_mega_bytes_heap must be greater than zero but is not"); + } + } + if (staticRepositoryCacheOneMaxMegaBytes == null) { + messages.append( + "\n property ehcache.static_repository_cache_one.max_mega_bytes_heap is required to be set, but has no value"); + } else { + if (staticRepositoryCacheOneMaxMegaBytes <= 0) { + messages.append( + "\n property ehcache.static_repository_cache_one.max_mega_bytes_heap must be greater than zero but is not"); + } + } + } + if (usesHeap && usesDisk) { + if (generalRepositoryCacheMaxMegaBytesLocalDisk != null + && generalRepositoryCacheMaxMegaBytes != null + && generalRepositoryCacheMaxMegaBytesLocalDisk <= generalRepositoryCacheMaxMegaBytes) { + messages.append( + "\n property ehcache.general_repository_cache.max_mega_bytes_heap must be set to a value less than the value of "); + messages.append( + "property ehcache.general_repository_cache.max_mega_bytes_local_disk, however "); + messages.append(generalRepositoryCacheMaxMegaBytes); + messages.append(" is not less than "); + messages.append(generalRepositoryCacheMaxMegaBytesLocalDisk); + } + if (staticRepositoryCacheOneMaxMegaBytesLocalDisk != null + && staticRepositoryCacheOneMaxMegaBytes != null + && staticRepositoryCacheOneMaxMegaBytesLocalDisk + <= staticRepositoryCacheOneMaxMegaBytes) { + messages.append( + "\n property ehcache.static_repository_cache_one.max_mega_bytes_heap must be set to a value less than the value of "); + messages.append( + "property ehcache.static_repository_cache_one.max_mega_bytes_local_disk, however "); + messages.append(staticRepositoryCacheOneMaxMegaBytes); + messages.append(" is not less than "); + messages.append(staticRepositoryCacheOneMaxMegaBytesLocalDisk); + } + } + if (messages.length() > MESSAGE_PREFIX.length()) { + LOG.error(messages.toString()); + LOG.error( + "because of Ehcache configuration errors, it is likely that an exception will be thrown during startup. Recent observed exceptions contain the string" + + " \"Provider org.redisson.jcache.JCachingProvider not a subtype\" even though the problem is in the Ehcache configuration settings."); + } + } +} diff --git a/src/main/java/org/cbioportal/legacy/persistence/util/CustomKeyGenerator.java b/src/main/java/org/cbioportal/legacy/persistence/util/CustomKeyGenerator.java new file mode 100644 index 00000000000..bed6de87516 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/persistence/util/CustomKeyGenerator.java @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2019 Memorial Sloan-Kettering Cancer Center. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS + * FOR A PARTICULAR PURPOSE. The software and documentation provided hereunder + * is on an "as is" basis, and Memorial Sloan-Kettering Cancer Center has no + * obligations to provide maintenance, support, updates, enhancements or + * modifications. In no event shall Memorial Sloan-Kettering Cancer Center be + * liable to any party for direct, indirect, special, incidental or + * consequential damages, including lost profits, arising out of the use of this + * software and its documentation, even if Memorial Sloan-Kettering Cancer + * Center has been advised of the possibility of such damage. + */ + +/* + * This file is part of cBioPortal. + * + * cBioPortal is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package org.cbioportal.legacy.persistence.util; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import java.lang.reflect.Method; +import java.util.Arrays; +import java.util.stream.Collectors; +import org.cbioportal.legacy.model.CancerStudy; +import org.cbioportal.legacy.model.util.Select; +import org.cbioportal.legacy.persistence.CacheEnabledConfig; +import org.cbioportal.legacy.persistence.StudyRepository; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cache.interceptor.KeyGenerator; +import org.springframework.util.DigestUtils; + +public class CustomKeyGenerator implements KeyGenerator { + public static final String CACHE_KEY_PARAM_DELIMITER = "_"; + public static final int PARAM_LENGTH_HASH_LIMIT = 1024; + + @Autowired private CacheEnabledConfig cacheEnabledConfig; + + @Autowired private StudyRepository studyRepository; + + private static final ObjectMapper mapper = new ObjectMapper(); + + private static final Logger LOG = LoggerFactory.getLogger(CustomKeyGenerator.class); + + public Object generate(Object target, Method method, Object... params) { + if (!cacheEnabledConfig.isEnabled() && !cacheEnabledConfig.isEnabledClickhouse()) { + return ""; + } + String key = + target.getClass().getSimpleName() + + CACHE_KEY_PARAM_DELIMITER + + method.getName() + + CACHE_KEY_PARAM_DELIMITER + + Arrays.stream(params) + .map(this::exceptionlessWrite) + .collect(Collectors.joining(CACHE_KEY_PARAM_DELIMITER)); + LOG.debug("Created key: " + key); + return key; + } + + private String exceptionlessWrite(Object toSerialize) { + if (toSerialize instanceof Select && ((Select) toSerialize).hasAll()) { + // Select implements Iterable, but Select.All throws an exception + // when you call iterator(), which breaks Jackson, so we need some custom logic + return "Select.ALL"; + } + try { + String json = mapper.writeValueAsString(toSerialize); + if (json.length() > PARAM_LENGTH_HASH_LIMIT) { + // To allow study-specific cache eviction, extract relevant + // study identifiers and add these to the cache keys. + String matchedStudyIds = + studyRepository.getAllStudies(null, "SUMMARY", null, null, null, null).stream() + .map(CancerStudy::getCancerStudyIdentifier) + .distinct() + .filter(json::contains) + .collect(Collectors.joining(CACHE_KEY_PARAM_DELIMITER)); + return matchedStudyIds + + CACHE_KEY_PARAM_DELIMITER + + DigestUtils.md5DigestAsHex(json.getBytes()); + } else { + // leave short keys intact, but remove semicolons to make things look cleaner in redis + return json.replaceAll(":", CACHE_KEY_PARAM_DELIMITER); + } + } catch (JsonProcessingException e) { + LOG.error("Could not serialize param to string: ", e); + return ""; + } + } +} diff --git a/src/main/java/org/cbioportal/legacy/persistence/util/CustomRedisCache.java b/src/main/java/org/cbioportal/legacy/persistence/util/CustomRedisCache.java new file mode 100644 index 00000000000..1d0a6a177fa --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/persistence/util/CustomRedisCache.java @@ -0,0 +1,204 @@ +package org.cbioportal.legacy.persistence.util; + +import java.io.*; +import java.util.concurrent.Callable; +import java.util.concurrent.TimeUnit; +import java.util.zip.GZIPInputStream; +import java.util.zip.GZIPOutputStream; +import org.redisson.api.RedissonClient; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.cache.Cache; +import org.springframework.cache.support.AbstractValueAdaptingCache; +import org.springframework.cache.support.SimpleValueWrapper; +import org.springframework.lang.Nullable; + +public class CustomRedisCache extends AbstractValueAdaptingCache { + private static final Logger LOG = LoggerFactory.getLogger(CustomRedisCache.class); + public static final String DELIMITER = ":"; + public static final int INFINITE_TTL = -1; + + private final String name; + private final long ttlMinutes; + private final RedissonClient redissonClient; + + /** + * Create a new ConcurrentMapCache with the specified name. + * + * @param name the name of the cache + */ + public CustomRedisCache(String name, RedissonClient client, long ttlMinutes) { + super(true); + this.name = name; + this.redissonClient = client; + this.ttlMinutes = ttlMinutes; + } + + @Override + public final String getName() { + return name; + } + + public final RedissonClient getNativeCache() { + return this.redissonClient; + } + + @Override + @Nullable + protected Object lookup(Object key) { + Object value = this.redissonClient.getBucket(name + DELIMITER + key).get(); + if (value != null) { + value = fromStoreValue(value); + asyncRefresh(key); + } + return value; + } + + private void asyncRefresh(Object key) { + if (ttlMinutes != INFINITE_TTL) { + this.redissonClient + .getBucket(name + DELIMITER + key) + .expireAsync(ttlMinutes, TimeUnit.MINUTES); + } + } + + @Override + @Nullable + public T get(Object key, Callable valueLoader) { + Object zippedValue = this.redissonClient.getBucket(name + DELIMITER + key).get(); + T value = null; + if (zippedValue != null) { + value = (T) fromStoreValue(zippedValue); + asyncRefresh(key); + } + try { + return value == null ? valueLoader.call() : value; + } catch (Exception ex) { + throw new ValueRetrievalException(key, valueLoader, ex); + } + } + + @Override + public void put(Object key, @Nullable Object value) { + if (value == null) { + LOG.warn("Storing null value for key {} in cache. That's probably not great.", key); + } + if (ttlMinutes == INFINITE_TTL) { + this.redissonClient.getBucket(name + DELIMITER + key).setAsync(toStoreValue(value)); + } else { + this.redissonClient + .getBucket(name + DELIMITER + key) + .setAsync(toStoreValue(value), ttlMinutes, TimeUnit.MINUTES); + } + } + + @Override + @Nullable + public ValueWrapper putIfAbsent(Object key, @Nullable Object value) { + Object cached = lookup(key); + if (cached != null) { + return toValueWrapper(cached); + } else { + put(key, value); + } + return toValueWrapper(value); + } + + @Override + public void evict(Object pattern) { + evictIfPresent(pattern); + } + + @Override + public boolean evictIfPresent(Object pattern) { + // Pattern is expected to be a regular expression + if (pattern instanceof String) { + String[] keys = + redissonClient + .getKeys() + .getKeysStream() + .filter(key -> key.startsWith(name)) + .filter(key -> key.matches((String) pattern)) + .toArray(String[]::new); + // Calling delete() with empty array causes an error in the Redisson client. + if (keys.length > 0) return redissonClient.getKeys().delete(keys) > 0; + } else { + LOG.warn( + "Pattern passed for cache key eviction is not of String type. Cache eviction could not be performed."); + } + return false; + } + + @Override + public void clear() { + this.redissonClient.getKeys().deleteByPattern(name + DELIMITER + "*"); + } + + @Override + public boolean invalidate() { + return this.redissonClient.getKeys().deleteByPattern(name + DELIMITER + "*") > 0; + } + + @Override + protected Object toStoreValue(@Nullable Object userValue) { + if (userValue == null) { + return null; + } + + ByteArrayOutputStream byteOut = new ByteArrayOutputStream(); + ObjectOutputStream objectOut; + try { + // serialize to byte array + objectOut = new ObjectOutputStream(byteOut); + objectOut.writeObject(userValue); + objectOut.flush(); + byte[] uncompressedByteArray = byteOut.toByteArray(); + + // compress byte array + byteOut = new ByteArrayOutputStream(uncompressedByteArray.length); + GZIPOutputStream g = new GZIPOutputStream(byteOut); + g.write(uncompressedByteArray); + g.close(); + return byteOut.toByteArray(); + } catch (IOException e) { + LOG.warn("Error compressing object for cache: ", e); + return null; + } + } + + @Override + protected Object fromStoreValue(@Nullable Object storeValue) { + if (storeValue == null) { + return null; + } + + byte[] bytes = (byte[]) storeValue; + ByteArrayInputStream byteIn = new ByteArrayInputStream(bytes); + ByteArrayOutputStream byteOut = new ByteArrayOutputStream(); + GZIPInputStream gzipIn; + try { + // inflate to byte array + gzipIn = new GZIPInputStream(byteIn); + byte[] buffer = new byte[1024]; + int len; + while ((len = gzipIn.read(buffer)) != -1) { + byteOut.write(buffer, 0, len); + } + byte[] unzippedBytes = byteOut.toByteArray(); + + // deserialize byte array to object + byteIn = new ByteArrayInputStream(unzippedBytes); + ObjectInputStream oi = new ObjectInputStream(byteIn); + return oi.readObject(); + } catch (IOException | ClassNotFoundException e) { + LOG.warn("Error inflating object from cache: ", e); + return null; + } + } + + @Nullable + @Override + protected Cache.ValueWrapper toValueWrapper(@Nullable Object storeValue) { + return (storeValue != null ? new SimpleValueWrapper(storeValue) : null); + } +} diff --git a/src/main/java/org/cbioportal/legacy/persistence/util/CustomRedisCacheManager.java b/src/main/java/org/cbioportal/legacy/persistence/util/CustomRedisCacheManager.java new file mode 100644 index 00000000000..7d9151c6da1 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/persistence/util/CustomRedisCacheManager.java @@ -0,0 +1,58 @@ +package org.cbioportal.legacy.persistence.util; + +import jakarta.validation.constraints.NotNull; +import java.util.Collection; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import org.redisson.api.RedissonClient; +import org.springframework.cache.Cache; +import org.springframework.cache.CacheManager; + +public class CustomRedisCacheManager implements CacheManager { + private final ConcurrentMap caches = new ConcurrentHashMap<>(); + private final RedissonClient client; + private final long ttlInMins; + + public CustomRedisCacheManager(RedissonClient client, long ttlInMins) { + this.client = client; + this.ttlInMins = ttlInMins; + } + + /** + * Get the cache associated with the given name. + * + *

Note that the cache may be lazily created at runtime if the native provider supports it. + * + * @param name the cache identifier (must not be {@code null}) + * @return the associated cache, or {@code null} if such a cache does not exist or could be not + * created + */ + @Override + public Cache getCache(String name) { + // !name.toLowerCase().contains("static") is a hack. Sometimes spring calls this getCache method + // from + // a place I can't control, so I needed a way in this method to determine whether or not the + // cache + // it's getting should have a ttl. + // In practice, any cache we have that is static should not expire. + // (I mean, we have two caches, so this isn't rocket science) + return getCache(name, !name.toLowerCase().contains("static")); + } + + @NotNull + public Cache getCache(String name, boolean expires) { + long clientTTLInMinutes = expires ? ttlInMins : CustomRedisCache.INFINITE_TTL; + return caches.computeIfAbsent( + name, k -> new CustomRedisCache(name, client, clientTTLInMinutes)); + } + + /** + * Get a collection of the cache names known by this manager. + * + * @return the names of all caches known by the cache manager + */ + @Override + public Collection getCacheNames() { + return caches.keySet(); + } +} diff --git a/src/main/java/org/cbioportal/legacy/persistence/util/CustomRedisCachingProvider.java b/src/main/java/org/cbioportal/legacy/persistence/util/CustomRedisCachingProvider.java new file mode 100644 index 00000000000..94f41d7863d --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/persistence/util/CustomRedisCachingProvider.java @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2020 Memorial Sloan-Kettering Cancer Center. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS + * FOR A PARTICULAR PURPOSE. The software and documentation provided hereunder + * is on an "as is" basis, and Memorial Sloan-Kettering Cancer Center has no + * obligations to provide maintenance, support, updates, enhancements or + * modifications. In no event shall Memorial Sloan-Kettering Cancer Center be + * liable to any party for direct, indirect, special, incidental or + * consequential damages, including lost profits, arising out of the use of this + * software and its documentation, even if Memorial Sloan-Kettering Cancer + * Center has been advised of the possibility of such damage. + */ + +/* + * This file is part of cBioPortal. + * + * cBioPortal is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package org.cbioportal.legacy.persistence.util; + +import org.redisson.Redisson; +import org.redisson.api.RedissonClient; +import org.redisson.config.Config; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.cache.Cache; +import org.springframework.cache.CacheManager; + +public class CustomRedisCachingProvider { + + private static final Logger LOG = LoggerFactory.getLogger(CustomRedisCachingProvider.class); + + @Value("${redis.name:cbioportal}") + private String redisName; + + @Value("${redis.leader_address}") + private String leaderAddress; + + @Value("${redis.follower_address}") + private String followerAddress; + + @Value("${redis.database}") + private Integer database; + + @Value("${redis.password}") + private String password; + + @Value("${redis.ttl_mins:10000}") + private Long expiryMins; + + @Value("${redis.clear_on_startup:true}") + private boolean clearOnStartup; + + public RedissonClient getRedissonClient() { + if (leaderAddress == null || "".equals(leaderAddress)) { + return null; + } + + Config config = new Config(); + LOG.debug("leaderAddress: " + leaderAddress); + LOG.debug("followerAddress: " + followerAddress); + config + .useMasterSlaveServers() + .setMasterAddress(leaderAddress) + .addSlaveAddress(followerAddress) + .setDatabase(database) + .setPassword(password); + + RedissonClient redissonClient = Redisson.create(config); + LOG.debug("Created Redisson Client: " + redissonClient); + return redissonClient; + } + + public CacheManager getCacheManager(RedissonClient redissonClient) { + CustomRedisCacheManager manager = new CustomRedisCacheManager(redissonClient, expiryMins); + + if (clearOnStartup) { + Cache generalCache = manager.getCache(redisName + "GeneralRepositoryCache"); + if (generalCache != null) { + generalCache.clear(); + } + + Cache staticRepositoryCache = manager.getCache(redisName + "StaticRepositoryCacheOne"); + if (staticRepositoryCache != null) { + staticRepositoryCache.clear(); + } + } + return manager; + } +} diff --git a/src/main/java/org/cbioportal/legacy/persistence/util/EhCacheUtils.java b/src/main/java/org/cbioportal/legacy/persistence/util/EhCacheUtils.java new file mode 100644 index 00000000000..65103b66d6a --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/persistence/util/EhCacheUtils.java @@ -0,0 +1,46 @@ +package org.cbioportal.legacy.persistence.util; + +import jakarta.annotation.PostConstruct; +import java.util.ArrayList; +import java.util.List; +import javax.cache.CacheManager; +import org.cbioportal.legacy.utils.config.annotation.ConditionalOnProperty; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +@Component +@ConditionalOnProperty( + name = "persistence.cache_type", + havingValue = {"ehcache-heap", "ehcache-disk", "ehcache-hybrid"}) +public class EhCacheUtils implements CacheUtils { + + @Autowired private CustomEhcachingProvider customEhcachingProvider; + private CacheManager cacheManager; + + @PostConstruct + public void init() { + this.cacheManager = customEhcachingProvider.getCacheManager(); + } + + @Override + public List getKeys(String cacheName) throws IllegalArgumentException { + javax.cache.Cache cache = cacheManager.getCache(cacheName); + if (cache == null) { + throw new IllegalArgumentException("Cannot find cache with name '" + cacheName + "'"); + } + List keysInCache = new ArrayList<>(); + cache.iterator().forEachRemaining(entry -> keysInCache.add(entry.getKey())); + return keysInCache; + } + + @Override + public void evictByPattern(String cacheName, String pattern) { + javax.cache.Cache cache = cacheManager.getCache(cacheName); + this.getKeys(cacheName).stream() + .filter(key -> key.matches(pattern)) + .forEach( + key -> { + cache.remove(key); + }); + } +} diff --git a/src/main/java/org/cbioportal/legacy/persistence/util/EhcacheStatistics.java b/src/main/java/org/cbioportal/legacy/persistence/util/EhcacheStatistics.java new file mode 100644 index 00000000000..8f9c0191671 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/persistence/util/EhcacheStatistics.java @@ -0,0 +1,156 @@ +/* + * Copyright (c) 2019 Memorial Sloan-Kettering Cancer Center. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS + * FOR A PARTICULAR PURPOSE. The software and documentation provided hereunder + * is on an "as is" basis, and Memorial Sloan-Kettering Cancer Center has no + * obligations to provide maintenance, support, updates, enhancements or + * modifications. In no event shall Memorial Sloan-Kettering Cancer Center be + * liable to any party for direct, indirect, special, incidental or + * consequential damages, including lost profits, arising out of the use of this + * software and its documentation, even if Memorial Sloan-Kettering Cancer + * Center has been advised of the possibility of such damage. + */ + +/* + * This file is part of cBioPortal. + * + * cBioPortal is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package org.cbioportal.legacy.persistence.util; + +import jakarta.annotation.PostConstruct; +import java.util.Map; +import org.cbioportal.legacy.utils.config.annotation.ConditionalOnProperty; +import org.ehcache.config.ResourceType; +import org.ehcache.core.statistics.*; +import org.ehcache.impl.internal.statistics.DefaultStatisticsService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +@Component +@ConditionalOnProperty( + name = "persistence.cache_type", + havingValue = {"ehcache-heap", "ehcache-disk", "ehcache-hybrid"}) +public class EhcacheStatistics { + + private static String TIER_NOT_IN_USE = "Tier not in use"; + + private static double BYTES_IN_MB = 1048576.0; + private static double BYTES_IN_GB = 1073741824.0; + + @Autowired private CustomEhcachingProvider customEhcachingProvider; + + private javax.cache.CacheManager cacheManager; + private DefaultStatisticsService statisticsService; + + @PostConstruct + public void initializeStatisticsService() { + try { + cacheManager = customEhcachingProvider.getCacheManager(); + statisticsService = new DefaultStatisticsService(); + for (String cacheName : cacheManager.getCacheNames()) { + javax.cache.Cache cache = cacheManager.getCache(cacheName); + org.ehcache.Cache ehcache = (org.ehcache.Cache) cache.unwrap(org.ehcache.Cache.class); + statisticsService.cacheAdded(cacheName, ehcache); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + public String getCacheStatistics() { + StringBuilder builder = new StringBuilder(); + builder.append("\n\nCACHE_STATISTICS START\n\n"); + for (String cacheName : cacheManager.getCacheNames()) { + builder.append("Cache: " + cacheName + "\n"); + builder.append( + "Allocated (heap): " + getAllocatedBytes(cacheName, ResourceType.Core.HEAP) + "\n"); + builder.append( + "Occupied (heap): " + + getOccupiedBytes(cacheName, "OnHeap", ResourceType.Core.HEAP) + + "\n"); + builder.append( + "Allocated (disk): " + getAllocatedBytes(cacheName, ResourceType.Core.DISK) + "\n"); + builder.append( + "Occupied (disk): " + getOccupiedBytes(cacheName, "Disk", ResourceType.Core.DISK) + "\n"); + builder.append("\n"); + } + builder.append("CACHE_STATISTICS END\n"); + return builder.toString(); + } + + private String getAllocatedBytes(String cacheName, ResourceType.Core resourceType) { + try { + org.ehcache.Cache ehcache = getEhcache(cacheName); + return (getAllocatedBytes(ehcache, resourceType) + getAllocatedUnit(ehcache, resourceType)); + } catch (NullPointerException e) { + return TIER_NOT_IN_USE; + } + } + + private String getOccupiedBytes(String cacheName, String tier, ResourceType.Core resourceType) { + try { + CacheStatistics cacheStatistics = statisticsService.getCacheStatistics(cacheName); + Map tierStatistics = cacheStatistics.getTierStatistics(); + long occupiedBytes = tierStatistics.get(tier).getOccupiedByteSize(); + return scaleOccupiedBytes(cacheName, occupiedBytes, resourceType); + } catch (NullPointerException e) { + return TIER_NOT_IN_USE; + } + } + + private org.ehcache.Cache getEhcache(String cacheName) { + javax.cache.Cache cache = cacheManager.getCache(cacheName); + return (org.ehcache.Cache) cache.unwrap(org.ehcache.Cache.class); + } + + private String getAllocatedBytes(org.ehcache.Cache ehcache, ResourceType.Core resourceType) + throws NullPointerException { + return String.valueOf( + ehcache + .getRuntimeConfiguration() + .getResourcePools() + .getPoolForResource(resourceType) + .getSize()); + } + + private String getAllocatedUnit(org.ehcache.Cache ehcache, ResourceType.Core resourceType) + throws NullPointerException { + return ehcache + .getRuntimeConfiguration() + .getResourcePools() + .getPoolForResource(resourceType) + .getUnit() + .toString(); + } + + private String scaleOccupiedBytes( + String cacheName, long occupiedBytes, ResourceType.Core resourceType) + throws NullPointerException { + org.ehcache.Cache ehcache = getEhcache(cacheName); + String allocatedUnit = getAllocatedUnit(ehcache, resourceType); + if (allocatedUnit.equals("MB")) { + return String.valueOf( + String.format("%.01f", occupiedBytes / BYTES_IN_MB) + "MB (" + occupiedBytes + " bytes)"); + } else if (allocatedUnit.equals("GB")) { + return String.valueOf( + String.format("%.01f", occupiedBytes / BYTES_IN_GB) + "GB (" + occupiedBytes + " bytes)"); + } else { + return (String.valueOf(occupiedBytes) + " bytes"); + } + } +} diff --git a/src/main/java/org/cbioportal/legacy/persistence/util/LoggingCacheErrorHandler.java b/src/main/java/org/cbioportal/legacy/persistence/util/LoggingCacheErrorHandler.java new file mode 100644 index 00000000000..c756190a8ba --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/persistence/util/LoggingCacheErrorHandler.java @@ -0,0 +1,48 @@ +package org.cbioportal.legacy.persistence.util; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.cache.Cache; +import org.springframework.cache.interceptor.CacheErrorHandler; + +/** + * Implementation of org.springframework.cache.interceptor.CacheErrorHandler that logs the error + * messages when performing Redis operations. Redis will throw a RuntimeException causing our APIs + * to return HTTP 500 responses, so we defined this class to just log the errors and allow our app + * fallback to the non-cached version. + */ +public class LoggingCacheErrorHandler implements CacheErrorHandler { + + private static final Logger LOG = LoggerFactory.getLogger(LoggingCacheErrorHandler.class); + + @Override + public void handleCacheGetError(RuntimeException exception, Cache cache, Object key) { + LOG.error( + String.format("Cache '%s' failed to get entry with key '%s'", cache.getName(), key), + exception); + LOG.error(String.format("Cache error message: '%s'", exception.getMessage())); + } + + @Override + public void handleCachePutError( + RuntimeException exception, Cache cache, Object key, Object value) { + LOG.error( + String.format("Cache '%s' failed to put entry with key '%s'", cache.getName(), key), + exception); + LOG.error(String.format("Cache error message: '%s'", exception.getMessage())); + } + + @Override + public void handleCacheEvictError(RuntimeException exception, Cache cache, Object key) { + LOG.error( + String.format("Cache '%s' failed to evict entry with key '%s'", cache.getName(), key), + exception); + LOG.error(String.format("Cache error message: '%s'", exception.getMessage())); + } + + @Override + public void handleCacheClearError(RuntimeException exception, Cache cache) { + LOG.error(String.format("Cache '%s' failed to clear entries", cache.getName()), exception); + LOG.error(String.format("Cache error message: '%s'", exception.getMessage())); + } +} diff --git a/src/main/java/org/cbioportal/legacy/persistence/util/RedisCacheUtils.java b/src/main/java/org/cbioportal/legacy/persistence/util/RedisCacheUtils.java new file mode 100644 index 00000000000..aa5faf82607 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/persistence/util/RedisCacheUtils.java @@ -0,0 +1,47 @@ +package org.cbioportal.legacy.persistence.util; + +import static org.cbioportal.legacy.persistence.util.CustomRedisCache.DELIMITER; + +import java.util.List; +import java.util.stream.Collectors; +import org.redisson.api.RedissonClient; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; +import org.springframework.cache.Cache; +import org.springframework.cache.CacheManager; +import org.springframework.stereotype.Component; + +@Component +@ConditionalOnExpression( + "#{environment['persistence.cache_type'] == 'redis' or environment['persistence.cache_type_clickhouse'] == 'redis'}") +public class RedisCacheUtils implements CacheUtils { + + @Autowired private CacheManager cacheManager; + + @Override + public List getKeys(String cacheName) { + Cache cache = cacheManager.getCache(cacheName); + + if (cache == null) { + throw new RuntimeException("Native cache not of class RedissonCache!!!"); + } + + if (cache.getNativeCache() instanceof RedissonClient) { + return ((RedissonClient) cache.getNativeCache()) + .getKeys() + .getKeysStream() + .filter(k -> k.startsWith(cache.getName() + DELIMITER)) + .collect(Collectors.toList()); + } else { + throw new RuntimeException("Native cache not of class RedissonCache!!!"); + } + } + + @Override + public void evictByPattern(String cacheName, String pattern) { + Cache cache = cacheManager.getCache(cacheName); + if (cache != null) { + cache.evict(pattern); + } + } +} diff --git a/src/main/java/org/cbioportal/legacy/properties/CustomDataSourceConfiguration.java b/src/main/java/org/cbioportal/legacy/properties/CustomDataSourceConfiguration.java new file mode 100644 index 00000000000..2613e1fdbd1 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/properties/CustomDataSourceConfiguration.java @@ -0,0 +1,34 @@ +package org.cbioportal.legacy.properties; + +import javax.sql.DataSource; +import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Profile; + +@Configuration +@Profile("clickhouse") +public class CustomDataSourceConfiguration { + @Bean + @ConfigurationProperties("spring.datasource.mysql") + public DataSourceProperties mysqlDataSourceProperties() { + return new DataSourceProperties(); + } + + @Bean + @ConfigurationProperties("spring.datasource.clickhouse") + public DataSourceProperties clickhouseDatSourceProperties() { + return new DataSourceProperties(); + } + + @Bean("mysqlDataSource") + public DataSource mysqlDataSource() { + return mysqlDataSourceProperties().initializeDataSourceBuilder().build(); + } + + @Bean("clickhouseDataSource") + public DataSource clickhouseDataSource() { + return clickhouseDatSourceProperties().initializeDataSourceBuilder().build(); + } +} diff --git a/src/main/java/org/cbioportal/legacy/properties/PortalProperties.java b/src/main/java/org/cbioportal/legacy/properties/PortalProperties.java new file mode 100644 index 00000000000..9e7f70fe66e --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/properties/PortalProperties.java @@ -0,0 +1,23 @@ +package org.cbioportal.legacy.properties; + +import org.cbioportal.legacy.utils.validation.AllowedValues; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Configuration; +import org.springframework.validation.annotation.Validated; + +@Validated +@Configuration +@ConfigurationProperties +public class PortalProperties { + + @AllowedValues(values = {"false", "saml", "oauth2", "optional_oauth2", "saml_plus_basic"}) + private String authenticate; + + public void setAuthenticate(String authenticate) { + this.authenticate = authenticate; + } + + public String getAuthenticate() { + return authenticate; + } +} diff --git a/src/main/java/org/cbioportal/legacy/service/AlterationCountService.java b/src/main/java/org/cbioportal/legacy/service/AlterationCountService.java new file mode 100644 index 00000000000..e7810c6413d --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/AlterationCountService.java @@ -0,0 +1,93 @@ +package org.cbioportal.legacy.service; + +import java.util.List; +import org.apache.commons.math3.util.Pair; +import org.cbioportal.legacy.model.AlterationCountByGene; +import org.cbioportal.legacy.model.AlterationCountByStructuralVariant; +import org.cbioportal.legacy.model.AlterationFilter; +import org.cbioportal.legacy.model.CopyNumberCountByGene; +import org.cbioportal.legacy.model.MolecularProfileCaseIdentifier; +import org.cbioportal.legacy.model.util.Select; + +public interface AlterationCountService { + + Pair, Long> getSampleAlterationGeneCounts( + List molecularProfileCaseIdentifiers, + Select entrezGeneIds, + boolean includeFrequency, + boolean includeMissingAlterationsFromGenePanel, + AlterationFilter alterationFilter); + + Pair, Long> getPatientAlterationGeneCounts( + List molecularProfileCaseIdentifiers, + Select entrezGeneIds, + boolean includeFrequency, + boolean includeMissingAlterationsFromGenePanel, + AlterationFilter alterationFilter); + + Pair, Long> getSampleMutationGeneCounts( + List molecularProfileCaseIdentifiers, + Select entrezGeneIds, + boolean includeFrequency, + boolean includeMissingAlterationsFromGenePanel, + AlterationFilter alterationFilter); + + Pair, Long> getPatientMutationGeneCounts( + List molecularProfileCaseIdentifiers, + Select entrezGeneIds, + boolean includeFrequency, + boolean includeMissingAlterationsFromGenePanel, + AlterationFilter alterationFilter); + + Pair, Long> getSampleStructuralVariantGeneCounts( + List molecularProfileCaseIdentifiers, + Select entrezGeneIds, + boolean includeFrequency, + boolean includeMissingAlterationsFromGenePanel, + AlterationFilter alterationFilter); + + Pair, Long> getPatientStructuralVariantGeneCounts( + List molecularProfileCaseIdentifiers, + Select entrezGeneIds, + boolean includeFrequency, + boolean includeMissingAlterationsFromGenePanel, + AlterationFilter alterationFilter); + + Pair, Long> getSampleStructuralVariantCounts( + List molecularProfileCaseIdentifiers, + boolean includeFrequency, + boolean includeMissingAlterationsFromGenePanel, + AlterationFilter alterationFilter); + + // Should be restored when old CNA count endpoint is retired + // Pair, Long> + // getSampleCnaCounts(List molecularProfileCaseIdentifiers, + // Select entrezGeneIds, + // boolean includeFrequency, + // boolean + // includeMissingAlterationsFromGenePanel, + // AlterationEventTypeFilter alterationFilter); + // + // Pair, Long> + // getPatientCnaCounts(List molecularProfileCaseIdentifiers, + // Select entrezGeneIds, + // boolean includeFrequency, + // boolean + // includeMissingAlterationsFromGenePanel, + // AlterationEventTypeFilter alterationFilter); + + // Should be removed when old CNA count endpoint is retired + Pair, Long> getSampleCnaGeneCounts( + List molecularProfileCaseIdentifiers, + Select entrezGeneIds, + boolean includeFrequency, + boolean includeMissingAlterationsFromGenePanel, + AlterationFilter alterationFilter); + + Pair, Long> getPatientCnaGeneCounts( + List molecularProfileCaseIdentifiers, + Select entrezGeneIds, + boolean includeFrequency, + boolean includeMissingAlterationsFromGenePanel, + AlterationFilter alterationFilter); +} diff --git a/src/main/java/org/cbioportal/legacy/service/AlterationDriverAnnotationService.java b/src/main/java/org/cbioportal/legacy/service/AlterationDriverAnnotationService.java new file mode 100644 index 00000000000..6fb6cdca64c --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/AlterationDriverAnnotationService.java @@ -0,0 +1,8 @@ +package org.cbioportal.legacy.service; + +import java.util.List; +import org.cbioportal.legacy.model.CustomDriverAnnotationReport; + +public interface AlterationDriverAnnotationService { + CustomDriverAnnotationReport getCustomDriverAnnotationProps(List molecularProfileIds); +} diff --git a/src/main/java/org/cbioportal/legacy/service/AlterationEnrichmentService.java b/src/main/java/org/cbioportal/legacy/service/AlterationEnrichmentService.java new file mode 100644 index 00000000000..6171e7c1f8c --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/AlterationEnrichmentService.java @@ -0,0 +1,18 @@ +package org.cbioportal.legacy.service; + +import java.util.List; +import java.util.Map; +import org.cbioportal.legacy.model.AlterationEnrichment; +import org.cbioportal.legacy.model.AlterationFilter; +import org.cbioportal.legacy.model.EnrichmentType; +import org.cbioportal.legacy.model.MolecularProfileCaseIdentifier; +import org.cbioportal.legacy.service.exception.MolecularProfileNotFoundException; + +public interface AlterationEnrichmentService { + + List getAlterationEnrichments( + Map> molecularProfileCaseSets, + EnrichmentType enrichmentType, + AlterationFilter alterationFilter) + throws MolecularProfileNotFoundException; +} diff --git a/src/main/java/org/cbioportal/legacy/service/AttributeByStudyService.java b/src/main/java/org/cbioportal/legacy/service/AttributeByStudyService.java new file mode 100644 index 00000000000..e4536255b1f --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/AttributeByStudyService.java @@ -0,0 +1,9 @@ +package org.cbioportal.legacy.service; + +import java.util.List; +import org.cbioportal.legacy.model.ClinicalAttribute; + +public interface AttributeByStudyService { + List getClinicalAttributesByStudyIdsAndAttributeIds( + List studyIds, List attributeIds); +} diff --git a/src/main/java/org/cbioportal/legacy/service/CacheService.java b/src/main/java/org/cbioportal/legacy/service/CacheService.java new file mode 100644 index 00000000000..7ab2fa308ae --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/CacheService.java @@ -0,0 +1,10 @@ +package org.cbioportal.legacy.service; + +import org.cbioportal.legacy.service.exception.CacheOperationException; + +public interface CacheService { + void clearCaches(boolean springManagedCache) throws CacheOperationException; + + void clearCachesForStudy(String studyId, boolean springManagedCache) + throws CacheOperationException; +} diff --git a/src/main/java/org/cbioportal/legacy/service/CacheStatisticsService.java b/src/main/java/org/cbioportal/legacy/service/CacheStatisticsService.java new file mode 100644 index 00000000000..84cb1e247c1 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/CacheStatisticsService.java @@ -0,0 +1,13 @@ +package org.cbioportal.legacy.service; + +import java.util.*; +import org.cbioportal.legacy.service.exception.CacheNotFoundException; + +public interface CacheStatisticsService { + + List getKeyCountsPerClass(String cacheName) throws CacheNotFoundException; + + List getKeysInCache(String cacheName) throws CacheNotFoundException; + + String getCacheStatistics(); +} diff --git a/src/main/java/org/cbioportal/legacy/service/CancerTypeService.java b/src/main/java/org/cbioportal/legacy/service/CancerTypeService.java new file mode 100644 index 00000000000..d5070c95dc7 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/CancerTypeService.java @@ -0,0 +1,19 @@ +package org.cbioportal.legacy.service; + +import java.util.List; +import java.util.Map; +import org.cbioportal.legacy.model.TypeOfCancer; +import org.cbioportal.legacy.model.meta.BaseMeta; +import org.cbioportal.legacy.service.exception.CancerTypeNotFoundException; + +public interface CancerTypeService { + + List getAllCancerTypes( + String projection, Integer pageSize, Integer pageNumber, String sortBy, String direction); + + BaseMeta getMetaCancerTypes(); + + TypeOfCancer getCancerType(String cancerTypeId) throws CancerTypeNotFoundException; + + Map getPrimarySiteMap(); +} diff --git a/src/main/java/org/cbioportal/legacy/service/ClinicalAttributeService.java b/src/main/java/org/cbioportal/legacy/service/ClinicalAttributeService.java new file mode 100644 index 00000000000..432923c7551 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/ClinicalAttributeService.java @@ -0,0 +1,39 @@ +package org.cbioportal.legacy.service; + +import java.util.List; +import org.cbioportal.legacy.model.ClinicalAttribute; +import org.cbioportal.legacy.model.ClinicalAttributeCount; +import org.cbioportal.legacy.model.meta.BaseMeta; +import org.cbioportal.legacy.service.exception.ClinicalAttributeNotFoundException; +import org.cbioportal.legacy.service.exception.StudyNotFoundException; + +public interface ClinicalAttributeService extends AttributeByStudyService { + + List getAllClinicalAttributes( + String projection, Integer pageSize, Integer pageNumber, String sortBy, String direction); + + BaseMeta getMetaClinicalAttributes(); + + ClinicalAttribute getClinicalAttribute(String studyId, String clinicalAttributeId) + throws ClinicalAttributeNotFoundException, StudyNotFoundException; + + List getAllClinicalAttributesInStudy( + String studyId, + String projection, + Integer pageSize, + Integer pageNumber, + String sortBy, + String direction) + throws StudyNotFoundException; + + BaseMeta getMetaClinicalAttributesInStudy(String studyId) throws StudyNotFoundException; + + List fetchClinicalAttributes(List studyIds, String projection); + + BaseMeta fetchMetaClinicalAttributes(List studyIds); + + List getClinicalAttributeCountsBySampleIds( + List studyIds, List sampleIds); + + List getClinicalAttributeCountsBySampleListId(String sampleListId); +} diff --git a/src/main/java/org/cbioportal/legacy/service/ClinicalDataDensityPlotService.java b/src/main/java/org/cbioportal/legacy/service/ClinicalDataDensityPlotService.java new file mode 100644 index 00000000000..4e7b9bafb4a --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/ClinicalDataDensityPlotService.java @@ -0,0 +1,14 @@ +package org.cbioportal.legacy.service; + +import java.util.List; +import org.cbioportal.legacy.model.ClinicalData; +import org.cbioportal.legacy.model.DensityPlotData; +import org.cbioportal.legacy.web.parameter.StudyViewFilter; +import org.cbioportal.legacy.web.util.DensityPlotParameters; + +public interface ClinicalDataDensityPlotService { + DensityPlotData getDensityPlotData( + List filteredClinicalData, + DensityPlotParameters densityPlotParameters, + StudyViewFilter studyViewFilter); +} diff --git a/src/main/java/org/cbioportal/legacy/service/ClinicalDataService.java b/src/main/java/org/cbioportal/legacy/service/ClinicalDataService.java new file mode 100644 index 00000000000..8648135cfdf --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/ClinicalDataService.java @@ -0,0 +1,93 @@ +package org.cbioportal.legacy.service; + +import java.util.List; +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.cbioportal.legacy.model.ClinicalData; +import org.cbioportal.legacy.model.ClinicalDataCountItem; +import org.cbioportal.legacy.model.SampleClinicalDataCollection; +import org.cbioportal.legacy.model.meta.BaseMeta; +import org.cbioportal.legacy.service.exception.PatientNotFoundException; +import org.cbioportal.legacy.service.exception.SampleNotFoundException; +import org.cbioportal.legacy.service.exception.StudyNotFoundException; + +public interface ClinicalDataService { + + List getAllClinicalDataOfSampleInStudy( + String studyId, + String sampleId, + String attributeId, + String projection, + Integer pageSize, + Integer pageNumber, + String sortBy, + String direction) + throws SampleNotFoundException, StudyNotFoundException; + + BaseMeta getMetaSampleClinicalData(String studyId, String sampleId, String attributeId) + throws SampleNotFoundException, StudyNotFoundException; + + List getAllClinicalDataOfPatientInStudy( + String studyId, + String patientId, + String attributeId, + String projection, + Integer pageSize, + Integer pageNumber, + String sortBy, + String direction) + throws PatientNotFoundException, StudyNotFoundException; + + BaseMeta getMetaPatientClinicalData(String studyId, String patientId, String attributeId) + throws PatientNotFoundException, StudyNotFoundException; + + List getAllClinicalDataInStudy( + String studyId, + String attributeId, + String clinicalDataType, + String projection, + Integer pageSize, + Integer pageNumber, + String sortBy, + String direction) + throws StudyNotFoundException; + + BaseMeta getMetaAllClinicalData(String studyId, String attributeId, String clinicalDataType) + throws StudyNotFoundException; + + List fetchAllClinicalDataInStudy( + String studyId, + List ids, + List attributeIds, + String clinicalDataType, + String projection) + throws StudyNotFoundException; + + BaseMeta fetchMetaClinicalDataInStudy( + String studyId, List ids, List attributeIds, String clinicalDataType) + throws StudyNotFoundException; + + List fetchClinicalData( + List studyIds, + List ids, + List attributeIds, + String clinicalDataType, + String projection); + + BaseMeta fetchMetaClinicalData( + List studyIds, List ids, List attributeIds, String clinicalDataType); + + List fetchClinicalDataCounts( + List studyIds, List sampleIds, List attributeIds); + + List getPatientClinicalDataDetailedToSample( + List studyIds, List patientIds, List attributeIds); + + ImmutablePair fetchSampleClinicalTable( + List studyIds, + List sampleIds, + Integer pageSize, + Integer pageNumber, + String searchTerm, + String sortBy, + String direction); +} diff --git a/src/main/java/org/cbioportal/legacy/service/ClinicalEventService.java b/src/main/java/org/cbioportal/legacy/service/ClinicalEventService.java new file mode 100644 index 00000000000..f1632828800 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/ClinicalEventService.java @@ -0,0 +1,53 @@ +package org.cbioportal.legacy.service; + +import java.util.List; +import java.util.Map; +import java.util.Set; +import org.cbioportal.legacy.model.ClinicalData; +import org.cbioportal.legacy.model.ClinicalEvent; +import org.cbioportal.legacy.model.ClinicalEventTypeCount; +import org.cbioportal.legacy.model.meta.BaseMeta; +import org.cbioportal.legacy.service.exception.PatientNotFoundException; +import org.cbioportal.legacy.service.exception.StudyNotFoundException; +import org.cbioportal.legacy.web.parameter.SurvivalRequest; + +public interface ClinicalEventService { + + List getAllClinicalEventsOfPatientInStudy( + String studyId, + String patientId, + String projection, + Integer pageSize, + Integer pageNumber, + String sortBy, + String direction) + throws PatientNotFoundException, StudyNotFoundException; + + BaseMeta getMetaPatientClinicalEvents(String studyId, String patientId) + throws PatientNotFoundException, StudyNotFoundException; + + List getAllClinicalEventsInStudy( + String studyId, + String projection, + Integer pageSize, + Integer pageNumber, + String sortBy, + String direction); + + BaseMeta getMetaClinicalEvents(String studyId) throws StudyNotFoundException; + + Map> getPatientsSamplesPerClinicalEventType( + List studyIds, List sampleIds); + + List getClinicalEventTypeCounts( + List studyIds, List sampleIds); + + List getSurvivalData( + List studyIds, + List patientIds, + String attributeIdPrefix, + SurvivalRequest survivalRequest); + + List getClinicalEventsMeta( + List studyIds, List patientIds, List clinicalEvents); +} diff --git a/src/main/java/org/cbioportal/legacy/service/CoExpressionService.java b/src/main/java/org/cbioportal/legacy/service/CoExpressionService.java new file mode 100644 index 00000000000..c5f4068349b --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/CoExpressionService.java @@ -0,0 +1,49 @@ +package org.cbioportal.legacy.service; + +import java.util.List; +import org.cbioportal.legacy.model.CoExpression; +import org.cbioportal.legacy.model.EntityType; +import org.cbioportal.legacy.service.exception.GeneNotFoundException; +import org.cbioportal.legacy.service.exception.GenesetNotFoundException; +import org.cbioportal.legacy.service.exception.MolecularProfileNotFoundException; +import org.cbioportal.legacy.service.exception.SampleListNotFoundException; + +public interface CoExpressionService { + + List getCoExpressions( + String molecularProfileId, + String sampleListId, + String geneticEntityId, + EntityType geneticEntityType, + Double threshold) + throws MolecularProfileNotFoundException, GenesetNotFoundException, GeneNotFoundException; + + List getCoExpressions( + String geneticEntityId, + EntityType geneticEntityType, + String sampleListId, + String molecularProfileIdA, + String molecularProfileIdB, + Double threshold) + throws MolecularProfileNotFoundException, + SampleListNotFoundException, + GenesetNotFoundException, + GeneNotFoundException; + + List fetchCoExpressions( + String geneticEntityId, + EntityType geneticEntityType, + List sampleIds, + String molecularProfileIdA, + String molecularProfileIdB, + Double threshold) + throws MolecularProfileNotFoundException, GenesetNotFoundException, GeneNotFoundException; + + List fetchCoExpressions( + String molecularProfileId, + List sampleIds, + String geneticEntityId, + EntityType geneticEntityType, + Double threshold) + throws MolecularProfileNotFoundException, GenesetNotFoundException, GeneNotFoundException; +} diff --git a/src/main/java/org/cbioportal/legacy/service/CopyNumberSegmentService.java b/src/main/java/org/cbioportal/legacy/service/CopyNumberSegmentService.java new file mode 100644 index 00000000000..d94385d515d --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/CopyNumberSegmentService.java @@ -0,0 +1,34 @@ +package org.cbioportal.legacy.service; + +import java.util.List; +import org.cbioportal.legacy.model.CopyNumberSeg; +import org.cbioportal.legacy.model.meta.BaseMeta; +import org.cbioportal.legacy.service.exception.SampleNotFoundException; +import org.cbioportal.legacy.service.exception.StudyNotFoundException; + +public interface CopyNumberSegmentService { + + List getCopyNumberSegmentsInSampleInStudy( + String studyId, + String sampleId, + String chromosome, + String projection, + Integer pageSize, + Integer pageNumber, + String sortBy, + String direction) + throws SampleNotFoundException, StudyNotFoundException; + + BaseMeta getMetaCopyNumberSegmentsInSampleInStudy( + String studyId, String sampleId, String chromosome) + throws SampleNotFoundException, StudyNotFoundException; + + List fetchCopyNumberSegments( + List studyIds, List sampleIds, String chromosome, String projection); + + BaseMeta fetchMetaCopyNumberSegments( + List studyIds, List sampleIds, String chromosome); + + List getCopyNumberSegmentsBySampleListId( + String studyId, String sampleListId, String chromosome, String projection); +} diff --git a/src/main/java/org/cbioportal/legacy/service/CosmicCountService.java b/src/main/java/org/cbioportal/legacy/service/CosmicCountService.java new file mode 100644 index 00000000000..52ef3b74ae3 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/CosmicCountService.java @@ -0,0 +1,9 @@ +package org.cbioportal.legacy.service; + +import java.util.List; +import org.cbioportal.legacy.model.CosmicMutation; + +public interface CosmicCountService { + + List fetchCosmicCountsByKeywords(List keywords); +} diff --git a/src/main/java/org/cbioportal/legacy/service/CustomDataService.java b/src/main/java/org/cbioportal/legacy/service/CustomDataService.java new file mode 100644 index 00000000000..aa86c65f626 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/CustomDataService.java @@ -0,0 +1,9 @@ +package org.cbioportal.legacy.service; + +import java.util.List; +import java.util.Map; +import org.cbioportal.legacy.service.util.CustomDataSession; + +public interface CustomDataService { + Map getCustomDataSessions(List attributes); +} diff --git a/src/main/java/org/cbioportal/legacy/service/DataAccessTokenService.java b/src/main/java/org/cbioportal/legacy/service/DataAccessTokenService.java new file mode 100644 index 00000000000..16056b343b4 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/DataAccessTokenService.java @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2018 Memorial Sloan-Kettering Cancer Center. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS + * FOR A PARTICULAR PURPOSE. The software and documentation provided hereunder + * is on an "as is" basis, and Memorial Sloan-Kettering Cancer Center has no + * obligations to provide maintenance, support, updates, enhancements or + * modifications. In no event shall Memorial Sloan-Kettering Cancer Center be + * liable to any party for direct, indirect, special, incidental or + * consequential damages, including lost profits, arising out of the use of this + * software and its documentation, even if Memorial Sloan-Kettering Cancer + * Center has been advised of the possibility of such damage. + */ + +/* + * This file is part of cBioPortal. + * + * cBioPortal is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package org.cbioportal.legacy.service; + +import java.util.Date; +import java.util.List; +import org.cbioportal.legacy.model.DataAccessToken; +import org.springframework.security.core.Authentication; + +public interface DataAccessTokenService { + + public DataAccessToken createDataAccessToken(String username); + + public List getAllDataAccessTokens(String username); + + public DataAccessToken getDataAccessToken(String username); + + public DataAccessToken getDataAccessTokenInfo(String token); + + public void revokeAllDataAccessTokens(String username); + + public void revokeDataAccessToken(String token); + + public String getUsername(String token); + + public Date getExpiration(String token); + + public Authentication createAuthenticationRequest(String token); + + /** + * Tests token validity. Token is valid if: - not yet expired and - not revoked and - can be + * verified as issued through this service (maybe via signature) + * + * @param token + * @return + */ + public Boolean isValid(String token); +} diff --git a/src/main/java/org/cbioportal/legacy/service/DiscreteCopyNumberService.java b/src/main/java/org/cbioportal/legacy/service/DiscreteCopyNumberService.java new file mode 100644 index 00000000000..d4b749b8c91 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/DiscreteCopyNumberService.java @@ -0,0 +1,66 @@ +package org.cbioportal.legacy.service; + +import java.util.List; +import org.cbioportal.legacy.model.CopyNumberCount; +import org.cbioportal.legacy.model.CopyNumberCountByGene; +import org.cbioportal.legacy.model.DiscreteCopyNumberData; +import org.cbioportal.legacy.model.GeneFilterQuery; +import org.cbioportal.legacy.model.meta.BaseMeta; +import org.cbioportal.legacy.service.exception.MolecularProfileNotFoundException; + +public interface DiscreteCopyNumberService { + + List getDiscreteCopyNumbersInMolecularProfileBySampleListId( + String molecularProfileId, + String sampleListId, + List entrezGeneIds, + List alterationTypes, + String projection) + throws MolecularProfileNotFoundException; + + BaseMeta getMetaDiscreteCopyNumbersInMolecularProfileBySampleListId( + String molecularProfileId, + String sampleListId, + List entrezGeneIds, + List alterationTypes) + throws MolecularProfileNotFoundException; + + List fetchDiscreteCopyNumbersInMolecularProfile( + String molecularProfileId, + List sampleIds, + List entrezGeneIds, + List alterationTypes, + String projection) + throws MolecularProfileNotFoundException; + + List getDiscreteCopyNumbersInMultipleMolecularProfiles( + List molecularProfileIds, + List sampleIds, + List entrezGeneIds, + List alterationTypes, + String projection); + + List getDiscreteCopyNumbersInMultipleMolecularProfilesByGeneQueries( + List molecularProfileIds, + List sampleIds, + List geneQueries, + String projection); + + BaseMeta fetchMetaDiscreteCopyNumbersInMolecularProfile( + String molecularProfileId, + List sampleIds, + List entrezGeneIds, + List alterationTypes) + throws MolecularProfileNotFoundException; + + List getSampleCountByGeneAndAlterationAndSampleIds( + String molecularProfileId, + List sampleIds, + List entrezGeneIds, + List alterations) + throws MolecularProfileNotFoundException; + + List fetchCopyNumberCounts( + String molecularProfileId, List entrezGeneIds, List alterations) + throws MolecularProfileNotFoundException; +} diff --git a/src/main/java/org/cbioportal/legacy/service/ExpressionEnrichmentService.java b/src/main/java/org/cbioportal/legacy/service/ExpressionEnrichmentService.java new file mode 100644 index 00000000000..7a6a53ae526 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/ExpressionEnrichmentService.java @@ -0,0 +1,38 @@ +package org.cbioportal.legacy.service; + +import java.util.List; +import java.util.Map; +import org.cbioportal.legacy.model.EnrichmentType; +import org.cbioportal.legacy.model.GenericAssayBinaryEnrichment; +import org.cbioportal.legacy.model.GenericAssayCategoricalEnrichment; +import org.cbioportal.legacy.model.GenericAssayEnrichment; +import org.cbioportal.legacy.model.GenomicEnrichment; +import org.cbioportal.legacy.model.MolecularProfileCaseIdentifier; +import org.cbioportal.legacy.service.exception.MolecularProfileNotFoundException; + +public interface ExpressionEnrichmentService { + + List getGenomicEnrichments( + String molecularProfileId, + Map> molecularProfileCaseSets, + EnrichmentType enrichmentType) + throws MolecularProfileNotFoundException; + + List getGenericAssayNumericalEnrichments( + String molecularProfileId, + Map> molecularProfileCaseSets, + EnrichmentType enrichmentType) + throws MolecularProfileNotFoundException; + + List getGenericAssayBinaryEnrichments( + String molecularProfileId, + Map> molecularProfileCaseSets, + EnrichmentType enrichmentType) + throws MolecularProfileNotFoundException; + + List getGenericAssayCategoricalEnrichments( + String molecularProfileId, + Map> molecularProfileCaseSets, + EnrichmentType enrichmentType) + throws MolecularProfileNotFoundException; +} diff --git a/src/main/java/org/cbioportal/legacy/service/FrontendPropertiesService.java b/src/main/java/org/cbioportal/legacy/service/FrontendPropertiesService.java new file mode 100644 index 00000000000..3f458466c08 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/FrontendPropertiesService.java @@ -0,0 +1,10 @@ +package org.cbioportal.legacy.service; + +import java.util.Map; + +public interface FrontendPropertiesService { + + String getFrontendProperty(FrontendPropertiesServiceImpl.FrontendProperty property); + + Map getFrontendProperties(); +} diff --git a/src/main/java/org/cbioportal/legacy/service/FrontendPropertiesServiceImpl.java b/src/main/java/org/cbioportal/legacy/service/FrontendPropertiesServiceImpl.java new file mode 100644 index 00000000000..53ff99bedef --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/FrontendPropertiesServiceImpl.java @@ -0,0 +1,404 @@ +package org.cbioportal.legacy.service; + +import jakarta.annotation.PostConstruct; +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; +import java.util.stream.Collectors; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.env.Environment; +import org.springframework.stereotype.Service; + +// Class adapted from legacy config_service.jsp and GlobalProperties.java +@Service +public class FrontendPropertiesServiceImpl implements FrontendPropertiesService { + + private final Logger log = LoggerFactory.getLogger(FrontendPropertiesServiceImpl.class); + + // This enum holds properties exposed to the frontend reactapp. + // Format: ("", "") + // There are some properties that require processing before being exposed to the frontend. + public enum FrontendProperty { + dat_method("dat.method", null), + oncoprint_custom_driver_annotation_binary_menu_label( + "oncoprint.custom_driver_annotation.binary.menu_label", null), + oncoprint_custom_driver_annotation_binary_menu_description( + "oncoprint.custom_driver_annotation.binary.menu_description", null), + disabled_tabs("disabled_tabs", null), + civic_url("civic.url", null), + oncoprint_custom_driver_annotation_binary_default( + "oncoprint.custom_driver_annotation.binary.default", null), + oncoprint_oncokb_default("oncoprint.oncokb.default", null), + oncoprint_hotspots_default("oncoprint.hotspots.default", null), + oncoprint_clustered_default("oncoprint.clustered.default", null), + oncokb_merge_icons_by_default("oncokb.merge_icons_by_default", null), + oncoprint_clinical_tracks_config_json("oncoprint.clinical_tracks.config_json", null), + genomenexus_url("genomenexus.url", null), + genomenexus_url_grch38("genomenexus.url.grch38", null), + genomenexus_isoform_override_source("genomenexus.isoform_override_source", null), + google_analytics_profile_id("google_analytics_profile_id", null), + google_tag_manager_id("google_tag_manager_id", null), + analytics_report_url("analytics_report_url", null), + oncoprint_hide_vus_default("oncoprint.hide_vus.default", null), + mycancergenome_show("mycancergenome.show", null), + oncokb_public_api_url("oncokb.public_api.url", null), + digitalslidearchive_iframe_url("digitalslidearchive.iframe.url", null), + digitalslidearchive_meta_url("digitalslidearchive.meta.url", null), + mdacc_heatmap_meta_url("mdacc.heatmap.meta.url", null), + mdacc_heatmap_patient_url("mdacc.heatmap.patient.url", null), + mdacc_heatmap_study_meta_url("mdacc.heatmap.study.meta.url", null), + mdacc_heatmap_study_url("mdacc.heatmap.study.url", null), + show_mdacc_heatmap("show.mdacc.heatmap", null), + oncoprint_custom_driver_annotation_tiers_menu_label( + "oncoprint.custom_driver_annotation.tiers.menu_label", null), + oncoprint_custom_driver_annotation_tiers_menu_description( + "oncoprint.custom_driver_annotation.tiers.menu_description", null), + patient_view_use_legacy_timeline("patient_view.use_legacy_timeline", null), + installation_map_url("installation_map_url", null), + priority_studies("priority_studies", null), + show_hotspot("show.hotspot", null), + show_oncokb("show.oncokb", null), + show_civic("show.civic", null), + show_genomenexus("show.genomenexus", null), + show_genomenexus_annotation_sources("show.genomenexus.annotation_sources", null), + show_mutation_mappert_tool_grch38("show.mutation_mappert_tool.grch38", null), + show_transcript_dropdown("show.transcript_dropdown", null), + show_signal("show.signal", null), + show_cbioportal("show.cbioportal", null), + show_cosmic("show.cosmic", null), + show_ndex("show.ndex", null), + survival_show_p_q_values_in_survival_type_table( + "survival.show_p_q_values_in_survival_type_table", null), + survival_min_group_threshold("survival.min_group_threshold", null), + survival_initial_x_axis_limit("survival.initial_x_axis_limit", null), + skin_documentation_about("skin.documentation.about", null), + skin_documentation_baseurl("skin.documentation.baseurl", null), + skin_example_study_queries("skin.example_study_queries", null), + skin_blurb("skin.blurb", null), + skin_custom_header_tabs("skin.custom_header_tabs", null), + skin_data_sets_footer("skin.data_sets_footer", null), + skin_data_sets_header("skin.data_sets_header", null), + skin_documentation_markdown("skin.documentation.markdown", null), + skin_email_contact("skin.email_contact", null), + skin_examples_right_column_html("skin.examples_right_column_html", null), + skin_documentation_faq("skin.documentation.faq", null), + skin_footer("skin.footer", null), + skin_footer_show_dev("skin.footer_show_dev", null), + skin_login_contact_html("skin.login.contact_html", null), + skin_login_saml_registration_html("skin.login.saml.registration_html", null), + skin_documentation_news("skin.documentation.news", null), + skin_documentation_oql("skin.documentation.oql", null), + skin_query_max_tree_depth("skin.query.max_tree_depth", null), + skin_quick_select_buttons("skin.quick_select_buttons", null), + skin_right_logo("skin.right_logo", null), + skin_left_logo("skin.left_logo", null), + skin_right_nav_show_data_sets("skin.right_nav.show_data_sets", null), + skin_right_nav_show_examples("skin.right_nav.show_examples", null), + skin_right_nav_show_testimonials("skin.right_nav.show_testimonials", null), + skin_right_nav_show_whats_new("skin.right_nav.show_whats_new", null), + skin_right_nav_show_twitter("skin.right_nav.show_twitter", null), + skin_right_nav_whats_new_blurb("skin.right_nav.whats_new_blurb", null), + skin_show_about_tab("skin.show_about_tab", null), + skin_show_data_tab("skin.show_data_tab", null), + skin_show_faqs_tab("skin.show_faqs_tab", null), + skin_show_news_tab("skin.show_news_tab", null), + skin_show_r_matlab_tab("skin.show_r_matlab_tab", null), + skin_show_tools_tab("skin.show_tools_tab", null), + skin_show_tutorials_tab("skin.show_tutorials_tab", null), + skin_show_web_api_tab("skin.show_web_api_tab", null), + skin_show_tweet_button("skin.show_tweet_button", null), + skin_show_study_help_button("skin.show_study_help_button", null), + skin_patientview_filter_genes_profiled_all_samples( + "skin.patientview.filter_genes_profiled_all_samples", null), + skin_patientview_show_mskcc_slide_viewer("skin.patientview.show_mskcc_slide_viewer", null), + skin_show_settings_menu("skin.show_settings_menu", null), + skin_hide_logout_button("skin.hide_logout_button", null), + quick_search_enabled("quick_search.enabled", null), + default_cross_cancer_study_session_id("default_cross_cancer_study_session_id", null), + default_cross_cancer_study_list("default_cross_cancer_study_list", null), + default_cross_cancer_study_list_name("default_cross_cancer_study_list_name", null), + skin_description("skin.description", null), + skin_title("skin.title", null), + app_name("app.name", null), + skin_authorization_message("skin.authorization_message", null), + session_url_length_threshold("session.url_length_threshold", null), + bitly_api_key("bitly.api_key", null), + bitly_user("bitly.user", null), + bitly_access_token("bitly.access.token", null), + oncoprint_custom_driver_annotation_tiers_default( + "oncoprint.custom_driver_annotation.tiers.default", null), + ensembl_transcript_url("ensembl.transcript_url", null), + enable_persistent_cache("enable_persistent_cache", null), + enable_request_body_gzip_compression("enable_request_body_gzip_compression", null), + query_product_limit("query_product_limit", null), + skin_show_gsva("skin.show_gsva", null), + saml_idp_metadata_entityid("saml.idp.metadata.entityid", null), + saml_logout_local("saml.logout.local", null), + skin_citation_rule_text("skin.citation_rule_text", null), + skin_geneset_hierarchy_default_p_value("skin.geneset_hierarchy.default_p_value", null), + skin_geneset_hierarchy_default_gsva_score("skin.geneset_hierarchy.default_gsva_score", null), + app_version("app.version", null), + frontendSentryEndpoint("sentryjs.frontend_project_endpoint", null), + + // These properties require additional processing. + // Names refer to the property that requires processing. + frontendConfigOverride("frontend.config", null), + query_sets_of_genes("querypage.setsofgenes.location", null), + authenticationMethod("authenticate", "false"), + mskWholeSlideViewerToken("msk.whole.slide.viewer.secret.key", null), + oncoprintOncoKbHotspotsDefault("oncoprint.oncokb_hotspots.default", "true"), + oncoKbTokenDefined("oncokb.token", ""), + sessionServiceEnabled("session.service.url", ""), + frontendUrl("frontend.url", null), + skin_hide_download_controls("skin.hide_download_controls", "show"), + study_download_url("study_download_url", "https://cbioportal-datahub.s3.amazonaws.com/"), + enable_cross_study_expression("enable_cross_study_expression", ""), + studyview_max_samples_selected("studyview.max_samples_selected", null), + skin_home_page_show_reference_genome("skin.home_page.show_reference_genome", null), + vaf_sequential_mode_default("vaf.sequential_mode.default", null), + vaf_log_scale_default("vaf.log_scale.default", null), + skin_patient_view_custom_sample_type_colors_json( + "skin.patient_view.custom_sample_type_colors_json", null), + skin_study_view_show_sv_table("skin.study_view.show_sv_table", null), + skin_home_page_show_unauthorized_studies("skin.home_page.show_unauthorized_studies", null), + skin_home_page_unauthorized_studies_global_message( + "skin.home_page.unauthorized_studies_global_message", null), + skin_mutation_table_namespace_column_show_by_default( + "skin.mutation_table.namespace_column.show_by_default", null), + skin_geneset_hierarchy_collapse_by_default("skin.geneset_hierarchy.collapse_by_default", null), + skin_patient_view_mutation_table_columns_show_on_init( + "skin.patient_view.mutation_table.columns.show_on_init", null), + skin_results_view_mutation_table_columns_show_on_init( + "skin.results_view.mutation_table.columns.show_on_init", null), + skin_patient_view_copy_number_table_columns_show_on_init( + "skin.patient_view.copy_number_table.columns.show_on_init", null), + skin_patient_view_structural_variant_table_columns_show_on_init( + "skin.patient_view.structural_variant_table.columns.show_on_init", null), + skin_results_view_tables_default_sort_column( + "skin.results_view.tables.default_sort_column", null), + skin_survival_plot_clinical_event_types_show_on_init( + "skin.survival_plot.clinical_event_types.show_on_init", null), + skin_show_donate_button("skin.show_donate_button", "false"), + + skin_patient_view_tables_default_sort_column( + "skin.patient_view.tables.default_sort_column", null), + enable_treatment_groups("enable_treatment_groups", null), + comparison_categorical_na_values("comparison.categorical_na_values", null), + clinical_attribute_product_limit("clinical_attribute_product_limit", null), + skin_right_nav_show_web_tours("skin.right_nav.show_web_tours", "false"), + + download_custom_buttons_json("download_custom_buttons_json", null), + + enable_study_tags("enable_study_tags", null), + + clickhouse_mode("clickhouse_mode", "false"); + + private final String propertyName; + private final String defaultValue; + + FrontendProperty(String name, String defaultValue) { + this.propertyName = name; + this.defaultValue = defaultValue; + } + + public String getPropertyName() { + return propertyName; + } + + public String getFrontendName() { + return this.name(); + } + + public String getDefaultValue() { + return defaultValue; + } + } + + @Autowired private Environment env; + + private static Map serverConfigProperties; + + @PostConstruct + public void init() { + serverConfigProperties = + Arrays.stream(FrontendProperty.values()) + // do not use toMap here because null values are problematic + .collect( + HashMap::new, + (out, property) -> out.put(property.getFrontendName(), getPropertyValue(property)), + HashMap::putAll); + } + + private String getPropertyValue(FrontendProperty property) { + String propertyValue = env.getProperty(property.getPropertyName(), property.getDefaultValue()); + if (propertyValue != null) propertyValue = propertyValue.trim(); + switch (property.getFrontendName()) { + // First, add properties that require pre-processing. + case "frontendConfigOverride": + case "query_sets_of_genes": + case "skin_patient_view_custom_sample_type_colors_json": + case "oncoprint_clinical_tracks_config_json": + case "download_custom_buttons_json": + return readFile(propertyValue); + case "oncoprintOncoKbHotspotsDefault": + return enableOncoKBandHotspotsParamValue(propertyValue); + case "oncoKbTokenDefined": + case "sessionServiceEnabled": + return String.valueOf(!propertyValue.isEmpty()); + case "frontendUrl": + return getFrontendUrl(propertyValue); + // For others, just return the value in the properties file. + default: + return propertyValue; + } + } + + private String enableOncoKBandHotspots(String enableOncoKBandHotspots) { + if (enableOncoKBandHotspots.equalsIgnoreCase("custom")) { + return "custom"; + } else if (enableOncoKBandHotspots.equalsIgnoreCase("false")) { + return "false"; + } + return "true"; + } + + private String enableOncoKBandHotspotsParamValue(String enableOncoKBandHotspots) { + switch (enableOncoKBandHotspots(enableOncoKBandHotspots)) { + case "true": + return "undefined"; + case "false": + return "\"disable\""; + case "custom": + return "\"custom\""; + } + return null; + } + + public String getFrontendProperty(FrontendProperty property) { + return serverConfigProperties.get(property.getFrontendName()); + } + + public Map getFrontendProperties() { + // Make sure that requests work on individual instances of this data. + return cloneProperties(); + } + + private Map cloneProperties() { + return serverConfigProperties.entrySet().stream() + .collect( + HashMap::new, + (out, entry) -> out.put(entry.getKey(), entry.getValue()), + HashMap::putAll); + } + + /** + * Find the file, either on the file system or in a .jar, and return as an InputStream. + * + * @propertiesFileName: the file path + * @return: a valid InputStream (not null), otherwise throws FileNotFoundException TECH: file + * system locations have precedence over classpath REF: based on getResourceStream() in + * WebServletContextListener.java + */ + private InputStream locateFile(String filePath) throws FileNotFoundException { + // try absolute or relative to working directory + File file = new File(filePath); + if (file.exists()) { + // throws if is a directory or cannot be opened + log.info("Found frontend config file: {}", file.getAbsolutePath()); + return new FileInputStream(file); + } + + // try relative to PORTAL_HOME + String home = System.getenv("PORTAL_HOME"); + if (home != null) { + file = new File(Paths.get(home, filePath).toString()); + if (file.exists()) { + log.info("Found frontend config file: {}", file.getAbsolutePath()); + return new FileInputStream(file); + } + } + + // try resource (e.g. app.jar) + InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream(filePath); + if (inputStream != null) { + log.info("Found frontend config resource: {}", filePath); + return inputStream; + } else { + throw new FileNotFoundException("File not found in system or classpath: " + filePath); + } + } + + /** + * Read the file, either on the file system or in a .jar, and return the content as a single-line + * string. + * + * @propertiesFileName: the file path + */ + private String readFile(String propertiesFileName) { + if (propertiesFileName == null || propertiesFileName.isEmpty()) { + return null; + } + + // strip off classpath prefix and always check all locations (ClassLoader and file system) + String filePath = + propertiesFileName.startsWith("classpath:") + ? propertiesFileName.substring("classpath:".length()) + : propertiesFileName; + + try { + InputStream inputStream = locateFile(filePath); + BufferedReader br = new BufferedReader(new InputStreamReader(inputStream)); + return br.lines().map(String::trim).collect(Collectors.joining("")); + } catch (Exception e) { + log.error("Error reading frontend config file: {}", e.getMessage()); + return null; + } + } + + public String getFrontendUrl(String propertyValue) { + String frontendUrlRuntime = env.getProperty("frontend.url.runtime", ""); + if (frontendUrlRuntime.length() > 0) { + try { + String url = + parseUrl(Files.readString(Paths.get(frontendUrlRuntime)).replaceAll("[\\r\\n]+", "")); + if (log.isInfoEnabled()) { + log.info("Using frontend from {}: {}", frontendUrlRuntime, url); + } + return url; + } catch (IOException e) { + // error reading file, use existing frontendUrl + if (log.isErrorEnabled()) { + log.error("Can't read frontend.url.runtime: {}", frontendUrlRuntime); + } + } + } + return propertyValue; + } + + /* + * Trim whitespace of url and append / if it does not exist. Return empty + * string otherwise. + */ + public static String parseUrl(String url) { + String rv = ""; + if (url != null && !url.isEmpty()) { + rv = url.trim(); + if (!rv.endsWith("/")) { + rv += "/"; + } + } + return rv; + } +} diff --git a/src/main/java/org/cbioportal/legacy/service/GeneMemoizerService.java b/src/main/java/org/cbioportal/legacy/service/GeneMemoizerService.java new file mode 100644 index 00000000000..24ef312ff07 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/GeneMemoizerService.java @@ -0,0 +1,10 @@ +package org.cbioportal.legacy.service; + +import java.util.List; +import org.cbioportal.legacy.model.ReferenceGenomeGene; + +public interface GeneMemoizerService { + List fetchGenes(String genomeName); + + void cacheGenes(List genes, String genomeName); +} diff --git a/src/main/java/org/cbioportal/legacy/service/GenePanelService.java b/src/main/java/org/cbioportal/legacy/service/GenePanelService.java new file mode 100644 index 00000000000..5ab50b4b01d --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/GenePanelService.java @@ -0,0 +1,46 @@ +package org.cbioportal.legacy.service; + +import java.util.List; +import java.util.Set; +import org.cbioportal.legacy.model.GenePanel; +import org.cbioportal.legacy.model.GenePanelData; +import org.cbioportal.legacy.model.MolecularProfileCaseIdentifier; +import org.cbioportal.legacy.model.meta.BaseMeta; +import org.cbioportal.legacy.service.exception.GenePanelNotFoundException; +import org.cbioportal.legacy.service.exception.MolecularProfileNotFoundException; +import org.springframework.cache.annotation.Cacheable; + +public interface GenePanelService { + + List getAllGenePanels( + String projection, Integer pageSize, Integer pageNumber, String sortBy, String direction); + + BaseMeta getMetaGenePanels(); + + GenePanel getGenePanel(String genePanelId) throws GenePanelNotFoundException; + + List getGenePanelData(String molecularProfileId, String sampleListId) + throws MolecularProfileNotFoundException; + + List fetchGenePanelData(String molecularProfileId, List sampleIds) + throws MolecularProfileNotFoundException; + + @Cacheable( + cacheResolver = "staticRepositoryCacheOneResolver", + condition = "@cacheEnabledConfig.getEnabled()") + List fetchGenePanelDataByMolecularProfileIds(Set molecularProfileIds); + + @Cacheable( + cacheResolver = "staticRepositoryCacheOneResolver", + condition = "@cacheEnabledConfig.getEnabled()") + List fetchGenePanelDataInMultipleMolecularProfiles( + List molecularProfileSampleIdentifiers); + + @Cacheable( + cacheResolver = "staticRepositoryCacheOneResolver", + condition = "@cacheEnabledConfig.getEnabled()") + List fetchGenePanelDataInMultipleMolecularProfilesByPatientIds( + List molecularProfileSampleIdentifiers); + + List fetchGenePanels(List genePanelIds, String projection); +} diff --git a/src/main/java/org/cbioportal/legacy/service/GeneService.java b/src/main/java/org/cbioportal/legacy/service/GeneService.java new file mode 100644 index 00000000000..23a4d11aa87 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/GeneService.java @@ -0,0 +1,32 @@ +package org.cbioportal.legacy.service; + +import java.util.List; +import org.cbioportal.legacy.model.Gene; +import org.cbioportal.legacy.model.meta.BaseMeta; +import org.cbioportal.legacy.service.exception.GeneNotFoundException; +import org.cbioportal.legacy.service.exception.GeneWithMultipleEntrezIdsException; + +public interface GeneService { + + List getAllGenes( + String keyword, + String alias, + String projection, + Integer pageSize, + Integer pageNumber, + String sortBy, + String direction); + + BaseMeta getMetaGenes(String keyword, String alias); + + Gene getGene(String geneId) throws GeneNotFoundException, GeneWithMultipleEntrezIdsException; + + Gene getGeneByGeneticEntityId(Integer geneticEntityId) throws GeneNotFoundException; + + List getAliasesOfGene(String geneId) + throws GeneNotFoundException, GeneWithMultipleEntrezIdsException; + + List fetchGenes(List geneIds, String geneIdType, String projection); + + BaseMeta fetchMetaGenes(List geneIds, String geneIdType); +} diff --git a/src/main/java/org/cbioportal/legacy/service/GenericAssayService.java b/src/main/java/org/cbioportal/legacy/service/GenericAssayService.java new file mode 100644 index 00000000000..77bde2e91ba --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/GenericAssayService.java @@ -0,0 +1,33 @@ +package org.cbioportal.legacy.service; + +import java.util.List; +import org.cbioportal.legacy.model.GenericAssayData; +import org.cbioportal.legacy.model.meta.GenericAssayMeta; +import org.cbioportal.legacy.service.exception.MolecularProfileNotFoundException; + +public interface GenericAssayService { + + List getGenericAssayMetaByStableIdsAndMolecularIds( + List stableIds, List molecularProfileIds, String projection); + + List getGenericAssayData( + String molecularProfileId, + String sampleListId, + List genericAssayStableIds, + String projection) + throws MolecularProfileNotFoundException; + + List fetchGenericAssayData( + String molecularProfileId, + List sampleIds, + List genericAssayStableIds, + String projection) + throws MolecularProfileNotFoundException; + + List fetchGenericAssayData( + List molecularProfileIds, + List sampleIds, + List genericAssayStableIds, + String projection) + throws MolecularProfileNotFoundException; +} diff --git a/src/main/java/org/cbioportal/legacy/service/GenesetCorrelationService.java b/src/main/java/org/cbioportal/legacy/service/GenesetCorrelationService.java new file mode 100644 index 00000000000..a0b307e33ab --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/GenesetCorrelationService.java @@ -0,0 +1,27 @@ +package org.cbioportal.legacy.service; + +import java.util.List; +import org.cbioportal.legacy.model.GenesetCorrelation; +import org.cbioportal.legacy.service.exception.GenesetNotFoundException; +import org.cbioportal.legacy.service.exception.MolecularProfileNotFoundException; +import org.cbioportal.legacy.service.exception.SampleListNotFoundException; + +public interface GenesetCorrelationService { + + List fetchCorrelatedGenes( + String genesetId, String geneticProfileId, double correlationThreshold) + throws MolecularProfileNotFoundException, GenesetNotFoundException; + + List fetchCorrelatedGenes( + String genesetId, + String geneticProfileId, + List sampleIds, + double correlationThreshold) + throws MolecularProfileNotFoundException, GenesetNotFoundException; + + List fetchCorrelatedGenes( + String genesetId, String geneticProfileId, String sampleListId, double correlationThreshold) + throws MolecularProfileNotFoundException, + SampleListNotFoundException, + GenesetNotFoundException; +} diff --git a/src/main/java/org/cbioportal/legacy/service/GenesetDataService.java b/src/main/java/org/cbioportal/legacy/service/GenesetDataService.java new file mode 100644 index 00000000000..965db56067d --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/GenesetDataService.java @@ -0,0 +1,21 @@ +package org.cbioportal.legacy.service; + +import java.util.List; +import org.cbioportal.legacy.model.GenesetMolecularAlteration; +import org.cbioportal.legacy.model.GenesetMolecularData; +import org.cbioportal.legacy.service.exception.MolecularProfileNotFoundException; +import org.cbioportal.legacy.service.exception.SampleListNotFoundException; + +public interface GenesetDataService { + + List fetchGenesetData( + String geneticProfileId, List sampleIds, List genesetIds) + throws MolecularProfileNotFoundException; + + List fetchGenesetData( + String geneticProfileId, String sampleListId, List genesetIds) + throws MolecularProfileNotFoundException, SampleListNotFoundException; + + List getGenesetAlterations( + String molecularProfileId, List genesetIds) throws MolecularProfileNotFoundException; +} diff --git a/src/main/java/org/cbioportal/legacy/service/GenesetHierarchyService.java b/src/main/java/org/cbioportal/legacy/service/GenesetHierarchyService.java new file mode 100644 index 00000000000..bcdb78cd4a5 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/GenesetHierarchyService.java @@ -0,0 +1,29 @@ +package org.cbioportal.legacy.service; + +import java.util.List; +import org.cbioportal.legacy.model.GenesetHierarchyInfo; +import org.cbioportal.legacy.service.exception.MolecularProfileNotFoundException; +import org.cbioportal.legacy.service.exception.SampleListNotFoundException; + +public interface GenesetHierarchyService { + + List fetchGenesetHierarchyInfo( + String geneticProfileId, Integer percentile, Double scoreThreshold, Double pvalueThreshold) + throws MolecularProfileNotFoundException; + + List fetchGenesetHierarchyInfo( + String geneticProfileId, + Integer percentile, + Double scoreThreshold, + Double pvalueThreshold, + List sampleIds) + throws MolecularProfileNotFoundException; + + List fetchGenesetHierarchyInfo( + String geneticProfileId, + Integer percentile, + Double scoreThreshold, + Double pvalueThreshold, + String sampleListId) + throws MolecularProfileNotFoundException, SampleListNotFoundException; +} diff --git a/src/main/java/org/cbioportal/legacy/service/GenesetService.java b/src/main/java/org/cbioportal/legacy/service/GenesetService.java new file mode 100644 index 00000000000..acca22b6c57 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/GenesetService.java @@ -0,0 +1,22 @@ +package org.cbioportal.legacy.service; + +import java.util.List; +import org.cbioportal.legacy.model.Gene; +import org.cbioportal.legacy.model.Geneset; +import org.cbioportal.legacy.model.meta.BaseMeta; +import org.cbioportal.legacy.service.exception.GenesetNotFoundException; + +public interface GenesetService { + + List getAllGenesets(String projection, Integer pageSize, Integer pageNumber); + + BaseMeta getMetaGenesets(); + + Geneset getGeneset(String genesetId) throws GenesetNotFoundException; + + List getGenesByGenesetId(String genesetId) throws GenesetNotFoundException; + + List fetchGenesets(List genesetIds); + + String getGenesetVersion(); +} diff --git a/src/main/java/org/cbioportal/legacy/service/MolecularDataService.java b/src/main/java/org/cbioportal/legacy/service/MolecularDataService.java new file mode 100644 index 00000000000..07da8377736 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/MolecularDataService.java @@ -0,0 +1,54 @@ +package org.cbioportal.legacy.service; + +import java.util.List; +import org.cbioportal.legacy.model.GeneFilterQuery; +import org.cbioportal.legacy.model.GeneMolecularAlteration; +import org.cbioportal.legacy.model.GeneMolecularData; +import org.cbioportal.legacy.model.meta.BaseMeta; +import org.cbioportal.legacy.service.exception.MolecularProfileNotFoundException; + +public interface MolecularDataService { + + List getMolecularData( + String molecularProfileId, + String sampleListId, + List entrezGeneIds, + String projection) + throws MolecularProfileNotFoundException; + + BaseMeta getMetaMolecularData( + String molecularProfileId, String sampleListId, List entrezGeneIds) + throws MolecularProfileNotFoundException; + + List fetchMolecularData( + String molecularProfileId, + List sampleIds, + List entrezGeneIds, + String projection) + throws MolecularProfileNotFoundException; + + BaseMeta fetchMetaMolecularData( + String molecularProfileId, List sampleIds, List entrezGeneIds) + throws MolecularProfileNotFoundException; + + Iterable getMolecularAlterations( + String molecularProfileId, List entrezGeneIds, String projection) + throws MolecularProfileNotFoundException; + + Integer getNumberOfSamplesInMolecularProfile(String molecularProfileId); + + List getMolecularDataInMultipleMolecularProfiles( + List molecularProfileIds, + List sampleIds, + List entrezGeneIds, + String projection); + + List getMolecularDataInMultipleMolecularProfilesByGeneQueries( + List molecularProfileIds, + List sampleIds, + List geneQueries, + String projection); + + BaseMeta getMetaMolecularDataInMultipleMolecularProfiles( + List molecularProfileIds, List sampleIds, List entrezGeneIds); +} diff --git a/src/main/java/org/cbioportal/legacy/service/MolecularProfileService.java b/src/main/java/org/cbioportal/legacy/service/MolecularProfileService.java new file mode 100644 index 00000000000..56099cca470 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/MolecularProfileService.java @@ -0,0 +1,60 @@ +package org.cbioportal.legacy.service; + +import java.util.List; +import java.util.Set; +import org.cbioportal.legacy.model.MolecularProfile; +import org.cbioportal.legacy.model.MolecularProfileCaseIdentifier; +import org.cbioportal.legacy.model.meta.BaseMeta; +import org.cbioportal.legacy.service.exception.MolecularProfileNotFoundException; +import org.cbioportal.legacy.service.exception.StudyNotFoundException; + +public interface MolecularProfileService { + + List getAllMolecularProfiles( + String projection, Integer pageSize, Integer pageNumber, String sortBy, String direction); + + BaseMeta getMetaMolecularProfiles(); + + MolecularProfile getMolecularProfile(String molecularProfileId) + throws MolecularProfileNotFoundException; + + List getMolecularProfiles(Set molecularProfileIds, String projection); + + BaseMeta getMetaMolecularProfiles(Set molecularProfileIds); + + List getAllMolecularProfilesInStudy( + String studyId, + String projection, + Integer pageSize, + Integer pageNumber, + String sortBy, + String direction) + throws StudyNotFoundException; + + BaseMeta getMetaMolecularProfilesInStudy(String studyId) throws StudyNotFoundException; + + List getMolecularProfilesInStudies(List studyIds, String projection); + + BaseMeta getMetaMolecularProfilesInStudies(List studyIds); + + List getMolecularProfilesReferredBy(String referringMolecularProfileId) + throws MolecularProfileNotFoundException; + + List getMolecularProfilesReferringTo(String referredMolecularProfileId) + throws MolecularProfileNotFoundException; + + List getMolecularProfileCaseIdentifiers( + List studyIds, List sampleIds); + + List getFirstMutationProfileCaseIdentifiers( + List studyIds, List sampleIds); + + List getMutationProfileCaseIdentifiers( + List studyIds, List sampleIds); + + List getFirstDiscreteCNAProfileCaseIdentifiers( + List studyIds, List sampleIds); + + List getFirstStructuralVariantProfileCaseIdentifiers( + List studyIds, List sampleIds); +} diff --git a/src/main/java/org/cbioportal/legacy/service/MrnaPercentileService.java b/src/main/java/org/cbioportal/legacy/service/MrnaPercentileService.java new file mode 100644 index 00000000000..5b71d4aa1fb --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/MrnaPercentileService.java @@ -0,0 +1,12 @@ +package org.cbioportal.legacy.service; + +import java.util.List; +import org.cbioportal.legacy.model.MrnaPercentile; +import org.cbioportal.legacy.service.exception.MolecularProfileNotFoundException; + +public interface MrnaPercentileService { + + List fetchMrnaPercentile( + String molecularProfileId, String sampleId, List entrezGeneIds) + throws MolecularProfileNotFoundException; +} diff --git a/src/main/java/org/cbioportal/legacy/service/MutationService.java b/src/main/java/org/cbioportal/legacy/service/MutationService.java new file mode 100644 index 00000000000..494355a5f8b --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/MutationService.java @@ -0,0 +1,76 @@ +package org.cbioportal.legacy.service; + +import java.util.List; +import org.cbioportal.legacy.model.GeneFilterQuery; +import org.cbioportal.legacy.model.GenomicDataCountItem; +import org.cbioportal.legacy.model.Mutation; +import org.cbioportal.legacy.model.MutationCountByPosition; +import org.cbioportal.legacy.model.meta.MutationMeta; +import org.cbioportal.legacy.service.exception.MolecularProfileNotFoundException; + +public interface MutationService { + + List getMutationsInMolecularProfileBySampleListId( + String molecularProfileId, + String sampleListId, + List entrezGeneIds, + boolean snpOnly, + String projection, + Integer pageSize, + Integer pageNumber, + String sortBy, + String direction) + throws MolecularProfileNotFoundException; + + MutationMeta getMetaMutationsInMolecularProfileBySampleListId( + String molecularProfileId, String sampleListId, List entrezGeneIds) + throws MolecularProfileNotFoundException; + + List getMutationsInMultipleMolecularProfiles( + List molecularProfileIds, + List sampleIds, + List entrezGeneIds, + String projection, + Integer pageSize, + Integer pageNumber, + String sortBy, + String direction); + + List getMutationsInMultipleMolecularProfilesByGeneQueries( + List molecularProfileIds, + List sampleIds, + List geneQueries, + String projection, + Integer pageSize, + Integer pageNumber, + String sortBy, + String direction); + + MutationMeta getMetaMutationsInMultipleMolecularProfiles( + List molecularProfileIds, List sampleIds, List entrezGeneIds); + + List fetchMutationsInMolecularProfile( + String molecularProfileId, + List sampleIds, + List entrezGeneIds, + boolean snpOnly, + String projection, + Integer pageSize, + Integer pageNumber, + String sortBy, + String direction) + throws MolecularProfileNotFoundException; + + MutationMeta fetchMetaMutationsInMolecularProfile( + String molecularProfileId, List sampleIds, List entrezGeneIds) + throws MolecularProfileNotFoundException; + + List fetchMutationCountsByPosition( + List entrezGeneIds, List proteinPosStarts, List proteinPosEnds); + + GenomicDataCountItem getMutationCountsByType( + List molecularProfileIds, + List sampleIds, + List entrezGeneIds, + String profileType); +} diff --git a/src/main/java/org/cbioportal/legacy/service/MutationSpectrumService.java b/src/main/java/org/cbioportal/legacy/service/MutationSpectrumService.java new file mode 100644 index 00000000000..9c0bbb94d99 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/MutationSpectrumService.java @@ -0,0 +1,14 @@ +package org.cbioportal.legacy.service; + +import java.util.List; +import org.cbioportal.legacy.model.MutationSpectrum; +import org.cbioportal.legacy.service.exception.MolecularProfileNotFoundException; + +public interface MutationSpectrumService { + + List getMutationSpectrums(String molecularProfileId, String sampleListId) + throws MolecularProfileNotFoundException; + + List fetchMutationSpectrums(String molecularProfileId, List sampleIds) + throws MolecularProfileNotFoundException; +} diff --git a/src/main/java/org/cbioportal/legacy/service/NamespaceAttributeService.java b/src/main/java/org/cbioportal/legacy/service/NamespaceAttributeService.java new file mode 100644 index 00000000000..b7ca8b30565 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/NamespaceAttributeService.java @@ -0,0 +1,13 @@ +package org.cbioportal.legacy.service; + +import java.util.List; +import org.cbioportal.legacy.model.NamespaceAttribute; +import org.cbioportal.legacy.model.NamespaceAttributeCount; + +public interface NamespaceAttributeService { + + List fetchNamespaceAttributes(List studyIds); + + List fetchNamespaceAttributeCountsBySampleIds( + List studyIds, List sampleIds, List namespaceAttributes); +} diff --git a/src/main/java/org/cbioportal/legacy/service/NamespaceDataService.java b/src/main/java/org/cbioportal/legacy/service/NamespaceDataService.java new file mode 100644 index 00000000000..33d6cfa2468 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/NamespaceDataService.java @@ -0,0 +1,24 @@ +package org.cbioportal.legacy.service; + +import java.util.List; +import org.cbioportal.legacy.model.NamespaceAttribute; +import org.cbioportal.legacy.model.NamespaceData; +import org.cbioportal.legacy.model.NamespaceDataCountItem; +import org.cbioportal.legacy.web.parameter.NamespaceDataFilter; + +public interface NamespaceDataService { + + List fetchNamespaceData( + List studyIds, + List sampleIds, + List namespaceDataFilters); + + List fetchNamespaceDataForComparison( + List studyIds, + List sampleIds, + NamespaceAttribute namespaceAttribute, + List values); + + List fetchNamespaceDataCounts( + List studyIds, List sampleIds, List namespaceAttributes); +} diff --git a/src/main/java/org/cbioportal/legacy/service/PatientService.java b/src/main/java/org/cbioportal/legacy/service/PatientService.java new file mode 100644 index 00000000000..fe1ad88b7ab --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/PatientService.java @@ -0,0 +1,40 @@ +package org.cbioportal.legacy.service; + +import java.util.List; +import org.cbioportal.legacy.model.Patient; +import org.cbioportal.legacy.model.meta.BaseMeta; +import org.cbioportal.legacy.service.exception.PatientNotFoundException; +import org.cbioportal.legacy.service.exception.StudyNotFoundException; + +public interface PatientService { + + List getAllPatients( + String keyword, + String projection, + Integer pageSize, + Integer pageNumber, + String sortBy, + String direction); + + BaseMeta getMetaPatients(String keyword); + + List getAllPatientsInStudy( + String studyId, + String projection, + Integer pageSize, + Integer pageNumber, + String sortBy, + String direction) + throws StudyNotFoundException; + + BaseMeta getMetaPatientsInStudy(String studyId) throws StudyNotFoundException; + + Patient getPatientInStudy(String studyId, String patientId) + throws PatientNotFoundException, StudyNotFoundException; + + List fetchPatients(List studyIds, List patientIds, String projection); + + BaseMeta fetchMetaPatients(List studyIds, List patientIds); + + List getPatientsOfSamples(List studyIds, List sampleIds); +} diff --git a/src/main/java/org/cbioportal/legacy/service/ReadPermissionService.java b/src/main/java/org/cbioportal/legacy/service/ReadPermissionService.java new file mode 100644 index 00000000000..0cf39cd703d --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/ReadPermissionService.java @@ -0,0 +1,10 @@ +package org.cbioportal.legacy.service; + +import java.util.Collection; +import org.cbioportal.legacy.model.ReadPermission; +import org.springframework.security.core.Authentication; + +public interface ReadPermissionService { + public void setReadPermission( + Collection entities, Authentication authentication); +} diff --git a/src/main/java/org/cbioportal/legacy/service/ReferenceGenomeGeneService.java b/src/main/java/org/cbioportal/legacy/service/ReferenceGenomeGeneService.java new file mode 100644 index 00000000000..ffb6ac82d69 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/ReferenceGenomeGeneService.java @@ -0,0 +1,17 @@ +package org.cbioportal.legacy.service; + +import java.util.List; +import org.cbioportal.legacy.model.ReferenceGenomeGene; + +public interface ReferenceGenomeGeneService { + List fetchAllReferenceGenomeGenes(String genomeName); + + List fetchGenesByGenomeName(List geneIds, String genomeName); + + List fetchGenesByHugoGeneSymbolsAndGenomeName( + List geneIds, String genomeName); + + ReferenceGenomeGene getReferenceGenomeGene(Integer geneID, String genomeName); + + ReferenceGenomeGene getReferenceGenomeGeneByEntityId(Integer entityId, String genomeName); +} diff --git a/src/main/java/org/cbioportal/legacy/service/ResourceDataService.java b/src/main/java/org/cbioportal/legacy/service/ResourceDataService.java new file mode 100644 index 00000000000..a74f8d2c5d5 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/ResourceDataService.java @@ -0,0 +1,52 @@ +package org.cbioportal.legacy.service; + +import java.util.List; +import org.cbioportal.legacy.model.ResourceData; +import org.cbioportal.legacy.service.exception.PatientNotFoundException; +import org.cbioportal.legacy.service.exception.SampleNotFoundException; +import org.cbioportal.legacy.service.exception.StudyNotFoundException; + +public interface ResourceDataService { + + List getAllResourceDataOfSampleInStudy( + String studyId, + String sampleId, + String resourceId, + String projection, + Integer pageSize, + Integer pageNumber, + String sortBy, + String direction) + throws SampleNotFoundException, StudyNotFoundException; + + List getAllResourceDataOfPatientInStudy( + String studyId, + String patientId, + String resourceId, + String projection, + Integer pageSize, + Integer pageNumber, + String sortBy, + String direction) + throws PatientNotFoundException, StudyNotFoundException; + + List getAllResourceDataForStudy( + String studyId, + String resourceId, + String projection, + Integer pageSize, + Integer pageNumber, + String sortBy, + String direction) + throws StudyNotFoundException; + + List getAllResourceDataForStudyPatientSample( + String studyId, + String resourceId, + String projection, + Integer pageSize, + Integer pageNumber, + String sortBy, + String direction) + throws StudyNotFoundException; +} diff --git a/src/main/java/org/cbioportal/legacy/service/ResourceDefinitionService.java b/src/main/java/org/cbioportal/legacy/service/ResourceDefinitionService.java new file mode 100644 index 00000000000..cfe9530b856 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/ResourceDefinitionService.java @@ -0,0 +1,24 @@ +package org.cbioportal.legacy.service; + +import java.util.List; +import org.cbioportal.legacy.model.ResourceDefinition; +import org.cbioportal.legacy.service.exception.ResourceDefinitionNotFoundException; +import org.cbioportal.legacy.service.exception.StudyNotFoundException; + +public interface ResourceDefinitionService { + + ResourceDefinition getResourceDefinition(String studyId, String resourceId) + throws ResourceDefinitionNotFoundException, StudyNotFoundException; + + List getAllResourceDefinitionsInStudy( + String studyId, + String projection, + Integer pageSize, + Integer pageNumber, + String sortBy, + String direction) + throws StudyNotFoundException; + + List fetchResourceDefinitions(List studyIds, String projection) + throws StudyNotFoundException; +} diff --git a/src/main/java/org/cbioportal/legacy/service/SampleListService.java b/src/main/java/org/cbioportal/legacy/service/SampleListService.java new file mode 100644 index 00000000000..5eb055e4984 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/SampleListService.java @@ -0,0 +1,34 @@ +package org.cbioportal.legacy.service; + +import java.util.List; +import org.cbioportal.legacy.model.SampleList; +import org.cbioportal.legacy.model.meta.BaseMeta; +import org.cbioportal.legacy.service.exception.SampleListNotFoundException; +import org.cbioportal.legacy.service.exception.StudyNotFoundException; + +public interface SampleListService { + + List getAllSampleLists( + String projection, Integer pageSize, Integer pageNumber, String sortBy, String direction); + + BaseMeta getMetaSampleLists(); + + SampleList getSampleList(String sampleListId) throws SampleListNotFoundException; + + List getAllSampleListsInStudy( + String studyId, + String projection, + Integer pageSize, + Integer pageNumber, + String sortBy, + String direction) + throws StudyNotFoundException; + + BaseMeta getMetaSampleListsInStudy(String studyId) throws StudyNotFoundException; + + List getAllSampleIdsInSampleList(String sampleListId) throws SampleListNotFoundException; + + List fetchSampleLists(List sampleListIds, String projection); + + List getAllSampleListsInStudies(List studyIds, String projection); +} diff --git a/src/main/java/org/cbioportal/legacy/service/SampleService.java b/src/main/java/org/cbioportal/legacy/service/SampleService.java new file mode 100644 index 00000000000..ba5f2c40655 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/SampleService.java @@ -0,0 +1,73 @@ +package org.cbioportal.legacy.service; + +import java.util.List; +import org.cbioportal.legacy.model.Sample; +import org.cbioportal.legacy.model.meta.BaseMeta; +import org.cbioportal.legacy.service.exception.PatientNotFoundException; +import org.cbioportal.legacy.service.exception.SampleNotFoundException; +import org.cbioportal.legacy.service.exception.StudyNotFoundException; + +public interface SampleService { + + List getAllSamplesInStudy( + String studyId, + String projection, + Integer pageSize, + Integer pageNumber, + String sortBy, + String direction) + throws StudyNotFoundException; + + BaseMeta getMetaSamplesInStudy(String studyId) throws StudyNotFoundException; + + List getAllSamplesInStudies( + List studyIds, + String projection, + Integer pageSize, + Integer pageNumber, + String sortBy, + String direction); + + Sample getSampleInStudy(String studyId, String sampleId) + throws SampleNotFoundException, StudyNotFoundException; + + List getAllSamplesOfPatientInStudy( + String studyId, + String patientId, + String projection, + Integer pageSize, + Integer pageNumber, + String sortBy, + String direction) + throws StudyNotFoundException, PatientNotFoundException; + + BaseMeta getMetaSamplesOfPatientInStudy(String studyId, String patientId) + throws StudyNotFoundException, PatientNotFoundException; + + List getAllSamplesOfPatientsInStudy( + String studyId, List patientIds, String projection); + + List getSamplesOfPatientsInMultipleStudies( + List studyIds, List patientIds, String projection); + + List fetchSamples(List studyIds, List sampleIds, String projection); + + List fetchSamples(List sampleListIds, String projection); + + BaseMeta fetchMetaSamples(List studyIds, List sampleIds); + + BaseMeta fetchMetaSamples(List sampleListIds); + + List getSamplesByInternalIds(List internalIds); + + List getAllSamples( + String keyword, + List studyIds, + String projection, + Integer pageSize, + Integer pageNumber, + String sort, + String direction); + + BaseMeta getMetaSamples(String keyword, List studyIds); +} diff --git a/src/main/java/org/cbioportal/legacy/service/ServerStatusService.java b/src/main/java/org/cbioportal/legacy/service/ServerStatusService.java new file mode 100644 index 00000000000..6864e56bad5 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/ServerStatusService.java @@ -0,0 +1,7 @@ +package org.cbioportal.legacy.service; + +import org.cbioportal.legacy.service.impl.ServerStatusServiceImpl.ServerStatusMessage; + +public interface ServerStatusService { + ServerStatusMessage getServerStatus(); +} diff --git a/src/main/java/org/cbioportal/legacy/service/SignificantCopyNumberRegionService.java b/src/main/java/org/cbioportal/legacy/service/SignificantCopyNumberRegionService.java new file mode 100644 index 00000000000..1e0700ab28a --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/SignificantCopyNumberRegionService.java @@ -0,0 +1,20 @@ +package org.cbioportal.legacy.service; + +import java.util.List; +import org.cbioportal.legacy.model.Gistic; +import org.cbioportal.legacy.model.meta.BaseMeta; +import org.cbioportal.legacy.service.exception.StudyNotFoundException; + +public interface SignificantCopyNumberRegionService { + + List getSignificantCopyNumberRegions( + String studyId, + String projection, + Integer pageSize, + Integer pageNumber, + String sortBy, + String direction) + throws StudyNotFoundException; + + BaseMeta getMetaSignificantCopyNumberRegions(String studyId) throws StudyNotFoundException; +} diff --git a/src/main/java/org/cbioportal/legacy/service/SignificantlyMutatedGeneService.java b/src/main/java/org/cbioportal/legacy/service/SignificantlyMutatedGeneService.java new file mode 100644 index 00000000000..47333d6a86e --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/SignificantlyMutatedGeneService.java @@ -0,0 +1,20 @@ +package org.cbioportal.legacy.service; + +import java.util.List; +import org.cbioportal.legacy.model.MutSig; +import org.cbioportal.legacy.model.meta.BaseMeta; +import org.cbioportal.legacy.service.exception.StudyNotFoundException; + +public interface SignificantlyMutatedGeneService { + + List getSignificantlyMutatedGenes( + String studyId, + String projection, + Integer pageSize, + Integer pageNumber, + String sortBy, + String direction) + throws StudyNotFoundException; + + BaseMeta getMetaSignificantlyMutatedGenes(String studyId) throws StudyNotFoundException; +} diff --git a/src/main/java/org/cbioportal/legacy/service/StaticDataTimestampService.java b/src/main/java/org/cbioportal/legacy/service/StaticDataTimestampService.java new file mode 100644 index 00000000000..e131bc6c682 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/StaticDataTimestampService.java @@ -0,0 +1,11 @@ +package org.cbioportal.legacy.service; + +import java.util.Date; +import java.util.List; +import java.util.Map; + +public interface StaticDataTimestampService { + Map getTimestamps(List tables); + + Map getTimestampsAsDates(List tables); +} diff --git a/src/main/java/org/cbioportal/legacy/service/StructuralVariantService.java b/src/main/java/org/cbioportal/legacy/service/StructuralVariantService.java new file mode 100644 index 00000000000..ba2af8408ae --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/StructuralVariantService.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2018 The Hyve B.V. + * This code is licensed under the GNU Affero General Public License (AGPL), + * version 3, or (at your option) any later version. + */ + +/* + * This file is part of cBioPortal. + * + * cBioPortal is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package org.cbioportal.legacy.service; + +import java.util.List; +import org.cbioportal.legacy.model.GeneFilterQuery; +import org.cbioportal.legacy.model.StructuralVariant; +import org.cbioportal.legacy.model.StructuralVariantFilterQuery; +import org.cbioportal.legacy.model.StructuralVariantQuery; + +public interface StructuralVariantService { + + List fetchStructuralVariants( + List molecularProfileIds, + List sampleIds, + List entrezGeneIds, + List structuralVariantQueries); + + List fetchStructuralVariantsByGeneQueries( + List molecularProfileIds, List sampleIds, List geneQueries); + + List fetchStructuralVariantsByStructVarQueries( + List molecularProfileIds, + List sampleIds, + List structVarQueries); +} diff --git a/src/main/java/org/cbioportal/legacy/service/StudyService.java b/src/main/java/org/cbioportal/legacy/service/StudyService.java new file mode 100644 index 00000000000..fc17d950765 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/StudyService.java @@ -0,0 +1,34 @@ +package org.cbioportal.legacy.service; + +import java.util.List; +import org.cbioportal.legacy.model.CancerStudy; +import org.cbioportal.legacy.model.CancerStudyTags; +import org.cbioportal.legacy.model.meta.BaseMeta; +import org.cbioportal.legacy.service.exception.StudyNotFoundException; +import org.cbioportal.legacy.utils.security.AccessLevel; +import org.springframework.security.core.Authentication; + +public interface StudyService { + + List getAllStudies( + String keyword, + String projection, + Integer pageSize, + Integer pageNumber, + String sortBy, + String direction, + Authentication authentication, + AccessLevel accessLevel); + + BaseMeta getMetaStudies(String keyword); + + CancerStudy getStudy(String studyId) throws StudyNotFoundException; + + List fetchStudies(List studyIds, String projection); + + BaseMeta fetchMetaStudies(List studyIds); + + CancerStudyTags getTags(String studyId, AccessLevel accessLevel); + + List getTagsForMultipleStudies(List studyIds); +} diff --git a/src/main/java/org/cbioportal/legacy/service/StudyViewColumnarService.java b/src/main/java/org/cbioportal/legacy/service/StudyViewColumnarService.java new file mode 100644 index 00000000000..6d19be865f6 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/StudyViewColumnarService.java @@ -0,0 +1,81 @@ +package org.cbioportal.legacy.service; + +import java.util.List; +import java.util.Map; +import org.cbioportal.legacy.model.AlterationCountByGene; +import org.cbioportal.legacy.model.CaseListDataCount; +import org.cbioportal.legacy.model.ClinicalData; +import org.cbioportal.legacy.model.ClinicalDataCountItem; +import org.cbioportal.legacy.model.ClinicalEventTypeCount; +import org.cbioportal.legacy.model.CopyNumberCountByGene; +import org.cbioportal.legacy.model.GenericAssayDataCountItem; +import org.cbioportal.legacy.model.GenomicDataCount; +import org.cbioportal.legacy.model.GenomicDataCountItem; +import org.cbioportal.legacy.model.PatientTreatmentReport; +import org.cbioportal.legacy.model.Sample; +import org.cbioportal.legacy.model.SampleTreatmentReport; +import org.cbioportal.legacy.service.exception.StudyNotFoundException; +import org.cbioportal.legacy.web.parameter.ClinicalDataType; +import org.cbioportal.legacy.web.parameter.GenericAssayDataBinFilter; +import org.cbioportal.legacy.web.parameter.GenericAssayDataFilter; +import org.cbioportal.legacy.web.parameter.GenomicDataBinFilter; +import org.cbioportal.legacy.web.parameter.GenomicDataFilter; +import org.cbioportal.legacy.web.parameter.StudyViewFilter; + +public interface StudyViewColumnarService { + + List getFilteredSamples(StudyViewFilter studyViewFilter); + + List getMutatedGenes(StudyViewFilter interceptedStudyViewFilter) + throws StudyNotFoundException; + + List getCnaGenes(StudyViewFilter interceptedStudyViewFilter) + throws StudyNotFoundException; + + List getStructuralVariantGenes(StudyViewFilter studyViewFilter) + throws StudyNotFoundException; + + Map getClinicalAttributeDatatypeMap(StudyViewFilter studyViewFilter); + + List getClinicalDataCounts( + StudyViewFilter studyViewFilter, List filteredAttributes); + + List getCaseListDataCounts(StudyViewFilter studyViewFilter); + + List getPatientClinicalData( + StudyViewFilter studyViewFilter, List attributeIds); + + List getSampleClinicalData( + StudyViewFilter studyViewFilter, List attributeIds); + + List getMolecularProfileSampleCounts(StudyViewFilter studyViewFilter); + + List getClinicalEventTypeCounts(StudyViewFilter studyViewFilter); + + PatientTreatmentReport getPatientTreatmentReport(StudyViewFilter studyViewFilter); + + SampleTreatmentReport getSampleTreatmentReport(StudyViewFilter studyViewFilter); + + List getCNACountsByGeneSpecific( + StudyViewFilter studyViewFilter, List genomicDataFilters); + + List getGenericAssayDataCounts( + StudyViewFilter studyViewFilter, List genericAssayDataFilters); + + List getMutationCountsByGeneSpecific( + StudyViewFilter studyViewFilter, List genomicDataFilters); + + List getGenomicDataBinCounts( + StudyViewFilter studyViewFilter, List genomicDataBinFilters); + + List getGenericAssayDataBinCounts( + StudyViewFilter studyViewFilter, List genericAssayDataBinFilters); + + List getMutationTypeCountsByGeneSpecific( + StudyViewFilter studyViewFilter, List genomicDataFilters); + + List fetchClinicalDataForXyPlot( + StudyViewFilter studyViewFilter, + List attributeIds, + boolean shouldFilterNonEmptyClinicalData); +} diff --git a/src/main/java/org/cbioportal/legacy/service/StudyViewService.java b/src/main/java/org/cbioportal/legacy/service/StudyViewService.java new file mode 100644 index 00000000000..a3088c4176f --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/StudyViewService.java @@ -0,0 +1,54 @@ +package org.cbioportal.legacy.service; + +import java.util.List; +import org.apache.commons.math3.util.Pair; +import org.cbioportal.legacy.model.AlterationCountByGene; +import org.cbioportal.legacy.model.AlterationCountByStructuralVariant; +import org.cbioportal.legacy.model.AlterationFilter; +import org.cbioportal.legacy.model.CopyNumberCountByGene; +import org.cbioportal.legacy.model.GenericAssayDataCountItem; +import org.cbioportal.legacy.model.GenomicDataCount; +import org.cbioportal.legacy.model.GenomicDataCountItem; +import org.cbioportal.legacy.model.NamespaceAttribute; +import org.cbioportal.legacy.model.NamespaceDataCountItem; +import org.cbioportal.legacy.service.exception.StudyNotFoundException; + +public interface StudyViewService { + List getGenomicDataCounts(List studyIds, List sampleIds); + + List getMutationAlterationCountByGenes( + List studyIds, List sampleIds, AlterationFilter annotationFilter) + throws StudyNotFoundException; + + List getMutationCountsByGeneSpecific( + List studyIds, + List sampleIds, + List> genomicDataFilters, + AlterationFilter annotationFilter); + + List getMutationTypeCountsByGeneSpecific( + List studyIds, List sampleIds, List> genomicDataFilters); + + List getStructuralVariantAlterationCountByGenes( + List studyIds, List sampleIds, AlterationFilter annotationFilter) + throws StudyNotFoundException; + + List getStructuralVariantAlterationCounts( + List studyIds, List sampleIds, AlterationFilter annotationFilters); + + List getCNAAlterationCountByGenes( + List studyIds, List sampleIds, AlterationFilter annotationFilter) + throws StudyNotFoundException; + + List getCNAAlterationCountsByGeneSpecific( + List studyIds, List sampleIds, List> genomicDataFilters); + + List fetchGenericAssayDataCounts( + List sampleIds, + List studyIds, + List stableIds, + List profileTypes); + + List fetchNamespaceDataCounts( + List studyIds, List sampleIds, List namespaceAttributes); +} diff --git a/src/main/java/org/cbioportal/legacy/service/TreatmentService.java b/src/main/java/org/cbioportal/legacy/service/TreatmentService.java new file mode 100644 index 00000000000..6dd8fab750a --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/TreatmentService.java @@ -0,0 +1,18 @@ +package org.cbioportal.legacy.service; + +import java.util.List; +import org.cbioportal.legacy.model.ClinicalEventKeyCode; +import org.cbioportal.legacy.model.PatientTreatmentRow; +import org.cbioportal.legacy.model.SampleTreatmentRow; + +public interface TreatmentService { + public List getAllSampleTreatmentRows( + List samples, List studies, ClinicalEventKeyCode key); + + public List getAllPatientTreatmentRows( + List samples, List studies, ClinicalEventKeyCode key); + + public Boolean containsTreatmentData(List studies, ClinicalEventKeyCode tier); + + public Boolean containsSampleTreatmentData(List studyIds, ClinicalEventKeyCode tier); +} diff --git a/src/main/java/org/cbioportal/legacy/service/VariantCountService.java b/src/main/java/org/cbioportal/legacy/service/VariantCountService.java new file mode 100644 index 00000000000..c235071c84a --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/VariantCountService.java @@ -0,0 +1,12 @@ +package org.cbioportal.legacy.service; + +import java.util.List; +import org.cbioportal.legacy.model.VariantCount; +import org.cbioportal.legacy.service.exception.MolecularProfileNotFoundException; + +public interface VariantCountService { + + List fetchVariantCounts( + String molecularProfileId, List entrezGeneIds, List keywords) + throws MolecularProfileNotFoundException; +} diff --git a/src/main/java/org/cbioportal/legacy/service/ViolinPlotService.java b/src/main/java/org/cbioportal/legacy/service/ViolinPlotService.java new file mode 100644 index 00000000000..b5757174802 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/ViolinPlotService.java @@ -0,0 +1,20 @@ +package org.cbioportal.legacy.service; + +import java.math.BigDecimal; +import java.util.List; +import java.util.Set; +import org.cbioportal.legacy.model.ClinicalData; +import org.cbioportal.legacy.model.ClinicalViolinPlotData; +import org.cbioportal.legacy.web.parameter.StudyViewFilter; + +public interface ViolinPlotService { + ClinicalViolinPlotData getClinicalViolinPlotData( + List sampleClinicalDataForViolinPlot, + Set samplesForSampleCountsIds, + BigDecimal axisStart, + BigDecimal axisEnd, + BigDecimal numCurvePoints, + Boolean useLogScale, + BigDecimal sigmaMultiplier, + StudyViewFilter studyViewFilter); +} diff --git a/src/main/java/org/cbioportal/legacy/service/exception/AccessForbiddenException.java b/src/main/java/org/cbioportal/legacy/service/exception/AccessForbiddenException.java new file mode 100644 index 00000000000..7cfa97cdebb --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/exception/AccessForbiddenException.java @@ -0,0 +1,7 @@ +package org.cbioportal.legacy.service.exception; + +public class AccessForbiddenException extends RuntimeException { + public AccessForbiddenException(String message) { + super(message); + } +} diff --git a/src/main/java/org/cbioportal/legacy/service/exception/CacheNotFoundException.java b/src/main/java/org/cbioportal/legacy/service/exception/CacheNotFoundException.java new file mode 100644 index 00000000000..4e64eba6191 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/exception/CacheNotFoundException.java @@ -0,0 +1,19 @@ +package org.cbioportal.legacy.service.exception; + +public class CacheNotFoundException extends Exception { + + private String cacheName; + + public CacheNotFoundException(String cacheName) { + super("No cache found with name " + cacheName); + this.cacheName = cacheName; + } + + public String getCacheName() { + return cacheName; + } + + public void setCacheName(String cacheName) { + this.cacheName = cacheName; + } +} diff --git a/src/main/java/org/cbioportal/legacy/service/exception/CacheOperationException.java b/src/main/java/org/cbioportal/legacy/service/exception/CacheOperationException.java new file mode 100644 index 00000000000..4eced584bfd --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/exception/CacheOperationException.java @@ -0,0 +1,7 @@ +package org.cbioportal.legacy.service.exception; + +public class CacheOperationException extends Exception { + public CacheOperationException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/src/main/java/org/cbioportal/legacy/service/exception/CancerTypeNotFoundException.java b/src/main/java/org/cbioportal/legacy/service/exception/CancerTypeNotFoundException.java new file mode 100644 index 00000000000..0e12ef34f66 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/exception/CancerTypeNotFoundException.java @@ -0,0 +1,19 @@ +package org.cbioportal.legacy.service.exception; + +public class CancerTypeNotFoundException extends Exception { + + private String cancerTypeId; + + public CancerTypeNotFoundException(String cancerTypeId) { + super(); + this.cancerTypeId = cancerTypeId; + } + + public String getCancerTypeId() { + return cancerTypeId; + } + + public void setCancerTypeId(String cancerTypeId) { + this.cancerTypeId = cancerTypeId; + } +} diff --git a/src/main/java/org/cbioportal/legacy/service/exception/ClinicalAttributeNotFoundException.java b/src/main/java/org/cbioportal/legacy/service/exception/ClinicalAttributeNotFoundException.java new file mode 100644 index 00000000000..2bda4c35a6d --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/exception/ClinicalAttributeNotFoundException.java @@ -0,0 +1,29 @@ +package org.cbioportal.legacy.service.exception; + +public class ClinicalAttributeNotFoundException extends Exception { + + private String studyId; + private String clinicalAttributeId; + + public ClinicalAttributeNotFoundException(String studyId, String clinicalAttributeId) { + super(); + this.studyId = studyId; + this.clinicalAttributeId = clinicalAttributeId; + } + + public String getStudyId() { + return studyId; + } + + public void setStudyId(String studyId) { + this.studyId = studyId; + } + + public String getClinicalAttributeId() { + return clinicalAttributeId; + } + + public void setClinicalAttributeId(String clinicalAttributeId) { + this.clinicalAttributeId = clinicalAttributeId; + } +} diff --git a/src/main/java/org/cbioportal/service/exception/DataAccessTokenNoUserIdentityException.java b/src/main/java/org/cbioportal/legacy/service/exception/DataAccessTokenNoUserIdentityException.java similarity index 90% rename from src/main/java/org/cbioportal/service/exception/DataAccessTokenNoUserIdentityException.java rename to src/main/java/org/cbioportal/legacy/service/exception/DataAccessTokenNoUserIdentityException.java index e698c562792..b1d4ac000e8 100644 --- a/src/main/java/org/cbioportal/service/exception/DataAccessTokenNoUserIdentityException.java +++ b/src/main/java/org/cbioportal/legacy/service/exception/DataAccessTokenNoUserIdentityException.java @@ -44,18 +44,17 @@ * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . -*/ + */ -package org.cbioportal.service.exception; +package org.cbioportal.legacy.service.exception; public class DataAccessTokenNoUserIdentityException extends RuntimeException { - public DataAccessTokenNoUserIdentityException() { - super(); - } - - public DataAccessTokenNoUserIdentityException(String message) { - super(message); - } + public DataAccessTokenNoUserIdentityException() { + super(); + } + public DataAccessTokenNoUserIdentityException(String message) { + super(message); + } } diff --git a/src/main/java/org/cbioportal/service/exception/DataAccessTokenProhibitedUserException.java b/src/main/java/org/cbioportal/legacy/service/exception/DataAccessTokenProhibitedUserException.java similarity index 90% rename from src/main/java/org/cbioportal/service/exception/DataAccessTokenProhibitedUserException.java rename to src/main/java/org/cbioportal/legacy/service/exception/DataAccessTokenProhibitedUserException.java index 6ed9a7ac6dc..099a79c0fb3 100644 --- a/src/main/java/org/cbioportal/service/exception/DataAccessTokenProhibitedUserException.java +++ b/src/main/java/org/cbioportal/legacy/service/exception/DataAccessTokenProhibitedUserException.java @@ -44,18 +44,17 @@ * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . -*/ + */ -package org.cbioportal.service.exception; +package org.cbioportal.legacy.service.exception; public class DataAccessTokenProhibitedUserException extends RuntimeException { - public DataAccessTokenProhibitedUserException() { - super(); - } - - public DataAccessTokenProhibitedUserException(String message) { - super(message); - } + public DataAccessTokenProhibitedUserException() { + super(); + } + public DataAccessTokenProhibitedUserException(String message) { + super(message); + } } diff --git a/src/main/java/org/cbioportal/legacy/service/exception/GeneNotFoundException.java b/src/main/java/org/cbioportal/legacy/service/exception/GeneNotFoundException.java new file mode 100644 index 00000000000..22a8b1a7926 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/exception/GeneNotFoundException.java @@ -0,0 +1,19 @@ +package org.cbioportal.legacy.service.exception; + +public class GeneNotFoundException extends Exception { + + private String geneId; + + public GeneNotFoundException(String geneId) { + super(); + this.geneId = geneId; + } + + public String getGeneId() { + return geneId; + } + + public void setGeneId(String geneId) { + this.geneId = geneId; + } +} diff --git a/src/main/java/org/cbioportal/legacy/service/exception/GenePanelNotFoundException.java b/src/main/java/org/cbioportal/legacy/service/exception/GenePanelNotFoundException.java new file mode 100644 index 00000000000..eed2693071e --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/exception/GenePanelNotFoundException.java @@ -0,0 +1,19 @@ +package org.cbioportal.legacy.service.exception; + +public class GenePanelNotFoundException extends Exception { + + private String genePanelId; + + public GenePanelNotFoundException(String genePanelId) { + super(); + this.genePanelId = genePanelId; + } + + public String getGenePanelId() { + return genePanelId; + } + + public void setGenePanelId(String genePanelId) { + this.genePanelId = genePanelId; + } +} diff --git a/src/main/java/org/cbioportal/legacy/service/exception/GeneWithMultipleEntrezIdsException.java b/src/main/java/org/cbioportal/legacy/service/exception/GeneWithMultipleEntrezIdsException.java new file mode 100644 index 00000000000..9664eee4018 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/exception/GeneWithMultipleEntrezIdsException.java @@ -0,0 +1,20 @@ +package org.cbioportal.legacy.service.exception; + +// TODO: this class should be removed once the issue is resolved database +public class GeneWithMultipleEntrezIdsException extends Exception { + + private String geneId; + + public GeneWithMultipleEntrezIdsException(String geneId) { + super(); + this.geneId = geneId; + } + + public String getGeneId() { + return geneId; + } + + public void setGeneId(String geneId) { + this.geneId = geneId; + } +} diff --git a/src/main/java/org/cbioportal/legacy/service/exception/GenericAssayNotFoundException.java b/src/main/java/org/cbioportal/legacy/service/exception/GenericAssayNotFoundException.java new file mode 100644 index 00000000000..af850bdbd33 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/exception/GenericAssayNotFoundException.java @@ -0,0 +1,25 @@ +package org.cbioportal.legacy.service.exception; + +public class GenericAssayNotFoundException extends Exception { + + private String stableId; + + public GenericAssayNotFoundException(String stableId) { + super(); + this.setStableId(stableId); + } + + /** + * @return the stableId + */ + public String getStableId() { + return stableId; + } + + /** + * @param stableId the stableId to set + */ + public void setStableId(String stableId) { + this.stableId = stableId; + } +} diff --git a/src/main/java/org/cbioportal/legacy/service/exception/GenesetNotFoundException.java b/src/main/java/org/cbioportal/legacy/service/exception/GenesetNotFoundException.java new file mode 100644 index 00000000000..cd4808f6fac --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/exception/GenesetNotFoundException.java @@ -0,0 +1,19 @@ +package org.cbioportal.legacy.service.exception; + +public class GenesetNotFoundException extends Exception { + + private String genesetId; + + public GenesetNotFoundException(String genesetId) { + super(); + this.genesetId = genesetId; + } + + public String getGenesetId() { + return genesetId; + } + + public void setGenesetId(String genesetId) { + this.genesetId = genesetId; + } +} diff --git a/src/main/java/org/cbioportal/service/exception/InvalidDataAccessTokenException.java b/src/main/java/org/cbioportal/legacy/service/exception/InvalidDataAccessTokenException.java similarity index 91% rename from src/main/java/org/cbioportal/service/exception/InvalidDataAccessTokenException.java rename to src/main/java/org/cbioportal/legacy/service/exception/InvalidDataAccessTokenException.java index d158d258a7c..64ff5eef703 100644 --- a/src/main/java/org/cbioportal/service/exception/InvalidDataAccessTokenException.java +++ b/src/main/java/org/cbioportal/legacy/service/exception/InvalidDataAccessTokenException.java @@ -44,19 +44,18 @@ * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . -*/ + */ // TODO move back package org.cbioportal.security.exception; -package org.cbioportal.service.exception; +package org.cbioportal.legacy.service.exception; public class InvalidDataAccessTokenException extends Exception { - public InvalidDataAccessTokenException() { - super(); - } - - public InvalidDataAccessTokenException(String message) { - super(message); - } + public InvalidDataAccessTokenException() { + super(); + } + public InvalidDataAccessTokenException(String message) { + super(message); + } } diff --git a/src/main/java/org/cbioportal/legacy/service/exception/MolecularProfileNotFoundException.java b/src/main/java/org/cbioportal/legacy/service/exception/MolecularProfileNotFoundException.java new file mode 100644 index 00000000000..418776a3fc3 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/exception/MolecularProfileNotFoundException.java @@ -0,0 +1,19 @@ +package org.cbioportal.legacy.service.exception; + +public class MolecularProfileNotFoundException extends Exception { + + private String molecularProfileId; + + public MolecularProfileNotFoundException(String molecularProfileId) { + super(); + this.molecularProfileId = molecularProfileId; + } + + public String getMolecularProfileId() { + return molecularProfileId; + } + + public void setMolecularProfileId(String molecularProfileId) { + this.molecularProfileId = molecularProfileId; + } +} diff --git a/src/main/java/org/cbioportal/legacy/service/exception/PatientNotFoundException.java b/src/main/java/org/cbioportal/legacy/service/exception/PatientNotFoundException.java new file mode 100644 index 00000000000..888334a6f8f --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/exception/PatientNotFoundException.java @@ -0,0 +1,29 @@ +package org.cbioportal.legacy.service.exception; + +public class PatientNotFoundException extends Exception { + + private String studyId; + private String patientId; + + public PatientNotFoundException(String studyId, String patientId) { + super(); + this.studyId = studyId; + this.patientId = patientId; + } + + public String getStudyId() { + return studyId; + } + + public void setStudyId(String studyId) { + this.studyId = studyId; + } + + public String getPatientId() { + return patientId; + } + + public void setPatientId(String patientId) { + this.patientId = patientId; + } +} diff --git a/src/main/java/org/cbioportal/legacy/service/exception/ResourceDefinitionNotFoundException.java b/src/main/java/org/cbioportal/legacy/service/exception/ResourceDefinitionNotFoundException.java new file mode 100644 index 00000000000..f129c04773e --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/exception/ResourceDefinitionNotFoundException.java @@ -0,0 +1,29 @@ +package org.cbioportal.legacy.service.exception; + +public class ResourceDefinitionNotFoundException extends Exception { + + private String studyId; + private String resourceId; + + public ResourceDefinitionNotFoundException(String studyId, String resourceId) { + super(); + this.studyId = studyId; + this.resourceId = resourceId; + } + + public String getStudyId() { + return studyId; + } + + public void setStudyId(String studyId) { + this.studyId = studyId; + } + + public String getResourceId() { + return resourceId; + } + + public void setResourceId(String resourceId) { + this.resourceId = resourceId; + } +} diff --git a/src/main/java/org/cbioportal/legacy/service/exception/SampleListNotFoundException.java b/src/main/java/org/cbioportal/legacy/service/exception/SampleListNotFoundException.java new file mode 100644 index 00000000000..c9e608ba037 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/exception/SampleListNotFoundException.java @@ -0,0 +1,19 @@ +package org.cbioportal.legacy.service.exception; + +public class SampleListNotFoundException extends Exception { + + private String sampleListId; + + public SampleListNotFoundException(String sampleListId) { + super(); + this.sampleListId = sampleListId; + } + + public String getSampleListId() { + return sampleListId; + } + + public void setSampleListId(String sampleListId) { + this.sampleListId = sampleListId; + } +} diff --git a/src/main/java/org/cbioportal/legacy/service/exception/SampleNotFoundException.java b/src/main/java/org/cbioportal/legacy/service/exception/SampleNotFoundException.java new file mode 100644 index 00000000000..18646390ceb --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/exception/SampleNotFoundException.java @@ -0,0 +1,29 @@ +package org.cbioportal.legacy.service.exception; + +public class SampleNotFoundException extends Exception { + + private String studyId; + private String sampleId; + + public SampleNotFoundException(String studyId, String sampleId) { + super(); + this.studyId = studyId; + this.sampleId = sampleId; + } + + public String getStudyId() { + return studyId; + } + + public void setStudyId(String studyId) { + this.studyId = studyId; + } + + public String getSampleId() { + return sampleId; + } + + public void setSampleId(String sampleId) { + this.sampleId = sampleId; + } +} diff --git a/src/main/java/org/cbioportal/legacy/service/exception/StudyNotFoundException.java b/src/main/java/org/cbioportal/legacy/service/exception/StudyNotFoundException.java new file mode 100644 index 00000000000..2199f26f6d8 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/exception/StudyNotFoundException.java @@ -0,0 +1,19 @@ +package org.cbioportal.legacy.service.exception; + +public class StudyNotFoundException extends Exception { + + private String studyId; + + public StudyNotFoundException(String studyId) { + super(); + this.studyId = studyId; + } + + public String getStudyId() { + return studyId; + } + + public void setStudyId(String studyId) { + this.studyId = studyId; + } +} diff --git a/src/main/java/org/cbioportal/service/exception/TokenNotFoundException.java b/src/main/java/org/cbioportal/legacy/service/exception/TokenNotFoundException.java similarity index 92% rename from src/main/java/org/cbioportal/service/exception/TokenNotFoundException.java rename to src/main/java/org/cbioportal/legacy/service/exception/TokenNotFoundException.java index 7a964e7aa98..40da7d87f08 100644 --- a/src/main/java/org/cbioportal/service/exception/TokenNotFoundException.java +++ b/src/main/java/org/cbioportal/legacy/service/exception/TokenNotFoundException.java @@ -1,4 +1,3 @@ - /* * Copyright (c) 2018 Memorial Sloan-Kettering Cancer Center. * @@ -45,19 +44,18 @@ * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . -*/ + */ // TODO move back package org.cbioportal.security.exception; -package org.cbioportal.service.exception; +package org.cbioportal.legacy.service.exception; public class TokenNotFoundException extends RuntimeException { - public TokenNotFoundException() { - super(); - } - - public TokenNotFoundException(String message) { - super(message); - } + public TokenNotFoundException() { + super(); + } + public TokenNotFoundException(String message) { + super(message); + } } diff --git a/src/main/java/org/cbioportal/legacy/service/impl/AlterationCountServiceImpl.java b/src/main/java/org/cbioportal/legacy/service/impl/AlterationCountServiceImpl.java new file mode 100644 index 00000000000..949eabcd845 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/impl/AlterationCountServiceImpl.java @@ -0,0 +1,315 @@ +package org.cbioportal.legacy.service.impl; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.TreeSet; +import java.util.function.BiFunction; +import java.util.function.Function; +import java.util.stream.Collectors; +import org.apache.commons.math3.util.Pair; +import org.cbioportal.legacy.model.AlterationCountBase; +import org.cbioportal.legacy.model.AlterationCountByGene; +import org.cbioportal.legacy.model.AlterationCountByStructuralVariant; +import org.cbioportal.legacy.model.AlterationFilter; +import org.cbioportal.legacy.model.CopyNumberCountByGene; +import org.cbioportal.legacy.model.MolecularProfile; +import org.cbioportal.legacy.model.MolecularProfileCaseIdentifier; +import org.cbioportal.legacy.model.util.Select; +import org.cbioportal.legacy.persistence.AlterationRepository; +import org.cbioportal.legacy.persistence.MolecularProfileRepository; +import org.cbioportal.legacy.service.AlterationCountService; +import org.cbioportal.legacy.service.util.AlterationEnrichmentUtil; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class AlterationCountServiceImpl implements AlterationCountService { + + private final AlterationRepository alterationRepository; + private final AlterationEnrichmentUtil alterationEnrichmentUtil; + private final AlterationEnrichmentUtil alterationEnrichmentUtilCna; + private final AlterationEnrichmentUtil + alterationEnrichmentUtilStructVar; + private final MolecularProfileRepository molecularProfileRepository; + + @Autowired + public AlterationCountServiceImpl( + AlterationRepository alterationRepository, + AlterationEnrichmentUtil alterationEnrichmentUtil, + AlterationEnrichmentUtil alterationEnrichmentUtilCna, + AlterationEnrichmentUtil + alterationEnrichmentUtilStructVar, + MolecularProfileRepository molecularProfileRepository) { + this.alterationRepository = alterationRepository; + this.alterationEnrichmentUtil = alterationEnrichmentUtil; + this.alterationEnrichmentUtilCna = alterationEnrichmentUtilCna; + this.alterationEnrichmentUtilStructVar = alterationEnrichmentUtilStructVar; + this.molecularProfileRepository = molecularProfileRepository; + } + + @Override + public Pair, Long> getSampleAlterationGeneCounts( + List molecularProfileCaseIdentifiers, + Select entrezGeneIds, + boolean includeFrequency, + boolean includeMissingAlterationsFromGenePanel, + AlterationFilter alterationFilter) { + + Function, List> dataFetcher = + profileCaseIdentifiers -> + alterationRepository.getSampleAlterationGeneCounts( + new TreeSet<>(profileCaseIdentifiers), entrezGeneIds, alterationFilter); + + BiFunction, List, Long> + includeFrequencyFunction = + (a, b) -> + alterationEnrichmentUtil.includeFrequencyForSamples( + a, b, includeMissingAlterationsFromGenePanel); + + return getAlterationGeneCounts( + molecularProfileCaseIdentifiers, includeFrequency, dataFetcher, includeFrequencyFunction); + } + + @Override + public Pair, Long> getPatientAlterationGeneCounts( + List molecularProfileCaseIdentifiers, + Select entrezGeneIds, + boolean includeFrequency, + boolean includeMissingAlterationsFromGenePanel, + AlterationFilter alterationFilter) { + + Function, List> dataFetcher = + profileCaseIdentifiers -> + alterationRepository.getPatientAlterationGeneCounts( + new TreeSet<>(profileCaseIdentifiers), entrezGeneIds, alterationFilter); + + BiFunction, List, Long> + includeFrequencyFunction = + (a, b) -> + alterationEnrichmentUtil.includeFrequencyForPatients( + a, b, includeMissingAlterationsFromGenePanel); + + return getAlterationGeneCounts( + molecularProfileCaseIdentifiers, includeFrequency, dataFetcher, includeFrequencyFunction); + } + + @Override + public Pair, Long> getSampleMutationGeneCounts( + List molecularProfileCaseIdentifiers, + Select entrezGeneIds, + boolean includeFrequency, + boolean includeMissingAlterationsFromGenePanel, + AlterationFilter alterationFilter) { + return getSampleAlterationGeneCounts( + molecularProfileCaseIdentifiers, + entrezGeneIds, + includeFrequency, + includeMissingAlterationsFromGenePanel, + alterationFilter); + } + + @Override + public Pair, Long> getPatientMutationGeneCounts( + List molecularProfileCaseIdentifiers, + Select entrezGeneIds, + boolean includeFrequency, + boolean includeMissingAlterationsFromGenePanel, + AlterationFilter alterationFilter) { + return getPatientAlterationGeneCounts( + molecularProfileCaseIdentifiers, + entrezGeneIds, + includeFrequency, + includeMissingAlterationsFromGenePanel, + alterationFilter); + } + + @Override + public Pair, Long> getSampleStructuralVariantGeneCounts( + List molecularProfileCaseIdentifiers, + Select entrezGeneIds, + boolean includeFrequency, + boolean includeMissingAlterationsFromGenePanel, + AlterationFilter alterationFilter) { + return getSampleAlterationGeneCounts( + molecularProfileCaseIdentifiers, + entrezGeneIds, + includeFrequency, + includeMissingAlterationsFromGenePanel, + alterationFilter); + } + + @Override + public Pair, Long> getPatientStructuralVariantGeneCounts( + List molecularProfileCaseIdentifiers, + Select entrezGeneIds, + boolean includeFrequency, + boolean includeMissingAlterationsFromGenePanel, + AlterationFilter alterationFilter) { + return getPatientAlterationGeneCounts( + molecularProfileCaseIdentifiers, + entrezGeneIds, + includeFrequency, + includeMissingAlterationsFromGenePanel, + alterationFilter); + } + + @Override + public Pair, Long> getSampleStructuralVariantCounts( + List molecularProfileCaseIdentifiers, + boolean includeFrequency, + boolean includeMissingAlterationsFromGenePanel, + AlterationFilter alterationFilter) { + + Function, List> + dataFetcher = + profileCaseIdentifiers -> + alterationRepository.getSampleStructuralVariantCounts( + new TreeSet<>(profileCaseIdentifiers), alterationFilter); + + BiFunction, List, Long> + includeFrequencyFunction = + (a, b) -> + alterationEnrichmentUtilStructVar.includeFrequencyForSamples( + a, b, includeMissingAlterationsFromGenePanel); + + return getAlterationGeneCounts( + molecularProfileCaseIdentifiers, includeFrequency, dataFetcher, includeFrequencyFunction); + } + + @Override + public Pair, Long> getSampleCnaGeneCounts( + List molecularProfileCaseIdentifiers, + Select entrezGeneIds, + boolean includeFrequency, + boolean includeMissingAlterationsFromGenePanel, + AlterationFilter alterationFilter) { + + Function, List> dataFetcher = + profileCaseIdentifiers -> + alterationRepository.getSampleCnaGeneCounts( + new TreeSet<>(profileCaseIdentifiers), entrezGeneIds, alterationFilter); + + BiFunction, List, Long> + includeFrequencyFunction = + (a, b) -> + alterationEnrichmentUtilCna.includeFrequencyForSamples( + a, b, includeMissingAlterationsFromGenePanel); + + return getAlterationGeneCounts( + molecularProfileCaseIdentifiers, includeFrequency, dataFetcher, includeFrequencyFunction); + } + + @Override + public Pair, Long> getPatientCnaGeneCounts( + List molecularProfileCaseIdentifiers, + Select entrezGeneIds, + boolean includeFrequency, + boolean includeMissingAlterationsFromGenePanel, + AlterationFilter alterationFilter) { + + Function, List> dataFetcher = + profileCaseIdentifiers -> + alterationRepository.getPatientCnaGeneCounts( + new TreeSet<>(profileCaseIdentifiers), entrezGeneIds, alterationFilter); + + BiFunction, List, Long> + includeFrequencyFunction = + (a, b) -> + alterationEnrichmentUtilCna.includeFrequencyForPatients( + a, b, includeMissingAlterationsFromGenePanel); + + return getAlterationGeneCounts( + molecularProfileCaseIdentifiers, includeFrequency, dataFetcher, includeFrequencyFunction); + } + + /** + * Retrieves gene alteration counts and calculates frequency if requested. + * + * @param The specific type extending AlterationCountBase + * @param molecularProfileCaseIdentifiers List of molecular profile identifiers + * @param includeFrequency Whether to include frequency calculation + * @param dataFetcher Function to fetch alteration count data + * @param includeFrequencyFunction Function needed for frequency calculation + * @return A pair containing the list of alteration counts and the total profiled cases count + */ + private Pair, Long> getAlterationGeneCounts( + List molecularProfileCaseIdentifiers, + boolean includeFrequency, + Function, List> dataFetcher, + BiFunction, List, Long> includeFrequencyFunction) { + + if (molecularProfileCaseIdentifiers.isEmpty()) { + return new Pair<>(Collections.emptyList(), 0L); + } + + // Get mapping from molecular profile IDs to study IDs + Map molecularProfileIdStudyIdMap = + molecularProfileRepository + .getMolecularProfiles( + molecularProfileCaseIdentifiers.stream() + .map(MolecularProfileCaseIdentifier::getMolecularProfileId) + .collect(Collectors.toSet()), + "SUMMARY") + .stream() + .collect( + Collectors.toMap( + MolecularProfile::getStableId, MolecularProfile::getCancerStudyIdentifier)); + + // Group by study ID and fetch alteration count data + List allAlterationCountByGenes = + molecularProfileCaseIdentifiers.stream() + .collect( + Collectors.groupingBy( + identifier -> + molecularProfileIdStudyIdMap.get(identifier.getMolecularProfileId()))) + .values() + .stream() + .flatMap(group -> dataFetcher.apply(group).stream()) + .toList(); + + // Merge alteration count data + List mergedAlterationCounts = mergeAlterationCounts(allAlterationCountByGenes); + + // Calculate frequency if requested + long profiledCasesCount = 0L; + if (includeFrequency) { + profiledCasesCount = + includeFrequencyFunction.apply(molecularProfileCaseIdentifiers, mergedAlterationCounts); + } + + return new Pair<>(mergedAlterationCounts, profiledCasesCount); + } + + /** + * Merges alteration counts across different studies for the same gene/event. + * + * @param The specific type extending AlterationCountBase + * @param alterationCountByGenes List of alteration counts to be merged + * @return A list of merged alteration counts + */ + private List mergeAlterationCounts( + List alterationCountByGenes) { + Map mergedAlterationCountsMap = new HashMap<>(); + + for (S datum : alterationCountByGenes) { + String key = datum.getUniqueEventKey(); + + if (mergedAlterationCountsMap.containsKey(key)) { + // If already seen, sum up relevant raw counts + S existing = mergedAlterationCountsMap.get(key); + existing.setTotalCount(existing.getTotalCount() + datum.getTotalCount()); + existing.setNumberOfAlteredCases( + existing.getNumberOfAlteredCases() + datum.getNumberOfAlteredCases()); + // NOTE: numberOfProfiledCases is intentionally not merged here + } else { + // First occurrence of this key, add to map + mergedAlterationCountsMap.put(key, datum); + } + } + + return new ArrayList<>(mergedAlterationCountsMap.values()); + } +} diff --git a/src/main/java/org/cbioportal/legacy/service/impl/AlterationDriverAnnotationServiceImpl.java b/src/main/java/org/cbioportal/legacy/service/impl/AlterationDriverAnnotationServiceImpl.java new file mode 100644 index 00000000000..6adb355d542 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/impl/AlterationDriverAnnotationServiceImpl.java @@ -0,0 +1,38 @@ +package org.cbioportal.legacy.service.impl; + +import java.util.*; +import java.util.stream.Collectors; +import org.cbioportal.legacy.model.AlterationDriverAnnotation; +import org.cbioportal.legacy.model.CustomDriverAnnotationReport; +import org.cbioportal.legacy.persistence.AlterationDriverAnnotationRepository; +import org.cbioportal.legacy.service.AlterationDriverAnnotationService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class AlterationDriverAnnotationServiceImpl implements AlterationDriverAnnotationService { + + @Autowired private AlterationDriverAnnotationRepository alterationDriverAnnotationRepository; + private final Set NO_DATA_TIERS = new HashSet<>(Arrays.asList(null, "", "NA")); + + public CustomDriverAnnotationReport getCustomDriverAnnotationProps( + List molecularProfileIds) { + + List rows = + alterationDriverAnnotationRepository.getAlterationDriverAnnotations(molecularProfileIds); + + Set tiers = + rows.stream() + .map(AlterationDriverAnnotation::getDriverTiersFilter) + .filter(driverTiersFilter -> !NO_DATA_TIERS.contains(driverTiersFilter)) + .collect(Collectors.toCollection(TreeSet::new)); + boolean hasBinary = + rows.stream() + .anyMatch( + d -> + "Putative_Driver".equals(d.getDriverFilter()) + || "Putative_Passenger".equals(d.getDriverFilter())); + + return new CustomDriverAnnotationReport(hasBinary, tiers); + } +} diff --git a/src/main/java/org/cbioportal/legacy/service/impl/AlterationEnrichmentServiceImpl.java b/src/main/java/org/cbioportal/legacy/service/impl/AlterationEnrichmentServiceImpl.java new file mode 100644 index 00000000000..39aeb7bcddc --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/impl/AlterationEnrichmentServiceImpl.java @@ -0,0 +1,58 @@ +package org.cbioportal.legacy.service.impl; + +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; +import org.apache.commons.math3.util.Pair; +import org.cbioportal.legacy.model.AlterationCountByGene; +import org.cbioportal.legacy.model.AlterationEnrichment; +import org.cbioportal.legacy.model.AlterationFilter; +import org.cbioportal.legacy.model.EnrichmentType; +import org.cbioportal.legacy.model.MolecularProfileCaseIdentifier; +import org.cbioportal.legacy.model.util.Select; +import org.cbioportal.legacy.service.AlterationCountService; +import org.cbioportal.legacy.service.AlterationEnrichmentService; +import org.cbioportal.legacy.service.util.AlterationEnrichmentUtil; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class AlterationEnrichmentServiceImpl implements AlterationEnrichmentService { + + @Autowired private AlterationCountService alterationCountService; + @Autowired private AlterationEnrichmentUtil alterationEnrichmentUtil; + + @Override + public List getAlterationEnrichments( + Map> molecularProfileCaseSets, + EnrichmentType enrichmentType, + AlterationFilter alterationFilter) { + + Map, Long>> alterationCountsbyEntrezGeneIdAndGroup = + getAlterationCountsbyEntrezGeneIdAndGroup( + molecularProfileCaseSets, enrichmentType, alterationFilter); + + return alterationEnrichmentUtil.createAlterationEnrichments( + alterationCountsbyEntrezGeneIdAndGroup); + } + + public Map, Long>> + getAlterationCountsbyEntrezGeneIdAndGroup( + Map> molecularProfileCaseSets, + EnrichmentType enrichmentType, + AlterationFilter alterationFilter) { + return molecularProfileCaseSets.entrySet().stream() + .collect( + Collectors.toMap( + entry -> entry.getKey(), // group name + entry -> { // group counts + if (enrichmentType.equals(EnrichmentType.SAMPLE)) { + return alterationCountService.getSampleAlterationGeneCounts( + entry.getValue(), Select.all(), true, true, alterationFilter); + } else { + return alterationCountService.getPatientAlterationGeneCounts( + entry.getValue(), Select.all(), true, true, alterationFilter); + } + })); + } +} diff --git a/src/main/java/org/cbioportal/legacy/service/impl/CacheServiceImpl.java b/src/main/java/org/cbioportal/legacy/service/impl/CacheServiceImpl.java new file mode 100644 index 00000000000..5e5ab29e069 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/impl/CacheServiceImpl.java @@ -0,0 +1,106 @@ +package org.cbioportal.legacy.service.impl; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.cbioportal.legacy.persistence.StudyRepository; +import org.cbioportal.legacy.persistence.cachemaputil.CacheMapUtil; +import org.cbioportal.legacy.persistence.cachemaputil.StaticRefCacheMapUtil; +import org.cbioportal.legacy.persistence.util.CacheUtils; +import org.cbioportal.legacy.service.CacheService; +import org.cbioportal.legacy.service.exception.CacheOperationException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cache.CacheManager; +import org.springframework.stereotype.Component; + +@Component +public class CacheServiceImpl implements CacheService { + + private static final Log LOG = LogFactory.getLog(CacheServiceImpl.class); + + @Autowired(required = false) + private CacheManager cacheManager; + + @Autowired private CacheMapUtil cacheMapUtil; + + // When caching is disabled there is no CacheUtils bean. + @Autowired(required = false) + private CacheUtils cacheUtils; + + @Autowired private StudyRepository studyRepository; + + @Override + public void clearCaches(boolean clearSpringManagedCache) throws CacheOperationException { + + // Flush Spring-managed caches (only when cache strategy has been defined). + if (clearSpringManagedCache) { + attemptEvictSpringManagedCache(".*"); + } + + // Flush cache used for user permission evaluation. + // Only needed when using cache not managed by the Spring caches. + if (cacheMapUtil instanceof StaticRefCacheMapUtil) { + ((StaticRefCacheMapUtil) cacheMapUtil).initializeCacheMemory(); + } + + // Note: DAO classes in package org.mskcc.cbio.portal.dao do have their own + // caching strategy. Since these classes are only used by the deprecated old + // version of the r-library and may result in problems in the running instance + // when flushing the cashes, we do not handle these caches in this service. + } + + // This evicts keys from the general and static caches when updating/adding/deleting a study. + public void clearCachesForStudy(String studyId, boolean clearSpringManagedCache) + throws CacheOperationException { + + List allStudyIds = + studyRepository.getAllStudies(null, "SUMMARY", null, null, null, null).stream() + .map(study -> study.getCancerStudyIdentifier()) + .collect(Collectors.toList()); + + // Flush Spring-managed caches (only when cache strategy has been defined). + if (clearSpringManagedCache) { + attemptEvictSpringManagedCache(buildEvictionRegex(studyId, allStudyIds)); + } + + // Flush cache used for user permission evaluation. + // Only needed when using cache not managed by the Spring caches. + if (cacheMapUtil instanceof StaticRefCacheMapUtil) { + ((StaticRefCacheMapUtil) cacheMapUtil).initializeCacheMemory(); + } + } + + private void attemptEvictSpringManagedCache(String pattern) throws CacheOperationException { + try { + if (cacheManager != null) { + cacheManager.getCacheNames().stream() + .forEach( + cacheName -> { + cacheUtils.evictByPattern(cacheName, pattern); + }); + } + } catch (RuntimeException e) { + e.printStackTrace(); + LOG.error("Error while evicting cache." + e.getMessage()); + throw new CacheOperationException("Error while evicting cache.", e); + } + } + + // Regex that selects keys that match id of deleted study + // or lacking any study id completely. For example: + // ^(?=.*study_id_1).*|^(?!.*study_id_1)(?!.*study_id_2)(?!.*study_id_3).* + // https://stackoverflow.com/a/8240998/11651683 + private String buildEvictionRegex(String studyId, List allStudyIds) { + + // make sure imported studyId is in all studies. + List all = new ArrayList<>(); + all.add(studyId); + all.addAll(allStudyIds); + + String allIdsRegex = all.stream().map(id -> "(?!.*" + id + ")").collect(Collectors.joining("")); + + return "^(?=.*" + studyId + ").*|^" + allIdsRegex + ".*"; + } +} diff --git a/src/main/java/org/cbioportal/legacy/service/impl/CacheStatisticsServiceImpl.java b/src/main/java/org/cbioportal/legacy/service/impl/CacheStatisticsServiceImpl.java new file mode 100644 index 00000000000..628a2874915 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/impl/CacheStatisticsServiceImpl.java @@ -0,0 +1,91 @@ +package org.cbioportal.legacy.service.impl; + +import jakarta.annotation.PostConstruct; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import javax.cache.Cache; +import org.cbioportal.legacy.persistence.util.CustomEhcachingProvider; +import org.cbioportal.legacy.service.CacheStatisticsService; +import org.cbioportal.legacy.service.exception.CacheNotFoundException; +import org.cbioportal.legacy.utils.config.annotation.ConditionalOnProperty; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; + +@Service +@ConditionalOnProperty( + name = "persistence.cache_type", + havingValue = {"ehcache-heap", "ehcache-disk", "ehcache-hybrid"}) +public class CacheStatisticsServiceImpl implements CacheStatisticsService { + + @Autowired private CustomEhcachingProvider customEhcachingProvider; + + private javax.cache.CacheManager cacheManager; + + @Value("${cache.statistics_endpoint_enabled:false}") + public boolean cacheStatisticsEndpointEnabled; + + @PostConstruct + public void initializeStatisticsService() { + cacheManager = customEhcachingProvider.getCacheManager(); + } + + protected void checkIfCacheStatisticsEndpointEnabled() { + if (!cacheStatisticsEndpointEnabled) { + // TODO re-implement Service module level Exception? + throw new RuntimeException( + "Cache statistics is not enabled for this instance of the portal."); + } + } + + @Override + public List getKeyCountsPerClass(String cacheName) throws CacheNotFoundException { + checkIfCacheStatisticsEndpointEnabled(); + Cache cache = cacheManager.getCache(cacheName); + if (cache == null) { + throw new CacheNotFoundException(cacheName); + } + Map classToKeyCount = new HashMap(); + Iterator> iterator = cache.iterator(); + while (iterator.hasNext()) { + Cache.Entry entry = iterator.next(); + String cacheKey = entry.getKey(); + String className = cacheKey.split("_")[0]; + int keyCount = classToKeyCount.containsKey(className) ? classToKeyCount.get(className) : 0; + classToKeyCount.put(className, keyCount + 1); + } + List keyCountsPerClass = new ArrayList(); + for (Map.Entry entry : classToKeyCount.entrySet()) { + keyCountsPerClass.add( + entry.getKey().toString() + ": " + entry.getValue().toString() + " keys"); + } + return keyCountsPerClass; + } + + @Override + public List getKeysInCache(String cacheName) throws CacheNotFoundException { + checkIfCacheStatisticsEndpointEnabled(); + Cache cache = cacheManager.getCache(cacheName); + if (cache == null) { + throw new CacheNotFoundException(cacheName); + } + Integer numberOfKeys = 0; + List keysInCache = new ArrayList(); + Iterator> iterator = cache.iterator(); + while (iterator.hasNext()) { + Cache.Entry entry = iterator.next(); + keysInCache.add(entry.getKey()); + numberOfKeys += 1; + } + keysInCache.add("Total Number of Keys: " + numberOfKeys.toString()); + return keysInCache; + } + + @Override + public String getCacheStatistics() { + throw new UnsupportedOperationException("Requested API is not implemented yet"); + } +} diff --git a/src/main/java/org/cbioportal/legacy/service/impl/CancerTypeServiceImpl.java b/src/main/java/org/cbioportal/legacy/service/impl/CancerTypeServiceImpl.java new file mode 100644 index 00000000000..b313d03d805 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/impl/CancerTypeServiceImpl.java @@ -0,0 +1,80 @@ +package org.cbioportal.legacy.service.impl; + +import jakarta.annotation.PostConstruct; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import org.cbioportal.legacy.model.TypeOfCancer; +import org.cbioportal.legacy.model.meta.BaseMeta; +import org.cbioportal.legacy.persistence.CancerTypeRepository; +import org.cbioportal.legacy.service.CancerTypeService; +import org.cbioportal.legacy.service.exception.CancerTypeNotFoundException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class CancerTypeServiceImpl implements CancerTypeService { + + private static final String TISSUE = "tissue"; + + @Autowired private CancerTypeRepository cancerTypeRepository; + + private Map primarySiteMap = new HashMap<>(); + + @PostConstruct + public void initPrimarySiteMap() { + + List allCancerTypes = getAllCancerTypes("SUMMARY", null, null, null, null); + + for (TypeOfCancer typeOfCancer : allCancerTypes) { + + if (!typeOfCancer.getTypeOfCancerId().equals(TISSUE)) { + TypeOfCancer primarySite = getParent(allCancerTypes, typeOfCancer); + primarySiteMap.put(typeOfCancer.getTypeOfCancerId(), primarySite); + } + } + } + + @Override + public List getAllCancerTypes( + String projection, Integer pageSize, Integer pageNumber, String sortBy, String direction) { + + return cancerTypeRepository.getAllCancerTypes( + projection, pageSize, pageNumber, sortBy, direction); + } + + @Override + public BaseMeta getMetaCancerTypes() { + return cancerTypeRepository.getMetaCancerTypes(); + } + + @Override + public TypeOfCancer getCancerType(String cancerTypeId) throws CancerTypeNotFoundException { + + TypeOfCancer typeOfCancer = cancerTypeRepository.getCancerType(cancerTypeId); + if (typeOfCancer == null) { + throw new CancerTypeNotFoundException(cancerTypeId); + } + + return typeOfCancer; + } + + @Override + public Map getPrimarySiteMap() { + return primarySiteMap; + } + + private TypeOfCancer getParent(List allCancerTypes, TypeOfCancer typeOfCancer) { + + if (typeOfCancer.getParent().equals(TISSUE)) { + return typeOfCancer; + } + + return getParent( + allCancerTypes, + allCancerTypes.stream() + .filter(c -> c.getTypeOfCancerId().equals(typeOfCancer.getParent())) + .findFirst() + .get()); + } +} diff --git a/src/main/java/org/cbioportal/legacy/service/impl/ClinicalAttributeServiceImpl.java b/src/main/java/org/cbioportal/legacy/service/impl/ClinicalAttributeServiceImpl.java new file mode 100644 index 00000000000..ca485602098 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/impl/ClinicalAttributeServiceImpl.java @@ -0,0 +1,122 @@ +package org.cbioportal.legacy.service.impl; + +import java.util.ArrayList; +import java.util.List; +import org.cbioportal.legacy.model.ClinicalAttribute; +import org.cbioportal.legacy.model.ClinicalAttributeCount; +import org.cbioportal.legacy.model.meta.BaseMeta; +import org.cbioportal.legacy.persistence.ClinicalAttributeRepository; +import org.cbioportal.legacy.service.ClinicalAttributeService; +import org.cbioportal.legacy.service.StudyService; +import org.cbioportal.legacy.service.exception.ClinicalAttributeNotFoundException; +import org.cbioportal.legacy.service.exception.StudyNotFoundException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.security.access.prepost.PostFilter; +import org.springframework.stereotype.Service; + +@Service +public class ClinicalAttributeServiceImpl implements ClinicalAttributeService { + + @Autowired private ClinicalAttributeRepository clinicalAttributeRepository; + @Autowired private StudyService studyService; + + @Value("${authenticate:false}") + private String AUTHENTICATE; + + @Override + @PostFilter( + "hasPermission(filterObject.cancerStudyIdentifier, 'CancerStudyId', T(org.cbioportal.legacy.utils.security.AccessLevel).READ)") + public List getAllClinicalAttributes( + String projection, Integer pageSize, Integer pageNumber, String sortBy, String direction) { + + List clinicalAttributes = + clinicalAttributeRepository.getAllClinicalAttributes( + projection, pageSize, pageNumber, sortBy, direction); + // copy the list before returning so @PostFilter doesn't taint the list stored in the + // persistence layer cache + return (AUTHENTICATE.equals("false")) + ? clinicalAttributes + : new ArrayList(clinicalAttributes); + } + + @Override + public BaseMeta getMetaClinicalAttributes() { + + return clinicalAttributeRepository.getMetaClinicalAttributes(); + } + + @Override + public ClinicalAttribute getClinicalAttribute(String studyId, String clinicalAttributeId) + throws ClinicalAttributeNotFoundException, StudyNotFoundException { + + studyService.getStudy(studyId); + + ClinicalAttribute clinicalAttribute = + clinicalAttributeRepository.getClinicalAttribute(studyId, clinicalAttributeId); + + if (clinicalAttribute == null) { + throw new ClinicalAttributeNotFoundException(studyId, clinicalAttributeId); + } + + return clinicalAttribute; + } + + @Override + public List getAllClinicalAttributesInStudy( + String studyId, + String projection, + Integer pageSize, + Integer pageNumber, + String sortBy, + String direction) + throws StudyNotFoundException { + + studyService.getStudy(studyId); + + return clinicalAttributeRepository.getAllClinicalAttributesInStudy( + studyId, projection, pageSize, pageNumber, sortBy, direction); + } + + @Override + public BaseMeta getMetaClinicalAttributesInStudy(String studyId) throws StudyNotFoundException { + + studyService.getStudy(studyId); + + return clinicalAttributeRepository.getMetaClinicalAttributesInStudy(studyId); + } + + @Override + public List fetchClinicalAttributes(List studyIds, String projection) { + + return clinicalAttributeRepository.fetchClinicalAttributes(studyIds, projection); + } + + @Override + public BaseMeta fetchMetaClinicalAttributes(List studyIds) { + + return clinicalAttributeRepository.fetchMetaClinicalAttributes(studyIds); + } + + @Override + public List getClinicalAttributeCountsBySampleIds( + List studyIds, List sampleIds) { + + return clinicalAttributeRepository.getClinicalAttributeCountsBySampleIds(studyIds, sampleIds); + } + + @Override + public List getClinicalAttributeCountsBySampleListId( + String sampleListId) { + + return clinicalAttributeRepository.getClinicalAttributeCountsBySampleListId(sampleListId); + } + + @Override + public List getClinicalAttributesByStudyIdsAndAttributeIds( + List studyIds, List attributeIds) { + + return clinicalAttributeRepository.getClinicalAttributesByStudyIdsAndAttributeIds( + studyIds, attributeIds); + } +} diff --git a/src/main/java/org/cbioportal/legacy/service/impl/ClinicalDataDensityPlotServiceImpl.java b/src/main/java/org/cbioportal/legacy/service/impl/ClinicalDataDensityPlotServiceImpl.java new file mode 100644 index 00000000000..b41b9f069a6 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/impl/ClinicalDataDensityPlotServiceImpl.java @@ -0,0 +1,198 @@ +package org.cbioportal.legacy.service.impl; + +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; +import org.apache.commons.lang3.math.NumberUtils; +import org.apache.commons.math3.stat.correlation.PearsonsCorrelation; +import org.apache.commons.math3.stat.correlation.SpearmansCorrelation; +import org.cbioportal.legacy.model.ClinicalData; +import org.cbioportal.legacy.model.DensityPlotBin; +import org.cbioportal.legacy.model.DensityPlotData; +import org.cbioportal.legacy.service.ClinicalDataDensityPlotService; +import org.cbioportal.legacy.web.parameter.StudyViewFilter; +import org.cbioportal.legacy.web.util.DensityPlotParameters; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Service; + +@Service +public class ClinicalDataDensityPlotServiceImpl implements ClinicalDataDensityPlotService { + + @Cacheable( + cacheResolver = "staticRepositoryCacheOneResolver", + condition = + "@cacheEnabledConfig.getEnabledClickhouse() && @studyViewFilterUtil.isUnfilteredQuery(#studyViewFilter)") + @Override + public DensityPlotData getDensityPlotData( + List sampleClinicalData, + DensityPlotParameters densityPlotParameters, + StudyViewFilter studyViewFilter) { + DensityPlotData result = new DensityPlotData(); + result.setBins(new ArrayList<>()); + + Map> clinicalDataGroupedBySampleId = + sampleClinicalData.stream() + .collect(Collectors.groupingBy(c -> c.getStudyId() + "_" + c.getSampleId())); + + List extractedXYClinicalData = + clinicalDataGroupedBySampleId.entrySet().stream() + .filter( + entry -> + entry.getValue().size() == 2 + && NumberUtils.isCreatable(entry.getValue().get(0).getAttrValue()) + && NumberUtils.isCreatable(entry.getValue().get(1).getAttrValue())) + .flatMap(entry -> entry.getValue().stream()) + .toList(); + + if (extractedXYClinicalData.isEmpty()) { + return result; + } + + Map> partition = + extractedXYClinicalData.stream() + .collect( + Collectors.partitioningBy( + c -> c.getAttrId().equals(densityPlotParameters.getXAxisAttributeId()))); + + boolean useXLogScale = + densityPlotParameters.getXAxisLogScale() + && ClinicalDataDensityPlotServiceImpl.isLogScalePossibleForAttribute( + densityPlotParameters.getXAxisAttributeId()); + boolean useYLogScale = + densityPlotParameters.getYAxisLogScale() + && ClinicalDataDensityPlotServiceImpl.isLogScalePossibleForAttribute( + densityPlotParameters.getYAxisAttributeId()); + + double[] xValues = + partition.get(true).stream() + .mapToDouble( + useXLogScale + ? ClinicalDataDensityPlotServiceImpl::parseValueLog + : ClinicalDataDensityPlotServiceImpl::parseValueLinear) + .toArray(); + double[] yValues = + partition.get(false).stream() + .mapToDouble( + useYLogScale + ? ClinicalDataDensityPlotServiceImpl::parseValueLog + : ClinicalDataDensityPlotServiceImpl::parseValueLinear) + .toArray(); + double[] xValuesCopy = Arrays.copyOf(xValues, xValues.length); + double[] yValuesCopy = Arrays.copyOf(yValues, yValues.length); // Why copy these? + Arrays.sort(xValuesCopy); + Arrays.sort(yValuesCopy); + + double xAxisStartValue = + densityPlotParameters.getXAxisStart() == null + ? xValuesCopy[0] + : (useXLogScale + ? ClinicalDataDensityPlotServiceImpl.logScale( + densityPlotParameters.getXAxisStart().doubleValue()) + : densityPlotParameters.getXAxisStart().doubleValue()); + double xAxisEndValue = + densityPlotParameters.getXAxisEnd() == null + ? xValuesCopy[xValuesCopy.length - 1] + : (useXLogScale + ? ClinicalDataDensityPlotServiceImpl.logScale( + densityPlotParameters.getXAxisEnd().doubleValue()) + : densityPlotParameters.getXAxisEnd().doubleValue()); + double yAxisStartValue = + densityPlotParameters.getYAxisStart() == null + ? yValuesCopy[0] + : (useYLogScale + ? ClinicalDataDensityPlotServiceImpl.logScale( + densityPlotParameters.getYAxisStart().doubleValue()) + : densityPlotParameters.getYAxisStart().doubleValue()); + double yAxisEndValue = + densityPlotParameters.getYAxisEnd() == null + ? yValuesCopy[yValuesCopy.length - 1] + : (useYLogScale + ? ClinicalDataDensityPlotServiceImpl.logScale( + densityPlotParameters.getYAxisEnd().doubleValue()) + : densityPlotParameters.getYAxisEnd().doubleValue()); + double xAxisBinInterval = + (xAxisEndValue - xAxisStartValue) / densityPlotParameters.getXAxisBinCount(); + double yAxisBinInterval = + (yAxisEndValue - yAxisStartValue) / densityPlotParameters.getYAxisBinCount(); + List bins = result.getBins(); + for (int i = 0; i < densityPlotParameters.getXAxisBinCount(); i++) { + for (int j = 0; j < densityPlotParameters.getYAxisBinCount(); j++) { + DensityPlotBin densityPlotBin = new DensityPlotBin(); + densityPlotBin.setBinX(BigDecimal.valueOf(xAxisStartValue + (i * xAxisBinInterval))); + densityPlotBin.setBinY(BigDecimal.valueOf(yAxisStartValue + (j * yAxisBinInterval))); + densityPlotBin.setCount(0); + bins.add(densityPlotBin); + } + } + + for (int i = 0; i < xValues.length; i++) { + double xValue = xValues[i]; + double yValue = yValues[i]; + int xBinIndex = (int) ((xValue - xAxisStartValue) / xAxisBinInterval); + int yBinIndex = (int) ((yValue - yAxisStartValue) / yAxisBinInterval); + int index = + (int) + (((xBinIndex - (xBinIndex == densityPlotParameters.getXAxisBinCount() ? 1 : 0)) + * densityPlotParameters.getYAxisBinCount()) + + (yBinIndex - (yBinIndex == densityPlotParameters.getYAxisBinCount() ? 1 : 0))); + DensityPlotBin densityPlotBin = bins.get(index); + densityPlotBin.setCount(densityPlotBin.getCount() + 1); + BigDecimal xValueBigDecimal = BigDecimal.valueOf(xValue); + BigDecimal yValueBigDecimal = BigDecimal.valueOf(yValue); + + // Set new min and max as needed + if (densityPlotBin.getMinX() == null + || densityPlotBin.getMinX().compareTo(xValueBigDecimal) > 0) { + densityPlotBin.setMinX(xValueBigDecimal); + } + if (densityPlotBin.getMaxX() == null + || densityPlotBin.getMaxX().compareTo(xValueBigDecimal) < 0) { + densityPlotBin.setMaxX(xValueBigDecimal); + } + if (densityPlotBin.getMinY() == null + || densityPlotBin.getMinY().compareTo(yValueBigDecimal) > 0) { + densityPlotBin.setMinY(yValueBigDecimal); + } + if (densityPlotBin.getMaxY() == null + || densityPlotBin.getMaxY().compareTo(yValueBigDecimal) < 0) { + densityPlotBin.setMaxY(yValueBigDecimal); + } + } + + if (xValues.length > 1) { + // need at least 2 entries in each to compute correlation + result.setPearsonCorr(new PearsonsCorrelation().correlation(xValues, yValues)); + result.setSpearmanCorr(new SpearmansCorrelation().correlation(xValues, yValues)); + } else { + // if less than 1 entry, just set 0 correlation + result.setSpearmanCorr(0.0); + result.setPearsonCorr(0.0); + } + + // filter out empty bins + result.setBins( + result.getBins().stream() + .filter((bin) -> (bin.getCount() > 0)) + .collect(Collectors.toList())); + return result; + } + + private static boolean isLogScalePossibleForAttribute(String clinicalAttributeId) { + return clinicalAttributeId.equals("MUTATION_COUNT"); + } + + private static double logScale(double val) { + return Math.log(1 + val); + } + + private static double parseValueLog(ClinicalData c) { + return ClinicalDataDensityPlotServiceImpl.logScale(Double.parseDouble(c.getAttrValue())); + } + + private static double parseValueLinear(ClinicalData c) { + return Double.parseDouble(c.getAttrValue()); + } +} diff --git a/src/main/java/org/cbioportal/legacy/service/impl/ClinicalDataServiceImpl.java b/src/main/java/org/cbioportal/legacy/service/impl/ClinicalDataServiceImpl.java new file mode 100644 index 00000000000..766253d013f --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/impl/ClinicalDataServiceImpl.java @@ -0,0 +1,353 @@ +package org.cbioportal.legacy.service.impl; + +import static org.cbioportal.legacy.utils.Encoder.calculateBase64; + +import java.util.*; +import java.util.function.Function; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.cbioportal.legacy.model.ClinicalAttribute; +import org.cbioportal.legacy.model.ClinicalData; +import org.cbioportal.legacy.model.ClinicalDataCount; +import org.cbioportal.legacy.model.ClinicalDataCountItem; +import org.cbioportal.legacy.model.Patient; +import org.cbioportal.legacy.model.SampleClinicalDataCollection; +import org.cbioportal.legacy.model.meta.BaseMeta; +import org.cbioportal.legacy.persistence.ClinicalDataRepository; +import org.cbioportal.legacy.persistence.mybatis.util.PaginationCalculator; +import org.cbioportal.legacy.service.ClinicalAttributeService; +import org.cbioportal.legacy.service.ClinicalDataService; +import org.cbioportal.legacy.service.PatientService; +import org.cbioportal.legacy.service.SampleService; +import org.cbioportal.legacy.service.StudyService; +import org.cbioportal.legacy.service.exception.PatientNotFoundException; +import org.cbioportal.legacy.service.exception.SampleNotFoundException; +import org.cbioportal.legacy.service.exception.StudyNotFoundException; +import org.cbioportal.legacy.service.util.ClinicalAttributeUtil; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class ClinicalDataServiceImpl implements ClinicalDataService { + + @Autowired private ClinicalDataRepository clinicalDataRepository; + @Autowired private StudyService studyService; + @Autowired private PatientService patientService; + @Autowired private SampleService sampleService; + @Autowired private ClinicalAttributeService clinicalAttributeService; + @Autowired private ClinicalAttributeUtil clinicalAttributeUtil; + + @Override + public List getAllClinicalDataOfSampleInStudy( + String studyId, + String sampleId, + String attributeId, + String projection, + Integer pageSize, + Integer pageNumber, + String sortBy, + String direction) + throws SampleNotFoundException, StudyNotFoundException { + + sampleService.getSampleInStudy(studyId, sampleId); + + return clinicalDataRepository.getAllClinicalDataOfSampleInStudy( + studyId, sampleId, attributeId, projection, pageSize, pageNumber, sortBy, direction); + } + + @Override + public BaseMeta getMetaSampleClinicalData(String studyId, String sampleId, String attributeId) + throws SampleNotFoundException, StudyNotFoundException { + + sampleService.getSampleInStudy(studyId, sampleId); + + return clinicalDataRepository.getMetaSampleClinicalData(studyId, sampleId, attributeId); + } + + @Override + public List getAllClinicalDataOfPatientInStudy( + String studyId, + String patientId, + String attributeId, + String projection, + Integer pageSize, + Integer pageNumber, + String sortBy, + String direction) + throws PatientNotFoundException, StudyNotFoundException { + + patientService.getPatientInStudy(studyId, patientId); + + return clinicalDataRepository.getAllClinicalDataOfPatientInStudy( + studyId, patientId, attributeId, projection, pageSize, pageNumber, sortBy, direction); + } + + @Override + public BaseMeta getMetaPatientClinicalData(String studyId, String patientId, String attributeId) + throws PatientNotFoundException, StudyNotFoundException { + + patientService.getPatientInStudy(studyId, patientId); + + return clinicalDataRepository.getMetaPatientClinicalData(studyId, patientId, attributeId); + } + + @Override + public List getAllClinicalDataInStudy( + String studyId, + String attributeId, + String clinicalDataType, + String projection, + Integer pageSize, + Integer pageNumber, + String sortBy, + String direction) + throws StudyNotFoundException { + + studyService.getStudy(studyId); + + return clinicalDataRepository.getAllClinicalDataInStudy( + studyId, + attributeId, + clinicalDataType, + projection, + pageSize, + pageNumber, + sortBy, + direction); + } + + @Override + public BaseMeta getMetaAllClinicalData( + String studyId, String attributeId, String clinicalDataType) throws StudyNotFoundException { + + studyService.getStudy(studyId); + + return clinicalDataRepository.getMetaAllClinicalData(studyId, attributeId, clinicalDataType); + } + + @Override + public List fetchAllClinicalDataInStudy( + String studyId, + List ids, + List attributeIds, + String clinicalDataType, + String projection) + throws StudyNotFoundException { + + studyService.getStudy(studyId); + + return clinicalDataRepository.fetchAllClinicalDataInStudy( + studyId, ids, attributeIds, clinicalDataType, projection); + } + + @Override + public BaseMeta fetchMetaClinicalDataInStudy( + String studyId, List ids, List attributeIds, String clinicalDataType) + throws StudyNotFoundException { + + studyService.getStudy(studyId); + + return clinicalDataRepository.fetchMetaClinicalDataInStudy( + studyId, ids, attributeIds, clinicalDataType); + } + + @Override + public List fetchClinicalData( + List studyIds, + List ids, + List attributeIds, + String clinicalDataType, + String projection) { + if (ids.isEmpty()) { + return new ArrayList<>(); + } + return clinicalDataRepository.fetchClinicalData( + studyIds, ids, attributeIds, clinicalDataType, projection); + } + + @Override + public BaseMeta fetchMetaClinicalData( + List studyIds, List ids, List attributeIds, String clinicalDataType) { + + return clinicalDataRepository.fetchMetaClinicalData( + studyIds, ids, attributeIds, clinicalDataType); + } + + @Override + public List fetchClinicalDataCounts( + List studyIds, List sampleIds, List attributeIds) { + + if (attributeIds.isEmpty()) { + return new ArrayList<>(); + } + + List clinicalAttributes = + clinicalAttributeService.getClinicalAttributesByStudyIdsAndAttributeIds( + studyIds, attributeIds); + + List sampleAttributeIds = new ArrayList<>(); + List patientAttributeIds = new ArrayList<>(); + // patient attributes which are also sample attributes in other studies + List conflictingPatientAttributeIds = new ArrayList<>(); + + clinicalAttributeUtil.extractCategorizedClinicalAttributes( + clinicalAttributes, + sampleAttributeIds, + patientAttributeIds, + conflictingPatientAttributeIds); + + List clinicalDataCounts = new ArrayList(); + if (!sampleAttributeIds.isEmpty()) { + clinicalDataCounts.addAll( + clinicalDataRepository.fetchClinicalDataCounts( + studyIds, sampleIds, sampleAttributeIds, "SAMPLE", "SUMMARY")); + } + + if (!patientAttributeIds.isEmpty()) { + clinicalDataCounts.addAll( + clinicalDataRepository.fetchClinicalDataCounts( + studyIds, sampleIds, patientAttributeIds, "PATIENT", "SUMMARY")); + } + + if (!conflictingPatientAttributeIds.isEmpty()) { + clinicalDataCounts.addAll( + clinicalDataRepository.fetchClinicalDataCounts( + studyIds, sampleIds, conflictingPatientAttributeIds, "PATIENT", "DETAILED")); + } + + sampleAttributeIds.addAll(conflictingPatientAttributeIds); + + clinicalDataCounts = + clinicalDataCounts.stream() + .filter( + c -> + !c.getValue().toUpperCase().equals("NA") + && !c.getValue().toUpperCase().equals("NAN") + && !c.getValue().toUpperCase().equals("N/A")) + .collect(Collectors.toList()); + + Map> clinicalDataCountMap = + clinicalDataCounts.stream() + .collect(Collectors.groupingBy(ClinicalDataCount::getAttributeId)); + + List patients = new ArrayList(); + if (!patientAttributeIds.isEmpty()) { + patients.addAll(patientService.getPatientsOfSamples(studyIds, sampleIds)); + } + + HashSet uniqueAttributeIds = new HashSet<>(attributeIds); + + return uniqueAttributeIds.stream() + .map( + attributeId -> { + int naCount = 0; + int totalCount = 0; + List counts = + clinicalDataCountMap.getOrDefault(attributeId, new ArrayList<>()); + + if (conflictingPatientAttributeIds.contains(attributeId)) { + // if its a conflicting attribute then sum all counts + counts = + counts.stream() + .collect( + Collectors.toMap( + ClinicalDataCount::getValue, + Function.identity(), + (clinicalDataCount1, clinicalDataCount2) -> { + clinicalDataCount1.setCount( + clinicalDataCount1.getCount() + + clinicalDataCount2.getCount()); + return clinicalDataCount1; + })) + .values() + .stream() + .collect(Collectors.toList()); + } + + if (!counts.isEmpty()) { + totalCount = counts.stream().mapToInt(ClinicalDataCount::getCount).sum(); + } + + if (sampleAttributeIds.contains(attributeId)) { + naCount = sampleIds.size() - totalCount; + } else { + naCount = patients.size() - totalCount; + } + + if (naCount > 0) { + ClinicalDataCount clinicalDataCount = new ClinicalDataCount(); + clinicalDataCount.setAttributeId(attributeId); + clinicalDataCount.setValue("NA"); + clinicalDataCount.setCount(naCount); + counts.add(clinicalDataCount); + } + + ClinicalDataCountItem clinicalDataCountItem = new ClinicalDataCountItem(); + clinicalDataCountItem.setAttributeId(attributeId); + clinicalDataCountItem.setCounts(counts); + return clinicalDataCountItem; + }) + .collect(Collectors.toList()); + } + + @Override + public List getPatientClinicalDataDetailedToSample( + List studyIds, List patientIds, List attributeIds) { + return clinicalDataRepository.getPatientClinicalDataDetailedToSample( + studyIds, patientIds, attributeIds); + } + + @Override + public ImmutablePair fetchSampleClinicalTable( + List studyIds, + List sampleIds, + Integer pageSize, + Integer pageNumber, + String searchTerm, + String sortBy, + String direction) { + if (studyIds == null || studyIds.isEmpty() || sampleIds == null || sampleIds.isEmpty()) { + return new ImmutablePair<>(SampleClinicalDataCollection.builder().build(), 0); + } + + // Request un-paginated data. + List allSampleInternalIds = + clinicalDataRepository.getVisibleSampleInternalIdsForClinicalTable( + studyIds, sampleIds, null, null, searchTerm, sortBy, direction); + Integer offset = PaginationCalculator.offset(pageSize, pageNumber); + + if (allSampleInternalIds.isEmpty() || offset >= allSampleInternalIds.size()) { + return new ImmutablePair<>(SampleClinicalDataCollection.builder().build(), 0); + } + + return buildSampleClinicalDataCollection(allSampleInternalIds, offset, pageSize); + } + + private ImmutablePair buildSampleClinicalDataCollection( + List allSampleInternalIds, Integer offset, Integer pageSize) { + + // Apply pagination to the sampleId list. + Integer toIndex = PaginationCalculator.lastIndex(offset, pageSize, allSampleInternalIds.size()); + List visibleSampleInternalIds = allSampleInternalIds.subList(offset, toIndex); + + List sampleClinicalData = + clinicalDataRepository.getSampleClinicalDataBySampleInternalIds(visibleSampleInternalIds); + List patientClinicalData = + clinicalDataRepository.getPatientClinicalDataBySampleInternalIds(visibleSampleInternalIds); + + // Merge sample and patient level clinical data and key by unique sample-key. + SampleClinicalDataCollection sampleClinicalDataCollection = + SampleClinicalDataCollection.builder() + .withByUniqueSampleKey( + Stream.concat(sampleClinicalData.stream(), patientClinicalData.stream()) + .collect( + Collectors.groupingBy( + clinicalDatum -> + calculateBase64( + clinicalDatum.getSampleId(), clinicalDatum.getStudyId())))) + .build(); + + return new ImmutablePair<>(sampleClinicalDataCollection, allSampleInternalIds.size()); + } +} diff --git a/src/main/java/org/cbioportal/legacy/service/impl/ClinicalEventServiceImpl.java b/src/main/java/org/cbioportal/legacy/service/impl/ClinicalEventServiceImpl.java new file mode 100644 index 00000000000..a6dc35a3c7a --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/impl/ClinicalEventServiceImpl.java @@ -0,0 +1,332 @@ +package org.cbioportal.legacy.service.impl; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.Set; +import java.util.function.Function; +import java.util.function.ToIntFunction; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import org.apache.commons.collections4.CollectionUtils; +import org.cbioportal.legacy.model.ClinicalData; +import org.cbioportal.legacy.model.ClinicalEvent; +import org.cbioportal.legacy.model.ClinicalEventData; +import org.cbioportal.legacy.model.ClinicalEventTypeCount; +import org.cbioportal.legacy.model.Patient; +import org.cbioportal.legacy.model.meta.BaseMeta; +import org.cbioportal.legacy.persistence.ClinicalEventRepository; +import org.cbioportal.legacy.service.ClinicalEventService; +import org.cbioportal.legacy.service.PatientService; +import org.cbioportal.legacy.service.exception.PatientNotFoundException; +import org.cbioportal.legacy.service.exception.StudyNotFoundException; +import org.cbioportal.legacy.web.parameter.ClinicalEventRequestIdentifier; +import org.cbioportal.legacy.web.parameter.OccurrencePosition; +import org.cbioportal.legacy.web.parameter.SurvivalRequest; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class ClinicalEventServiceImpl implements ClinicalEventService { + + @Autowired private ClinicalEventRepository clinicalEventRepository; + @Autowired private PatientService patientService; + + @Override + public List getAllClinicalEventsOfPatientInStudy( + String studyId, + String patientId, + String projection, + Integer pageSize, + Integer pageNumber, + String sortBy, + String direction) + throws PatientNotFoundException, StudyNotFoundException { + + patientService.getPatientInStudy(studyId, patientId); + + List clinicalEvents = + clinicalEventRepository.getAllClinicalEventsOfPatientInStudy( + studyId, patientId, projection, pageSize, pageNumber, sortBy, direction); + + if (!projection.equals("ID") && !clinicalEvents.isEmpty()) { + + List clinicalEventDataList = + clinicalEventRepository.getDataOfClinicalEvents( + clinicalEvents.stream() + .map(ClinicalEvent::getClinicalEventId) + .collect(Collectors.toList())); + + clinicalEvents.forEach( + c -> + c.setAttributes( + clinicalEventDataList.stream() + .filter(a -> a.getClinicalEventId().equals(c.getClinicalEventId())) + .collect(Collectors.toList()))); + } + + return clinicalEvents; + } + + @Override + public BaseMeta getMetaPatientClinicalEvents(String studyId, String patientId) + throws PatientNotFoundException, StudyNotFoundException { + + patientService.getPatientInStudy(studyId, patientId); + + return clinicalEventRepository.getMetaPatientClinicalEvents(studyId, patientId); + } + + @Override + public List getAllClinicalEventsInStudy( + String studyId, + String projection, + Integer pageSize, + Integer pageNumber, + String sortBy, + String direction) { + + List clinicalEvents = + clinicalEventRepository.getAllClinicalEventsInStudy( + studyId, projection, pageSize, pageNumber, sortBy, direction); + + if (!projection.equals("ID")) { + + List clinicalEventDataList = + clinicalEventRepository.getDataOfClinicalEvents( + clinicalEvents.stream() + .map(ClinicalEvent::getClinicalEventId) + .collect(Collectors.toList())); + + clinicalEvents.forEach( + c -> + c.setAttributes( + clinicalEventDataList.stream() + .filter(a -> a.getClinicalEventId().equals(c.getClinicalEventId())) + .collect(Collectors.toList()))); + } + + return clinicalEvents; + } + + @Override + public BaseMeta getMetaClinicalEvents(String studyId) throws StudyNotFoundException { + return clinicalEventRepository.getMetaClinicalEvents(studyId); + } + + @Override + public Map> getPatientsSamplesPerClinicalEventType( + List studyIds, List sampleIds) { + + return clinicalEventRepository.getSamplesOfPatientsPerEventTypeInStudy(studyIds, sampleIds); + } + + @Override + public List getClinicalEventTypeCounts( + List studyIds, List sampleIds) { + + List patients = patientService.getPatientsOfSamples(studyIds, sampleIds); + + List studies = + patients.stream().map(Patient::getCancerStudyIdentifier).collect(Collectors.toList()); + List patientIds = + patients.stream().map(Patient::getStableId).collect(Collectors.toList()); + + List clinicalEvents = + clinicalEventRepository.getPatientsDistinctClinicalEventInStudies(studies, patientIds); + + Map clinicalEventTypeCountMap = new HashMap<>(); + for (ClinicalEvent e : clinicalEvents) { + clinicalEventTypeCountMap.put( + e.getEventType(), clinicalEventTypeCountMap.getOrDefault(e.getEventType(), 0) + 1); + } + + return clinicalEventTypeCountMap.entrySet().stream() + .map(e -> new ClinicalEventTypeCount(e.getKey(), e.getValue())) + .collect(Collectors.toList()); + } + + @Override + public List getSurvivalData( + List studyIds, + List patientIds, + String attributeIdPrefix, + SurvivalRequest survivalRequest) { + List startClinicalEventsMeta = + getToClinicalEvents(survivalRequest.getStartEventRequestIdentifier()); + List patientStartEvents = + clinicalEventRepository.getTimelineEvents(studyIds, patientIds, startClinicalEventsMeta); + + // only fetch end timeline events for patients that have endClinicalEventsMeta and start + // timeline events + List patientEndEvents = + filterClinicalEvents(patientStartEvents, survivalRequest.getEndEventRequestIdentifier()); + + ToIntFunction startPositionIdentifier = + getPositionIdentifier(survivalRequest.getStartEventRequestIdentifier().getPosition()); + ToIntFunction endPositionIdentifier = + getPositionIdentifier(survivalRequest.getEndEventRequestIdentifier().getPosition()); + Map patientEndEventsById = + patientEndEvents.stream() + .collect(Collectors.toMap(ClinicalEventServiceImpl::getKey, Function.identity())); + + // filter out cases where start event is less than end event + patientStartEvents = + patientStartEvents.stream() + .filter( + event -> + Optional.ofNullable(patientEndEventsById.get(getKey(event))) + .map(endPositionIdentifier::applyAsInt) + .map(endDate -> startPositionIdentifier.applyAsInt(event) < endDate) + .orElse(true)) + .toList(); + + List patientCensoredEvents = + filterClinicalEvents( + patientStartEvents, survivalRequest.getCensoredEventRequestIdentifier()); + Map patientCensoredEventsById = + patientCensoredEvents.stream() + .collect(Collectors.toMap(ClinicalEventServiceImpl::getKey, Function.identity())); + + return patientStartEvents.stream() + .flatMap( + event -> { + ClinicalData clinicalDataMonths = + buildClinicalSurvivalMonths( + attributeIdPrefix, + event, + survivalRequest, + patientEndEventsById, + patientCensoredEventsById); + if (clinicalDataMonths == null) return Stream.empty(); + ClinicalData clinicalDataStatus = + buildClinicalSurvivalStatus(attributeIdPrefix, event, patientEndEventsById); + + return Stream.of(clinicalDataMonths, clinicalDataStatus); + }) + .toList(); + } + + @Override + public List getClinicalEventsMeta( + List studyIds, List patientIds, List clinicalEvents) { + return clinicalEventRepository.getClinicalEventsMeta(studyIds, patientIds, clinicalEvents); + } + + private static String getKey(ClinicalEvent clinicalEvent) { + return clinicalEvent.getStudyId() + clinicalEvent.getPatientId(); + } + + private static List getToClinicalEvents( + ClinicalEventRequestIdentifier clinicalEventRequestIdentifier) { + return clinicalEventRequestIdentifier.getClinicalEventRequests().stream() + .map( + x -> { + ClinicalEvent clinicalEvent = new ClinicalEvent(); + clinicalEvent.setEventType(x.getEventType()); + clinicalEvent.setAttributes(x.getAttributes()); + + return clinicalEvent; + }) + .toList(); + } + + private ToIntFunction getPositionIdentifier(OccurrencePosition position) { + return position.equals(OccurrencePosition.FIRST) + ? ClinicalEvent::getStartDate + : ClinicalEvent::getStopDate; + } + + private List filterClinicalEvents( + List patientEvents, + ClinicalEventRequestIdentifier clinicalEventRequestIdentifier) { + List filteredStudyIds = new ArrayList<>(); + List filteredPatientIds = new ArrayList<>(); + for (ClinicalEvent clinicalEvent : patientEvents) { + filteredStudyIds.add(clinicalEvent.getStudyId()); + filteredPatientIds.add(clinicalEvent.getPatientId()); + } + + List clinicalEventsMeta = new ArrayList<>(); + if (clinicalEventRequestIdentifier != null) { + clinicalEventsMeta = getToClinicalEvents(clinicalEventRequestIdentifier); + } + + // only fetch end timeline events for patients that have endClinicalEventsMeta and start + // timeline events + List queriedPatientEvents = new ArrayList<>(); + if (CollectionUtils.isNotEmpty(filteredStudyIds)) { + queriedPatientEvents = + clinicalEventRepository.getTimelineEvents( + filteredStudyIds, filteredPatientIds, clinicalEventsMeta); + } + return queriedPatientEvents; + } + + private ClinicalData buildClinicalSurvivalMonths( + String attributeIdPrefix, + ClinicalEvent event, + SurvivalRequest survivalRequest, + Map patientEndEventsById, + Map patientCensoredEventsById) { + final String SURVIVAL_MONTH_ATTRIBUTE = attributeIdPrefix + "_MONTHS"; + ClinicalData clinicalDataMonths = new ClinicalData(); + clinicalDataMonths.setStudyId(event.getStudyId()); + clinicalDataMonths.setPatientId(event.getPatientId()); + clinicalDataMonths.setAttrId(SURVIVAL_MONTH_ATTRIBUTE); + + ToIntFunction startPositionIdentifier = + getPositionIdentifier(survivalRequest.getStartEventRequestIdentifier().getPosition()); + ToIntFunction endPositionIdentifier = + survivalRequest.getEndEventRequestIdentifier() == null + ? ClinicalEvent::getStopDate + : getPositionIdentifier(survivalRequest.getEndEventRequestIdentifier().getPosition()); + ToIntFunction censoredPositionIdentifier = + survivalRequest.getCensoredEventRequestIdentifier() == null + ? ClinicalEvent::getStopDate + : getPositionIdentifier( + survivalRequest.getCensoredEventRequestIdentifier().getPosition()); + + int startDate = startPositionIdentifier.applyAsInt(event); + int endDate; + if (patientEndEventsById.containsKey(getKey(event))) { + endDate = endPositionIdentifier.applyAsInt(patientEndEventsById.get(getKey(event))); + } else { + // ignore cases where patient does not have censored timeline events or + // stop date of start event is less than start date of censored events + if (!patientCensoredEventsById.containsKey(getKey(event)) + || startDate + >= censoredPositionIdentifier.applyAsInt( + patientCensoredEventsById.get(getKey(event)))) { + return null; + } + + endDate = censoredPositionIdentifier.applyAsInt(patientCensoredEventsById.get(getKey(event))); + } + final String SURVIVAL_MONTH = String.valueOf((endDate - startDate) / 30.4); + clinicalDataMonths.setAttrValue(SURVIVAL_MONTH); + + return clinicalDataMonths; + } + + private ClinicalData buildClinicalSurvivalStatus( + String attributeIdPrefix, + ClinicalEvent event, + Map patientEndEventsById) { + + ClinicalData clinicalDataStatus = new ClinicalData(); + clinicalDataStatus.setStudyId(event.getStudyId()); + clinicalDataStatus.setPatientId(event.getPatientId()); + clinicalDataStatus.setAttrId(attributeIdPrefix + "_STATUS"); + + if (patientEndEventsById.containsKey(getKey(event))) { + clinicalDataStatus.setAttrValue("1:EVENT"); + } else { + clinicalDataStatus.setAttrValue("0:CENSORED"); + } + + return clinicalDataStatus; + } +} diff --git a/src/main/java/org/cbioportal/legacy/service/impl/CoExpressionServiceImpl.java b/src/main/java/org/cbioportal/legacy/service/impl/CoExpressionServiceImpl.java new file mode 100644 index 00000000000..1d8a7bb00ab --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/impl/CoExpressionServiceImpl.java @@ -0,0 +1,343 @@ +package org.cbioportal.legacy.service.impl; + +import java.util.*; +import java.util.Map.Entry; +import java.util.concurrent.CompletableFuture; +import java.util.function.Function; +import java.util.stream.Collectors; +import org.cbioportal.legacy.model.CoExpression; +import org.cbioportal.legacy.model.EntityType; +import org.cbioportal.legacy.model.MolecularAlteration; +import org.cbioportal.legacy.model.MolecularData; +import org.cbioportal.legacy.model.MolecularProfile; +import org.cbioportal.legacy.model.MolecularProfileSamples; +import org.cbioportal.legacy.model.Sample; +import org.cbioportal.legacy.persistence.MolecularDataRepository; +import org.cbioportal.legacy.persistence.SampleListRepository; +import org.cbioportal.legacy.service.CoExpressionService; +import org.cbioportal.legacy.service.GenesetDataService; +import org.cbioportal.legacy.service.MolecularDataService; +import org.cbioportal.legacy.service.MolecularProfileService; +import org.cbioportal.legacy.service.SampleService; +import org.cbioportal.legacy.service.exception.GeneNotFoundException; +import org.cbioportal.legacy.service.exception.GenesetNotFoundException; +import org.cbioportal.legacy.service.exception.MolecularProfileNotFoundException; +import org.cbioportal.legacy.service.exception.SampleListNotFoundException; +import org.cbioportal.legacy.service.util.CoExpressionAsyncMethods; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class CoExpressionServiceImpl implements CoExpressionService { + + @Autowired private CoExpressionAsyncMethods asyncMethods; + @Autowired private MolecularDataService molecularDataService; + @Autowired private GenesetDataService genesetDataService; + @Autowired private MolecularProfileService molecularProfileService; + @Autowired private SampleListRepository sampleListRepository; + @Autowired private MolecularDataRepository molecularDataRepository; + @Autowired private SampleService sampleService; + + @Override + // transaction needs to be setup here in order to return Iterable from molecularDataService in + // fetchCoExpressions + @Transactional(readOnly = true) + public List getCoExpressions( + String geneticEntityId, + EntityType geneticEntityType, + String sampleListId, + String molecularProfileIdA, + String molecularProfileIdB, + Double threshold) + throws MolecularProfileNotFoundException, + SampleListNotFoundException, + GenesetNotFoundException, + GeneNotFoundException { + + if (molecularProfileIdA.equals(molecularProfileIdB)) { + return getCoExpressions( + molecularProfileIdA, sampleListId, geneticEntityId, geneticEntityType, threshold); + } + + List computedCoExpressions = null; + List molecularDataListA = null; + List molecularDataListB = null; + if (geneticEntityType.equals(EntityType.GENE)) { + molecularDataListA = + molecularDataService.getMolecularData(molecularProfileIdA, sampleListId, null, "SUMMARY"); + } else if (geneticEntityType.equals(EntityType.GENESET)) { + molecularDataListA = + genesetDataService.fetchGenesetData(molecularProfileIdA, sampleListId, null); + } + MolecularProfile molecularProfileB = + molecularProfileService.getMolecularProfile(molecularProfileIdB); + Boolean isMolecularProfileBOfGenesetType = + molecularProfileB + .getMolecularAlterationType() + .equals(MolecularProfile.MolecularAlterationType.GENESET_SCORE); + if (isMolecularProfileBOfGenesetType) { + molecularDataListB = + genesetDataService.fetchGenesetData(molecularProfileIdB, sampleListId, null); + } else { + molecularDataListB = + molecularDataService.getMolecularData(molecularProfileIdB, sampleListId, null, "SUMMARY"); + } + Set samplesA = + new HashSet( + (molecularDataListA.stream().map(g -> g.getSampleId()).collect(Collectors.toList()))); + Set samplesB = + new HashSet( + (molecularDataListB.stream().map(g -> g.getSampleId()).collect(Collectors.toList()))); + Set sharedSamples = new HashSet(samplesA); // use the copy constructor + sharedSamples.retainAll(samplesB); + List finalmolecularDataListA = + molecularDataListA.stream() + .filter(p -> sharedSamples.contains(p.getSampleId())) + .collect(Collectors.toList()); + List finalmolecularDataListB = + molecularDataListB.stream() + .filter(p -> sharedSamples.contains(p.getSampleId())) + .collect(Collectors.toList()); + + return computeCoExpressionsFromMolecularData( + finalmolecularDataListB, finalmolecularDataListA, geneticEntityId, threshold); + } + + @Override + public List getCoExpressions( + String molecularProfileId, + String sampleListId, + String geneticEntityId, + EntityType geneticEntityType, + Double threshold) + throws MolecularProfileNotFoundException, GenesetNotFoundException, GeneNotFoundException { + + List sampleIds = sampleListRepository.getAllSampleIdsInSampleList(sampleListId); + if (sampleIds.isEmpty()) { + return Collections.emptyList(); + } + + return fetchCoExpressions( + molecularProfileId, sampleIds, geneticEntityId, geneticEntityType, threshold); + } + + @Override + public List fetchCoExpressions( + String molecularProfileId, + List sampleIds, + String queryGeneticEntityId, + EntityType geneticEntityType, + Double threshold) + throws MolecularProfileNotFoundException, GenesetNotFoundException, GeneNotFoundException { + + // For the purpose of the CoExpression computation, we separate the MolecularAlteration + // (genetic_alteration table record) for the query gene/geneset from the MolecularAlteration(s) + // for the remaining genes/geneset in the profile. + MolecularAlteration queryMolecularDataList = null; + Iterable maItr = null; + if (geneticEntityType.equals(EntityType.GENE)) { + List queryGeneticEntityIds = Arrays.asList(Integer.valueOf(queryGeneticEntityId)); + maItr = + molecularDataService.getMolecularAlterations( + molecularProfileId, queryGeneticEntityIds, "SUMMARY"); + } else if (geneticEntityType.equals(EntityType.GENESET)) { + List queryGeneticEntityIds = Arrays.asList(queryGeneticEntityId); + maItr = genesetDataService.getGenesetAlterations(molecularProfileId, queryGeneticEntityIds); + } + for (MolecularAlteration ma : maItr) { + queryMolecularDataList = ma; + } + if (queryMolecularDataList == null) { + return Collections.emptyList(); + } + + // These next few lines are used to build a map of internal sample ids to + // indices into the genetic_alteration.VALUES column. Recall this column + // of the genetic_alteration table is a comma separated list of scalar values. + // Each value in this list is associated with a sample at the same position found in + // the genetic_profile_samples.ORDERED_SAMPLE_LIST column. + MolecularProfileSamples commaSeparatedSampleIdsOfMolecularProfile = + molecularDataRepository.getCommaSeparatedSampleIdsOfMolecularProfile(molecularProfileId); + List internalSampleIds = + Arrays.stream(commaSeparatedSampleIdsOfMolecularProfile.getSplitSampleIds()) + .mapToInt(Integer::parseInt) + .boxed() + .collect(Collectors.toList()); + Map internalSampleIdToIndexMap = new HashMap<>(); + for (int lc = 0; lc < internalSampleIds.size(); lc++) { + internalSampleIdToIndexMap.put(internalSampleIds.get(lc), lc); + } + + // These next few lines build a list of Sample from the sampleIds method parameter (the user + // query). + // A map is then built of internal sample ids to indices into the Sample list (although the map + // is + // only used to quickly identify if a sample in the molecular profile is part of the user query + // - see below). + MolecularProfile molecularProfile = + molecularProfileService.getMolecularProfile(molecularProfileId); + List studyIds = new ArrayList<>(); + sampleIds.forEach(s -> studyIds.add(molecularProfile.getCancerStudyIdentifier())); + List samples = sampleService.fetchSamples(studyIds, sampleIds, "ID"); + Map selectedSampleIdsMap = new HashMap<>(); + for (int lc = 0; lc < samples.size(); lc++) { + selectedSampleIdsMap.put(samples.get(lc).getInternalId(), lc); + } + + // These next few lines build a list of indices into the genetic_alteration.VALUES + // column by iterating over all the samples in the molecular profile (method parameter) + // and selecting only samples that are included in the user query. + Set includedIndexes = new HashSet<>(); + for (Integer internalSampleId : internalSampleIds) { + if (selectedSampleIdsMap.containsKey(internalSampleId)) { + includedIndexes.add(internalSampleIdToIndexMap.get(internalSampleId)); + } + } + + // These next few lines filter out genetic_alteration values from the query gene/geneset + // genetic_alteration.VALUES column by considering only the indices of the samples in the user + // query. + List queryValues = Arrays.asList(queryMolecularDataList.getSplitValues()); + List includedQueryValues = + includedIndexes.stream().map(index -> queryValues.get(index)).collect(Collectors.toList()); + + // Get an iterator to all the MolecularAlteration (genetic_alteration table records) in the + // profile + if (geneticEntityType.equals(EntityType.GENE)) { + maItr = molecularDataService.getMolecularAlterations(molecularProfileId, null, "SUMMARY"); + } else if (geneticEntityType.equals(EntityType.GENESET)) { + maItr = genesetDataService.getGenesetAlterations(molecularProfileId, null); + } + + // For each MolecularAlteration in the profile, compute a CoExpression to return. + // If the MolecularAlteration is for the query gene/geneset, skip it. Otherwise, + // filter out genetic_alteration values from genetic_alteration.VALUES + // by considering oly the indices of the samples in the user query. + List> returnFutures = new ArrayList<>(); + for (MolecularAlteration ma : maItr) { + String entityId = ma.getStableId(); + if (entityId.equals(queryGeneticEntityId)) { + continue; + } + List internalValues = new ArrayList<>(Arrays.asList(ma.getSplitValues())); + List values = + includedIndexes.stream() + .map(index -> internalValues.get(index)) + .collect(Collectors.toList()); + + CompletableFuture future = + asyncMethods.computeCoExpression(entityId, values, includedQueryValues, threshold); + returnFutures.add(future); + } + return returnFutures.stream() + .map(CompletableFuture::join) + .filter(Objects::nonNull) + .collect(Collectors.toList()); + } + + @Override + // transaction needs to be setup here in order to return Iterable from molecularDataService in + // fetchCoExpressions + @Transactional(readOnly = true) + public List fetchCoExpressions( + String geneticEntityId, + EntityType geneticEntityType, + List sampleIds, + String molecularProfileIdA, + String molecularProfileIdB, + Double threshold) + throws MolecularProfileNotFoundException, GenesetNotFoundException, GeneNotFoundException { + + if (molecularProfileIdA.equals(molecularProfileIdB)) { + return fetchCoExpressions( + molecularProfileIdA, sampleIds, geneticEntityId, geneticEntityType, threshold); + } + + List computedCoExpressions = null; + List molecularDataListA = null; + List molecularDataListB = null; + if (geneticEntityType.equals(EntityType.GENE)) { + molecularDataListA = + molecularDataService.fetchMolecularData(molecularProfileIdA, sampleIds, null, "SUMMARY"); + } else if (geneticEntityType.equals(EntityType.GENESET)) { + molecularDataListA = + genesetDataService.fetchGenesetData(molecularProfileIdA, sampleIds, null); + } + MolecularProfile molecularProfileB = + molecularProfileService.getMolecularProfile(molecularProfileIdB); + Boolean isMolecularProfileBOfGenesetType = + molecularProfileB + .getMolecularAlterationType() + .equals(MolecularProfile.MolecularAlterationType.GENESET_SCORE); + if (isMolecularProfileBOfGenesetType) { + molecularDataListB = + genesetDataService.fetchGenesetData(molecularProfileIdB, sampleIds, null).stream() + .collect(Collectors.toList()); + } else { + molecularDataListB = + molecularDataService + .fetchMolecularData(molecularProfileIdB, sampleIds, null, "SUMMARY") + .stream() + .collect(Collectors.toList()); + } + return computeCoExpressionsFromMolecularData( + molecularDataListB, molecularDataListA, geneticEntityId, threshold); + } + + private List computeCoExpressionsFromMolecularData( + List molecularDataListB, + List molecularDataListA, + String queryGeneticEntityId, + Double threshold) + throws GenesetNotFoundException, GeneNotFoundException { + + Map> molecularDataMapA = + molecularDataListA.stream().collect(Collectors.groupingBy(MolecularData::getStableId)); + Map> molecularDataMapB = + molecularDataListB.stream().collect(Collectors.groupingBy(MolecularData::getStableId)); + + if (!molecularDataMapA.keySet().contains(queryGeneticEntityId)) { + return Collections.emptyList(); + } + + List finalMolecularDataListA = + (List) molecularDataMapA.remove(queryGeneticEntityId); + if (molecularDataMapB.get(queryGeneticEntityId) != null) { + List finalMolecularDataListB = + (List) molecularDataMapB.remove(queryGeneticEntityId); + if (finalMolecularDataListB == null) { + return Collections.emptyList(); + } + } + + List> returnFutures = new ArrayList<>(); + + Map dataMapA = + finalMolecularDataListA.stream() + .collect(Collectors.toMap(MolecularData::getSampleId, Function.identity())); + + for (Entry> entry : molecularDataMapB.entrySet()) { + List valuesA = new ArrayList<>(); + List valuesB = new ArrayList<>(); + + entry.getValue().stream() + .forEach( + molecularData -> { + if (dataMapA.containsKey(molecularData.getSampleId())) { + valuesA.add(molecularData.getValue()); + valuesB.add(dataMapA.get(molecularData.getSampleId()).getValue()); + } + }); + + CompletableFuture future = + asyncMethods.computeCoExpression(entry.getKey(), valuesA, valuesB, threshold); + returnFutures.add(future); + } + + return returnFutures.stream() + .map(CompletableFuture::join) + .filter(Objects::nonNull) + .collect(Collectors.toList()); + } +} diff --git a/src/main/java/org/cbioportal/legacy/service/impl/CopyNumberSegmentServiceImpl.java b/src/main/java/org/cbioportal/legacy/service/impl/CopyNumberSegmentServiceImpl.java new file mode 100644 index 00000000000..009004ce8b7 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/impl/CopyNumberSegmentServiceImpl.java @@ -0,0 +1,71 @@ +package org.cbioportal.legacy.service.impl; + +import java.util.List; +import org.cbioportal.legacy.model.CopyNumberSeg; +import org.cbioportal.legacy.model.meta.BaseMeta; +import org.cbioportal.legacy.persistence.CopyNumberSegmentRepository; +import org.cbioportal.legacy.service.CopyNumberSegmentService; +import org.cbioportal.legacy.service.SampleService; +import org.cbioportal.legacy.service.exception.SampleNotFoundException; +import org.cbioportal.legacy.service.exception.StudyNotFoundException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class CopyNumberSegmentServiceImpl implements CopyNumberSegmentService { + + @Autowired private CopyNumberSegmentRepository copyNumberSegmentRepository; + @Autowired private SampleService sampleService; + + @Override + public List getCopyNumberSegmentsInSampleInStudy( + String studyId, + String sampleId, + String chromosome, + String projection, + Integer pageSize, + Integer pageNumber, + String sortBy, + String direction) + throws SampleNotFoundException, StudyNotFoundException { + + sampleService.getSampleInStudy(studyId, sampleId); + + return copyNumberSegmentRepository.getCopyNumberSegmentsInSampleInStudy( + studyId, sampleId, chromosome, projection, pageSize, pageNumber, sortBy, direction); + } + + @Override + public BaseMeta getMetaCopyNumberSegmentsInSampleInStudy( + String studyId, String sampleId, String chromosome) + throws SampleNotFoundException, StudyNotFoundException { + + sampleService.getSampleInStudy(studyId, sampleId); + + return copyNumberSegmentRepository.getMetaCopyNumberSegmentsInSampleInStudy( + studyId, sampleId, chromosome); + } + + @Override + public List fetchCopyNumberSegments( + List studyIds, List sampleIds, String chromosome, String projection) { + + return copyNumberSegmentRepository.fetchCopyNumberSegments( + studyIds, sampleIds, chromosome, projection); + } + + @Override + public BaseMeta fetchMetaCopyNumberSegments( + List studyIds, List sampleIds, String chromsome) { + + return copyNumberSegmentRepository.fetchMetaCopyNumberSegments(studyIds, sampleIds, chromsome); + } + + @Override + public List getCopyNumberSegmentsBySampleListId( + String studyId, String sampleListId, String chromosome, String projection) { + + return copyNumberSegmentRepository.getCopyNumberSegmentsBySampleListId( + studyId, sampleListId, chromosome, projection); + } +} diff --git a/src/main/java/org/cbioportal/legacy/service/impl/CosmicCountServiceImpl.java b/src/main/java/org/cbioportal/legacy/service/impl/CosmicCountServiceImpl.java new file mode 100644 index 00000000000..c8558492300 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/impl/CosmicCountServiceImpl.java @@ -0,0 +1,20 @@ +package org.cbioportal.legacy.service.impl; + +import java.util.List; +import org.cbioportal.legacy.model.CosmicMutation; +import org.cbioportal.legacy.persistence.CosmicCountRepository; +import org.cbioportal.legacy.service.CosmicCountService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class CosmicCountServiceImpl implements CosmicCountService { + + @Autowired private CosmicCountRepository cosmicCountRepository; + + @Override + public List fetchCosmicCountsByKeywords(List keywords) { + + return cosmicCountRepository.fetchCosmicCountsByKeywords(keywords); + } +} diff --git a/src/main/java/org/cbioportal/legacy/service/impl/CustomDataServiceImpl.java b/src/main/java/org/cbioportal/legacy/service/impl/CustomDataServiceImpl.java new file mode 100644 index 00000000000..166661c1274 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/impl/CustomDataServiceImpl.java @@ -0,0 +1,59 @@ +package org.cbioportal.legacy.service.impl; + +import com.fasterxml.jackson.databind.ObjectMapper; +import java.util.List; +import java.util.Map; +import java.util.concurrent.CompletableFuture; +import java.util.stream.Collectors; +import org.cbioportal.legacy.service.CustomDataService; +import org.cbioportal.legacy.service.util.CustomDataSession; +import org.cbioportal.legacy.service.util.SessionServiceRequestHandler; +import org.cbioportal.legacy.utils.removeme.Session; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class CustomDataServiceImpl implements CustomDataService { + @Autowired private SessionServiceRequestHandler sessionServiceRequestHandler; + + @Autowired private ObjectMapper sessionServiceObjectMapper; + + /** + * Retrieve CustomDataSession from session service for custom data attributes. + * + * @param customAttributeIds - attribute id/hash of custom data used as session service key. + * @return Map of custom data attribute id to the CustomDataSession + */ + @Override + public Map getCustomDataSessions(List customAttributeIds) { + Map> postFuturesMap = + customAttributeIds.stream() + .collect( + Collectors.toMap( + attributeId -> attributeId, + attributeId -> + CompletableFuture.supplyAsync( + () -> { + try { + String customDataSessionJson = + sessionServiceRequestHandler.getSessionDataJson( + Session.SessionType.custom_data, attributeId); + return sessionServiceObjectMapper.readValue( + customDataSessionJson, CustomDataSession.class); + } catch (Exception e) { + return null; + } + }))); + + CompletableFuture.allOf( + postFuturesMap.values().toArray(new CompletableFuture[postFuturesMap.size()])) + .join(); + + Map customDataSessions = + postFuturesMap.entrySet().stream() + .filter(entry -> entry.getValue().join() != null) + .collect(Collectors.toMap(entry -> entry.getKey(), entry -> entry.getValue().join())); + + return customDataSessions; + } +} diff --git a/src/main/java/org/cbioportal/legacy/service/impl/DiscreteCopyNumberServiceImpl.java b/src/main/java/org/cbioportal/legacy/service/impl/DiscreteCopyNumberServiceImpl.java new file mode 100644 index 00000000000..acd4b0627df --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/impl/DiscreteCopyNumberServiceImpl.java @@ -0,0 +1,291 @@ +package org.cbioportal.legacy.service.impl; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Optional; +import java.util.stream.Collectors; +import org.cbioportal.legacy.model.CNA; +import org.cbioportal.legacy.model.CopyNumberCount; +import org.cbioportal.legacy.model.CopyNumberCountByGene; +import org.cbioportal.legacy.model.DiscreteCopyNumberData; +import org.cbioportal.legacy.model.GeneFilterQuery; +import org.cbioportal.legacy.model.GeneMolecularData; +import org.cbioportal.legacy.model.MolecularProfile; +import org.cbioportal.legacy.model.meta.BaseMeta; +import org.cbioportal.legacy.persistence.DiscreteCopyNumberRepository; +import org.cbioportal.legacy.service.DiscreteCopyNumberService; +import org.cbioportal.legacy.service.MolecularDataService; +import org.cbioportal.legacy.service.MolecularProfileService; +import org.cbioportal.legacy.service.exception.MolecularProfileNotFoundException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class DiscreteCopyNumberServiceImpl implements DiscreteCopyNumberService { + + @Autowired private DiscreteCopyNumberRepository discreteCopyNumberRepository; + @Autowired private MolecularDataService molecularDataService; + @Autowired private MolecularProfileService molecularProfileService; + + @Override + public List getDiscreteCopyNumbersInMolecularProfileBySampleListId( + String molecularProfileId, + String sampleListId, + List entrezGeneIds, + List alterationTypes, + String projection) + throws MolecularProfileNotFoundException { + + validateMolecularProfile(molecularProfileId); + if (isHomdelOrAmpOnly(alterationTypes)) { + + return discreteCopyNumberRepository.getDiscreteCopyNumbersInMolecularProfileBySampleListId( + molecularProfileId, sampleListId, entrezGeneIds, alterationTypes, projection); + } + + return molecularDataService + .getMolecularData(molecularProfileId, sampleListId, entrezGeneIds, projection) + .stream() + .filter(g -> isValidAlteration(alterationTypes, g)) + .map(this::convert) + .collect(Collectors.toList()); + } + + @Override + public BaseMeta getMetaDiscreteCopyNumbersInMolecularProfileBySampleListId( + String molecularProfileId, + String sampleListId, + List entrezGeneIds, + List alterationTypes) + throws MolecularProfileNotFoundException { + + validateMolecularProfile(molecularProfileId); + if (isHomdelOrAmpOnly(alterationTypes)) { + return discreteCopyNumberRepository + .getMetaDiscreteCopyNumbersInMolecularProfileBySampleListId( + molecularProfileId, sampleListId, entrezGeneIds, alterationTypes); + } + + long totalCount = + molecularDataService + .getMolecularData(molecularProfileId, sampleListId, entrezGeneIds, "ID") + .stream() + .filter(g -> isValidAlteration(alterationTypes, g)) + .count(); + + BaseMeta baseMeta = new BaseMeta(); + baseMeta.setTotalCount(Math.toIntExact(totalCount)); + + return baseMeta; + } + + @Override + public List fetchDiscreteCopyNumbersInMolecularProfile( + String molecularProfileId, + List sampleIds, + List entrezGeneIds, + List alterationTypes, + String projection) + throws MolecularProfileNotFoundException { + + validateMolecularProfile(molecularProfileId); + if (isHomdelOrAmpOnly(alterationTypes)) { + return discreteCopyNumberRepository.fetchDiscreteCopyNumbersInMolecularProfile( + molecularProfileId, sampleIds, entrezGeneIds, alterationTypes, projection); + } + + return molecularDataService + .fetchMolecularData(molecularProfileId, sampleIds, entrezGeneIds, projection) + .stream() + .filter(g -> isValidAlteration(alterationTypes, g)) + .map(this::convert) + .collect(Collectors.toList()); + } + + @Override + public List getDiscreteCopyNumbersInMultipleMolecularProfiles( + List molecularProfileIds, + List sampleIds, + List entrezGeneIds, + List alterationTypes, + String projection) { + + if (isHomdelOrAmpOnly(alterationTypes)) { + return discreteCopyNumberRepository.getDiscreteCopyNumbersInMultipleMolecularProfiles( + molecularProfileIds, sampleIds, entrezGeneIds, alterationTypes, projection); + } + + return molecularDataService + .getMolecularDataInMultipleMolecularProfiles( + molecularProfileIds, sampleIds, entrezGeneIds, projection) + .stream() + .filter(g -> isValidAlteration(alterationTypes, g)) + .map(this::convert) + .collect(Collectors.toList()); + } + + @Override + public List + getDiscreteCopyNumbersInMultipleMolecularProfilesByGeneQueries( + List molecularProfileIds, + List sampleIds, + List geneQueries, + String projection) { + + List cnas = + geneQueries.stream() + .map(q -> q.getAlterations()) + .flatMap(List::stream) + .collect(Collectors.toList()); + if (cnas.isEmpty()) return Collections.emptyList(); + + if (isHomdelOrAmpOnlyCna(cnas)) { + return discreteCopyNumberRepository + .getDiscreteCopyNumbersInMultipleMolecularProfilesByGeneQueries( + molecularProfileIds, sampleIds, geneQueries, projection); + } + + return molecularDataService + .getMolecularDataInMultipleMolecularProfilesByGeneQueries( + molecularProfileIds, sampleIds, geneQueries, projection) + .stream() + .map(this::convert) + .collect(Collectors.toList()); + } + + @Override + public BaseMeta fetchMetaDiscreteCopyNumbersInMolecularProfile( + String molecularProfileId, + List sampleIds, + List entrezGeneIds, + List alterationTypes) + throws MolecularProfileNotFoundException { + + validateMolecularProfile(molecularProfileId); + if (isHomdelOrAmpOnly(alterationTypes)) { + return discreteCopyNumberRepository.fetchMetaDiscreteCopyNumbersInMolecularProfile( + molecularProfileId, sampleIds, entrezGeneIds, alterationTypes); + } + + long totalCount = + molecularDataService + .fetchMolecularData(molecularProfileId, sampleIds, entrezGeneIds, "ID") + .stream() + .filter(g -> isValidAlteration(alterationTypes, g)) + .count(); + + BaseMeta baseMeta = new BaseMeta(); + baseMeta.setTotalCount(Math.toIntExact(totalCount)); + + return baseMeta; + } + + @Override + public List getSampleCountByGeneAndAlterationAndSampleIds( + String molecularProfileId, + List sampleIds, + List entrezGeneIds, + List alterations) + throws MolecularProfileNotFoundException { + + validateMolecularProfile(molecularProfileId); + + return discreteCopyNumberRepository.getSampleCountByGeneAndAlterationAndSampleIds( + molecularProfileId, sampleIds, entrezGeneIds, alterations); + } + + @Override + public List fetchCopyNumberCounts( + String molecularProfileId, List entrezGeneIds, List alterations) + throws MolecularProfileNotFoundException { + + validateMolecularProfile(molecularProfileId); + + Integer numberOfSamplesInMolecularProfile = + molecularDataService.getNumberOfSamplesInMolecularProfile(molecularProfileId); + List copyNumberSampleCountByGeneList = + getSampleCountByGeneAndAlterationAndSampleIds( + molecularProfileId, null, entrezGeneIds, alterations); + + List copyNumberCounts = new ArrayList<>(); + for (int i = 0; i < alterations.size(); i++) { + Integer alteration = alterations.get(i); + Integer entrezGeneId = entrezGeneIds.get(i); + + CopyNumberCount copyNumberCount = new CopyNumberCount(); + copyNumberCount.setMolecularProfileId(molecularProfileId); + copyNumberCount.setEntrezGeneId(entrezGeneId); + copyNumberCount.setAlteration(alteration); + copyNumberCount.setNumberOfSamples(numberOfSamplesInMolecularProfile); + + Optional copyNumberSampleCountByGene = + copyNumberSampleCountByGeneList.stream() + .filter( + p -> + p.getEntrezGeneId().equals(entrezGeneId) + && p.getAlteration().equals(alteration)) + .findFirst(); + copyNumberSampleCountByGene.ifPresent( + m -> copyNumberCount.setNumberOfSamplesWithAlterationInGene(m.getNumberOfAlteredCases())); + + copyNumberCounts.add(copyNumberCount); + } + + return copyNumberCounts; + } + + private DiscreteCopyNumberData convert(GeneMolecularData molecularData) { + + DiscreteCopyNumberData discreteCopyNumberData = new DiscreteCopyNumberData(); + discreteCopyNumberData.setMolecularProfileId(molecularData.getMolecularProfileId()); + discreteCopyNumberData.setStudyId(molecularData.getStudyId()); + discreteCopyNumberData.setPatientId(molecularData.getPatientId()); + discreteCopyNumberData.setSampleId(molecularData.getSampleId()); + discreteCopyNumberData.setEntrezGeneId(molecularData.getEntrezGeneId()); + discreteCopyNumberData.setGene(molecularData.getGene()); + discreteCopyNumberData.setAlteration(Integer.parseInt(molecularData.getValue())); + + return discreteCopyNumberData; + } + + private boolean isHomdelOrAmpOnly(List alterationTypes) { + return !alterationTypes.contains(-1) + && !alterationTypes.contains(0) + && !alterationTypes.contains(1); + } + + private boolean isHomdelOrAmpOnlyCna(List alterationTypes) { + return !alterationTypes.contains(CNA.HETLOSS) + && !alterationTypes.contains(CNA.DIPLOID) + && !alterationTypes.contains(CNA.GAIN); + } + + private boolean isValidAlteration( + List alterationTypes, GeneMolecularData molecularData) { + + boolean result; + try { + result = alterationTypes.contains(Integer.parseInt(molecularData.getValue())); + } catch (NumberFormatException ex) { + result = false; + } + return result; + } + + private MolecularProfile validateMolecularProfile(String molecularProfileId) + throws MolecularProfileNotFoundException { + + MolecularProfile molecularProfile = + molecularProfileService.getMolecularProfile(molecularProfileId); + + if (!molecularProfile + .getMolecularAlterationType() + .equals(MolecularProfile.MolecularAlterationType.COPY_NUMBER_ALTERATION) + || !MolecularProfile.DataType.DISCRETE.name().equals(molecularProfile.getDatatype())) { + throw new MolecularProfileNotFoundException(molecularProfileId); + } + + return molecularProfile; + } +} diff --git a/src/main/java/org/cbioportal/legacy/service/impl/EhcacheStatisticsServiceImpl.java b/src/main/java/org/cbioportal/legacy/service/impl/EhcacheStatisticsServiceImpl.java new file mode 100644 index 00000000000..2c104b50be7 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/impl/EhcacheStatisticsServiceImpl.java @@ -0,0 +1,23 @@ +package org.cbioportal.legacy.service.impl; + +import org.cbioportal.legacy.persistence.util.EhcacheStatistics; +import org.cbioportal.legacy.utils.config.annotation.ConditionalOnProperty; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Primary; +import org.springframework.stereotype.Service; + +@Primary // if there is another CacheStatisticsService bean this one should be the one selected +@Service +@ConditionalOnProperty( + name = "persistence.cache_type", + havingValue = {"ehcache-heap", "ehcache-disk", "ehcache-hybrid"}) +public class EhcacheStatisticsServiceImpl extends CacheStatisticsServiceImpl { + + @Autowired public EhcacheStatistics ehcacheStatistics; + + @Override + public String getCacheStatistics() { + super.checkIfCacheStatisticsEndpointEnabled(); + return ehcacheStatistics.getCacheStatistics(); + } +} diff --git a/src/main/java/org/cbioportal/legacy/service/impl/ExpressionEnrichmentServiceImpl.java b/src/main/java/org/cbioportal/legacy/service/impl/ExpressionEnrichmentServiceImpl.java new file mode 100644 index 00000000000..6535670f0a0 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/impl/ExpressionEnrichmentServiceImpl.java @@ -0,0 +1,371 @@ +package org.cbioportal.legacy.service.impl; + +import java.math.BigDecimal; +import java.util.*; +import java.util.function.Function; +import java.util.stream.Collectors; +import org.apache.commons.lang3.BooleanUtils; +import org.cbioportal.legacy.model.EnrichmentType; +import org.cbioportal.legacy.model.Gene; +import org.cbioportal.legacy.model.GeneMolecularAlteration; +import org.cbioportal.legacy.model.GenericAssayBinaryEnrichment; +import org.cbioportal.legacy.model.GenericAssayCategoricalEnrichment; +import org.cbioportal.legacy.model.GenericAssayEnrichment; +import org.cbioportal.legacy.model.GenericAssayMolecularAlteration; +import org.cbioportal.legacy.model.GenomicEnrichment; +import org.cbioportal.legacy.model.MolecularProfile; +import org.cbioportal.legacy.model.MolecularProfile.MolecularAlterationType; +import org.cbioportal.legacy.model.MolecularProfileCaseIdentifier; +import org.cbioportal.legacy.model.Sample; +import org.cbioportal.legacy.model.meta.GenericAssayMeta; +import org.cbioportal.legacy.persistence.MolecularDataRepository; +import org.cbioportal.legacy.service.ExpressionEnrichmentService; +import org.cbioportal.legacy.service.GeneService; +import org.cbioportal.legacy.service.GenericAssayService; +import org.cbioportal.legacy.service.MolecularProfileService; +import org.cbioportal.legacy.service.SampleService; +import org.cbioportal.legacy.service.exception.MolecularProfileNotFoundException; +import org.cbioportal.legacy.service.util.ExpressionEnrichmentUtil; +import org.cbioportal.legacy.service.util.FisherExactTestCalculator; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class ExpressionEnrichmentServiceImpl implements ExpressionEnrichmentService { + + @Autowired private MolecularProfileService molecularProfileService; + @Autowired private MolecularDataRepository molecularDataRepository; + @Autowired private GeneService geneService; + @Autowired private ExpressionEnrichmentUtil expressionEnrichmentUtil; + @Autowired private GenericAssayService genericAssayService; + @Autowired private SampleService sampleService; + + @Autowired + private FisherExactTestCalculator fisherExactTestCalculator = new FisherExactTestCalculator(); + + @Override + // transaction needs to be setup here in order to return Iterable from + // molecularDataService in fetchCoExpressions + @Transactional(readOnly = true) + public List getGenomicEnrichments( + String molecularProfileId, + Map> molecularProfileCaseSets, + EnrichmentType enrichmentType) + throws MolecularProfileNotFoundException { + MolecularProfile molecularProfile = + molecularProfileService.getMolecularProfile(molecularProfileId); + List validGenomicMolecularAlterationTypes = + Arrays.asList( + MolecularAlterationType.MICRO_RNA_EXPRESSION, + MolecularAlterationType.MRNA_EXPRESSION, + MolecularAlterationType.MRNA_EXPRESSION_NORMALS, + MolecularAlterationType.RNA_EXPRESSION, + MolecularAlterationType.METHYLATION, + MolecularAlterationType.METHYLATION_BINARY, + MolecularAlterationType.PHOSPHORYLATION, + MolecularAlterationType.PROTEIN_LEVEL, + MolecularAlterationType.PROTEIN_ARRAY_PROTEIN_LEVEL, + MolecularAlterationType.PROTEIN_ARRAY_PHOSPHORYLATION); + validateMolecularProfile(molecularProfile, validGenomicMolecularAlterationTypes); + Iterable maItr = + molecularDataRepository.getGeneMolecularAlterationsIterableFast( + molecularProfile.getStableId()); + List expressionEnrichments = + expressionEnrichmentUtil.getEnrichments( + molecularProfile, molecularProfileCaseSets, enrichmentType, maItr); + List entrezGeneIds = + expressionEnrichments.stream() + .map(GenomicEnrichment::getEntrezGeneId) + .collect(Collectors.toList()); + Map> geneMapByEntrezId = + geneService + .fetchGenes( + entrezGeneIds.stream().map(Object::toString).collect(Collectors.toList()), + "ENTREZ_GENE_ID", + "SUMMARY") + .stream() + .collect(Collectors.groupingBy(Gene::getEntrezGeneId)); + return expressionEnrichments.stream() + // filter Enrichments having no gene reference object(this + // happens when multiple + // entrez ids map to same hugo gene symbol) + .filter( + expressionEnrichment -> + geneMapByEntrezId.containsKey(expressionEnrichment.getEntrezGeneId())) + .map( + expressionEnrichment -> { + Gene gene = geneMapByEntrezId.get(expressionEnrichment.getEntrezGeneId()).get(0); + expressionEnrichment.setHugoGeneSymbol(gene.getHugoGeneSymbol()); + return expressionEnrichment; + }) + .collect(Collectors.toList()); + } + + @Override + // transaction needs to be setup here in order to return Iterable from + // molecularDataRepository in getGenericAssayMolecularAlterationsIterable + @Transactional(readOnly = true) + public List getGenericAssayNumericalEnrichments( + String molecularProfileId, + Map> molecularProfileCaseSets, + EnrichmentType enrichmentType) + throws MolecularProfileNotFoundException { + MolecularProfile molecularProfile = + molecularProfileService.getMolecularProfile(molecularProfileId); + validateMolecularProfile( + molecularProfile, Arrays.asList(MolecularAlterationType.GENERIC_ASSAY)); + Iterable maItr = + molecularDataRepository.getGenericAssayMolecularAlterationsIterable( + molecularProfile.getStableId(), null, "SUMMARY"); + Map> filteredMolecularProfileCaseSets; + if (BooleanUtils.isTrue(molecularProfile.getPatientLevel())) { + // Build sampleIdToPatientIdMap to quick find if a sample has shared patientId with other + // samples + List sampleIds = + molecularProfileCaseSets.values().stream() + .flatMap(Collection::stream) + .map(MolecularProfileCaseIdentifier::getCaseId) + .collect(Collectors.toList()); + List studyIds = + Collections.nCopies(sampleIds.size(), molecularProfile.getCancerStudyIdentifier()); + List samples = sampleService.fetchSamples(studyIds, sampleIds, "SUMMARY"); + Map sampleIdToPatientIdMap = + samples.stream().collect(Collectors.toMap(Sample::getStableId, Sample::getPatientId)); + // Build filteredMolecularProfileCaseSets + filteredMolecularProfileCaseSets = new HashMap<>(); + for (Map.Entry> pair : + molecularProfileCaseSets.entrySet()) { + Set patientSet = new HashSet(); + List identifierListUniqueByPatientId = new ArrayList<>(); + for (MolecularProfileCaseIdentifier caseIdentifier : pair.getValue()) { + if (!patientSet.contains(sampleIdToPatientIdMap.get(caseIdentifier.getCaseId()))) { + identifierListUniqueByPatientId.add(caseIdentifier); + patientSet.add(sampleIdToPatientIdMap.get(caseIdentifier.getCaseId())); + } + } + filteredMolecularProfileCaseSets.put(pair.getKey(), identifierListUniqueByPatientId); + } + } else { + filteredMolecularProfileCaseSets = molecularProfileCaseSets; + } + List genericAssayEnrichments = + expressionEnrichmentUtil.getEnrichments( + molecularProfile, filteredMolecularProfileCaseSets, enrichmentType, maItr); + List getGenericAssayStableIds = + genericAssayEnrichments.stream() + .map(GenericAssayEnrichment::getStableId) + .collect(Collectors.toList()); + Map genericAssayMetaByStableId = + genericAssayService + .getGenericAssayMetaByStableIdsAndMolecularIds( + getGenericAssayStableIds, + getGenericAssayStableIds.stream() + .map(stableId -> molecularProfileId) + .collect(Collectors.toList()), + "SUMMARY") + .stream() + .collect(Collectors.toMap(GenericAssayMeta::getStableId, Function.identity())); + return genericAssayEnrichments.stream() + .map( + enrichmentDatum -> { + enrichmentDatum.setGenericEntityMetaProperties( + genericAssayMetaByStableId + .get(enrichmentDatum.getStableId()) + .getGenericEntityMetaProperties()); + return enrichmentDatum; + }) + .collect(Collectors.toList()); + } + + @Override + @Transactional(readOnly = true) + public List getGenericAssayBinaryEnrichments( + String molecularProfileId, + Map> molecularProfileCaseSets, + EnrichmentType enrichmentType) + throws MolecularProfileNotFoundException { + + // Validate and fetch molecular profile + MolecularProfile molecularProfile = + getAndValidateMolecularProfile(molecularProfileId, "BINARY"); + + // Get the molecular alterations for the provided profile + Iterable maItr = + molecularDataRepository.getGenericAssayMolecularAlterationsIterable( + molecularProfile.getStableId(), null, "SUMMARY"); + + // Filter the case sets based on molecular profile + Map> filteredMolecularProfileCaseSets = + filterMolecularProfileCaseSets(molecularProfile, molecularProfileCaseSets); + + // Obtain binary enrichments from the utility + List genericAssayBinaryEnrichments = + expressionEnrichmentUtil.getGenericAssayBinaryEnrichments( + molecularProfile, filteredMolecularProfileCaseSets, enrichmentType, maItr); + + // Calculate q-values for enrichments + calcQValues(genericAssayBinaryEnrichments); + + // Extract stable IDs from binary enrichments + List getGenericAssayStableIds = + genericAssayBinaryEnrichments.stream() + .map(GenericAssayEnrichment::getStableId) + .collect(Collectors.toList()); + + // Fetch metadata of generic assays by their stable IDs + Map genericAssayMetaByStableId = + getGenericAssayMetaByStableId(getGenericAssayStableIds, molecularProfileId); + + // Assign meta properties to each enrichment + return genericAssayBinaryEnrichments.stream() + .map( + enrichmentDatum -> { + enrichmentDatum.setGenericEntityMetaProperties( + genericAssayMetaByStableId + .get(enrichmentDatum.getStableId()) + .getGenericEntityMetaProperties()); + return enrichmentDatum; + }) + .collect(Collectors.toList()); + } + + @Override + @Transactional(readOnly = true) + public List getGenericAssayCategoricalEnrichments( + String molecularProfileId, + Map> molecularProfileCaseSets, + EnrichmentType enrichmentType) + throws MolecularProfileNotFoundException { + + MolecularProfile molecularProfile = + getAndValidateMolecularProfile(molecularProfileId, "CATEGORICAL"); + + Iterable maItr = + molecularDataRepository.getGenericAssayMolecularAlterationsIterable( + molecularProfile.getStableId(), null, "SUMMARY"); + + Map> filteredMolecularProfileCaseSets = + filterMolecularProfileCaseSets(molecularProfile, molecularProfileCaseSets); + + List genericAssayCategoricalEnrichments = + expressionEnrichmentUtil.getGenericAssayCategoricalEnrichments( + molecularProfile, filteredMolecularProfileCaseSets, enrichmentType, maItr); + + calcQValues(genericAssayCategoricalEnrichments); + + List getGenericAssayStableIds = + genericAssayCategoricalEnrichments.stream() + .map(GenericAssayEnrichment::getStableId) + .collect(Collectors.toList()); + Map genericAssayMetaByStableId = + getGenericAssayMetaByStableId(getGenericAssayStableIds, molecularProfileId); + + return genericAssayCategoricalEnrichments.stream() + .map( + enrichmentDatum -> { + enrichmentDatum.setGenericEntityMetaProperties( + genericAssayMetaByStableId + .get(enrichmentDatum.getStableId()) + .getGenericEntityMetaProperties()); + return enrichmentDatum; + }) + .collect(Collectors.toList()); + } + + private MolecularProfile getAndValidateMolecularProfile( + String molecularProfileId, String dataType) throws MolecularProfileNotFoundException { + MolecularProfile molecularProfile = + molecularProfileService.getMolecularProfile(molecularProfileId); + validateMolecularProfile( + molecularProfile, + Arrays.asList(MolecularProfile.MolecularAlterationType.GENERIC_ASSAY), + dataType); + return molecularProfile; + } + + private void validateMolecularProfile( + MolecularProfile molecularProfile, + List validMolecularAlterationTypes, + String dataType) + throws MolecularProfileNotFoundException { + if (!validMolecularAlterationTypes.contains(molecularProfile.getMolecularAlterationType())) { + // Check alteration type + throw new MolecularProfileNotFoundException(molecularProfile.getStableId()); + } + // Check datatype for binary or categorical + if (molecularProfile + .getMolecularAlterationType() + .equals(MolecularProfile.MolecularAlterationType.GENERIC_ASSAY) + && !molecularProfile.getDatatype().equals(dataType)) + throw new MolecularProfileNotFoundException(molecularProfile.getStableId()); + } + + private Map> filterMolecularProfileCaseSets( + MolecularProfile molecularProfile, + Map> molecularProfileCaseSets) { + if (BooleanUtils.isTrue(molecularProfile.getPatientLevel())) { + // If patient level, filter duplicates by patient id + // For now we only support sample level for samples + List sampleIds = + molecularProfileCaseSets.values().stream() + .flatMap(Collection::stream) + .map(MolecularProfileCaseIdentifier::getCaseId) + .collect(Collectors.toList()); + List studyIds = + Collections.nCopies(sampleIds.size(), molecularProfile.getCancerStudyIdentifier()); + List samples = sampleService.fetchSamples(studyIds, sampleIds, "ID"); + Map sampleIdToPatientIdMap = + samples.stream().collect(Collectors.toMap(Sample::getStableId, Sample::getPatientId)); + + Map> filteredMolecularProfileCaseSets = + new HashMap<>(); + for (Map.Entry> pair : + molecularProfileCaseSets.entrySet()) { + Set patientSet = new HashSet(); + List identifierListUniqueByPatientId = new ArrayList<>(); + for (MolecularProfileCaseIdentifier caseIdentifier : pair.getValue()) { + if (!patientSet.contains(sampleIdToPatientIdMap.get(caseIdentifier.getCaseId()))) { + identifierListUniqueByPatientId.add(caseIdentifier); + patientSet.add(sampleIdToPatientIdMap.get(caseIdentifier.getCaseId())); + } + } + filteredMolecularProfileCaseSets.put(pair.getKey(), identifierListUniqueByPatientId); + } + return filteredMolecularProfileCaseSets; + } else { + return molecularProfileCaseSets; + } + } + + private Map getGenericAssayMetaByStableId( + List stableIds, String molecularProfileId) { + return genericAssayService + .getGenericAssayMetaByStableIdsAndMolecularIds( + stableIds, + stableIds.stream().map(sid -> molecularProfileId).collect(Collectors.toList()), + "SUMMARY") + .stream() + .collect(Collectors.toMap(GenericAssayMeta::getStableId, Function.identity())); + } + + private void calcQValues(List enrichments) { + // Sort enrichments by pValue + Collections.sort(enrichments, GenericAssayEnrichment::compare); + BigDecimal[] pValues = enrichments.stream().map(T::getpValue).toArray(BigDecimal[]::new); + BigDecimal[] qValues = fisherExactTestCalculator.calcqValue(pValues); + // Assign q-values to enrichments + for (int i = 0; i < enrichments.size(); i++) { + enrichments.get(i).setqValue(qValues[i]); + } + } + + private void validateMolecularProfile( + MolecularProfile molecularProfile, + List validMolecularAlterationTypes) + throws MolecularProfileNotFoundException { + if (!validMolecularAlterationTypes.contains(molecularProfile.getMolecularAlterationType())) { + throw new MolecularProfileNotFoundException(molecularProfile.getStableId()); + } + } +} diff --git a/src/main/java/org/cbioportal/legacy/service/impl/GeneMemoizerServiceImpl.java b/src/main/java/org/cbioportal/legacy/service/impl/GeneMemoizerServiceImpl.java new file mode 100644 index 00000000000..e89c1db08c0 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/impl/GeneMemoizerServiceImpl.java @@ -0,0 +1,46 @@ +package org.cbioportal.legacy.service.impl; + +import java.util.*; +import org.cbioportal.legacy.model.ReferenceGenomeGene; +import org.cbioportal.legacy.service.GeneMemoizerService; +import org.cbioportal.legacy.service.StaticDataTimestampService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class GeneMemoizerServiceImpl implements GeneMemoizerService { + @Autowired private StaticDataTimestampService timestampService; + + private static final List TABLES = Arrays.asList("gene", "reference_genome_gene"); + + private static final Map> memoization = new HashMap<>(); + private static final Map expiry = new HashMap<>(); + private static final Object lock = new Object(); + + @Override + public List fetchGenes(String genomeName) { + synchronized (lock) { + if (memoization.containsKey(genomeName) && allTablesUpToDate(expiry.get(genomeName))) { + return memoization.get(genomeName); + } + } + + return null; + } + + private boolean allTablesUpToDate(Date expiration) { + Map timestamps = timestampService.getTimestampsAsDates(TABLES); + return TABLES.stream() + .map((table) -> timestamps.containsKey(table) && timestamps.get(table).before(expiration)) + .reduce((all, next) -> all && next) + .orElse(false); + } + + @Override + public void cacheGenes(List genes, String genomeName) { + synchronized (lock) { + expiry.put(genomeName, new Date()); + memoization.put(genomeName, genes); + } + } +} diff --git a/src/main/java/org/cbioportal/legacy/service/impl/GenePanelServiceImpl.java b/src/main/java/org/cbioportal/legacy/service/impl/GenePanelServiceImpl.java new file mode 100644 index 00000000000..0b0087aaaaf --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/impl/GenePanelServiceImpl.java @@ -0,0 +1,236 @@ +package org.cbioportal.legacy.service.impl; + +import static java.util.stream.Collectors.*; + +import java.util.*; +import java.util.function.Function; +import java.util.stream.Collectors; +import org.apache.commons.collections4.CollectionUtils; +import org.cbioportal.legacy.model.GenePanel; +import org.cbioportal.legacy.model.GenePanelData; +import org.cbioportal.legacy.model.GenePanelToGene; +import org.cbioportal.legacy.model.MolecularProfile; +import org.cbioportal.legacy.model.MolecularProfileCaseIdentifier; +import org.cbioportal.legacy.model.SampleList; +import org.cbioportal.legacy.model.meta.BaseMeta; +import org.cbioportal.legacy.persistence.GenePanelRepository; +import org.cbioportal.legacy.service.GenePanelService; +import org.cbioportal.legacy.service.MolecularProfileService; +import org.cbioportal.legacy.service.SampleListService; +import org.cbioportal.legacy.service.exception.GenePanelNotFoundException; +import org.cbioportal.legacy.service.exception.MolecularProfileNotFoundException; +import org.cbioportal.legacy.service.exception.SampleListNotFoundException; +import org.cbioportal.legacy.service.util.MolecularProfileUtil; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class GenePanelServiceImpl implements GenePanelService { + @Autowired private GenePanelRepository genePanelRepository; + @Autowired private MolecularProfileService molecularProfileService; + @Autowired private SampleListService sampleListService; + @Autowired private MolecularProfileUtil molecularProfileUtil; + + private final String SEQUENCED_LIST_SUFFIX = "_sequenced"; + + private final Function SAMPLE_IDENTIFIER_GENERATOR = + d -> d.getMolecularProfileId() + d.getSampleId(); + private final Function PATIENT_IDENTIFIER_GENERATOR = + d -> d.getMolecularProfileId() + d.getPatientId(); + + @Override + public List getAllGenePanels( + String projection, Integer pageSize, Integer pageNumber, String sortBy, String direction) { + + List genePanels = + genePanelRepository.getAllGenePanels(projection, pageSize, pageNumber, sortBy, direction); + + if (projection.equals("DETAILED")) { + + List genePanelToGeneList = + genePanelRepository.getGenesOfPanels( + genePanels.stream().map(GenePanel::getStableId).collect(toList())); + + genePanels.forEach( + g -> + g.setGenes( + genePanelToGeneList.stream() + .filter(p -> p.getGenePanelId().equals(g.getStableId())) + .collect(toList()))); + } + + return genePanels; + } + + @Override + public BaseMeta getMetaGenePanels() { + + return genePanelRepository.getMetaGenePanels(); + } + + @Override + public GenePanel getGenePanel(String genePanelId) throws GenePanelNotFoundException { + + GenePanel genePanel = genePanelRepository.getGenePanel(genePanelId); + if (genePanel == null) { + throw new GenePanelNotFoundException(genePanelId); + } + + genePanel.setGenes( + genePanelRepository.getGenesOfPanels(Collections.singletonList(genePanelId))); + return genePanel; + } + + @Override + public List fetchGenePanels(List genePanelIds, String projection) { + + List genePanels = genePanelRepository.fetchGenePanels(genePanelIds, projection); + + if (projection.equals("DETAILED")) { + + List genePanelToGeneList = + genePanelRepository.getGenesOfPanels( + genePanels.stream().map(GenePanel::getStableId).collect(toList())); + + genePanels.forEach( + g -> + g.setGenes( + genePanelToGeneList.stream() + .filter(p -> p.getGenePanelId().equals(g.getStableId())) + .collect(toList()))); + } + + return genePanels; + } + + @Override + public List getGenePanelData(String molecularProfileId, String sampleListId) + throws MolecularProfileNotFoundException { + + MolecularProfile molecularProfile = + molecularProfileService.getMolecularProfile(molecularProfileId); + + List genePanelData = + genePanelRepository.getGenePanelDataBySampleListId( + molecularProfile.getStableId(), sampleListId); + + return annotateDataFromSequencedSampleLists(genePanelData, molecularProfile); + } + + @Override + public List fetchGenePanelData(String molecularProfileId, List sampleIds) + throws MolecularProfileNotFoundException { + + List molecularProfileSampleIdentifiers = + sampleIds.stream() + .map(sampleId -> new MolecularProfileCaseIdentifier(sampleId, molecularProfileId)) + .collect(toList()); + + return fetchGenePanelDataInMultipleMolecularProfiles(molecularProfileSampleIdentifiers); + } + + @Override + public List fetchGenePanelDataByMolecularProfileIds( + Set molecularProfileIds) { + + List molecularProfiles = + molecularProfileService.getMolecularProfiles(molecularProfileIds, "SUMMARY"); + + Set uniqueMolecularProfileIds = + molecularProfiles.stream().map(MolecularProfile::getStableId).collect(toSet()); + + Map> molecularProfileIdToGenePanelDataMap = + uniqueMolecularProfileIds.stream() + // query database with each profile id so data cached in a modular way for each profile + .collect( + Collectors.toMap( + Function.identity(), + profileId -> + genePanelRepository.fetchGenePanelDataByMolecularProfileId(profileId))); + + Map molecularProfileIdMap = + molecularProfiles.stream() + .collect(Collectors.toMap(MolecularProfile::getStableId, Function.identity())); + + return molecularProfileIds.stream() + .flatMap( + profileId -> { + List genePanelData = + molecularProfileIdToGenePanelDataMap.getOrDefault(profileId, new ArrayList<>()); + if (CollectionUtils.isNotEmpty(genePanelData)) { + genePanelData = + annotateDataFromSequencedSampleLists( + genePanelData, molecularProfileIdMap.get(profileId)); + } + return genePanelData.stream(); + }) + .collect(Collectors.toList()); + } + + @Override + public List fetchGenePanelDataInMultipleMolecularProfiles( + List molecularProfileSampleIdentifiers) { + return getGenePanelData(molecularProfileSampleIdentifiers, SAMPLE_IDENTIFIER_GENERATOR); + } + + @Override + public List fetchGenePanelDataInMultipleMolecularProfilesByPatientIds( + List molecularProfilePatientIdentifiers) { + return getGenePanelData(molecularProfilePatientIdentifiers, PATIENT_IDENTIFIER_GENERATOR); + } + + private List getGenePanelData( + List molecularProfileCaseIdentifiers, + Function keyGenerator) { + Set molecularProfileIds = + molecularProfileCaseIdentifiers.stream() + .map(MolecularProfileCaseIdentifier::getMolecularProfileId) + .collect(toSet()); + + Map queriedMolecularProfileCaseIdentifierMap = + molecularProfileCaseIdentifiers.stream() + .collect( + Collectors.toMap( + datum -> datum.getMolecularProfileId() + datum.getCaseId(), datum -> true)); + + return fetchGenePanelDataByMolecularProfileIds(molecularProfileIds).stream() + .filter( + datum -> + queriedMolecularProfileCaseIdentifierMap.containsKey(keyGenerator.apply(datum))) + .collect(toList()); + } + + /** + * For mutation use sequenced case/sample list to check if the sample are profiled or not + * + * @param genePanelData list of gene panel data objects + * @param molecularProfile MolecularProfile + * @return List of GenePanelData + */ + private List annotateDataFromSequencedSampleLists( + List genePanelData, MolecularProfile molecularProfile) { + + if (MolecularProfile.MolecularAlterationType.MUTATION_EXTENDED.equals( + molecularProfile.getMolecularAlterationType())) { + try { + SampleList sampleList = + sampleListService.getSampleList( + molecularProfile.getCancerStudyIdentifier() + SEQUENCED_LIST_SUFFIX); + Map sampleSequencedBySampleList = + sampleList.getSampleIds().stream().collect(toMap(Function.identity(), d -> true)); + return genePanelData.stream() + .peek( + datum -> { + if (!datum.getProfiled()) { + datum.setProfiled( + sampleSequencedBySampleList.getOrDefault(datum.getSampleId(), false)); + } + }) + .collect(toList()); + + } catch (SampleListNotFoundException ignored) { + } + } + return genePanelData; + } +} diff --git a/src/main/java/org/cbioportal/legacy/service/impl/GeneServiceImpl.java b/src/main/java/org/cbioportal/legacy/service/impl/GeneServiceImpl.java new file mode 100644 index 00000000000..c64f558d8e2 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/impl/GeneServiceImpl.java @@ -0,0 +1,194 @@ +package org.cbioportal.legacy.service.impl; + +import static java.util.stream.Collectors.*; + +import jakarta.annotation.PostConstruct; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; +import org.cbioportal.legacy.model.Gene; +import org.cbioportal.legacy.model.GeneAlias; +import org.cbioportal.legacy.model.meta.BaseMeta; +import org.cbioportal.legacy.persistence.GeneRepository; +import org.cbioportal.legacy.service.GeneService; +import org.cbioportal.legacy.service.exception.GeneNotFoundException; +import org.cbioportal.legacy.service.exception.GeneWithMultipleEntrezIdsException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class GeneServiceImpl implements GeneService { + + public static final String ENTREZ_GENE_ID_GENE_ID_TYPE = "ENTREZ_GENE_ID"; + + @Autowired private GeneRepository geneRepository; + + private Map> geneAliasMap = new HashMap<>(); + + @PostConstruct + public void init() { + // query all genes so they would be cached + getAllGenes(null, null, "SUMMARY", null, null, null, null); + + geneAliasMap = + geneRepository.getAllAliases().stream() + .collect( + Collectors.groupingBy( + GeneAlias::getEntrezGeneId, + Collectors.mapping(GeneAlias::getGeneAlias, Collectors.toList()))); + } + + @Override + public List getAllGenes( + String keyword, + String alias, + String projection, + Integer pageSize, + Integer pageNumber, + String sortBy, + String direction) { + + List geneList = + geneRepository.getAllGenes( + keyword, alias, projection, pageSize, pageNumber, sortBy, direction); + + if (keyword != null && (pageSize == null || geneList.size() < pageSize)) { + List aliasMatchingGenes = findAliasMatchingGenes(keyword); + if (pageSize != null) { + int toIndex = + aliasMatchingGenes.size() > pageSize - geneList.size() + ? pageSize - geneList.size() + : aliasMatchingGenes.size(); + aliasMatchingGenes = aliasMatchingGenes.subList(0, toIndex); + } + for (Gene gene : aliasMatchingGenes) { + if (!geneList.stream().anyMatch(c -> c.getEntrezGeneId().equals(gene.getEntrezGeneId()))) { + geneList.add(gene); + } + } + } + + return filterGenesWithMultipleEntrezIds(geneList); + } + + @Override + public BaseMeta getMetaGenes(String keyword, String alias) { + + if (keyword == null) { + return geneRepository.getMetaGenes(keyword, alias); + } else { + BaseMeta baseMeta = new BaseMeta(); + baseMeta.setTotalCount(getAllGenes(keyword, null, "SUMMARY", null, null, null, null).size()); + return baseMeta; + } + } + + @Override + public Gene getGeneByGeneticEntityId(Integer geneticEntityId) throws GeneNotFoundException { + + Gene gene; + gene = geneRepository.getGeneByGeneticEntityId(geneticEntityId); + if (gene == null) throw new GeneNotFoundException(Integer.toString(geneticEntityId)); + return gene; + } + + @Override + public Gene getGene(String geneId) + throws GeneNotFoundException, GeneWithMultipleEntrezIdsException { + + Gene gene; + + if (isInteger(geneId)) { + gene = geneRepository.getGeneByEntrezGeneId(Integer.valueOf(geneId)); + } else { + gene = geneRepository.getGeneByHugoGeneSymbol(geneId); + } + if (gene == null) { + throw new GeneNotFoundException(geneId); + } + return gene; + } + + @Override + public List getAliasesOfGene(String geneId) + throws GeneNotFoundException, GeneWithMultipleEntrezIdsException { + + getGene(geneId); + + if (isInteger(geneId)) { + return geneRepository.getAliasesOfGeneByEntrezGeneId(Integer.valueOf(geneId)); + } else { + return geneRepository.getAliasesOfGeneByHugoGeneSymbol(geneId); + } + } + + @Override + public List fetchGenes(List geneIds, String geneIdType, String projection) { + + List geneList; + + if (geneIdType.equals(ENTREZ_GENE_ID_GENE_ID_TYPE)) { + geneList = + geneRepository.fetchGenesByEntrezGeneIds( + geneIds.stream() + .filter(this::isInteger) + .map(Integer::valueOf) + .collect(Collectors.toList()), + projection); + } else { + geneList = geneRepository.fetchGenesByHugoGeneSymbols(geneIds, projection); + } + + return filterGenesWithMultipleEntrezIds(geneList); + } + + @Override + public BaseMeta fetchMetaGenes(List geneIds, String geneIdType) { + + BaseMeta baseMeta; + + if (geneIdType.equals(ENTREZ_GENE_ID_GENE_ID_TYPE)) { + baseMeta = + geneRepository.fetchMetaGenesByEntrezGeneIds( + geneIds.stream() + .filter(this::isInteger) + .map(Integer::valueOf) + .collect(Collectors.toList())); + } else { + baseMeta = geneRepository.fetchMetaGenesByHugoGeneSymbols(geneIds); + } + + return baseMeta; + } + + private boolean isInteger(String geneId) { + return geneId.matches("^-?\\d+$"); + } + + private List findAliasMatchingGenes(String keyword) { + + List matchingGenes = new ArrayList<>(); + + List matchingEntrezGeneIds = new ArrayList<>(); + for (Map.Entry> entry : geneAliasMap.entrySet()) { + if (entry.getValue().contains(keyword.toLowerCase())) { + matchingEntrezGeneIds.add(String.valueOf(entry.getKey())); + } + } + if (!matchingEntrezGeneIds.isEmpty()) { + matchingGenes = fetchGenes(matchingEntrezGeneIds, ENTREZ_GENE_ID_GENE_ID_TYPE, "SUMMARY"); + } + return matchingGenes; + } + + private List filterGenesWithMultipleEntrezIds(List geneList) { + return geneList.stream().collect(groupingBy(Gene::getHugoGeneSymbol)).values().stream() + .filter( + groupedGenes -> + groupedGenes.size() == 1) // filter out genes having duplicate hugoGeneSymbol + .map(groupedGenes -> groupedGenes.get(0)) + .collect(toList()); + } +} diff --git a/src/main/java/org/cbioportal/legacy/service/impl/GenericAssayServiceImpl.java b/src/main/java/org/cbioportal/legacy/service/impl/GenericAssayServiceImpl.java new file mode 100644 index 00000000000..847ddd2036c --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/impl/GenericAssayServiceImpl.java @@ -0,0 +1,274 @@ +package org.cbioportal.legacy.service.impl; + +import java.util.*; +import java.util.function.Function; +import java.util.stream.Collectors; +import org.cbioportal.legacy.model.GenericAssayAdditionalProperty; +import org.cbioportal.legacy.model.GenericAssayData; +import org.cbioportal.legacy.model.GenericAssayMolecularAlteration; +import org.cbioportal.legacy.model.MolecularProfile; +import org.cbioportal.legacy.model.MolecularProfile.MolecularAlterationType; +import org.cbioportal.legacy.model.MolecularProfileSamples; +import org.cbioportal.legacy.model.Sample; +import org.cbioportal.legacy.model.meta.GenericAssayMeta; +import org.cbioportal.legacy.persistence.GenericAssayRepository; +import org.cbioportal.legacy.persistence.MolecularDataRepository; +import org.cbioportal.legacy.persistence.SampleListRepository; +import org.cbioportal.legacy.service.GenericAssayService; +import org.cbioportal.legacy.service.MolecularProfileService; +import org.cbioportal.legacy.service.SampleService; +import org.cbioportal.legacy.service.exception.MolecularProfileNotFoundException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class GenericAssayServiceImpl implements GenericAssayService { + + @Autowired private GenericAssayRepository genericAssayRepository; + + @Autowired private MolecularDataRepository molecularDataRepository; + + @Autowired private SampleService sampleService; + + @Autowired private MolecularProfileService molecularProfileService; + + @Autowired private SampleListRepository sampleListRepository; + + @Override + public List getGenericAssayMetaByStableIdsAndMolecularIds( + List stableIds, List molecularProfileIds, String projection) { + Set allStableIds = new HashSet(); + // extract genericAssayStableIds from the GENERIC_ASSAY profiles + if (molecularProfileIds != null) { + List distinctMolecularProfileIds = + molecularProfileIds.stream().distinct().sorted().collect(Collectors.toList()); + if (distinctMolecularProfileIds.size() > 0) { + // fetch one profile at a time to improve cache performace for multiple profiles query + for (String distinctMolecularProfileId : distinctMolecularProfileIds) { + allStableIds.addAll( + genericAssayRepository.getGenericAssayStableIdsByMolecularIds( + Arrays.asList(distinctMolecularProfileId))); + } + } + // if stableIds and molecularProfileIds both exist, find the common + if (stableIds != null) { + Map allStableIdMap = + allStableIds.stream() + .collect(Collectors.toMap(stableId -> stableId, stableId -> stableId)); + + allStableIds = + stableIds.stream() + .filter(stableId -> allStableIdMap.containsKey(stableId)) + .collect(Collectors.toSet()); + } + } else { + // add all stableIds since molecularProfileIds is null + if (stableIds != null) { + allStableIds.addAll(stableIds); + } + } + List distinctStableIds = new ArrayList(allStableIds); + List metaResults = new ArrayList(); + // TODO: move below logic to sql query + if (distinctStableIds.size() > 0) { + List metaData = + genericAssayRepository.getGenericAssayMeta(distinctStableIds); + // just return stable_id if projection is ID + if (projection.equals("ID")) { + for (GenericAssayMeta meta : metaData) { + metaResults.add(new GenericAssayMeta(meta.getStableId())); + } + } else { + Map> additionalPropertiesGroupedByStableId = + genericAssayRepository.getGenericAssayAdditionalproperties(distinctStableIds).stream() + .collect(Collectors.groupingBy(GenericAssayAdditionalProperty::getStableId)); + for (GenericAssayMeta meta : metaData) { + String stableId = meta.getStableId(); + HashMap map = new HashMap<>(); + if (additionalPropertiesGroupedByStableId.containsKey(stableId)) { + for (GenericAssayAdditionalProperty additionalProperty : + additionalPropertiesGroupedByStableId.get(stableId)) { + map.put(additionalProperty.getName(), additionalProperty.getValue()); + } + } + meta.setGenericEntityMetaProperties(map); + metaResults.add(meta); + } + } + } + return metaResults; + } + + @Override + public List fetchGenericAssayData( + List molecularProfileIds, + List sampleIds, + List genericAssayStableIds, + String projection) + throws MolecularProfileNotFoundException { + List result = new ArrayList<>(); + + SortedSet distinctMolecularProfileIds = new TreeSet<>(molecularProfileIds); + + Map commaSeparatedSampleIdsOfMolecularProfilesMap = + molecularDataRepository.commaSeparatedSampleIdsOfMolecularProfilesMap( + distinctMolecularProfileIds); + + Map> internalSampleIdsMap = new HashMap<>(); + List allInternalSampleIds = new ArrayList<>(); + + for (String molecularProfileId : distinctMolecularProfileIds) { + List internalSampleIds = + Arrays.stream( + Optional.ofNullable( + commaSeparatedSampleIdsOfMolecularProfilesMap.get(molecularProfileId)) + .orElseThrow( + () -> + new IllegalArgumentException( + "Sample IDs for MolecularProfileId " + + molecularProfileId + + " are null.")) + .getSplitSampleIds()) + .mapToInt(Integer::parseInt) + .boxed() + .collect(Collectors.toList()); + HashMap molecularProfileSampleMap = new HashMap(); + for (int lc = 0; lc < internalSampleIds.size(); lc++) { + molecularProfileSampleMap.put(internalSampleIds.get(lc), lc); + } + internalSampleIdsMap.put(molecularProfileId, molecularProfileSampleMap); + allInternalSampleIds.addAll(internalSampleIds); + } + + List molecularProfiles = new ArrayList<>(); + List distinctMolecularProfiles = + molecularProfileService.getMolecularProfiles(distinctMolecularProfileIds, "SUMMARY"); + Map molecularProfileMapById = + distinctMolecularProfiles.stream() + .collect(Collectors.toMap(MolecularProfile::getStableId, Function.identity())); + Map> molecularProfileMapByStudyId = + distinctMolecularProfiles.stream() + .collect(Collectors.groupingBy(MolecularProfile::getCancerStudyIdentifier)); + List samples; + if (sampleIds == null) { + samples = sampleService.getSamplesByInternalIds(allInternalSampleIds); + for (String molecularProfileId : distinctMolecularProfileIds) { + if (internalSampleIdsMap.get(molecularProfileId) == null) { + throw new IllegalArgumentException( + "InternalSampleIdsMap for MolecularProfileId " + molecularProfileId + " is null."); + } + internalSampleIdsMap + .get(molecularProfileId) + .keySet() + .forEach(s -> molecularProfiles.add(molecularProfileMapById.get(molecularProfileId))); + } + } else { + for (String molecularProfileId : molecularProfileIds) { + MolecularProfile molecularProfile = molecularProfileMapById.get(molecularProfileId); + if (molecularProfile == null) { + throw new IllegalArgumentException( + "MolecularProfile for MolecularProfileId " + molecularProfileId + " is null."); + } + molecularProfiles.add(molecularProfile); + } + List studyIds = + molecularProfiles.stream() + .map(MolecularProfile::getCancerStudyIdentifier) + .collect(Collectors.toList()); + samples = sampleService.fetchSamples(studyIds, sampleIds, "ID"); + } + + List molecularAlterations = new ArrayList<>(); + for (String distinctMolecularProfileId : distinctMolecularProfileIds) { + molecularAlterations.addAll( + molecularDataRepository.getGenericAssayMolecularAlterations( + distinctMolecularProfileId, genericAssayStableIds, projection)); + } + Map> molecularAlterationsMap = + molecularAlterations.stream() + .collect(Collectors.groupingBy(GenericAssayMolecularAlteration::getMolecularProfileId)); + + for (Sample sample : samples) { + List studyMolecularProfiles = + molecularProfileMapByStudyId.get(sample.getCancerStudyIdentifier()); + if (studyMolecularProfiles == null) { + throw new IllegalArgumentException( + "MolecularProfiles for StudyId " + sample.getCancerStudyIdentifier() + " is null."); + } + for (MolecularProfile molecularProfile : studyMolecularProfiles) { + String molecularProfileId = molecularProfile.getStableId(); + if (internalSampleIdsMap.get(molecularProfileId) == null) { + throw new IllegalArgumentException( + "InternalSampleIdsMap for MolecularProfileId " + molecularProfileId + " is null."); + } + if (sample.getInternalId() == null) { + throw new IllegalArgumentException( + "InternalId for Sample " + sample.getInternalId() + " is null."); + } + Integer indexOfSampleId = + internalSampleIdsMap.get(molecularProfileId).get(sample.getInternalId()); + if (indexOfSampleId != null && molecularAlterationsMap.containsKey(molecularProfileId)) { + for (GenericAssayMolecularAlteration molecularAlteration : + molecularAlterationsMap.get(molecularProfileId)) { + GenericAssayData molecularData = new GenericAssayData(); + molecularData.setMolecularProfileId(molecularProfileId); + molecularData.setSampleId(sample.getStableId()); + molecularData.setPatientId(sample.getPatientStableId()); + molecularData.setStudyId(sample.getCancerStudyIdentifier()); + molecularData.setGenericAssayStableId(molecularAlteration.getGenericAssayStableId()); + molecularData.setValue(molecularAlteration.getSplitValues()[indexOfSampleId]); + if (molecularProfile.getPatientLevel() != null) { + molecularData.setPatientLevel(molecularProfile.getPatientLevel()); + } + result.add(molecularData); + } + } + } + } + return result; + } + + @Override + public List getGenericAssayData( + String molecularProfileId, + String sampleListId, + List genericAssayStableIds, + String projection) + throws MolecularProfileNotFoundException { + + validateMolecularProfile(molecularProfileId); + List sampleIds = sampleListRepository.getAllSampleIdsInSampleList(sampleListId); + if (sampleIds.isEmpty()) { + return Collections.emptyList(); + } + return fetchGenericAssayData( + Arrays.asList(molecularProfileId), sampleIds, genericAssayStableIds, projection); + } + + @Override + public List fetchGenericAssayData( + String molecularProfileId, + List sampleIds, + List genericAssayStableIds, + String projection) + throws MolecularProfileNotFoundException { + + validateMolecularProfile(molecularProfileId); + return fetchGenericAssayData( + Arrays.asList(molecularProfileId), sampleIds, genericAssayStableIds, projection); + } + + private void validateMolecularProfile(String molecularProfileId) + throws MolecularProfileNotFoundException { + + MolecularProfile molecularProfile = + molecularProfileService.getMolecularProfile(molecularProfileId); + + if (!molecularProfile + .getMolecularAlterationType() + .equals(MolecularAlterationType.GENERIC_ASSAY)) { + + throw new MolecularProfileNotFoundException(molecularProfileId); + } + } +} diff --git a/src/main/java/org/cbioportal/legacy/service/impl/GenesetCorrelationServiceImpl.java b/src/main/java/org/cbioportal/legacy/service/impl/GenesetCorrelationServiceImpl.java new file mode 100644 index 00000000000..70c3619d87e --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/impl/GenesetCorrelationServiceImpl.java @@ -0,0 +1,273 @@ +/* + * Copyright (c) 2016 The Hyve B.V. + * This code is licensed under the GNU Affero General Public License (AGPL), + * version 3, or (at your option) any later version. + */ + +/* + * This file is part of cBioPortal. + * + * cBioPortal is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package org.cbioportal.legacy.service.impl; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; +import org.apache.commons.lang3.math.NumberUtils; +import org.apache.commons.math3.stat.correlation.SpearmansCorrelation; +import org.cbioportal.legacy.model.CancerStudy; +import org.cbioportal.legacy.model.Gene; +import org.cbioportal.legacy.model.GeneMolecularData; +import org.cbioportal.legacy.model.GenesetCorrelation; +import org.cbioportal.legacy.model.GenesetMolecularData; +import org.cbioportal.legacy.model.MolecularProfile; +import org.cbioportal.legacy.model.Sample; +import org.cbioportal.legacy.service.GenesetCorrelationService; +import org.cbioportal.legacy.service.GenesetDataService; +import org.cbioportal.legacy.service.GenesetService; +import org.cbioportal.legacy.service.MolecularDataService; +import org.cbioportal.legacy.service.MolecularProfileService; +import org.cbioportal.legacy.service.SampleListService; +import org.cbioportal.legacy.service.SampleService; +import org.cbioportal.legacy.service.exception.GenesetNotFoundException; +import org.cbioportal.legacy.service.exception.MolecularProfileNotFoundException; +import org.cbioportal.legacy.service.exception.SampleListNotFoundException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class GenesetCorrelationServiceImpl implements GenesetCorrelationService { + + @Autowired private MolecularDataService molecularDataService; + @Autowired private GenesetDataService genesetDataService; + @Autowired private MolecularProfileService molecularProfileService; + @Autowired private GenesetService genesetService; + @Autowired private SampleService sampleService; + @Autowired private SampleListService sampleListService; + + public List fetchCorrelatedGenes( + String genesetId, String molecularProfileId, double correlationThreshold) + throws MolecularProfileNotFoundException, GenesetNotFoundException { + + // get sample ids from study + CancerStudy cancerStudy = + molecularProfileService.getMolecularProfile(molecularProfileId).getCancerStudy(); + List samples = + sampleService.fetchSamples( + Arrays.asList(cancerStudy.getCancerStudyIdentifier()), null, "SUMMARY"); + // convert to string list: + List sampleIds = + samples.stream().map(o -> o.getStableId()).collect(Collectors.toList()); + return fetchCorrelatedGenes(genesetId, molecularProfileId, sampleIds, correlationThreshold); + } + + public List fetchCorrelatedGenes( + String genesetId, String molecularProfileId, String sampleListId, double correlationThreshold) + throws MolecularProfileNotFoundException, + SampleListNotFoundException, + GenesetNotFoundException { + + // get sample ids from sampleList + List sampleIds = sampleListService.getAllSampleIdsInSampleList(sampleListId); + return fetchCorrelatedGenes(genesetId, molecularProfileId, sampleIds, correlationThreshold); + } + + public List fetchCorrelatedGenes( + String genesetId, + String molecularProfileId, + List sampleIds, + double correlationThreshold) + throws MolecularProfileNotFoundException, GenesetNotFoundException { + + List result = new ArrayList(); + + // find the genes in the geneset + List genes = genesetService.getGenesByGenesetId(genesetId); + + // the geneset data: + List genesetData = + genesetDataService.fetchGenesetData( + molecularProfileId, sampleIds, Arrays.asList(genesetId)); + double[] genesetValues = getGenesetValues(sampleIds, genesetData); + // find the expression profile related to the given geneticProfileId + List expressionProfilesReferredByGenesetProfile = + molecularProfileService.getMolecularProfilesReferredBy(molecularProfileId); + // we expect only 1 in this case (a geneset only refers to 1 expression profile, so give error + // otherwise): + if (expressionProfilesReferredByGenesetProfile.size() != 1) { + throw new RuntimeException( + "Unexpected error: given geneset profile refers to " + + expressionProfilesReferredByGenesetProfile.size() + + " profile(s). Should refer to only 1"); + } + MolecularProfile expressionProfile = expressionProfilesReferredByGenesetProfile.get(0); + MolecularProfile zscoresProfile = getLinkedZscoreProfile(expressionProfile); + + // TODO : if this turns out to take too long, we can always implement this loop in parallel to + // improve + // performance. Multi-threading is easy in this scenario. + // get genetic data for each gene and calculate correlation + for (Gene gene : genes) { + Integer entrezGeneId = gene.getEntrezGeneId(); + List geneData = + molecularDataService.fetchMolecularData( + expressionProfile.getStableId(), sampleIds, Arrays.asList(entrezGeneId), "SUMMARY"); + double correlationValue = calculateCorrelation(sampleIds, geneData, genesetValues); + // filter out the ones below correlationThreshold + if (correlationValue < correlationThreshold) { + continue; + } + GenesetCorrelation genesetCorrelationItem = new GenesetCorrelation(); + genesetCorrelationItem.setEntrezGeneId(entrezGeneId); + genesetCorrelationItem.setHugoGeneSymbol(gene.getHugoGeneSymbol()); + genesetCorrelationItem.setCorrelationValue(correlationValue); + genesetCorrelationItem.setExpressionMolecularProfileId(expressionProfile.getStableId()); + genesetCorrelationItem.setzScoreMolecularProfileId(zscoresProfile.getStableId()); + result.add(genesetCorrelationItem); + } + // return sorted + sortResult(result); + return result; + } + + private MolecularProfile getLinkedZscoreProfile(MolecularProfile expressionProfile) + throws MolecularProfileNotFoundException { + + // Find the related z-score profile via the genetic_profile_link table: + List referringProfiles = + molecularProfileService.getMolecularProfilesReferringTo(expressionProfile.getStableId()); + MolecularProfile zscoresProfile = null; + for (MolecularProfile referringProfile : referringProfiles) { + // use the first z-score profile we can find in this list of referring profiles (normally + // there should be only 1 anyway): + if (referringProfile.getDatatype().equals("Z-SCORE")) { + zscoresProfile = referringProfile; + break; + } + } + // if none found, give clear error message...something is wrong with this study: + if (zscoresProfile == null) { + throw new IllegalArgumentException( + "The expression profile [" + + expressionProfile.getStableId() + + "] linked to the given " + + "gene set scores profile does not have a corresponding z-scores profile in this study."); + } + return zscoresProfile; + } + + private void sortResult(List result) { + + result.sort( + (GenesetCorrelation o1, GenesetCorrelation o2) -> { + // descending order, also check for NaN + if (o1.getCorrelationValue().isNaN()) return 1; + if (o2.getCorrelationValue().isNaN()) return -1; + + if (o1.getCorrelationValue() < o2.getCorrelationValue()) return 1; + if (o1.getCorrelationValue() > o2.getCorrelationValue()) return -1; + + return 0; + }); + } + + /** + * Calculates the Spearman correlation between the genesetValues list and the list built up from + * geneGeneticDataItems for the given sampleIds. + * + *

Before calculating the correlation, this method prepares the gene values, filtering both + * them and genesetValues, removing samples where the value is not present in either gene or gene + * set dimension. + * + * @param sampleIds: samples over which to calculate correlation + * @param geneGeneticDataItems: gene (expression) values for the set of samples + * @param genesetValues: gene set scores for the set of samples + * @return: Spearman's correlation value between values in geneGeneticDataItems and genesetValues. + */ + private double calculateCorrelation( + List sampleIds, + List geneGeneticDataItems, + double[] genesetValues) { + + // index geneData values + Map sampleValues = new HashMap(); + for (GeneMolecularData geneGeneticDataItem : geneGeneticDataItems) { + double value = Double.NaN; + if (NumberUtils.isNumber(geneGeneticDataItem.getValue())) { + value = Double.parseDouble(geneGeneticDataItem.getValue()); + } + sampleValues.put(geneGeneticDataItem.getSampleId(), value); + } + // get values + List geneValueList = new ArrayList(); + List genesetValueList = new ArrayList(); + for (int i = 0; i < sampleIds.size(); i++) { + String sampleId = sampleIds.get(i); + Double value = sampleValues.get(sampleId); + if (value == null) { + value = Double.NaN; // set to NaN when value is not available for this sample + } + // if both this value and genesetValues[i] are NaN, then skip this item (since it will not be + // allowed by the correlation method): + if (!Double.isNaN(value) && !Double.isNaN(genesetValues[i])) { + geneValueList.add(value); + // build up genesetValues is same way: + genesetValueList.add(genesetValues[i]); + } + } + // final filtered lists: + double[] geneValuesFiltered = geneValueList.stream().mapToDouble(d -> d).toArray(); + double[] genesetValuesFiltered = genesetValueList.stream().mapToDouble(d -> d).toArray(); + double correlationValue = 0; + // arrays need to be at least 2 long to calculate correlation: + if (geneValuesFiltered.length >= 2) { + // calculate spearman correlation + SpearmansCorrelation spearmansCorrelation = new SpearmansCorrelation(); + correlationValue = + spearmansCorrelation.correlation(geneValuesFiltered, genesetValuesFiltered); + } + return correlationValue; + } + + private double[] getGenesetValues( + List sampleIds, List genesetDataItems) { + + // index genesetData values + Map sampleValues = new HashMap(); + for (GenesetMolecularData genesetDataItem : genesetDataItems) { + double value = Double.NaN; + if (NumberUtils.isNumber(genesetDataItem.getValue())) { + value = Double.parseDouble(genesetDataItem.getValue()); + } + sampleValues.put(genesetDataItem.getSampleId(), value); + } + // get values + double[] result = new double[sampleIds.size()]; + for (int i = 0; i < sampleIds.size(); i++) { + String sampleId = sampleIds.get(i); + Double value = sampleValues.get(sampleId); + if (value != null) { + result[i] = value; + } else { + result[i] = Double.NaN; // set to NaN when value is not available for this sample + } + } + return result; + } +} diff --git a/src/main/java/org/cbioportal/legacy/service/impl/GenesetDataServiceImpl.java b/src/main/java/org/cbioportal/legacy/service/impl/GenesetDataServiceImpl.java new file mode 100644 index 00000000000..528b3fa57c6 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/impl/GenesetDataServiceImpl.java @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2016 The Hyve B.V. + * This code is licensed under the GNU Affero General Public License (AGPL), + * version 3, or (at your option) any later version. + */ + +/* + * This file is part of cBioPortal. + * + * cBioPortal is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package org.cbioportal.legacy.service.impl; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; +import org.cbioportal.legacy.model.GenesetMolecularAlteration; +import org.cbioportal.legacy.model.GenesetMolecularData; +import org.cbioportal.legacy.model.MolecularProfile; +import org.cbioportal.legacy.model.MolecularProfileSamples; +import org.cbioportal.legacy.model.Sample; +import org.cbioportal.legacy.persistence.MolecularDataRepository; +import org.cbioportal.legacy.service.GenesetDataService; +import org.cbioportal.legacy.service.MolecularProfileService; +import org.cbioportal.legacy.service.SampleListService; +import org.cbioportal.legacy.service.SampleService; +import org.cbioportal.legacy.service.exception.MolecularProfileNotFoundException; +import org.cbioportal.legacy.service.exception.SampleListNotFoundException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class GenesetDataServiceImpl implements GenesetDataService { + + @Autowired private MolecularDataRepository molecularDataRepository; + @Autowired private SampleService sampleService; + @Autowired private MolecularProfileService molecularProfileService; + @Autowired private SampleListService sampleListService; + + public List fetchGenesetData( + String molecularProfileId, List sampleIds, List genesetIds) + throws MolecularProfileNotFoundException { + + // validate (throws exception if profile is not found): + MolecularProfile molecularProfile = + molecularProfileService.getMolecularProfile(molecularProfileId); + + List genesetDataList = new ArrayList<>(); + + MolecularProfileSamples commaSeparatedSampleIdsOfGeneticProfile = + molecularDataRepository.getCommaSeparatedSampleIdsOfMolecularProfile(molecularProfileId); + if (commaSeparatedSampleIdsOfGeneticProfile == null) { + // no data, return empty list: + return genesetDataList; + } + List internalSampleIds = + Arrays.stream(commaSeparatedSampleIdsOfGeneticProfile.getSplitSampleIds()) + .mapToInt(Integer::parseInt) + .boxed() + .collect(Collectors.toList()); + + List samples; + if (sampleIds == null) { + samples = sampleService.getSamplesByInternalIds(internalSampleIds); + } else { + List studyIds = new ArrayList<>(); + sampleIds.forEach(s -> studyIds.add(molecularProfile.getCancerStudyIdentifier())); + samples = sampleService.fetchSamples(studyIds, sampleIds, "ID"); + } + + List genesetAlterations = + molecularDataRepository.getGenesetMolecularAlterations( + molecularProfileId, genesetIds, "SUMMARY"); + + for (Sample sample : samples) { + int indexOfSampleId = internalSampleIds.indexOf(sample.getInternalId()); + if (indexOfSampleId != -1) { + for (GenesetMolecularAlteration genesetAlteration : genesetAlterations) { + GenesetMolecularData genesetData = new GenesetMolecularData(); + genesetData.setMolecularProfileId(molecularProfileId); + genesetData.setSampleId(sample.getStableId()); + genesetData.setPatientId(sample.getPatientStableId()); + genesetData.setStudyId(sample.getCancerStudyIdentifier()); + genesetData.setGenesetId(genesetAlteration.getGenesetId()); + genesetData.setValue(genesetAlteration.getSplitValues()[indexOfSampleId]); + genesetDataList.add(genesetData); + } + } + } + + return genesetDataList; + } + + public List fetchGenesetData( + String geneticProfileId, String sampleListId, List genesetIds) + throws MolecularProfileNotFoundException, SampleListNotFoundException { + + // get list of samples for given sampleListId: + List sampleIds = sampleListService.getAllSampleIdsInSampleList(sampleListId); + return fetchGenesetData(geneticProfileId, sampleIds, genesetIds); + } + + @Override + public List getGenesetAlterations( + String molecularProfileId, List genesetIds) throws MolecularProfileNotFoundException { + + return molecularDataRepository.getGenesetMolecularAlterations( + molecularProfileId, genesetIds, "SUMMARY"); + } +} diff --git a/src/main/java/org/cbioportal/legacy/service/impl/GenesetHierarchyServiceImpl.java b/src/main/java/org/cbioportal/legacy/service/impl/GenesetHierarchyServiceImpl.java new file mode 100644 index 00000000000..02ac21c3d09 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/impl/GenesetHierarchyServiceImpl.java @@ -0,0 +1,400 @@ +/* + * Copyright (c) 2016 The Hyve B.V. + * This code is licensed under the GNU Affero General Public License (AGPL), + * version 3, or (at your option) any later version. + */ + +/* + * This file is part of cBioPortal. + * + * cBioPortal is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +package org.cbioportal.legacy.service.impl; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; +import org.apache.commons.lang3.math.NumberUtils; +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.cbioportal.legacy.model.CancerStudy; +import org.cbioportal.legacy.model.Geneset; +import org.cbioportal.legacy.model.GenesetHierarchyInfo; +import org.cbioportal.legacy.model.GenesetMolecularData; +import org.cbioportal.legacy.model.MolecularProfile; +import org.cbioportal.legacy.model.Sample; +import org.cbioportal.legacy.persistence.GenesetHierarchyRepository; +import org.cbioportal.legacy.service.GenesetDataService; +import org.cbioportal.legacy.service.GenesetHierarchyService; +import org.cbioportal.legacy.service.MolecularProfileService; +import org.cbioportal.legacy.service.SampleListService; +import org.cbioportal.legacy.service.SampleService; +import org.cbioportal.legacy.service.exception.MolecularProfileNotFoundException; +import org.cbioportal.legacy.service.exception.SampleListNotFoundException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class GenesetHierarchyServiceImpl implements GenesetHierarchyService { + + @Autowired private GenesetDataService genesetDataService; + @Autowired private MolecularProfileService geneticProfileService; + @Autowired private GenesetHierarchyRepository genesetHierarchyRepository; + @Autowired private SampleService sampleService; + @Autowired private SampleListService sampleListService; + + public List fetchGenesetHierarchyInfo( + String geneticProfileId, Integer percentile, Double scoreThreshold, Double pvalueThreshold) + throws MolecularProfileNotFoundException { + + // get sample ids from study + CancerStudy cancerStudy = + geneticProfileService.getMolecularProfile(geneticProfileId).getCancerStudy(); + List samples = + sampleService.fetchSamples( + Arrays.asList(cancerStudy.getCancerStudyIdentifier()), null, "SUMMARY"); + // convert to string list: + List sampleIds = + samples.stream().map(o -> o.getStableId()).collect(Collectors.toList()); + return fetchGenesetHierarchyInfo( + geneticProfileId, percentile, scoreThreshold, pvalueThreshold, sampleIds); + } + + public List fetchGenesetHierarchyInfo( + String geneticProfileId, + Integer percentile, + Double scoreThreshold, + Double pvalueThreshold, + String sampleListId) + throws MolecularProfileNotFoundException, SampleListNotFoundException { + + // get sample ids from sampleList + List sampleIds = sampleListService.getAllSampleIdsInSampleList(sampleListId); + return fetchGenesetHierarchyInfo( + geneticProfileId, percentile, scoreThreshold, pvalueThreshold, sampleIds); + } + + public List fetchGenesetHierarchyInfo( + String geneticProfileId, + Integer percentile, + Double scoreThreshold, + Double pvalueThreshold, + List sampleIds) + throws MolecularProfileNotFoundException { + + // validate: + MolecularProfile geneticProfile = geneticProfileService.getMolecularProfile(geneticProfileId); + // also validate if profile is of geneset_score type: + if (!geneticProfile.getDatatype().equals("GSVA-SCORE")) { + throw new IllegalArgumentException( + "Genetic profile should be of DATA_TYPE = GSVA-SCORE, but found: " + + geneticProfile.getDatatype()); + } + + // get list of genesets and respective score records for gene sets that have data for this + // profile: + List genesetScores = + genesetDataService.fetchGenesetData(geneticProfileId, sampleIds, null); + List genesetPvalues = getGenesetPvalues(geneticProfileId, sampleIds); + + return getGenesetHierarchyItems( + genesetScores, genesetPvalues, percentile, scoreThreshold, pvalueThreshold); + } + + /** + * Finds and retrieves the gene set p-values of the profile linked to the given + * scoresGeneticProfileId. + * + * @param scoresGeneticProfileId: genetic profile containing gene set scores + * @param sampleIds: samples to use for the representative score calculation + * @return + * @throws MolecularProfileNotFoundException + */ + private List getGenesetPvalues( + String scoresGeneticProfileId, List sampleIds) + throws MolecularProfileNotFoundException { + + List pvaluesGeneticProfiles = + geneticProfileService.getMolecularProfilesReferringTo(scoresGeneticProfileId); + // validate : + if (pvaluesGeneticProfiles == null || pvaluesGeneticProfiles.size() != 1) { + // unexpected, but could happen if dataset validation is skipped + throw new RuntimeException( + "The given gene set profile [" + + scoresGeneticProfileId + + "] should have (at least) 1 and only 1 linked p-values profile in DB"); + } + // validate if profile is of pvalue type: + if (!pvaluesGeneticProfiles.get(0).getDatatype().equals("P-VALUE")) { + throw new IllegalArgumentException("Genetic profile should be of DATA_TYPE = P-VALUE"); + } + + List genesetPvalues = + genesetDataService.fetchGenesetData( + pvaluesGeneticProfiles.get(0).getStableId(), sampleIds, null); + return genesetPvalues; + } + + /** + * Return the hierarchy nodes and leafs (gene sets) based on data found in genesetScores. + * + * @param genesetScores: gene set score data found for the given geneticProfileId and sampleIds + * @param percentile: percentile to use for the representative score calculation + * @param scoreThreshold: filter criterion + * @param pvalueThreshold: filter criterion + * @return + * @throws MolecularProfileNotFoundException + */ + private List getGenesetHierarchyItems( + List genesetScores, + List genesetPvalues, + Integer percentile, + Double scoreThreshold, + Double pvalueThreshold) + throws MolecularProfileNotFoundException { + + List genesetIds = + new ArrayList( + genesetScores.stream().map(o -> o.getGenesetId()).collect(Collectors.toSet())); + + // add all hierarchy nodes that have no leafs, but are intermediate/super nodes: + List hierarchySuperNodes = + genesetHierarchyRepository.getGenesetHierarchySuperNodes(genesetIds); + + // index genesetData : + Map> genesetScoresMap = + genesetScores.stream().collect(Collectors.groupingBy(GenesetMolecularData::getGenesetId)); + Map> genesetPvaluesMap = + genesetPvalues.stream().collect(Collectors.groupingBy(GenesetMolecularData::getGenesetId)); + + // get the nodes that have gene sets as child/leafs: + List hierarchyGenesetParents = + genesetHierarchyRepository.getGenesetHierarchyParents( + genesetIds); // maybe rename to pre-leafItems? + if (genesetIds != null) { + // complement the result with the gene sets info: + for (GenesetHierarchyInfo hierarchyItem : hierarchyGenesetParents) { + List genesets = + genesetHierarchyRepository.getGenesetHierarchyGenesets(hierarchyItem.getNodeId()); + // get only the ones that have data, filtering out the other ones (probably not needed, but + // just to be sure): + genesets = getFilteredGenesets(genesets, genesetScoresMap); + // for each gene set, calculate representative score: + fillRepresentativeScoresAndPvalues( + genesets, genesetScoresMap, genesetPvaluesMap, percentile); + // filter out the ones that don't satisfy thresholds: + genesets = getFilteredGenesets(genesets, scoreThreshold, pvalueThreshold); + hierarchyItem.setGenesets(genesets); + // if genesets turns out to be empty, still consider it as a possible super node (will be + // filtered below if it is not): + if (genesets.size() == 0) { + hierarchySuperNodes.add(hierarchyItem); + } + } + } + // remove the hierarchyGenesetParents that have no gene set leaf nodes: + hierarchyGenesetParents = getFilteredHierarchyGenesetParents(hierarchyGenesetParents); + // remove nodes from hierarchySuperNodes that do not lead to a leaf node: + hierarchySuperNodes = + getFilteredHierarchySuperNodes(hierarchySuperNodes, hierarchyGenesetParents); + // TODO could probably simplify some of this code above by merging hierarchySuperNodes and + // hierarchyGenesetParents at the start + // and filtering the tree in one recursive function... + + // join both lists: + hierarchySuperNodes.addAll(hierarchyGenesetParents); + + return hierarchySuperNodes; + } + + private List getFilteredGenesets( + List genesets, Double scoreThreshold, Double pvalueThreshold) { + + return genesets.stream() + .filter( + g -> + Math.abs(g.getRepresentativeScore()) >= scoreThreshold + && g.getRepresentativePvalue() <= pvalueThreshold) + .collect(Collectors.toList()); + } + + private List getFilteredHierarchySuperNodes( + List hierarchySuperNodes, List referringNodes) { + + // index referred node ids: + Set referredNodesSet = + referringNodes.stream().map(GenesetHierarchyInfo::getParentId).collect(Collectors.toSet()); + + // also make index for super nodes as they could refer to each other + List referredNodes = new ArrayList(); + for (GenesetHierarchyInfo hierarchySuperNode : hierarchySuperNodes) { + if (referredNodesSet.contains(hierarchySuperNode.getNodeId())) { + // there are child nodes, so add this one: + if (!referredNodes.contains(hierarchySuperNode)) { + referredNodes.add(hierarchySuperNode); + } + } + } + if (referredNodes.size() > 0) { + // recursion: also add the parents of the referredNodes + List parents = + getFilteredHierarchySuperNodes(hierarchySuperNodes, referredNodes); + for (GenesetHierarchyInfo parent : parents) { + if (!referredNodes.contains(parent)) referredNodes.add(parent); + } + } + return referredNodes; + } + + private List getFilteredHierarchyGenesetParents( + List hierarchyGenesetParents) { + + List result = new ArrayList(); + for (GenesetHierarchyInfo hierarchyGenesetParent : hierarchyGenesetParents) { + if (hierarchyGenesetParent.getGenesets().size() > 0) { + // there are leaf nodes, so add this one: + result.add(hierarchyGenesetParent); + } + } + return result; + } + + private List getFilteredGenesets( + List genesets, Map> genesetDataMap) { + + List result = new ArrayList(); + for (Geneset geneset : genesets) { + if (genesetDataMap.get(geneset.getGenesetId()) != null) { + // there is data, so add this one: + result.add(geneset); + } + } + return result; + } + + /** + * This will set the representativeScore attribute for each gene set, based on the data (the gene + * set scores per sample). + * + * @param sampleIds + * @param genesets: list of gene sets for which to calculate and record the representativeScore + * @param genesetDataMap: the set of GSVA(like) scores per sample for each gene set + * @param percentile: (optional) which percentile to use when determining the representativeScore. + * If not set, max of absolute score is returned. + * @throws MolecularProfileNotFoundException + */ + private void fillRepresentativeScoresAndPvalues( + List genesets, + Map> genesetScoresMap, + Map> genesetPvaluesMap, + Integer percentile) + throws MolecularProfileNotFoundException { + + genesets.stream() + .forEach( + g -> + calculateAndSetRepresentativeScoreAndPvalue( + g, genesetScoresMap, genesetPvaluesMap, percentile)); + } + + private void calculateAndSetRepresentativeScoreAndPvalue( + Geneset geneset, + Map> genesetScoresMap, + Map> genesetPvaluesMap, + Integer percentile) { + + List genesetScoreData = genesetScoresMap.get(geneset.getGenesetId()); + List genesetPvalueData = genesetPvaluesMap.get(geneset.getGenesetId()); + + // lists to hold the score and p-value pairs: + List> positiveScoresAndPvalues = + new ArrayList>(); + List> negativeScoresAndPvalues = + new ArrayList>(); + + // return the maximum absolute value found: + double max = 0; + double pvalueOfMax = 1; + for (int i = 0; i < genesetScoreData.size(); i++) { + String scoreString = genesetScoreData.get(i).getValue(); + String pvalueString = genesetPvalueData.get(i).getValue(); + + if (!NumberUtils.isNumber(scoreString)) continue; + + double score = Double.parseDouble(scoreString); + double pvalue = 1.0; + if (NumberUtils.isNumber(pvalueString)) pvalue = Double.parseDouble(pvalueString); + if (score >= 0) { + positiveScoresAndPvalues.add(new ImmutablePair(score, pvalue)); + } else { + negativeScoresAndPvalues.add(new ImmutablePair(score, pvalue)); + } + + // keep track of max, in case percentile is null + if (Math.abs(score) > Math.abs(max)) { + max = score; // here no abs, since we want to get the raw score (could be negative) + pvalueOfMax = pvalue; + } + } + + if (percentile == null) { + geneset.setRepresentativeScore(max); + geneset.setRepresentativePvalue(pvalueOfMax); + } else { + // sort scores (NB: .getLeft() returns the score, .getRight() returns the pvalue of each + // pair): + positiveScoresAndPvalues.sort( + (ImmutablePair o1, ImmutablePair o2) -> + Double.compare(o1.getLeft(), o2.getLeft())); + // negative scores descending: + negativeScoresAndPvalues.sort( + (ImmutablePair o1, ImmutablePair o2) -> + Double.compare(o2.getLeft(), o1.getLeft())); + + // use percentile: + ImmutablePair representativePositiveScoreAndPvalue = + new ImmutablePair(0.0, 1.0); + ImmutablePair representativeNegativeScoreAndPvalue = + new ImmutablePair(0.0, 1.0); + if (positiveScoresAndPvalues.size() > 0) { + int idxPositiveScores = + (int) Math.round(percentile * positiveScoresAndPvalues.size() / 100.0); + if (idxPositiveScores == 0) { // (can happen when positiveScoresAndPvalues.size() is small) + idxPositiveScores = 1; + } + representativePositiveScoreAndPvalue = positiveScoresAndPvalues.get(idxPositiveScores - 1); + } + if (negativeScoresAndPvalues.size() > 0) { + int idxNegativeScores = + (int) Math.round(percentile * negativeScoresAndPvalues.size() / 100.0); + if (idxNegativeScores == 0) { // (can happen when positiveScoresAndPvalues.size() is small) + idxNegativeScores = 1; + } + representativeNegativeScoreAndPvalue = negativeScoresAndPvalues.get(idxNegativeScores - 1); + } + + // set best one: + if (Math.abs(representativePositiveScoreAndPvalue.getLeft()) + > Math.abs(representativeNegativeScoreAndPvalue.getLeft())) { + geneset.setRepresentativeScore(representativePositiveScoreAndPvalue.getLeft()); + geneset.setRepresentativePvalue(representativePositiveScoreAndPvalue.getRight()); + } else { + geneset.setRepresentativeScore(representativeNegativeScoreAndPvalue.getLeft()); + geneset.setRepresentativePvalue(representativeNegativeScoreAndPvalue.getRight()); + } + } + } +} diff --git a/src/main/java/org/cbioportal/legacy/service/impl/GenesetServiceImpl.java b/src/main/java/org/cbioportal/legacy/service/impl/GenesetServiceImpl.java new file mode 100644 index 00000000000..5d08301db3e --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/impl/GenesetServiceImpl.java @@ -0,0 +1,62 @@ +package org.cbioportal.legacy.service.impl; + +import java.util.List; +import org.cbioportal.legacy.model.Gene; +import org.cbioportal.legacy.model.Geneset; +import org.cbioportal.legacy.model.meta.BaseMeta; +import org.cbioportal.legacy.persistence.GenesetRepository; +import org.cbioportal.legacy.service.GenesetService; +import org.cbioportal.legacy.service.exception.GenesetNotFoundException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class GenesetServiceImpl implements GenesetService { + + @Autowired private GenesetRepository genesetRepository; + + @Override + public List getAllGenesets(String projection, Integer pageSize, Integer pageNumber) { + List genesetList = genesetRepository.getAllGenesets(projection, pageSize, pageNumber); + return genesetList; + } + + @Override + public BaseMeta getMetaGenesets() { + return genesetRepository.getMetaGenesets(); + } + + @Override + public Geneset getGeneset(String genesetId) throws GenesetNotFoundException { + Geneset geneset = genesetRepository.getGeneset(genesetId); + + if (geneset == null) { + throw new GenesetNotFoundException(genesetId); + } + return geneset; + } + + @Override + public List getGenesByGenesetId(String genesetId) throws GenesetNotFoundException { + + // validate (throws exception if not found): + this.getGeneset(genesetId); + return genesetRepository.getGenesByGenesetId(genesetId); + } + + @Override + public List fetchGenesets(List genesetIds) { + + return genesetRepository.fetchGenesets(genesetIds); + } + + @Override + public String getGenesetVersion() { + String genesetVersion = genesetRepository.getGenesetVersion(); + if (genesetVersion == null) { + return ""; + } else { + return genesetVersion; + } + } +} diff --git a/src/main/java/org/cbioportal/legacy/service/impl/JwtDataAccessTokenServiceImpl.java b/src/main/java/org/cbioportal/legacy/service/impl/JwtDataAccessTokenServiceImpl.java new file mode 100644 index 00000000000..ce783133a10 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/impl/JwtDataAccessTokenServiceImpl.java @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2018 Memorial Sloan-Kettering Cancer Center. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS + * FOR A PARTICULAR PURPOSE. The software and documentation provided hereunder + * is on an "as is" basis, and Memorial Sloan-Kettering Cancer Center has no + * obligations to provide maintenance, support, updates, enhancements or + * modifications. In no event shall Memorial Sloan-Kettering Cancer Center be + * liable to any party for direct, indirect, special, incidental or + * consequential damages, including lost profits, arising out of the use of this + * software and its documentation, even if Memorial Sloan-Kettering Cancer + * Center has been advised of the possibility of such damage. + */ + +/* + * This file is part of cBioPortal. + * + * cBioPortal is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package org.cbioportal.legacy.service.impl; + +import java.util.Date; +import java.util.List; +import org.cbioportal.legacy.model.DataAccessToken; +import org.cbioportal.legacy.service.DataAccessTokenService; +import org.cbioportal.legacy.service.exception.InvalidDataAccessTokenException; +import org.cbioportal.legacy.service.util.JwtUtils; +import org.cbioportal.legacy.utils.config.annotation.ConditionalOnProperty; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.authentication.BadCredentialsException; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.Authentication; +import org.springframework.stereotype.Component; + +@Component +@ConditionalOnProperty(name = "dat.method", havingValue = "jwt") +public class JwtDataAccessTokenServiceImpl implements DataAccessTokenService { + + @Autowired private JwtUtils jwtUtils; + + private static final Logger LOG = LoggerFactory.getLogger(JwtDataAccessTokenServiceImpl.class); + + // TODO : we could add a persistence layer to store pairs of ... then a + // user can revoke all thier tokens before a particular date and we would only need to store the + // most recent revoke date for that user. But it would have to be persisted, or else a restart of + // the server would lose the memory of revocation + + @Override + public DataAccessToken createDataAccessToken(String username) { + return jwtUtils.createToken(username); + } + + @Override + public List getAllDataAccessTokens(String username) { + throw new UnsupportedOperationException( + "this implementation of (pure) JWT Data Access Tokens does not allow retrieval of stored tokens"); + } + + @Override + public DataAccessToken getDataAccessToken(String username) { + throw new UnsupportedOperationException( + "this implementation of (pure) JWT Data Access Tokens does not allow retrieval of stored tokens"); + } + + @Override + public DataAccessToken getDataAccessTokenInfo(String token) { + throw new UnsupportedOperationException( + "this implementation of (pure) JWT Data Access Tokens does not allow this operation"); + } + + @Override + public void revokeAllDataAccessTokens(String username) { + throw new UnsupportedOperationException( + "this implementation of (pure) JWT Data Access Tokens does not allow revocation of tokens"); + } + + @Override + public void revokeDataAccessToken(String token) { + throw new UnsupportedOperationException( + "this implementation of (pure) JWT Data Access Tokens does not allow revocation of tokens"); + } + + @Override + public Boolean isValid(String token) { + try { + jwtUtils.validate(token); + } catch (InvalidDataAccessTokenException idate) { + LOG.error("isValid(), " + idate); + return Boolean.FALSE; + } + return Boolean.TRUE; + } + + @Override + public String getUsername(String token) { + try { + return jwtUtils.extractSubject(token); + } catch (InvalidDataAccessTokenException idate) { + // TODO is this what we want to do? + return null; + } + } + + @Override + public Date getExpiration(String token) { + try { + return jwtUtils.extractExpirationDate(token); + } catch (InvalidDataAccessTokenException idate) { + return null; + } + } + + @Override + public Authentication createAuthenticationRequest(String token) { + + if (!isValid(token)) { + LOG.error("invalid token = " + token); + throw new BadCredentialsException("Invalid access token"); + } + String userName = getUsername(token); + + // When DaoAuthenticationProvider does authentication on user returned by + // PortalUserDetailsService + // which has password "unused", this password won't match, and then there is a BadCredentials + // exception thrown + // this is a good way to catch that the wrong authetication provider is being used. + return new UsernamePasswordAuthenticationToken(userName, "does not match unused"); + } +} diff --git a/src/main/java/org/cbioportal/legacy/service/impl/MolecularDataServiceImpl.java b/src/main/java/org/cbioportal/legacy/service/impl/MolecularDataServiceImpl.java new file mode 100644 index 00000000000..83d37c69649 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/impl/MolecularDataServiceImpl.java @@ -0,0 +1,356 @@ +package org.cbioportal.legacy.service.impl; + +import static java.util.stream.Collectors.groupingBy; +import static java.util.stream.Collectors.toMap; + +import java.util.*; +import java.util.function.Function; +import java.util.stream.Collectors; +import org.cbioportal.legacy.model.DiscreteCopyNumberData; +import org.cbioportal.legacy.model.GeneFilterQuery; +import org.cbioportal.legacy.model.GeneMolecularAlteration; +import org.cbioportal.legacy.model.GeneMolecularData; +import org.cbioportal.legacy.model.MolecularProfile; +import org.cbioportal.legacy.model.MolecularProfile.MolecularAlterationType; +import org.cbioportal.legacy.model.MolecularProfileSamples; +import org.cbioportal.legacy.model.Sample; +import org.cbioportal.legacy.model.meta.BaseMeta; +import org.cbioportal.legacy.persistence.DiscreteCopyNumberRepository; +import org.cbioportal.legacy.persistence.MolecularDataRepository; +import org.cbioportal.legacy.persistence.SampleListRepository; +import org.cbioportal.legacy.service.MolecularDataService; +import org.cbioportal.legacy.service.MolecularProfileService; +import org.cbioportal.legacy.service.SampleService; +import org.cbioportal.legacy.service.exception.MolecularProfileNotFoundException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.stereotype.Service; + +@Service +public class MolecularDataServiceImpl implements MolecularDataService { + + @Autowired private MolecularDataRepository molecularDataRepository; + @Autowired private SampleService sampleService; + @Autowired private MolecularProfileService molecularProfileService; + @Autowired private SampleListRepository sampleListRepository; + @Autowired private DiscreteCopyNumberRepository discreteCopyNumberRepository; + + @Override + public List getMolecularData( + String molecularProfileId, + String sampleListId, + List entrezGeneIds, + String projection) + throws MolecularProfileNotFoundException { + + validateMolecularProfile(molecularProfileId); + List sampleIds = sampleListRepository.getAllSampleIdsInSampleList(sampleListId); + if (sampleIds.isEmpty()) { + return Collections.emptyList(); + } + return fetchMolecularData(molecularProfileId, sampleIds, entrezGeneIds, projection); + } + + @Override + public BaseMeta getMetaMolecularData( + String molecularProfileId, String sampleListId, List entrezGeneIds) + throws MolecularProfileNotFoundException { + + BaseMeta baseMeta = new BaseMeta(); + baseMeta.setTotalCount( + getMolecularData(molecularProfileId, sampleListId, entrezGeneIds, "ID").size()); + return baseMeta; + } + + @Override + public List fetchMolecularData( + String molecularProfileId, + List sampleIds, + List entrezGeneIds, + String projection) + throws MolecularProfileNotFoundException { + + validateMolecularProfile(molecularProfileId); + List molecularDataList = new ArrayList<>(); + + MolecularProfileSamples commaSeparatedSampleIdsOfMolecularProfile = + molecularDataRepository.getCommaSeparatedSampleIdsOfMolecularProfile(molecularProfileId); + if (commaSeparatedSampleIdsOfMolecularProfile == null) { + return molecularDataList; + } + List internalSampleIds = + Arrays.stream(commaSeparatedSampleIdsOfMolecularProfile.getSplitSampleIds()) + .mapToInt(Integer::parseInt) + .boxed() + .collect(Collectors.toList()); + Map internalSampleIdsMap = new HashMap<>(); + for (int lc = 0; lc < internalSampleIds.size(); lc++) { + internalSampleIdsMap.put(internalSampleIds.get(lc), lc); + } + + List samples; + if (sampleIds == null) { + samples = sampleService.getSamplesByInternalIds(internalSampleIds); + } else { + MolecularProfile molecularProfile = + molecularProfileService.getMolecularProfile(molecularProfileId); + List studyIds = new ArrayList<>(); + sampleIds.forEach(s -> studyIds.add(molecularProfile.getCancerStudyIdentifier())); + samples = sampleService.fetchSamples(studyIds, sampleIds, "ID"); + } + + List molecularAlterations = + molecularDataRepository.getGeneMolecularAlterations( + molecularProfileId, entrezGeneIds, projection); + + for (Sample sample : samples) { + Integer indexOfSampleId = internalSampleIdsMap.get(sample.getInternalId()); + if (indexOfSampleId != null) { + for (GeneMolecularAlteration molecularAlteration : molecularAlterations) { + GeneMolecularData molecularData = new GeneMolecularData(); + molecularData.setMolecularProfileId(molecularProfileId); + molecularData.setSampleId(sample.getStableId()); + molecularData.setPatientId(sample.getPatientStableId()); + molecularData.setStudyId(sample.getCancerStudyIdentifier()); + molecularData.setEntrezGeneId(molecularAlteration.getEntrezGeneId()); + molecularData.setValue(molecularAlteration.getSplitValues()[indexOfSampleId]); + molecularData.setGene(molecularAlteration.getGene()); + molecularDataList.add(molecularData); + } + } + } + + return molecularDataList; + } + + @Override + public BaseMeta fetchMetaMolecularData( + String molecularProfileId, List sampleIds, List entrezGeneIds) + throws MolecularProfileNotFoundException { + + BaseMeta baseMeta = new BaseMeta(); + baseMeta.setTotalCount( + fetchMolecularData(molecularProfileId, sampleIds, entrezGeneIds, "ID").size()); + return baseMeta; + } + + @Override + public Iterable getMolecularAlterations( + String molecularProfileId, List entrezGeneIds, String projection) + throws MolecularProfileNotFoundException { + + validateMolecularProfile(molecularProfileId); + if ((entrezGeneIds == null || entrezGeneIds.isEmpty()) && projection.equals("SUMMARY")) { + return molecularDataRepository.getGeneMolecularAlterationsIterableFast(molecularProfileId); + } + return molecularDataRepository.getGeneMolecularAlterationsIterable( + molecularProfileId, entrezGeneIds, projection); + } + + @Override + public Integer getNumberOfSamplesInMolecularProfile(String molecularProfileId) { + + MolecularProfileSamples commaSeparatedSampleIdsOfMolecularProfile = + molecularDataRepository.getCommaSeparatedSampleIdsOfMolecularProfile(molecularProfileId); + if (commaSeparatedSampleIdsOfMolecularProfile == null) { + return null; + } + + return commaSeparatedSampleIdsOfMolecularProfile.getSplitSampleIds().length; + } + + @Override + public List getMolecularDataInMultipleMolecularProfiles( + List molecularProfileIds, + List sampleIds, + List entrezGeneIds, + String projection) { + + List molecularDataList = new ArrayList<>(); + SortedSet distinctMolecularProfileIds = new TreeSet<>(molecularProfileIds); + + Map commaSeparatedSampleIdsOfMolecularProfilesMap = + molecularDataRepository.commaSeparatedSampleIdsOfMolecularProfilesMap( + distinctMolecularProfileIds); + if (commaSeparatedSampleIdsOfMolecularProfilesMap.size() == 0) { + return molecularDataList; + } + + Map> internalSampleIdsMap = new HashMap<>(); + List allInternalSampleIds = new ArrayList<>(); + + for (String molecularProfileId : distinctMolecularProfileIds) { + List internalSampleIds = + Arrays.stream( + commaSeparatedSampleIdsOfMolecularProfilesMap + .get(molecularProfileId) + .getSplitSampleIds()) + .mapToInt(Integer::parseInt) + .boxed() + .collect(Collectors.toList()); + HashMap molecularProfileSampleMap = new HashMap(); + for (int lc = 0; lc < internalSampleIds.size(); lc++) { + molecularProfileSampleMap.put(internalSampleIds.get(lc), lc); + } + internalSampleIdsMap.put(molecularProfileId, molecularProfileSampleMap); + allInternalSampleIds.addAll(internalSampleIds); + } + + List molecularProfiles = new ArrayList<>(); + List distinctMolecularProfiles = + molecularProfileService.getMolecularProfiles(distinctMolecularProfileIds, "SUMMARY"); + Map molecularProfileMapById = + distinctMolecularProfiles.stream() + .collect(Collectors.toMap(MolecularProfile::getStableId, Function.identity())); + Map> molecularProfileMapByStudyId = + distinctMolecularProfiles.stream() + .collect(groupingBy(MolecularProfile::getCancerStudyIdentifier)); + List samples; + if (sampleIds == null) { + samples = sampleService.getSamplesByInternalIds(allInternalSampleIds); + for (String molecularProfileId : distinctMolecularProfileIds) { + internalSampleIdsMap + .get(molecularProfileId) + .keySet() + .forEach(s -> molecularProfiles.add(molecularProfileMapById.get(molecularProfileId))); + } + } else { + for (String molecularProfileId : molecularProfileIds) { + molecularProfiles.add(molecularProfileMapById.get(molecularProfileId)); + } + List studyIds = + molecularProfiles.stream() + .map(MolecularProfile::getCancerStudyIdentifier) + .collect(Collectors.toList()); + samples = sampleService.fetchSamples(studyIds, sampleIds, "ID"); + } + + // query each entrezGeneId separately so they can be cached + List molecularAlterations = + entrezGeneIds.stream() + .flatMap( + gene -> + molecularDataRepository + .getGeneMolecularAlterationsInMultipleMolecularProfiles( + distinctMolecularProfileIds, + Collections.singletonList(gene), + projection) + .stream()) + .collect(Collectors.toList()); + Map> molecularAlterationsMap = + molecularAlterations.stream() + .collect(groupingBy(GeneMolecularAlteration::getMolecularProfileId)); + + for (Sample sample : samples) { + for (MolecularProfile molecularProfile : + molecularProfileMapByStudyId.get(sample.getCancerStudyIdentifier())) { + String molecularProfileId = molecularProfile.getStableId(); + Integer indexOfSampleId = + internalSampleIdsMap.get(molecularProfileId).get(sample.getInternalId()); + if (indexOfSampleId != null && molecularAlterationsMap.containsKey(molecularProfileId)) { + for (GeneMolecularAlteration molecularAlteration : + molecularAlterationsMap.get(molecularProfileId)) { + GeneMolecularData molecularData = new GeneMolecularData(); + molecularData.setMolecularProfileId(molecularProfileId); + molecularData.setSampleId(sample.getStableId()); + molecularData.setPatientId(sample.getPatientStableId()); + molecularData.setStudyId(sample.getCancerStudyIdentifier()); + molecularData.setEntrezGeneId(molecularAlteration.getEntrezGeneId()); + try { + molecularData.setValue(molecularAlteration.getSplitValues()[indexOfSampleId]); + } catch (ArrayIndexOutOfBoundsException e) { + molecularData.setValue(null); + } + molecularData.setGene(molecularAlteration.getGene()); + molecularDataList.add(molecularData); + } + } + } + } + + return molecularDataList; + } + + @Override + public List getMolecularDataInMultipleMolecularProfilesByGeneQueries( + List molecularProfileIds, + List sampleIds, + List geneQueries, + String projection) { + // Molecular alterations for all genes in the geneQueries + List entrezGeneIds = + geneQueries.stream().map(GeneFilterQuery::getEntrezGeneId).collect(Collectors.toList()); + List molecularDataList = + getMolecularDataInMultipleMolecularProfiles( + molecularProfileIds, sampleIds, entrezGeneIds, projection); + + // All CNA events that match requested geneQueries + List copyNumberData = + discreteCopyNumberRepository.getDiscreteCopyNumbersInMultipleMolecularProfilesByGeneQueries( + molecularProfileIds, sampleIds, geneQueries, projection); + + // molecularProfile->entrezGeneId->sampleId->alterationType lookup table for CNA events + Map cnaEventLookup = + copyNumberData.stream().collect(toMap(d -> cnaEventKey(d), Function.identity())); + + // remove molecular data that is not covered by a CNA event + molecularDataList = + molecularDataList.stream() + .filter(d -> cnaEventLookup.containsKey(cnaEventKey(d))) + .collect(Collectors.toList()); + + return molecularDataList; + } + + @Override + @PreAuthorize( + "hasPermission(#molecularProfileIds, 'Collection', T(org.cbioportal.legacy.utils.security.AccessLevel).READ)") + public BaseMeta getMetaMolecularDataInMultipleMolecularProfiles( + List molecularProfileIds, List sampleIds, List entrezGeneIds) { + + BaseMeta baseMeta = new BaseMeta(); + baseMeta.setTotalCount( + getMolecularDataInMultipleMolecularProfiles( + molecularProfileIds, sampleIds, entrezGeneIds, "ID") + .size()); + return baseMeta; + } + + private void validateMolecularProfile(String molecularProfileId) + throws MolecularProfileNotFoundException { + + MolecularProfile molecularProfile = + molecularProfileService.getMolecularProfile(molecularProfileId); + + if (molecularProfile + .getMolecularAlterationType() + .equals(MolecularAlterationType.MUTATION_EXTENDED) + || molecularProfile + .getMolecularAlterationType() + .equals(MolecularAlterationType.MUTATION_UNCALLED) + || molecularProfile + .getMolecularAlterationType() + .equals(MolecularAlterationType.STRUCTURAL_VARIANT)) { + + throw new MolecularProfileNotFoundException(molecularProfileId); + } + } + + private String cnaEventKey(DiscreteCopyNumberData cna) { + StringJoiner stringJoiner = new StringJoiner("_"); + stringJoiner.add(cna.getMolecularProfileId()); + stringJoiner.add(String.valueOf(cna.getEntrezGeneId())); + stringJoiner.add(cna.getSampleId()); + stringJoiner.add(String.valueOf(cna.getAlteration())); + return stringJoiner.toString(); + } + + private String cnaEventKey(GeneMolecularData cna) { + StringJoiner stringJoiner = new StringJoiner("_"); + stringJoiner.add(cna.getMolecularProfileId()); + stringJoiner.add(String.valueOf(cna.getEntrezGeneId())); + stringJoiner.add(cna.getSampleId()); + stringJoiner.add(String.valueOf(cna.getValue())); + return stringJoiner.toString(); + } +} diff --git a/src/main/java/org/cbioportal/legacy/service/impl/MolecularProfileServiceImpl.java b/src/main/java/org/cbioportal/legacy/service/impl/MolecularProfileServiceImpl.java new file mode 100644 index 00000000000..587103604ef --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/impl/MolecularProfileServiceImpl.java @@ -0,0 +1,191 @@ +package org.cbioportal.legacy.service.impl; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import java.util.Set; +import java.util.function.Predicate; +import org.cbioportal.legacy.model.MolecularProfile; +import org.cbioportal.legacy.model.MolecularProfileCaseIdentifier; +import org.cbioportal.legacy.model.meta.BaseMeta; +import org.cbioportal.legacy.persistence.MolecularProfileRepository; +import org.cbioportal.legacy.service.MolecularProfileService; +import org.cbioportal.legacy.service.StudyService; +import org.cbioportal.legacy.service.exception.MolecularProfileNotFoundException; +import org.cbioportal.legacy.service.exception.StudyNotFoundException; +import org.cbioportal.legacy.service.util.MolecularProfileUtil; +import org.cbioportal.legacy.web.parameter.Projection; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.security.access.prepost.PostFilter; +import org.springframework.stereotype.Service; + +@Service +public class MolecularProfileServiceImpl implements MolecularProfileService { + + @Autowired private MolecularProfileRepository molecularProfileRepository; + @Autowired private StudyService studyService; + @Autowired private MolecularProfileUtil molecularProfileUtil; + + @Value("${authenticate:false}") + private String AUTHENTICATE; + + @Override + @PostFilter( + "hasPermission(filterObject, T(org.cbioportal.legacy.utils.security.AccessLevel).READ)") + public List getAllMolecularProfiles( + String projection, Integer pageSize, Integer pageNumber, String sortBy, String direction) { + + List molecularProfiles = + molecularProfileRepository.getAllMolecularProfiles( + projection, pageSize, pageNumber, sortBy, direction); + // copy the list before returning so @PostFilter doesn't taint the list stored in the + // persistence layer cache + return (AUTHENTICATE.equals("false")) + ? molecularProfiles + : new ArrayList(molecularProfiles); + } + + @Override + public BaseMeta getMetaMolecularProfiles() { + + return molecularProfileRepository.getMetaMolecularProfiles(); + } + + @Override + public MolecularProfile getMolecularProfile(String molecularProfileId) + throws MolecularProfileNotFoundException { + + MolecularProfile molecularProfile = + molecularProfileRepository.getMolecularProfile(molecularProfileId); + if (molecularProfile == null) { + throw new MolecularProfileNotFoundException(molecularProfileId); + } + + return molecularProfile; + } + + @Override + public List getMolecularProfiles( + Set molecularProfileIds, String projection) { + + return molecularProfileRepository.getMolecularProfiles(molecularProfileIds, projection); + } + + @Override + public BaseMeta getMetaMolecularProfiles(Set molecularProfileIds) { + + return molecularProfileRepository.getMetaMolecularProfiles(molecularProfileIds); + } + + @Override + public List getAllMolecularProfilesInStudy( + String studyId, + String projection, + Integer pageSize, + Integer pageNumber, + String sortBy, + String direction) + throws StudyNotFoundException { + + studyService.getStudy(studyId); + + return molecularProfileRepository.getAllMolecularProfilesInStudy( + studyId, projection, pageSize, pageNumber, sortBy, direction); + } + + @Override + public BaseMeta getMetaMolecularProfilesInStudy(String studyId) throws StudyNotFoundException { + + studyService.getStudy(studyId); + + return molecularProfileRepository.getMetaMolecularProfilesInStudy(studyId); + } + + @Override + public List getMolecularProfilesInStudies( + List studyIds, String projection) { + + return molecularProfileRepository.getMolecularProfilesInStudies(studyIds, projection); + } + + @Override + public BaseMeta getMetaMolecularProfilesInStudies(List studyIds) { + + return molecularProfileRepository.getMetaMolecularProfilesInStudies(studyIds); + } + + @Override + public List getMolecularProfilesReferredBy(String referringMolecularProfileId) + throws MolecularProfileNotFoundException { + + // validate (throws exception if profile not found): + this.getMolecularProfile(referringMolecularProfileId); + return molecularProfileRepository.getMolecularProfilesReferredBy(referringMolecularProfileId); + } + + @Override + public List getMolecularProfilesReferringTo(String referredMolecularProfileId) + throws MolecularProfileNotFoundException { + + // validate (throws exception if profile not found): + this.getMolecularProfile(referredMolecularProfileId); + return molecularProfileRepository.getMolecularProfilesReferringTo(referredMolecularProfileId); + } + + @Override + public List getMolecularProfileCaseIdentifiers( + List studyIds, List sampleIds) { + return getFilteredMolecularProfileCaseIdentifiers(studyIds, sampleIds, Optional.empty()); + } + + @Override + public List getFirstMutationProfileCaseIdentifiers( + List studyIds, List sampleIds) { + return getFirstFilteredMolecularProfileCaseIdentifiers( + studyIds, sampleIds, Optional.of(molecularProfileUtil.isMutationProfile)); + } + + @Override + public List getMutationProfileCaseIdentifiers( + List studyIds, List sampleIds) { + return getFilteredMolecularProfileCaseIdentifiers( + studyIds, sampleIds, Optional.of(molecularProfileUtil.isMutationProfile)); + } + + @Override + public List getFirstDiscreteCNAProfileCaseIdentifiers( + List studyIds, List sampleIds) { + return getFilteredMolecularProfileCaseIdentifiers( + studyIds, sampleIds, Optional.of(molecularProfileUtil.isDiscreteCNAMolecularProfile)); + } + + @Override + public List getFirstStructuralVariantProfileCaseIdentifiers( + List studyIds, List sampleIds) { + return getFirstFilteredMolecularProfileCaseIdentifiers( + studyIds, sampleIds, Optional.of(molecularProfileUtil.isStructuralVariantMolecularProfile)); + } + + private List getFirstFilteredMolecularProfileCaseIdentifiers( + List studyIds, + List sampleIds, + Optional> profileFilter) { + List molecularProfiles = + getMolecularProfilesInStudies( + studyIds.stream().distinct().toList(), Projection.SUMMARY.name()); + return molecularProfileUtil.getFirstFilteredMolecularProfileCaseIdentifiers( + molecularProfiles, studyIds, sampleIds, profileFilter); + } + + private List getFilteredMolecularProfileCaseIdentifiers( + List studyIds, + List sampleIds, + Optional> profileFilter) { + List molecularProfiles = + getMolecularProfilesInStudies( + studyIds.stream().distinct().toList(), Projection.SUMMARY.name()); + return molecularProfileUtil.getFilteredMolecularProfileCaseIdentifiers( + molecularProfiles, studyIds, sampleIds, profileFilter); + } +} diff --git a/src/main/java/org/cbioportal/legacy/service/impl/MrnaPercentileServiceImpl.java b/src/main/java/org/cbioportal/legacy/service/impl/MrnaPercentileServiceImpl.java new file mode 100644 index 00000000000..916294b9478 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/impl/MrnaPercentileServiceImpl.java @@ -0,0 +1,93 @@ +package org.cbioportal.legacy.service.impl; + +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; +import org.apache.commons.lang3.math.NumberUtils; +import org.apache.commons.math3.stat.ranking.NaNStrategy; +import org.apache.commons.math3.stat.ranking.NaturalRanking; +import org.apache.commons.math3.stat.ranking.TiesStrategy; +import org.cbioportal.legacy.model.GeneMolecularData; +import org.cbioportal.legacy.model.MolecularProfile; +import org.cbioportal.legacy.model.MrnaPercentile; +import org.cbioportal.legacy.service.MolecularDataService; +import org.cbioportal.legacy.service.MolecularProfileService; +import org.cbioportal.legacy.service.MrnaPercentileService; +import org.cbioportal.legacy.service.exception.MolecularProfileNotFoundException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class MrnaPercentileServiceImpl implements MrnaPercentileService { + + @Autowired private MolecularDataService molecularDataService; + @Autowired private MolecularProfileService molecularProfileService; + + private NaturalRanking naturalRanking = + new NaturalRanking(NaNStrategy.REMOVED, TiesStrategy.MAXIMUM); + + @Override + public List fetchMrnaPercentile( + String molecularProfileId, String sampleId, List entrezGeneIds) + throws MolecularProfileNotFoundException { + + validateMolecularProfile(molecularProfileId); + + List allMolecularDataList = + molecularDataService.fetchMolecularData(molecularProfileId, null, entrezGeneIds, "SUMMARY"); + + List molecularDataList = + allMolecularDataList.stream() + .filter(g -> g.getSampleId().equals(sampleId)) + .collect(Collectors.toList()); + + List mrnaPercentileList = new ArrayList<>(); + for (GeneMolecularData molecularData : molecularDataList) { + if (NumberUtils.isNumber(molecularData.getValue())) { + MrnaPercentile mrnaPercentile = new MrnaPercentile(); + mrnaPercentile.setEntrezGeneId(molecularData.getEntrezGeneId()); + mrnaPercentile.setSampleId(sampleId); + mrnaPercentile.setPatientId(molecularData.getPatientId()); + mrnaPercentile.setStudyId(molecularData.getStudyId()); + mrnaPercentile.setMolecularProfileId(molecularProfileId); + mrnaPercentile.setzScore(new BigDecimal(molecularData.getValue())); + + List molecularDataListOfGene = + allMolecularDataList.stream() + .filter( + g -> + g.getEntrezGeneId().equals(molecularData.getEntrezGeneId()) + && NumberUtils.isNumber(g.getValue())) + .collect(Collectors.toList()); + + double[] values = + molecularDataListOfGene.stream() + .mapToDouble(g -> Double.parseDouble(g.getValue())) + .toArray(); + double[] ranks = naturalRanking.rank(values); + double rank = ranks[molecularDataListOfGene.indexOf(molecularData)]; + double percentile = (rank / ranks.length) * 100; + mrnaPercentile.setPercentile( + BigDecimal.valueOf(percentile).setScale(2, BigDecimal.ROUND_HALF_UP)); + mrnaPercentileList.add(mrnaPercentile); + } + } + + return mrnaPercentileList; + } + + private void validateMolecularProfile(String molecularProfileId) + throws MolecularProfileNotFoundException { + + MolecularProfile molecularProfile = + molecularProfileService.getMolecularProfile(molecularProfileId); + + if (!molecularProfile + .getMolecularAlterationType() + .equals(MolecularProfile.MolecularAlterationType.MRNA_EXPRESSION)) { + + throw new MolecularProfileNotFoundException(molecularProfileId); + } + } +} diff --git a/src/main/java/org/cbioportal/legacy/service/impl/MutationServiceImpl.java b/src/main/java/org/cbioportal/legacy/service/impl/MutationServiceImpl.java new file mode 100644 index 00000000000..8c238155008 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/impl/MutationServiceImpl.java @@ -0,0 +1,207 @@ +package org.cbioportal.legacy.service.impl; + +import java.util.ArrayList; +import java.util.List; +import org.cbioportal.legacy.model.GeneFilterQuery; +import org.cbioportal.legacy.model.GenomicDataCountItem; +import org.cbioportal.legacy.model.MolecularProfile; +import org.cbioportal.legacy.model.Mutation; +import org.cbioportal.legacy.model.MutationCountByPosition; +import org.cbioportal.legacy.model.meta.MutationMeta; +import org.cbioportal.legacy.persistence.MutationRepository; +import org.cbioportal.legacy.service.MolecularProfileService; +import org.cbioportal.legacy.service.MutationService; +import org.cbioportal.legacy.service.exception.MolecularProfileNotFoundException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class MutationServiceImpl implements MutationService { + + @Autowired private MutationRepository mutationRepository; + @Autowired private MolecularProfileService molecularProfileService; + + @Override + public List getMutationsInMolecularProfileBySampleListId( + String molecularProfileId, + String sampleListId, + List entrezGeneIds, + boolean snpOnly, + String projection, + Integer pageSize, + Integer pageNumber, + String sortBy, + String direction) + throws MolecularProfileNotFoundException { + + validateMolecularProfile(molecularProfileId); + + List mutationList = + mutationRepository.getMutationsInMolecularProfileBySampleListId( + molecularProfileId, + sampleListId, + entrezGeneIds, + snpOnly, + projection, + pageSize, + pageNumber, + sortBy, + direction); + + return mutationList; + } + + @Override + public MutationMeta getMetaMutationsInMolecularProfileBySampleListId( + String molecularProfileId, String sampleListId, List entrezGeneIds) + throws MolecularProfileNotFoundException { + + validateMolecularProfile(molecularProfileId); + + return mutationRepository.getMetaMutationsInMolecularProfileBySampleListId( + molecularProfileId, sampleListId, entrezGeneIds); + } + + public List getMutationsInMultipleMolecularProfilesByGeneQueries( + List molecularProfileIds, + List sampleIds, + List geneQueries, + String projection, + Integer pageSize, + Integer pageNumber, + String sortBy, + String direction) { + + List mutationList = + mutationRepository.getMutationsInMultipleMolecularProfilesByGeneQueries( + molecularProfileIds, + sampleIds, + geneQueries, + projection, + pageSize, + pageNumber, + sortBy, + direction); + + return mutationList; + } + + @Override + public List getMutationsInMultipleMolecularProfiles( + List molecularProfileIds, + List sampleIds, + List entrezGeneIds, + String projection, + Integer pageSize, + Integer pageNumber, + String sortBy, + String direction) { + + List mutationList = + mutationRepository.getMutationsInMultipleMolecularProfiles( + molecularProfileIds, + sampleIds, + entrezGeneIds, + projection, + pageSize, + pageNumber, + sortBy, + direction); + + return mutationList; + } + + @Override + public MutationMeta getMetaMutationsInMultipleMolecularProfiles( + List molecularProfileIds, List sampleIds, List entrezGeneIds) { + + return mutationRepository.getMetaMutationsInMultipleMolecularProfiles( + molecularProfileIds, sampleIds, entrezGeneIds); + } + + @Override + public List fetchMutationsInMolecularProfile( + String molecularProfileId, + List sampleIds, + List entrezGeneIds, + boolean snpOnly, + String projection, + Integer pageSize, + Integer pageNumber, + String sortBy, + String direction) + throws MolecularProfileNotFoundException { + + validateMolecularProfile(molecularProfileId); + + List mutationList = + mutationRepository.fetchMutationsInMolecularProfile( + molecularProfileId, + sampleIds, + entrezGeneIds, + snpOnly, + projection, + pageSize, + pageNumber, + sortBy, + direction); + + return mutationList; + } + + @Override + public MutationMeta fetchMetaMutationsInMolecularProfile( + String molecularProfileId, List sampleIds, List entrezGeneIds) + throws MolecularProfileNotFoundException { + + validateMolecularProfile(molecularProfileId); + + return mutationRepository.fetchMetaMutationsInMolecularProfile( + molecularProfileId, sampleIds, entrezGeneIds); + } + + @Override + public List fetchMutationCountsByPosition( + List entrezGeneIds, List proteinPosStarts, List proteinPosEnds) { + + List mutationCountByPositionList = new ArrayList<>(); + for (int i = 0; i < entrezGeneIds.size(); i++) { + + MutationCountByPosition mutationCountByPosition = + mutationRepository.getMutationCountByPosition( + entrezGeneIds.get(i), proteinPosStarts.get(i), proteinPosEnds.get(i)); + mutationCountByPositionList.add(mutationCountByPosition); + } + + return mutationCountByPositionList; + } + + @Override + public GenomicDataCountItem getMutationCountsByType( + List molecularProfileIds, + List sampleIds, + List entrezGeneIds, + String profileType) { + return mutationRepository.getMutationCountsByType( + molecularProfileIds, sampleIds, entrezGeneIds, profileType); + } + + private MolecularProfile validateMolecularProfile(String molecularProfileId) + throws MolecularProfileNotFoundException { + + MolecularProfile molecularProfile = + molecularProfileService.getMolecularProfile(molecularProfileId); + + if (!(molecularProfile + .getMolecularAlterationType() + .equals(MolecularProfile.MolecularAlterationType.MUTATION_EXTENDED) + || molecularProfile + .getMolecularAlterationType() + .equals(MolecularProfile.MolecularAlterationType.MUTATION_UNCALLED))) { + + throw new MolecularProfileNotFoundException(molecularProfileId); + } + + return molecularProfile; + } +} diff --git a/src/main/java/org/cbioportal/legacy/service/impl/MutationSpectrumServiceImpl.java b/src/main/java/org/cbioportal/legacy/service/impl/MutationSpectrumServiceImpl.java new file mode 100644 index 00000000000..6c9dceee9e2 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/impl/MutationSpectrumServiceImpl.java @@ -0,0 +1,98 @@ +package org.cbioportal.legacy.service.impl; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; +import org.cbioportal.legacy.model.Mutation; +import org.cbioportal.legacy.model.MutationSpectrum; +import org.cbioportal.legacy.service.MutationService; +import org.cbioportal.legacy.service.MutationSpectrumService; +import org.cbioportal.legacy.service.exception.MolecularProfileNotFoundException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class MutationSpectrumServiceImpl implements MutationSpectrumService { + + @Autowired private MutationService mutationService; + + @Override + public List getMutationSpectrums(String molecularProfileId, String sampleListId) + throws MolecularProfileNotFoundException { + + List mutations = + mutationService.getMutationsInMolecularProfileBySampleListId( + molecularProfileId, sampleListId, null, true, "SUMMARY", null, null, null, null); + + return createMutationSpectrums(molecularProfileId, mutations); + } + + @Override + public List fetchMutationSpectrums( + String molecularProfileId, List sampleIds) throws MolecularProfileNotFoundException { + + List mutations = + mutationService.fetchMutationsInMolecularProfile( + molecularProfileId, sampleIds, null, true, "SUMMARY", null, null, null, null); + + return createMutationSpectrums(molecularProfileId, mutations); + } + + private List createMutationSpectrums( + String molecularProfileId, List mutations) { + + Map> mutationMap = + mutations.stream().collect(Collectors.groupingBy(Mutation::getSampleId)); + + List mutationSpectrums = new ArrayList<>(); + for (String sampleId : mutationMap.keySet()) { + + List mutationsInSample = mutationMap.get(sampleId); + MutationSpectrum mutationSpectrum = new MutationSpectrum(); + mutationSpectrum.setMolecularProfileId(molecularProfileId); + mutationSpectrum.setSampleId(sampleId); + mutationSpectrum.setPatientId(mutationsInSample.get(0).getPatientId()); + mutationSpectrum.setStudyId(mutationsInSample.get(0).getStudyId()); + mutationSpectrum.setCtoA( + Math.toIntExact( + mutationsInSample.stream() + .filter(m -> checkSpectrum(m, "C", "A") || checkSpectrum(m, "G", "T")) + .count())); + mutationSpectrum.setCtoG( + Math.toIntExact( + mutationsInSample.stream() + .filter(m -> checkSpectrum(m, "C", "G") || checkSpectrum(m, "G", "C")) + .count())); + mutationSpectrum.setCtoT( + Math.toIntExact( + mutationsInSample.stream() + .filter(m -> checkSpectrum(m, "C", "T") || checkSpectrum(m, "G", "A")) + .count())); + mutationSpectrum.setTtoA( + Math.toIntExact( + mutationsInSample.stream() + .filter(m -> checkSpectrum(m, "T", "A") || checkSpectrum(m, "A", "T")) + .count())); + mutationSpectrum.setTtoC( + Math.toIntExact( + mutationsInSample.stream() + .filter(m -> checkSpectrum(m, "T", "C") || checkSpectrum(m, "A", "G")) + .count())); + mutationSpectrum.setTtoG( + Math.toIntExact( + mutationsInSample.stream() + .filter(m -> checkSpectrum(m, "T", "G") || checkSpectrum(m, "A", "C")) + .count())); + mutationSpectrums.add(mutationSpectrum); + } + + return mutationSpectrums; + } + + private boolean checkSpectrum(Mutation mutation, String referenceAllele, String tumorSeqAllele) { + + return mutation.getReferenceAllele().equals(referenceAllele) + && mutation.getTumorSeqAllele().equals(tumorSeqAllele); + } +} diff --git a/src/main/java/org/cbioportal/legacy/service/impl/NamespaceAttributeServiceImpl.java b/src/main/java/org/cbioportal/legacy/service/impl/NamespaceAttributeServiceImpl.java new file mode 100644 index 00000000000..26b6d437975 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/impl/NamespaceAttributeServiceImpl.java @@ -0,0 +1,43 @@ +package org.cbioportal.legacy.service.impl; + +import java.util.List; +import org.cbioportal.legacy.model.NamespaceAttribute; +import org.cbioportal.legacy.model.NamespaceAttributeCount; +import org.cbioportal.legacy.persistence.NamespaceRepository; +import org.cbioportal.legacy.service.NamespaceAttributeService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class NamespaceAttributeServiceImpl implements NamespaceAttributeService { + + private final NamespaceRepository namespaceRepository; + + @Autowired + public NamespaceAttributeServiceImpl(NamespaceRepository namespaceRepository) { + this.namespaceRepository = namespaceRepository; + } + + @Override + public List fetchNamespaceAttributes(List studyIds) { + + List outerNamespaceKeys = + namespaceRepository.getNamespaceOuterKey(studyIds); + + return outerNamespaceKeys.stream() + .flatMap( + outerNamespaceKey -> + namespaceRepository + .getNamespaceInnerKey(outerNamespaceKey.getOuterKey(), studyIds) + .stream()) + .toList(); + } + + @Override + public List fetchNamespaceAttributeCountsBySampleIds( + List studyIds, List sampleIds, List namespaceAttributes) { + + return namespaceRepository.getNamespaceAttributeCountsBySampleIds( + studyIds, sampleIds, namespaceAttributes); + } +} diff --git a/src/main/java/org/cbioportal/legacy/service/impl/NamespaceDataServiceImpl.java b/src/main/java/org/cbioportal/legacy/service/impl/NamespaceDataServiceImpl.java new file mode 100644 index 00000000000..48d76a81caf --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/impl/NamespaceDataServiceImpl.java @@ -0,0 +1,98 @@ +package org.cbioportal.legacy.service.impl; + +import java.util.ArrayList; +import java.util.List; +import org.cbioportal.legacy.model.NamespaceAttribute; +import org.cbioportal.legacy.model.NamespaceData; +import org.cbioportal.legacy.model.NamespaceDataCount; +import org.cbioportal.legacy.model.NamespaceDataCountItem; +import org.cbioportal.legacy.persistence.NamespaceRepository; +import org.cbioportal.legacy.service.NamespaceDataService; +import org.cbioportal.legacy.web.parameter.NamespaceDataFilter; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class NamespaceDataServiceImpl implements NamespaceDataService { + + private final NamespaceRepository namespaceRepository; + + @Autowired + public NamespaceDataServiceImpl(NamespaceRepository namespaceRepository) { + this.namespaceRepository = namespaceRepository; + } + + @Override + public List fetchNamespaceData( + List studyIds, + List sampleIds, + List namespaceDataFitlers) { + + if (sampleIds.isEmpty()) { + return new ArrayList<>(); + } + + return namespaceDataFitlers.stream() + .map( + namespaceDataFilter -> { + String outerKey = namespaceDataFilter.getOuterKey(); + String innerKey = namespaceDataFilter.getInnerKey(); + + return namespaceRepository.getNamespaceData(studyIds, sampleIds, outerKey, innerKey); + }) + .flatMap(List::stream) + .toList(); + } + + @Override + public List fetchNamespaceDataForComparison( + List studyIds, + List sampleIds, + NamespaceAttribute namespaceAttribute, + List values) { + + if (sampleIds.isEmpty()) { + return new ArrayList<>(); + } + + return values.stream() + .map( + value -> { + String outerKey = namespaceAttribute.getOuterKey(); + String innerKey = namespaceAttribute.getInnerKey(); + + return namespaceRepository.getNamespaceDataForComparison( + studyIds, sampleIds, outerKey, innerKey, value); + }) + .flatMap(List::stream) + .toList(); + } + + @Override + public List fetchNamespaceDataCounts( + List studyIds, List sampleIds, List namespaceAttributes) { + + return namespaceAttributes.stream() + .map( + namespaceAttribute -> { + String outerKey = namespaceAttribute.getOuterKey(); + String innerKey = namespaceAttribute.getInnerKey(); + + List namespaceDataCounts = + namespaceRepository.getNamespaceDataCounts( + studyIds, sampleIds, outerKey, innerKey); + + if (namespaceDataCounts == null || namespaceDataCounts.isEmpty()) { + return null; + } + + NamespaceDataCountItem namespaceDataCountItem = new NamespaceDataCountItem(); + namespaceDataCountItem.setOuterKey(outerKey); + namespaceDataCountItem.setInnerKey(innerKey); + namespaceDataCountItem.setCounts(namespaceDataCounts); + + return namespaceDataCountItem; + }) + .toList(); + } +} diff --git a/src/main/java/org/cbioportal/legacy/service/impl/PatientServiceImpl.java b/src/main/java/org/cbioportal/legacy/service/impl/PatientServiceImpl.java new file mode 100644 index 00000000000..f63df0c043b --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/impl/PatientServiceImpl.java @@ -0,0 +1,108 @@ +package org.cbioportal.legacy.service.impl; + +import java.util.ArrayList; +import java.util.List; +import org.cbioportal.legacy.model.Patient; +import org.cbioportal.legacy.model.meta.BaseMeta; +import org.cbioportal.legacy.persistence.PatientRepository; +import org.cbioportal.legacy.service.PatientService; +import org.cbioportal.legacy.service.StudyService; +import org.cbioportal.legacy.service.exception.PatientNotFoundException; +import org.cbioportal.legacy.service.exception.StudyNotFoundException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.security.access.prepost.PostFilter; +import org.springframework.stereotype.Service; + +@Service +public class PatientServiceImpl implements PatientService { + + @Autowired private PatientRepository patientRepository; + @Autowired private StudyService studyService; + + @Value("${authenticate:false}") + private String AUTHENTICATE; + + @Override + @PostFilter( + "hasPermission(filterObject, T(org.cbioportal.legacy.utils.security.AccessLevel).READ)") + public List getAllPatients( + String keyword, + String projection, + Integer pageSize, + Integer pageNumber, + String sortBy, + String direction) { + + List patients = + patientRepository.getAllPatients( + keyword, projection, pageSize, pageNumber, sortBy, direction); + // copy the list before returning so @PostFilter doesn't taint the list stored in the + // persistence layer cache + return (AUTHENTICATE.equals("false")) ? patients : new ArrayList(patients); + } + + @Override + public BaseMeta getMetaPatients(String keyword) { + + return patientRepository.getMetaPatients(keyword); + } + + @Override + public List getAllPatientsInStudy( + String studyId, + String projection, + Integer pageSize, + Integer pageNumber, + String sortBy, + String direction) + throws StudyNotFoundException { + + studyService.getStudy(studyId); + + return patientRepository.getAllPatientsInStudy( + studyId, projection, pageSize, pageNumber, sortBy, direction); + } + + @Override + public BaseMeta getMetaPatientsInStudy(String studyId) throws StudyNotFoundException { + + studyService.getStudy(studyId); + + return patientRepository.getMetaPatientsInStudy(studyId); + } + + @Override + public Patient getPatientInStudy(String studyId, String patientId) + throws PatientNotFoundException, StudyNotFoundException { + + studyService.getStudy(studyId); + + Patient patient = patientRepository.getPatientInStudy(studyId, patientId); + + if (patient == null) { + throw new PatientNotFoundException(studyId, patientId); + } + + return patient; + } + + @Override + public List fetchPatients( + List studyIds, List patientIds, String projection) { + + return patientRepository.fetchPatients(studyIds, patientIds, projection); + } + + @Override + public BaseMeta fetchMetaPatients(List studyIds, List patientIds) { + + return patientRepository.fetchMetaPatients(studyIds, patientIds); + } + + @Override + public List getPatientsOfSamples(List studyIds, List sampleIds) { + + return patientRepository.getPatientsOfSamples(studyIds, sampleIds); + } +} diff --git a/src/main/java/org/cbioportal/legacy/service/impl/ReadPermissionServiceImpl.java b/src/main/java/org/cbioportal/legacy/service/impl/ReadPermissionServiceImpl.java new file mode 100644 index 00000000000..cf091832175 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/impl/ReadPermissionServiceImpl.java @@ -0,0 +1,34 @@ +package org.cbioportal.legacy.service.impl; + +import java.util.Collection; +import org.cbioportal.application.security.CancerStudyPermissionEvaluator; +import org.cbioportal.legacy.model.ReadPermission; +import org.cbioportal.legacy.service.ReadPermissionService; +import org.cbioportal.legacy.utils.security.AccessLevel; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.core.Authentication; +import org.springframework.stereotype.Service; + +@Service +public class ReadPermissionServiceImpl implements ReadPermissionService { + + // The CancerStudyPermissionEvaluator bean does not exist on portals w/o user-authentication + @Autowired(required = false) + private CancerStudyPermissionEvaluator cancerStudyPermissionEvaluator; + + @Override + public void setReadPermission( + Collection entities, Authentication authentication) { + entities.forEach( + s -> { + // Add user read-permission to each entity when authentication is used (defaults + // to 'true' on portals w/o user-authentication). + boolean hasReadPermission = + authentication == null + || cancerStudyPermissionEvaluator == null + || cancerStudyPermissionEvaluator.hasPermission( + authentication, s, AccessLevel.READ); + s.setReadPermission(hasReadPermission); + }); + } +} diff --git a/src/main/java/org/cbioportal/legacy/service/impl/RedisCacheStatisticsServiceImpl.java b/src/main/java/org/cbioportal/legacy/service/impl/RedisCacheStatisticsServiceImpl.java new file mode 100644 index 00000000000..c465e75798c --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/impl/RedisCacheStatisticsServiceImpl.java @@ -0,0 +1,96 @@ +package org.cbioportal.legacy.service.impl; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.function.Function; +import java.util.stream.Collectors; +import org.cbioportal.legacy.persistence.util.CustomKeyGenerator; +import org.cbioportal.legacy.persistence.util.CustomRedisCache; +import org.cbioportal.legacy.service.CacheStatisticsService; +import org.cbioportal.legacy.service.exception.CacheNotFoundException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; +import org.springframework.cache.Cache; +import org.springframework.cache.CacheManager; +import org.springframework.security.access.AccessDeniedException; +import org.springframework.stereotype.Service; + +@Service +@ConditionalOnExpression( + "#{environment['persistence.cache_type'] == 'redis' or environment['persistence.cache_type_clickhouse'] == 'redis'}") +public class RedisCacheStatisticsServiceImpl implements CacheStatisticsService { + + @Autowired public CacheManager cacheManager; + + @Value("${cache.statistics_endpoint_enabled:false}") + public boolean cacheStatisticsEndpointEnabled; + + protected void checkIfCacheStatisticsEndpointEnabled() { + if (!cacheStatisticsEndpointEnabled) { + throw new AccessDeniedException( + "Cache statistics is not enabled for this instance of the portal."); + } + } + + @Override + public List getKeyCountsPerClass(String cacheName) throws CacheNotFoundException { + checkIfCacheStatisticsEndpointEnabled(); + if (!cacheManager.getCacheNames().contains(cacheName)) { + throw new CacheNotFoundException(cacheName); + } + + Cache cache = cacheManager.getCache(cacheName); + if (cache instanceof CustomRedisCache) { + CustomRedisCache redisCache = (CustomRedisCache) cache; + Map keyCountPerClass = + redisCache + .getNativeCache() + .getKeys() + .getKeysStream() + .filter(k -> k.startsWith(redisCache.getName())) + // cut off cache name from key + .map( + k -> + k.substring( + redisCache.getName().length() + CustomRedisCache.DELIMITER.length())) + // cut off everything after the class of the class of the cached method + .map(k -> k.substring(0, k.indexOf(CustomKeyGenerator.CACHE_KEY_PARAM_DELIMITER))) + .collect(Collectors.groupingBy(Function.identity(), Collectors.counting())); + + return keyCountPerClass.entrySet().stream() + .map(e -> e.getKey() + ": " + e.getValue() + " keys") + .collect(Collectors.toList()); + } + + return new ArrayList<>(); + } + + @Override + public List getKeysInCache(String cacheName) throws CacheNotFoundException { + checkIfCacheStatisticsEndpointEnabled(); + if (!cacheManager.getCacheNames().contains(cacheName)) { + throw new CacheNotFoundException(cacheName); + } + + Cache cache = cacheManager.getCache(cacheName); + + if (cache instanceof CustomRedisCache) { + CustomRedisCache redisCache = (CustomRedisCache) cache; + return redisCache + .getNativeCache() + .getKeys() + .getKeysStream() + .filter(k -> k.startsWith(redisCache.getName())) + .collect(Collectors.toList()); + } + + return new ArrayList<>(); + } + + @Override + public String getCacheStatistics() { + throw new UnsupportedOperationException("Requested API is not implemented yet"); + } +} diff --git a/src/main/java/org/cbioportal/legacy/service/impl/ReferenceGenomeGeneServiceImpl.java b/src/main/java/org/cbioportal/legacy/service/impl/ReferenceGenomeGeneServiceImpl.java new file mode 100644 index 00000000000..cb84e1f29e0 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/impl/ReferenceGenomeGeneServiceImpl.java @@ -0,0 +1,45 @@ +package org.cbioportal.legacy.service.impl; + +import java.util.List; +import org.cbioportal.legacy.model.ReferenceGenomeGene; +import org.cbioportal.legacy.persistence.ReferenceGenomeGeneRepository; +import org.cbioportal.legacy.service.ReferenceGenomeGeneService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class ReferenceGenomeGeneServiceImpl implements ReferenceGenomeGeneService { + + @Autowired private ReferenceGenomeGeneRepository referenceGenomeGeneRepository; + + @Override + public List fetchAllReferenceGenomeGenes(String genomeName) { + + return referenceGenomeGeneRepository.getAllGenesByGenomeName(genomeName); + } + + @Override + public List fetchGenesByGenomeName( + List geneIds, String genomeName) { + return referenceGenomeGeneRepository.getGenesByGenomeName(geneIds, genomeName); + } + + @Override + public List fetchGenesByHugoGeneSymbolsAndGenomeName( + List geneIds, String genomeName) { + return referenceGenomeGeneRepository.getGenesByHugoGeneSymbolsAndGenomeName( + geneIds, genomeName); + } + + @Override + public ReferenceGenomeGene getReferenceGenomeGene(Integer geneId, String genomeName) { + + return referenceGenomeGeneRepository.getReferenceGenomeGene(geneId, genomeName); + } + + @Override + public ReferenceGenomeGene getReferenceGenomeGeneByEntityId(Integer entityId, String genomeName) { + + return referenceGenomeGeneRepository.getReferenceGenomeGeneByEntityId(entityId, genomeName); + } +} diff --git a/src/main/java/org/cbioportal/legacy/service/impl/ResourceDataServiceImpl.java b/src/main/java/org/cbioportal/legacy/service/impl/ResourceDataServiceImpl.java new file mode 100644 index 00000000000..2f843bd02df --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/impl/ResourceDataServiceImpl.java @@ -0,0 +1,103 @@ +package org.cbioportal.legacy.service.impl; + +import java.util.ArrayList; +import java.util.List; +import org.cbioportal.legacy.model.ResourceData; +import org.cbioportal.legacy.persistence.ResourceDataRepository; +import org.cbioportal.legacy.service.PatientService; +import org.cbioportal.legacy.service.ResourceDataService; +import org.cbioportal.legacy.service.SampleService; +import org.cbioportal.legacy.service.StudyService; +import org.cbioportal.legacy.service.exception.PatientNotFoundException; +import org.cbioportal.legacy.service.exception.SampleNotFoundException; +import org.cbioportal.legacy.service.exception.StudyNotFoundException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class ResourceDataServiceImpl implements ResourceDataService { + + @Autowired private ResourceDataRepository resourceDataRepository; + @Autowired private StudyService studyService; + @Autowired private PatientService patientService; + @Autowired private SampleService sampleService; + + @Override + public List getAllResourceDataOfSampleInStudy( + String studyId, + String sampleId, + String resourceId, + String projection, + Integer pageSize, + Integer pageNumber, + String sortBy, + String direction) + throws SampleNotFoundException, StudyNotFoundException { + sampleService.getSampleInStudy(studyId, sampleId); + + return resourceDataRepository.getAllResourceDataOfSampleInStudy( + studyId, sampleId, resourceId, projection, pageSize, pageNumber, sortBy, direction); + } + + @Override + public List getAllResourceDataOfPatientInStudy( + String studyId, + String patientId, + String resourceId, + String projection, + Integer pageSize, + Integer pageNumber, + String sortBy, + String direction) + throws PatientNotFoundException, StudyNotFoundException { + + patientService.getPatientInStudy(studyId, patientId); + + return resourceDataRepository.getAllResourceDataOfPatientInStudy( + studyId, patientId, resourceId, projection, pageSize, pageNumber, sortBy, direction); + } + + @Override + public List getAllResourceDataForStudy( + String studyId, + String resourceId, + String projection, + Integer pageSize, + Integer pageNumber, + String sortBy, + String direction) + throws StudyNotFoundException { + + studyService.getStudy(studyId); + + return resourceDataRepository.getAllResourceDataForStudy( + studyId, resourceId, projection, pageSize, pageNumber, sortBy, direction); + } + + @Override + public List getAllResourceDataForStudyPatientSample( + String studyId, + String resourceId, + String projection, + Integer pageSize, + Integer pageNumber, + String sortBy, + String direction) + throws StudyNotFoundException { + + studyService.getStudy(studyId); + + List results = new ArrayList(); + + results.addAll( + resourceDataRepository.getAllResourceDataForStudy( + studyId, resourceId, projection, pageSize, pageNumber, sortBy, direction)); + results.addAll( + resourceDataRepository.getResourceDataForAllPatientsInStudy( + studyId, resourceId, projection, pageSize, pageNumber, sortBy, direction)); + results.addAll( + resourceDataRepository.getResourceDataForAllSamplesInStudy( + studyId, resourceId, projection, pageSize, pageNumber, sortBy, direction)); + return results; + } +} diff --git a/src/main/java/org/cbioportal/legacy/service/impl/ResourceDefinitionServiceImpl.java b/src/main/java/org/cbioportal/legacy/service/impl/ResourceDefinitionServiceImpl.java new file mode 100644 index 00000000000..b12d0f05693 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/impl/ResourceDefinitionServiceImpl.java @@ -0,0 +1,58 @@ +package org.cbioportal.legacy.service.impl; + +import java.util.Collections; +import java.util.List; +import org.cbioportal.legacy.model.ResourceDefinition; +import org.cbioportal.legacy.persistence.ResourceDefinitionRepository; +import org.cbioportal.legacy.service.ResourceDefinitionService; +import org.cbioportal.legacy.service.StudyService; +import org.cbioportal.legacy.service.exception.ResourceDefinitionNotFoundException; +import org.cbioportal.legacy.service.exception.StudyNotFoundException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class ResourceDefinitionServiceImpl implements ResourceDefinitionService { + + @Autowired private ResourceDefinitionRepository resourceDefinitionRepository; + @Autowired private StudyService studyService; + + @Override + public ResourceDefinition getResourceDefinition(String studyId, String resourceId) + throws ResourceDefinitionNotFoundException, StudyNotFoundException { + + studyService.getStudy(studyId); + + ResourceDefinition resourceDefinition = + resourceDefinitionRepository.getResourceDefinition(studyId, resourceId); + + if (resourceDefinition == null) { + throw new ResourceDefinitionNotFoundException(studyId, resourceId); + } + + return resourceDefinition; + } + + @Override + public List getAllResourceDefinitionsInStudy( + String studyId, + String projection, + Integer pageSize, + Integer pageNumber, + String sortBy, + String direction) + throws StudyNotFoundException { + + studyService.getStudy(studyId); + + return resourceDefinitionRepository.fetchResourceDefinitions( + Collections.singletonList(studyId), projection, pageSize, pageNumber, sortBy, direction); + } + + @Override + public List fetchResourceDefinitions(List studyIds, String projection) + throws StudyNotFoundException { + return resourceDefinitionRepository.fetchResourceDefinitions( + studyIds, projection, null, null, null, null); + } +} diff --git a/src/main/java/org/cbioportal/legacy/service/impl/SampleListServiceImpl.java b/src/main/java/org/cbioportal/legacy/service/impl/SampleListServiceImpl.java new file mode 100644 index 00000000000..749edca1500 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/impl/SampleListServiceImpl.java @@ -0,0 +1,161 @@ +package org.cbioportal.legacy.service.impl; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; +import org.cbioportal.legacy.model.SampleList; +import org.cbioportal.legacy.model.SampleListToSampleId; +import org.cbioportal.legacy.model.meta.BaseMeta; +import org.cbioportal.legacy.persistence.SampleListRepository; +import org.cbioportal.legacy.service.SampleListService; +import org.cbioportal.legacy.service.StudyService; +import org.cbioportal.legacy.service.exception.SampleListNotFoundException; +import org.cbioportal.legacy.service.exception.StudyNotFoundException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.security.access.prepost.PostFilter; +import org.springframework.stereotype.Service; + +@Service +public class SampleListServiceImpl implements SampleListService { + + @Autowired private SampleListRepository sampleListRepository; + @Autowired private StudyService studyService; + + @Value("${authenticate:false}") + private String AUTHENTICATE; + + @Override + @PostFilter( + "hasPermission(filterObject, T(org.cbioportal.legacy.utils.security.AccessLevel).READ)") + public List getAllSampleLists( + String projection, Integer pageSize, Integer pageNumber, String sortBy, String direction) { + + List sampleListsFromRepo = + sampleListRepository.getAllSampleLists(projection, pageSize, pageNumber, sortBy, direction); + // copy the list before returning so @PostFilter doesn't taint the list stored in the + // persistence layer cache + List sampleLists = + (AUTHENTICATE.equals("false")) + ? sampleListsFromRepo + : new ArrayList(sampleListsFromRepo); + + if (projection.equals("DETAILED")) { + addSampleIds(sampleLists); + addSampleCounts(sampleLists); + } + + return sampleLists; + } + + @Override + public BaseMeta getMetaSampleLists() { + + return sampleListRepository.getMetaSampleLists(); + } + + @Override + public SampleList getSampleList(String sampleListId) throws SampleListNotFoundException { + + SampleList sampleList = sampleListRepository.getSampleList(sampleListId); + if (sampleList == null) { + throw new SampleListNotFoundException(sampleListId); + } + + List sampleListToSampleIds = + sampleListRepository.getSampleListSampleIds(Arrays.asList(sampleList.getListId())); + sampleList.setSampleIds( + sampleListToSampleIds.stream() + .map(SampleListToSampleId::getSampleId) + .collect(Collectors.toList())); + sampleList.setSampleCount(sampleList.getSampleIds().size()); + return sampleList; + } + + @Override + public List getAllSampleListsInStudy( + String studyId, + String projection, + Integer pageSize, + Integer pageNumber, + String sortBy, + String direction) + throws StudyNotFoundException { + + studyService.getStudy(studyId); + + List sampleLists = + sampleListRepository.getAllSampleListsInStudies( + Arrays.asList(studyId), projection, pageSize, pageNumber, sortBy, direction); + + if (projection.equals("DETAILED")) { + addSampleIds(sampleLists); + addSampleCounts(sampleLists); + } + + return sampleLists; + } + + @Override + public BaseMeta getMetaSampleListsInStudy(String studyId) throws StudyNotFoundException { + + studyService.getStudy(studyId); + + return sampleListRepository.getMetaSampleListsInStudy(studyId); + } + + @Override + public List getAllSampleIdsInSampleList(String sampleListId) + throws SampleListNotFoundException { + + getSampleList(sampleListId); + + return sampleListRepository.getAllSampleIdsInSampleList(sampleListId); + } + + @Override + public List fetchSampleLists(List sampleListIds, String projection) { + + List sampleLists = sampleListRepository.getSampleLists(sampleListIds, projection); + + if (projection.equals("DETAILED")) { + addSampleIds(sampleLists); + addSampleCounts(sampleLists); + } + + return sampleLists; + } + + private void addSampleCounts(List sampleLists) { + + sampleLists.forEach(s -> s.setSampleCount(s.getSampleIds().size())); + } + + private void addSampleIds(List sampleLists) { + + for (SampleList sampleList : sampleLists) { + sampleList.setSampleIds( + sampleListRepository + .getSampleListSampleIds(Arrays.asList(sampleList.getListId())) + .stream() + .map(SampleListToSampleId::getSampleId) + .collect(Collectors.toList())); + } + } + + @Override + public List getAllSampleListsInStudies(List studyIds, String projection) { + + List sampleLists = + sampleListRepository.getAllSampleListsInStudies( + studyIds, projection, null, null, null, null); + + if (projection.equals("DETAILED")) { + addSampleIds(sampleLists); + addSampleCounts(sampleLists); + } + + return sampleLists; + } +} diff --git a/src/main/java/org/cbioportal/legacy/service/impl/SampleServiceImpl.java b/src/main/java/org/cbioportal/legacy/service/impl/SampleServiceImpl.java new file mode 100644 index 00000000000..8b8fde73ff8 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/impl/SampleServiceImpl.java @@ -0,0 +1,244 @@ +package org.cbioportal.legacy.service.impl; + +import java.util.*; +import java.util.stream.Collectors; +import org.cbioportal.legacy.model.Sample; +import org.cbioportal.legacy.model.meta.BaseMeta; +import org.cbioportal.legacy.persistence.CopyNumberSegmentRepository; +import org.cbioportal.legacy.persistence.MolecularProfileRepository; +import org.cbioportal.legacy.persistence.SampleListRepository; +import org.cbioportal.legacy.persistence.SampleRepository; +import org.cbioportal.legacy.service.PatientService; +import org.cbioportal.legacy.service.SampleService; +import org.cbioportal.legacy.service.StudyService; +import org.cbioportal.legacy.service.exception.PatientNotFoundException; +import org.cbioportal.legacy.service.exception.SampleNotFoundException; +import org.cbioportal.legacy.service.exception.StudyNotFoundException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Service; + +@Service +public class SampleServiceImpl implements SampleService { + + private static final String SEQUENCED = "_sequenced"; + private static final String STRUCTURAL_VARIANT = "_sv"; + + @Autowired private SampleRepository sampleRepository; + @Autowired private StudyService studyService; + @Autowired private PatientService patientService; + @Autowired private SampleListRepository sampleListRepository; + @Autowired private CopyNumberSegmentRepository copyNumberSegmentRepository; + @Autowired private MolecularProfileRepository molecularProfileRepository; + + @Override + public List getAllSamples( + String keyword, + List studyIds, + String projection, + Integer pageSize, + Integer pageNumber, + String sort, + String direction) { + List samples = + sampleRepository.getAllSamples( + keyword, studyIds, projection, pageSize, pageNumber, sort, direction); + processSamples(samples, projection); + return samples; + } + + @Override + public BaseMeta getMetaSamples(String keyword, List studyIds) { + return sampleRepository.getMetaSamples(keyword, studyIds); + } + + @Override + public List getAllSamplesInStudy( + String studyId, + String projection, + Integer pageSize, + Integer pageNumber, + String sortBy, + String direction) + throws StudyNotFoundException { + + studyService.getStudy(studyId); + List samples = + sampleRepository.getAllSamplesInStudy( + studyId, projection, pageSize, pageNumber, sortBy, direction); + + processSamples(samples, projection); + return samples; + } + + @Override + public BaseMeta getMetaSamplesInStudy(String studyId) throws StudyNotFoundException { + + studyService.getStudy(studyId); + + return sampleRepository.getMetaSamplesInStudy(studyId); + } + + @Override + public List getAllSamplesInStudies( + List studyIds, + String projection, + Integer pageSize, + Integer pageNumber, + String sortBy, + String direction) { + + return sampleRepository.getAllSamplesInStudies( + studyIds, projection, pageSize, pageNumber, sortBy, direction); + } + + @Override + public Sample getSampleInStudy(String studyId, String sampleId) + throws SampleNotFoundException, StudyNotFoundException { + + studyService.getStudy(studyId); + Sample sample = sampleRepository.getSampleInStudy(studyId, sampleId); + + if (sample == null) { + throw new SampleNotFoundException(studyId, sampleId); + } + + processSamples(Arrays.asList(sample), "DETAILED"); + return sample; + } + + @Override + public List getAllSamplesOfPatientInStudy( + String studyId, + String patientId, + String projection, + Integer pageSize, + Integer pageNumber, + String sortBy, + String direction) + throws StudyNotFoundException, PatientNotFoundException { + + patientService.getPatientInStudy(studyId, patientId); + List samples = + sampleRepository.getAllSamplesOfPatientInStudy( + studyId, patientId, projection, pageSize, pageNumber, sortBy, direction); + + processSamples(samples, projection); + return samples; + } + + @Override + public BaseMeta getMetaSamplesOfPatientInStudy(String studyId, String patientId) + throws StudyNotFoundException, PatientNotFoundException { + + patientService.getPatientInStudy(studyId, patientId); + + return sampleRepository.getMetaSamplesOfPatientInStudy(studyId, patientId); + } + + @Override + public List getAllSamplesOfPatientsInStudy( + String studyId, List patientIds, String projection) { + + List samples = + sampleRepository.getAllSamplesOfPatientsInStudy(studyId, patientIds, projection); + + processSamples(samples, projection); + return samples; + } + + @Override + public List getSamplesOfPatientsInMultipleStudies( + List studyIds, List patientIds, String projection) { + + List samples = + sampleRepository.getSamplesOfPatientsInMultipleStudies(studyIds, patientIds, projection); + + processSamples(samples, projection); + return samples; + } + + @Override + public List fetchSamples( + List studyIds, List sampleIds, String projection) { + + List samples = sampleRepository.fetchSamples(studyIds, sampleIds, projection); + processSamples(samples, projection); + return samples; + } + + @Override + @Cacheable( + cacheResolver = "staticRepositoryCacheOneResolver", + condition = "@cacheEnabledConfig.getEnabled()") + public List fetchSamples(List sampleListIds, String projection) { + + List samples = sampleRepository.fetchSamplesBySampleListIds(sampleListIds, projection); + + processSamples(samples, projection); + return samples; + } + + @Override + public BaseMeta fetchMetaSamples(List studyIds, List sampleIds) { + + return sampleRepository.fetchMetaSamples(studyIds, sampleIds); + } + + @Override + public BaseMeta fetchMetaSamples(List sampleListIds) { + + return sampleRepository.fetchMetaSamples(sampleListIds); + } + + @Override + public List getSamplesByInternalIds(List internalIds) { + + return sampleRepository.getSamplesByInternalIds(internalIds); + } + + private void processSamples(List samples, String projection) { + if (projection.equals("DETAILED")) { + Map> sequencedSampleIdsMap = new HashMap<>(); + Map> structuralVariantSampleIdsMap = new HashMap<>(); + List distinctStudyIds = + samples.stream() + .map(Sample::getCancerStudyIdentifier) + .distinct() + .collect(Collectors.toList()); + for (String studyId : distinctStudyIds) { + sequencedSampleIdsMap.put( + studyId, + new HashSet( + sampleListRepository.getAllSampleIdsInSampleList(studyId + SEQUENCED))); + // Seems like this is built for future use to support additional detailing about samples + // with sv data + // would be used to set a data member at the end of this function + Set svSamples = new HashSet(); + svSamples = + new HashSet( + sampleListRepository.getAllSampleIdsInSampleList(studyId + STRUCTURAL_VARIANT)); + structuralVariantSampleIdsMap.put(studyId, svSamples); + } + + List samplesWithCopyNumberSeg = + copyNumberSegmentRepository.fetchSamplesWithCopyNumberSegments( + samples.stream().map(Sample::getCancerStudyIdentifier).collect(Collectors.toList()), + samples.stream().map(Sample::getStableId).collect(Collectors.toList()), + null); + + Set samplesWithCopyNumberSegMap = new HashSet<>(); + samplesWithCopyNumberSegMap.addAll(samplesWithCopyNumberSeg); + + samples.forEach( + sample -> { + sample.setSequenced( + sequencedSampleIdsMap + .get(sample.getCancerStudyIdentifier()) + .contains(sample.getStableId())); + sample.setCopyNumberSegmentPresent( + samplesWithCopyNumberSegMap.contains(sample.getInternalId())); + }); + } + } +} diff --git a/src/main/java/org/cbioportal/legacy/service/impl/ServerStatusServiceImpl.java b/src/main/java/org/cbioportal/legacy/service/impl/ServerStatusServiceImpl.java new file mode 100644 index 00000000000..0092879c599 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/impl/ServerStatusServiceImpl.java @@ -0,0 +1,45 @@ +package org.cbioportal.legacy.service.impl; + +import java.io.Serializable; +import java.util.List; +import org.cbioportal.legacy.model.TypeOfCancer; +import org.cbioportal.legacy.persistence.CancerTypeRepository; +import org.cbioportal.legacy.service.ServerStatusService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class ServerStatusServiceImpl implements ServerStatusService { + + public static final String MESSAGE_RUNNING = "UP"; + public static final String MESSAGE_DOWN = "DOWN"; + + private static final ServerStatusMessage objRunning = new ServerStatusMessage(MESSAGE_RUNNING); + private static final ServerStatusMessage objDown = new ServerStatusMessage(MESSAGE_DOWN); + + @Autowired private CancerTypeRepository cancerTypeRepository; + + @Override + public ServerStatusMessage getServerStatus() { + List allCancerTypes = + cancerTypeRepository.getAllCancerTypes("SUMMARY", null, null, null, null); + if (allCancerTypes.size() > 0) { + return objRunning; + } + return objDown; + } + + public static final class ServerStatusMessage implements Serializable { + + private static final long serialVersionUID = 1L; + String status; + + ServerStatusMessage(String message) { + this.status = message; + } + + public String getStatus() { + return this.status; + } + } +} diff --git a/src/main/java/org/cbioportal/legacy/service/impl/SignificantCopyNumberRegionServiceImpl.java b/src/main/java/org/cbioportal/legacy/service/impl/SignificantCopyNumberRegionServiceImpl.java new file mode 100644 index 00000000000..875c94d0635 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/impl/SignificantCopyNumberRegionServiceImpl.java @@ -0,0 +1,62 @@ +package org.cbioportal.legacy.service.impl; + +import java.util.List; +import java.util.stream.Collectors; +import org.cbioportal.legacy.model.Gistic; +import org.cbioportal.legacy.model.GisticToGene; +import org.cbioportal.legacy.model.meta.BaseMeta; +import org.cbioportal.legacy.persistence.SignificantCopyNumberRegionRepository; +import org.cbioportal.legacy.service.SignificantCopyNumberRegionService; +import org.cbioportal.legacy.service.StudyService; +import org.cbioportal.legacy.service.exception.StudyNotFoundException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class SignificantCopyNumberRegionServiceImpl implements SignificantCopyNumberRegionService { + + @Autowired private SignificantCopyNumberRegionRepository significantCopyNumberRegionRepository; + @Autowired private StudyService studyService; + + @Override + public List getSignificantCopyNumberRegions( + String studyId, + String projection, + Integer pageSize, + Integer pageNumber, + String sortBy, + String direction) + throws StudyNotFoundException { + + studyService.getStudy(studyId); + + List gisticList = + significantCopyNumberRegionRepository.getSignificantCopyNumberRegions( + studyId, projection, pageSize, pageNumber, sortBy, direction); + + if (!projection.equals("ID") && !gisticList.isEmpty()) { + + List gisticToGeneList = + significantCopyNumberRegionRepository.getGenesOfRegions( + gisticList.stream().map(Gistic::getGisticRoiId).collect(Collectors.toList())); + + gisticList.forEach( + g -> + g.setGenes( + gisticToGeneList.stream() + .filter(p -> p.getGisticRoiId().equals(g.getGisticRoiId())) + .collect(Collectors.toList()))); + } + + return gisticList; + } + + @Override + public BaseMeta getMetaSignificantCopyNumberRegions(String studyId) + throws StudyNotFoundException { + + studyService.getStudy(studyId); + + return significantCopyNumberRegionRepository.getMetaSignificantCopyNumberRegions(studyId); + } +} diff --git a/src/main/java/org/cbioportal/legacy/service/impl/SignificantlyMutatedGeneServiceImpl.java b/src/main/java/org/cbioportal/legacy/service/impl/SignificantlyMutatedGeneServiceImpl.java new file mode 100644 index 00000000000..a12d279fb3f --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/impl/SignificantlyMutatedGeneServiceImpl.java @@ -0,0 +1,42 @@ +package org.cbioportal.legacy.service.impl; + +import java.util.List; +import org.cbioportal.legacy.model.MutSig; +import org.cbioportal.legacy.model.meta.BaseMeta; +import org.cbioportal.legacy.persistence.SignificantlyMutatedGeneRepository; +import org.cbioportal.legacy.service.SignificantlyMutatedGeneService; +import org.cbioportal.legacy.service.StudyService; +import org.cbioportal.legacy.service.exception.StudyNotFoundException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class SignificantlyMutatedGeneServiceImpl implements SignificantlyMutatedGeneService { + + @Autowired private SignificantlyMutatedGeneRepository significantlyMutatedGeneRepository; + @Autowired private StudyService studyService; + + @Override + public List getSignificantlyMutatedGenes( + String studyId, + String projection, + Integer pageSize, + Integer pageNumber, + String sortBy, + String direction) + throws StudyNotFoundException { + + studyService.getStudy(studyId); + + return significantlyMutatedGeneRepository.getSignificantlyMutatedGenes( + studyId, projection, pageSize, pageNumber, sortBy, direction); + } + + @Override + public BaseMeta getMetaSignificantlyMutatedGenes(String studyId) throws StudyNotFoundException { + + studyService.getStudy(studyId); + + return significantlyMutatedGeneRepository.getMetaSignificantlyMutatedGenes(studyId); + } +} diff --git a/src/main/java/org/cbioportal/legacy/service/impl/StaticDataTimestampServiceImpl.java b/src/main/java/org/cbioportal/legacy/service/impl/StaticDataTimestampServiceImpl.java new file mode 100644 index 00000000000..d4e32189f36 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/impl/StaticDataTimestampServiceImpl.java @@ -0,0 +1,43 @@ +package org.cbioportal.legacy.service.impl; + +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; +import org.cbioportal.legacy.model.TableTimestampPair; +import org.cbioportal.legacy.persistence.StaticDataTimeStampRepository; +import org.cbioportal.legacy.service.StaticDataTimestampService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class StaticDataTimestampServiceImpl implements StaticDataTimestampService { + @Autowired private StaticDataTimeStampRepository staticDataTimeStampRepository; + + @Override + public Map getTimestamps(List tables) { + List timestamps = staticDataTimeStampRepository.getTimestamps(tables); + return timestamps.stream() + .collect( + Collectors.toMap(TableTimestampPair::getTableName, TableTimestampPair::getUpdateTime)); + } + + @Override + public Map getTimestampsAsDates(List tables) { + List timestamps = staticDataTimeStampRepository.getTimestamps(tables); + return timestamps.stream() + .collect( + Collectors.toMap( + TableTimestampPair::getTableName, (pair) -> toDate(pair.getUpdateTime()))); + } + + private Date toDate(String date) { + try { + return new SimpleDateFormat("yyyy-MM-dd hh:mm:ss.sss").parse(date); + } catch (ParseException ignored) { + return new Date(); + } + } +} diff --git a/src/main/java/org/cbioportal/legacy/service/impl/StructuralVariantServiceImpl.java b/src/main/java/org/cbioportal/legacy/service/impl/StructuralVariantServiceImpl.java new file mode 100644 index 00000000000..20969eb74c5 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/impl/StructuralVariantServiceImpl.java @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2018 - 2022 The Hyve B.V. + * This code is licensed under the GNU Affero General Public License (AGPL), + * version 3, or (at your option) any later version. + */ + +/* + * This file is part of cBioPortal. + * + * cBioPortal is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package org.cbioportal.legacy.service.impl; + +import java.util.*; +import java.util.List; +import org.cbioportal.legacy.model.GeneFilterQuery; +import org.cbioportal.legacy.model.StructuralVariant; +import org.cbioportal.legacy.model.StructuralVariantFilterQuery; +import org.cbioportal.legacy.model.StructuralVariantQuery; +import org.cbioportal.legacy.persistence.StructuralVariantRepository; +import org.cbioportal.legacy.service.StructuralVariantService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class StructuralVariantServiceImpl implements StructuralVariantService { + + @Autowired private StructuralVariantRepository structuralVariantRepository; + + @Override + public List fetchStructuralVariants( + List molecularProfileIds, + List sampleIds, + List entrezGeneIds, + List structuralVariantQueries) { + return structuralVariantRepository.fetchStructuralVariants( + molecularProfileIds, sampleIds, entrezGeneIds, structuralVariantQueries); + } + + @Override + public List fetchStructuralVariantsByGeneQueries( + List molecularProfileIds, List sampleIds, List geneQueries) { + + return structuralVariantRepository.fetchStructuralVariantsByGeneQueries( + molecularProfileIds, sampleIds, geneQueries); + } + + @Override + public List fetchStructuralVariantsByStructVarQueries( + List molecularProfileIds, + List sampleIds, + List structVarQueries) { + return structuralVariantRepository.fetchStructuralVariantsByStructVarQueries( + molecularProfileIds, sampleIds, structVarQueries); + } +} diff --git a/src/main/java/org/cbioportal/legacy/service/impl/StudyServiceImpl.java b/src/main/java/org/cbioportal/legacy/service/impl/StudyServiceImpl.java new file mode 100644 index 00000000000..07ad37a757d --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/impl/StudyServiceImpl.java @@ -0,0 +1,150 @@ +package org.cbioportal.legacy.service.impl; + +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; +import org.cbioportal.legacy.model.CancerStudy; +import org.cbioportal.legacy.model.CancerStudyTags; +import org.cbioportal.legacy.model.TypeOfCancer; +import org.cbioportal.legacy.model.meta.BaseMeta; +import org.cbioportal.legacy.persistence.StudyRepository; +import org.cbioportal.legacy.service.CancerTypeService; +import org.cbioportal.legacy.service.ReadPermissionService; +import org.cbioportal.legacy.service.StudyService; +import org.cbioportal.legacy.service.exception.StudyNotFoundException; +import org.cbioportal.legacy.utils.security.AccessLevel; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.access.prepost.PostFilter; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.security.core.Authentication; +import org.springframework.stereotype.Service; + +@Service +public class StudyServiceImpl implements StudyService { + + @Autowired private StudyRepository studyRepository; + + @Autowired private CancerTypeService cancerTypeService; + + @Autowired private ReadPermissionService readPermissionService; + + @Override + @PostFilter("hasPermission(filterObject,#accessLevel)") + public List getAllStudies( + String keyword, + String projection, + Integer pageSize, + Integer pageNumber, + String sortBy, + String direction, + Authentication authentication, + AccessLevel accessLevel) { + + List allStudies = + studyRepository.getAllStudies(keyword, projection, pageSize, pageNumber, sortBy, direction); + Map sortedAllStudiesByCancerStudyIdentifier = + allStudies.stream() + .collect( + Collectors.toMap( + c -> c.getCancerStudyIdentifier(), c -> c, (e1, e2) -> e2, LinkedHashMap::new)); + if (keyword != null && (pageSize == null || allStudies.size() < pageSize)) { + List primarySiteMatchingStudies = findPrimarySiteMatchingStudies(keyword); + for (CancerStudy cancerStudy : primarySiteMatchingStudies) { + if (!sortedAllStudiesByCancerStudyIdentifier.containsKey( + cancerStudy.getCancerStudyIdentifier())) { + sortedAllStudiesByCancerStudyIdentifier.put( + cancerStudy.getCancerStudyIdentifier(), cancerStudy); + } + if (pageSize != null && sortedAllStudiesByCancerStudyIdentifier.size() == pageSize) { + break; + } + } + } + + // For authenticated portals it is essential to make a new list, such + // that @PostFilter does not taint the list stored in the mybatis + // second-level cache. When making changes to this make sure to copy the + // allStudies list at least for the AUTHENTICATE.equals("true") case + List returnedStudyObjects = + sortedAllStudiesByCancerStudyIdentifier.values().stream().collect(Collectors.toList()); + + // When using prop. 'skin.home_page.show_unauthorized_studies' this endpoint + // returns the full list of studies, some of which can be accessed by the user. + readPermissionService.setReadPermission(returnedStudyObjects, authentication); + + return returnedStudyObjects; + } + + @Override + public BaseMeta getMetaStudies(String keyword) { + if (keyword == null) { + return studyRepository.getMetaStudies(keyword); + } else { + BaseMeta baseMeta = new BaseMeta(); + baseMeta.setTotalCount( + getAllStudies(keyword, "SUMMARY", null, null, null, null, null, AccessLevel.READ).size()); + return baseMeta; + } + } + + @Override + public CancerStudy getStudy(String studyId) throws StudyNotFoundException { + + CancerStudy cancerStudy = studyRepository.getStudy(studyId, "DETAILED"); + if (cancerStudy == null) { + throw new StudyNotFoundException(studyId); + } + + return cancerStudy; + } + + @Override + public List fetchStudies(List studyIds, String projection) { + + return studyRepository.fetchStudies(studyIds, projection); + } + + @Override + public BaseMeta fetchMetaStudies(List studyIds) { + + return studyRepository.fetchMetaStudies(studyIds); + } + + @Override + @PreAuthorize("hasPermission(#studyId, 'CancerStudyId', #accessLevel)") + public CancerStudyTags getTags(String studyId, AccessLevel accessLevel) { + + return studyRepository.getTags(studyId); + } + + @Override + public List getTagsForMultipleStudies(List studyIds) { + + return studyRepository.getTagsForMultipleStudies(studyIds); + } + + private List findPrimarySiteMatchingStudies(String keyword) { + + List matchingStudies = new ArrayList<>(); + + List matchingCancerTypes = new ArrayList<>(); + for (Map.Entry entry : cancerTypeService.getPrimarySiteMap().entrySet()) { + if (entry.getValue().getTypeOfCancerId().toLowerCase().contains(keyword.toLowerCase()) + || entry.getValue().getName().toLowerCase().contains(keyword.toLowerCase())) { + matchingCancerTypes.add(entry.getKey()); + } + } + if (!matchingCancerTypes.isEmpty()) { + List allUnfilteredStudies = + studyRepository.getAllStudies(null, "SUMMARY", null, null, null, null); + for (CancerStudy cancerStudy : allUnfilteredStudies) { + if (matchingCancerTypes.contains(cancerStudy.getTypeOfCancerId())) { + matchingStudies.add(cancerStudy); + } + } + } + return matchingStudies; + } +} diff --git a/src/main/java/org/cbioportal/legacy/service/impl/StudyViewServiceImpl.java b/src/main/java/org/cbioportal/legacy/service/impl/StudyViewServiceImpl.java new file mode 100644 index 00000000000..ebb78899a0f --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/impl/StudyViewServiceImpl.java @@ -0,0 +1,613 @@ +package org.cbioportal.legacy.service.impl; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.Set; +import java.util.function.Function; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import org.apache.commons.collections4.map.MultiKeyMap; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.math3.util.Pair; +import org.cbioportal.legacy.model.AlterationCountByGene; +import org.cbioportal.legacy.model.AlterationCountByStructuralVariant; +import org.cbioportal.legacy.model.AlterationFilter; +import org.cbioportal.legacy.model.CNA; +import org.cbioportal.legacy.model.CopyNumberCountByGene; +import org.cbioportal.legacy.model.Gene; +import org.cbioportal.legacy.model.GeneMolecularData; +import org.cbioportal.legacy.model.GenePanelData; +import org.cbioportal.legacy.model.GenericAssayData; +import org.cbioportal.legacy.model.GenericAssayDataCount; +import org.cbioportal.legacy.model.GenericAssayDataCountItem; +import org.cbioportal.legacy.model.GenomicDataCount; +import org.cbioportal.legacy.model.GenomicDataCountItem; +import org.cbioportal.legacy.model.Gistic; +import org.cbioportal.legacy.model.MolecularProfile; +import org.cbioportal.legacy.model.MolecularProfileCaseIdentifier; +import org.cbioportal.legacy.model.MutSig; +import org.cbioportal.legacy.model.MutationFilterOption; +import org.cbioportal.legacy.model.NamespaceAttribute; +import org.cbioportal.legacy.model.NamespaceDataCountItem; +import org.cbioportal.legacy.model.util.Select; +import org.cbioportal.legacy.service.AlterationCountService; +import org.cbioportal.legacy.service.GenePanelService; +import org.cbioportal.legacy.service.GeneService; +import org.cbioportal.legacy.service.GenericAssayService; +import org.cbioportal.legacy.service.MolecularDataService; +import org.cbioportal.legacy.service.MolecularProfileService; +import org.cbioportal.legacy.service.MutationService; +import org.cbioportal.legacy.service.NamespaceDataService; +import org.cbioportal.legacy.service.SignificantCopyNumberRegionService; +import org.cbioportal.legacy.service.SignificantlyMutatedGeneService; +import org.cbioportal.legacy.service.StudyViewService; +import org.cbioportal.legacy.service.exception.MolecularProfileNotFoundException; +import org.cbioportal.legacy.service.exception.StudyNotFoundException; +import org.cbioportal.legacy.service.util.MolecularProfileUtil; +import org.cbioportal.legacy.web.parameter.GeneIdType; +import org.cbioportal.legacy.web.parameter.Projection; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class StudyViewServiceImpl implements StudyViewService { + private static final List CNA_TYPES_AMP_AND_HOMDEL = + Collections.unmodifiableList(Arrays.asList(CNA.AMP, CNA.HOMDEL)); + private final MolecularProfileService molecularProfileService; + private final GenePanelService genePanelService; + private final MolecularProfileUtil molecularProfileUtil; + private final AlterationCountService alterationCountService; + private final NamespaceDataService namespaceDataService; + private final SignificantlyMutatedGeneService significantlyMutatedGeneService; + private final SignificantCopyNumberRegionService significantCopyNumberRegionService; + private final GenericAssayService genericAssayService; + private final GeneService geneService; + private final MolecularDataService molecularDataService; + private final MutationService mutationService; + + // constructor dependency injections + @Autowired + public StudyViewServiceImpl( + MolecularProfileService molecularProfileService, + GenePanelService genePanelService, + MolecularProfileUtil molecularProfileUtil, + AlterationCountService alterationCountService, + NamespaceDataService namespaceDataService, + SignificantlyMutatedGeneService significantlyMutatedGeneService, + SignificantCopyNumberRegionService significantCopyNumberRegionService, + GenericAssayService genericAssayService, + GeneService geneService, + MolecularDataService molecularDataService, + MutationService mutationService) { + this.molecularProfileService = molecularProfileService; + this.genePanelService = genePanelService; + this.molecularProfileUtil = molecularProfileUtil; + this.alterationCountService = alterationCountService; + this.namespaceDataService = namespaceDataService; + this.significantlyMutatedGeneService = significantlyMutatedGeneService; + this.significantCopyNumberRegionService = significantCopyNumberRegionService; + this.genericAssayService = genericAssayService; + this.geneService = geneService; + this.molecularDataService = molecularDataService; + this.mutationService = mutationService; + } + + @Override + public List getGenomicDataCounts( + List studyIds, List sampleIds) { + List molecularProfileSampleIdentifiers = + molecularProfileService.getMolecularProfileCaseIdentifiers(studyIds, sampleIds); + + // first get all molecular profiles + List molecularProfiles = + molecularProfileService.getMolecularProfilesInStudies( + new ArrayList<>(new HashSet<>(studyIds)), Projection.SUMMARY.name()); + Map molecularProfileMap = + molecularProfiles.stream() + .collect(Collectors.toMap(MolecularProfile::getStableId, Function.identity())); + + // get gene panels + Map molecularProfileCaseCountSet = + genePanelService + .fetchGenePanelDataInMultipleMolecularProfiles(molecularProfileSampleIdentifiers) + .stream() + .filter(GenePanelData::getProfiled) + .collect(Collectors.groupingBy(GenePanelData::getMolecularProfileId)) + .entrySet() + .stream() + .collect( + Collectors.toMap( + Map.Entry::getKey, + entry -> + (int) + entry.getValue().stream() + .map( + d -> + molecularProfileMap.get(entry.getKey()).getPatientLevel() + ? d.getPatientId() + : d.getSampleId()) + .distinct() + .count())); + + return molecularProfileUtil + .categorizeMolecularProfilesByStableIdSuffixes(molecularProfiles) + .entrySet() + .stream() + .map( + entry -> { + GenomicDataCount dataCount = new GenomicDataCount(); + dataCount.setValue(entry.getKey()); + + Integer count = + entry.getValue().stream() + .mapToInt( + molecularProfile -> + molecularProfileCaseCountSet.getOrDefault( + molecularProfile.getStableId(), 0)) + .sum(); + + dataCount.setCount(count); + dataCount.setLabel(entry.getValue().get(0).getName()); + return dataCount; + }) + .filter(dataCount -> dataCount.getCount() > 0) + .toList(); + } + + @Override + public List getMutationAlterationCountByGenes( + List studyIds, List sampleIds, AlterationFilter alterationFilter) + throws StudyNotFoundException { + List caseIdentifiers = + molecularProfileService.getFirstMutationProfileCaseIdentifiers(studyIds, sampleIds); + List alterationCountByGenes = + alterationCountService + .getSampleMutationGeneCounts( + caseIdentifiers, Select.all(), true, false, alterationFilter) + .getFirst(); + annotateDataWithQValue(studyIds, alterationCountByGenes); + return alterationCountByGenes; + } + + @Override + public List fetchNamespaceDataCounts( + List studyIds, List sampleIds, List namespaceAttributes) { + + if (namespaceAttributes.isEmpty()) { + return new ArrayList<>(); + } + + return namespaceDataService.fetchNamespaceDataCounts(studyIds, sampleIds, namespaceAttributes); + } + + @Override + public List getMutationCountsByGeneSpecific( + List studyIds, + List sampleIds, + List> genomicDataFilters, + AlterationFilter alterationFilter) { + List caseIdentifiers = + molecularProfileService.getMutationProfileCaseIdentifiers(studyIds, sampleIds); + + Set hugoGeneSymbols = + genomicDataFilters.stream().map(Pair::getKey).collect(Collectors.toSet()); + + List entrezGeneIds = + geneService + .fetchGenes( + new ArrayList<>(hugoGeneSymbols), + GeneIdType.HUGO_GENE_SYMBOL.name(), + Projection.SUMMARY.name()) + .stream() + .map(Gene::getEntrezGeneId) + .toList(); + + Pair, Long> alterationCountsWithProfiledTotal = + alterationCountService.getSampleMutationGeneCounts( + caseIdentifiers, Select.byValues(entrezGeneIds), true, false, alterationFilter); + + List alterationCountByGenes = + alterationCountsWithProfiledTotal.getFirst(); + Long totalProfiledCases = alterationCountsWithProfiledTotal.getSecond(); + + return genomicDataFilters.stream() + .flatMap( + genomicDataFilter -> { + GenomicDataCountItem genomicDataCountItem = new GenomicDataCountItem(); + String hugoGeneSymbol = genomicDataFilter.getKey(); + String profileType = genomicDataFilter.getValue(); + genomicDataCountItem.setHugoGeneSymbol(hugoGeneSymbol); + genomicDataCountItem.setProfileType(profileType); + + Optional filteredAlterationCount = + alterationCountByGenes.stream() + .filter( + g -> + StringUtils.isNotEmpty(g.getHugoGeneSymbol()) + && g.getHugoGeneSymbol().equals(hugoGeneSymbol)) + .findFirst(); + + int totalCount = sampleIds.size(); + int mutatedCount = 0; + int profiledCount = Math.toIntExact(totalProfiledCases); + + if (filteredAlterationCount.isPresent()) { + mutatedCount = filteredAlterationCount.get().getNumberOfAlteredCases(); + profiledCount = filteredAlterationCount.get().getNumberOfProfiledCases(); + } + + List genomicDataCounts = new ArrayList<>(); + + GenomicDataCount genomicDataCountMutated = new GenomicDataCount(); + genomicDataCountMutated.setLabel(MutationFilterOption.MUTATED.getSelectedOption()); + genomicDataCountMutated.setValue(MutationFilterOption.MUTATED.name()); + genomicDataCountMutated.setCount(mutatedCount); + genomicDataCountMutated.setUniqueCount(mutatedCount); + if (genomicDataCountMutated.getCount() > 0) + genomicDataCounts.add(genomicDataCountMutated); + + GenomicDataCount genomicDataCountWildType = new GenomicDataCount(); + genomicDataCountWildType.setLabel( + MutationFilterOption.NOT_MUTATED.getSelectedOption()); + genomicDataCountWildType.setValue(MutationFilterOption.NOT_MUTATED.name()); + genomicDataCountWildType.setCount(profiledCount - mutatedCount); + genomicDataCountWildType.setUniqueCount(profiledCount - mutatedCount); + if (genomicDataCountWildType.getCount() > 0) + genomicDataCounts.add(genomicDataCountWildType); + + GenomicDataCount genomicDataCountNotProfiled = new GenomicDataCount(); + genomicDataCountNotProfiled.setLabel( + MutationFilterOption.NOT_PROFILED.getSelectedOption()); + genomicDataCountNotProfiled.setValue(MutationFilterOption.NOT_PROFILED.name()); + genomicDataCountNotProfiled.setCount(totalCount - profiledCount); + genomicDataCountNotProfiled.setUniqueCount(totalCount - profiledCount); + if (genomicDataCountNotProfiled.getCount() > 0) + genomicDataCounts.add(genomicDataCountNotProfiled); + + genomicDataCountItem.setCounts(genomicDataCounts); + + return Stream.of(genomicDataCountItem); + }) + .toList(); + } + + @Override + public List getMutationTypeCountsByGeneSpecific( + List studyIds, + List sampleIds, + List> genomicDataFilters) { + Set hugoGeneSymbols = + genomicDataFilters.stream().map(Pair::getKey).collect(Collectors.toSet()); + + Map geneSymbolIdMap = + geneService + .fetchGenes( + new ArrayList<>(hugoGeneSymbols), + GeneIdType.HUGO_GENE_SYMBOL.name(), + Projection.SUMMARY.name()) + .stream() + .collect(Collectors.toMap(Gene::getHugoGeneSymbol, Gene::getEntrezGeneId)); + + return genomicDataFilters.stream() + .flatMap( + genomicDataFilter -> { + String hugoGeneSymbol = genomicDataFilter.getKey(); + String profileType = genomicDataFilter.getValue(); + + List stableIds = + Collections.singletonList(geneSymbolIdMap.get(hugoGeneSymbol)); + + Pair, List> sampleAndProfileIds = + getMappedSampleAndProfileIds(studyIds, sampleIds, profileType); + List mappedSampleIds = sampleAndProfileIds.getFirst(); + List mappedProfileIds = sampleAndProfileIds.getSecond(); + + if (mappedSampleIds.isEmpty() || mappedProfileIds.isEmpty()) { + return Stream.of(); + } + + GenomicDataCountItem genomicDataCountItem = + mutationService.getMutationCountsByType( + mappedProfileIds, mappedSampleIds, stableIds, profileType); + + return Stream.ofNullable(genomicDataCountItem); + }) + .toList(); + } + + @Override + public List getStructuralVariantAlterationCountByGenes( + List studyIds, List sampleIds, AlterationFilter alterationFilter) + throws StudyNotFoundException { + List caseIdentifiers = + molecularProfileService.getFirstStructuralVariantProfileCaseIdentifiers( + studyIds, sampleIds); + List alterationCountByGenes = + alterationCountService + .getSampleStructuralVariantGeneCounts( + caseIdentifiers, Select.all(), true, false, alterationFilter) + .getFirst(); + annotateDataWithQValue(studyIds, alterationCountByGenes); + return alterationCountByGenes; + } + + @Override + public List getStructuralVariantAlterationCounts( + List studyIds, List sampleIds, AlterationFilter annotationFilters) { + List caseIdentifiers = + molecularProfileService.getFirstStructuralVariantProfileCaseIdentifiers( + studyIds, sampleIds); + return alterationCountService + .getSampleStructuralVariantCounts(caseIdentifiers, true, false, annotationFilters) + .getFirst(); + } + + private void annotateDataWithQValue( + List studyIds, List alterationCountByGenes) + throws StudyNotFoundException { + Set distinctStudyIds = new HashSet<>(studyIds); + if (!alterationCountByGenes.isEmpty() && distinctStudyIds.size() == 1) { + Map mutSigMap = + significantlyMutatedGeneService + .getSignificantlyMutatedGenes( + studyIds.get(0), Projection.SUMMARY.name(), null, null, null, null) + .stream() + .collect(Collectors.toMap(MutSig::getEntrezGeneId, Function.identity())); + alterationCountByGenes.forEach( + r -> { + if (mutSigMap.containsKey(r.getEntrezGeneId())) { + r.setqValue(mutSigMap.get(r.getEntrezGeneId()).getqValue()); + } + }); + } + } + + @Override + public List getCNAAlterationCountByGenes( + List studyIds, List sampleIds, AlterationFilter alterationFilter) + throws StudyNotFoundException { + List caseIdentifiers = + molecularProfileService.getFirstDiscreteCNAProfileCaseIdentifiers(studyIds, sampleIds); + + List copyNumberCountByGenes = + alterationCountService + .getSampleCnaGeneCounts(caseIdentifiers, Select.all(), true, false, alterationFilter) + .getFirst(); + Set distinctStudyIds = new HashSet<>(studyIds); + if (distinctStudyIds.size() == 1 && !copyNumberCountByGenes.isEmpty()) { + List gisticList = + significantCopyNumberRegionService.getSignificantCopyNumberRegions( + studyIds.get(0), Projection.SUMMARY.name(), null, null, null, null); + MultiKeyMap gisticMap = new MultiKeyMap(); + gisticList.forEach( + g -> + g.getGenes() + .forEach( + gene -> { + Gistic gistic = (Gistic) gisticMap.get(gene.getEntrezGeneId(), g.getAmp()); + if (gistic == null || g.getqValue().compareTo(gistic.getqValue()) < 0) { + gisticMap.put(gene.getEntrezGeneId(), g.getAmp(), g); + } + })); + copyNumberCountByGenes.forEach( + r -> { + if (gisticMap.containsKey(r.getEntrezGeneId(), r.getAlteration().equals(2))) { + r.setqValue( + ((Gistic) gisticMap.get(r.getEntrezGeneId(), r.getAlteration().equals(2))) + .getqValue()); + } + }); + } + return copyNumberCountByGenes; + } + + @Override + public List getCNAAlterationCountsByGeneSpecific( + List studyIds, + List sampleIds, + List> genomicDataFilters) { + Set hugoGeneSymbols = + genomicDataFilters.stream().map(Pair::getKey).collect(Collectors.toSet()); + + Map geneSymbolIdMap = + geneService + .fetchGenes( + new ArrayList<>(hugoGeneSymbols), + GeneIdType.HUGO_GENE_SYMBOL.name(), + Projection.SUMMARY.name()) + .stream() + .collect(Collectors.toMap(Gene::getHugoGeneSymbol, Gene::getEntrezGeneId)); + + return genomicDataFilters.stream() + .flatMap( + genomicDataFilter -> { + GenomicDataCountItem genomicDataCountItem = new GenomicDataCountItem(); + String hugoGeneSymbol = genomicDataFilter.getKey(); + String profileType = genomicDataFilter.getValue(); + genomicDataCountItem.setHugoGeneSymbol(hugoGeneSymbol); + genomicDataCountItem.setProfileType(profileType); + + List stableIds = List.of(geneSymbolIdMap.get(hugoGeneSymbol).toString()); + + Pair, List> sampleAndProfileIds = + getMappedSampleAndProfileIds(studyIds, sampleIds, profileType); + List mappedSampleIds = sampleAndProfileIds.getFirst(); + List mappedProfileIds = sampleAndProfileIds.getSecond(); + + if (mappedSampleIds.isEmpty()) { + return Stream.of(); + } + + List geneMolecularDataList = + molecularDataService.getMolecularDataInMultipleMolecularProfiles( + mappedProfileIds, + mappedSampleIds, + stableIds.stream().map(Integer::parseInt).toList(), + Projection.SUMMARY.name()); + + List genomicDataCounts = + geneMolecularDataList.stream() + .filter( + g -> StringUtils.isNotEmpty(g.getValue()) && !g.getValue().equals("NA")) + .collect(Collectors.groupingBy(GeneMolecularData::getValue)) + .entrySet() + .stream() + .map( + entry -> { + Integer alteration = Integer.valueOf(entry.getKey()); + List geneMolecularData = entry.getValue(); + int count = geneMolecularData.size(); + + String label = CNA.getByCode(alteration.shortValue()).getDescription(); + + GenomicDataCount genomicDataCount = new GenomicDataCount(); + genomicDataCount.setLabel(label); + genomicDataCount.setValue(String.valueOf(alteration)); + genomicDataCount.setCount(count); + + return genomicDataCount; + }) + .collect(Collectors.toList()); + + int totalCount = + genomicDataCounts.stream().mapToInt(GenomicDataCount::getCount).sum(); + int naCount = sampleIds.size() - totalCount; + + if (naCount > 0) { + GenomicDataCount genomicDataCount = new GenomicDataCount(); + genomicDataCount.setLabel("NA"); + genomicDataCount.setValue("NA"); + genomicDataCount.setCount(naCount); + genomicDataCounts.add(genomicDataCount); + } + + genomicDataCountItem.setCounts(genomicDataCounts); + return Stream.of(genomicDataCountItem); + }) + .toList(); + } + + @Override + public List fetchGenericAssayDataCounts( + List sampleIds, + List studyIds, + List stableIds, + List profileTypes) { + if (stableIds.isEmpty()) { + return new ArrayList<>(); + } + + List data = + profileTypes.stream() + .flatMap( + profileType -> { + Pair, List> sampleAndProfileIds = + getMappedSampleAndProfileIds(studyIds, sampleIds, profileType); + List mappedSampleIds = sampleAndProfileIds.getFirst(); + List mappedProfileIds = sampleAndProfileIds.getSecond(); + + try { + return genericAssayService + .fetchGenericAssayData( + mappedProfileIds, mappedSampleIds, stableIds, Projection.SUMMARY.name()) + .stream(); + } catch (MolecularProfileNotFoundException e) { + return new ArrayList().stream(); + } + }) + .toList(); + + return data.stream() + .collect(Collectors.groupingBy(GenericAssayData::getGenericAssayStableId)) + .entrySet() + .stream() + .map( + entry -> { + List groupData = entry.getValue(); + boolean isPatientLevel = !groupData.isEmpty() && groupData.get(0).getPatientLevel(); + + List filteredData; + int totalIds; + + if (isPatientLevel) { + Set uniquePatientIds = + data.stream().map(GenericAssayData::getPatientId).collect(Collectors.toSet()); + totalIds = uniquePatientIds.size(); + + filteredData = + groupData.stream() + .filter( + g -> StringUtils.isNotEmpty(g.getValue()) && !g.getValue().equals("NA")) + .collect(Collectors.groupingBy(GenericAssayData::getPatientId)) + .values() + .stream() + .map(patientSamples -> patientSamples.get(0)) + .toList(); + } else { + totalIds = sampleIds.size(); + filteredData = + groupData.stream() + .filter( + g -> StringUtils.isNotEmpty(g.getValue()) && !g.getValue().equals("NA")) + .toList(); + } + + int naCount = totalIds - filteredData.size(); + + List counts = + filteredData.stream() + .collect(Collectors.groupingBy(GenericAssayData::getValue)) + .entrySet() + .stream() + .map( + datum -> + new GenericAssayDataCount(datum.getKey(), datum.getValue().size())) + .collect(Collectors.toList()); + + if (naCount > 0) { + counts.add(new GenericAssayDataCount("NA", naCount)); + } + + GenericAssayDataCountItem countItem = new GenericAssayDataCountItem(); + countItem.setStableId(entry.getKey()); + countItem.setCounts(counts); + return countItem; + }) + .toList(); + } + + private Pair, List> getMappedSampleAndProfileIds( + List studyIds, List sampleIds, String profileType) { + List molecularProfiles = + molecularProfileService.getMolecularProfilesInStudies(studyIds, Projection.SUMMARY.name()); + + Map> molecularProfileMap = + molecularProfileUtil.categorizeMolecularProfilesByStableIdSuffixes(molecularProfiles); + + Map studyIdToMolecularProfileIdMap = + molecularProfileMap.getOrDefault(profileType, new ArrayList()).stream() + .collect( + Collectors.toMap( + MolecularProfile::getCancerStudyIdentifier, MolecularProfile::getStableId)); + + List mappedSampleIds = new ArrayList<>(); + List mappedProfileIds = new ArrayList<>(); + + for (int i = 0; i < sampleIds.size(); i++) { + String studyId = studyIds.get(i); + + // add samples only if the studyId is existed in the map + if (studyIdToMolecularProfileIdMap.containsKey(studyId)) { + mappedSampleIds.add(sampleIds.get(i)); + mappedProfileIds.add(studyIdToMolecularProfileIdMap.get(studyId)); + } + } + + return new Pair<>(mappedSampleIds, mappedProfileIds); + } +} diff --git a/src/main/java/org/cbioportal/legacy/service/impl/TreatmentServiceImpl.java b/src/main/java/org/cbioportal/legacy/service/impl/TreatmentServiceImpl.java new file mode 100644 index 00000000000..9d8619a59fa --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/impl/TreatmentServiceImpl.java @@ -0,0 +1,213 @@ +package org.cbioportal.legacy.service.impl; + +import java.util.*; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.apache.commons.lang3.tuple.Pair; +import org.cbioportal.legacy.model.ClinicalEventKeyCode; +import org.cbioportal.legacy.model.ClinicalEventSample; +import org.cbioportal.legacy.model.PatientTreatmentRow; +import org.cbioportal.legacy.model.SampleTreatmentRow; +import org.cbioportal.legacy.model.TemporalRelation; +import org.cbioportal.legacy.model.Treatment; +import org.cbioportal.legacy.persistence.TreatmentRepository; +import org.cbioportal.legacy.service.TreatmentService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class TreatmentServiceImpl implements TreatmentService { + @Autowired TreatmentRepository treatmentRepository; + + private Pair, List> filterIds( + List sampleIds, List studyIds, ClinicalEventKeyCode key) { + if (sampleIds == null || studyIds == null || sampleIds.size() != studyIds.size()) { + return new ImmutablePair<>(sampleIds, studyIds); + } + Set studiesWithTreatments = + studyIds.stream() + .distinct() + .filter( + studyId -> + treatmentRepository.hasTreatmentData(Collections.singletonList(studyId), key)) + .collect(Collectors.toSet()); + + ArrayList filteredSampleIds = new ArrayList<>(); + ArrayList filteredStudyIds = new ArrayList<>(); + for (int i = 0; i < sampleIds.size(); i++) { + String studyId = studyIds.get(i); + String sampleId = sampleIds.get(i); + if (studiesWithTreatments.contains(studyId)) { + filteredSampleIds.add(sampleId); + filteredStudyIds.add(studyId); + } + } + return new ImmutablePair<>(filteredSampleIds, filteredStudyIds); + } + + @Override + public List getAllSampleTreatmentRows( + List sampleIds, List studyIds, ClinicalEventKeyCode key) { + Pair, List> filteredIds = filterIds(sampleIds, studyIds, key); + sampleIds = filteredIds.getLeft(); + studyIds = filteredIds.getRight(); + + Map> samplesByPatient = + treatmentRepository.getSamplesByPatientId(sampleIds, studyIds); + Map> treatmentsByPatient = + treatmentRepository.getTreatmentsByPatientId(sampleIds, studyIds, key); + + Stream rows = + samplesByPatient.keySet().stream() + .flatMap( + patientId -> + getSampleTreatmentRowsForPatient( + patientId, samplesByPatient, treatmentsByPatient)) + .filter(row -> row.getCount() != 0); + return flattenRows(rows); + } + + private Stream getSampleTreatmentRowsForPatient( + String patientId, + Map> samplesByPatient, + Map> treatmentsByPatient) { + List treatments = treatmentsByPatient.getOrDefault(patientId, new ArrayList<>()); + List samples = samplesByPatient.get(patientId); + + Map rows = new HashMap<>(); + + for (Treatment treatment : treatments) { + TreatmentRowTriplet triplet; + + if (!rows.containsKey(treatment.getTreatment())) { + triplet = new TreatmentRowTriplet(samples, treatment.getTreatment()); + rows.put(treatment.getTreatment(), triplet); + } else { + triplet = rows.get(treatment.getTreatment()); + } + + triplet.moveSamplesToPost(treatment); + } + + return rows.values().stream().flatMap(TreatmentRowTriplet::toRows); + } + + private List flattenRows(Stream rows) { + Map uniqueRows = new HashMap<>(); + rows.forEach( + rowToAdd -> { + if (uniqueRows.containsKey(rowToAdd.key())) { + uniqueRows.get(rowToAdd.key()).add(rowToAdd); + } else { + uniqueRows.put(rowToAdd.key(), rowToAdd); + } + }); + + return new ArrayList<>(uniqueRows.values()); + } + + /** + * For a given treatment, you can have samples that are taken before (pre), after (post), or that + * don't have a date (unknown) + * + *

This class accepts an initial list of samples and a treatment. At the start, all samples are + * considered pre, as there hasn't been any treatment start / stop times. + * + *

You then call moveSamplesToPost on this with a series of matching treatments. Each call will + * move samples taken + */ + private static class TreatmentRowTriplet { + private final Set pre, post; + private final String treatment; + + TreatmentRowTriplet(List samples, String treatment) { + this.treatment = treatment; + post = new HashSet<>(); + pre = samples.stream().filter(s -> s.getTimeTaken() != null).collect(Collectors.toSet()); + } + + /** + * Moves any samples marked as pre that were taken after the treatment started to post. + * + * @param treatment a treatment with a start value. It is assumed that the treatment matches the + * treatment stored in this triplet + */ + void moveSamplesToPost(Treatment treatment) { + for (Iterator iterator = pre.iterator(); iterator.hasNext(); ) { + ClinicalEventSample clinicalEventSample = iterator.next(); + // edge case: is a sample taken the same day a treatment starts pre or post? + // We're saying pre here + if (clinicalEventSample.getTimeTaken() > treatment.getStart()) { + iterator.remove(); + post.add(clinicalEventSample); + } + } + } + + Stream toRows() { + return Stream.of( + new SampleTreatmentRow(TemporalRelation.Pre, treatment, pre.size(), pre), + new SampleTreatmentRow(TemporalRelation.Post, treatment, post.size(), post) + // We made the decision to filter out unknown rows. I'm leaving this line of code + // to document this decision. + // new SampleTreatmentRow(TemporalRelation.Unknown, treatment, unknown.size(), unknown) + ); + } + } + + @Override + public List getAllPatientTreatmentRows( + List sampleIds, List studyIds, ClinicalEventKeyCode key) { + Pair, List> filteredIds = filterIds(sampleIds, studyIds, key); + sampleIds = filteredIds.getLeft(); + studyIds = filteredIds.getRight(); + + Map> samplesByPatient = + treatmentRepository.getShallowSamplesByPatientId(sampleIds, studyIds); + + Map> treatmentSet = + treatmentRepository.getTreatments(sampleIds, studyIds, key).stream() + .collect(Collectors.groupingBy(Treatment::getTreatment)); + + /* + This logic transforms treatmentSet to list of PatientTreatmentRow. transformation steps: + - key in treatmentSet is going to be treatment + - get all unique patient ids -> this is going to give count + - get all clinicalEventSamples using above unique patient ids + */ + return treatmentSet.entrySet().stream() + .map( + entry -> { + String treatment = entry.getKey(); + Set patientIds = + entry.getValue().stream() + .map(Treatment::getPatientId) + .collect(Collectors.toSet()); + Set clinicalEventSamples = + patientIds.stream() + .flatMap( + patientId -> + samplesByPatient.getOrDefault(patientId, new ArrayList<>()).stream()) + .collect(Collectors.toSet()); + return new PatientTreatmentRow(treatment, patientIds.size(), clinicalEventSamples); + }) + .collect(Collectors.toList()); + } + + @Override + public Boolean containsTreatmentData(List studies, ClinicalEventKeyCode key) { + return treatmentRepository.hasTreatmentData(studies, key); + } + + @Override + public Boolean containsSampleTreatmentData(List studyIds, ClinicalEventKeyCode key) { + studyIds = + studyIds.stream() + .filter( + studyId -> + treatmentRepository.hasTreatmentData(Collections.singletonList(studyId), key)) + .collect(Collectors.toList()); + return studyIds.size() > 0 && treatmentRepository.hasSampleTimelineData(studyIds); + } +} diff --git a/src/main/java/org/cbioportal/legacy/service/impl/UnauthDataAccessTokenServiceImpl.java b/src/main/java/org/cbioportal/legacy/service/impl/UnauthDataAccessTokenServiceImpl.java new file mode 100644 index 00000000000..9030bfc7a67 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/impl/UnauthDataAccessTokenServiceImpl.java @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2018 Memorial Sloan-Kettering Cancer Center. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS + * FOR A PARTICULAR PURPOSE. The software and documentation provided hereunder + * is on an "as is" basis, and Memorial Sloan-Kettering Cancer Center has no + * obligations to provide maintenance, support, updates, enhancements or + * modifications. In no event shall Memorial Sloan-Kettering Cancer Center be + * liable to any party for direct, indirect, special, incidental or + * consequential damages, including lost profits, arising out of the use of this + * software and its documentation, even if Memorial Sloan-Kettering Cancer + * Center has been advised of the possibility of such damage. + */ + +/* + * This file is part of cBioPortal. + * + * cBioPortal is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package org.cbioportal.legacy.service.impl; + +import java.util.Date; +import java.util.List; +import org.cbioportal.legacy.model.DataAccessToken; +import org.cbioportal.legacy.service.DataAccessTokenService; +import org.cbioportal.legacy.utils.config.annotation.ConditionalOnProperty; +import org.springframework.security.access.AccessDeniedException; +import org.springframework.security.core.Authentication; +import org.springframework.stereotype.Component; + +/** + * @author ochoaa + */ +@Component +@ConditionalOnProperty(name = "dat.method", havingValue = "none", matchIfMissing = true) +public class UnauthDataAccessTokenServiceImpl implements DataAccessTokenService { + + @Override + public DataAccessToken createDataAccessToken(String username) { + throw new AccessDeniedException( + "Data Access Tokens are not supported for unauthenticated portals."); + } + + @Override + public List getAllDataAccessTokens(String username) { + throw new AccessDeniedException( + "Data Access Tokens are not supported for unauthenticated portals."); + } + + @Override + public DataAccessToken getDataAccessToken(String username) { + throw new AccessDeniedException( + "Data Access Tokens are not supported for unauthenticated portals."); + } + + @Override + public DataAccessToken getDataAccessTokenInfo(String token) { + throw new AccessDeniedException( + "Data Access Tokens are not supported for unauthenticated portals."); + } + + @Override + public void revokeAllDataAccessTokens(String username) { + throw new AccessDeniedException( + "Data Access Tokens are not supported for unauthenticated portals."); + } + + @Override + public void revokeDataAccessToken(String token) { + throw new AccessDeniedException( + "Data Access Tokens are not supported for unauthenticated portals."); + } + + @Override + public String getUsername(String token) { + throw new AccessDeniedException( + "Data Access Tokens are not supported for unauthenticated portals."); + } + + @Override + public Date getExpiration(String token) { + throw new AccessDeniedException( + "Data Access Tokens are not supported for unauthenticated portals."); + } + + @Override + public Boolean isValid(String token) { + throw new AccessDeniedException( + "Data Access Tokens are not supported for unauthenticated portals."); + } + + @Override + public Authentication createAuthenticationRequest(String token) { + return null; + } +} diff --git a/src/main/java/org/cbioportal/legacy/service/impl/UuidDataAccessTokenServiceImpl.java b/src/main/java/org/cbioportal/legacy/service/impl/UuidDataAccessTokenServiceImpl.java new file mode 100644 index 00000000000..4bdbc6782f2 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/impl/UuidDataAccessTokenServiceImpl.java @@ -0,0 +1,192 @@ +/* + * Copyright (c) 2018 Memorial Sloan-Kettering Cancer Center. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS + * FOR A PARTICULAR PURPOSE. The software and documentation provided hereunder + * is on an "as is" basis, and Memorial Sloan-Kettering Cancer Center has no + * obligations to provide maintenance, support, updates, enhancements or + * modifications. In no event shall Memorial Sloan-Kettering Cancer Center be + * liable to any party for direct, indirect, special, incidental or + * consequential damages, including lost profits, arising out of the use of this + * software and its documentation, even if Memorial Sloan-Kettering Cancer + * Center has been advised of the possibility of such damage. + */ + +/* + * This file is part of cBioPortal. + * + * cBioPortal is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package org.cbioportal.legacy.service.impl; + +import java.util.Calendar; +import java.util.Date; +import java.util.List; +import java.util.UUID; +import org.cbioportal.legacy.model.DataAccessToken; +import org.cbioportal.legacy.persistence.DataAccessTokenRepository; +import org.cbioportal.legacy.service.DataAccessTokenService; +import org.cbioportal.legacy.service.exception.TokenNotFoundException; +import org.cbioportal.legacy.utils.config.annotation.ConditionalOnProperty; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.security.authentication.BadCredentialsException; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.Authentication; +import org.springframework.stereotype.Component; + +@Component +@ConditionalOnProperty(name = "dat.method", havingValue = "uuid") +public class UuidDataAccessTokenServiceImpl implements DataAccessTokenService { + + @Autowired private DataAccessTokenRepository dataAccessTokenRepository; + + @Value("${dat.ttl_seconds:-1}") + private int datTtlSeconds; + + @Value("${dat.uuid.max_number_per_user:-1}") + private int maxNumberOfAccessTokens; + + private static final Logger log = LoggerFactory.getLogger(UuidDataAccessTokenServiceImpl.class); + + // create a data access token (randomly generated UUID) and insert corresponding record into table + // with parts: + // username + // uuid + // expiration date (current time + 1 month) + @Override + public DataAccessToken createDataAccessToken(String username) { + if (username == null || username.trim().length() == 0) { + throw new IllegalArgumentException("username cannot be empty"); + } + if (getNumberOfTokensForUsername(username) >= maxNumberOfAccessTokens) { + revokeOldestDataAccessTokenForUsername(username); + } + String uuid = UUID.randomUUID().toString(); + Calendar calendar = Calendar.getInstance(); + Date creationDate = calendar.getTime(); + calendar.add(Calendar.SECOND, datTtlSeconds); + Date expirationDate = calendar.getTime(); + + DataAccessToken dataAccessToken = + new DataAccessToken(uuid, username, expirationDate, creationDate); + dataAccessTokenRepository.addDataAccessToken(dataAccessToken); + return dataAccessToken; + } + + // get all user tokens/uuids sorted from oldest to newest + @Override + public List getAllDataAccessTokens(String username) { + List allDataAccessTokens = + dataAccessTokenRepository.getAllDataAccessTokensForUsername(username); + return allDataAccessTokens; + } + + // get newest data access token for a given username + @Override + public DataAccessToken getDataAccessToken(String username) { + List allDataAccessTokens = + dataAccessTokenRepository.getAllDataAccessTokensForUsername(username); + DataAccessToken newestDataAccessToken = allDataAccessTokens.get(allDataAccessTokens.size() - 1); + return newestDataAccessToken; + } + + @Override + public DataAccessToken getDataAccessTokenInfo(String token) { + DataAccessToken dataAccessToken = dataAccessTokenRepository.getDataAccessToken(token); + if (dataAccessToken == null) { + throw new TokenNotFoundException("Specified token " + token + " does not exist"); + } + return dataAccessToken; + } + + @Override + public void revokeAllDataAccessTokens(String username) { + dataAccessTokenRepository.removeAllDataAccessTokensForUsername(username); + } + + @Override + public void revokeDataAccessToken(String token) { + DataAccessToken dataAccessToken = dataAccessTokenRepository.getDataAccessToken(token); + if (dataAccessToken == null) { + throw new TokenNotFoundException("Specified token " + token + " does not exist"); + } + dataAccessTokenRepository.removeDataAccessToken(token); + } + + @Override + public String getUsername(String token) { + DataAccessToken dataAccessToken = dataAccessTokenRepository.getDataAccessToken(token); + return dataAccessToken.getUsername(); + } + + @Override + public Date getExpiration(String token) { + DataAccessToken dataAccessToken = dataAccessTokenRepository.getDataAccessToken(token); + return dataAccessToken.getExpiration(); + } + + @Override + public Boolean isValid(String dataAccessToken) { + DataAccessToken storedDataAccessToken = null; + try { + storedDataAccessToken = dataAccessTokenRepository.getDataAccessToken(dataAccessToken); + } catch (Exception e) { + log.error("Error retrieving data access token, " + dataAccessToken + " from token store"); + return Boolean.FALSE; + } + Calendar calendar = Calendar.getInstance(); + Date currentDate = calendar.getTime(); + if (storedDataAccessToken == null + || storedDataAccessToken.getExpiration().before(currentDate)) { + return Boolean.FALSE; + } + return Boolean.TRUE; + } + + private int getNumberOfTokensForUsername(String username) { + List allDataAccessTokens = + dataAccessTokenRepository.getAllDataAccessTokensForUsername(username); + return allDataAccessTokens.size(); + } + + // revokes oldest token in token management system for a user + private void revokeOldestDataAccessTokenForUsername(String username) { + List allDataAccessTokens = + dataAccessTokenRepository.getAllDataAccessTokensForUsername(username); + DataAccessToken oldestDataAccessToken = allDataAccessTokens.get(0); + dataAccessTokenRepository.removeDataAccessToken(oldestDataAccessToken.getToken()); + } + + @Override + public Authentication createAuthenticationRequest(String token) { + + if (!isValid(token)) { + log.error("invalid token = " + token); + throw new BadCredentialsException("Invalid access token"); + } + String userName = getUsername(token); + + // when DaoAuthenticationProvider does authentication on user returned by + // PortalUserDetailsService + // which has password "unused", this password won't match, and then there is a BadCredentials + // exception thrown + // this is a good way to catch that the wrong authetication provider is being used + return new UsernamePasswordAuthenticationToken(userName, "does not match unused"); + } +} diff --git a/src/main/java/org/cbioportal/legacy/service/impl/VariantCountServiceImpl.java b/src/main/java/org/cbioportal/legacy/service/impl/VariantCountServiceImpl.java new file mode 100644 index 00000000000..674ceef6f01 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/impl/VariantCountServiceImpl.java @@ -0,0 +1,74 @@ +package org.cbioportal.legacy.service.impl; + +import java.util.List; +import org.cbioportal.legacy.model.MolecularProfile; +import org.cbioportal.legacy.model.VariantCount; +import org.cbioportal.legacy.persistence.VariantCountRepository; +import org.cbioportal.legacy.service.MolecularProfileService; +import org.cbioportal.legacy.service.MutationService; +import org.cbioportal.legacy.service.SampleListService; +import org.cbioportal.legacy.service.VariantCountService; +import org.cbioportal.legacy.service.exception.MolecularProfileNotFoundException; +import org.cbioportal.legacy.service.exception.SampleListNotFoundException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class VariantCountServiceImpl implements VariantCountService { + + private static final String SEQUENCED_LIST_SUFFIX = "_sequenced"; + + @Autowired private VariantCountRepository variantCountRepository; + @Autowired private MutationService mutationService; + @Autowired private SampleListService sampleListService; + @Autowired private MolecularProfileService molecularProfileService; + + @Override + public List fetchVariantCounts( + String molecularProfileId, List entrezGeneIds, List keywords) + throws MolecularProfileNotFoundException { + + MolecularProfile molecularProfile = validateMolecularProfile(molecularProfileId); + + Integer numberOfSamplesInMolecularProfile = + getNumberOfSamplesInMolecularProfile(molecularProfile); + + List variantCounts = + variantCountRepository.fetchVariantCounts(molecularProfileId, entrezGeneIds, keywords); + variantCounts.forEach(v -> v.setNumberOfSamples(numberOfSamplesInMolecularProfile)); + return variantCounts; + } + + private Integer getNumberOfSamplesInMolecularProfile(MolecularProfile molecularProfile) + throws MolecularProfileNotFoundException { + + try { + return sampleListService + .getSampleList(molecularProfile.getCancerStudyIdentifier() + SEQUENCED_LIST_SUFFIX) + .getSampleCount(); + } catch (SampleListNotFoundException ex) { + return mutationService + .fetchMetaMutationsInMolecularProfile(molecularProfile.getStableId(), null, null) + .getSampleCount(); + } + } + + private MolecularProfile validateMolecularProfile(String molecularProfileId) + throws MolecularProfileNotFoundException { + + MolecularProfile molecularProfile = + molecularProfileService.getMolecularProfile(molecularProfileId); + + if (!(molecularProfile + .getMolecularAlterationType() + .equals(MolecularProfile.MolecularAlterationType.MUTATION_EXTENDED) + || molecularProfile + .getMolecularAlterationType() + .equals(MolecularProfile.MolecularAlterationType.MUTATION_UNCALLED))) { + + throw new MolecularProfileNotFoundException(molecularProfileId); + } + + return molecularProfile; + } +} diff --git a/src/main/java/org/cbioportal/legacy/service/impl/ViolinPlotServiceImpl.java b/src/main/java/org/cbioportal/legacy/service/impl/ViolinPlotServiceImpl.java new file mode 100644 index 00000000000..1a23ac6011a --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/impl/ViolinPlotServiceImpl.java @@ -0,0 +1,260 @@ +package org.cbioportal.legacy.service.impl; + +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; +import org.apache.commons.lang3.math.NumberUtils; +import org.apache.commons.math3.analysis.function.Gaussian; +import org.apache.commons.math3.stat.descriptive.rank.Percentile; +import org.cbioportal.legacy.model.ClinicalData; +import org.cbioportal.legacy.model.ClinicalViolinPlotBoxData; +import org.cbioportal.legacy.model.ClinicalViolinPlotData; +import org.cbioportal.legacy.model.ClinicalViolinPlotIndividualPoint; +import org.cbioportal.legacy.model.ClinicalViolinPlotRowData; +import org.cbioportal.legacy.service.ViolinPlotService; +import org.cbioportal.legacy.web.parameter.StudyViewFilter; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Service; + +@Service +public class ViolinPlotServiceImpl implements ViolinPlotService { + // If a row has less than this many points, do not compute a + // violin, because it doesn't make sense. + static final int SHOW_ONLY_POINTS_THRESHOLD = 7; + + @Cacheable( + cacheResolver = "staticRepositoryCacheOneResolver", + condition = + "@cacheEnabledConfig.getEnabledClickhouse() && @studyViewFilterUtil.isUnfilteredQuery(#studyViewFilter)") + public ClinicalViolinPlotData getClinicalViolinPlotData( + List sampleClinicalDataForViolinPlot, + Set samplesForSampleCountsIds, + BigDecimal axisStart, + BigDecimal axisEnd, + BigDecimal numCurvePoints, + Boolean useLogScale, + BigDecimal sigmaMultiplier, + StudyViewFilter studyViewFilter) { + ClinicalViolinPlotData result = new ClinicalViolinPlotData(); + result.setAxisStart(Double.POSITIVE_INFINITY); + result.setAxisEnd(Double.NEGATIVE_INFINITY); + result.setRows(new ArrayList<>()); + + // clinicalDataMap is a map sampleId->studyId->data + Map>> clinicalDataMap = + sampleClinicalDataForViolinPlot.stream() + .collect( + Collectors.groupingBy( + ClinicalData::getSampleId, Collectors.groupingBy(ClinicalData::getStudyId))); + + // Group data by category + Map> groupedDetailedData = new HashMap<>(); + clinicalDataMap.forEach( + (studyId, dataBySampleId) -> + dataBySampleId.forEach( + (sampleId, sampleData) -> { + // sampleData.size() == 2 means we have clinical data for the sample for both of + // the queried attributes + // We also ensure that the second data is numerical, as expected + if (sampleData.size() == 2) { + int numericalIndex = 0; + int categoricalIndex = 1; + if (NumberUtils.isCreatable(sampleData.get(1).getAttrValue())) { + numericalIndex = 1; + categoricalIndex = 0; + } + String category = sampleData.get(categoricalIndex).getAttrValue(); + ClinicalData datum = sampleData.get(numericalIndex); + if (!groupedDetailedData.containsKey(category)) { + groupedDetailedData.put(category, new ArrayList<>()); + } + groupedDetailedData.get(category).add(datum); + } + })); + + if (groupedDetailedData.isEmpty()) { + return result; + } + + // Calculate boxes, outliers, and data bounds + Map boxData = new HashMap<>(); + Map> nonOutliers = new HashMap<>(); + Map> outliers = new HashMap<>(); + groupedDetailedData.forEach( + (category, data) -> { + Percentile percentile = new Percentile(); + // fill double[] to pass into Percentile + double[] values = new double[data.size()]; + double min = Double.POSITIVE_INFINITY; + double max = Double.NEGATIVE_INFINITY; + int valuesIndex = 0; + for (ClinicalData d : data) { + if (NumberUtils.isCreatable(d.getAttrValue())) { + Double value = + useLogScale + ? ViolinPlotServiceImpl.logScale(Double.parseDouble(d.getAttrValue())) + : Double.parseDouble(d.getAttrValue()); + values[valuesIndex] = value; + min = Math.min(value, min); + max = Math.max(value, max); + valuesIndex += 1; + } + } + + percentile.setData(values); + + double q1 = percentile.evaluate(25); + double q3 = percentile.evaluate(75); + double IQR = q3 - q1; + double SUSPECTED_OUTLIER_MULTIPLE = 1.5; + double OUTLIER_MULTIPLE = 3; + double outlierThresholdLower = q1 - OUTLIER_MULTIPLE * IQR; + double outlierThresholdUpper = q3 + OUTLIER_MULTIPLE * IQR; + double suspectedOutlierThresholdLower = q1 - SUSPECTED_OUTLIER_MULTIPLE * IQR; + double suspectedOutlierThresholdUpper = q3 + SUSPECTED_OUTLIER_MULTIPLE * IQR; + + List _outliers = new ArrayList<>(); + List _nonOutliers = new ArrayList<>(); + List detailedData = groupedDetailedData.get(category); + int numSuspectedOutliers = 0; + for (ClinicalData d : detailedData) { + if (NumberUtils.isCreatable(d.getAttrValue())) { + Double value = + useLogScale + ? ViolinPlotServiceImpl.logScale(Double.parseDouble(d.getAttrValue())) + : Double.parseDouble(d.getAttrValue()); + boolean isOutlier = false; + if (value <= suspectedOutlierThresholdLower) { + numSuspectedOutliers += 1; + if (value <= outlierThresholdLower) { + isOutlier = true; + } + } else if (value >= suspectedOutlierThresholdUpper) { + numSuspectedOutliers += 1; + if (value >= outlierThresholdUpper) { + isOutlier = true; + } + } + if (isOutlier) { + _outliers.add(d); + } else { + _nonOutliers.add(d); + } + } + } + + ClinicalViolinPlotBoxData _boxData = new ClinicalViolinPlotBoxData(); + _boxData.setMedian(percentile.evaluate(50)); + _boxData.setQ1(q1); + _boxData.setQ3(q3); + _boxData.setWhiskerLower(numSuspectedOutliers > 0 ? suspectedOutlierThresholdLower : min); + _boxData.setWhiskerUpper(numSuspectedOutliers > 0 ? suspectedOutlierThresholdUpper : max); + + result.setAxisStart(Math.min(result.getAxisStart(), min)); + result.setAxisEnd(Math.max(result.getAxisEnd(), max)); + + nonOutliers.put(category, _nonOutliers); + outliers.put(category, _outliers); + boxData.put(category, _boxData); + }); + + // Set axis bounds from parameters, if given + if (axisStart != null) { + result.setAxisStart(axisStart.doubleValue()); + } + if (axisEnd != null) { + result.setAxisEnd(axisEnd.doubleValue()); + } + + // Create curves + // By this point, we know the axis bounds + List curvePoints = new ArrayList<>(); + Double stepSize = + (result.getAxisEnd() - result.getAxisStart()) / (numCurvePoints.doubleValue() - 1); + for (int i = 0; i < numCurvePoints.intValue(); i++) { + curvePoints.add(result.getAxisStart() + i * stepSize); + } + double sigma = sigmaMultiplier.doubleValue() * stepSize; + List rows = result.getRows(); + nonOutliers.forEach( + (category, data) -> { + ClinicalViolinPlotRowData row = new ClinicalViolinPlotRowData(); + row.setCategory(category); + row.setNumSamples( + countFilteredSamples(samplesForSampleCountsIds, data, outliers.get(category))); + row.setBoxData(boxData.get(category).limitWhiskers(result)); + + List _individualPoints = new ArrayList<>(); + + if (data.size() + outliers.get(category).size() <= SHOW_ONLY_POINTS_THRESHOLD) { + // show only individual points when data is small + row.setCurveData(new ArrayList<>()); + _individualPoints.addAll(data); + _individualPoints.addAll(outliers.get(category)); + } else { + // build violin only based on non-outliers + List gaussians = new ArrayList<>(); + for (ClinicalData d : data) { + Double value = + useLogScale + ? ViolinPlotServiceImpl.logScale(Double.parseDouble(d.getAttrValue())) + : Double.parseDouble(d.getAttrValue()); + gaussians.add(new Gaussian(value, sigma)); + } + + row.setCurveData( + curvePoints.parallelStream() + .map( + p -> { + BigDecimal sum = new BigDecimal(0); + for (Gaussian g : gaussians) { + sum = sum.add(BigDecimal.valueOf(g.value(p))); + } + return sum.doubleValue(); + }) + .collect(Collectors.toList())); + + // render outliers as individual points + _individualPoints = outliers.get(category); + } + + List individualPoints = new ArrayList<>(); + for (ClinicalData d : _individualPoints) { + ClinicalViolinPlotIndividualPoint p = new ClinicalViolinPlotIndividualPoint(); + p.setSampleId(d.getSampleId()); + p.setStudyId(d.getStudyId()); + p.setValue( + useLogScale + ? ViolinPlotServiceImpl.logScale(Double.parseDouble(d.getAttrValue())) + : Double.parseDouble(d.getAttrValue())); + individualPoints.add(p); + } + row.setIndividualPoints(individualPoints); + rows.add(row); + }); + + // put everything into bins and then do one gaussian per bin, weighted by bin size + return result; + } + + @SafeVarargs + private static int countFilteredSamples( + Set filteredSampleIds, List... dataLists) { + return (int) + Arrays.stream(dataLists) + .flatMap(Collection::stream) + .map(ClinicalData::getInternalId) + .filter(filteredSampleIds::contains) + .count(); + } + + private static double logScale(double val) { + return Math.log(1 + val); + } +} diff --git a/src/main/java/org/cbioportal/legacy/service/util/AlterationCountServiceUtil.java b/src/main/java/org/cbioportal/legacy/service/util/AlterationCountServiceUtil.java new file mode 100644 index 00000000000..0056e7233e7 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/util/AlterationCountServiceUtil.java @@ -0,0 +1,198 @@ +package org.cbioportal.legacy.service.util; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.function.Function; +import java.util.stream.Collectors; +import org.apache.commons.math3.util.Pair; +import org.cbioportal.legacy.model.AlterationCountBase; +import org.cbioportal.legacy.model.AlterationCountByGene; +import org.cbioportal.legacy.model.CopyNumberCountByGene; +import org.cbioportal.legacy.model.Gistic; +import org.cbioportal.legacy.model.GisticToGene; +import org.cbioportal.legacy.model.MolecularProfile; +import org.cbioportal.legacy.model.MutSig; +import org.springframework.lang.NonNull; + +public class AlterationCountServiceUtil { + + private AlterationCountServiceUtil() {} + + private static final String WHOLE_EXOME_SEQUENCING = "WES"; + + public static int computeTotalProfiledCount( + boolean hasGenePanelData, + int alterationsProfiledCount, + int sampleProfileCountWithoutGenePanelData, + int totalProfiledCount) { + int profiledCount = + hasGenePanelData + ? alterationsProfiledCount + sampleProfileCountWithoutGenePanelData + : sampleProfileCountWithoutGenePanelData; + return profiledCount == 0 ? totalProfiledCount : profiledCount; + } + + public static List updateAlterationCountsWithMutSigQValue( + List alterationCountByGenes, Map mutSigs) { + + if (!mutSigs.isEmpty()) { + alterationCountByGenes.parallelStream() + .filter(alterationCount -> mutSigs.containsKey(alterationCount.getHugoGeneSymbol())) + .forEach( + alterationCount -> + alterationCount.setqValue( + mutSigs.get(alterationCount.getHugoGeneSymbol()).getqValue())); + } + return alterationCountByGenes; + } + + public static List updateAlterationCountsWithCNASigQValue( + List alterationCountByGenes, + Map, Gistic> gisticMap) { + + if (!gisticMap.isEmpty()) { + alterationCountByGenes.parallelStream() + .filter( + alterationCount -> + gisticMap.containsKey( + Pair.create( + alterationCount.getHugoGeneSymbol(), alterationCount.getAlteration()))) + .forEach( + alterationCount -> + alterationCount.setqValue( + gisticMap + .get( + Pair.create( + alterationCount.getHugoGeneSymbol(), + alterationCount.getAlteration())) + .getqValue())); + } + return alterationCountByGenes; + } + + public static List getFirstMolecularProfileGroupedByStudy( + List molecularProfiles) { + return molecularProfiles.stream() + .collect( + Collectors.toMap( + MolecularProfile::getCancerStudyIdentifier, + Function.identity(), + (existing, replacement) -> existing // Keep the first occurrence + )) + .values() + .stream() + .toList(); + } + + /** + * Combines alteration counts by Hugo gene symbols. If multiple entries exist for the same gene + * symbol, their number of altered cases and total counts are summed up. Returns a list of unique + * AlterationCountByGene objects where each gene symbol is represented only once. + * + *

This appears in the Data where Genes have similar Hugo Gene Symbols but different Entrez Ids + * + * @param alterationCounts List of AlterationCountByGene objects, potentially with duplicate gene + * symbols + * @return List of AlterationCountByGene objects with unique gene symbols and combined counts + */ + public static List combineAlterationCountsWithConflictingHugoSymbols( + List alterationCounts) { + Map alterationCountByGeneMap = new HashMap<>(); + for (var alterationCount : alterationCounts) { + if (alterationCountByGeneMap.containsKey(alterationCount.getHugoGeneSymbol())) { + AlterationCountByGene toUpdate = + alterationCountByGeneMap.get(alterationCount.getHugoGeneSymbol()); + toUpdate.setNumberOfAlteredCases( + toUpdate.getNumberOfAlteredCases() + alterationCount.getNumberOfAlteredCases()); + toUpdate.setTotalCount(toUpdate.getTotalCount() + alterationCount.getTotalCount()); + } else { + alterationCountByGeneMap.put(alterationCount.getHugoGeneSymbol(), alterationCount); + } + } + return alterationCountByGeneMap.values().stream().toList(); + } + + /** + * Combines alteration counts by Hugo gene symbols. If multiple entries exist for the same gene + * symbol, their number of altered cases and total counts are summed up. Returns a list of unique + * AlterationCountByGene objects where each gene symbol is represented only once. + * + *

This appears in the Data where Genes have similar Hugo Gene Symbols but different Entrez + * Ids. This is a special case to handle Copy Number Mutations where the Alteration type should be + * a part of the key + * + * @param alterationCounts List of CopyNumberCountByGene objects, potentially with duplicate gene + * symbols + * @return List of AlterationCountByGene objects with unique gene symbols and combined counts + */ + public static List combineCopyNumberCountsWithConflictingHugoSymbols( + List alterationCounts) { + Map, CopyNumberCountByGene> alterationCountByGeneMap = new HashMap<>(); + for (var alterationCount : alterationCounts) { + var copyNumberKey = + Pair.create(alterationCount.getHugoGeneSymbol(), alterationCount.getAlteration()); + if (alterationCountByGeneMap.containsKey(copyNumberKey)) { + CopyNumberCountByGene toUpdate = alterationCountByGeneMap.get(copyNumberKey); + toUpdate.setNumberOfAlteredCases( + toUpdate.getNumberOfAlteredCases() + alterationCount.getNumberOfAlteredCases()); + toUpdate.setTotalCount(toUpdate.getTotalCount() + alterationCount.getTotalCount()); + } else { + alterationCountByGeneMap.put(copyNumberKey, alterationCount); + } + } + return alterationCountByGeneMap.values().stream().toList(); + } + + public static boolean hasGenePanelData(@NonNull Set matchingGenePanelIds) { + return matchingGenePanelIds.contains(WHOLE_EXOME_SEQUENCING) && matchingGenePanelIds.size() > 1 + || !matchingGenePanelIds.contains(WHOLE_EXOME_SEQUENCING) + && !matchingGenePanelIds.isEmpty(); + } + + public static void setupGisticMap( + List gisticList, Map, Gistic> gisticMap) { + for (Gistic gistic : gisticList) { + var amp = gistic.getAmp().booleanValue() ? 2 : -2; + for (GisticToGene gene : gistic.getGenes()) { + var key = Pair.create(gene.getHugoGeneSymbol(), amp); + Gistic currentGistic = gisticMap.get(key); + if (currentGistic == null || gistic.getqValue().compareTo(currentGistic.getqValue()) < 0) { + gisticMap.put(key, gistic); + } + } + } + } + + public static void setupAlterationGeneCountsMap( + List studyAlterationCountByGenes, Map totalResult) { + + studyAlterationCountByGenes.forEach( + datum -> { + String key = datum.getUniqueEventKey(); + if (totalResult.containsKey(key)) { + S alterationCountByGene = totalResult.get(key); + alterationCountByGene.setTotalCount( + alterationCountByGene.getTotalCount() + datum.getTotalCount()); + alterationCountByGene.setNumberOfAlteredCases( + alterationCountByGene.getNumberOfAlteredCases() + datum.getNumberOfAlteredCases()); + alterationCountByGene.setNumberOfProfiledCases( + alterationCountByGene.getNumberOfProfiledCases() + + datum.getNumberOfProfiledCases()); + Set matchingGenePanelIds = new HashSet<>(); + if (!alterationCountByGene.getMatchingGenePanelIds().isEmpty()) { + matchingGenePanelIds.addAll(alterationCountByGene.getMatchingGenePanelIds()); + } + if (!datum.getMatchingGenePanelIds().isEmpty()) { + matchingGenePanelIds.addAll(datum.getMatchingGenePanelIds()); + } + alterationCountByGene.setMatchingGenePanelIds(matchingGenePanelIds); + totalResult.put(key, alterationCountByGene); + } else { + totalResult.put(key, datum); + } + }); + } +} diff --git a/src/main/java/org/cbioportal/legacy/service/util/AlterationEnrichmentUtil.java b/src/main/java/org/cbioportal/legacy/service/util/AlterationEnrichmentUtil.java new file mode 100644 index 00000000000..75d85bca557 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/util/AlterationEnrichmentUtil.java @@ -0,0 +1,309 @@ +package org.cbioportal.legacy.service.util; + +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; +import java.util.function.Function; +import java.util.stream.Collectors; +import org.apache.commons.math3.stat.inference.ChiSquareTest; +import org.apache.commons.math3.util.Pair; +import org.cbioportal.legacy.model.AlterationCountBase; +import org.cbioportal.legacy.model.AlterationCountByGene; +import org.cbioportal.legacy.model.AlterationEnrichment; +import org.cbioportal.legacy.model.CountSummary; +import org.cbioportal.legacy.model.Gene; +import org.cbioportal.legacy.model.GenePanelData; +import org.cbioportal.legacy.model.MolecularProfile; +import org.cbioportal.legacy.model.MolecularProfile.MolecularAlterationType; +import org.cbioportal.legacy.model.MolecularProfileCaseIdentifier; +import org.cbioportal.legacy.service.GenePanelService; +import org.cbioportal.legacy.service.GeneService; +import org.cbioportal.legacy.service.MolecularProfileService; +import org.cbioportal.legacy.service.exception.MolecularProfileNotFoundException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +@Component +public class AlterationEnrichmentUtil { + + @Autowired private FisherExactTestCalculator fisherExactTestCalculator; + @Autowired private GeneService geneService; + @Autowired private ProfiledCasesCounter profiledCasesCounter; + @Autowired private GenePanelService genePanelService; + @Autowired private MolecularProfileService molecularProfileService; + + public List createAlterationEnrichments( + Map, Long>> mutationCountsbyGroup) { + + Map> mutationCountsbyEntrezGeneIdAndGroup = + mutationCountsbyGroup.entrySet().stream() + .collect( + Collectors.toMap( + entry -> entry.getKey(), + entry -> { + // convert list of alterations to map with EntrezGeneId as key + return entry.getValue().getFirst().stream() + .collect( + Collectors.toMap(AlterationCountByGene::getEntrezGeneId, c -> c)); + })); + Map profiledCaseCountsByGroup = + mutationCountsbyGroup.entrySet().stream() + .collect(Collectors.toMap(Entry::getKey, entry -> entry.getValue().getSecond())); + Set allGeneIds = + mutationCountsbyEntrezGeneIdAndGroup.values().stream() + .flatMap(x -> x.keySet().stream()) + .collect(Collectors.toSet()); + + Set groups = mutationCountsbyEntrezGeneIdAndGroup.keySet(); + + List genes = + geneService.fetchGenes( + allGeneIds.stream().map(Object::toString).collect(Collectors.toList()), + "ENTREZ_GENE_ID", + "SUMMARY"); + return genes.stream() + .filter( + gene -> { + // filter genes where number of altered cases in all groups is 0 + // or where number of altered cases > number of profiled cases + // (the latter can happen in targeted studies when the gene is not on a panel, + // but it is a participant in a structural variant, e.g. fusion, with a gene + // that is on the panel + return groups.stream() + .filter( + group -> { + AlterationCountByGene mutationCountByGene = + mutationCountsbyEntrezGeneIdAndGroup + .getOrDefault( + group, new HashMap()) + .get(gene.getEntrezGeneId()); + return mutationCountByGene == null + ? false + : (mutationCountByGene.getNumberOfAlteredCases() != 0 + && mutationCountByGene.getNumberOfAlteredCases() + <= mutationCountByGene.getNumberOfProfiledCases()); + }) + .count() + > 0; + }) + .map( + gene -> { + AlterationEnrichment alterationEnrichment = new AlterationEnrichment(); + alterationEnrichment.setEntrezGeneId(gene.getEntrezGeneId()); + alterationEnrichment.setHugoGeneSymbol(gene.getHugoGeneSymbol()); + List counts = + groups.stream() + .map( + group -> { + CountSummary groupCasesCount = new CountSummary(); + AlterationCountByGene mutationCountByGene = + mutationCountsbyEntrezGeneIdAndGroup + .getOrDefault( + group, new HashMap()) + .get(gene.getEntrezGeneId()); + + Integer alteredCount = + mutationCountByGene != null + ? mutationCountByGene.getNumberOfAlteredCases() + : 0; + Integer profiledCount = + mutationCountByGene != null + ? mutationCountByGene.getNumberOfProfiledCases() + : profiledCaseCountsByGroup.get(group).intValue(); + groupCasesCount.setName(group); + groupCasesCount.setAlteredCount(alteredCount); + groupCasesCount.setProfiledCount(profiledCount); + return groupCasesCount; + }) + .collect(Collectors.toList()); + List filteredCounts = + counts.stream() + .filter(groupCasesCount -> groupCasesCount.getProfiledCount() > 0) + .collect(Collectors.toList()); + + // groups where number of altered cases is greater than profiled cases. + // This is a temporary fix for https://github.com/cBioPortal/cbioportal/issues/7274 + // and https://github.com/cBioPortal/cbioportal/issues/7418 + long invalidDataGroups = + filteredCounts.stream() + .filter( + groupCasesCount -> + groupCasesCount.getAlteredCount() + > groupCasesCount.getProfiledCount()) + .count(); + + // calculate p-value only if more than one group have profile cases count + // greater than 0 + if (filteredCounts.size() > 1 && invalidDataGroups == 0) { + double pValue; + // if groups size is two do Fisher Exact test else do Chi-Square test + if (groups.size() == 2) { + + int alteredInNoneCount = + counts.get(1).getProfiledCount() - counts.get(1).getAlteredCount(); + int alteredOnlyInQueryGenesCount = + counts.get(0).getProfiledCount() - counts.get(0).getAlteredCount(); + + pValue = + fisherExactTestCalculator.getTwoTailedPValue( + alteredInNoneCount, + counts.get(1).getAlteredCount(), + alteredOnlyInQueryGenesCount, + counts.get(0).getAlteredCount()); + } else { + + long[][] array = + counts.stream() + .map( + count -> { + return new long[] { + count.getAlteredCount(), + count.getProfiledCount() - count.getAlteredCount() + }; + }) + .toArray(long[][]::new); + + ChiSquareTest chiSquareTest = new ChiSquareTest(); + pValue = chiSquareTest.chiSquareTest(array); + + // set p-value to 1 when the cases in all groups are altered + if (Double.isNaN(pValue)) { + pValue = 1; + } + } + alterationEnrichment.setpValue(BigDecimal.valueOf(pValue)); + } + + alterationEnrichment.setCounts(counts); + return alterationEnrichment; + }) + .collect(Collectors.toList()); + } + + public long includeFrequencyForSamples( + List molecularProfileCaseIdentifiers, + List alterationCounts, + boolean includeMissingAlterationsFromGenePanel) { + + // Collect profile id and sample id arrays. + // These are arrays of equal length, where every index + // represents a sample id / profile id-combination + List sampleIds = new ArrayList<>(); + List molecularProfileIds = new ArrayList<>(); + molecularProfileCaseIdentifiers.forEach( + pair -> { + sampleIds.add(pair.getCaseId()); + molecularProfileIds.add(pair.getMolecularProfileId()); + }); + + List genePanelDataList = + genePanelService.fetchGenePanelDataInMultipleMolecularProfiles( + molecularProfileCaseIdentifiers); + + profiledCasesCounter.calculate( + alterationCounts, + genePanelDataList, + includeMissingAlterationsFromGenePanel, + profiledCasesCounter.sampleUniqueIdentifier); + + return genePanelDataList.stream() + .filter(GenePanelData::getProfiled) + .map(profiledCasesCounter.sampleUniqueIdentifier) + .distinct() + .count(); + } + + public long includeFrequencyForPatients( + List molecularProfileCaseIdentifiers, + List alterationCounts, + boolean includeMissingAlterationsFromGenePanel) { + + // Collect profile id and sample id arrays. + // These are arrays of equal length, where every index + // represents a sample id / profile id-combination + List patientIds = new ArrayList<>(); + List molecularProfileIds = new ArrayList<>(); + molecularProfileCaseIdentifiers.forEach( + pair -> { + patientIds.add(pair.getCaseId()); + molecularProfileIds.add(pair.getMolecularProfileId()); + }); + + List genePanelDataList = + genePanelService.fetchGenePanelDataInMultipleMolecularProfilesByPatientIds( + molecularProfileCaseIdentifiers); + + profiledCasesCounter.calculate( + alterationCounts, + genePanelDataList, + includeMissingAlterationsFromGenePanel, + profiledCasesCounter.patientUniqueIdentifier); + + return genePanelDataList.stream() + .filter(GenePanelData::getProfiled) + .map(profiledCasesCounter.patientUniqueIdentifier) + .distinct() + .count(); + } + + public void validateMolecularProfiles( + Map> molecularProfileCaseSets, + List validMolecularAlterationTypes, + String dataType) + throws MolecularProfileNotFoundException { + + Set molecularProfileIds = + molecularProfileCaseSets.values().stream() + .flatMap( + molecularProfileCaseIdentifiers -> + molecularProfileCaseIdentifiers.stream() + .map(MolecularProfileCaseIdentifier::getMolecularProfileId)) + .collect(Collectors.toSet()); + + List molecularProfiles = + molecularProfileService.getMolecularProfiles(molecularProfileIds, "SUMMARY"); + + if (molecularProfileIds.size() != molecularProfiles.size()) { + Map molecularProfileMap = + molecularProfiles.stream() + .collect(Collectors.toMap(MolecularProfile::getStableId, Function.identity())); + String invalidMolecularProfileIds = + molecularProfileIds.stream() + .filter(molecularProfileId -> !molecularProfileMap.containsKey(molecularProfileId)) + .collect(Collectors.joining(",")); + throw new MolecularProfileNotFoundException(invalidMolecularProfileIds); + } + + Map validMolecularAlterationTypeMap = + validMolecularAlterationTypes.stream() + .collect(Collectors.toMap(Function.identity(), Function.identity())); + + List invalidMolecularProfiles = + molecularProfiles.stream() + .filter( + molecularProfile -> { + if (validMolecularAlterationTypeMap.containsKey( + molecularProfile.getMolecularAlterationType())) { + if (dataType != null) { + return !molecularProfile.getDatatype().equals(dataType); + } + // valid profile + return false; + } + // invalid profile + return true; + }) + .collect(Collectors.toList()); + + if (!invalidMolecularProfiles.isEmpty()) { + throw new MolecularProfileNotFoundException( + invalidMolecularProfiles.stream() + .map(MolecularProfile::getStableId) + .collect(Collectors.joining(","))); + } + } +} diff --git a/src/main/java/org/cbioportal/legacy/service/util/BinnableCustomDataValue.java b/src/main/java/org/cbioportal/legacy/service/util/BinnableCustomDataValue.java new file mode 100644 index 00000000000..32c7da6f23c --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/util/BinnableCustomDataValue.java @@ -0,0 +1,44 @@ +package org.cbioportal.legacy.service.util; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import java.io.Serializable; +import org.cbioportal.legacy.model.Binnable; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class BinnableCustomDataValue implements Binnable, Serializable { + + private final CustomDataValue customDataValue; + private final String attrId; + private final Boolean patientAttribute; + + public BinnableCustomDataValue( + CustomDataValue customDataValue, String attributeId, Boolean patientAttribute) { + this.customDataValue = customDataValue; + this.attrId = attributeId; + this.patientAttribute = patientAttribute; + } + + public String getSampleId() { + return customDataValue.getSampleId(); + } + + public String getPatientId() { + return customDataValue.getPatientId(); + } + + public String getStudyId() { + return customDataValue.getStudyId(); + } + + public String getAttrId() { + return attrId; + } + + public Boolean isPatientAttribute() { + return patientAttribute; + } + + public String getAttrValue() { + return customDataValue.getValue(); + } +} diff --git a/src/main/java/org/cbioportal/legacy/service/util/ChromosomeCalculator.java b/src/main/java/org/cbioportal/legacy/service/util/ChromosomeCalculator.java new file mode 100644 index 00000000000..620995b417d --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/util/ChromosomeCalculator.java @@ -0,0 +1,31 @@ +package org.cbioportal.legacy.service.util; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import org.springframework.stereotype.Component; + +@Component +public class ChromosomeCalculator { + + private String getChromosome(String cytoband) { + + if (cytoband == null) { + return null; + } + + cytoband = cytoband.toUpperCase(); + if (cytoband.startsWith("X")) { + return "X"; + } else if (cytoband.startsWith("Y")) { + return "Y"; + } + + Pattern p = Pattern.compile("([0-9]+).*"); + Matcher m = p.matcher(cytoband); + if (m.find()) { + return m.group(1); + } + + return null; + } +} diff --git a/src/main/java/org/cbioportal/legacy/service/util/ClinicalAttributeUtil.java b/src/main/java/org/cbioportal/legacy/service/util/ClinicalAttributeUtil.java new file mode 100644 index 00000000000..0d4cb4096ac --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/util/ClinicalAttributeUtil.java @@ -0,0 +1,64 @@ +package org.cbioportal.legacy.service.util; + +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; +import org.cbioportal.legacy.model.ClinicalAttribute; +import org.springframework.stereotype.Component; + +@Component +public class ClinicalAttributeUtil { + + public void extractCategorizedClinicalAttributes( + List clinicalAttributes, + List sampleAttributeIds, + List patientAttributeIds, + List conflictingPatientAttributeIds) { + + Set sampleAttributeIdsSet = new HashSet(); + Set patientAttributeIdsSet = new HashSet(); + Set conflictingPatientAttributeIdsSet = new HashSet(); + + Map>> groupedAttributesByIdAndType = + clinicalAttributes.stream() + .collect( + Collectors.groupingBy( + ClinicalAttribute::getAttrId, + Collectors.groupingBy(ClinicalAttribute::getPatientAttribute))); + + groupedAttributesByIdAndType + .entrySet() + .forEach( + entry -> { + if (entry.getValue().keySet().size() == 1) { + entry.getValue().entrySet().stream() + .forEach( + x -> { + if (x.getKey()) { + patientAttributeIdsSet.add(entry.getKey()); + } else { + sampleAttributeIdsSet.add(entry.getKey()); + } + }); + } else { + entry + .getValue() + .entrySet() + .forEach( + x -> { + if (x.getKey()) { + conflictingPatientAttributeIdsSet.add(entry.getKey()); + } else { + sampleAttributeIdsSet.add(entry.getKey()); + } + }); + } + }); + + sampleAttributeIds.addAll(sampleAttributeIdsSet); + patientAttributeIds.addAll(patientAttributeIdsSet); + conflictingPatientAttributeIds.addAll(conflictingPatientAttributeIdsSet); + } +} diff --git a/src/main/java/org/cbioportal/legacy/service/util/CoExpressionAsyncMethods.java b/src/main/java/org/cbioportal/legacy/service/util/CoExpressionAsyncMethods.java new file mode 100644 index 00000000000..420a82ede75 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/util/CoExpressionAsyncMethods.java @@ -0,0 +1,62 @@ +package org.cbioportal.legacy.service.util; + +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.concurrent.CompletableFuture; +import org.apache.commons.lang3.math.NumberUtils; +import org.apache.commons.math3.linear.Array2DRowRealMatrix; +import org.apache.commons.math3.linear.RealMatrix; +import org.apache.commons.math3.stat.correlation.SpearmansCorrelation; +import org.cbioportal.legacy.model.CoExpression; +import org.springframework.scheduling.annotation.Async; +import org.springframework.stereotype.Component; + +@Component +public class CoExpressionAsyncMethods { + + @Async + public CompletableFuture computeCoExpression( + String entityId, List valuesA, List valuesB, Double threshold) { + + List valuesACopy = new ArrayList<>(valuesA); + List valuesBCopy = new ArrayList<>(valuesB); + + Iterator itA = valuesACopy.listIterator(); + Iterator itB = valuesBCopy.listIterator(); + while (itA.hasNext() && itB.hasNext()) { + if (!NumberUtils.isCreatable(itA.next()) | !NumberUtils.isCreatable(itB.next())) { + itA.remove(); + itB.remove(); + } + } + + CoExpression coExpression = new CoExpression(); + coExpression.setGeneticEntityId(entityId); + + double[] valuesBNumber = valuesBCopy.stream().mapToDouble(Double::parseDouble).toArray(); + double[] valuesANumber = valuesACopy.stream().mapToDouble(Double::parseDouble).toArray(); + + if (valuesANumber.length <= 2) { + return null; + } + + double[][] arrays = new double[2][valuesANumber.length]; + arrays[0] = valuesBNumber; + arrays[1] = valuesANumber; + SpearmansCorrelation spearmansCorrelation = + new SpearmansCorrelation((new Array2DRowRealMatrix(arrays, false)).transpose()); + + double spearmansValue = spearmansCorrelation.correlation(valuesBNumber, valuesANumber); + if (Double.isNaN(spearmansValue) || Math.abs(spearmansValue) < threshold) { + return null; + } + coExpression.setSpearmansCorrelation(BigDecimal.valueOf(spearmansValue)); + + RealMatrix resultMatrix = spearmansCorrelation.getRankCorrelation().getCorrelationPValues(); + coExpression.setpValue(BigDecimal.valueOf(resultMatrix.getEntry(0, 1))); + + return CompletableFuture.supplyAsync(() -> coExpression); + } +} diff --git a/src/main/java/org/cbioportal/legacy/service/util/CustomAttributeWithData.java b/src/main/java/org/cbioportal/legacy/service/util/CustomAttributeWithData.java new file mode 100644 index 00000000000..8cff95429ea --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/util/CustomAttributeWithData.java @@ -0,0 +1,114 @@ +package org.cbioportal.legacy.service.util; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import jakarta.validation.constraints.NotNull; +import java.io.Serializable; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class CustomAttributeWithData implements Serializable { + + private String owner = "anonymous"; + private Set origin = new HashSet<>(); + private Long created = System.currentTimeMillis(); + private Long lastUpdated = System.currentTimeMillis(); + private Set users = new HashSet<>(); + + @NotNull private String displayName; + private String description; + private String datatype; + @NotNull private Boolean patientAttribute; + private String priority; + + private List data; + + public String getOwner() { + return owner; + } + + public void setOwner(String owner) { + this.owner = owner; + } + + public void setOrigin(Set origin) { + this.origin = origin; + } + + public Long getCreated() { + return created; + } + + public void setCreated(Long created) { + this.created = created; + } + + public Long getLastUpdated() { + return lastUpdated; + } + + public void setLastUpdated(Long lastUpdated) { + this.lastUpdated = lastUpdated; + } + + public Set getUsers() { + return users; + } + + public void setUsers(Set users) { + this.users = users; + } + + public Set getOrigin() { + return this.origin; + } + + public List getData() { + return data; + } + + public void setData(List data) { + this.data = data; + } + + public String getDisplayName() { + return displayName; + } + + public void setDisplayName(String displayName) { + this.displayName = displayName; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public String getDatatype() { + return datatype; + } + + public void setDatatype(String datatype) { + this.datatype = datatype; + } + + public Boolean getPatientAttribute() { + return patientAttribute; + } + + public void setPatientAttribute(Boolean patientAttribute) { + this.patientAttribute = patientAttribute; + } + + public String getPriority() { + return priority; + } + + public void setPriority(String priority) { + this.priority = priority; + } +} diff --git a/src/main/java/org/cbioportal/legacy/service/util/CustomDataSession.java b/src/main/java/org/cbioportal/legacy/service/util/CustomDataSession.java new file mode 100644 index 00000000000..e2cfd71d41a --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/util/CustomDataSession.java @@ -0,0 +1,43 @@ +package org.cbioportal.legacy.service.util; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.databind.ObjectMapper; +import java.io.IOException; +import org.cbioportal.legacy.utils.removeme.Session; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class CustomDataSession extends Session { + + private static final Logger LOG = LoggerFactory.getLogger(CustomDataSession.class); + private CustomAttributeWithData data; + + @Override + public void setData(Object data) { + ObjectMapper mapper = new ObjectMapper(); + try { + this.data = mapper.readValue(mapper.writeValueAsString(data), CustomAttributeWithData.class); + } catch (IOException e) { + LOG.error("Error occurred", e); + } + } + + @Override + public CustomAttributeWithData getData() { + return data; + } + + @JsonIgnore + @Override + public String getSource() { + return super.getSource(); + } + + @JsonIgnore + @Override + public SessionType getType() { + return super.getType(); + } +} diff --git a/src/main/java/org/cbioportal/legacy/service/util/CustomDataValue.java b/src/main/java/org/cbioportal/legacy/service/util/CustomDataValue.java new file mode 100644 index 00000000000..3a95a520265 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/util/CustomDataValue.java @@ -0,0 +1,47 @@ +package org.cbioportal.legacy.service.util; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import jakarta.validation.constraints.NotNull; +import java.io.Serializable; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class CustomDataValue implements Serializable { + + private String sampleId; + @NotNull private String patientId; + @NotNull private String studyId; + + private String value; + + public String getSampleId() { + return sampleId; + } + + public void setSampleId(String sampleId) { + this.sampleId = sampleId; + } + + public String getPatientId() { + return patientId; + } + + public void setPatientId(String patientId) { + this.patientId = patientId; + } + + public String getStudyId() { + return studyId; + } + + public void setStudyId(String studyId) { + this.studyId = studyId; + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } +} diff --git a/src/main/java/org/cbioportal/legacy/service/util/ExpressionEnrichmentUtil.java b/src/main/java/org/cbioportal/legacy/service/util/ExpressionEnrichmentUtil.java new file mode 100644 index 00000000000..4053ab2f8b0 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/util/ExpressionEnrichmentUtil.java @@ -0,0 +1,459 @@ +package org.cbioportal.legacy.service.util; + +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; +import java.util.function.Function; +import java.util.stream.Collectors; +import java.util.stream.IntStream; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.math.NumberUtils; +import org.apache.commons.math3.stat.StatUtils; +import org.apache.commons.math3.stat.descriptive.DescriptiveStatistics; +import org.apache.commons.math3.stat.inference.ChiSquareTest; +import org.apache.commons.math3.stat.inference.OneWayAnova; +import org.apache.commons.math3.stat.inference.TestUtils; +import org.cbioportal.legacy.model.EnrichmentType; +import org.cbioportal.legacy.model.ExpressionEnrichment; +import org.cbioportal.legacy.model.GenericAssayBinaryEnrichment; +import org.cbioportal.legacy.model.GenericAssayCategoricalEnrichment; +import org.cbioportal.legacy.model.GenericAssayCountSummary; +import org.cbioportal.legacy.model.GenericAssayEnrichment; +import org.cbioportal.legacy.model.GenericAssayMolecularAlteration; +import org.cbioportal.legacy.model.GenomicEnrichment; +import org.cbioportal.legacy.model.GroupStatistics; +import org.cbioportal.legacy.model.MolecularAlteration; +import org.cbioportal.legacy.model.MolecularProfile; +import org.cbioportal.legacy.model.MolecularProfileCaseIdentifier; +import org.cbioportal.legacy.model.MolecularProfileSamples; +import org.cbioportal.legacy.model.Sample; +import org.cbioportal.legacy.persistence.MolecularDataRepository; +import org.cbioportal.legacy.service.SampleService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +@Component +public class ExpressionEnrichmentUtil { + + @Autowired private SampleService sampleService; + @Autowired private MolecularDataRepository molecularDataRepository; + + private static final double LOG2 = Math.log(2); + private static final String RNA_SEQ = "rna_seq"; + private static final List posTypeList = Arrays.asList("true", "yes"); + private static final List negTypeList = Arrays.asList("false", "no"); + private static final String ALTERED = "1"; + private static final String UNALTERED = "0"; + + public List getEnrichments( + MolecularProfile molecularProfile, + Map> molecularProfileCaseSets, + EnrichmentType enrichmentType, + Iterable maItr) { + List expressionEnrichments = new ArrayList<>(); + + Map> groupIndicesMap = + getGroupIndicesMap(molecularProfileCaseSets, enrichmentType, molecularProfile); + for (MolecularAlteration ma : maItr) { + List groupsStatistics = new ArrayList(); + // used for p-value calculation + List groupedValues = new ArrayList(); + + for (Entry> group : groupIndicesMap.entrySet()) { + + // get expression values to all the indices in the group + List molecularDataValues = + group.getValue().stream() + .map(sampleIndex -> ma.getSplitValues()[sampleIndex]) + .filter(a -> NumberUtils.isNumber(a)) + .collect(Collectors.toList()); + + // ignore group if there are less than 2 values + if (molecularDataValues.size() < 2) { + continue; + } + + double[] values = getAlterationValues(molecularDataValues, molecularProfile.getStableId()); + + GroupStatistics groupStatistics = new GroupStatistics(); + double alteredMean = StatUtils.mean(values); + double alteredStandardDeviation = calculateStandardDeviation(values); + + // ignore if mean or standard deviation are not numbers + if (Double.isNaN(alteredMean) || Double.isNaN(alteredStandardDeviation)) { + continue; + } + + groupedValues.add(values); + groupStatistics.setName(group.getKey()); + groupStatistics.setMeanExpression(BigDecimal.valueOf(alteredMean)); + groupStatistics.setStandardDeviation(BigDecimal.valueOf(alteredStandardDeviation)); + groupsStatistics.add(groupStatistics); + } + + // calculate p-value and add enrichment if atleast 2 groups have data + if (groupsStatistics.size() > 1) { + double pValue = calculatePValue(groupedValues); + if (Double.isNaN(pValue)) { + continue; + } + S expressionEnrichment = null; + if (ma instanceof GenericAssayMolecularAlteration) { + GenericAssayEnrichment genericAssayEnrichment = new GenericAssayEnrichment(); + genericAssayEnrichment.setStableId(ma.getStableId()); + expressionEnrichment = (S) genericAssayEnrichment; + } else { + GenomicEnrichment genomicEnrichment = new GenomicEnrichment(); + genomicEnrichment.setEntrezGeneId(Integer.valueOf(ma.getStableId())); + expressionEnrichment = (S) genomicEnrichment; + } + expressionEnrichment.setpValue(BigDecimal.valueOf(pValue)); + expressionEnrichment.setGroupsStatistics(groupsStatistics); + expressionEnrichments.add(expressionEnrichment); + } + } + return expressionEnrichments; + } + + public + List getGenericAssayCategoricalEnrichments( + MolecularProfile molecularProfile, + Map> molecularProfileCaseSets, + EnrichmentType enrichmentType, + Iterable maItr) { + + List expressionEnrichments = new ArrayList<>(); + Map> groupCategoryStatistics = new HashMap<>(); + Map> groupIndicesMap = + getGroupIndicesMap(molecularProfileCaseSets, enrichmentType, molecularProfile); + + for (MolecularAlteration ma : maItr) { + List groupsStatistics = new ArrayList(); + for (Entry> group : groupIndicesMap.entrySet()) { + // Get the corresponding split values for the group + List groupValues = + group.getValue().stream() + .map(sampleIndex -> ma.getSplitValues()[sampleIndex]) + .collect(Collectors.toList()); + // Group and count the split values + Map groupedSplitValues = + groupValues.stream() + .collect(Collectors.toMap(Function.identity(), v -> 1, Integer::sum)); + + // ignore group if there are less than 2 values + if (groupValues.size() < 2) { + continue; + } + + GroupStatistics groupStatistics = new GroupStatistics(); + groupStatistics.setName(group.getKey()); + groupsStatistics.add(groupStatistics); + groupCategoryStatistics.put(group.getKey(), groupedSplitValues); + } + + // calculate p-value and add enrichment if atleast 2 groups have data + + if (groupsStatistics.size() > 1) { + long[][] array = getCategoricalValues(groupCategoryStatistics); + double pValue; + if (array[0].length <= 1) { + pValue = 1; + } else { + ChiSquareTest chiSquareTest = new ChiSquareTest(); + pValue = chiSquareTest.chiSquareTest(array); + } + + // set p-value to 1 when the cases in all groups are altered + if (Double.isNaN(pValue)) { + pValue = 1; + } + + S expressionEnrichment = null; + GenericAssayCategoricalEnrichment genericAssayCategoricalEnrichment = + new GenericAssayCategoricalEnrichment(); + genericAssayCategoricalEnrichment.setStableId(ma.getStableId()); + expressionEnrichment = (S) genericAssayCategoricalEnrichment; + + expressionEnrichment.setpValue(BigDecimal.valueOf(pValue)); + expressionEnrichment.setGroupsStatistics(groupsStatistics); + expressionEnrichments.add(expressionEnrichment); + } + } + return expressionEnrichments; + } + + public + List getGenericAssayBinaryEnrichments( + MolecularProfile molecularProfile, + Map> molecularProfileCaseSets, + EnrichmentType enrichmentType, + Iterable maItr) { + List expressionEnrichments = new ArrayList<>(); + + Map> groupIndicesMap = + getGroupIndicesMap(molecularProfileCaseSets, enrichmentType, molecularProfile); + + for (MolecularAlteration ma : maItr) { + List genericAssayCountSummaries = new ArrayList<>(); + List groupsStatistics = new ArrayList(); + // used for p-value calculation + List groupedValues = new ArrayList(); + + for (Entry> group : groupIndicesMap.entrySet()) { + GenericAssayCountSummary genericAssayCountSummary = new GenericAssayCountSummary(); + genericAssayCountSummary.setName(group.getKey()); + + // get expression values to all the indices in the group, filter NA and map binary values + List molecularDataValues = + group.getValue().stream() + .map(sampleIndex -> ma.getSplitValues()[sampleIndex]) + .filter(StringUtils::isNotEmpty) + .map( + a -> { + if (posTypeList.contains(a)) { + return ALTERED; + } else if (negTypeList.contains(a)) { + return UNALTERED; + } else { + return a; + } + }) + .collect(Collectors.toList()); + + // ignore group if there are less than 2 values + if (molecularDataValues.size() < 2) { + continue; + } + genericAssayCountSummary.setTotalCount(molecularDataValues.size()); + + double[] values = getAlterationValues(molecularDataValues, molecularProfile.getStableId()); + genericAssayCountSummary.setCount( + (int) Arrays.stream(values).filter(num -> num == 1).count()); + GroupStatistics groupStatistics = new GroupStatistics(); + double alteredMean = StatUtils.mean(values); + double alteredStandardDeviation = calculateStandardDeviation(values); + + // ignore if mean or standard deviation are not numbers + if (Double.isNaN(alteredMean) || Double.isNaN(alteredStandardDeviation)) { + continue; + } + + groupedValues.add(values); + groupStatistics.setName(group.getKey()); + groupStatistics.setMeanExpression(BigDecimal.valueOf(alteredMean)); + groupStatistics.setStandardDeviation(BigDecimal.valueOf(alteredStandardDeviation)); + groupsStatistics.add(groupStatistics); + genericAssayCountSummaries.add(genericAssayCountSummary); + } + + // calculate p-value and add enrichment if atleast 2 groups have data + if (groupsStatistics.size() > 1) { + + double pValue = calculatePValue(groupedValues); + if (Double.isNaN(pValue)) { + continue; + } + S expressionEnrichment = null; + GenericAssayBinaryEnrichment genericAssayBinaryEnrichment = + new GenericAssayBinaryEnrichment(); + genericAssayBinaryEnrichment.setStableId(ma.getStableId()); + genericAssayBinaryEnrichment.setCounts(genericAssayCountSummaries); + expressionEnrichment = (S) genericAssayBinaryEnrichment; + + expressionEnrichment.setpValue(BigDecimal.valueOf(pValue)); + expressionEnrichment.setGroupsStatistics(groupsStatistics); + expressionEnrichments.add(expressionEnrichment); + } + } + return expressionEnrichments; + } + + private double[] getAlterationValues( + List molecularDataValues, String molecularProfileId) { + + if (molecularProfileId.contains(RNA_SEQ)) { + return molecularDataValues.stream() + .mapToDouble( + d -> { + double datum = Double.parseDouble(d); + // reset to 0 if there are any negative values and then do log1p + return Math.log1p(datum < 0 ? 0 : datum) / LOG2; + }) + .toArray(); + } else { + return molecularDataValues.stream().mapToDouble(g -> Double.parseDouble(g)).toArray(); + } + } + + private long[][] getCategoricalValues(Map> groupCategoryStatistics) { + // Determine the number of rows and columns + int numRows = groupCategoryStatistics.size(); + Set allCategories = + groupCategoryStatistics.values().stream() + .flatMap(innerMap -> innerMap.keySet().stream()) + .collect(Collectors.toSet()); + int numCols = allCategories.size(); + + // Create the 2-dimensional long array + long[][] array = new long[numRows][numCols]; + + // Iterate over the outer map (group -> categories) + List groupKeys = new ArrayList<>(groupCategoryStatistics.keySet()); + for (int row = 0; row < numRows; row++) { + String groupKey = groupKeys.get(row); + Map innerMap = groupCategoryStatistics.get(groupKey); + + // Iterate over all categories + List categoryKeys = new ArrayList<>(allCategories); + for (int col = 0; col < numCols; col++) { + String categoryKey = categoryKeys.get(col); + + // Get the count from the inner map, or set as zero if the category doesn't exist + int count = innerMap.getOrDefault(categoryKey, 0); + array[row][col] = count; + } + } + return array; + } + + private double calculatePValue(List alteredValues) { + + if (alteredValues.size() == 2) { + return TestUtils.tTest(alteredValues.get(0), alteredValues.get(1)); + } else { + // calculate Anova statisitcs if there are more than 2 groups + OneWayAnova oneWayAnova = new OneWayAnova(); + return oneWayAnova.anovaPValue(alteredValues); + } + } + + private double calculateStandardDeviation(double[] values) { + + DescriptiveStatistics descriptiveStatistics = new DescriptiveStatistics(); + for (double value : values) { + descriptiveStatistics.addValue(value); + } + return descriptiveStatistics.getStandardDeviation(); + } + + /** + * This method maps valid samples in molecularProfileCaseSets to indices in + * genetic_alteration.VALUES column. Recall this column of the genetic_alteration table is a comma + * separated list of scalar values. Each value in this list is associated with a sample at the + * same position found in the genetic_profile_samples.ORDERED_SAMPLE_LIST column. + * + * @param molecularProfileCaseSets + * @param enrichmentType + * @param molecularProfile + * @return + */ + private Map> getGroupIndicesMap( + Map> molecularProfileCaseSets, + EnrichmentType enrichmentType, + MolecularProfile molecularProfile) { + + MolecularProfileSamples commaSeparatedSampleIdsOfMolecularProfile = + molecularDataRepository.getCommaSeparatedSampleIdsOfMolecularProfile( + molecularProfile.getStableId()); + + List internalSampleIds = + Arrays.stream(commaSeparatedSampleIdsOfMolecularProfile.getSplitSampleIds()) + .mapToInt(Integer::parseInt) + .boxed() + .collect(Collectors.toList()); + + Map internalSampleIdToIndexMap = + IntStream.range(0, internalSampleIds.size()) + .boxed() + .collect(Collectors.toMap(internalSampleIds::get, Function.identity())); + + Map> selectedCaseIdToInternalIdsMap = + getCaseIdToInternalIdsMap(molecularProfileCaseSets, enrichmentType, molecularProfile); + + // this block map caseIds(sampleIds or patientids) to sampleIndices which + // represents the position fount in the + // genetic_profile_samples.ORDERED_SAMPLE_LIST column + Map> groupIndicesMap = + molecularProfileCaseSets.entrySet().stream() + .collect( + Collectors.toMap( + entity -> entity.getKey(), + entity -> { + List sampleIndices = new ArrayList<>(); + entity + .getValue() + .forEach( + molecularProfileCaseIdentifier -> { + // consider only valid samples + if (selectedCaseIdToInternalIdsMap.containsKey( + molecularProfileCaseIdentifier.getCaseId())) { + List sampleInternalIds = + selectedCaseIdToInternalIdsMap.get( + molecularProfileCaseIdentifier.getCaseId()); + + // only consider samples which are profiled for the give molecular + // profile id + sampleInternalIds.forEach( + sampleInternalId -> { + if (internalSampleIdToIndexMap.containsKey( + sampleInternalId)) { + sampleIndices.add( + internalSampleIdToIndexMap.get(sampleInternalId)); + } + }); + } + }); + return sampleIndices; + })); + return groupIndicesMap; + } + + private Map> getCaseIdToInternalIdsMap( + Map> molecularProfileCaseSets, + EnrichmentType enrichmentType, + MolecularProfile molecularProfile) { + + if (enrichmentType.equals(EnrichmentType.PATIENT)) { + List patientIds = + molecularProfileCaseSets.values().stream() + .flatMap( + molecularProfileCaseSet -> + molecularProfileCaseSet.stream() + .map(MolecularProfileCaseIdentifier::getCaseId)) + .collect(Collectors.toList()); + + List samples = + sampleService.getAllSamplesOfPatientsInStudy( + molecularProfile.getCancerStudyIdentifier(), patientIds, "SUMMARY"); + + return samples.stream() + .collect( + Collectors.groupingBy( + Sample::getPatientStableId, + Collectors.mapping(Sample::getInternalId, Collectors.toList()))); + } else { + List sampleIds = new ArrayList<>(); + List studyIds = new ArrayList<>(); + + molecularProfileCaseSets + .values() + .forEach( + molecularProfileCaseIdentifiers -> { + molecularProfileCaseIdentifiers.forEach( + molecularProfileCaseIdentifier -> { + sampleIds.add(molecularProfileCaseIdentifier.getCaseId()); + studyIds.add(molecularProfile.getCancerStudyIdentifier()); + }); + }); + List samples = sampleService.fetchSamples(studyIds, sampleIds, "ID"); + + return samples.stream() + .collect(Collectors.toMap(Sample::getStableId, x -> Arrays.asList(x.getInternalId()))); + } + } +} diff --git a/src/main/java/org/cbioportal/legacy/service/util/FisherExactTestCalculator.java b/src/main/java/org/cbioportal/legacy/service/util/FisherExactTestCalculator.java new file mode 100644 index 00000000000..9b6715c77a5 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/util/FisherExactTestCalculator.java @@ -0,0 +1,127 @@ +package org.cbioportal.legacy.service.util; + +import java.math.BigDecimal; +import org.springframework.stereotype.Component; + +@Component +public class FisherExactTestCalculator { + + private double getPValue(int a, int b, int c, int d, double[] f) { + + int n = a + b + c + d; + double p = (f[a + b] + f[c + d] + f[a + c] + f[b + d]) - (f[a] + f[b] + f[c] + f[d] + f[n]); + return Math.exp(p); + } + + public double getCumulativePValue(int a, int b, int c, int d) { + + int min, i; + int n = a + b + c + d; + double p = 0; + double[] f = new double[n + 1]; + f[0] = 0.0; + + for (int j = 1; j <= n; j++) { + f[j] = f[j - 1] + Math.log(j); + } + + p += getPValue(a, b, c, d, f); + if ((a * d) >= (b * c)) { + min = (c < b) ? c : b; + for (i = 0; i < min; i++) { + p += getPValue(++a, --b, --c, ++d, f); + } + } + + if ((a * d) < (b * c)) { + min = (a < d) ? a : d; + for (i = 0; i < min; i++) { + p += getPValue(--a, ++b, ++c, --d, f); + } + } + return p; + } + + public double getTwoTailedPValue(int a, int b, int c, int d) { + + int min, i; + int n = a + b + c + d; + double p = 0; + double[] f = new double[n + 1]; + f[0] = 0.0; + + for (int j = 1; j <= n; j++) { + f[j] = f[j - 1] + Math.log(j); + } + + double baseP = getPValue(a, b, c, d, f); + // in order for a table under consideration to have its p-value included + // in the final result, it must have a p-value less than the baseP, i.e. + // Fisher's exact test computes the probability, given the observed marginal + // frequencies, of obtaining exactly the frequencies observed and any configuration more + // extreme. + // By "more extreme," we mean any configuration (given observed marginals) with a + // smaller probability of + // occurrence in the same direction (one-tailed) or in both directions (two-tailed). + + int initialA = a, initialB = b, initialC = c, initialD = d; + p += baseP; + + min = (c < b) ? c : b; + for (i = 0; i < min; i++) { + double tempP = getPValue(++a, --b, --c, ++d, f); + if (tempP <= baseP) { + p += tempP; + } + } + + // reset the values to their original so we can repeat this process for the other side + a = initialA; + b = initialB; + c = initialC; + d = initialD; + + min = (a < d) ? a : d; + for (i = 0; i < min; i++) { + double pTemp = getPValue(--a, ++b, ++c, --d, f); + if (pTemp <= baseP) { + p += pTemp; + } + } + return p; + } + + public BigDecimal[] calcqValue(BigDecimal[] pValuesInIncreasingOrder) { + BigDecimal cachedElement = BigDecimal.valueOf(0.0); + int dataLength = pValuesInIncreasingOrder.length; + BigDecimal[] reversedQValues = new BigDecimal[dataLength]; + + reverseValues(dataLength, pValuesInIncreasingOrder); + + for (int i = 0; i < dataLength; i++) { + if (i > 0) { + BigDecimal calculatedValue = + cachedElement.min( + (pValuesInIncreasingOrder[i].multiply(new BigDecimal(dataLength))) + .divide(new BigDecimal(dataLength - i), BigDecimal.ROUND_HALF_UP)); + cachedElement = calculatedValue; + reversedQValues[i] = calculatedValue; + } else { + cachedElement = pValuesInIncreasingOrder[i]; + reversedQValues[i] = pValuesInIncreasingOrder[i]; + } + } + + reverseValues(dataLength, reversedQValues); + + return reversedQValues; + } + + private void reverseValues(int dataLength, BigDecimal[] reversedQValues) { + for (int i = 0; i < dataLength / 2; i++) { + BigDecimal temp = reversedQValues[i]; + reversedQValues[i] = reversedQValues[dataLength - i - 1]; + reversedQValues[dataLength - i - 1] = temp; + } + } +} diff --git a/src/main/java/org/cbioportal/legacy/service/util/JwtUtils.java b/src/main/java/org/cbioportal/legacy/service/util/JwtUtils.java new file mode 100644 index 00000000000..77c34623c50 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/util/JwtUtils.java @@ -0,0 +1,158 @@ +/* + * Copyright (c) 2018 Memorial Sloan-Kettering Cancer Center. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS + * FOR A PARTICULAR PURPOSE. The software and documentation provided hereunder + * is on an "as is" basis, and Memorial Sloan-Kettering Cancer Center has no + * obligations to provide maintenance, support, updates, enhancements or + * modifications. In no event shall Memorial Sloan-Kettering Cancer Center be + * liable to any party for direct, indirect, special, incidental or + * consequential damages, including lost profits, arising out of the use of this + * software and its documentation, even if Memorial Sloan-Kettering Cancer + * Center has been advised of the possibility of such damage. + */ + +/* + * Copyright 2002-2018 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * This file is part of cBioPortal. + * + * cBioPortal is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package org.cbioportal.legacy.service.util; + +import io.jsonwebtoken.Claims; +import io.jsonwebtoken.ExpiredJwtException; +import io.jsonwebtoken.Jws; +import io.jsonwebtoken.Jwts; +import io.jsonwebtoken.SignatureAlgorithm; +import io.jsonwebtoken.SignatureException; +import io.jsonwebtoken.io.Decoders; +import io.jsonwebtoken.security.Keys; +import java.util.*; +import javax.crypto.SecretKey; +import org.cbioportal.legacy.model.DataAccessToken; +import org.cbioportal.legacy.service.exception.InvalidDataAccessTokenException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +@Component +public class JwtUtils { + + private byte[] decodedSecretKey; + + @Value("${dat.jwt.secret_key:none}") // default value is none + private void setDecodedSecretKey(String secretKey) { + if (!secretKey.isEmpty() && !secretKey.equalsIgnoreCase("none")) { + this.decodedSecretKey = Decoders.BASE64.decode(secretKey); + } + } + + @Value("${dat.ttl_seconds:-1}") // default value is -1 + private int jwtTtlSeconds; + + private static final Logger LOG = LoggerFactory.getLogger(JwtUtils.class); + + public DataAccessToken createToken(String username) { + return this.createToken(username, this.jwtTtlSeconds); + } + + public DataAccessToken createToken(String username, int jwtTtlSeconds) { + if (username == null || username.trim().length() == 0) { + throw new IllegalArgumentException("subject cannot be empty"); + } + Calendar calendar = Calendar.getInstance(); + Date creationDate = calendar.getTime(); + calendar.add(Calendar.SECOND, jwtTtlSeconds); + Date expirationDate = calendar.getTime(); + String jws = + Jwts.builder() + .setSubject(username) + .setIssuedAt(creationDate) + .setExpiration(expirationDate) + .signWith(SignatureAlgorithm.HS256, decodedSecretKey) + .compact(); + return new DataAccessToken(jws, username, expirationDate, creationDate); + } + + public void validate(String token) throws InvalidDataAccessTokenException { + Map properties = extractClaims(token); + } + + public String extractSubject(String token) throws InvalidDataAccessTokenException { + Claims claims = extractClaims(token); + return claims.getSubject(); + } + + public Date extractExpirationDate(String token) throws InvalidDataAccessTokenException { + Claims claims = extractClaims(token); + return claims.getExpiration(); + } + + public Map extractProperties(String token) + throws InvalidDataAccessTokenException { + return extractClaims(token); + } + + public Claims extractClaims(String token) throws InvalidDataAccessTokenException { + Claims claims = null; + try { + Jws jwsClaims = Jwts.parser().setSigningKey(decodedSecretKey).parseClaimsJws(token); + claims = jwsClaims.getBody(); + } catch (SignatureException e) { + LOG.error("Error occurred", e); + throw new InvalidDataAccessTokenException("signature not valid"); + } catch (ExpiredJwtException e) { + LOG.error("Error occurred", e); + throw new InvalidDataAccessTokenException("token has expired"); + } + return claims; + } + + public static String createNewSecretKey() { + SecretKey key = + Keys.secretKeyFor( + SignatureAlgorithm + .HS256); // TODO: consider other Algorithms .. or parameterizing this choice + String encodedKey = Base64.getEncoder().encodeToString(key.getEncoded()); + return encodedKey; + } + + public static void main(String[] args) { + if (args.length == 1 && args[0].equals("--make-key")) { + System.out.println("Creating new secret key for JWTS token signing:"); + System.out.println(createNewSecretKey()); + } else { + System.out.println("usage: JwtUtils --make-key"); + } + } +} diff --git a/src/main/java/org/cbioportal/legacy/service/util/MolecularProfileUtil.java b/src/main/java/org/cbioportal/legacy/service/util/MolecularProfileUtil.java new file mode 100644 index 00000000000..fd4ce6a4bfc --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/util/MolecularProfileUtil.java @@ -0,0 +1,102 @@ +package org.cbioportal.legacy.service.util; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.function.Predicate; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import org.cbioportal.legacy.model.MolecularProfile; +import org.cbioportal.legacy.model.MolecularProfileCaseIdentifier; +import org.springframework.stereotype.Component; + +@Component +public class MolecularProfileUtil { + + public final String MUTATION_PROFILE_SUFFIX = "_mutations"; + public final String STRUCTURAL_VARIANT_PROFILE_SUFFIX = "_structural_variants"; + + public Predicate isStructuralVariantMolecularProfile = + m -> + m.getMolecularAlterationType() + .equals(MolecularProfile.MolecularAlterationType.STRUCTURAL_VARIANT); + + public Predicate isDiscreteCNAMolecularProfile = + m -> + m.getMolecularAlterationType() + .equals(MolecularProfile.MolecularAlterationType.COPY_NUMBER_ALTERATION) + && m.getDatatype().equals("DISCRETE"); + + public Predicate isMutationProfile = + m -> + m.getMolecularAlterationType() + .equals(MolecularProfile.MolecularAlterationType.MUTATION_EXTENDED); + + public Map> categorizeMolecularProfilesByStableIdSuffixes( + List molecularProfiles) { + return molecularProfiles.stream() + .collect( + Collectors.groupingBy( + molecularProfile -> + molecularProfile + .getStableId() + .replace(molecularProfile.getCancerStudyIdentifier() + "_", ""))); + } + + public List getFirstFilteredMolecularProfileCaseIdentifiers( + List molecularProfiles, + List studyIds, + List sampleIds, + Optional> profileFilter) { + Map> mapByStudyId = + getFilteredMolecularProfilesByStudyId(molecularProfiles, profileFilter); + List caseIdentifiers = new ArrayList<>(); + for (int studyIdIdx = 0; studyIdIdx < studyIds.size(); studyIdIdx++) { + String studyId = studyIds.get(studyIdIdx); + if (mapByStudyId.containsKey(studyId)) { + // only add identifier for one molecular profile + caseIdentifiers.add( + new MolecularProfileCaseIdentifier( + sampleIds.get(studyIdIdx), mapByStudyId.get(studyId).getFirst().getStableId())); + } + } + return caseIdentifiers; + } + + public List getFilteredMolecularProfileCaseIdentifiers( + List molecularProfiles, + List studyIds, + List sampleIds, + Optional> profileFilter) { + Map> mapByStudyId = + getFilteredMolecularProfilesByStudyId(molecularProfiles, profileFilter); + List caseIdentifiers = new ArrayList<>(); + for (int studyIdIdx = 0; studyIdIdx < studyIds.size(); studyIdIdx++) { + String studyId = studyIds.get(studyIdIdx); + if (mapByStudyId.containsKey(studyId)) { + // add case identifiers for all molecular profiles + int finalStudyIdIdx = studyIdIdx; + mapByStudyId + .getOrDefault(studyId, new ArrayList<>()) + .forEach( + molecularProfile -> + caseIdentifiers.add( + new MolecularProfileCaseIdentifier( + sampleIds.get(finalStudyIdIdx), molecularProfile.getStableId()))); + } + } + return caseIdentifiers; + } + + private Map> getFilteredMolecularProfilesByStudyId( + List molecularProfiles, + Optional> profileFilter) { + Stream molecularProfileStream = molecularProfiles.stream(); + if (profileFilter.isPresent()) { + molecularProfileStream = molecularProfileStream.filter(profileFilter.get()); + } + return molecularProfileStream.collect( + Collectors.groupingBy(MolecularProfile::getCancerStudyIdentifier)); + } +} diff --git a/src/main/java/org/cbioportal/legacy/service/util/MskWholeSlideViewerTokenGenerator.java b/src/main/java/org/cbioportal/legacy/service/util/MskWholeSlideViewerTokenGenerator.java new file mode 100644 index 00000000000..94d1c5680e4 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/util/MskWholeSlideViewerTokenGenerator.java @@ -0,0 +1,37 @@ +package org.cbioportal.legacy.service.util; + +import java.util.Base64; +import javax.crypto.Mac; +import javax.crypto.spec.SecretKeySpec; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class MskWholeSlideViewerTokenGenerator { + // ~ Static fields + // ======================================================================================================== + + private static final Logger logger = + LoggerFactory.getLogger(MskWholeSlideViewerTokenGenerator.class); + private static final String PORTAL_NAME = "cbioportal"; + + // ~ Methods + // ======================================================================================================== + + public static String generateTokenByHmacSHA256( + String username, String secretKey, String timeStamp) { + try { + String message = PORTAL_NAME + "?" + "user=" + username + "&t=" + timeStamp; + + Mac sha256_HMAC = Mac.getInstance("HmacSHA256"); + SecretKeySpec secret_key = new SecretKeySpec(secretKey.getBytes(), "HmacSHA256"); + sha256_HMAC.init(secret_key); + String hash = Base64.getEncoder().encodeToString(sha256_HMAC.doFinal(message.getBytes())); + return hash; + } catch (Exception e) { + if (logger.isErrorEnabled()) { + logger.error("Error generate msk Whole slide viewer token: " + e.getMessage()); + } + return null; + } + } +} diff --git a/src/main/java/org/cbioportal/legacy/service/util/ProfiledCasesCounter.java b/src/main/java/org/cbioportal/legacy/service/util/ProfiledCasesCounter.java new file mode 100644 index 00000000000..b8bdf7238d0 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/util/ProfiledCasesCounter.java @@ -0,0 +1,245 @@ +package org.cbioportal.legacy.service.util; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.function.Function; +import java.util.stream.Collectors; +import org.apache.commons.math3.util.Pair; +import org.cbioportal.legacy.model.AlterationCountBase; +import org.cbioportal.legacy.model.AlterationCountByGene; +import org.cbioportal.legacy.model.AlterationCountByStructuralVariant; +import org.cbioportal.legacy.model.GenePanel; +import org.cbioportal.legacy.model.GenePanelData; +import org.cbioportal.legacy.model.GenePanelToGene; +import org.cbioportal.legacy.service.GenePanelService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +@Component +public class ProfiledCasesCounter { + + @Autowired private GenePanelService genePanelService; + + Function sampleUniqueIdentifier = + sample -> sample.getStudyId() + sample.getSampleId(); + Function patientUniqueIdentifier = + sample -> sample.getStudyId() + sample.getPatientId(); + + private enum ProfiledCaseType { + SAMPLE, + PATIENT + } + + public void calculate( + List alterationCounts, + List genePanelDataList, + boolean includeMissingAlterationsFromGenePanel, + Function caseUniqueIdentifier) { + + ProfiledCaseType profiledCaseType = + (caseUniqueIdentifier == patientUniqueIdentifier) + ? ProfiledCaseType.PATIENT + : ProfiledCaseType.SAMPLE; + Map> casesWithDataInGenePanel = + extractCasesWithDataInGenePanel(genePanelDataList, caseUniqueIdentifier); + List genePanels = new ArrayList<>(); + if (!casesWithDataInGenePanel.isEmpty()) { + genePanels = + genePanelService.fetchGenePanels( + new ArrayList<>(casesWithDataInGenePanel.keySet()), "DETAILED"); + } + + Map, List> geneToGenePanel = new HashMap<>(); + for (GenePanel genePanel : genePanels) { + for (GenePanelToGene genePanelToGene : genePanel.getGenes()) { + // TODO I am not sure whether it is smart to include the HUGO gene suymbol in the key here. + // What if two panels have the same Entrez gene id with different Hugo gene symbols? If that + // situation + // can never occur, better not include the HUGO symbol in the key and only use entrez gene + // id. It confuses + // developers that may think it is an important key element. + Pair key = + new Pair<>(genePanelToGene.getEntrezGeneId(), genePanelToGene.getHugoGeneSymbol()); + if (geneToGenePanel.containsKey(key)) { + geneToGenePanel.get(key).add(genePanel); + } else { + List geneGenePanelList = new ArrayList<>(); + geneGenePanelList.add(genePanel); + geneToGenePanel.put(key, geneGenePanelList); + } + } + } + + List genePanelData = + genePanelDataList.stream().filter(GenePanelData::getProfiled).collect(Collectors.toList()); + + Set profiledCases = + genePanelData.stream() + // there can be duplicate patient or sample id, append study id + .map(caseUniqueIdentifier) + .collect(Collectors.toSet()); + int profiledCasesCount = profiledCases.size(); + + // here we look for cases where none of the profiles have gene panel ids + // a case with at least one profile with gene panel id is considered as a case with gene panel + // data + // so a case is considered without panel data only if none of the profiles has a gene panel id + + // first identify cases with gene panel data + Set casesWithPanelData = + genePanelData.stream() + .filter(g -> g.getGenePanelId() != null) + // there can be duplicate patient or sample id, append study id + .map(caseUniqueIdentifier) + .collect(Collectors.toSet()); + + // find all unique cases + Set casesWithoutPanelData = + genePanelData.stream() + // there can be duplicate patient or sample id, append study id + .map(caseUniqueIdentifier) + .collect(Collectors.toSet()); + + // removing cases with panel data from all unique cases gives us the cases without panel data + casesWithoutPanelData.removeAll(casesWithPanelData); + + for (T alterationCount : alterationCounts) { + Set totalProfiledPatients = new HashSet<>(); + Set allMatchingGenePanelIds = new HashSet<>(); + int totalProfiledSamples = 0; + // different calculations depending on if gene is linked to gene panels + if (alterationIsCoveredByGenePanel(alterationCount, geneToGenePanel)) { + // for every gene panel associated containing the gene, use the sum of unique cases + // as well as cases without panel data + for (GenePanel genePanel : + getGenePanelsForAlterationCount(alterationCount, geneToGenePanel)) { + allMatchingGenePanelIds.add(genePanel.getStableId()); + if (profiledCaseType == ProfiledCaseType.PATIENT) { + totalProfiledPatients.addAll(casesWithDataInGenePanel.get(genePanel.getStableId())); + } else { + totalProfiledSamples += casesWithDataInGenePanel.get(genePanel.getStableId()).size(); + } + } + if (profiledCaseType == ProfiledCaseType.PATIENT) { + totalProfiledPatients.addAll(casesWithoutPanelData); + alterationCount.setNumberOfProfiledCases(totalProfiledPatients.size()); + } else { + totalProfiledSamples += casesWithoutPanelData.size(); + alterationCount.setNumberOfProfiledCases(totalProfiledSamples); + } + } else { + // casesWithoutPanelData is more accurate, so we use profiledCasesCount as a fallback to + // prevent a divide by zero error which can happen for targeted studies + // in which certain genes have events that are not captured by the panel. + alterationCount.setNumberOfProfiledCases( + !casesWithoutPanelData.isEmpty() ? casesWithoutPanelData.size() : profiledCasesCount); + } + alterationCount.setMatchingGenePanelIds(allMatchingGenePanelIds); + } + + if (includeMissingAlterationsFromGenePanel) { + Set genesWithAlteration = + alterationCounts.stream() + .flatMap(count -> Arrays.stream(count.getEntrezGeneIds())) + .collect(Collectors.toSet()); + + geneToGenePanel + .entrySet() + .forEach( + entry -> { + Integer entrezGeneId = entry.getKey().getFirst(); + String hugoGeneSymbol = entry.getKey().getSecond(); + // add alterationCount object where there are no alterations but have genePanel + // object + if (!genesWithAlteration.contains(entrezGeneId)) { + AlterationCountByGene alterationCountByGene = new AlterationCountByGene(); + + Set totalProfiledPatients = new HashSet<>(); + Set allMatchingGenePanelIds = new HashSet<>(); + int totalProfiledSamples = 0; + for (GenePanel genePanel : + geneToGenePanel.get(new Pair<>(entrezGeneId, hugoGeneSymbol))) { + allMatchingGenePanelIds.add(genePanel.getStableId()); + if (profiledCaseType == ProfiledCaseType.PATIENT) { + totalProfiledPatients.addAll( + casesWithDataInGenePanel.get(genePanel.getStableId())); + } else { + totalProfiledSamples += + casesWithDataInGenePanel.get(genePanel.getStableId()).size(); + } + } + if (profiledCaseType == ProfiledCaseType.PATIENT) { + totalProfiledPatients.addAll(casesWithoutPanelData); + } else { + totalProfiledSamples += casesWithoutPanelData.size(); + } + + alterationCountByGene.setEntrezGeneId(entrezGeneId); + alterationCountByGene.setMatchingGenePanelIds(allMatchingGenePanelIds); + if (profiledCaseType == ProfiledCaseType.PATIENT) { + alterationCountByGene.setNumberOfProfiledCases(totalProfiledPatients.size()); + } else { + alterationCountByGene.setNumberOfProfiledCases(totalProfiledSamples); + } + alterationCountByGene.setNumberOfAlteredCases(0); + alterationCountByGene.setTotalCount(0); + alterationCountByGene.setHugoGeneSymbol(hugoGeneSymbol); + + alterationCounts.add((T) alterationCountByGene); + } + }); + } + } + + private Map> extractCasesWithDataInGenePanel( + List genePanelDataList, Function caseUniqueIdentifier) { + + Map> casesWithDataInGenePanel = new HashMap<>(); + // loop through all membership records -- ignore any where g.getGenePanelId == null + for (GenePanelData genePanelDataRecord : genePanelDataList) { + String associatedGenePanel = genePanelDataRecord.getGenePanelId(); + if (associatedGenePanel != null) { + casesWithDataInGenePanel.putIfAbsent(associatedGenePanel, new HashSet<>()); + Set casesForThisGenePanel = casesWithDataInGenePanel.get(associatedGenePanel); + casesForThisGenePanel.add(caseUniqueIdentifier.apply(genePanelDataRecord)); + } + } + return casesWithDataInGenePanel; + } + + private boolean alterationIsCoveredByGenePanel( + T alterationCount, Map, List> entrezIdToGenePanel) { + return !getGenePanelsForAlterationCount(alterationCount, entrezIdToGenePanel).isEmpty(); + } + + private List getGenePanelsForAlterationCount( + T alterationCount, Map, List> entrezIdToGenePanel) { + if (alterationCount instanceof AlterationCountByGene alterationCountByGene) { + Integer entrezId = alterationCountByGene.getEntrezGeneId(); + String hugoSymbol = alterationCountByGene.getHugoGeneSymbol(); + return entrezIdToGenePanel.getOrDefault(new Pair<>(entrezId, hugoSymbol), new ArrayList<>()); + } + if (alterationCount + instanceof AlterationCountByStructuralVariant alterationCountByStructuralVariant) { + Integer gene1EntrezId = alterationCountByStructuralVariant.getGene1EntrezGeneId(); + String gene1HugoSymbol = alterationCountByStructuralVariant.getGene1HugoGeneSymbol(); + Integer gene2EntrezId = alterationCountByStructuralVariant.getGene2EntrezGeneId(); + String gene2HugoSymbol = alterationCountByStructuralVariant.getGene2HugoGeneSymbol(); + List panels = + entrezIdToGenePanel.getOrDefault( + new Pair<>(gene1EntrezId, gene1HugoSymbol), new ArrayList<>()); + panels.addAll( + entrezIdToGenePanel.getOrDefault( + new Pair<>(gene2EntrezId, gene2HugoSymbol), new ArrayList<>())); + return panels.stream().distinct().collect(Collectors.toList()); + } + throw new IllegalArgumentException( + "At present only AlterationCountByGene or AlterationCountByStructuralVariant are " + + "supported."); + } +} diff --git a/src/main/java/org/cbioportal/legacy/service/util/SessionServiceConfig.java b/src/main/java/org/cbioportal/legacy/service/util/SessionServiceConfig.java new file mode 100644 index 00000000000..f34d7485715 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/util/SessionServiceConfig.java @@ -0,0 +1,15 @@ +package org.cbioportal.legacy.service.util; + +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class SessionServiceConfig { + + @Bean + public ObjectMapper sessionServiceObjectMapper() { + return new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + } +} diff --git a/src/main/java/org/cbioportal/legacy/service/util/SessionServiceRequestHandler.java b/src/main/java/org/cbioportal/legacy/service/util/SessionServiceRequestHandler.java new file mode 100644 index 00000000000..e34010dad35 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/util/SessionServiceRequestHandler.java @@ -0,0 +1,398 @@ +package org.cbioportal.legacy.service.util; + +import static org.cbioportal.legacy.utils.removeme.Session.*; + +import com.mongodb.BasicDBObject; +import java.io.Serializable; +import java.nio.charset.Charset; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Set; +import java.util.regex.Pattern; +import org.apache.commons.codec.binary.Base64; +import org.apache.commons.lang3.StringUtils; +import org.cbioportal.legacy.utils.removeme.Session; +import org.cbioportal.legacy.web.parameter.CustomGeneList; +import org.cbioportal.legacy.web.parameter.PageSettings; +import org.cbioportal.legacy.web.parameter.PageSettingsData; +import org.cbioportal.legacy.web.parameter.VirtualStudy; +import org.cbioportal.legacy.web.parameter.VirtualStudyData; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.core.ParameterizedTypeReference; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.HttpStatusCode; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Component; +import org.springframework.web.client.RestTemplate; +import org.springframework.web.util.UriComponentsBuilder; + +@Component +public class SessionServiceRequestHandler { + + private static final Logger LOG = LoggerFactory.getLogger(SessionServiceRequestHandler.class); + + private static final String QUERY_OPERATOR_ALL = "$all"; + private static final String QUERY_OPERATOR_SIZE = "$size"; + private static final String QUERY_OPERATOR_AND = "$and"; + + @Value("${session.service.url:}") + private String sessionServiceURL; + + @Value("${session.service.user:}") + private String sessionServiceUser; + + @Value("${session.service.password:}") + private String sessionServicePassword; + + private Boolean isBasicAuthEnabled() { + return isSessionServiceEnabled() + && sessionServicePassword != null + && !sessionServicePassword.equals(""); + } + + public Boolean isSessionServiceEnabled() { + return !StringUtils.isEmpty(sessionServiceURL); + } + + public HttpHeaders getHttpHeaders() { + + return new HttpHeaders() { + { + if (isBasicAuthEnabled()) { + String auth = sessionServiceUser + ":" + sessionServicePassword; + byte[] encodedAuth = Base64.encodeBase64(auth.getBytes(Charset.forName("US-ASCII"))); + String authHeader = "Basic " + new String(encodedAuth); + set("Authorization", authHeader); + } + set("Content-Type", "application/json"); + } + }; + } + + public String getSessionDataJson(SessionType type, String id) throws Exception { + + RestTemplate restTemplate = new RestTemplate(); + + String url = + UriComponentsBuilder.fromUriString(sessionServiceURL) + .pathSegment(type.name()) + .pathSegment(id) + .build() + .toUriString(); + + // add basic authentication in header + HttpEntity headers = new HttpEntity<>(getHttpHeaders()); + ResponseEntity responseEntity = + restTemplate.exchange(url, HttpMethod.GET, headers, String.class); + + return responseEntity.getBody(); + } + + /** + * Gets virtual study by id + * + * @param id - id of the virtual study to read + * @return virtual study + */ + public VirtualStudy getVirtualStudyById(String id) { + + String url = + UriComponentsBuilder.fromUriString(sessionServiceURL) + .pathSegment("virtual_study") + .pathSegment(id) + .build() + .toUriString(); + + ResponseEntity responseEntity = + new RestTemplate() + .exchange(url, HttpMethod.GET, new HttpEntity<>(getHttpHeaders()), VirtualStudy.class); + HttpStatusCode statusCode = responseEntity.getStatusCode(); + VirtualStudy virtualStudy = responseEntity.getBody(); + if (!statusCode.is2xxSuccessful() || virtualStudy == null) { + LOG.error( + "The downstream server replied with statusCode={} and body={}." + + " Replying with the same status code to the client.", + statusCode, + virtualStudy); + throw new IllegalStateException("The downstream server response is not successful"); + } + return responseEntity.getBody(); + } + + /** + * Get list of virtual studies accessible to user + * + * @param username - user for whom get list of virtual studies + * @return - list of virtual studies + */ + public List getVirtualStudiesAccessibleToUser(String username) { + BasicDBObject basicDBObject = new BasicDBObject(); + basicDBObject.put( + "data.users", Pattern.compile(Pattern.quote(username), Pattern.CASE_INSENSITIVE)); + + String url = + UriComponentsBuilder.fromUriString(sessionServiceURL) + .pathSegment("virtual_study") + .pathSegment("query") + .pathSegment("fetch") + .build() + .toUriString(); + + ResponseEntity> responseEntity = + new RestTemplate() + .exchange( + url, + HttpMethod.POST, + new HttpEntity<>(basicDBObject.toString(), getHttpHeaders()), + new ParameterizedTypeReference<>() {}); + + return responseEntity.getBody(); + } + + /** + * Creates a virtual study out of virtual study definition (aka virtualStudyData) + * + * @param virtualStudyData - definition of virtual study + * @return virtual study object with id and the virtualStudyData + */ + public VirtualStudy createVirtualStudy(VirtualStudyData virtualStudyData) { + + String url = + UriComponentsBuilder.fromUriString(sessionServiceURL) + .pathSegment("virtual_study") + .build() + .toUriString(); + + ResponseEntity responseEntity = + new RestTemplate() + .exchange( + url, + HttpMethod.POST, + new HttpEntity<>(virtualStudyData, getHttpHeaders()), + new ParameterizedTypeReference<>() {}); + + return responseEntity.getBody(); + } + + /** + * Soft delete of the virtual study by de-associating all assigned users. + * + * @param id - id of virtual study to soft delete + */ + public void softRemoveVirtualStudy(String id) { + VirtualStudy virtualStudy = getVirtualStudyById(id); + VirtualStudyData data = virtualStudy.getData(); + data.setUsers(Collections.emptySet()); + updateVirtualStudy(virtualStudy); + } + + /** + * Updates virtual study + * + * @param virtualStudy - virtual study to update + */ + public void updateVirtualStudy(VirtualStudy virtualStudy) { + + String url = + UriComponentsBuilder.fromUriString(sessionServiceURL) + .pathSegment("virtual_study") + .pathSegment(virtualStudy.getId()) + .build() + .toUriString(); + + new RestTemplate().put(url, new HttpEntity<>(virtualStudy.getData(), getHttpHeaders())); + } + + private List getPageSettingsForUser( + String username, Set origin, String sessionPageName) { + + List basicDBObjects = new ArrayList<>(); + basicDBObjects.add( + new BasicDBObject( + "data.owner", Pattern.compile(Pattern.quote(username), Pattern.CASE_INSENSITIVE))); + basicDBObjects.add( + new BasicDBObject("data.origin", new BasicDBObject(QUERY_OPERATOR_ALL, origin))); + basicDBObjects.add( + new BasicDBObject("data.origin", new BasicDBObject(QUERY_OPERATOR_SIZE, origin.size()))); + basicDBObjects.add(new BasicDBObject("data.page", sessionPageName)); + + BasicDBObject queryDBObject = new BasicDBObject(QUERY_OPERATOR_AND, basicDBObjects); + + String url = + UriComponentsBuilder.fromUriString(sessionServiceURL) + .pathSegment(Session.SessionType.settings.name()) + .pathSegment("query") + .pathSegment("fetch") + .build() + .toUriString(); + + ResponseEntity> responseEntity = + new RestTemplate() + .exchange( + url, + HttpMethod.POST, + new HttpEntity(queryDBObject.toString(), getHttpHeaders()), + new ParameterizedTypeReference>() {}); + + return responseEntity.getBody(); + } + + public List getVirtualStudiesForUser(String username, List studyIds) { + // ignore origin studies order + // add $size to make sure origin studies is not a subset + List basicDBObjects = new ArrayList<>(); + basicDBObjects.add( + new BasicDBObject( + "data.users", Pattern.compile(Pattern.quote(username), Pattern.CASE_INSENSITIVE))); + basicDBObjects.add( + new BasicDBObject("data.origin", new BasicDBObject(QUERY_OPERATOR_ALL, studyIds))); + basicDBObjects.add( + new BasicDBObject("data.origin", new BasicDBObject(QUERY_OPERATOR_SIZE, studyIds.size()))); + + BasicDBObject queryDBObject = new BasicDBObject(QUERY_OPERATOR_AND, basicDBObjects); + + RestTemplate restTemplate = new RestTemplate(); + + HttpEntity httpEntity = new HttpEntity<>(queryDBObject.toString(), getHttpHeaders()); + + String url = + UriComponentsBuilder.fromUriString(sessionServiceURL) + .pathSegment(Session.SessionType.group.name()) + .pathSegment("query") + .pathSegment("fetch") + .build() + .toUriString(); + + ResponseEntity> responseEntity = + restTemplate.exchange( + url, + HttpMethod.POST, + httpEntity, + new ParameterizedTypeReference>() {}); + + return responseEntity.getBody(); + } + + public List getCustomGeneListsForUser(String username) { + BasicDBObject basicDBObject = new BasicDBObject(); + basicDBObject.put( + "data.users", Pattern.compile(Pattern.quote(username), Pattern.CASE_INSENSITIVE)); + + RestTemplate restTemplate = new RestTemplate(); + + HttpEntity httpEntity = new HttpEntity<>(basicDBObject.toString(), getHttpHeaders()); + + String url = + UriComponentsBuilder.fromUriString(sessionServiceURL) + .pathSegment(Session.SessionType.custom_gene_list.name()) + .pathSegment("query") + .pathSegment("fetch") + .build() + .toUriString(); + + ResponseEntity> responseEntity = + restTemplate.exchange( + url, + HttpMethod.POST, + httpEntity, + new ParameterizedTypeReference>() {}); + + return responseEntity.getBody(); + } + + public List getCustomDataSessionForUser( + String username, List studyIds) { + List basicDBObjects = new ArrayList<>(); + basicDBObjects.add( + new BasicDBObject( + "data.users", Pattern.compile(Pattern.quote(username), Pattern.CASE_INSENSITIVE))); + basicDBObjects.add( + new BasicDBObject("data.origin", new BasicDBObject(QUERY_OPERATOR_ALL, studyIds))); + basicDBObjects.add( + new BasicDBObject("data.origin", new BasicDBObject(QUERY_OPERATOR_SIZE, studyIds.size()))); + + BasicDBObject queryDBObject = new BasicDBObject(QUERY_OPERATOR_AND, basicDBObjects); + + RestTemplate restTemplate = new RestTemplate(); + + HttpEntity httpEntity = new HttpEntity<>(queryDBObject.toString(), getHttpHeaders()); + + String url = + UriComponentsBuilder.fromUriString(sessionServiceURL) + .pathSegment(Session.SessionType.custom_data.name()) + .pathSegment("query") + .pathSegment("fetch") + .build() + .toUriString(); + + ResponseEntity> responseEntity = + restTemplate.exchange( + url, + HttpMethod.POST, + httpEntity, + new ParameterizedTypeReference>() {}); + + return responseEntity.getBody(); + } + + public ResponseEntity createSession( + SessionType type, T payload) { + RestTemplate restTemplate = new RestTemplate(); + HttpEntity httpEntity = new HttpEntity<>(payload, getHttpHeaders()); + + String url = + UriComponentsBuilder.fromUriString(sessionServiceURL) + .pathSegment(type.name()) + .build() + .toUriString(); + + ResponseEntity responseEntity = + restTemplate.exchange(url, HttpMethod.POST, httpEntity, Session.class); + + return new ResponseEntity<>(responseEntity.getBody(), responseEntity.getStatusCode()); + } + + public void updateUsers(SessionType type, String id, T payload) { + RestTemplate restTemplate = new RestTemplate(); + HttpEntity httpEntity = new HttpEntity<>(payload, getHttpHeaders()); + + String url = + UriComponentsBuilder.fromUriString(sessionServiceURL) + .pathSegment(type.name()) + .pathSegment(id) + .build() + .toUriString(); + + restTemplate.put(url, httpEntity); + } + + public void updatePageSettings(SessionType type, String id, PageSettingsData body) { + RestTemplate restTemplate = new RestTemplate(); + HttpEntity httpEntity = new HttpEntity<>(body, getHttpHeaders()); + + String url = + UriComponentsBuilder.fromUriString(sessionServiceURL) + .pathSegment(type.name()) + .pathSegment(id) + .build() + .toUriString(); + + restTemplate.put(url, httpEntity); + } + + public PageSettings getRecentlyUpdatePageSettings( + String username, Set origin, String sessionPageName) { + List sessions = getPageSettingsForUser(username, origin, sessionPageName); + // sort last updated in descending order + sessions.sort( + (PageSettings s1, PageSettings s2) -> + s1.getData().getLastUpdated() > s2.getData().getLastUpdated() ? -1 : 1); + + return sessions.isEmpty() ? null : sessions.get(0); + } +} diff --git a/src/main/java/org/cbioportal/legacy/service/util/StudyViewColumnarServiceUtil.java b/src/main/java/org/cbioportal/legacy/service/util/StudyViewColumnarServiceUtil.java new file mode 100644 index 00000000000..d8106ba8adb --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/service/util/StudyViewColumnarServiceUtil.java @@ -0,0 +1,203 @@ +package org.cbioportal.legacy.service.util; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; +import org.cbioportal.legacy.model.CaseListDataCount; +import org.cbioportal.legacy.model.ClinicalAttribute; +import org.cbioportal.legacy.model.ClinicalDataCount; +import org.cbioportal.legacy.model.ClinicalDataCountItem; +import org.cbioportal.legacy.model.GenomicDataCount; +import org.cbioportal.legacy.model.GenomicDataCountItem; +import org.cbioportal.legacy.web.parameter.GenomicDataFilter; + +public class StudyViewColumnarServiceUtil { + + private StudyViewColumnarServiceUtil() {} + + public static final String MUTATED_COUNT = "mutatedCount"; + public static final String NOT_MUTATED_COUNT = "notMutatedCount"; + public static final String NOT_PROFILED_COUNT = "notProfiledCount"; + + public static List mergeClinicalDataCounts( + List items) { + items.forEach( + attr -> { + Map> countsPerType = + attr.getCounts().stream().collect(Collectors.groupingBy(ClinicalDataCount::getValue)); + List res = + countsPerType.entrySet().stream() + .map( + entry -> { + ClinicalDataCount mergedCount = new ClinicalDataCount(); + mergedCount.setAttributeId(attr.getAttributeId()); + mergedCount.setValue(entry.getKey()); + mergedCount.setCount( + entry.getValue().stream().mapToInt(ClinicalDataCount::getCount).sum()); + return mergedCount; + }) + .toList(); + attr.setCounts(res); + }); + return items; + } + + public static List addClinicalDataCountsForMissingAttributes( + List counts, + List attributes, + Integer filteredSampleCount, + Integer filteredPatientCount) { + Map map = + counts.stream() + .collect(Collectors.toMap(ClinicalDataCountItem::getAttributeId, item -> item)); + + List result = new ArrayList<>(counts); + + attributes.forEach( + attr -> { + Integer count = + attr.getPatientAttribute().booleanValue() + ? filteredPatientCount + : filteredSampleCount; + + if (!map.containsKey(attr.getAttrId())) { + ClinicalDataCountItem newItem = new ClinicalDataCountItem(); + newItem.setAttributeId(attr.getAttrId()); + ClinicalDataCount countObj = new ClinicalDataCount(); + countObj.setCount(count); + countObj.setValue("NA"); + countObj.setAttributeId(attr.getAttrId()); + newItem.setCounts(List.of(countObj)); + result.add(newItem); + } + }); + + return result; + } + + public static List mergeGenomicDataCounts(List sampleCounts) { + Map> countsPerType = + sampleCounts.stream().collect(Collectors.groupingBy(GenomicDataCount::getValue)); + + List mergedCounts = new ArrayList<>(); + for (Map.Entry> entry : countsPerType.entrySet()) { + var dc = new GenomicDataCount(); + dc.setValue(entry.getKey()); + dc.setLabel(entry.getValue().get(0).getLabel()); + Integer sum = + entry.getValue().stream() + .map(GenomicDataCount::getCount) + .collect(Collectors.summingInt(Integer::intValue)); + dc.setCount(sum); + mergedCounts.add(dc); + } + return mergedCounts; + } + + public static List mergeCaseListCounts(List counts) { + Map> countsPerListType = + counts.stream().collect((Collectors.groupingBy(CaseListDataCount::getValue))); + + // different cancer studies combined into one cohort will have separate case lists + // of a given type (e.g. rppa). We need to merge the counts for these + // different lists based on the type and choose a label + // this code just picks the first label, which assumes that the labels will match for a give + // type + List mergedCounts = new ArrayList<>(); + for (Map.Entry> entry : countsPerListType.entrySet()) { + var dc = new CaseListDataCount(); + dc.setValue(entry.getKey()); + // here just snatch the label of the first profile + dc.setLabel(entry.getValue().get(0).getLabel()); + Integer sum = + entry.getValue().stream() + .map(x -> x.getCount()) + .collect(Collectors.summingInt(Integer::intValue)); + dc.setCount(sum); + mergedCounts.add(dc); + } + return mergedCounts; + } + + /** + * Normalizes data counts by merging attribute values in a case-insensitive way. For example + * attribute values "TRUE", "True", and 'true' will be merged into a single aggregated count. This + * method assumes that all the counts in the given dataCounts list has the same attributeId. + * + * @param dataCounts list of data counts for a single attribute + * @return normalized list of data counts + */ + public static List normalizeDataCounts(List dataCounts) { + Collection normalizedDataCounts = + dataCounts.stream() + .collect( + Collectors.groupingBy( + c -> c.getValue().toLowerCase(), + Collectors.reducing( + new ClinicalDataCount(), + (count1, count2) -> { + // assuming attribute ids are the same for all data counts, just pick the + // first one + String attributeId = + count1.getAttributeId() != null + ? count1.getAttributeId() + : count2.getAttributeId(); + + // pick the value in a deterministic way by prioritizing lower case over + // upper case. + // for example, 'True' will be picked in case of 2 different values like + // 'TRUE', and 'True', + // and 'true' will be picked in case of 3 different values like 'TRUE', + // 'True', and 'true' + String value = + count1.getValue() != null ? count1.getValue() : count2.getValue(); + if (count1.getValue() != null && count2.getValue() != null) { + value = + count1.getValue().compareTo(count2.getValue()) > 0 + ? count1.getValue() + : count2.getValue(); + } + + // aggregate counts for the merged values + Integer count = + (count1.getCount() != null ? count1.getCount() : 0) + + (count2.getCount() != null ? count2.getCount() : 0); + + ClinicalDataCount aggregated = new ClinicalDataCount(); + aggregated.setAttributeId(attributeId); + aggregated.setValue(value); + aggregated.setCount(count); + return aggregated; + }))) + .values(); + + return new ArrayList<>(normalizedDataCounts); + } + + public static GenomicDataCountItem createGenomicDataCountItemFromMutationCounts( + GenomicDataFilter genomicDataFilter, Map counts) { + List genomicDataCountList = new ArrayList<>(); + if (counts.getOrDefault(MUTATED_COUNT, 0) > 0) + genomicDataCountList.add( + new GenomicDataCount( + "Mutated", "MUTATED", counts.get(MUTATED_COUNT), counts.get(MUTATED_COUNT))); + if (counts.getOrDefault(NOT_MUTATED_COUNT, 0) > 0) + genomicDataCountList.add( + new GenomicDataCount( + "Not Mutated", + "NOT_MUTATED", + counts.get(NOT_MUTATED_COUNT), + counts.get(NOT_MUTATED_COUNT))); + if (counts.getOrDefault(NOT_PROFILED_COUNT, 0) > 0) + genomicDataCountList.add( + new GenomicDataCount( + "Not Profiled", + "NOT_PROFILED", + counts.get(NOT_PROFILED_COUNT), + counts.get(NOT_PROFILED_COUNT))); + return new GenomicDataCountItem( + genomicDataFilter.getHugoGeneSymbol(), "mutations", genomicDataCountList); + } +} diff --git a/src/main/java/org/cbioportal/legacy/url_shortener/URLShortenerController.java b/src/main/java/org/cbioportal/legacy/url_shortener/URLShortenerController.java new file mode 100644 index 00000000000..92b0ae4434e --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/url_shortener/URLShortenerController.java @@ -0,0 +1,43 @@ +package org.cbioportal.legacy.url_shortener; + +import fr.plaisance.bitly.Bit; +import fr.plaisance.bitly.Bitly; +import org.apache.commons.validator.routines.UrlValidator; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +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.bind.annotation.RestController; + +// TODO Consider creating separate DispatcherServlets as in the original web.xml +// See: https://stackoverflow.com/a/30686733/11651683 +@RestController +public class URLShortenerController { + + @Value("${bitly.access.token}") + private String bitlyAccessToken; + + private Bitly bitly; + private UrlValidator urlValidator = new UrlValidator(); + + @RequestMapping( + path = "/api/url-shortener", + method = RequestMethod.GET, + produces = MediaType.APPLICATION_JSON_VALUE) + public ResponseEntity urlShortener(@RequestParam String url) { + + if (urlValidator.isValid(url)) { + if (bitly == null) { + bitly = Bit.ly(bitlyAccessToken); + } + return new ResponseEntity<>( + new URLShortenerResponse(bitly.shorten(url), null), HttpStatus.OK); + } else { + return new ResponseEntity<>( + new URLShortenerResponse(null, "Invalid URL"), HttpStatus.BAD_REQUEST); + } + } +} diff --git a/src/main/java/org/cbioportal/legacy/url_shortener/URLShortenerResponse.java b/src/main/java/org/cbioportal/legacy/url_shortener/URLShortenerResponse.java new file mode 100644 index 00000000000..e08994f87f0 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/url_shortener/URLShortenerResponse.java @@ -0,0 +1,28 @@ +package org.cbioportal.legacy.url_shortener; + +public class URLShortenerResponse { + + private String shortURL; + private String error; + + public URLShortenerResponse(String shortURL, String error) { + this.shortURL = shortURL; + this.error = error; + } + + public String getShortURL() { + return shortURL; + } + + public void setShortURL(String shortURL) { + this.shortURL = shortURL; + } + + public String getError() { + return error; + } + + public void setError(String error) { + this.error = error; + } +} diff --git a/src/main/java/org/cbioportal/legacy/utils/Encoder.java b/src/main/java/org/cbioportal/legacy/utils/Encoder.java new file mode 100644 index 00000000000..7334cb8b8e1 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/utils/Encoder.java @@ -0,0 +1,21 @@ +package org.cbioportal.legacy.utils; + +import java.util.Base64; + +public class Encoder { + + private Encoder() {} + + private static final Base64.Encoder BASE64_ENCODER = Base64.getEncoder().withoutPadding(); + private static final Base64.Decoder BASE64_DECODER = Base64.getDecoder(); + + public static final String DELIMITER = ":"; + + public static String calculateBase64(String firstInput, String secondInput) { + return BASE64_ENCODER.encodeToString((firstInput + DELIMITER + secondInput).getBytes()); + } + + public static String decodeBase64(String input) { + return new String(BASE64_DECODER.decode(input)); + } +} diff --git a/src/main/java/org/cbioportal/legacy/utils/config/PropertyCondition.java b/src/main/java/org/cbioportal/legacy/utils/config/PropertyCondition.java new file mode 100644 index 00000000000..d71498f00ea --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/utils/config/PropertyCondition.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2020 The Hyve B.V. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS + * FOR A PARTICULAR PURPOSE. The software and documentation provided hereunder + * is on an "as is" basis, and Memorial Sloan-Kettering Cancer Center has no + * obligations to provide maintenance, support, updates, enhancements or + * modifications. In no event shall Memorial Sloan-Kettering Cancer Center be + * liable to any party for direct, indirect, special, incidental or + * consequential damages, including lost profits, arising out of the use of this + * software and its documentation, even if Memorial Sloan-Kettering Cancer + * Center has been advised of the possibility of such damage. + */ + +/* + * This file is part of cBioPortal. + * + * cBioPortal is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +package org.cbioportal.legacy.utils.config; + +import java.util.Map; +import java.util.stream.Stream; +import org.cbioportal.legacy.utils.config.annotation.ConditionalOnProperty; +import org.springframework.context.annotation.Condition; +import org.springframework.context.annotation.ConditionContext; +import org.springframework.context.annotation.PropertySource; +import org.springframework.context.annotation.PropertySources; +import org.springframework.core.type.AnnotatedTypeMetadata; + +@PropertySources({ + @PropertySource(value = "classpath:application.properties", ignoreResourceNotFound = true), + @PropertySource( + value = "file:///${PORTAL_HOME}/application.properties", + ignoreResourceNotFound = true) +}) +// Adapted from Spring Boot +public class PropertyCondition implements Condition { + + public PropertyCondition() { + super(); + } + + @Override + public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { + Map attributes = + metadata.getAnnotationAttributes(ConditionalOnProperty.class.getName()); + String name = (String) attributes.get("name"); + Object requiredValue = attributes.get("havingValue"); + boolean matchIfMissing = (boolean) attributes.get("matchIfMissing"); + boolean isNot = (boolean) attributes.get("isNot"); + String actualValue = context.getEnvironment().getProperty(name); + if (actualValue == null) return matchIfMissing; + if (requiredValue instanceof String[]) { + if (isNot) + return Stream.of((String[]) requiredValue) + .noneMatch(value -> value.equalsIgnoreCase(actualValue)); + return Stream.of((String[]) requiredValue) + .anyMatch(value -> value.equalsIgnoreCase(actualValue)); + } + return isNot + ? !((String) requiredValue).equalsIgnoreCase(actualValue) + : ((String) requiredValue).equalsIgnoreCase(actualValue); + } +} diff --git a/src/main/java/org/cbioportal/legacy/utils/config/annotation/ConditionalOnProperty.java b/src/main/java/org/cbioportal/legacy/utils/config/annotation/ConditionalOnProperty.java new file mode 100644 index 00000000000..df6a5ece461 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/utils/config/annotation/ConditionalOnProperty.java @@ -0,0 +1,53 @@ +package org.cbioportal.legacy.utils.config.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import org.cbioportal.legacy.utils.config.PropertyCondition; +import org.springframework.context.annotation.Conditional; + +/* +Examples: + +Only instantiate when property my_prop has value correct_value: +- @ConditionalOnProperty(name = "my_prop", havingValue = "correct_value") + +Only instantiate when property my_prop does not have value correct_value: +- @ConditionalOnProperty(name = "my_prop", havingValue = "correct_value", isNot = true) + +Only instantiate when property my_prop has value correct_value_1 or correct_value_2: +- @ConditionalOnProperty(name = "my_prop", havingValue = { "correct_value_1", "correct_value_2"} ) + +Only instantiate when property my_prop does not have value correct_value_1 and not value correct_value_2: +- @ConditionalOnProperty(name = "my_prop", havingValue = { "correct_value_1", "correct_value_2"}, isNot = true) + +Instantiate by default (when property is not defined in portal properties: +- @ConditionalOnProperty(name = "not_existing_prop", havingValue = "correct_value", matchIfMissing = true) +*/ + +@Target({ElementType.TYPE, ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +@Conditional(value = PropertyCondition.class) +public @interface ConditionalOnProperty { + /** Name string. Name of the application property. */ + String name() default ""; + + /** + * havingValue string [ ]. Value or values compared with application property (can be string or + * string[]). + */ + String[] havingValue() default {}; + + /** + * isNot boolean. When true a bean will be created when the application property is not equal to + * any of the values passed by havingValues. + */ + boolean isNot() default false; + + /** + * matchIfMissing boolean. Default behavior when application property is not defined. Default is + * false, which means the bean is not created when property is undefined. + */ + boolean matchIfMissing() default false; +} diff --git a/src/main/java/org/cbioportal/legacy/utils/removeme/Session.java b/src/main/java/org/cbioportal/legacy/utils/removeme/Session.java new file mode 100644 index 00000000000..da6fb71e0fa --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/utils/removeme/Session.java @@ -0,0 +1,87 @@ +package org.cbioportal.legacy.utils.removeme; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonView; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Size; +import org.bson.Document; +import org.springframework.data.annotation.Id; +import org.springframework.util.DigestUtils; + +// TODO this class was taken from session service. The session service dependency had to be dropped +// since it forced cbioportal into autoconfiguration of mongoDB connections. +// When session service is updated reinstate the correct session service dependency. + +@JsonInclude(JsonInclude.Include.NON_NULL) +public class Session { + + public enum SessionType { + main_session, + virtual_study, + group, + comparison_session, + settings, + custom_data, + genomic_chart, + custom_gene_list + } + + @Id private String id; + @NotNull private String checksum; + @NotNull private Object data; + + @NotNull + @Size(min = 3, message = "source has a minimum length of 3") + private String source; + + @NotNull private SessionType type; + + @JsonView(Session.Views.IdOnly.class) + public String getId() { + return id; + } + + public String getChecksum() { + return checksum; + } + + public void setData(Object data) { + if (data instanceof String) { + this.data = Document.parse((String) data); + } else { + this.data = data; + } + this.checksum = DigestUtils.md5DigestAsHex(this.data.toString().getBytes()); + } + + @JsonView(Session.Views.Full.class) + public Object getData() { + return data; + } + + public void setType(SessionType type) { + this.type = type; + } + + @JsonView(Session.Views.Full.class) + public SessionType getType() { + return type; + } + + public void setSource(String source) { + this.source = source; + } + + @JsonView(Session.Views.Full.class) + public String getSource() { + return source; + } + + public static final class Views { + // show only id + public interface IdOnly {} + + // show all data + public interface Full extends Session.Views.IdOnly {} + } +} diff --git a/src/main/java/org/cbioportal/legacy/utils/security/AccessLevel.java b/src/main/java/org/cbioportal/legacy/utils/security/AccessLevel.java new file mode 100644 index 00000000000..2d936b5b2b2 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/utils/security/AccessLevel.java @@ -0,0 +1,6 @@ +package org.cbioportal.legacy.utils.security; + +public enum AccessLevel { + READ, + LIST +} diff --git a/src/main/java/org/cbioportal/legacy/utils/security/PortalSecurityConfig.java b/src/main/java/org/cbioportal/legacy/utils/security/PortalSecurityConfig.java new file mode 100644 index 00000000000..99b48d480b7 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/utils/security/PortalSecurityConfig.java @@ -0,0 +1,10 @@ +package org.cbioportal.legacy.utils.security; + +public class PortalSecurityConfig { + + // This method is the equivalent of GlobalProperties.usersMustAuthenticate() + // method in the org.mskcc.cbio.portal.util package. Update both when changes are needed. + public static boolean userAuthorizationEnabled(String authenticate) { + return authenticate != null && !authenticate.equals("false"); + } +} diff --git a/src/main/java/org/cbioportal/legacy/utils/validation/AllowedValues.java b/src/main/java/org/cbioportal/legacy/utils/validation/AllowedValues.java new file mode 100644 index 00000000000..eb70748255e --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/utils/validation/AllowedValues.java @@ -0,0 +1,28 @@ +package org.cbioportal.legacy.utils.validation; + +import jakarta.validation.Constraint; +import jakarta.validation.Payload; +import jakarta.validation.ReportAsSingleViolation; +import jakarta.validation.constraints.NotNull; +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Documented +@Constraint(validatedBy = AllowedValuesValidatorImpl.class) +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.FIELD) +@NotNull(message = "Value cannot be null") +@ReportAsSingleViolation +public @interface AllowedValues { + + String[] values() default {}; + + String message() default "Value is not valid"; + + Class[] groups() default {}; + + Class[] payload() default {}; +} diff --git a/src/main/java/org/cbioportal/legacy/utils/validation/AllowedValuesValidatorImpl.java b/src/main/java/org/cbioportal/legacy/utils/validation/AllowedValuesValidatorImpl.java new file mode 100644 index 00000000000..887b3ce5687 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/utils/validation/AllowedValuesValidatorImpl.java @@ -0,0 +1,29 @@ +package org.cbioportal.legacy.utils.validation; + +import jakarta.validation.ConstraintValidator; +import jakarta.validation.ConstraintValidatorContext; +import java.util.Arrays; +import java.util.stream.Collectors; + +public class AllowedValuesValidatorImpl implements ConstraintValidator { + + String[] valueList; + + @Override + public boolean isValid(String value, ConstraintValidatorContext context) { + boolean isValid = Arrays.stream(valueList).anyMatch(allowedValue -> allowedValue.equals(value)); + if (!isValid) { + context.disableDefaultConstraintViolation(); + context + .buildConstraintViolationWithTemplate( + "Allowed values are: " + Arrays.stream(valueList).collect(Collectors.joining(", "))) + .addConstraintViolation(); + } + return isValid; + } + + @Override + public void initialize(AllowedValues constraintAnnotation) { + valueList = constraintAnnotation.values(); + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/AlterationDriverAnnotationController.java b/src/main/java/org/cbioportal/legacy/web/AlterationDriverAnnotationController.java new file mode 100644 index 00000000000..0bff92635ba --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/AlterationDriverAnnotationController.java @@ -0,0 +1,54 @@ +package org.cbioportal.legacy.web; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.tags.Tag; +import java.util.List; +import org.cbioportal.legacy.model.CustomDriverAnnotationReport; +import org.cbioportal.legacy.service.AlterationDriverAnnotationService; +import org.cbioportal.legacy.web.config.annotation.InternalApi; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RestController; + +@InternalApi +@RestController() +@RequestMapping("/api") +@Validated +@Tag(name = "Custom driver annotations", description = " ") +public class AlterationDriverAnnotationController { + + @Autowired private AlterationDriverAnnotationService alterationDriverAnnotationService; + + @PreAuthorize( + "hasPermission(#molecularProfileIds, 'Collection', T(org.cbioportal.legacy.utils.security.AccessLevel).READ)") + @RequestMapping( + value = "/custom-driver-annotation-report/fetch", + method = RequestMethod.POST, + consumes = MediaType.APPLICATION_JSON_VALUE, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(summary = "Return availability of custom driver annotations for molecular profiles") + @ApiResponse( + responseCode = "200", + description = "OK", + content = @Content(schema = @Schema(implementation = CustomDriverAnnotationReport.class))) + public ResponseEntity fetchAlterationDriverAnnotationReport( + @Parameter(required = true, description = "List of Molecular Profile Ids") @RequestBody + List molecularProfileIds) { + + CustomDriverAnnotationReport customDriverAnnotationReport = + alterationDriverAnnotationService.getCustomDriverAnnotationProps(molecularProfileIds); + + return new ResponseEntity<>(customDriverAnnotationReport, HttpStatus.OK); + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/AlterationEnrichmentController.java b/src/main/java/org/cbioportal/legacy/web/AlterationEnrichmentController.java new file mode 100644 index 00000000000..2856b601b88 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/AlterationEnrichmentController.java @@ -0,0 +1,101 @@ +package org.cbioportal.legacy.web; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.ArraySchema; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; +import org.cbioportal.legacy.model.AlterationEnrichment; +import org.cbioportal.legacy.model.AlterationFilter; +import org.cbioportal.legacy.model.EnrichmentType; +import org.cbioportal.legacy.model.MolecularProfileCaseIdentifier; +import org.cbioportal.legacy.service.AlterationEnrichmentService; +import org.cbioportal.legacy.service.exception.MolecularProfileNotFoundException; +import org.cbioportal.legacy.web.config.annotation.InternalApi; +import org.cbioportal.legacy.web.parameter.MolecularProfileCasesGroupAndAlterationTypeFilter; +import org.cbioportal.legacy.web.parameter.MolecularProfileCasesGroupFilter; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.RequestAttribute; +import org.springframework.web.bind.annotation.RequestBody; +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.bind.annotation.RestController; + +@InternalApi +@RestController() +@RequestMapping("/api") +@Validated +@Tag(name = "Alteration Enrichments", description = " ") +public class AlterationEnrichmentController { + + @Autowired private AlterationEnrichmentService alterationEnrichmentService; + + @PreAuthorize( + "hasPermission(#involvedCancerStudies, 'Collection', T(org.cbioportal.legacy.utils.security.AccessLevel).READ)") + @RequestMapping( + value = "/alteration-enrichments/fetch", + method = RequestMethod.POST, + consumes = MediaType.APPLICATION_JSON_VALUE, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(summary = "Fetch alteration enrichments in molecular profiles") + @ApiResponse( + responseCode = "200", + description = "OK", + content = + @Content( + array = @ArraySchema(schema = @Schema(implementation = AlterationEnrichment.class)))) + public ResponseEntity> fetchAlterationEnrichments( + @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface + @RequestAttribute(required = false, value = "involvedCancerStudies") + Collection involvedCancerStudies, + @Parameter(hidden = true) + // prevent reference to this attribute in the swagger-ui interface. this attribute is + // needed for the @PreAuthorize tag above. + @Valid + @RequestAttribute( + required = false, + value = "interceptedMolecularProfileCasesGroupFilters") + List interceptedMolecularProfileCasesGroupFilters, + @Parameter(hidden = true) + @Valid + @RequestAttribute(required = false, value = "alterationEventTypes") + AlterationFilter alterationEventTypes, + @Parameter(description = "Type of the enrichment e.g. SAMPLE or PATIENT") + @RequestParam(defaultValue = "SAMPLE") + EnrichmentType enrichmentType, + @Parameter( + required = true, + description = + "List of groups containing sample identifiers and list of Alteration Types") + @Valid + @RequestBody(required = false) + MolecularProfileCasesGroupAndAlterationTypeFilter groupsAndAlterationTypes) + throws MolecularProfileNotFoundException { + + Map> groupCaseIdentifierSet = + interceptedMolecularProfileCasesGroupFilters.stream() + .collect( + Collectors.toMap( + MolecularProfileCasesGroupFilter::getName, + MolecularProfileCasesGroupFilter::getMolecularProfileCaseIdentifiers)); + + List alterationEnrichments = + alterationEnrichmentService.getAlterationEnrichments( + groupCaseIdentifierSet, enrichmentType, alterationEventTypes); + + return new ResponseEntity<>(alterationEnrichments, HttpStatus.OK); + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/CacheController.java b/src/main/java/org/cbioportal/legacy/web/CacheController.java new file mode 100644 index 00000000000..46b00b7c555 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/CacheController.java @@ -0,0 +1,100 @@ +package org.cbioportal.legacy.web; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.cbioportal.legacy.service.CacheService; +import org.cbioportal.legacy.service.exception.CacheOperationException; +import org.cbioportal.legacy.web.config.annotation.InternalApi; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestHeader; +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.bind.annotation.RestController; + +@RestController +@Validated +@InternalApi +@Tag(name = "Cache") +public class CacheController { + + @Autowired private CacheService cacheService; + + @Value("${cache.endpoint.api-key:not set}") + private String requiredApiKey; + + @Value("${cache.endpoint.enabled:false}") + private boolean cacheEndpointEnabled; + + @RequestMapping( + value = "/api/cache", + method = RequestMethod.DELETE, + produces = MediaType.TEXT_PLAIN_VALUE) + @Operation(summary = "Clear and reinitialize caches") + @ApiResponse( + responseCode = "200", + description = "OK", + content = @Content(schema = @Schema(implementation = String.class))) + public ResponseEntity clearAllCaches( + @Parameter( + description = + "Secret API key passed in HTTP header. The key is configured in application.properties of the portal instance.") + @RequestHeader(value = "X-API-KEY") + String providedApiKey, + @Parameter(description = "Clear Spring-managed caches") + @RequestParam(defaultValue = "true", required = false) + final boolean springManagedCache) + throws CacheOperationException { + if (!cacheEndpointEnabled) { + return new ResponseEntity<>( + "Cache endpoint is disabled for this instance.", HttpStatus.NOT_FOUND); + } + if ("not set".equals(requiredApiKey) || !requiredApiKey.equals(providedApiKey)) { + return new ResponseEntity<>("", HttpStatus.UNAUTHORIZED); + } + cacheService.clearCaches(springManagedCache); + return new ResponseEntity<>("Flushed all caches!!!", HttpStatus.OK); + } + + @RequestMapping( + value = "/cache/{studyId}", + method = RequestMethod.DELETE, + produces = MediaType.TEXT_PLAIN_VALUE) + @Operation(summary = "Clear and reinitialize caches after import/removal/update of a study") + @ApiResponse( + responseCode = "200", + description = "OK", + content = @Content(schema = @Schema(implementation = String.class))) + public ResponseEntity clearCachesForStudy( + @Parameter( + description = + "Secret API key passed in HTTP header. The key is configured in application.properties of the portal instance.") + @RequestHeader(value = "X-API-KEY") + String providedApiKey, + @PathVariable String studyId, + @Parameter(description = "Clear Spring-managed caches") + @RequestParam(defaultValue = "true", required = false) + final boolean springManagedCache) + throws CacheOperationException { + if (!cacheEndpointEnabled) { + return new ResponseEntity<>( + "Cache endpoint is disabled for this instance.", HttpStatus.NOT_FOUND); + } + if ("not set".equals(requiredApiKey) || !requiredApiKey.equals(providedApiKey)) { + return new ResponseEntity<>("", HttpStatus.UNAUTHORIZED); + } + + cacheService.clearCachesForStudy(studyId, springManagedCache); + return new ResponseEntity<>("Flushed " + studyId + " caches!!!", HttpStatus.OK); + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/CacheStatsController.java b/src/main/java/org/cbioportal/legacy/web/CacheStatsController.java new file mode 100644 index 00000000000..184258768bf --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/CacheStatsController.java @@ -0,0 +1,80 @@ +package org.cbioportal.legacy.web; + +import io.swagger.v3.oas.annotations.Hidden; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.ArraySchema; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.tags.Tag; +import java.util.List; +import org.cbioportal.legacy.service.CacheStatisticsService; +import org.cbioportal.legacy.service.exception.CacheNotFoundException; +import org.cbioportal.legacy.utils.config.annotation.ConditionalOnProperty; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@Validated +@Tag(name = "CacheStats", description = " ") +@Hidden +@ConditionalOnProperty( + name = "persistence.cache_type", + havingValue = {"ehcache-heap", "ehcache-disk", "ehcache-hybrid", "redis"}) +public class CacheStatsController { + + @Autowired public CacheStatisticsService cacheStatisticsService; + + @RequestMapping( + value = "/api/{cache}/keysInCache", + method = RequestMethod.GET, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(description = "Get list of keys in cache") + @ApiResponse( + responseCode = "200", + description = "OK", + content = @Content(array = @ArraySchema(schema = @Schema(implementation = String.class)))) + public ResponseEntity> getKeysInCache( + @Parameter(required = true, description = "Cache name") @PathVariable String cache) + throws CacheNotFoundException { + List strings = cacheStatisticsService.getKeysInCache(cache); + return new ResponseEntity<>(strings, HttpStatus.OK); + } + + @RequestMapping( + value = "/api/{cache}/keyCountsPerClass", + method = RequestMethod.GET, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(description = "Get counts of keys per repository class") + @ApiResponse( + responseCode = "200", + description = "OK", + content = @Content(array = @ArraySchema(schema = @Schema(implementation = String.class)))) + public ResponseEntity> getKeyCountsPerClass( + @Parameter(required = true, description = "Cache name") @PathVariable String cache) + throws CacheNotFoundException { + List strings = cacheStatisticsService.getKeyCountsPerClass(cache); + return new ResponseEntity<>(strings, HttpStatus.OK); + } + + @RequestMapping( + value = "/api/cacheStatistics", + method = RequestMethod.GET, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(description = "Get general cache statistics") + @ApiResponse( + responseCode = "200", + description = "OK", + content = @Content(schema = @Schema(implementation = String.class))) + public ResponseEntity getCacheStatistics() throws CacheNotFoundException { + return new ResponseEntity<>(cacheStatisticsService.getCacheStatistics(), HttpStatus.OK); + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/CancerTypeController.java b/src/main/java/org/cbioportal/legacy/web/CancerTypeController.java new file mode 100644 index 00000000000..7c498b4aca3 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/CancerTypeController.java @@ -0,0 +1,105 @@ +package org.cbioportal.legacy.web; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.ArraySchema; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.constraints.Max; +import jakarta.validation.constraints.Min; +import java.util.List; +import org.cbioportal.legacy.model.TypeOfCancer; +import org.cbioportal.legacy.service.CancerTypeService; +import org.cbioportal.legacy.service.exception.CancerTypeNotFoundException; +import org.cbioportal.legacy.web.config.PublicApiTags; +import org.cbioportal.legacy.web.config.annotation.PublicApi; +import org.cbioportal.legacy.web.parameter.Direction; +import org.cbioportal.legacy.web.parameter.HeaderKeyConstants; +import org.cbioportal.legacy.web.parameter.PagingConstants; +import org.cbioportal.legacy.web.parameter.Projection; +import org.cbioportal.legacy.web.parameter.sort.CancerTypeSortBy; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.PathVariable; +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.bind.annotation.RestController; + +@PublicApi +@RestController +@Validated +@Tag(name = PublicApiTags.CANCER_TYPES, description = " ") +public class CancerTypeController { + + @Autowired private CancerTypeService cancerTypeService; + + @RequestMapping( + value = "/api/cancer-types", + method = RequestMethod.GET, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(description = "Get all cancer types") + @ApiResponse( + responseCode = "200", + description = "OK", + content = + @Content(array = @ArraySchema(schema = @Schema(implementation = TypeOfCancer.class)))) + public ResponseEntity> getAllCancerTypes( + @Parameter(description = "Level of detail of the response") + @RequestParam(defaultValue = "SUMMARY") + final Projection projection, + @Parameter(description = "Page size of the result list") + @Max(PagingConstants.MAX_PAGE_SIZE) + @Min(PagingConstants.MIN_PAGE_SIZE) + @RequestParam(defaultValue = PagingConstants.DEFAULT_PAGE_SIZE) + final Integer pageSize, + @Parameter(description = "Page number of the result list") + @Min(PagingConstants.MIN_PAGE_NUMBER) + @RequestParam(defaultValue = PagingConstants.DEFAULT_PAGE_NUMBER) + final Integer pageNumber, + @Parameter(description = "Name of the property that the result list is sorted by") + @RequestParam(required = false) + final CancerTypeSortBy sortBy, + @Parameter(description = "Direction of the sort") @RequestParam(defaultValue = "ASC") + final Direction direction) { + + if (projection == Projection.META) { + final HttpHeaders responseHeaders = new HttpHeaders(); + responseHeaders.add( + HeaderKeyConstants.TOTAL_COUNT, + cancerTypeService.getMetaCancerTypes().getTotalCount().toString()); + return new ResponseEntity<>(responseHeaders, HttpStatus.OK); + } else { + return new ResponseEntity<>( + cancerTypeService.getAllCancerTypes( + projection.name(), + pageSize, + pageNumber, + sortBy == null ? null : sortBy.getOriginalValue(), + direction.name()), + HttpStatus.OK); + } + } + + @RequestMapping( + value = "/api/cancer-types/{cancerTypeId}", + method = RequestMethod.GET, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(description = "Get a cancer type") + @ApiResponse( + responseCode = "200", + description = "OK", + content = @Content(schema = @Schema(implementation = String.class))) + public ResponseEntity getCancerType( + @Parameter(required = true, description = "Cancer Type ID e.g. acc") @PathVariable + final String cancerTypeId) + throws CancerTypeNotFoundException { + return new ResponseEntity<>(cancerTypeService.getCancerType(cancerTypeId), HttpStatus.OK); + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/ClinicalAttributeController.java b/src/main/java/org/cbioportal/legacy/web/ClinicalAttributeController.java new file mode 100644 index 00000000000..761fe87d240 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/ClinicalAttributeController.java @@ -0,0 +1,214 @@ +package org.cbioportal.legacy.web; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.ArraySchema; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.constraints.Max; +import jakarta.validation.constraints.Min; +import jakarta.validation.constraints.Size; +import java.util.List; +import org.cbioportal.legacy.model.ClinicalAttribute; +import org.cbioportal.legacy.service.ClinicalAttributeService; +import org.cbioportal.legacy.service.exception.ClinicalAttributeNotFoundException; +import org.cbioportal.legacy.service.exception.StudyNotFoundException; +import org.cbioportal.legacy.web.config.PublicApiTags; +import org.cbioportal.legacy.web.config.annotation.PublicApi; +import org.cbioportal.legacy.web.parameter.Direction; +import org.cbioportal.legacy.web.parameter.HeaderKeyConstants; +import org.cbioportal.legacy.web.parameter.PagingConstants; +import org.cbioportal.legacy.web.parameter.Projection; +import org.cbioportal.legacy.web.parameter.sort.ClinicalAttributeSortBy; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +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.bind.annotation.RestController; + +@PublicApi +@RestController() +@RequestMapping("/api") +@Validated +@Tag(name = PublicApiTags.CLINICAL_ATTRIBUTES, description = " ") +public class ClinicalAttributeController { + + @Autowired private ClinicalAttributeService clinicalAttributeService; + + @RequestMapping( + value = "/clinical-attributes", + method = RequestMethod.GET, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(description = "Get all clinical attributes") + @ApiResponse( + responseCode = "200", + description = "OK", + content = + @Content( + array = @ArraySchema(schema = @Schema(implementation = ClinicalAttribute.class)))) + public ResponseEntity> getAllClinicalAttributes( + @Parameter(description = "Level of detail of the response") + @RequestParam(defaultValue = "SUMMARY") + Projection projection, + @Parameter(description = "Page size of the result list") + @Max(PagingConstants.MAX_PAGE_SIZE) + @Min(PagingConstants.MIN_PAGE_SIZE) + @RequestParam(defaultValue = PagingConstants.DEFAULT_PAGE_SIZE) + Integer pageSize, + @Parameter(description = "Page number of the result list") + @Min(PagingConstants.MIN_PAGE_NUMBER) + @RequestParam(defaultValue = PagingConstants.DEFAULT_PAGE_NUMBER) + Integer pageNumber, + @Parameter(description = "Name of the property that the result list is sorted by") + @RequestParam(required = false) + ClinicalAttributeSortBy sortBy, + @Parameter(description = "Direction of the sort") @RequestParam(defaultValue = "ASC") + Direction direction) { + + if (projection == Projection.META) { + HttpHeaders responseHeaders = new HttpHeaders(); + responseHeaders.add( + HeaderKeyConstants.TOTAL_COUNT, + clinicalAttributeService.getMetaClinicalAttributes().getTotalCount().toString()); + return new ResponseEntity<>(responseHeaders, HttpStatus.OK); + } else { + return new ResponseEntity<>( + clinicalAttributeService.getAllClinicalAttributes( + projection.name(), + pageSize, + pageNumber, + sortBy == null ? null : sortBy.getOriginalValue(), + direction.name()), + HttpStatus.OK); + } + } + + @PreAuthorize( + "hasPermission(#studyId, 'CancerStudyId', T(org.cbioportal.legacy.utils.security.AccessLevel).READ)") + @RequestMapping( + value = "/studies/{studyId}/clinical-attributes", + method = RequestMethod.GET, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(description = "Get all clinical attributes in the specified study") + @ApiResponse( + responseCode = "200", + description = "OK", + content = + @Content( + array = @ArraySchema(schema = @Schema(implementation = ClinicalAttribute.class)))) + public ResponseEntity> getAllClinicalAttributesInStudy( + @Parameter(required = true, description = "Study ID e.g. acc_tcga") @PathVariable + String studyId, + @Parameter(description = "Level of detail of the response") + @RequestParam(defaultValue = "SUMMARY") + Projection projection, + @Parameter(description = "Page size of the result list") + @Max(PagingConstants.MAX_PAGE_SIZE) + @Min(PagingConstants.MIN_PAGE_SIZE) + @RequestParam(defaultValue = PagingConstants.DEFAULT_PAGE_SIZE) + Integer pageSize, + @Parameter(description = "Page number of the result list") + @Min(PagingConstants.MIN_PAGE_NUMBER) + @RequestParam(defaultValue = PagingConstants.DEFAULT_PAGE_NUMBER) + Integer pageNumber, + @Parameter(description = "Name of the property that the result list is sorted by") + @RequestParam(required = false) + ClinicalAttributeSortBy sortBy, + @Parameter(description = "Direction of the sort") @RequestParam(defaultValue = "ASC") + Direction direction) + throws StudyNotFoundException { + + if (projection == Projection.META) { + HttpHeaders responseHeaders = new HttpHeaders(); + responseHeaders.add( + HeaderKeyConstants.TOTAL_COUNT, + clinicalAttributeService + .getMetaClinicalAttributesInStudy(studyId) + .getTotalCount() + .toString()); + return new ResponseEntity<>(responseHeaders, HttpStatus.OK); + } else { + return new ResponseEntity<>( + clinicalAttributeService.getAllClinicalAttributesInStudy( + studyId, + projection.name(), + pageSize, + pageNumber, + sortBy == null ? null : sortBy.getOriginalValue(), + direction.name()), + HttpStatus.OK); + } + } + + @PreAuthorize( + "hasPermission(#studyId, 'CancerStudyId', T(org.cbioportal.legacy.utils.security.AccessLevel).READ)") + @RequestMapping( + value = "/studies/{studyId}/clinical-attributes/{clinicalAttributeId}", + method = RequestMethod.GET, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(description = "Get specified clinical attribute") + @ApiResponse( + responseCode = "200", + description = "OK", + content = @Content(schema = @Schema(implementation = ClinicalAttribute.class))) + public ResponseEntity getClinicalAttributeInStudy( + @Parameter(required = true, description = "Study ID e.g. acc_tcga") @PathVariable + String studyId, + @Parameter(required = true, description = "Clinical Attribute ID e.g. CANCER_TYPE") + @PathVariable + String clinicalAttributeId) + throws ClinicalAttributeNotFoundException, StudyNotFoundException { + + return new ResponseEntity<>( + clinicalAttributeService.getClinicalAttribute(studyId, clinicalAttributeId), HttpStatus.OK); + } + + @PreAuthorize( + "hasPermission(#studyIds, 'Collection', T(org.cbioportal.legacy.utils.security.AccessLevel).READ)") + @RequestMapping( + value = "/clinical-attributes/fetch", + method = RequestMethod.POST, + consumes = MediaType.APPLICATION_JSON_VALUE, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(description = "Fetch clinical attributes") + @ApiResponse( + responseCode = "200", + description = "OK", + content = + @Content( + array = @ArraySchema(schema = @Schema(implementation = ClinicalAttribute.class)))) + public ResponseEntity> fetchClinicalAttributes( + @Parameter(required = true, description = "List of Study IDs") + @Size(min = 1, max = PagingConstants.MAX_PAGE_SIZE) + @RequestBody + List studyIds, + @Parameter(description = "Level of detail of the response") + @RequestParam(defaultValue = "SUMMARY") + Projection projection) { + + if (projection == Projection.META) { + HttpHeaders responseHeaders = new HttpHeaders(); + responseHeaders.add( + HeaderKeyConstants.TOTAL_COUNT, + clinicalAttributeService + .fetchMetaClinicalAttributes(studyIds) + .getTotalCount() + .toString()); + return new ResponseEntity<>(responseHeaders, HttpStatus.OK); + } else { + return new ResponseEntity<>( + clinicalAttributeService.fetchClinicalAttributes(studyIds, projection.name()), + HttpStatus.OK); + } + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/ClinicalAttributeCountController.java b/src/main/java/org/cbioportal/legacy/web/ClinicalAttributeCountController.java new file mode 100644 index 00000000000..4c323617529 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/ClinicalAttributeCountController.java @@ -0,0 +1,94 @@ +package org.cbioportal.legacy.web; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.ArraySchema; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import org.cbioportal.legacy.model.ClinicalAttributeCount; +import org.cbioportal.legacy.service.ClinicalAttributeService; +import org.cbioportal.legacy.web.config.InternalApiTags; +import org.cbioportal.legacy.web.config.annotation.InternalApi; +import org.cbioportal.legacy.web.parameter.ClinicalAttributeCountFilter; +import org.cbioportal.legacy.web.parameter.SampleIdentifier; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.RequestAttribute; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RestController; + +@InternalApi +@RestController() +@RequestMapping("/api") +@Validated +@Tag(name = InternalApiTags.CLINICAL_ATTRIBUTES_COUNT, description = " ") +public class ClinicalAttributeCountController { + + @Autowired private ClinicalAttributeService clinicalAttributeService; + + @PreAuthorize( + "hasPermission(#involvedCancerStudies, 'Collection', T(org.cbioportal.legacy.utils.security.AccessLevel).READ)") + @RequestMapping( + value = "/clinical-attributes/counts/fetch", + method = RequestMethod.POST, + consumes = MediaType.APPLICATION_JSON_VALUE, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation( + description = + "Get counts for clinical attributes according to their data availability for selected samples/patients") + @ApiResponse( + responseCode = "200", + description = "OK", + content = + @Content( + array = + @ArraySchema(schema = @Schema(implementation = ClinicalAttributeCount.class)))) + public ResponseEntity> getClinicalAttributeCounts( + @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface + @RequestAttribute(required = false, value = "involvedCancerStudies") + Collection involvedCancerStudies, + @Parameter( + hidden = + true) // prevent reference to this attribute in the swagger-ui interface. this + // attribute is needed for the @PreAuthorize tag above. + @Valid + @RequestAttribute(required = false, value = "interceptedClinicalAttributeCountFilter") + ClinicalAttributeCountFilter interceptedClinicalAttributeCountFilter, + @Parameter(required = true, description = "List of SampleIdentifiers or Sample List ID") + @Valid + @RequestBody(required = false) + ClinicalAttributeCountFilter clinicalAttributeCountFilter) { + + List clinicalAttributeCountList; + if (interceptedClinicalAttributeCountFilter.getSampleListId() != null) { + clinicalAttributeCountList = + clinicalAttributeService.getClinicalAttributeCountsBySampleListId( + interceptedClinicalAttributeCountFilter.getSampleListId()); + } else { + List sampleIdentifiers = + interceptedClinicalAttributeCountFilter.getSampleIdentifiers(); + List studyIds = new ArrayList<>(); + List sampleIds = new ArrayList<>(); + for (SampleIdentifier sampleIdentifier : sampleIdentifiers) { + studyIds.add(sampleIdentifier.getStudyId()); + sampleIds.add(sampleIdentifier.getSampleId()); + } + clinicalAttributeCountList = + clinicalAttributeService.getClinicalAttributeCountsBySampleIds(studyIds, sampleIds); + } + + return new ResponseEntity<>(clinicalAttributeCountList, HttpStatus.OK); + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/ClinicalDataController.java b/src/main/java/org/cbioportal/legacy/web/ClinicalDataController.java new file mode 100644 index 00000000000..8db21ab6753 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/ClinicalDataController.java @@ -0,0 +1,366 @@ +package org.cbioportal.legacy.web; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.ArraySchema; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import jakarta.validation.constraints.Max; +import jakarta.validation.constraints.Min; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import org.cbioportal.legacy.model.ClinicalData; +import org.cbioportal.legacy.service.ClinicalDataService; +import org.cbioportal.legacy.service.exception.PatientNotFoundException; +import org.cbioportal.legacy.service.exception.SampleNotFoundException; +import org.cbioportal.legacy.service.exception.StudyNotFoundException; +import org.cbioportal.legacy.web.config.PublicApiTags; +import org.cbioportal.legacy.web.config.annotation.PublicApi; +import org.cbioportal.legacy.web.parameter.ClinicalDataIdentifier; +import org.cbioportal.legacy.web.parameter.ClinicalDataMultiStudyFilter; +import org.cbioportal.legacy.web.parameter.ClinicalDataSingleStudyFilter; +import org.cbioportal.legacy.web.parameter.ClinicalDataType; +import org.cbioportal.legacy.web.parameter.Direction; +import org.cbioportal.legacy.web.parameter.HeaderKeyConstants; +import org.cbioportal.legacy.web.parameter.PagingConstants; +import org.cbioportal.legacy.web.parameter.Projection; +import org.cbioportal.legacy.web.parameter.sort.ClinicalDataSortBy; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestAttribute; +import org.springframework.web.bind.annotation.RequestBody; +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.bind.annotation.RestController; + +@PublicApi +@RestController() +@RequestMapping("/api") +@Validated +@Tag(name = PublicApiTags.CLINICAL_DATA, description = " ") +public class ClinicalDataController { + + public static final int CLINICAL_DATA_MAX_PAGE_SIZE = 10000000; + private static final String CLINICAL_DATA_DEFAULT_PAGE_SIZE = "10000000"; + + @Autowired private ClinicalDataService clinicalDataService; + + @PreAuthorize( + "hasPermission(#studyId, 'CancerStudyId', T(org.cbioportal.legacy.utils.security.AccessLevel).READ)") + @RequestMapping( + value = "/studies/{studyId}/samples/{sampleId}/clinical-data", + method = RequestMethod.GET, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(description = "Get all clinical data of a sample in a study") + @ApiResponse( + responseCode = "200", + description = "OK", + content = + @Content(array = @ArraySchema(schema = @Schema(implementation = ClinicalData.class)))) + public ResponseEntity> getAllClinicalDataOfSampleInStudy( + @Parameter(required = true, description = "Study ID e.g. acc_tcga") @PathVariable + String studyId, + @Parameter(required = true, description = "Sample ID e.g. TCGA-OR-A5J2-01") @PathVariable + String sampleId, + @Parameter(description = "Attribute ID e.g. CANCER_TYPE") @RequestParam(required = false) + String attributeId, + @Parameter(description = "Level of detail of the response") + @RequestParam(defaultValue = "SUMMARY") + Projection projection, + @Parameter(description = "Page size of the result list") + @Max(CLINICAL_DATA_MAX_PAGE_SIZE) + @Min(PagingConstants.MIN_PAGE_SIZE) + @RequestParam(defaultValue = CLINICAL_DATA_DEFAULT_PAGE_SIZE) + Integer pageSize, + @Parameter(description = "Page number of the result list") + @Min(PagingConstants.MIN_PAGE_NUMBER) + @RequestParam(defaultValue = PagingConstants.DEFAULT_PAGE_NUMBER) + Integer pageNumber, + @Parameter(description = "Name of the property that the result list is sorted by") + @RequestParam(required = false) + ClinicalDataSortBy sortBy, + @Parameter(description = "Direction of the sort") @RequestParam(defaultValue = "ASC") + Direction direction) + throws SampleNotFoundException, StudyNotFoundException { + + if (projection == Projection.META) { + HttpHeaders responseHeaders = new HttpHeaders(); + responseHeaders.add( + HeaderKeyConstants.TOTAL_COUNT, + clinicalDataService + .getMetaSampleClinicalData(studyId, sampleId, attributeId) + .getTotalCount() + .toString()); + return new ResponseEntity<>(responseHeaders, HttpStatus.OK); + } else { + return new ResponseEntity<>( + clinicalDataService.getAllClinicalDataOfSampleInStudy( + studyId, + sampleId, + attributeId, + projection.name(), + pageSize, + pageNumber, + sortBy == null ? null : sortBy.getOriginalValue(), + direction.name()), + HttpStatus.OK); + } + } + + @PreAuthorize( + "hasPermission(#studyId, 'CancerStudyId', T(org.cbioportal.legacy.utils.security.AccessLevel).READ)") + @RequestMapping( + value = "/studies/{studyId}/patients/{patientId}/clinical-data", + method = RequestMethod.GET, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(description = "Get all clinical data of a patient in a study") + @ApiResponse( + responseCode = "200", + description = "OK", + content = + @Content(array = @ArraySchema(schema = @Schema(implementation = ClinicalData.class)))) + public ResponseEntity> getAllClinicalDataOfPatientInStudy( + @Parameter(required = true, description = "Study ID e.g. acc_tcga") @PathVariable + String studyId, + @Parameter(required = true, description = "Patient ID e.g. TCGA-OR-A5J2") @PathVariable + String patientId, + @Parameter(description = "Attribute ID e.g. AGE") @RequestParam(required = false) + String attributeId, + @Parameter(description = "Level of detail of the response") + @RequestParam(defaultValue = "SUMMARY") + Projection projection, + @Parameter(description = "Page size of the result list") + @Max(CLINICAL_DATA_MAX_PAGE_SIZE) + @Min(PagingConstants.MIN_PAGE_SIZE) + @RequestParam(defaultValue = CLINICAL_DATA_DEFAULT_PAGE_SIZE) + Integer pageSize, + @Parameter(description = "Page number of the result list") + @Min(PagingConstants.MIN_PAGE_NUMBER) + @RequestParam(defaultValue = PagingConstants.DEFAULT_PAGE_NUMBER) + Integer pageNumber, + @Parameter(description = "Name of the property that the result list is sorted by") + @RequestParam(required = false) + ClinicalDataSortBy sortBy, + @Parameter(description = "Direction of the sort") @RequestParam(defaultValue = "ASC") + Direction direction) + throws PatientNotFoundException, StudyNotFoundException { + + if (projection == Projection.META) { + HttpHeaders responseHeaders = new HttpHeaders(); + responseHeaders.add( + HeaderKeyConstants.TOTAL_COUNT, + clinicalDataService + .getMetaPatientClinicalData(studyId, patientId, attributeId) + .getTotalCount() + .toString()); + return new ResponseEntity<>(responseHeaders, HttpStatus.OK); + } else { + return new ResponseEntity<>( + clinicalDataService.getAllClinicalDataOfPatientInStudy( + studyId, + patientId, + attributeId, + projection.name(), + pageSize, + pageNumber, + sortBy == null ? null : sortBy.getOriginalValue(), + direction.name()), + HttpStatus.OK); + } + } + + @PreAuthorize( + "hasPermission(#studyId, 'CancerStudyId', T(org.cbioportal.legacy.utils.security.AccessLevel).READ)") + @RequestMapping( + value = "/studies/{studyId}/clinical-data", + method = RequestMethod.GET, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(description = "Get all clinical data in a study") + @ApiResponse( + responseCode = "200", + description = "OK", + content = + @Content(array = @ArraySchema(schema = @Schema(implementation = ClinicalData.class)))) + public ResponseEntity> getAllClinicalDataInStudy( + @Parameter(required = true, description = "Study ID e.g. acc_tcga") @PathVariable + String studyId, + @Parameter(description = "Attribute ID e.g. CANCER_TYPE") @RequestParam(required = false) + String attributeId, + @Parameter(description = "Type of the clinical data") @RequestParam(defaultValue = "SAMPLE") + ClinicalDataType clinicalDataType, + @Parameter(description = "Level of detail of the response") + @RequestParam(defaultValue = "SUMMARY") + Projection projection, + @Parameter(description = "Page size of the result list") + @Max(CLINICAL_DATA_MAX_PAGE_SIZE) + @Min(PagingConstants.MIN_PAGE_SIZE) + @RequestParam(defaultValue = CLINICAL_DATA_DEFAULT_PAGE_SIZE) + Integer pageSize, + @Parameter(description = "Page number of the result list") + @Min(PagingConstants.MIN_PAGE_NUMBER) + @RequestParam(defaultValue = PagingConstants.DEFAULT_PAGE_NUMBER) + Integer pageNumber, + @Parameter(description = "Name of the property that the result list is sorted by") + @RequestParam(required = false) + ClinicalDataSortBy sortBy, + @Parameter(description = "Direction of the sort") @RequestParam(defaultValue = "ASC") + Direction direction) + throws StudyNotFoundException { + + if (projection == Projection.META) { + HttpHeaders responseHeaders = new HttpHeaders(); + responseHeaders.add( + HeaderKeyConstants.TOTAL_COUNT, + clinicalDataService + .getMetaAllClinicalData(studyId, attributeId, clinicalDataType.name()) + .getTotalCount() + .toString()); + return new ResponseEntity<>(responseHeaders, HttpStatus.OK); + } else { + return new ResponseEntity<>( + clinicalDataService.getAllClinicalDataInStudy( + studyId, + attributeId, + clinicalDataType.name(), + projection.name(), + pageSize, + pageNumber, + sortBy == null ? null : sortBy.getOriginalValue(), + direction.name()), + HttpStatus.OK); + } + } + + @PreAuthorize( + "hasPermission(#studyId, 'CancerStudyId', T(org.cbioportal.legacy.utils.security.AccessLevel).READ)") + @RequestMapping( + value = "/studies/{studyId}/clinical-data/fetch", + method = RequestMethod.POST, + consumes = MediaType.APPLICATION_JSON_VALUE, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(description = "Fetch clinical data by patient IDs or sample IDs (specific study)") + @ApiResponse( + responseCode = "200", + description = "OK", + content = + @Content(array = @ArraySchema(schema = @Schema(implementation = ClinicalData.class)))) + public ResponseEntity> fetchAllClinicalDataInStudy( + @Parameter(required = true, description = "Study ID e.g. acc_tcga") @PathVariable + String studyId, + @Parameter(description = "Type of the clinical data") @RequestParam(defaultValue = "SAMPLE") + ClinicalDataType clinicalDataType, + @Parameter(required = true, description = "List of patient or sample IDs and attribute IDs") + @Valid + @RequestBody + ClinicalDataSingleStudyFilter clinicalDataSingleStudyFilter, + @Parameter(description = "Level of detail of the response") + @RequestParam(defaultValue = "SUMMARY") + Projection projection) + throws StudyNotFoundException { + + if (projection == Projection.META) { + HttpHeaders responseHeaders = new HttpHeaders(); + responseHeaders.add( + HeaderKeyConstants.TOTAL_COUNT, + clinicalDataService + .fetchMetaClinicalDataInStudy( + studyId, + clinicalDataSingleStudyFilter.getIds(), + clinicalDataSingleStudyFilter.getAttributeIds(), + clinicalDataType.name()) + .getTotalCount() + .toString()); + return new ResponseEntity<>(responseHeaders, HttpStatus.OK); + } else { + return new ResponseEntity<>( + clinicalDataService.fetchAllClinicalDataInStudy( + studyId, + clinicalDataSingleStudyFilter.getIds(), + clinicalDataSingleStudyFilter.getAttributeIds(), + clinicalDataType.name(), + projection.name()), + HttpStatus.OK); + } + } + + @PreAuthorize( + "hasPermission(#involvedCancerStudies, 'Collection', T(org.cbioportal.legacy.utils.security.AccessLevel).READ)") + @RequestMapping( + value = "/clinical-data/fetch", + method = RequestMethod.POST, + consumes = MediaType.APPLICATION_JSON_VALUE, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(description = "Fetch clinical data by patient IDs or sample IDs (all studies)") + @ApiResponse( + responseCode = "200", + description = "OK", + content = + @Content(array = @ArraySchema(schema = @Schema(implementation = ClinicalData.class)))) + public ResponseEntity> fetchClinicalData( + @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface + @RequestAttribute(required = false, value = "involvedCancerStudies") + Collection involvedCancerStudies, + @Parameter( + hidden = + true) // prevent reference to this attribute in the swagger-ui interface. this + // attribute is needed for the @PreAuthorize tag above. + @Valid + @RequestAttribute(required = false, value = "interceptedClinicalDataMultiStudyFilter") + ClinicalDataMultiStudyFilter interceptedClinicalDataMultiStudyFilter, + @Parameter(description = "Type of the clinical data") @RequestParam(defaultValue = "SAMPLE") + ClinicalDataType clinicalDataType, + @Parameter( + required = true, + description = "List of patient or sample identifiers and attribute IDs") + @Valid + @RequestBody(required = false) + ClinicalDataMultiStudyFilter clinicalDataMultiStudyFilter, + @Parameter(description = "Level of detail of the response") + @RequestParam(defaultValue = "SUMMARY") + Projection projection) { + + List studyIds = new ArrayList<>(); + List ids = new ArrayList<>(); + + for (ClinicalDataIdentifier identifier : + interceptedClinicalDataMultiStudyFilter.getIdentifiers()) { + studyIds.add(identifier.getStudyId()); + ids.add(identifier.getEntityId()); + } + + if (projection == Projection.META) { + HttpHeaders responseHeaders = new HttpHeaders(); + responseHeaders.add( + HeaderKeyConstants.TOTAL_COUNT, + clinicalDataService + .fetchMetaClinicalData( + studyIds, + ids, + interceptedClinicalDataMultiStudyFilter.getAttributeIds(), + clinicalDataType.name()) + .getTotalCount() + .toString()); + return new ResponseEntity<>(responseHeaders, HttpStatus.OK); + } else { + return new ResponseEntity<>( + clinicalDataService.fetchClinicalData( + studyIds, + ids, + interceptedClinicalDataMultiStudyFilter.getAttributeIds(), + clinicalDataType.name(), + projection.name()), + HttpStatus.OK); + } + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/ClinicalDataEnrichmentController.java b/src/main/java/org/cbioportal/legacy/web/ClinicalDataEnrichmentController.java new file mode 100644 index 00000000000..278c1708ba5 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/ClinicalDataEnrichmentController.java @@ -0,0 +1,160 @@ +package org.cbioportal.legacy.web; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.ArraySchema; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; +import org.apache.commons.collections4.map.MultiKeyMap; +import org.cbioportal.legacy.model.ClinicalAttribute; +import org.cbioportal.legacy.model.ClinicalDataEnrichment; +import org.cbioportal.legacy.model.Sample; +import org.cbioportal.legacy.service.ClinicalAttributeService; +import org.cbioportal.legacy.service.SampleService; +import org.cbioportal.legacy.web.config.annotation.InternalApi; +import org.cbioportal.legacy.web.parameter.GroupFilter; +import org.cbioportal.legacy.web.parameter.Projection; +import org.cbioportal.legacy.web.parameter.SampleIdentifier; +import org.cbioportal.legacy.web.util.ClinicalDataEnrichmentUtil; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.RequestAttribute; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RestController; + +@InternalApi +@RestController +@RequestMapping("/api") +@Validated +@Tag(name = "Clinical Data Enrichments", description = " ") +public class ClinicalDataEnrichmentController { + + @Autowired private ClinicalDataEnrichmentUtil clinicalDataEnrichmentUtil; + + @Autowired private ClinicalAttributeService clinicalAttributeService; + + @Autowired private SampleService sampleService; + + @PreAuthorize( + "hasPermission(#involvedCancerStudies, 'Collection', T(org.cbioportal.legacy.utils.security.AccessLevel).READ)") + @RequestMapping( + value = "/clinical-data-enrichments/fetch", + method = RequestMethod.POST, + consumes = MediaType.APPLICATION_JSON_VALUE, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(description = "Fetch clinical data enrichments for the sample groups") + @ApiResponse( + responseCode = "200", + description = "OK", + content = + @Content( + array = + @ArraySchema(schema = @Schema(implementation = ClinicalDataEnrichment.class)))) + public ResponseEntity> fetchClinicalEnrichments( + @Parameter(required = true, description = "List of altered and unaltered Sample/Patient IDs") + @Valid + @RequestBody(required = false) + GroupFilter groupFilter, + @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface + @RequestAttribute(required = false, value = "involvedCancerStudies") + Collection involvedCancerStudies, + @Parameter( + hidden = + true) // prevent reference to this attribute in the swagger-ui interface. this + // attribute is needed for the @PreAuthorize tag above. + @Valid + @RequestAttribute(required = false, value = "interceptedGroupFilter") + GroupFilter interceptedGroupFilter) { + + List studyIds = + interceptedGroupFilter.getGroups().stream() + .flatMap( + group -> group.getSampleIdentifiers().stream().map(SampleIdentifier::getStudyId)) + .collect(Collectors.toList()); + + List sampleIds = + interceptedGroupFilter.getGroups().stream() + .flatMap( + group -> group.getSampleIdentifiers().stream().map(SampleIdentifier::getSampleId)) + .collect(Collectors.toList()); + + List samples = + sampleService.fetchSamples(studyIds, sampleIds, Projection.SUMMARY.name()); + + MultiKeyMap sampleSet = new MultiKeyMap(); + + samples.stream() + .forEach( + sample -> + sampleSet.put(sample.getCancerStudyIdentifier(), sample.getStableId(), sample)); + + // samples for each group + List> groupedSamples = + interceptedGroupFilter.getGroups().stream() + .map( + group -> + group.getSampleIdentifiers().stream() + .map( + sampleIdentifier -> + (Sample) + sampleSet.get( + sampleIdentifier.getStudyId(), + sampleIdentifier.getSampleId())) + .filter(sample -> sample != null) + .collect(Collectors.toList())) + .filter(validSamples -> validSamples.size() > 0) + .collect(Collectors.toList()); + + return new ResponseEntity<>(fetchClinicalDataEnrichemnts(groupedSamples), HttpStatus.OK); + } + + private List fetchClinicalDataEnrichemnts( + List> groupedSamples) { + + List clinicalEnrichments = new ArrayList(); + + if (!groupedSamples.isEmpty()) { + Set studyIds = + groupedSamples.stream() + .flatMap(samples -> samples.stream().map(Sample::getCancerStudyIdentifier)) + .collect(Collectors.toSet()); + + List clinicalAttributes = + clinicalAttributeService.fetchClinicalAttributes( + new ArrayList(studyIds), "SUMMARY"); + + // remove all duplicate attributes + Map clinicalAttributesByUniqId = + clinicalAttributes.stream() + .collect( + Collectors.toMap( + c -> c.getAttrId() + c.getPatientAttribute(), c -> c, (e1, e2) -> e2)); + + clinicalAttributes = new ArrayList<>(clinicalAttributesByUniqId.values()); + + clinicalEnrichments.addAll( + clinicalDataEnrichmentUtil.createEnrichmentsForCategoricalData( + clinicalAttributes, groupedSamples)); + + clinicalEnrichments.addAll( + clinicalDataEnrichmentUtil.createEnrichmentsForNumericData( + clinicalAttributes, groupedSamples)); + } + return clinicalEnrichments; + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/ClinicalEventController.java b/src/main/java/org/cbioportal/legacy/web/ClinicalEventController.java new file mode 100644 index 00000000000..0aafb7afca0 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/ClinicalEventController.java @@ -0,0 +1,224 @@ +package org.cbioportal.legacy.web; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.ArraySchema; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import jakarta.validation.constraints.Max; +import jakarta.validation.constraints.Min; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import org.cbioportal.legacy.model.ClinicalEvent; +import org.cbioportal.legacy.service.ClinicalEventService; +import org.cbioportal.legacy.service.exception.PatientNotFoundException; +import org.cbioportal.legacy.service.exception.StudyNotFoundException; +import org.cbioportal.legacy.web.config.InternalApiTags; +import org.cbioportal.legacy.web.config.annotation.InternalApi; +import org.cbioportal.legacy.web.parameter.ClinicalEventAttributeRequest; +import org.cbioportal.legacy.web.parameter.Direction; +import org.cbioportal.legacy.web.parameter.HeaderKeyConstants; +import org.cbioportal.legacy.web.parameter.PagingConstants; +import org.cbioportal.legacy.web.parameter.PatientIdentifier; +import org.cbioportal.legacy.web.parameter.Projection; +import org.cbioportal.legacy.web.parameter.sort.ClinicalEventSortBy; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestAttribute; +import org.springframework.web.bind.annotation.RequestBody; +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.bind.annotation.RestController; + +@InternalApi +@RestController() +@RequestMapping("/api") +@Validated +@Tag(name = InternalApiTags.CLINICAL_EVENTS, description = " ") +public class ClinicalEventController { + + @Autowired private ClinicalEventService clinicalEventService; + + @PreAuthorize( + "hasPermission(#studyId, 'CancerStudyId', T(org.cbioportal.legacy.utils.security.AccessLevel).READ)") + @RequestMapping( + value = "/studies/{studyId}/patients/{patientId}/clinical-events", + method = RequestMethod.GET, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(description = "Get all clinical events of a patient in a study") + @ApiResponse( + responseCode = "200", + description = "OK", + content = + @Content(array = @ArraySchema(schema = @Schema(implementation = ClinicalEvent.class)))) + public ResponseEntity> getAllClinicalEventsOfPatientInStudy( + @Parameter(required = true, description = "Study ID e.g. lgg_ucsf_2014") @PathVariable + String studyId, + @Parameter(required = true, description = "Patient ID e.g. P01") @PathVariable + String patientId, + @Parameter(description = "Level of detail of the response") + @RequestParam(defaultValue = "SUMMARY") + Projection projection, + @Parameter(description = "Page size of the result list") + @Max(PagingConstants.MAX_PAGE_SIZE) + @Min(PagingConstants.MIN_PAGE_SIZE) + @RequestParam(defaultValue = PagingConstants.DEFAULT_PAGE_SIZE) + Integer pageSize, + @Parameter(description = "Page number of the result list") + @Min(PagingConstants.MIN_PAGE_NUMBER) + @RequestParam(defaultValue = PagingConstants.DEFAULT_PAGE_NUMBER) + Integer pageNumber, + @Parameter(description = "Name of the property that the result list is sorted by") + @RequestParam(required = false) + ClinicalEventSortBy sortBy, + @Parameter(description = "Direction of the sort") @RequestParam(defaultValue = "ASC") + Direction direction) + throws PatientNotFoundException, StudyNotFoundException { + + if (projection == Projection.META) { + HttpHeaders responseHeaders = new HttpHeaders(); + responseHeaders.add( + HeaderKeyConstants.TOTAL_COUNT, + clinicalEventService + .getMetaPatientClinicalEvents(studyId, patientId) + .getTotalCount() + .toString()); + return new ResponseEntity<>(responseHeaders, HttpStatus.OK); + } else { + return new ResponseEntity<>( + clinicalEventService.getAllClinicalEventsOfPatientInStudy( + studyId, + patientId, + projection.name(), + pageSize, + pageNumber, + sortBy == null ? null : sortBy.getOriginalValue(), + direction.name()), + HttpStatus.OK); + } + } + + @PreAuthorize( + "hasPermission(#studyId, 'CancerStudyId', T(org.cbioportal.legacy.utils.security.AccessLevel).READ)") + @RequestMapping( + value = "/studies/{studyId}/clinical-events", + method = RequestMethod.GET, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(description = "Get all clinical events in a study") + @ApiResponse( + responseCode = "200", + description = "OK", + content = + @Content(array = @ArraySchema(schema = @Schema(implementation = ClinicalEvent.class)))) + public ResponseEntity> getAllClinicalEventsInStudy( + @Parameter(required = true, description = "Study ID e.g. lgg_ucsf_2014") @PathVariable + String studyId, + @Parameter(description = "Level of detail of the response") + @RequestParam(defaultValue = "SUMMARY") + Projection projection, + @Parameter(description = "Page size of the result list") + @Max(PagingConstants.MAX_PAGE_SIZE) + @Min(PagingConstants.MIN_PAGE_SIZE) + @RequestParam(defaultValue = PagingConstants.DEFAULT_PAGE_SIZE) + Integer pageSize, + @Parameter(description = "Page number of the result list") + @Min(PagingConstants.MIN_PAGE_NUMBER) + @RequestParam(defaultValue = PagingConstants.DEFAULT_PAGE_NUMBER) + Integer pageNumber, + @Parameter(description = "Name of the property that the result list is sorted by") + @RequestParam(required = false) + ClinicalEventSortBy sortBy, + @Parameter(description = "Direction of the sort") @RequestParam(defaultValue = "ASC") + Direction direction) + throws PatientNotFoundException, StudyNotFoundException { + + if (projection == Projection.META) { + HttpHeaders responseHeaders = new HttpHeaders(); + responseHeaders.add( + HeaderKeyConstants.TOTAL_COUNT, + clinicalEventService.getMetaClinicalEvents(studyId).getTotalCount().toString()); + return new ResponseEntity<>(responseHeaders, HttpStatus.OK); + } else { + return new ResponseEntity<>( + clinicalEventService.getAllClinicalEventsInStudy( + studyId, + projection.name(), + pageSize, + pageNumber, + sortBy == null ? null : sortBy.getOriginalValue(), + direction.name()), + HttpStatus.OK); + } + } + + @PreAuthorize( + "hasPermission(#involvedCancerStudies, 'Collection', T(org.cbioportal.legacy.utils.security.AccessLevel).READ)") + @RequestMapping( + value = "/clinical-events-meta/fetch", + method = RequestMethod.POST, + consumes = MediaType.APPLICATION_JSON_VALUE, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(description = "Fetch clinical events meta") + @ApiResponse( + responseCode = "200", + description = "OK", + content = + @Content(array = @ArraySchema(schema = @Schema(implementation = ClinicalEvent.class)))) + public ResponseEntity> fetchClinicalEventsMeta( + @Parameter(required = true, description = "clinical events Request") + @Valid + @RequestBody(required = false) + ClinicalEventAttributeRequest clinicalEventAttributeRequest, + @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface + @RequestAttribute(required = false, value = "involvedCancerStudies") + Collection involvedCancerStudies, + @Parameter( + hidden = + true) // prevent reference to this attribute in the swagger-ui interface. This + // attribute is needed for the @PreAuthorize tag above. + @Valid + @RequestAttribute(required = false, value = "interceptedClinicalEventAttributeRequest") + ClinicalEventAttributeRequest interceptedClinicalEventAttributeRequest) { + + return new ResponseEntity<>( + cachedClinicalEventsMeta(interceptedClinicalEventAttributeRequest), HttpStatus.OK); + } + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + public List cachedClinicalEventsMeta( + ClinicalEventAttributeRequest interceptedClinicalEventAttributeRequest) { + List studyIds = new ArrayList<>(); + List patientIds = new ArrayList<>(); + for (PatientIdentifier patientIdentifier : + interceptedClinicalEventAttributeRequest.getPatientIdentifiers()) { + studyIds.add(patientIdentifier.getStudyId()); + patientIds.add(patientIdentifier.getPatientId()); + } + + List clinicalEventsRequest = + interceptedClinicalEventAttributeRequest.getClinicalEventRequests().stream() + .map( + x -> { + ClinicalEvent clinicalEvent = new ClinicalEvent(); + clinicalEvent.setEventType(x.getEventType()); + clinicalEvent.setAttributes(x.getAttributes()); + return clinicalEvent; + }) + .toList(); + return clinicalEventService.getClinicalEventsMeta(studyIds, patientIds, clinicalEventsRequest); + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/CoExpressionController.java b/src/main/java/org/cbioportal/legacy/web/CoExpressionController.java new file mode 100644 index 00000000000..611620a5d46 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/CoExpressionController.java @@ -0,0 +1,111 @@ +package org.cbioportal.legacy.web; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.ArraySchema; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import java.util.List; +import org.cbioportal.legacy.model.CoExpression; +import org.cbioportal.legacy.model.EntityType; +import org.cbioportal.legacy.service.CoExpressionService; +import org.cbioportal.legacy.web.config.annotation.InternalApi; +import org.cbioportal.legacy.web.parameter.CoExpressionFilter; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.RequestBody; +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.bind.annotation.RestController; + +@InternalApi +@RestController() +@RequestMapping("/api") +@Validated +@Tag(name = "Co-Expressions", description = " ") +public class CoExpressionController { + + @Autowired private CoExpressionService coExpressionService; + + // requires permission to access both molecularProfileIdA and molecularProfileIdB because service + // layer does not enforce requirement that both profiles are in the same study + @PreAuthorize( + "hasPermission(#molecularProfileIdA, 'MolecularProfileId', T(org.cbioportal.legacy.utils.security.AccessLevel).READ) and hasPermission(#molecularProfileIdB, 'MolecularProfileId', T(org.cbioportal.legacy.utils.security.AccessLevel).READ)") + @RequestMapping( + value = "/molecular-profiles/co-expressions/fetch", + method = RequestMethod.POST, + consumes = MediaType.APPLICATION_JSON_VALUE, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation( + description = + "Calculates correlations between a genetic entity from a specific profile and another profile from the same study") + @ApiResponse( + responseCode = "200", + description = "OK", + content = + @Content(array = @ArraySchema(schema = @Schema(implementation = CoExpression.class)))) + public ResponseEntity> fetchCoExpressions( + @Parameter( + required = true, + description = + "Molecular Profile ID from the Genetic Entity referenced in the co-expression filter e.g. acc_tcga_rna_seq_v2_mrna") + @RequestParam + String molecularProfileIdA, + @Parameter( + required = true, + description = + "Molecular Profile ID (can be the same as molecularProfileIdA) e.g. acc_tcga_rna_seq_v2_mrna") + @RequestParam + String molecularProfileIdB, + @Parameter( + required = true, + description = "List of Sample IDs/Sample List ID and Entrez Gene ID/Gene set ID") + @Valid + @RequestBody + CoExpressionFilter coExpressionFilter, + @Parameter(description = "Threshold") @RequestParam(defaultValue = "0.3") Double threshold) + throws Exception { + + List coExpressionList; + String geneticEntityId = null; + EntityType geneticEntityType = null; + + if (coExpressionFilter.getEntrezGeneId() != null) { + geneticEntityId = coExpressionFilter.getEntrezGeneId().toString(); + geneticEntityType = EntityType.GENE; + } else { + geneticEntityId = coExpressionFilter.getGenesetId(); + geneticEntityType = EntityType.GENESET; + } + + if (coExpressionFilter.getSampleListId() != null) { + coExpressionList = + coExpressionService.getCoExpressions( + geneticEntityId, + geneticEntityType, + coExpressionFilter.getSampleListId(), + molecularProfileIdA, + molecularProfileIdB, + threshold); + } else { + coExpressionList = + coExpressionService.fetchCoExpressions( + geneticEntityId, + geneticEntityType, + coExpressionFilter.getSampleIds(), + molecularProfileIdA, + molecularProfileIdB, + threshold); + } + + return new ResponseEntity<>(coExpressionList, HttpStatus.OK); + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/CopyNumberSegmentController.java b/src/main/java/org/cbioportal/legacy/web/CopyNumberSegmentController.java new file mode 100644 index 00000000000..7cb4aaa2405 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/CopyNumberSegmentController.java @@ -0,0 +1,172 @@ +package org.cbioportal.legacy.web; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.ArraySchema; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.constraints.Max; +import jakarta.validation.constraints.Min; +import jakarta.validation.constraints.Size; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import org.cbioportal.legacy.model.CopyNumberSeg; +import org.cbioportal.legacy.service.CopyNumberSegmentService; +import org.cbioportal.legacy.service.exception.SampleNotFoundException; +import org.cbioportal.legacy.service.exception.StudyNotFoundException; +import org.cbioportal.legacy.web.config.PublicApiTags; +import org.cbioportal.legacy.web.config.annotation.PublicApi; +import org.cbioportal.legacy.web.parameter.Direction; +import org.cbioportal.legacy.web.parameter.HeaderKeyConstants; +import org.cbioportal.legacy.web.parameter.PagingConstants; +import org.cbioportal.legacy.web.parameter.Projection; +import org.cbioportal.legacy.web.parameter.SampleIdentifier; +import org.cbioportal.legacy.web.parameter.sort.CopyNumberSegmentSortBy; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestAttribute; +import org.springframework.web.bind.annotation.RequestBody; +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.bind.annotation.RestController; + +@PublicApi +@RestController() +@RequestMapping("/api") +@Validated +@Tag(name = PublicApiTags.COPY_NUMBER_SEGMENTS, description = " ") +public class CopyNumberSegmentController { + + private static final int COPY_NUMBER_SEGMENT_MAX_PAGE_SIZE = 20000; + private static final String COPY_NUMBER_SEGMENT_DEFAULT_PAGE_SIZE = "20000"; + + @Autowired private CopyNumberSegmentService copyNumberSegmentService; + + @PreAuthorize( + "hasPermission(#studyId, 'CancerStudyId', T(org.cbioportal.legacy.utils.security.AccessLevel).READ)") + @RequestMapping( + value = "/studies/{studyId}/samples/{sampleId}/copy-number-segments", + method = RequestMethod.GET, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(description = "Get copy number segments in a sample in a study") + @ApiResponse( + responseCode = "200", + description = "OK", + content = + @Content(array = @ArraySchema(schema = @Schema(implementation = CopyNumberSeg.class)))) + public ResponseEntity> getCopyNumberSegmentsInSampleInStudy( + @Parameter(required = true, description = "Study ID e.g. acc_tcga") @PathVariable + String studyId, + @Parameter(required = true, description = "Sample ID e.g. TCGA-OR-A5J2-01") @PathVariable + String sampleId, + @Parameter(description = "Chromosome") @RequestParam(required = false) String chromosome, + @Parameter(description = "Level of detail of the response") + @RequestParam(defaultValue = "SUMMARY") + Projection projection, + @Parameter(description = "Page size of the result list") + @Max(COPY_NUMBER_SEGMENT_MAX_PAGE_SIZE) + @Min(PagingConstants.MIN_PAGE_SIZE) + @RequestParam(defaultValue = COPY_NUMBER_SEGMENT_DEFAULT_PAGE_SIZE) + Integer pageSize, + @Parameter(description = "Page number of the result list") + @Min(PagingConstants.MIN_PAGE_NUMBER) + @RequestParam(defaultValue = PagingConstants.DEFAULT_PAGE_NUMBER) + Integer pageNumber, + @Parameter(description = "Name of the property that the result list is sorted by") + @RequestParam(required = false) + CopyNumberSegmentSortBy sortBy, + @Parameter(description = "Direction of the sort") @RequestParam(defaultValue = "ASC") + Direction direction) + throws SampleNotFoundException, StudyNotFoundException { + + if (projection == Projection.META) { + HttpHeaders responseHeaders = new HttpHeaders(); + responseHeaders.add( + HeaderKeyConstants.TOTAL_COUNT, + copyNumberSegmentService + .getMetaCopyNumberSegmentsInSampleInStudy(studyId, sampleId, chromosome) + .getTotalCount() + .toString()); + return new ResponseEntity<>(responseHeaders, HttpStatus.OK); + } else { + return new ResponseEntity<>( + copyNumberSegmentService.getCopyNumberSegmentsInSampleInStudy( + studyId, + sampleId, + chromosome, + projection.name(), + pageSize, + pageNumber, + sortBy == null ? null : sortBy.getOriginalValue(), + direction.name()), + HttpStatus.OK); + } + } + + @PreAuthorize( + "hasPermission(#involvedCancerStudies, 'Collection', T(org.cbioportal.legacy.utils.security.AccessLevel).READ)") + @RequestMapping( + value = "/copy-number-segments/fetch", + method = RequestMethod.POST, + consumes = MediaType.APPLICATION_JSON_VALUE, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(description = "Fetch copy number segments by sample ID") + @ApiResponse( + responseCode = "200", + description = "OK", + content = + @Content(array = @ArraySchema(schema = @Schema(implementation = CopyNumberSeg.class)))) + public ResponseEntity> fetchCopyNumberSegments( + @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface + @RequestAttribute(required = false, value = "involvedCancerStudies") + Collection involvedCancerStudies, + @Parameter( + hidden = + true) // prevent reference to this attribute in the swagger-ui interface. this + // attribute is needed for the @PreAuthorize tag above. + @RequestAttribute(required = false, value = "interceptedSampleIdentifiers") + List interceptedSampleIdentifiers, + @Parameter(required = true, description = "List of sample identifiers") + @Size(min = 1, max = PagingConstants.MAX_PAGE_SIZE) + @RequestBody(required = false) + List sampleIdentifiers, + @Parameter(description = "Chromosome") @RequestParam(required = false) String chromosome, + @Parameter(description = "Level of detail of the response") + @RequestParam(defaultValue = "SUMMARY") + Projection projection) { + + List studyIds = new ArrayList<>(); + List sampleIds = new ArrayList<>(); + + for (SampleIdentifier sampleIdentifier : interceptedSampleIdentifiers) { + studyIds.add(sampleIdentifier.getStudyId()); + sampleIds.add(sampleIdentifier.getSampleId()); + } + + if (projection == Projection.META) { + HttpHeaders responseHeaders = new HttpHeaders(); + responseHeaders.add( + HeaderKeyConstants.TOTAL_COUNT, + copyNumberSegmentService + .fetchMetaCopyNumberSegments(studyIds, sampleIds, chromosome) + .getTotalCount() + .toString()); + return new ResponseEntity<>(responseHeaders, HttpStatus.OK); + } else { + return new ResponseEntity<>( + copyNumberSegmentService.fetchCopyNumberSegments( + studyIds, sampleIds, chromosome, projection.name()), + HttpStatus.OK); + } + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/CosmicCountController.java b/src/main/java/org/cbioportal/legacy/web/CosmicCountController.java new file mode 100644 index 00000000000..53b3d46d603 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/CosmicCountController.java @@ -0,0 +1,55 @@ +package org.cbioportal.legacy.web; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.ArraySchema; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.constraints.Size; +import java.util.List; +import org.cbioportal.legacy.model.CosmicMutation; +import org.cbioportal.legacy.service.CosmicCountService; +import org.cbioportal.legacy.web.config.annotation.InternalApi; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RestController; + +@InternalApi +@RestController +@Validated +@Tag(name = "Cosmic Counts", description = " ") +public class CosmicCountController { + + private static final int COSMIC_COUNT_MAX_PAGE_SIZE = 50000; + + @Autowired private CosmicCountService cosmicCountService; + + @RequestMapping( + value = "/api/cosmic-counts/fetch", + method = RequestMethod.POST, + consumes = MediaType.APPLICATION_JSON_VALUE, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(description = "Get counts within the COSMIC database by keywords") + @ApiResponse( + responseCode = "200", + description = "OK", + content = + @Content(array = @ArraySchema(schema = @Schema(implementation = CosmicMutation.class)))) + public ResponseEntity> fetchCosmicCounts( + @Parameter(required = true, description = "List of keywords") + @Size(min = 1, max = COSMIC_COUNT_MAX_PAGE_SIZE) + @RequestBody + List keywords) { + + return new ResponseEntity<>( + cosmicCountService.fetchCosmicCountsByKeywords(keywords), HttpStatus.OK); + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/DataAccessTokenController.java b/src/main/java/org/cbioportal/legacy/web/DataAccessTokenController.java new file mode 100644 index 00000000000..7182b4a2193 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/DataAccessTokenController.java @@ -0,0 +1,196 @@ +/* + * This file is part of cBioPortal. + * + * cBioPortal is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package org.cbioportal.legacy.web; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.ArraySchema; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.util.HashSet; +import java.util.List; +import java.util.Objects; +import java.util.Set; +import org.apache.commons.lang3.StringUtils; +import org.cbioportal.legacy.model.DataAccessToken; +import org.cbioportal.legacy.service.DataAccessTokenService; +import org.cbioportal.legacy.service.exception.DataAccessTokenNoUserIdentityException; +import org.cbioportal.legacy.service.exception.DataAccessTokenProhibitedUserException; +import org.cbioportal.legacy.utils.config.annotation.ConditionalOnProperty; +import org.cbioportal.legacy.web.config.annotation.InternalApi; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.client.HttpClientErrorException; + +@InternalApi +@Validated +@RestController +@ConditionalOnProperty( + name = "dat.method", + havingValue = "oauth2", + isNot = true, + matchIfMissing = true) +@Tag(name = "Data Access Tokens", description = " ") +public class DataAccessTokenController { + + @Value("${dat.unauth_users:anonymousUser}") + private String usersWhoCannotUseTokens; + + private String userRoleToAccessToken; + + @Value("${download_group:}") // default is empty string + public void setUserRoleToAccessToken(String property) { + userRoleToAccessToken = property; + } + + private final DataAccessTokenService tokenService; + private final Set usersWhoCannotUseTokenSet; + + private static final String FILE_NAME = "cbioportal_data_access_token.txt"; + + @Autowired + public DataAccessTokenController(DataAccessTokenService tokenService) { + this.tokenService = tokenService; + if (Objects.isNull(usersWhoCannotUseTokens)) { + usersWhoCannotUseTokens = ""; + } + usersWhoCannotUseTokenSet = new HashSet<>(List.of((usersWhoCannotUseTokens.split(",")))); + } + + @RequestMapping(method = RequestMethod.GET, value = "/api/data-access-token") + @Operation(description = "Create a new data access token") + @ApiResponse( + responseCode = "200", + description = "OK", + content = @Content(schema = @Schema(implementation = String.class))) + public ResponseEntity downloadDataAccessToken( + Authentication authentication, HttpServletRequest request, HttpServletResponse response) { + // for other methods add header to trigger download of the token by the browser + response.setHeader("Content-Disposition", "attachment; filename=" + FILE_NAME); + String userName = getAuthenticatedUser(authentication); + DataAccessToken token = tokenService.createDataAccessToken(userName); + if (token == null) { + return new ResponseEntity<>(HttpStatus.NOT_FOUND); + } + + return new ResponseEntity<>(token.toString(), HttpStatus.CREATED); + } + + // retrieve and trigger download OAuth2 offline token + @RequestMapping(method = RequestMethod.GET, value = "/api/data-access-token/oauth2") + @Parameter(hidden = true) + @ApiResponse( + responseCode = "200", + description = "OK", + content = @Content(schema = @Schema(implementation = String.class))) + public ResponseEntity downloadOAuth2DataAccessToken( + HttpServletRequest request, HttpServletResponse response) throws IOException { + throw new UnsupportedOperationException( + "this endpoint is only enabled when dat is set to oauth2."); + } + + @RequestMapping( + method = RequestMethod.POST, + value = "/api/data-access-tokens", + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(description = "Get all data access tokens") + @ApiResponse( + responseCode = "200", + description = "OK", + content = @Content(schema = @Schema(implementation = DataAccessToken.class))) + public ResponseEntity createDataAccessToken(Authentication authentication) + throws HttpClientErrorException { + String userName = getAuthenticatedUser(authentication); + DataAccessToken token = tokenService.createDataAccessToken(userName); + if (token == null) { + return new ResponseEntity<>(HttpStatus.NOT_FOUND); + } + return new ResponseEntity<>(token, HttpStatus.CREATED); + } + + @RequestMapping(method = RequestMethod.GET, value = "/api/data-access-tokens") + @Operation(description = "Retrieve all data access tokens") + @ApiResponse( + responseCode = "200", + description = "OK", + content = + @Content(array = @ArraySchema(schema = @Schema(implementation = DataAccessToken.class)))) + public ResponseEntity> getAllDataAccessTokens( + HttpServletRequest request, Authentication authentication) { + String userName = getAuthenticatedUser(authentication); + List allDataAccessTokens = tokenService.getAllDataAccessTokens(userName); + return new ResponseEntity<>(allDataAccessTokens, HttpStatus.OK); + } + + @RequestMapping(method = RequestMethod.GET, value = "/api/data-access-tokens/{token}") + @Operation(description = "Retrieve an existing data access token") + @ApiResponse( + responseCode = "200", + description = "OK", + content = @Content(schema = @Schema(implementation = DataAccessToken.class))) + public ResponseEntity getDataAccessToken( + @Parameter(required = true, description = "token") @PathVariable String token) { + DataAccessToken dataAccessToken = tokenService.getDataAccessTokenInfo(token); + return new ResponseEntity<>(dataAccessToken, HttpStatus.OK); + } + + @RequestMapping(method = RequestMethod.DELETE, value = "/api/data-access-tokens") + @Operation(description = "Delete all data access tokens") + public void revokeAllDataAccessTokens(Authentication authentication) { + tokenService.revokeAllDataAccessTokens(getAuthenticatedUser(authentication)); + } + + @RequestMapping(method = RequestMethod.DELETE, value = "/api/data-access-tokens/{token}") + @Operation(description = "Delete a data access token") + public void revokeDataAccessToken( + @Parameter(required = true, description = "token") @PathVariable String token) { + tokenService.revokeDataAccessToken(token); + } + + private String getAuthenticatedUser(Authentication authentication) { + if (authentication == null || !authentication.isAuthenticated()) { + throw new DataAccessTokenNoUserIdentityException(); + } + String username = authentication.getName(); + if (usersWhoCannotUseTokenSet.contains(username)) { + throw new DataAccessTokenProhibitedUserException(); + } + if (StringUtils.isNotEmpty(userRoleToAccessToken) + && !authentication + .getAuthorities() + .contains(new SimpleGrantedAuthority(userRoleToAccessToken))) { + throw new DataAccessTokenProhibitedUserException(); + } + return username; + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/DiscreteCopyNumberController.java b/src/main/java/org/cbioportal/legacy/web/DiscreteCopyNumberController.java new file mode 100644 index 00000000000..fdea7dc234b --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/DiscreteCopyNumberController.java @@ -0,0 +1,176 @@ +package org.cbioportal.legacy.web; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.ArraySchema; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import java.util.List; +import org.cbioportal.legacy.model.DiscreteCopyNumberData; +import org.cbioportal.legacy.model.meta.BaseMeta; +import org.cbioportal.legacy.service.DiscreteCopyNumberService; +import org.cbioportal.legacy.service.exception.MolecularProfileNotFoundException; +import org.cbioportal.legacy.web.config.PublicApiTags; +import org.cbioportal.legacy.web.config.annotation.PublicApi; +import org.cbioportal.legacy.web.parameter.DiscreteCopyNumberEventType; +import org.cbioportal.legacy.web.parameter.DiscreteCopyNumberFilter; +import org.cbioportal.legacy.web.parameter.HeaderKeyConstants; +import org.cbioportal.legacy.web.parameter.Projection; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +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.bind.annotation.RestController; + +@PublicApi +@RestController() +@RequestMapping("/api") +@Validated +@Tag(name = PublicApiTags.DISCRETE_COPY_NUMBER_ALTERATIONS, description = " ") +public class DiscreteCopyNumberController { + + @Autowired private DiscreteCopyNumberService discreteCopyNumberService; + + @PreAuthorize( + "hasPermission(#molecularProfileId, 'MolecularProfileId', T(org.cbioportal.legacy.utils.security.AccessLevel).READ)") + @RequestMapping( + value = "/molecular-profiles/{molecularProfileId}/discrete-copy-number", + method = RequestMethod.GET, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(description = "Get discrete copy number alterations in a molecular profile") + @ApiResponse( + responseCode = "200", + description = "OK", + content = + @Content( + array = + @ArraySchema(schema = @Schema(implementation = DiscreteCopyNumberData.class)))) + public ResponseEntity> getDiscreteCopyNumbersInMolecularProfile( + @Parameter(required = true, description = "Molecular Profile ID e.g. acc_tcga_gistic") + @PathVariable + String molecularProfileId, + @Parameter(required = true, description = "Sample List ID e.g. acc_tcga_all") @RequestParam + String sampleListId, + @Parameter(description = "Type of the copy number event") + @RequestParam(defaultValue = "HOMDEL_AND_AMP") + DiscreteCopyNumberEventType discreteCopyNumberEventType, + @Parameter(description = "Level of detail of the response") + @RequestParam(defaultValue = "SUMMARY") + Projection projection) + throws MolecularProfileNotFoundException { + + if (projection == Projection.META) { + HttpHeaders responseHeaders = new HttpHeaders(); + responseHeaders.add( + HeaderKeyConstants.TOTAL_COUNT, + discreteCopyNumberService + .getMetaDiscreteCopyNumbersInMolecularProfileBySampleListId( + molecularProfileId, + sampleListId, + null, + discreteCopyNumberEventType.getAlterationTypes()) + .getTotalCount() + .toString()); + return new ResponseEntity<>(responseHeaders, HttpStatus.OK); + } else { + return new ResponseEntity<>( + discreteCopyNumberService.getDiscreteCopyNumbersInMolecularProfileBySampleListId( + molecularProfileId, + sampleListId, + null, + discreteCopyNumberEventType.getAlterationTypes(), + projection.name()), + HttpStatus.OK); + } + } + + @PreAuthorize( + "hasPermission(#molecularProfileId, 'MolecularProfileId', T(org.cbioportal.legacy.utils.security.AccessLevel).READ)") + @RequestMapping( + value = "/molecular-profiles/{molecularProfileId}/discrete-copy-number/fetch", + method = RequestMethod.POST, + consumes = MediaType.APPLICATION_JSON_VALUE, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation( + description = "Fetch discrete copy number alterations in a molecular profile by sample ID") + @ApiResponse( + responseCode = "200", + description = "OK", + content = + @Content( + array = + @ArraySchema(schema = @Schema(implementation = DiscreteCopyNumberData.class)))) + public ResponseEntity> fetchDiscreteCopyNumbersInMolecularProfile( + @Parameter(required = true, description = "Molecular Profile ID e.g. acc_tcga_gistic") + @PathVariable + String molecularProfileId, + @Parameter(description = "Type of the copy number event") + @RequestParam(defaultValue = "HOMDEL_AND_AMP") + DiscreteCopyNumberEventType discreteCopyNumberEventType, + @Parameter( + required = true, + description = "List of Sample IDs/Sample List ID and Entrez Gene IDs") + @Valid + @RequestBody + DiscreteCopyNumberFilter discreteCopyNumberFilter, + @Parameter(description = "Level of detail of the response") + @RequestParam(defaultValue = "SUMMARY") + Projection projection) + throws MolecularProfileNotFoundException { + + if (projection == Projection.META) { + HttpHeaders responseHeaders = new HttpHeaders(); + BaseMeta baseMeta; + + if (discreteCopyNumberFilter.getSampleListId() != null) { + baseMeta = + discreteCopyNumberService.getMetaDiscreteCopyNumbersInMolecularProfileBySampleListId( + molecularProfileId, + discreteCopyNumberFilter.getSampleListId(), + discreteCopyNumberFilter.getEntrezGeneIds(), + discreteCopyNumberEventType.getAlterationTypes()); + } else { + baseMeta = + discreteCopyNumberService.fetchMetaDiscreteCopyNumbersInMolecularProfile( + molecularProfileId, + discreteCopyNumberFilter.getSampleIds(), + discreteCopyNumberFilter.getEntrezGeneIds(), + discreteCopyNumberEventType.getAlterationTypes()); + } + responseHeaders.add(HeaderKeyConstants.TOTAL_COUNT, baseMeta.getTotalCount().toString()); + return new ResponseEntity<>(responseHeaders, HttpStatus.OK); + } else { + List discreteCopyNumberDataList; + if (discreteCopyNumberFilter.getSampleListId() != null) { + discreteCopyNumberDataList = + discreteCopyNumberService.getDiscreteCopyNumbersInMolecularProfileBySampleListId( + molecularProfileId, + discreteCopyNumberFilter.getSampleListId(), + discreteCopyNumberFilter.getEntrezGeneIds(), + discreteCopyNumberEventType.getAlterationTypes(), + projection.name()); + } else { + discreteCopyNumberDataList = + discreteCopyNumberService.fetchDiscreteCopyNumbersInMolecularProfile( + molecularProfileId, + discreteCopyNumberFilter.getSampleIds(), + discreteCopyNumberFilter.getEntrezGeneIds(), + discreteCopyNumberEventType.getAlterationTypes(), + projection.name()); + } + + return new ResponseEntity<>(discreteCopyNumberDataList, HttpStatus.OK); + } + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/DiscreteCopyNumberCountController.java b/src/main/java/org/cbioportal/legacy/web/DiscreteCopyNumberCountController.java new file mode 100644 index 00000000000..20b7d21eb54 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/DiscreteCopyNumberCountController.java @@ -0,0 +1,80 @@ +package org.cbioportal.legacy.web; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.ArraySchema; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.constraints.Size; +import java.util.ArrayList; +import java.util.List; +import org.cbioportal.legacy.model.CopyNumberCount; +import org.cbioportal.legacy.service.DiscreteCopyNumberService; +import org.cbioportal.legacy.service.exception.MolecularProfileNotFoundException; +import org.cbioportal.legacy.web.config.InternalApiTags; +import org.cbioportal.legacy.web.config.annotation.InternalApi; +import org.cbioportal.legacy.web.parameter.CopyNumberCountIdentifier; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RestController; + +@InternalApi +@RestController() +@RequestMapping("/api") +@Validated +@Tag(name = InternalApiTags.DISCRETE_COPY_NUMBER_ALTERATION_COUNTS, description = " ") +public class DiscreteCopyNumberCountController { + + private static final int COPY_NUMBER_COUNT_MAX_PAGE_SIZE = 50000; + + @Autowired private DiscreteCopyNumberService discreteCopyNumberService; + + @PreAuthorize( + "hasPermission(#molecularProfileId, 'MolecularProfileId', T(org.cbioportal.legacy.utils.security.AccessLevel).READ)") + @RequestMapping( + value = "/molecular-profiles/{molecularProfileId}/discrete-copy-number-counts/fetch", + method = RequestMethod.POST, + consumes = MediaType.APPLICATION_JSON_VALUE, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation( + description = "Get counts of specific genes and alterations within a CNA molecular profile") + @ApiResponse( + responseCode = "200", + description = "OK", + content = + @Content(array = @ArraySchema(schema = @Schema(implementation = CopyNumberCount.class)))) + public ResponseEntity> fetchCopyNumberCounts( + @Parameter(required = true, description = "Molecular Profile ID e.g. acc_tcga_gistic") + @PathVariable + String molecularProfileId, + @Parameter(required = true, description = "List of copy number count identifiers") + @Size(min = 1, max = COPY_NUMBER_COUNT_MAX_PAGE_SIZE) + @RequestBody + List copyNumberCountIdentifiers) + throws MolecularProfileNotFoundException { + + List entrezGeneIds = new ArrayList<>(); + List alterations = new ArrayList<>(); + + for (CopyNumberCountIdentifier copyNumberCountIdentifier : copyNumberCountIdentifiers) { + + entrezGeneIds.add(copyNumberCountIdentifier.getEntrezGeneId()); + alterations.add(copyNumberCountIdentifier.getAlteration()); + } + + return new ResponseEntity<>( + discreteCopyNumberService.fetchCopyNumberCounts( + molecularProfileId, entrezGeneIds, alterations), + HttpStatus.OK); + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/DocRedirectController.java b/src/main/java/org/cbioportal/legacy/web/DocRedirectController.java new file mode 100644 index 00000000000..b853d12d769 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/DocRedirectController.java @@ -0,0 +1,43 @@ +package org.cbioportal.legacy.web; + +import jakarta.servlet.http.HttpServletRequest; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.servlet.mvc.support.RedirectAttributes; +import org.springframework.web.servlet.view.RedirectView; + +/** + * Springfox 3.0 doesn't completely respect the path we specify for the swagger UI This redirect + * puts the api-doc json in the specified path so that the swagger UI works and the frontend can + * pull the json. + */ +// @Controller +public class DocRedirectController { + @GetMapping("/api-docs") + public RedirectView docRedirect( + @RequestParam(value = "group", defaultValue = "default") String group, + final RedirectAttributes redirectAttributes, + HttpServletRequest request) { + redirectAttributes.addAttribute("group", group); + String baseUrl = getBaseUrl(request, "/api/api-docs"); + return new RedirectView(baseUrl + "/api/v2/api-docs"); + } + + @GetMapping({"/", "/swagger-ui.html"}) + public RedirectView swaggerUIRedirect( + @RequestParam(value = "group", defaultValue = "default") String group, + final RedirectAttributes redirectAttributes, + HttpServletRequest request) { + redirectAttributes.addAttribute("group", group); + String baseUrl = getBaseUrl(request, "/api/(|swagger-ui.html)"); + return new RedirectView(baseUrl + "/api/swagger-ui/index.html"); + } + + private String getBaseUrl(HttpServletRequest request, String suffix) { + Pattern p = Pattern.compile("^(.*)(" + suffix + ")$"); + Matcher m = p.matcher(request.getRequestURI()); + return m.find() ? m.group(1) : ""; + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/ExecuterTimeInterceptor.java b/src/main/java/org/cbioportal/legacy/web/ExecuterTimeInterceptor.java new file mode 100644 index 00000000000..7e339d5ff63 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/ExecuterTimeInterceptor.java @@ -0,0 +1,25 @@ +package org.cbioportal.legacy.web; + +import org.springframework.ui.ModelMap; +import org.springframework.web.context.request.WebRequest; +import org.springframework.web.context.request.WebRequestInterceptor; + +public class ExecuterTimeInterceptor implements WebRequestInterceptor { + + @Override + public void postHandle(WebRequest webRequest, ModelMap modelMap) { + // unimplemented + } + + @Override + public void afterCompletion(WebRequest webRequest, Exception e) { + // unimplemented + } + + @Override + public void preHandle(WebRequest webRequest) { + + long startTime = System.currentTimeMillis(); + webRequest.setAttribute("startTime", startTime, 0); + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/ExpressionEnrichmentController.java b/src/main/java/org/cbioportal/legacy/web/ExpressionEnrichmentController.java new file mode 100644 index 00000000000..258e9b2312c --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/ExpressionEnrichmentController.java @@ -0,0 +1,174 @@ +package org.cbioportal.legacy.web; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.ArraySchema; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; +import org.cbioportal.legacy.model.EnrichmentType; +import org.cbioportal.legacy.model.ExpressionEnrichment; +import org.cbioportal.legacy.model.GenericAssayEnrichment; +import org.cbioportal.legacy.model.GenomicEnrichment; +import org.cbioportal.legacy.model.MolecularProfileCaseIdentifier; +import org.cbioportal.legacy.service.ExpressionEnrichmentService; +import org.cbioportal.legacy.service.exception.GenericAssayNotFoundException; +import org.cbioportal.legacy.service.exception.MolecularProfileNotFoundException; +import org.cbioportal.legacy.web.config.annotation.InternalApi; +import org.cbioportal.legacy.web.parameter.MolecularProfileCasesGroupFilter; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.RequestAttribute; +import org.springframework.web.bind.annotation.RequestBody; +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.bind.annotation.RestController; + +@InternalApi +@RestController() +@RequestMapping("/api") +@Validated +@Tag(name = "Enrichments", description = " ") +public class ExpressionEnrichmentController { + @Autowired private ExpressionEnrichmentService expressionEnrichmentService; + + @PreAuthorize( + "hasPermission(#involvedCancerStudies, 'Collection', T(org.cbioportal.legacy.utils.security.AccessLevel).READ)") + @RequestMapping( + value = "/expression-enrichments/fetch", + method = RequestMethod.POST, + consumes = MediaType.APPLICATION_JSON_VALUE, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(description = "Fetch genomic enrichments in a molecular profile") + @ApiResponse( + responseCode = "200", + description = "OK", + content = + @Content( + array = @ArraySchema(schema = @Schema(implementation = GenomicEnrichment.class)))) + public ResponseEntity> fetchGenomicEnrichments( + @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface + @RequestAttribute(required = false, value = "involvedCancerStudies") + Collection involvedCancerStudies, + @Parameter(description = "Type of the enrichment e.g. SAMPLE or PATIENT") + @RequestParam(defaultValue = "SAMPLE") + EnrichmentType enrichmentType, + @Parameter( + required = true, + description = "List of groups containing sample and molecular profile identifiers") + @Valid + @RequestBody(required = false) + List groups, + @Parameter( + hidden = + true) // prevent reference to this attribute in the swagger-ui interface. this + // attribute is needed for the @PreAuthorize tag above. + @Valid + @RequestAttribute( + required = false, + value = "interceptedMolecularProfileCasesGroupFilters") + List interceptedMolecularProfileCasesGroupFilters) + throws MolecularProfileNotFoundException { + + return new ResponseEntity<>( + fetchExpressionEnrichments( + enrichmentType, interceptedMolecularProfileCasesGroupFilters, false), + HttpStatus.OK); + } + + @PreAuthorize( + "hasPermission(#involvedCancerStudies, 'Collection', T(org.cbioportal.legacy.utils.security.AccessLevel).READ)") + @RequestMapping( + value = "/generic-assay-enrichments/fetch", + method = RequestMethod.POST, + consumes = MediaType.APPLICATION_JSON_VALUE, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(description = "Fetch generic assay enrichments in a molecular profile") + @ApiResponse( + responseCode = "200", + description = "OK", + content = + @Content( + array = + @ArraySchema(schema = @Schema(implementation = GenericAssayEnrichment.class)))) + public ResponseEntity> fetchGenericAssayEnrichments( + @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface + @RequestAttribute(required = false, value = "involvedCancerStudies") + Collection involvedCancerStudies, + @Parameter(description = "Type of the enrichment e.g. SAMPLE or PATIENT") + @RequestParam(defaultValue = "SAMPLE") + EnrichmentType enrichmentType, + @Parameter( + required = true, + description = "List of groups containing sample and molecular profile identifiers") + @Valid + @RequestBody(required = false) + List groups, + @Parameter( + hidden = + true) // prevent reference to this attribute in the swagger-ui interface. this + // attribute is needed for the @PreAuthorize tag above. + @Valid + @RequestAttribute( + required = false, + value = "interceptedMolecularProfileCasesGroupFilters") + List interceptedMolecularProfileCasesGroupFilters) + throws MolecularProfileNotFoundException, + UnsupportedOperationException, + GenericAssayNotFoundException { + + return new ResponseEntity<>( + fetchExpressionEnrichments( + enrichmentType, interceptedMolecularProfileCasesGroupFilters, true), + HttpStatus.OK); + } + + private List fetchExpressionEnrichments( + EnrichmentType enrichmentType, + List interceptedMolecularProfileCasesGroupFilters, + Boolean isRequestForGenericAssayEnrichments) + throws MolecularProfileNotFoundException { + + Map> groupCaseIdentifierSet = + interceptedMolecularProfileCasesGroupFilters.stream() + .collect( + Collectors.toMap( + MolecularProfileCasesGroupFilter::getName, + MolecularProfileCasesGroupFilter::getMolecularProfileCaseIdentifiers)); + + Set molecularProfileIds = + groupCaseIdentifierSet.values().stream() + .flatMap( + molecularProfileCaseSet -> + molecularProfileCaseSet.stream() + .map(MolecularProfileCaseIdentifier::getMolecularProfileId)) + .collect(Collectors.toSet()); + + if (molecularProfileIds.size() > 1) { + throw new UnsupportedOperationException( + "Multi-study expression enrichments is not yet implemented"); + } + + if (isRequestForGenericAssayEnrichments) { + return (List) + expressionEnrichmentService.getGenericAssayNumericalEnrichments( + molecularProfileIds.iterator().next(), groupCaseIdentifierSet, enrichmentType); + } + + return (List) + expressionEnrichmentService.getGenomicEnrichments( + molecularProfileIds.iterator().next(), groupCaseIdentifierSet, enrichmentType); + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/GeneController.java b/src/main/java/org/cbioportal/legacy/web/GeneController.java new file mode 100644 index 00000000000..2d557cf1135 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/GeneController.java @@ -0,0 +1,166 @@ +package org.cbioportal.legacy.web; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.ArraySchema; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.constraints.Max; +import jakarta.validation.constraints.Min; +import jakarta.validation.constraints.Size; +import java.util.List; +import org.cbioportal.legacy.model.Gene; +import org.cbioportal.legacy.service.GeneService; +import org.cbioportal.legacy.service.exception.GeneNotFoundException; +import org.cbioportal.legacy.service.exception.GeneWithMultipleEntrezIdsException; +import org.cbioportal.legacy.web.config.PublicApiTags; +import org.cbioportal.legacy.web.config.annotation.PublicApi; +import org.cbioportal.legacy.web.parameter.Direction; +import org.cbioportal.legacy.web.parameter.GeneIdType; +import org.cbioportal.legacy.web.parameter.HeaderKeyConstants; +import org.cbioportal.legacy.web.parameter.PagingConstants; +import org.cbioportal.legacy.web.parameter.Projection; +import org.cbioportal.legacy.web.parameter.sort.GeneSortBy; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +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.bind.annotation.RestController; + +@PublicApi +@RestController +@Validated +@Tag(name = PublicApiTags.GENES, description = " ") +public class GeneController { + + @Autowired private GeneService geneService; + + @RequestMapping( + value = "/api/genes", + method = RequestMethod.GET, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(description = "Get all genes") + @ApiResponse( + responseCode = "200", + description = "OK", + content = @Content(array = @ArraySchema(schema = @Schema(implementation = Gene.class)))) + public ResponseEntity> getAllGenes( + @Parameter(description = "Search keyword that applies to hugo gene symbol of the genes") + @RequestParam(required = false) + String keyword, + @Parameter(description = "Alias of the gene") @RequestParam(required = false) String alias, + @Parameter(description = "Level of detail of the response") + @RequestParam(defaultValue = "SUMMARY") + Projection projection, + @Parameter(description = "Page size of the result list") + @Max(PagingConstants.MAX_PAGE_SIZE) + @Min(PagingConstants.MIN_PAGE_SIZE) + @RequestParam(defaultValue = PagingConstants.DEFAULT_PAGE_SIZE) + Integer pageSize, + @Parameter(description = "Page number of the result list") + @Min(PagingConstants.MIN_PAGE_NUMBER) + @RequestParam(defaultValue = PagingConstants.DEFAULT_PAGE_NUMBER) + Integer pageNumber, + @Parameter(description = "Name of the property that the result list is sorted by") + @RequestParam(required = false) + GeneSortBy sortBy, + @Parameter(description = "Direction of the sort") @RequestParam(defaultValue = "ASC") + Direction direction) { + + if (projection == Projection.META) { + HttpHeaders responseHeaders = new HttpHeaders(); + responseHeaders.add( + HeaderKeyConstants.TOTAL_COUNT, + geneService.getMetaGenes(keyword, alias).getTotalCount().toString()); + return new ResponseEntity<>(responseHeaders, HttpStatus.OK); + } else { + return new ResponseEntity<>( + geneService.getAllGenes( + keyword, + alias, + projection.name(), + pageSize, + pageNumber, + sortBy == null ? null : sortBy.getOriginalValue(), + direction.name()), + HttpStatus.OK); + } + } + + @RequestMapping( + value = "/api/genes/{geneId}", + method = RequestMethod.GET, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(description = "Get a gene") + @ApiResponse( + responseCode = "200", + description = "OK", + content = @Content(schema = @Schema(implementation = Gene.class))) + public ResponseEntity getGene( + @Parameter(required = true, description = "Entrez Gene ID or Hugo Gene Symbol e.g. 1 or A1BG") + @PathVariable + String geneId) + throws GeneNotFoundException, GeneWithMultipleEntrezIdsException { + + return new ResponseEntity<>(geneService.getGene(geneId), HttpStatus.OK); + } + + @RequestMapping( + value = "/api/genes/{geneId}/aliases", + method = RequestMethod.GET, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(description = "Get aliases of a gene") + @ApiResponse( + responseCode = "200", + description = "OK", + content = @Content(array = @ArraySchema(schema = @Schema(implementation = String.class)))) + public ResponseEntity> getAliasesOfGene( + @Parameter(required = true, description = "Entrez Gene ID or Hugo Gene Symbol e.g. 1 or A1BG") + @PathVariable + String geneId) + throws GeneNotFoundException, GeneWithMultipleEntrezIdsException { + + return new ResponseEntity<>(geneService.getAliasesOfGene(geneId), HttpStatus.OK); + } + + @RequestMapping( + value = "/api/genes/fetch", + method = RequestMethod.POST, + consumes = MediaType.APPLICATION_JSON_VALUE, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(description = "Fetch genes by ID") + @ApiResponse( + responseCode = "200", + description = "OK", + content = @Content(array = @ArraySchema(schema = @Schema(implementation = Gene.class)))) + public ResponseEntity> fetchGenes( + @RequestParam(defaultValue = "ENTREZ_GENE_ID") GeneIdType geneIdType, + @Parameter(required = true, description = "List of Gene IDs") + @Size(min = 1, max = PagingConstants.MAX_PAGE_SIZE) + @RequestBody + List geneIds, + @Parameter(description = "Level of detail of the response") + @RequestParam(defaultValue = "SUMMARY") + Projection projection) { + + if (projection == Projection.META) { + HttpHeaders responseHeaders = new HttpHeaders(); + responseHeaders.add( + HeaderKeyConstants.TOTAL_COUNT, + geneService.fetchMetaGenes(geneIds, geneIdType.name()).getTotalCount().toString()); + return new ResponseEntity<>(responseHeaders, HttpStatus.OK); + } else { + return new ResponseEntity<>( + geneService.fetchGenes(geneIds, geneIdType.name(), projection.name()), HttpStatus.OK); + } + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/GenePanelController.java b/src/main/java/org/cbioportal/legacy/web/GenePanelController.java new file mode 100644 index 00000000000..7d42569aca6 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/GenePanelController.java @@ -0,0 +1,155 @@ +package org.cbioportal.legacy.web; + +import io.swagger.v3.oas.annotations.Hidden; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.ArraySchema; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.constraints.Max; +import jakarta.validation.constraints.Min; +import jakarta.validation.constraints.Size; +import java.util.List; +import org.cbioportal.legacy.model.GenePanel; +import org.cbioportal.legacy.service.GenePanelService; +import org.cbioportal.legacy.service.exception.GenePanelNotFoundException; +import org.cbioportal.legacy.web.config.PublicApiTags; +import org.cbioportal.legacy.web.config.annotation.PublicApi; +import org.cbioportal.legacy.web.parameter.Direction; +import org.cbioportal.legacy.web.parameter.HeaderKeyConstants; +import org.cbioportal.legacy.web.parameter.PagingConstants; +import org.cbioportal.legacy.web.parameter.Projection; +import org.cbioportal.legacy.web.parameter.sort.GenePanelSortBy; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +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.bind.annotation.RestController; + +@PublicApi +@RestController() +@RequestMapping("/api") +@Validated +@Tag(name = PublicApiTags.GENE_PANELS, description = " ") +public class GenePanelController { + + @Autowired private GenePanelService genePanelService; + + @Hidden + @RequestMapping( + value = "/gene-panels/", + method = RequestMethod.GET, + produces = MediaType.APPLICATION_JSON_VALUE) + public ResponseEntity> getAllGenePanels_trailing( + @RequestParam(defaultValue = "SUMMARY") Projection projection, + @Parameter(description = "Page size of the result list") + @Max(PagingConstants.MAX_PAGE_SIZE) + @Min(PagingConstants.MIN_PAGE_SIZE) + @RequestParam(defaultValue = PagingConstants.DEFAULT_PAGE_SIZE) + Integer pageSize, + @Parameter(description = "Page number of the result list") + @Min(PagingConstants.MIN_PAGE_NUMBER) + @RequestParam(defaultValue = PagingConstants.DEFAULT_PAGE_NUMBER) + Integer pageNumber, + @RequestParam(required = false) GenePanelSortBy sortBy, + @Parameter(description = "Direction of the sort") @RequestParam(defaultValue = "ASC") + Direction direction) { + return getAllGenePanels(projection, pageSize, pageNumber, sortBy, direction); + } + + @RequestMapping( + value = "/gene-panels", + method = RequestMethod.GET, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(description = "Get all gene panels") + @ApiResponse( + responseCode = "200", + description = "OK", + content = @Content(array = @ArraySchema(schema = @Schema(implementation = GenePanel.class)))) + public ResponseEntity> getAllGenePanels( + @Parameter(description = "Level of detail of the response") + @RequestParam(defaultValue = "SUMMARY") + Projection projection, + @Parameter(description = "Page size of the result list") + @Max(PagingConstants.MAX_PAGE_SIZE) + @Min(PagingConstants.MIN_PAGE_SIZE) + @RequestParam(defaultValue = PagingConstants.DEFAULT_PAGE_SIZE) + Integer pageSize, + @Parameter(description = "Page number of the result list") + @Min(PagingConstants.MIN_PAGE_NUMBER) + @RequestParam(defaultValue = PagingConstants.DEFAULT_PAGE_NUMBER) + Integer pageNumber, + @Parameter(description = "Name of the property that the result list is sorted by") + @RequestParam(required = false) + GenePanelSortBy sortBy, + @Parameter(description = "Direction of the sort") @RequestParam(defaultValue = "ASC") + Direction direction) { + + if (projection == Projection.META) { + HttpHeaders responseHeaders = new HttpHeaders(); + responseHeaders.add( + HeaderKeyConstants.TOTAL_COUNT, + genePanelService.getMetaGenePanels().getTotalCount().toString()); + return new ResponseEntity<>(responseHeaders, HttpStatus.OK); + } else { + return new ResponseEntity<>( + genePanelService.getAllGenePanels( + projection.name(), + pageSize, + pageNumber, + sortBy == null ? null : sortBy.getOriginalValue(), + direction.name()), + HttpStatus.OK); + } + } + + @RequestMapping( + value = "/gene-panels/{genePanelId}", + method = RequestMethod.GET, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(description = "Get gene panel") + @ApiResponse( + responseCode = "200", + description = "OK", + content = @Content(schema = @Schema(implementation = GenePanel.class))) + public ResponseEntity getGenePanel( + @Parameter(required = true, description = "Gene Panel ID e.g. NSCLC_UNITO_2016_PANEL") + @PathVariable + String genePanelId) + throws GenePanelNotFoundException { + + return new ResponseEntity<>(genePanelService.getGenePanel(genePanelId), HttpStatus.OK); + } + + @RequestMapping( + value = "/gene-panels/fetch", + method = RequestMethod.POST, + consumes = MediaType.APPLICATION_JSON_VALUE, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(description = "Get gene panel") + @ApiResponse( + responseCode = "200", + description = "OK", + content = @Content(array = @ArraySchema(schema = @Schema(implementation = GenePanel.class)))) + public ResponseEntity> fetchGenePanels( + @Parameter(required = true, description = "List of Gene Panel IDs") + @Size(min = 1, max = PagingConstants.MAX_PAGE_SIZE) + @RequestBody + List genePanelIds, + @Parameter(description = "Level of detail of the response") + @RequestParam(defaultValue = "SUMMARY") + Projection projection) { + + return new ResponseEntity<>( + genePanelService.fetchGenePanels(genePanelIds, projection.name()), HttpStatus.OK); + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/GenePanelDataController.java b/src/main/java/org/cbioportal/legacy/web/GenePanelDataController.java new file mode 100644 index 00000000000..64113148d23 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/GenePanelDataController.java @@ -0,0 +1,151 @@ +package org.cbioportal.legacy.web; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.ArraySchema; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import java.util.Collection; +import java.util.HashSet; +import java.util.List; +import java.util.stream.Collectors; +import org.cbioportal.legacy.model.GenePanelData; +import org.cbioportal.legacy.model.MolecularProfileCaseIdentifier; +import org.cbioportal.legacy.service.GenePanelService; +import org.cbioportal.legacy.service.exception.MolecularProfileNotFoundException; +import org.cbioportal.legacy.web.config.PublicApiTags; +import org.cbioportal.legacy.web.config.annotation.PublicApi; +import org.cbioportal.legacy.web.parameter.GenePanelDataFilter; +import org.cbioportal.legacy.web.parameter.GenePanelDataMultipleStudyFilter; +import org.cbioportal.legacy.web.parameter.SampleMolecularIdentifier; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.util.CollectionUtils; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestAttribute; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RestController; + +@PublicApi +@RestController +@RequestMapping("/api") +@Validated +@Tag(name = PublicApiTags.GENE_PANEL_DATA, description = " ") +public class GenePanelDataController { + + @Autowired private GenePanelService genePanelService; + + @PreAuthorize( + "hasPermission(#molecularProfileId, 'MolecularProfileId', T(org.cbioportal.legacy.utils.security.AccessLevel).READ)") + @RequestMapping( + value = "/molecular-profiles/{molecularProfileId}/gene-panel-data/fetch", + method = RequestMethod.POST, + consumes = MediaType.APPLICATION_JSON_VALUE, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(description = "Get gene panel data") + @ApiResponse( + responseCode = "200", + description = "OK", + content = + @Content(array = @ArraySchema(schema = @Schema(implementation = GenePanelData.class)))) + public ResponseEntity> getGenePanelData( + @Parameter( + required = true, + description = "Molecular Profile ID e.g. nsclc_unito_2016_mutations") + @PathVariable + String molecularProfileId, + @Parameter( + required = true, + description = "List of Sample IDs/Sample List ID and Entrez Gene IDs") + @Valid + @RequestBody + GenePanelDataFilter genePanelDataFilter) + throws MolecularProfileNotFoundException { + + List genePanelDataList; + if (genePanelDataFilter.getSampleListId() != null) { + genePanelDataList = + genePanelService.getGenePanelData( + molecularProfileId, genePanelDataFilter.getSampleListId()); + } else { + genePanelDataList = + genePanelService.fetchGenePanelData( + molecularProfileId, genePanelDataFilter.getSampleIds()); + } + + return new ResponseEntity<>(genePanelDataList, HttpStatus.OK); + } + + @PreAuthorize( + "hasPermission(#involvedCancerStudies, 'Collection', T(org.cbioportal.legacy.utils.security.AccessLevel).READ)") + @RequestMapping( + value = "/gene-panel-data/fetch", + method = RequestMethod.POST, + consumes = MediaType.APPLICATION_JSON_VALUE, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(description = "Fetch gene panel data") + @ApiResponse( + responseCode = "200", + description = "OK", + content = + @Content(array = @ArraySchema(schema = @Schema(implementation = GenePanelData.class)))) + public ResponseEntity> fetchGenePanelDataInMultipleMolecularProfiles( + @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface + @RequestAttribute(required = false, value = "involvedCancerStudies") + Collection involvedCancerStudies, + @Parameter( + hidden = + true) // prevent reference to this attribute in the swagger-ui interface. this + // attribute is needed for the @PreAuthorize tag above. + @Valid + @RequestAttribute(required = false, value = "interceptedGenePanelDataMultipleStudyFilter") + GenePanelDataMultipleStudyFilter interceptedGenePanelDataMultipleStudyFilter, + @Parameter(required = true, description = "Gene panel data filter object") + @RequestBody(required = false) + GenePanelDataMultipleStudyFilter genePanelDataMultipleStudyFilter) { + + List genePanelDataList; + if (CollectionUtils.isEmpty( + interceptedGenePanelDataMultipleStudyFilter.getMolecularProfileIds())) { + + List molecularSampleIdentifier = + interceptedGenePanelDataMultipleStudyFilter.getSampleMolecularIdentifiers(); + + if (molecularSampleIdentifier == null) { + return ResponseEntity.ok(List.of()); + } + + List molecularProfileSampleIdentifiers = + molecularSampleIdentifier.stream() + .map( + sampleMolecularIdentifier -> { + MolecularProfileCaseIdentifier profileCaseIdentifier = + new MolecularProfileCaseIdentifier(); + profileCaseIdentifier.setMolecularProfileId( + sampleMolecularIdentifier.getMolecularProfileId()); + profileCaseIdentifier.setCaseId(sampleMolecularIdentifier.getSampleId()); + return profileCaseIdentifier; + }) + .collect(Collectors.toList()); + + genePanelDataList = + genePanelService.fetchGenePanelDataInMultipleMolecularProfiles( + molecularProfileSampleIdentifiers); + } else { + genePanelDataList = + genePanelService.fetchGenePanelDataByMolecularProfileIds( + new HashSet<>(interceptedGenePanelDataMultipleStudyFilter.getMolecularProfileIds())); + } + + return ResponseEntity.ok(genePanelDataList); + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/GeneralControllerAdvice.java b/src/main/java/org/cbioportal/legacy/web/GeneralControllerAdvice.java new file mode 100644 index 00000000000..c4c5347f413 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/GeneralControllerAdvice.java @@ -0,0 +1,38 @@ +package org.cbioportal.legacy.web; + +import org.springframework.core.MethodParameter; +import org.springframework.http.MediaType; +import org.springframework.http.converter.HttpMessageConverter; +import org.springframework.http.server.ServerHttpRequest; +import org.springframework.http.server.ServerHttpResponse; +import org.springframework.http.server.ServletServerHttpRequest; +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice; + +@ControllerAdvice +public class GeneralControllerAdvice implements ResponseBodyAdvice { + + @Override + public boolean supports( + MethodParameter returnType, Class> converterType) { + return true; + } + + @Override + public Object beforeBodyWrite( + Object body, + MethodParameter returnType, + MediaType selectedContentType, + Class> selectedConverterType, + ServerHttpRequest request, + ServerHttpResponse response) { + ServletServerHttpRequest servletServerRequest = (ServletServerHttpRequest) request; + + // report the procesing time of all api endpoints to aid in benchmarking as we transition + // to clickhouse + long startTime = (long) servletServerRequest.getServletRequest().getAttribute("startTime"); + long timeElapsed = System.currentTimeMillis() - startTime; + response.getHeaders().add("Elapsed-Time", String.valueOf(timeElapsed)); + return body; + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/GenericAssayController.java b/src/main/java/org/cbioportal/legacy/web/GenericAssayController.java new file mode 100644 index 00000000000..25b3d25ae43 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/GenericAssayController.java @@ -0,0 +1,133 @@ +package org.cbioportal.legacy.web; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.ArraySchema; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import java.util.Arrays; +import java.util.List; +import org.cbioportal.legacy.model.meta.GenericAssayMeta; +import org.cbioportal.legacy.service.GenericAssayService; +import org.cbioportal.legacy.service.exception.GenericAssayNotFoundException; +import org.cbioportal.legacy.web.config.PublicApiTags; +import org.cbioportal.legacy.web.config.annotation.PublicApi; +import org.cbioportal.legacy.web.parameter.GenericAssayMetaFilter; +import org.cbioportal.legacy.web.parameter.Projection; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +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.bind.annotation.RestController; + +@PublicApi +@RestController() +@RequestMapping("/api") +@Validated +@Tag(name = PublicApiTags.GENERIC_ASSAYS, description = " ") +public class GenericAssayController { + + @Autowired private GenericAssayService genericAssayService; + + // PreAuthorize is removed for performance reason + @RequestMapping( + value = "/generic_assay_meta/fetch", + method = RequestMethod.POST, + consumes = MediaType.APPLICATION_JSON_VALUE, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(description = "Fetch meta data for generic-assay by ID") + @ApiResponse( + responseCode = "200", + description = "OK", + content = + @Content(array = @ArraySchema(schema = @Schema(implementation = GenericAssayMeta.class)))) + public ResponseEntity> fetchGenericAssayMeta( + @Parameter(required = true, description = "List of Molecular Profile ID or List of Stable ID") + @Valid + @RequestBody + GenericAssayMetaFilter genericAssayMetaFilter, + @Parameter(description = "Level of detail of the response") + @RequestParam(defaultValue = "SUMMARY") + Projection projection) + throws GenericAssayNotFoundException { + List result; + + if (genericAssayMetaFilter.getGenericAssayStableIds() == null) { + result = + genericAssayService.getGenericAssayMetaByStableIdsAndMolecularIds( + null, genericAssayMetaFilter.getMolecularProfileIds(), projection.name()); + } else if (genericAssayMetaFilter.getMolecularProfileIds() == null) { + result = + genericAssayService.getGenericAssayMetaByStableIdsAndMolecularIds( + genericAssayMetaFilter.getGenericAssayStableIds(), null, projection.name()); + } else { + result = + genericAssayService.getGenericAssayMetaByStableIdsAndMolecularIds( + genericAssayMetaFilter.getGenericAssayStableIds(), + genericAssayMetaFilter.getMolecularProfileIds(), + projection.name()); + } + return new ResponseEntity<>(result, HttpStatus.OK); + } + + // PreAuthorize is removed for performance reason + @RequestMapping( + value = "/generic-assay-meta/{molecularProfileId}", + method = RequestMethod.GET, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(description = "Fetch meta data for generic-assay by ID") + @ApiResponse( + responseCode = "200", + description = "OK", + content = + @Content(array = @ArraySchema(schema = @Schema(implementation = GenericAssayMeta.class)))) + public ResponseEntity> getGenericAssayMeta( + @Parameter(required = true, description = "Molecular Profile ID") @PathVariable + String molecularProfileId, + @Parameter(description = "Level of detail of the response") + @RequestParam(defaultValue = "SUMMARY") + Projection projection) + throws GenericAssayNotFoundException { + List result; + + result = + genericAssayService.getGenericAssayMetaByStableIdsAndMolecularIds( + null, Arrays.asList(molecularProfileId), projection.name()); + + return new ResponseEntity<>(result, HttpStatus.OK); + } + + @RequestMapping( + value = "/generic-assay-meta/generic-assay/{genericAssayStableId}", + method = RequestMethod.GET, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(description = "Fetch meta data for generic-assay by ID") + @ApiResponse( + responseCode = "200", + description = "OK", + content = + @Content(array = @ArraySchema(schema = @Schema(implementation = GenericAssayMeta.class)))) + public ResponseEntity> getGenericAssayMeta_ga( + @Parameter(required = false, description = "Generic Assay stable ID") @PathVariable + String genericAssayStableId, + @Parameter(description = "Level of detail of the response") + @RequestParam(defaultValue = "SUMMARY") + Projection projection) + throws GenericAssayNotFoundException { + List result; + result = + genericAssayService.getGenericAssayMetaByStableIdsAndMolecularIds( + Arrays.asList(genericAssayStableId), null, projection.name()); + + return new ResponseEntity<>(result, HttpStatus.OK); + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/GenericAssayDataController.java b/src/main/java/org/cbioportal/legacy/web/GenericAssayDataController.java new file mode 100644 index 00000000000..91e7104bc35 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/GenericAssayDataController.java @@ -0,0 +1,231 @@ +package org.cbioportal.legacy.web; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.ArraySchema; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; +import java.util.stream.Collectors; +import org.apache.commons.lang3.StringUtils; +import org.cbioportal.legacy.model.GenericAssayData; +import org.cbioportal.legacy.service.GenericAssayService; +import org.cbioportal.legacy.service.exception.MolecularProfileNotFoundException; +import org.cbioportal.legacy.web.config.PublicApiTags; +import org.cbioportal.legacy.web.config.annotation.PublicApi; +import org.cbioportal.legacy.web.parameter.GenericAssayDataMultipleStudyFilter; +import org.cbioportal.legacy.web.parameter.GenericAssayFilter; +import org.cbioportal.legacy.web.parameter.HeaderKeyConstants; +import org.cbioportal.legacy.web.parameter.Projection; +import org.cbioportal.legacy.web.parameter.SampleMolecularIdentifier; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestAttribute; +import org.springframework.web.bind.annotation.RequestBody; +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.bind.annotation.RestController; + +@PublicApi +@RestController +@RequestMapping("/api") +@Validated +@Tag(name = PublicApiTags.GENERIC_ASSAY_DATA, description = " ") +public class GenericAssayDataController { + + @Autowired private GenericAssayService genericAssayService; + + @PreAuthorize( + "hasPermission(#molecularProfileId, 'MolecularProfileId', T(org.cbioportal.legacy.utils.security.AccessLevel).READ)") + @RequestMapping( + value = "/generic-assay-data/{molecularProfileId}/generic-assay/{genericAssayStableId}", + method = RequestMethod.GET, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(description = "Get generic_assay_data in a molecular profile") + @ApiResponse( + responseCode = "200", + description = "OK", + content = + @Content(array = @ArraySchema(schema = @Schema(implementation = GenericAssayData.class)))) + public ResponseEntity> getGenericAssayDataInMolecularProfile( + @Parameter(required = true, description = "Molecular Profile ID") @PathVariable + String molecularProfileId, + @Parameter(required = true, description = "Generic Assay stable ID") @PathVariable + String genericAssayStableId, + @Parameter(description = "Level of detail of the response") + @RequestParam(defaultValue = "SUMMARY") + Projection projection) + throws MolecularProfileNotFoundException { + + List result; + result = + filterEmptyGenericAssayData( + genericAssayService.fetchGenericAssayData( + molecularProfileId, null, Arrays.asList(genericAssayStableId), projection.name())); + + if (projection == Projection.META) { + HttpHeaders responseHeaders = new HttpHeaders(); + responseHeaders.add(HeaderKeyConstants.TOTAL_COUNT, String.valueOf(result.size())); + return new ResponseEntity<>(responseHeaders, HttpStatus.OK); + } else { + return new ResponseEntity<>(result, HttpStatus.OK); + } + } + + @PreAuthorize( + "hasPermission(#molecularProfileId, 'MolecularProfileId', T(org.cbioportal.legacy.utils.security.AccessLevel).READ)") + @RequestMapping( + value = "/generic_assay_data/{molecularProfileId}/fetch", + method = RequestMethod.POST, + consumes = MediaType.APPLICATION_JSON_VALUE, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(description = "fetch generic_assay_data in a molecular profile") + @ApiResponse( + responseCode = "200", + description = "OK", + content = + @Content(array = @ArraySchema(schema = @Schema(implementation = GenericAssayData.class)))) + public ResponseEntity> fetchGenericAssayDataInMolecularProfile( + @Parameter(required = true, description = "Molecular Profile ID") @PathVariable + String molecularProfileId, + @Parameter( + required = true, + description = "List of Sample IDs/Sample List ID and Generic Assay IDs") + @Valid + @RequestBody + GenericAssayFilter genericAssayDataFilter, + @Parameter(description = "Level of detail of the response") + @RequestParam(defaultValue = "SUMMARY") + Projection projection) + throws MolecularProfileNotFoundException { + + List result; + if (genericAssayDataFilter.getSampleListId() != null) { + result = + filterEmptyGenericAssayData( + genericAssayService.getGenericAssayData( + molecularProfileId, + genericAssayDataFilter.getSampleListId(), + genericAssayDataFilter.getGenericAssayStableIds(), + projection.name())); + } else { + result = + filterEmptyGenericAssayData( + genericAssayService.fetchGenericAssayData( + molecularProfileId, + genericAssayDataFilter.getSampleIds(), + genericAssayDataFilter.getGenericAssayStableIds(), + projection.name())); + } + + if (projection == Projection.META) { + HttpHeaders responseHeaders = new HttpHeaders(); + responseHeaders.add(HeaderKeyConstants.TOTAL_COUNT, String.valueOf(result.size())); + return new ResponseEntity<>(responseHeaders, HttpStatus.OK); + } else { + return new ResponseEntity<>(result, HttpStatus.OK); + } + } + + @PreAuthorize( + "hasPermission(#involvedCancerStudies, 'Collection', T(org.cbioportal.legacy.utils.security.AccessLevel).READ)") + @RequestMapping( + value = "/generic_assay_data/fetch", + method = RequestMethod.POST, + consumes = MediaType.APPLICATION_JSON_VALUE, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(description = "Fetch generic_assay_data") + @ApiResponse( + responseCode = "200", + description = "OK", + content = + @Content(array = @ArraySchema(schema = @Schema(implementation = GenericAssayData.class)))) + public ResponseEntity> fetchGenericAssayDataInMultipleMolecularProfiles( + @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface + @RequestAttribute(required = false, value = "involvedCancerStudies") + Collection involvedCancerStudies, + @Parameter( + hidden = + true) // prevent reference to this attribute in the swagger-ui interface. this + // attribute is needed for the @PreAuthorize tag above. + @RequestAttribute( + required = false, + value = "interceptedGenericAssayDataMultipleStudyFilter") + GenericAssayDataMultipleStudyFilter interceptedGenericAssayDataMultipleStudyFilter, + @Parameter( + required = true, + description = + "List of Molecular Profile ID and Sample ID pairs or List of Molecular" + + "Profile IDs and Generic Assay IDs") + @Valid + @RequestBody(required = false) + GenericAssayDataMultipleStudyFilter genericAssayDataMultipleStudyFilter, + @Parameter(description = "Level of detail of the response") + @RequestParam(defaultValue = "SUMMARY") + Projection projection) + throws MolecularProfileNotFoundException { + + List result; + if (interceptedGenericAssayDataMultipleStudyFilter.getMolecularProfileIds() != null) { + result = + filterEmptyGenericAssayData( + genericAssayService.fetchGenericAssayData( + interceptedGenericAssayDataMultipleStudyFilter.getMolecularProfileIds(), + null, + interceptedGenericAssayDataMultipleStudyFilter.getGenericAssayStableIds(), + projection.name())); + } else { + + List molecularProfileIds = new ArrayList<>(); + List sampleIds = new ArrayList<>(); + extractMolecularProfileAndSampleIds( + interceptedGenericAssayDataMultipleStudyFilter, molecularProfileIds, sampleIds); + result = + filterEmptyGenericAssayData( + genericAssayService.fetchGenericAssayData( + molecularProfileIds, + sampleIds, + interceptedGenericAssayDataMultipleStudyFilter.getGenericAssayStableIds(), + projection.name())); + } + + if (projection == Projection.META) { + HttpHeaders responseHeaders = new HttpHeaders(); + responseHeaders.add(HeaderKeyConstants.TOTAL_COUNT, String.valueOf(result.size())); + return new ResponseEntity<>(responseHeaders, HttpStatus.OK); + } else { + return new ResponseEntity<>(result, HttpStatus.OK); + } + } + + private void extractMolecularProfileAndSampleIds( + GenericAssayDataMultipleStudyFilter molecularDataMultipleStudyFilter, + List molecularProfileIds, + List sampleIds) { + for (SampleMolecularIdentifier sampleMolecularIdentifier : + molecularDataMultipleStudyFilter.getSampleMolecularIdentifiers()) { + molecularProfileIds.add(sampleMolecularIdentifier.getMolecularProfileId()); + sampleIds.add(sampleMolecularIdentifier.getSampleId()); + } + } + + private List filterEmptyGenericAssayData( + List genericAssayDataList) { + return genericAssayDataList.stream() + .filter(g -> StringUtils.isNotEmpty(g.getValue()) && !g.getValue().equals("NA")) + .collect(Collectors.toList()); + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/GenericAssayEnrichmentController.java b/src/main/java/org/cbioportal/legacy/web/GenericAssayEnrichmentController.java new file mode 100644 index 00000000000..51f20c917b5 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/GenericAssayEnrichmentController.java @@ -0,0 +1,179 @@ +package org.cbioportal.legacy.web; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.ArraySchema; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; +import org.cbioportal.legacy.model.EnrichmentType; +import org.cbioportal.legacy.model.GenericAssayBinaryEnrichment; +import org.cbioportal.legacy.model.GenericAssayCategoricalEnrichment; +import org.cbioportal.legacy.model.MolecularProfileCaseIdentifier; +import org.cbioportal.legacy.service.ExpressionEnrichmentService; +import org.cbioportal.legacy.service.exception.MolecularProfileNotFoundException; +import org.cbioportal.legacy.web.config.annotation.InternalApi; +import org.cbioportal.legacy.web.parameter.MolecularProfileCasesGroupFilter; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.RequestAttribute; +import org.springframework.web.bind.annotation.RequestBody; +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.bind.annotation.RestController; + +@InternalApi +@RestController +@Validated +@Tag(name = "Generic Assay Enrichment Data", description = " ") +public class GenericAssayEnrichmentController { + @Autowired private ExpressionEnrichmentService expressionEnrichmentService; + + @PreAuthorize( + "hasPermission(#involvedCancerStudies, 'Collection', T(org.cbioportal.legacy.utils.security.AccessLevel).READ)") + @RequestMapping( + value = "/api/generic-assay-categorical-enrichments/fetch", + method = RequestMethod.POST, + consumes = MediaType.APPLICATION_JSON_VALUE, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation( + description = "Fetch generic assay categorical data enrichments in a molecular profile") + @ApiResponse( + responseCode = "200", + description = "OK", + content = + @Content( + array = + @ArraySchema( + schema = @Schema(implementation = GenericAssayCategoricalEnrichment.class)))) + public ResponseEntity> + fetchGenericAssayCategoricalDataEnrichmentInMultipleMolecularProfiles( + @Parameter(hidden = true) + @RequestAttribute(required = false, value = "involvedCancerStudies") + Collection involvedCancerStudies, + @Parameter(description = "Type of the enrichment e.g. SAMPLE or PATIENT") + @RequestParam(defaultValue = "SAMPLE") + EnrichmentType enrichmentType, + @Parameter( + required = true, + description = + "List of groups containing sample and molecular profile identifiers") + @Valid + @RequestBody(required = false) + List groups, + @Parameter(hidden = true) + @Valid + @RequestAttribute( + required = false, + value = "interceptedMolecularProfileCasesGroupFilters") + List interceptedMolecularProfileCasesGroupFilters) + throws MolecularProfileNotFoundException, UnsupportedOperationException { + + return new ResponseEntity<>( + fetchExpressionEnrichments(enrichmentType, interceptedMolecularProfileCasesGroupFilters), + HttpStatus.OK); + } + + @PreAuthorize( + "hasPermission(#involvedCancerStudies, 'Collection', T(org.cbioportal.legacy.utils.security.AccessLevel).READ)") + @RequestMapping( + value = "/api/generic-assay-binary-enrichments/fetch", + method = RequestMethod.POST, + consumes = MediaType.APPLICATION_JSON_VALUE, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(description = "Fetch generic assay binary data enrichments in a molecular profile") + @ApiResponse( + responseCode = "200", + description = "OK", + content = + @Content( + array = + @ArraySchema( + schema = @Schema(implementation = GenericAssayBinaryEnrichment.class)))) + public ResponseEntity> + fetchGenericAssayBinaryDataEnrichmentInMultipleMolecularProfiles( + @Parameter(hidden = true) + @RequestAttribute(required = false, value = "involvedCancerStudies") + Collection involvedCancerStudies, + @Parameter(description = "Type of the enrichment e.g. SAMPLE or PATIENT") + @RequestParam(defaultValue = "SAMPLE") + EnrichmentType enrichmentType, + @Parameter( + required = true, + description = + "List of groups containing sample and molecular profile identifiers") + @Valid + @RequestBody(required = false) + List groups, + @Parameter(hidden = true) + @Valid + @RequestAttribute( + required = false, + value = "interceptedMolecularProfileCasesGroupFilters") + List interceptedMolecularProfileCasesGroupFilters) + throws MolecularProfileNotFoundException, UnsupportedOperationException { + + Map> groupCaseIdentifierSet = + interceptedMolecularProfileCasesGroupFilters.stream() + .collect( + Collectors.toMap( + MolecularProfileCasesGroupFilter::getName, + MolecularProfileCasesGroupFilter::getMolecularProfileCaseIdentifiers)); + + Set molecularProfileIds = + groupCaseIdentifierSet.values().stream() + .flatMap( + molecularProfileCaseSet -> + molecularProfileCaseSet.stream() + .map(MolecularProfileCaseIdentifier::getMolecularProfileId)) + .collect(Collectors.toSet()); + + if (molecularProfileIds.size() > 1) { + throw new UnsupportedOperationException("Multi-study enrichments is not yet implemented"); + } + + return new ResponseEntity<>( + expressionEnrichmentService.getGenericAssayBinaryEnrichments( + molecularProfileIds.iterator().next(), groupCaseIdentifierSet, enrichmentType), + HttpStatus.OK); + } + + private List fetchExpressionEnrichments( + EnrichmentType enrichmentType, + List interceptedMolecularProfileCasesGroupFilters) + throws MolecularProfileNotFoundException { + Map> groupCaseIdentifierSet = + interceptedMolecularProfileCasesGroupFilters.stream() + .collect( + Collectors.toMap( + MolecularProfileCasesGroupFilter::getName, + MolecularProfileCasesGroupFilter::getMolecularProfileCaseIdentifiers)); + + Set molecularProfileIds = + groupCaseIdentifierSet.values().stream() + .flatMap( + molecularProfileCaseSet -> + molecularProfileCaseSet.stream() + .map(MolecularProfileCaseIdentifier::getMolecularProfileId)) + .collect(Collectors.toSet()); + + if (molecularProfileIds.size() > 1) { + throw new UnsupportedOperationException( + "Multi-study expression enrichments is not yet implemented"); + } + return expressionEnrichmentService.getGenericAssayCategoricalEnrichments( + molecularProfileIds.iterator().next(), groupCaseIdentifierSet, enrichmentType); + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/GenesetController.java b/src/main/java/org/cbioportal/legacy/web/GenesetController.java new file mode 100644 index 00000000000..f17f4888916 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/GenesetController.java @@ -0,0 +1,126 @@ +package org.cbioportal.legacy.web; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.ArraySchema; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.constraints.Max; +import jakarta.validation.constraints.Min; +import jakarta.validation.constraints.Size; +import java.util.List; +import org.cbioportal.legacy.model.Geneset; +import org.cbioportal.legacy.service.GenesetService; +import org.cbioportal.legacy.service.exception.GenesetNotFoundException; +import org.cbioportal.legacy.web.config.annotation.InternalApi; +import org.cbioportal.legacy.web.parameter.HeaderKeyConstants; +import org.cbioportal.legacy.web.parameter.PagingConstants; +import org.cbioportal.legacy.web.parameter.Projection; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +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.bind.annotation.RestController; + +@InternalApi +@RestController +@Validated +@Tag(name = "Gene Sets", description = " ") +public class GenesetController { + + @Autowired private GenesetService genesetService; + + @RequestMapping( + value = "/api/genesets", + method = RequestMethod.GET, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(description = "Get all gene sets") + @ApiResponse( + responseCode = "200", + description = "OK", + content = @Content(array = @ArraySchema(schema = @Schema(implementation = Geneset.class)))) + public ResponseEntity> getAllGenesets( + @Parameter(description = "Level of detail of the response") + @RequestParam(defaultValue = "SUMMARY") + Projection projection, + @Parameter(description = "Page size of the result list") + @Max(Integer.MAX_VALUE) + @Min(PagingConstants.MIN_PAGE_SIZE) + @RequestParam(defaultValue = PagingConstants.DEFAULT_PAGE_SIZE) + Integer pageSize, + @Parameter(description = "Page number of the result list") + @Min(PagingConstants.MIN_PAGE_NUMBER) + @RequestParam(defaultValue = PagingConstants.DEFAULT_PAGE_NUMBER) + Integer pageNumber) { + + if (projection == Projection.META) { + HttpHeaders responseHeaders = new HttpHeaders(); + responseHeaders.add( + HeaderKeyConstants.TOTAL_COUNT, + genesetService.getMetaGenesets().getTotalCount().toString()); + return new ResponseEntity<>(responseHeaders, HttpStatus.OK); + } else { + return new ResponseEntity<>( + genesetService.getAllGenesets(projection.name(), pageSize, pageNumber), HttpStatus.OK); + } + } + + @RequestMapping( + value = "/api/genesets/{genesetId}", + method = RequestMethod.GET, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(description = "Get a gene set") + @ApiResponse( + responseCode = "200", + description = "OK", + content = @Content(schema = @Schema(implementation = Geneset.class))) + public ResponseEntity getGeneset( + @Parameter(required = true, description = "Gene set ID e.g. GNF2_ZAP70") @PathVariable + String genesetId) + throws GenesetNotFoundException { + + return new ResponseEntity<>(genesetService.getGeneset(genesetId), HttpStatus.OK); + } + + @RequestMapping( + value = "/api/genesets/fetch", + method = RequestMethod.POST, + consumes = MediaType.APPLICATION_JSON_VALUE, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(description = "Fetch gene sets by ID") + @ApiResponse( + responseCode = "200", + description = "OK", + content = @Content(array = @ArraySchema(schema = @Schema(implementation = Geneset.class)))) + public ResponseEntity> fetchGenesets( + @Parameter(required = true, description = "List of Geneset IDs") + @Size(min = 1, max = PagingConstants.MAX_PAGE_SIZE) + @RequestBody + List genesetIds) { + + return new ResponseEntity<>(genesetService.fetchGenesets(genesetIds), HttpStatus.OK); + } + + @RequestMapping( + value = "/api/genesets/version", + method = RequestMethod.GET, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(description = "Get the geneset version") + @ApiResponse( + responseCode = "200", + description = "OK", + content = @Content(schema = @Schema(implementation = String.class))) + public ResponseEntity getGenesetVersion() { + + return new ResponseEntity<>("\"" + genesetService.getGenesetVersion() + "\"", HttpStatus.OK); + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/GenesetCorrelationController.java b/src/main/java/org/cbioportal/legacy/web/GenesetCorrelationController.java new file mode 100644 index 00000000000..da9be707164 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/GenesetCorrelationController.java @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2016 The Hyve B.V. + * This code is licensed under the GNU Affero General Public License (AGPL), + * version 3, or (at your option) any later version. + */ + +/* + * This file is part of cBioPortal. + * + * cBioPortal is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package org.cbioportal.legacy.web; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.ArraySchema; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.constraints.Max; +import jakarta.validation.constraints.Min; +import java.util.List; +import org.cbioportal.legacy.model.GenesetCorrelation; +import org.cbioportal.legacy.service.GenesetCorrelationService; +import org.cbioportal.legacy.service.exception.GenesetNotFoundException; +import org.cbioportal.legacy.service.exception.MolecularProfileNotFoundException; +import org.cbioportal.legacy.service.exception.SampleListNotFoundException; +import org.cbioportal.legacy.web.config.annotation.InternalApi; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +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.bind.annotation.RestController; + +@InternalApi +@RestController() +@RequestMapping("/api") +@Validated +@Tag(name = "Gene Set Correlation", description = " ") +public class GenesetCorrelationController { + + @Autowired private GenesetCorrelationService genesetCorrelationService; + + @PreAuthorize( + "hasPermission(#geneticProfileId, 'GeneticProfileId', T(org.cbioportal.legacy.utils.security.AccessLevel).READ)") + @RequestMapping( + value = "/genesets/{genesetId}/expression-correlation/fetch", + method = RequestMethod.POST, + consumes = MediaType.APPLICATION_JSON_VALUE, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation( + description = + "Get the genes in a gene set that have expression correlated to the gene set scores (calculated using Spearman's correlation)") + @ApiResponse( + responseCode = "200", + description = "OK", + content = + @Content( + array = @ArraySchema(schema = @Schema(implementation = GenesetCorrelation.class)))) + public ResponseEntity> fetchCorrelatedGenes( + @Parameter(required = true, description = "Gene set ID, e.g. HINATA_NFKB_MATRIX.") + @PathVariable + String genesetId, + @Parameter(required = true, description = "Genetic Profile ID e.g. gbm_tcga_gsva_scores") + @RequestParam + String geneticProfileId, + @Parameter( + description = + "Correlation threshold (for absolute correlation value, Spearman correlation)") + @Max(1) + @Min(0) + @RequestParam(defaultValue = "0.3") + Double correlationThreshold, + @Parameter( + description = + "Identifier of pre-defined sample list with samples to query, e.g. brca_tcga_all") + @RequestParam(required = false) + String sampleListId, + @Parameter( + description = + "Fill this one if you want to specify a subset of samples:" + + " sampleIds: custom list of samples or patients to query, e.g. [\"TCGA-A1-A0SD-01\", \"TCGA-A1-A0SE-01\"]") + @RequestBody(required = false) + List sampleIds) + throws MolecularProfileNotFoundException, + SampleListNotFoundException, + GenesetNotFoundException { + + if (sampleListId != null && sampleListId.trim().length() > 0) { + return new ResponseEntity<>( + genesetCorrelationService.fetchCorrelatedGenes( + genesetId, geneticProfileId, sampleListId, correlationThreshold.doubleValue()), + HttpStatus.OK); + } + if (sampleIds != null && sampleIds.size() > 0) { + return new ResponseEntity<>( + genesetCorrelationService.fetchCorrelatedGenes( + genesetId, geneticProfileId, sampleIds, correlationThreshold.doubleValue()), + HttpStatus.OK); + } else { + return new ResponseEntity<>( + genesetCorrelationService.fetchCorrelatedGenes( + genesetId, geneticProfileId, correlationThreshold.doubleValue()), + HttpStatus.OK); + } + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/GenesetDataController.java b/src/main/java/org/cbioportal/legacy/web/GenesetDataController.java new file mode 100644 index 00000000000..f3c9422dd6d --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/GenesetDataController.java @@ -0,0 +1,87 @@ +package org.cbioportal.legacy.web; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.ArraySchema; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.tags.Tag; +import java.util.List; +import org.cbioportal.legacy.model.GenesetMolecularData; +import org.cbioportal.legacy.service.GenesetDataService; +import org.cbioportal.legacy.service.exception.MolecularProfileNotFoundException; +import org.cbioportal.legacy.service.exception.SampleListNotFoundException; +import org.cbioportal.legacy.web.config.annotation.InternalApi; +import org.cbioportal.legacy.web.parameter.GenesetDataFilterCriteria; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RestController; + +@InternalApi +@RestController() +@RequestMapping("/api") +@Validated +@Tag(name = "Gene Set Scores", description = " ") +public class GenesetDataController { + + @Autowired private GenesetDataService genesetDataService; + + @PreAuthorize( + "hasPermission(#geneticProfileId, 'GeneticProfileId', T(org.cbioportal.legacy.utils.security.AccessLevel).READ)") + @RequestMapping( + value = "/genetic-profiles/{geneticProfileId}/geneset-genetic-data/fetch", + method = RequestMethod.POST, + consumes = MediaType.APPLICATION_JSON_VALUE, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation( + description = + "Fetch gene set \"genetic data\" items (gene set scores) by profile Id, gene set ids and sample ids") + @ApiResponse( + responseCode = "200", + description = "OK", + content = + @Content( + array = @ArraySchema(schema = @Schema(implementation = GenesetMolecularData.class)))) + public ResponseEntity> fetchGeneticDataItems( + @Parameter(required = true, description = "Genetic profile ID, e.g. gbm_tcga_gsva_scores") + @PathVariable + String geneticProfileId, + @Parameter( + required = true, + description = + "Search criteria to return the values for a given set of samples and gene set items. " + + "genesetIds: The list of identifiers for the gene sets of interest, e.g. HINATA_NFKB_MATRIX. " + + "Use one of these if you want to specify a subset of samples:" + + "(1) sampleListId: Identifier of pre-defined sample list with samples to query, e.g. brca_tcga_all " + + "or (2) sampleIds: custom list of samples or patients to query, e.g. TCGA-BH-A1EO-01, TCGA-AR-A1AR-01") + @RequestBody + GenesetDataFilterCriteria genesetDataFilterCriteria) + throws MolecularProfileNotFoundException, SampleListNotFoundException { + + if (genesetDataFilterCriteria.getSampleListId() != null + && genesetDataFilterCriteria.getSampleListId().trim().length() > 0) { + return new ResponseEntity<>( + genesetDataService.fetchGenesetData( + geneticProfileId, + genesetDataFilterCriteria.getSampleListId(), + genesetDataFilterCriteria.getGenesetIds()), + HttpStatus.OK); + } else { + return new ResponseEntity<>( + genesetDataService.fetchGenesetData( + geneticProfileId, + genesetDataFilterCriteria.getSampleIds(), + genesetDataFilterCriteria.getGenesetIds()), + HttpStatus.OK); + } + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/GenesetHierarchyController.java b/src/main/java/org/cbioportal/legacy/web/GenesetHierarchyController.java new file mode 100644 index 00000000000..f3ae1aa3e1e --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/GenesetHierarchyController.java @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2016 The Hyve B.V. + * This code is licensed under the GNU Affero General Public License (AGPL), + * version 3, or (at your option) any later version. + */ + +/* + * This file is part of cBioPortal. + * + * cBioPortal is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package org.cbioportal.legacy.web; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.ArraySchema; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.constraints.Max; +import jakarta.validation.constraints.Min; +import java.util.List; +import org.cbioportal.legacy.model.GenesetHierarchyInfo; +import org.cbioportal.legacy.service.GenesetHierarchyService; +import org.cbioportal.legacy.service.exception.MolecularProfileNotFoundException; +import org.cbioportal.legacy.service.exception.SampleListNotFoundException; +import org.cbioportal.legacy.web.config.annotation.InternalApi; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.RequestBody; +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.bind.annotation.RestController; + +@InternalApi +@RestController() +@RequestMapping("/api") +@Validated +@Tag(name = "Gene Set Hierarchy", description = " ") +public class GenesetHierarchyController { + + @Autowired private GenesetHierarchyService genesetHierarchyService; + + @PreAuthorize( + "hasPermission(#geneticProfileId, 'GeneticProfileId', T(org.cbioportal.legacy.utils.security.AccessLevel).READ)") + @RequestMapping( + value = "/geneset-hierarchy/fetch", + method = RequestMethod.POST, + consumes = MediaType.APPLICATION_JSON_VALUE, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation( + description = + "Get gene set hierarchical organization information. I.e. how different gene sets relate to other gene sets, in a hierarchy") + @ApiResponse( + responseCode = "200", + description = "OK", + content = + @Content( + array = @ArraySchema(schema = @Schema(implementation = GenesetHierarchyInfo.class)))) + public ResponseEntity> fetchGenesetHierarchyInfo( + @Parameter( + required = true, + description = + "Genetic Profile ID e.g. gbm_tcga_gsva_scores. The final hierarchy " + + " will only include gene sets scored in the specified profile.") + @RequestParam + String geneticProfileId, + @Parameter( + description = + "Percentile (for score calculation). Which percentile to use when determining the *representative score*") + @Max(100) + @Min(1) + @RequestParam(defaultValue = "75") + Integer percentile, + @Parameter( + description = + "Gene set score threshold (for absolute score value). Filters out gene sets where the GSVA(like) *representative score* is under this threshold.") + @Max(1) + @Min(0) + @RequestParam(defaultValue = "0.4") + Double scoreThreshold, + @Parameter( + description = + "p-value threshold. Filters out gene sets for which the score p-value is higher than this threshold.") + @Max(1) + @Min(0) + @RequestParam(defaultValue = "0.05") + Double pvalueThreshold, + @Parameter( + description = + "Identifier of pre-defined sample list with samples to query, e.g. brca_tcga_all") + @RequestParam(required = false) + String sampleListId, + @Parameter( + description = + "Fill this one if you want to specify a subset of samples:" + + " sampleIds: custom list of samples or patients to query, e.g. [\"TCGA-A1-A0SD-01\", \"TCGA-A1-A0SE-01\"]") + @RequestBody(required = false) + List sampleIds) + throws MolecularProfileNotFoundException, SampleListNotFoundException { + + if (sampleListId != null && sampleListId.trim().length() > 0) { + return new ResponseEntity<>( + genesetHierarchyService.fetchGenesetHierarchyInfo( + geneticProfileId, percentile, scoreThreshold, pvalueThreshold, sampleListId), + HttpStatus.OK); + } else if (sampleIds != null && sampleIds.size() > 0) { + return new ResponseEntity<>( + genesetHierarchyService.fetchGenesetHierarchyInfo( + geneticProfileId, percentile, scoreThreshold, pvalueThreshold, sampleIds), + HttpStatus.OK); + } else { + return new ResponseEntity<>( + genesetHierarchyService.fetchGenesetHierarchyInfo( + geneticProfileId, percentile, scoreThreshold, pvalueThreshold), + HttpStatus.OK); + } + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/IndexPageController.java b/src/main/java/org/cbioportal/legacy/web/IndexPageController.java new file mode 100644 index 00000000000..1eeb0f5f69b --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/IndexPageController.java @@ -0,0 +1,152 @@ +package org.cbioportal.legacy.web; + +import static org.cbioportal.legacy.service.FrontendPropertiesServiceImpl.FrontendProperty; + +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonSerializer; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializerProvider; +import com.fasterxml.jackson.databind.module.SimpleModule; +import jakarta.servlet.http.HttpServletRequest; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; +import org.cbioportal.legacy.service.FrontendPropertiesService; +import org.cbioportal.legacy.service.util.MskWholeSlideViewerTokenGenerator; +import org.cbioportal.legacy.web.util.HttpRequestUtils; +import org.json.simple.JSONObject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.ResponseEntity; +import org.springframework.security.core.Authentication; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; + +@Controller +public class IndexPageController { + private static final Logger log = LoggerFactory.getLogger(IndexPageController.class); + + @Autowired private FrontendPropertiesService frontendPropertiesService; + + @Autowired private HttpRequestUtils requestUtils; + + @Value("${authenticate}") + private String[] authenticate; + + @Value("${saml.idp.metadata.entityid:not_defined_in_portalproperties}") + private String samlIdpEntityId; + + @Value("${msk.whole.slide.viewer.secret.key:}") + private String wholeSlideViewerKey; + + private final ObjectMapper mapper = new ObjectMapper(); + + private Map getFrontendProperties( + HttpServletRequest request, Authentication authentication) { + String baseUrl = requestUtils.getBaseUrl(request); + Map properties = new HashMap<>(); + + Map originalProperties = frontendPropertiesService.getFrontendProperties(); + + for (Map.Entry entry : originalProperties.entrySet()) { + String value = entry.getValue(); + if (value != null && (value.equalsIgnoreCase("true") || value.equalsIgnoreCase("false"))) { + properties.put(entry.getKey(), Boolean.valueOf(value)); + } else { + properties.put(entry.getKey(), value); + } + } + properties.put("base_url", baseUrl); + properties.put( + "user_email_address", authentication != null ? authentication.getName() : "anonymousUser"); + properties.put( + "user_display_name", authentication != null ? authentication.getName() : "anonymousUser"); + // Set MSK slide viewer token at runtime + properties.put( + "mskWholeSlideViewerToken", + getMskWholeSlideViewerToken(wholeSlideViewerKey, authentication)); + return properties; + } + + private String getMskWholeSlideViewerToken(String secretKey, Authentication authentication) { + // this token is for the msk portal + // the token is generated based on users' timestamp to let the slide viewer know whether the + // token is expired and then decide whether to allow the user to login the viewer + // every time when we refresh the page or goto the new page, a new token should be generated + if (secretKey != null) secretKey = secretKey.trim(); + String timeStamp = String.valueOf(System.currentTimeMillis()); + + if (authentication != null + && authentication.isAuthenticated() + && secretKey != null + && !secretKey.isEmpty()) { + return "{ \"token\":\"" + + MskWholeSlideViewerTokenGenerator.generateTokenByHmacSHA256( + authentication.getName(), secretKey, timeStamp) + + "\", \"time\":\"" + + timeStamp + + "\"}"; + } else { + return null; + } + } + + @RequestMapping({"/", "/index", "/index.html", "/study/summary", "/results"}) + public String showIndexPage( + HttpServletRequest request, Authentication authentication, Model model) + throws JsonProcessingException { + + SimpleModule simpleModule = new SimpleModule(); + simpleModule.addSerializer(String.class, new CustomFrontendPropertiesSerializer()); + mapper.registerModule(simpleModule); + + String baseUrl = requestUtils.getBaseUrl(request); + JSONObject postData = requestUtils.getPostData(request); + + model.addAttribute( + "propertiesJson", + mapper.writeValueAsString(getFrontendProperties(request, authentication))); + model.addAttribute( + "frontendUrl", frontendPropertiesService.getFrontendProperty(FrontendProperty.frontendUrl)); + model.addAttribute("baseUrl", baseUrl); + model.addAttribute("contextPath", request.getContextPath()); + model.addAttribute( + "appVersion", frontendPropertiesService.getFrontendProperty(FrontendProperty.app_version)); + model.addAttribute("postData", postData.isEmpty() ? "undefined" : postData); + model.addAttribute( + "googleTagManagerId", + frontendPropertiesService.getFrontendProperty(FrontendProperty.google_tag_manager_id)); + + return "index"; + } + + @GetMapping("/config_service") + public ResponseEntity getConfigService( + HttpServletRequest request, Authentication authentication) { + return ResponseEntity.ok(getFrontendProperties(request, authentication)); + } + + public FrontendPropertiesService getFrontendPropertiesService() { + return frontendPropertiesService; + } + + public static class CustomFrontendPropertiesSerializer extends JsonSerializer { + @Override + public void serialize( + String value, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) + throws IOException { + if ("true".equalsIgnoreCase(value) || "false".equalsIgnoreCase((value))) { + jsonGenerator.writeBoolean("true".equalsIgnoreCase(value)); + } else if (value != null) { + jsonGenerator.writeString(value); + } else { + jsonGenerator.writeNull(); + } + } + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/InfoController.java b/src/main/java/org/cbioportal/legacy/web/InfoController.java new file mode 100644 index 00000000000..c8c98786d07 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/InfoController.java @@ -0,0 +1,90 @@ +package org.cbioportal.legacy.web; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.cbioportal.legacy.model.Info; +import org.cbioportal.legacy.web.config.PublicApiTags; +import org.cbioportal.legacy.web.config.annotation.PublicApi; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RestController; + +@PublicApi +@RestController +@Validated +@Tag(name = PublicApiTags.INFO, description = " ") +public class InfoController { + + @Value("${portal.version}") + private String portalVersion; + + @Value("${db.version}") + private String dbVersion; + + @Value("${derived_table.version}") + private String derivedTableVersion; + + @Value("${git.branch:not set}") + private String gitBranch; + + @Value("${git.commit.id.full:not set}") + private String gitCommitId; + + @Value("${git.commit.id.abbrev:not set}") + private String gitCommitIdAbbrev; + + @Value("${git.commit.id.describe:not set}") + private String gitCommitIdDescribe; + + @Value("${git.commit.id.describe-short:not set}") + private String gitCommitIdDescribeShort; + + @Value("${git.commit.message.full:not set}") + private String gitCommitMessageFull; + + @Value("${git.commit.message.short:not set}") + private String gitCommitMessageShort; + + @Value("${git.commit.user.email:not set}") + private String gitCommitMessageUserEmail; + + @Value("${git.commit.user.name:not set}") + private String gitCommitMessageUserName; + + @Value("${git.dirty:not set}") + private String gitDirty; + + @RequestMapping( + value = "/api/info", + method = RequestMethod.GET, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(description = "Get information about the running instance") + @ApiResponse( + responseCode = "200", + description = "OK", + content = @Content(schema = @Schema(implementation = Info.class))) + public ResponseEntity getInfo() { + Info info = new Info(); + info.setPortalVersion(portalVersion); + info.setDbVersion(dbVersion); + info.setDerivedTableVersion(derivedTableVersion); + info.setGitBranch(gitBranch); + info.setGitCommitId(gitCommitId); + info.setGitCommitIdDescribe(gitCommitIdDescribe); + info.setGitCommitIdDescribeShort(gitCommitIdDescribeShort); + info.setGitCommitMessageShort(gitCommitMessageShort); + info.setGitCommitMessageFull(gitCommitMessageFull); + info.setGitCommitMessageUserEmail(gitCommitMessageUserEmail); + info.setGitCommitMessageUserName(gitCommitMessageUserName); + info.isGitDirty(Boolean.valueOf(gitDirty)); + return new ResponseEntity<>(info, HttpStatus.OK); + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/LegacyApiController.java b/src/main/java/org/cbioportal/legacy/web/LegacyApiController.java new file mode 100644 index 00000000000..013b8304429 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/LegacyApiController.java @@ -0,0 +1,56 @@ +package org.cbioportal.legacy.web; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ObjectNode; +import jakarta.servlet.http.HttpServletRequest; +import java.io.IOException; +import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; +import java.util.Objects; +import org.springframework.core.io.ClassPathResource; +import org.springframework.core.io.Resource; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.lang.Nullable; +import org.springframework.util.FileCopyUtils; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +public class LegacyApiController { + + private static final String JSON_HOST_KEY = "host"; + private static final String REQUEST_HEADER_HOST = "Host"; + private static final String LEGACY_API_FILE_JSON = "legacy-api.json"; + + @Nullable private String legacySwaggerJson; + + @GetMapping(value = "/api/v2/api-docs", produces = MediaType.APPLICATION_JSON_VALUE) + public ResponseEntity getLegacyAPI(HttpServletRequest request) throws IOException { + + if (Objects.isNull(legacySwaggerJson)) { + legacySwaggerJson = getLegacySwagger(request.getHeader(REQUEST_HEADER_HOST)); + } + return ResponseEntity.ok(legacySwaggerJson); + } + + private String getLegacySwagger(String host) throws IOException { + Resource resource = new ClassPathResource(LEGACY_API_FILE_JSON); + InputStreamReader reader = + new InputStreamReader(resource.getInputStream(), StandardCharsets.UTF_8); + + String jsonData = FileCopyUtils.copyToString(reader); + + ObjectMapper objectMapper = new ObjectMapper(); + JsonNode jsonNode = objectMapper.readTree(jsonData); + + // Update key host + if (jsonNode.has(JSON_HOST_KEY)) { + ((ObjectNode) jsonNode).put(JSON_HOST_KEY, host); + } + + // Convert back to string + return objectMapper.writeValueAsString(jsonNode); + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/LoginPageController.java b/src/main/java/org/cbioportal/legacy/web/LoginPageController.java new file mode 100644 index 00000000000..b9dbad8d52e --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/LoginPageController.java @@ -0,0 +1,109 @@ +package org.cbioportal.legacy.web; + +import jakarta.servlet.http.HttpServletRequest; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; +import org.cbioportal.legacy.service.FrontendPropertiesService; +import org.cbioportal.legacy.service.FrontendPropertiesServiceImpl; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; +import org.springframework.http.MediaType; +import org.springframework.security.core.Authentication; +import org.springframework.security.oauth2.client.registration.ClientRegistration; +import org.springframework.security.oauth2.client.registration.InMemoryClientRegistrationRepository; +import org.springframework.security.oauth2.client.web.OAuth2AuthorizationRequestRedirectFilter; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; + +@Controller +@ConditionalOnExpression("{'oauth2','saml','optional_oauth2'}.contains('${authenticate}')") +public class LoginPageController { + private static final Logger log = LoggerFactory.getLogger(LoginPageController.class); + + @Autowired private FrontendPropertiesService frontendPropertiesService; + + @Autowired(required = false) + private InMemoryClientRegistrationRepository clientRegistrationRepository; + + @Value("${authenticate}") + private String authenticate; + + @Value("${security.force_redirect_on_one_idp:true}") + private boolean forceRedirectOnOneIdentityProvider; + + @PostMapping(value = "/login", produces = MediaType.APPLICATION_JSON_VALUE) + public String showLoginPagePost( + HttpServletRequest request, Authentication authentication, Model model) { + populateModel(request, model, new HashMap<>()); + return "login"; + } + + @GetMapping(value = "/login", produces = MediaType.APPLICATION_JSON_VALUE) + public String showLoginPage( + HttpServletRequest request, Authentication authentication, Model model) { + Map oauth2AuthenticationUrls = getOauth2AuthenticationUrls(); + boolean logoutFailure = request.getParameterMap().containsKey("logout_failure"); + if (oauth2AuthenticationUrls.size() == 1 + && !logoutFailure + && this.forceRedirectOnOneIdentityProvider) { + log.debug("Redirecting to Identity Provider"); + return "redirect:" + oauth2AuthenticationUrls.values().iterator().next(); + } + populateModel(request, model, oauth2AuthenticationUrls); + + return "login"; + } + + private void populateModel( + HttpServletRequest request, Model model, Map oauth2AuthenticationUrls) { + model.addAttribute("oauth_urls", oauth2AuthenticationUrls); + model.addAttribute( + "skin_title", + frontendPropertiesService.getFrontendProperty( + FrontendPropertiesServiceImpl.FrontendProperty.skin_title)); + model.addAttribute( + "skin_authorization_message", + frontendPropertiesService.getFrontendProperty( + FrontendPropertiesServiceImpl.FrontendProperty.skin_authorization_message)); + model.addAttribute( + "skin_login_contact_html", + frontendPropertiesService.getFrontendProperty( + FrontendPropertiesServiceImpl.FrontendProperty.skin_login_contact_html)); + model.addAttribute( + "skin_login_saml_registration_html", + frontendPropertiesService.getFrontendProperty( + FrontendPropertiesServiceImpl.FrontendProperty.skin_login_saml_registration_html)); + model.addAttribute( + "saml_idp_metadata_entityid", + frontendPropertiesService.getFrontendProperty( + FrontendPropertiesServiceImpl.FrontendProperty.saml_idp_metadata_entityid)); + model.addAttribute("logout_success", request.getParameterMap().containsKey("logout_success")); + model.addAttribute("login_error", request.getParameterMap().containsKey("logout_failure")); + model.addAttribute( + "show_saml", + frontendPropertiesService + .getFrontendProperty( + FrontendPropertiesServiceImpl.FrontendProperty.authenticationMethod) + .equals("saml")); + } + + private Map getOauth2AuthenticationUrls() { + Map oauth2AuthenticationUrls = new HashMap<>(); + if (!Objects.isNull(clientRegistrationRepository) && !Objects.equals(authenticate, "saml")) { + for (ClientRegistration clientRegistration : clientRegistrationRepository) { + oauth2AuthenticationUrls.put( + clientRegistration.getRegistrationId(), + OAuth2AuthorizationRequestRedirectFilter.DEFAULT_AUTHORIZATION_REQUEST_BASE_URI + + "/" + + clientRegistration.getRegistrationId()); + } + } + return oauth2AuthenticationUrls; + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/MatchMinerController.java b/src/main/java/org/cbioportal/legacy/web/MatchMinerController.java new file mode 100644 index 00000000000..979824ff1be --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/MatchMinerController.java @@ -0,0 +1,89 @@ +package org.cbioportal.legacy.web; + +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import jakarta.servlet.http.HttpServletRequest; +import java.net.URI; +import java.net.URISyntaxException; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import org.apache.commons.codec.binary.Base64; +import org.json.simple.JSONObject; +import org.json.simple.parser.JSONParser; +import org.json.simple.parser.ParseException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.http.converter.StringHttpMessageConverter; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.client.RestTemplate; + +@RestController +@RequestMapping("/api/matchminer") +public class MatchMinerController { + + private static final Logger LOG = LoggerFactory.getLogger(MatchMinerController.class); + + @Value("${matchminer.url:}") + private String url; + + @Value("${matchminer.token:}") + private String token; + + @RequestMapping(value = "/api/**", produces = "application/json") + @ApiResponse( + responseCode = "200", + description = "OK", + content = @Content(schema = @Schema(implementation = Object.class))) + public ResponseEntity proxy( + @RequestBody(required = false) JSONObject body, + HttpMethod method, + HttpServletRequest request) { + try { + // TODO when reimplemeting different dispatcherservlets with different context roots + // reset this to 'String requestPathInfo = request.getPathInfo();' + String requestPathInfo = + request.getPathInfo() == null ? request.getServletPath() : request.getPathInfo(); + String path = requestPathInfo.replace("/matchminer", ""); + URI uri = new URI(this.url + path); + + HttpHeaders httpHeaders = new HttpHeaders(); + String contentType = request.getHeader("Content-Type"); + if (contentType != null) { + httpHeaders.setContentType(MediaType.valueOf(contentType)); + } + if (!this.token.equals("")) { + String auth = this.token + ":"; + byte[] encodedAuth = Base64.encodeBase64(auth.getBytes(Charset.forName("US-ASCII"))); + String authHeader = "Basic " + new String(encodedAuth); + httpHeaders.set("Authorization", authHeader); + } + + RestTemplate restTemplate = new RestTemplate(); + restTemplate + .getMessageConverters() + .add(0, new StringHttpMessageConverter(StandardCharsets.UTF_8)); + ResponseEntity responseEntity = + restTemplate.exchange(uri, method, new HttpEntity<>(body, httpHeaders), String.class); + // The response might be a json object or a json array, so I return Object to cover both + // cases. + Object response = new JSONParser().parse(responseEntity.getBody()); + return new ResponseEntity<>(response, responseEntity.getStatusCode()); + } catch (URISyntaxException e) { + LOG.error("Error occurred", e); + return new ResponseEntity<>(HttpStatus.BAD_REQUEST); + } catch (ParseException e) { + LOG.error("Error occurred", e); + return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR); + } + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/MolecularDataController.java b/src/main/java/org/cbioportal/legacy/web/MolecularDataController.java new file mode 100644 index 00000000000..0f3478c9f14 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/MolecularDataController.java @@ -0,0 +1,265 @@ +package org.cbioportal.legacy.web; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.ArraySchema; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; +import org.apache.commons.lang3.math.NumberUtils; +import org.cbioportal.legacy.model.GeneMolecularData; +import org.cbioportal.legacy.model.NumericGeneMolecularData; +import org.cbioportal.legacy.service.MolecularDataService; +import org.cbioportal.legacy.service.exception.MolecularProfileNotFoundException; +import org.cbioportal.legacy.web.config.PublicApiTags; +import org.cbioportal.legacy.web.config.annotation.PublicApi; +import org.cbioportal.legacy.web.parameter.HeaderKeyConstants; +import org.cbioportal.legacy.web.parameter.MolecularDataFilter; +import org.cbioportal.legacy.web.parameter.MolecularDataMultipleStudyFilter; +import org.cbioportal.legacy.web.parameter.Projection; +import org.cbioportal.legacy.web.parameter.SampleMolecularIdentifier; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestAttribute; +import org.springframework.web.bind.annotation.RequestBody; +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.bind.annotation.RestController; + +@PublicApi +@RestController() +@RequestMapping("/api") +@Validated +@Tag(name = PublicApiTags.MOLECULAR_DATA, description = " ") +public class MolecularDataController { + + @Autowired private MolecularDataService molecularDataService; + + @PreAuthorize( + "hasPermission(#molecularProfileId, 'MolecularProfileId', T(org.cbioportal.legacy.utils.security.AccessLevel).READ)") + @RequestMapping( + value = "/molecular-profiles/{molecularProfileId}/molecular-data", + method = RequestMethod.GET, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(description = "Get all molecular data in a molecular profile") + @ApiResponse( + responseCode = "200", + description = "OK", + content = + @Content( + array = + @ArraySchema(schema = @Schema(implementation = NumericGeneMolecularData.class)))) + public ResponseEntity> getAllMolecularDataInMolecularProfile( + @Parameter( + required = true, + description = "Molecular Profile ID e.g. acc_tcga_rna_seq_v2_mrna") + @PathVariable + String molecularProfileId, + @Parameter(required = true, description = "Sample List ID e.g. acc_tcga_all") @RequestParam + String sampleListId, + @Parameter(required = true, description = "Entrez Gene ID e.g. 1") @RequestParam + Integer entrezGeneId, + @Parameter(description = "Level of detail of the response") + @RequestParam(defaultValue = "SUMMARY") + Projection projection) + throws MolecularProfileNotFoundException { + + List result = + filterNonNumberMolecularData( + molecularDataService.getMolecularData( + molecularProfileId, sampleListId, Arrays.asList(entrezGeneId), projection.name())); + + if (projection == Projection.META) { + HttpHeaders responseHeaders = new HttpHeaders(); + responseHeaders.add(HeaderKeyConstants.TOTAL_COUNT, String.valueOf(result.size())); + return new ResponseEntity<>(responseHeaders, HttpStatus.OK); + } else { + return new ResponseEntity<>(result, HttpStatus.OK); + } + } + + @PreAuthorize( + "hasPermission(#molecularProfileId, 'MolecularProfileId', T(org.cbioportal.legacy.utils.security.AccessLevel).READ)") + @RequestMapping( + value = "/molecular-profiles/{molecularProfileId}/molecular-data/fetch", + method = RequestMethod.POST, + consumes = MediaType.APPLICATION_JSON_VALUE, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(description = "Fetch molecular data in a molecular profile") + @ApiResponse( + responseCode = "200", + description = "OK", + content = + @Content( + array = + @ArraySchema(schema = @Schema(implementation = NumericGeneMolecularData.class)))) + public ResponseEntity> fetchAllMolecularDataInMolecularProfile( + @Parameter( + required = true, + description = "Molecular Profile ID e.g. acc_tcga_rna_seq_v2_mrna") + @PathVariable + String molecularProfileId, + @Parameter( + required = true, + description = "List of Sample IDs/Sample List ID and Entrez Gene IDs") + @Valid + @RequestBody + MolecularDataFilter molecularDataFilter, + @Parameter(description = "Level of detail of the response") + @RequestParam(defaultValue = "SUMMARY") + Projection projection) + throws MolecularProfileNotFoundException { + + List result; + if (molecularDataFilter.getSampleListId() != null) { + result = + filterNonNumberMolecularData( + molecularDataService.getMolecularData( + molecularProfileId, + molecularDataFilter.getSampleListId(), + molecularDataFilter.getEntrezGeneIds(), + projection.name())); + } else { + result = + filterNonNumberMolecularData( + molecularDataService.fetchMolecularData( + molecularProfileId, + molecularDataFilter.getSampleIds(), + molecularDataFilter.getEntrezGeneIds(), + projection.name())); + } + + if (projection == Projection.META) { + HttpHeaders responseHeaders = new HttpHeaders(); + responseHeaders.add(HeaderKeyConstants.TOTAL_COUNT, String.valueOf(result.size())); + return new ResponseEntity<>(responseHeaders, HttpStatus.OK); + } else { + return new ResponseEntity<>(result, HttpStatus.OK); + } + } + + @PreAuthorize( + "hasPermission(#involvedCancerStudies, 'Collection', T(org.cbioportal.legacy.utils.security.AccessLevel).READ)") + @RequestMapping( + value = "/molecular-data/fetch", + method = RequestMethod.POST, + consumes = MediaType.APPLICATION_JSON_VALUE, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(description = "Fetch molecular data") + @ApiResponse( + responseCode = "200", + description = "OK", + content = + @Content( + array = + @ArraySchema(schema = @Schema(implementation = NumericGeneMolecularData.class)))) + public ResponseEntity> + fetchMolecularDataInMultipleMolecularProfiles( + @Parameter( + hidden = true) // prevent reference to this attribute in the swagger-ui interface + @RequestAttribute(required = false, value = "involvedCancerStudies") + Collection involvedCancerStudies, + @Parameter( + hidden = + true) // prevent reference to this attribute in the swagger-ui interface. this + // attribute is needed for the @PreAuthorize tag above. + @Valid + @RequestAttribute( + required = false, + value = "interceptedMolecularDataMultipleStudyFilter") + MolecularDataMultipleStudyFilter interceptedMolecularDataMultipleStudyFilter, + @Parameter( + required = true, + description = + "List of Molecular Profile ID and Sample ID pairs or List of Molecular" + + "Profile IDs and Entrez Gene IDs") + @Valid + @RequestBody(required = false) + MolecularDataMultipleStudyFilter molecularDataMultipleStudyFilter, + @Parameter(description = "Level of detail of the response") + @RequestParam(defaultValue = "SUMMARY") + Projection projection) { + + List result; + if (interceptedMolecularDataMultipleStudyFilter.getMolecularProfileIds() != null) { + result = + filterNonNumberMolecularData( + molecularDataService.getMolecularDataInMultipleMolecularProfiles( + interceptedMolecularDataMultipleStudyFilter.getMolecularProfileIds(), + null, + interceptedMolecularDataMultipleStudyFilter.getEntrezGeneIds(), + projection.name())); + } else { + + List molecularProfileIds = new ArrayList<>(); + List sampleIds = new ArrayList<>(); + extractMolecularProfileAndSampleIds( + interceptedMolecularDataMultipleStudyFilter, molecularProfileIds, sampleIds); + result = + filterNonNumberMolecularData( + molecularDataService.getMolecularDataInMultipleMolecularProfiles( + molecularProfileIds, + sampleIds, + interceptedMolecularDataMultipleStudyFilter.getEntrezGeneIds(), + projection.name())); + } + + if (projection == Projection.META) { + HttpHeaders responseHeaders = new HttpHeaders(); + responseHeaders.add(HeaderKeyConstants.TOTAL_COUNT, String.valueOf(result.size())); + return new ResponseEntity<>(responseHeaders, HttpStatus.OK); + } else { + return new ResponseEntity<>(result, HttpStatus.OK); + } + } + + private void extractMolecularProfileAndSampleIds( + MolecularDataMultipleStudyFilter molecularDataMultipleStudyFilter, + List molecularProfileIds, + List sampleIds) { + + for (SampleMolecularIdentifier sampleMolecularIdentifier : + molecularDataMultipleStudyFilter.getSampleMolecularIdentifiers()) { + + molecularProfileIds.add(sampleMolecularIdentifier.getMolecularProfileId()); + sampleIds.add(sampleMolecularIdentifier.getSampleId()); + } + } + + private List filterNonNumberMolecularData( + List geneMolecularDataList) { + + List result = new ArrayList<>(); + geneMolecularDataList.forEach( + g -> { + String value = g.getValue(); + if (NumberUtils.isNumber(value)) { + NumericGeneMolecularData data = new NumericGeneMolecularData(); + data.setEntrezGeneId(g.getEntrezGeneId()); + data.setGene(g.getGene()); + data.setMolecularProfileId(g.getMolecularProfileId()); + data.setPatientId(g.getPatientId()); + data.setSampleId(g.getSampleId()); + data.setStudyId(g.getStudyId()); + data.setValue(new BigDecimal(g.getValue())); + result.add(data); + } + }); + + return result; + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/MolecularProfileController.java b/src/main/java/org/cbioportal/legacy/web/MolecularProfileController.java new file mode 100644 index 00000000000..19eb109ba7e --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/MolecularProfileController.java @@ -0,0 +1,239 @@ +package org.cbioportal.legacy.web; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.ArraySchema; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import jakarta.validation.constraints.Max; +import jakarta.validation.constraints.Min; +import java.util.Collection; +import java.util.List; +import org.cbioportal.legacy.model.MolecularProfile; +import org.cbioportal.legacy.model.meta.BaseMeta; +import org.cbioportal.legacy.service.MolecularProfileService; +import org.cbioportal.legacy.service.exception.MolecularProfileNotFoundException; +import org.cbioportal.legacy.service.exception.StudyNotFoundException; +import org.cbioportal.legacy.web.config.PublicApiTags; +import org.cbioportal.legacy.web.config.annotation.PublicApi; +import org.cbioportal.legacy.web.parameter.Direction; +import org.cbioportal.legacy.web.parameter.HeaderKeyConstants; +import org.cbioportal.legacy.web.parameter.MolecularProfileFilter; +import org.cbioportal.legacy.web.parameter.PagingConstants; +import org.cbioportal.legacy.web.parameter.Projection; +import org.cbioportal.legacy.web.parameter.sort.MolecularProfileSortBy; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestAttribute; +import org.springframework.web.bind.annotation.RequestBody; +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.bind.annotation.RestController; + +@PublicApi +@RestController() +@RequestMapping("/api") +@Validated +@Tag(name = PublicApiTags.MOLECULAR_PROFILES, description = " ") +public class MolecularProfileController { + + @Autowired private MolecularProfileService molecularProfileService; + + @RequestMapping( + value = "/molecular-profiles", + method = RequestMethod.GET, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(description = "Get all molecular profiles") + @ApiResponse( + responseCode = "200", + description = "OK", + content = + @Content(array = @ArraySchema(schema = @Schema(implementation = MolecularProfile.class)))) + public ResponseEntity> getAllMolecularProfiles( + @Parameter(description = "Level of detail of the response") + @RequestParam(defaultValue = "SUMMARY") + Projection projection, + @Parameter(description = "Page size of the result list") + @Max(PagingConstants.MAX_PAGE_SIZE) + @Min(PagingConstants.MIN_PAGE_SIZE) + @RequestParam(defaultValue = PagingConstants.DEFAULT_PAGE_SIZE) + Integer pageSize, + @Parameter(description = "Page number of the result list") + @Min(PagingConstants.MIN_PAGE_NUMBER) + @RequestParam(defaultValue = PagingConstants.DEFAULT_PAGE_NUMBER) + Integer pageNumber, + @Parameter(description = "Name of the property that the result list is sorted by") + @RequestParam(required = false) + MolecularProfileSortBy sortBy, + @Parameter(description = "Direction of the sort") @RequestParam(defaultValue = "ASC") + Direction direction) { + + if (projection == Projection.META) { + HttpHeaders responseHeaders = new HttpHeaders(); + responseHeaders.add( + HeaderKeyConstants.TOTAL_COUNT, + molecularProfileService.getMetaMolecularProfiles().getTotalCount().toString()); + return new ResponseEntity<>(responseHeaders, HttpStatus.OK); + } else { + return new ResponseEntity<>( + molecularProfileService.getAllMolecularProfiles( + projection.name(), + pageSize, + pageNumber, + sortBy == null ? null : sortBy.getOriginalValue(), + direction.name()), + HttpStatus.OK); + } + } + + @PreAuthorize( + "hasPermission(#molecularProfileId, 'MolecularProfileId', T(org.cbioportal.legacy.utils.security.AccessLevel).READ)") + @RequestMapping( + value = "/molecular-profiles/{molecularProfileId}", + method = RequestMethod.GET, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(description = "Get molecular profile") + @ApiResponse( + responseCode = "200", + description = "OK", + content = @Content(schema = @Schema(implementation = MolecularProfile.class))) + public ResponseEntity getMolecularProfile( + @Parameter(required = true, description = "Molecular Profile ID e.g. acc_tcga_mutations") + @PathVariable + String molecularProfileId) + throws MolecularProfileNotFoundException { + + return new ResponseEntity<>( + molecularProfileService.getMolecularProfile(molecularProfileId), HttpStatus.OK); + } + + @PreAuthorize( + "hasPermission(#studyId, 'CancerStudyId', T(org.cbioportal.legacy.utils.security.AccessLevel).READ)") + @RequestMapping( + value = "/studies/{studyId}/molecular-profiles", + method = RequestMethod.GET, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(description = "Get all molecular profiles in a study") + @ApiResponse( + responseCode = "200", + description = "OK", + content = + @Content(array = @ArraySchema(schema = @Schema(implementation = MolecularProfile.class)))) + public ResponseEntity> getAllMolecularProfilesInStudy( + @Parameter(required = true, description = "Study ID e.g. acc_tcga") @PathVariable + String studyId, + @Parameter(description = "Level of detail of the response") + @RequestParam(defaultValue = "SUMMARY") + Projection projection, + @Parameter(description = "Page size of the result list") + @Max(PagingConstants.MAX_PAGE_SIZE) + @Min(PagingConstants.MIN_PAGE_SIZE) + @RequestParam(defaultValue = PagingConstants.DEFAULT_PAGE_SIZE) + Integer pageSize, + @Parameter(description = "Page number of the result list") + @Min(PagingConstants.MIN_PAGE_NUMBER) + @RequestParam(defaultValue = PagingConstants.DEFAULT_PAGE_NUMBER) + Integer pageNumber, + @Parameter(description = "Name of the property that the result list is sorted by") + @RequestParam(required = false) + MolecularProfileSortBy sortBy, + @Parameter(description = "Direction of the sort") @RequestParam(defaultValue = "ASC") + Direction direction) + throws StudyNotFoundException { + + if (projection == Projection.META) { + HttpHeaders responseHeaders = new HttpHeaders(); + responseHeaders.add( + HeaderKeyConstants.TOTAL_COUNT, + molecularProfileService + .getMetaMolecularProfilesInStudy(studyId) + .getTotalCount() + .toString()); + return new ResponseEntity<>(responseHeaders, HttpStatus.OK); + } else { + return new ResponseEntity<>( + molecularProfileService.getAllMolecularProfilesInStudy( + studyId, + projection.name(), + pageSize, + pageNumber, + sortBy == null ? null : sortBy.getOriginalValue(), + direction.name()), + HttpStatus.OK); + } + } + + @PreAuthorize( + "hasPermission(#involvedCancerStudies, 'Collection', T(org.cbioportal.legacy.utils.security.AccessLevel).READ)") + @RequestMapping( + value = "/molecular-profiles/fetch", + method = RequestMethod.POST, + consumes = MediaType.APPLICATION_JSON_VALUE, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(description = "Fetch molecular profiles") + @ApiResponse( + responseCode = "200", + description = "OK", + content = + @Content(array = @ArraySchema(schema = @Schema(implementation = MolecularProfile.class)))) + public ResponseEntity> fetchMolecularProfiles( + @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface + @RequestAttribute(required = false, value = "involvedCancerStudies") + Collection involvedCancerStudies, + @Parameter( + hidden = + true) // prevent reference to this attribute in the swagger-ui interface. this + // attribute is needed for the @PreAuthorize tag above. + @Valid + @RequestAttribute(required = false, value = "interceptedMolecularProfileFilter") + MolecularProfileFilter interceptedMolecularProfileFilter, + @Parameter( + required = true, + description = "List of Molecular Profile IDs or List of Study IDs") + @Valid + @RequestBody(required = false) + MolecularProfileFilter molecularProfileFilter, + @Parameter(description = "Level of detail of the response") + @RequestParam(defaultValue = "SUMMARY") + Projection projection) { + + if (projection == Projection.META) { + HttpHeaders responseHeaders = new HttpHeaders(); + BaseMeta baseMeta; + + if (interceptedMolecularProfileFilter.getStudyIds() != null) { + baseMeta = + molecularProfileService.getMetaMolecularProfilesInStudies( + interceptedMolecularProfileFilter.getStudyIds()); + } else { + baseMeta = + molecularProfileService.getMetaMolecularProfiles( + interceptedMolecularProfileFilter.getMolecularProfileIds()); + } + responseHeaders.add(HeaderKeyConstants.TOTAL_COUNT, baseMeta.getTotalCount().toString()); + return new ResponseEntity<>(responseHeaders, HttpStatus.OK); + } else { + List molecularProfiles; + if (interceptedMolecularProfileFilter.getStudyIds() != null) { + molecularProfiles = + molecularProfileService.getMolecularProfilesInStudies( + interceptedMolecularProfileFilter.getStudyIds(), projection.name()); + } else { + molecularProfiles = + molecularProfileService.getMolecularProfiles( + interceptedMolecularProfileFilter.getMolecularProfileIds(), projection.name()); + } + return new ResponseEntity<>(molecularProfiles, HttpStatus.OK); + } + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/MrnaPercentileController.java b/src/main/java/org/cbioportal/legacy/web/MrnaPercentileController.java new file mode 100644 index 00000000000..adc63ea29bd --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/MrnaPercentileController.java @@ -0,0 +1,70 @@ +package org.cbioportal.legacy.web; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.ArraySchema; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.constraints.Size; +import java.util.List; +import org.cbioportal.legacy.model.MrnaPercentile; +import org.cbioportal.legacy.service.MrnaPercentileService; +import org.cbioportal.legacy.service.exception.MolecularProfileNotFoundException; +import org.cbioportal.legacy.web.config.annotation.InternalApi; +import org.cbioportal.legacy.web.parameter.PagingConstants; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +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.bind.annotation.RestController; + +@InternalApi +@RestController() +@RequestMapping("/api") +@Validated +@Tag(name = "mRNA Percentile", description = " ") +public class MrnaPercentileController { + + @Autowired private MrnaPercentileService mrnaPercentileService; + + @PreAuthorize( + "hasPermission(#molecularProfileId, 'MolecularProfileId', T(org.cbioportal.legacy.utils.security.AccessLevel).READ)") + @RequestMapping( + value = "/molecular-profiles/{molecularProfileId}/mrna-percentile/fetch", + method = RequestMethod.POST, + consumes = MediaType.APPLICATION_JSON_VALUE, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(description = "Get mRNA expression percentiles for list of genes for a sample") + @ApiResponse( + responseCode = "200", + description = "OK", + content = + @Content(array = @ArraySchema(schema = @Schema(implementation = MrnaPercentile.class)))) + public ResponseEntity> fetchMrnaPercentile( + @Parameter( + required = true, + description = "Molecular Profile ID e.g. acc_tcga_rna_seq_v2_mrna") + @PathVariable + String molecularProfileId, + @Parameter(required = true, description = "Sample ID e.g. TCGA-OR-A5J2-01") @RequestParam + String sampleId, + @Parameter(required = true, description = "List of Entrez Gene IDs") + @Size(min = 1, max = PagingConstants.MAX_PAGE_SIZE) + @RequestBody + List entrezGeneIds) + throws MolecularProfileNotFoundException { + + return new ResponseEntity<>( + mrnaPercentileService.fetchMrnaPercentile(molecularProfileId, sampleId, entrezGeneIds), + HttpStatus.OK); + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/MskEntityTranslationController.java b/src/main/java/org/cbioportal/legacy/web/MskEntityTranslationController.java new file mode 100644 index 00000000000..9466bcc20c2 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/MskEntityTranslationController.java @@ -0,0 +1,259 @@ +/* + * Copyright (c) 2017-2021 Memorial Sloan-Kettering Cancer Center. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS + * FOR A PARTICULAR PURPOSE. The software and documentation provided hereunder + * is on an "as is" basis, and Memorial Sloan-Kettering Cancer Center has no + * obligations to provide maintenance, support, updates, enhancements or + * modifications. In no event shall Memorial Sloan-Kettering Cancer Center be + * liable to any party for direct, indirect, special, incidental or + * consequential damages, including lost profits, arising out of the use of this + * software and its documentation, even if Memorial Sloan-Kettering Cancer + * Center has been advised of the possibility of such damage. + */ + +/* + * This file is part of cBioPortal. + * + * cBioPortal is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package org.cbioportal.legacy.web; + +import java.util.HashMap; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import org.cbioportal.legacy.service.PatientService; +import org.cbioportal.legacy.service.SampleService; +import org.cbioportal.legacy.service.exception.PatientNotFoundException; +import org.cbioportal.legacy.service.exception.SampleNotFoundException; +import org.cbioportal.legacy.service.exception.StudyNotFoundException; +import org.cbioportal.legacy.utils.config.annotation.ConditionalOnProperty; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.PropertySource; +import org.springframework.context.annotation.PropertySources; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Controller; +import org.springframework.ui.ModelMap; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.client.RestTemplate; +import org.springframework.web.servlet.ModelAndView; + +/** + * This class checks for the existence and location of entities {samples, patients} based on MSK + * entity stable id patterns, such as DMP (Department of Molecular Pathology) sample identifiers. + */ +@Controller +@PropertySources({ + @PropertySource(value = "classpath:application.properties", ignoreResourceNotFound = true), + @PropertySource( + value = "file:///${PORTAL_HOME}/application.properties", + ignoreResourceNotFound = true) +}) +@ConditionalOnProperty(name = "msk_entity_translation_enabled", havingValue = "true") +public class MskEntityTranslationController { + + @Autowired private SampleService sampleService; + + @Autowired private PatientService patientService; + + private String sampleViewURL; + + @Value("${sample_view.url}") + public void setSampleViewURL(String property) { + this.sampleViewURL = property; + } + + private String patientViewURL; + + @Value("${patient_view.url}") + public void setPatientViewURL(String property) { + this.patientViewURL = property; + } + + @Value("${mpath.decryption_url:}") + private String mpathDecryptionUrl; + + @Value("${mpath.token:}") + private String mpathToken; + + private static final String ARCHER = "mskarcher"; + private static final String RAINDANCE = "mskraindance"; + private static final String IMPACT = "mskimpact"; + + private static Pattern dmpSampleIDPattern = initDMPSampleIDPattern(); + + private static Pattern initDMPSampleIDPattern() { + return Pattern.compile("(P-[0-9]{7,})-T[0-9]{2,}-(\\w{3,})"); + } + + @RequestMapping( + value = {"/api-legacy/epic/sample/{sampleID}"}, + method = RequestMethod.GET) + public ModelAndView redirectIMPACTSampleForEpic(@PathVariable String sampleID, ModelMap model) { + String decryptedId = getDecryptedId(sampleID); + return new ModelAndView(getRedirectURL(decryptedId), model); + } + + @RequestMapping(value = "/api-legacy/crdb/{sampleID}", method = RequestMethod.GET) + public ModelAndView redirectCRDB(@PathVariable String sampleID, ModelMap model) { + return new ModelAndView(getRedirectURL(sampleID), model); + } + + // Decryption only works for Sample IDs (not patient IDs) + // Ids not found will not be decrypted -- will propagate down and result in 400 Error Request + // Should be avoided upstream in Epic by using /exists endpoint to check firstd + private String getDecryptedId(String id) { + String requestUrl = mpathDecryptionUrl + id; + RestTemplate restTemplate = new RestTemplate(); + LinkedMultiValueMap map = new LinkedMultiValueMap<>(); + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_JSON); + headers.add("x-api-key", mpathToken); + HttpEntity> requestEntity = new HttpEntity<>(map, headers); + ResponseEntity responseEntity = + restTemplate.exchange(requestUrl, HttpMethod.GET, requestEntity, Object.class); + String decryptedId = id; + if (responseEntity.getStatusCode().value() == 200 && responseEntity.getBody() != null) { + decryptedId = responseEntity.getBody().toString(); + } + return decryptedId; + } + + private String getRedirectURL(String sampleID) { + String redirectURL = "redirect:" + sampleViewURL; + String studyID = getCancerStudy(sampleID); + if (!checkIfSampleExistsInStudy(studyID, sampleID)) { + if (studyID.equals(ARCHER)) { + String patientID = getPatientID(sampleID); + if (patientID != null) { + return getPatientRedirectURL(patientID); + } + // else patientID is null + } + // else sample doesn't exist in this study and it is not archer + } + // this will not work for invalid sample ids and sample + // ids that do not belong to the expected study, + // but in practice that should not happen because users are meant to + // call /{cis|crdb}/{sampleID}/exists before displaying any URL + redirectURL = redirectURL.replace("STUDY_ID", studyID); + redirectURL = redirectURL.replace("SAMPLE_ID", sampleID); + return redirectURL; + } + + private String getPatientRedirectURL(String patientID) { + String redirectURL = "redirect:" + patientViewURL; + redirectURL = redirectURL.replace("STUDY_ID", IMPACT); + redirectURL = redirectURL.replace("CASE_ID", patientID); + return redirectURL; + } + + @RequestMapping( + value = {"/api-legacy/cis/{sampleID}/exists", "/api-legacy/crdb/{sampleID}/exists"}, + method = RequestMethod.GET) + public @ResponseBody HashMap exists( + @PathVariable String sampleID, ModelMap model) { + HashMap result = new HashMap(); + result.put("exists", new Boolean(checkIfSampleExists(sampleID))); + return result; + } + + @RequestMapping( + value = {"/api-legacy/epic/{sampleID}/exists"}, + method = RequestMethod.GET) + public @ResponseBody HashMap existsForEpic( + @PathVariable String sampleID, ModelMap model) { + HashMap result = new HashMap(); + String decryptedId = getDecryptedId(sampleID); + result.put("exists", new Boolean(checkIfSampleExists(decryptedId))); + return result; + } + + private boolean checkIfPatientExists(String studyID, String sampleID) { + try { + String patientID = getPatientID(sampleID); + if (patientID != null) { + patientService.getPatientInStudy(studyID, patientID); + } else { // could not parse out patient id + return false; + } + } catch (PatientNotFoundException e) { + return false; + } catch (StudyNotFoundException e) { + return false; + } + return true; + } + + private boolean checkIfSampleExists(String sampleID) { + String studyID = getCancerStudy(sampleID); + // note if we map to a study that they do not have permission to view + // then an AccessDeniedException will be thrown that we cannot catch here + if (!checkIfSampleExistsInStudy(studyID, sampleID)) { + if (studyID.equals(ARCHER)) { + // check if patient exists in mskimpact + return checkIfPatientExists(IMPACT, sampleID); + } else { + return false; + } + } + return true; + } + + private boolean checkIfSampleExistsInStudy(String studyID, String sampleID) { + try { + sampleService.getSampleInStudy(studyID, sampleID); + } catch (SampleNotFoundException e) { + return false; + } catch (StudyNotFoundException e) { + return false; + } + // note if we map to a study that they do not have permission to view + // then an AccessDeniedException will be thrown that we cannot catch here + return true; + } + + private String getPatientID(String sampleID) { + Matcher matcher = dmpSampleIDPattern.matcher(sampleID); + if (matcher.find()) { + return matcher.group(1); + } + return null; + } + + private String getCancerStudy(String sampleID) { + // TODO: create tech stack to get study id given sample id + Matcher matcher = dmpSampleIDPattern.matcher(sampleID); + if (matcher.find()) { + String sampleIDSuffix = matcher.group(2); + if (sampleIDSuffix.contains("TS") || sampleIDSuffix.contains("TB")) { + return RAINDANCE; + } else if (sampleIDSuffix.contains("AS") || sampleIDSuffix.contains("AH")) { + return ARCHER; + } + } + return IMPACT; + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/MutationController.java b/src/main/java/org/cbioportal/legacy/web/MutationController.java new file mode 100644 index 00000000000..12c34634d02 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/MutationController.java @@ -0,0 +1,336 @@ +package org.cbioportal.legacy.web; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.ArraySchema; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import jakarta.validation.constraints.Max; +import jakarta.validation.constraints.Min; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; +import org.cbioportal.legacy.model.Mutation; +import org.cbioportal.legacy.model.meta.MutationMeta; +import org.cbioportal.legacy.service.MutationService; +import org.cbioportal.legacy.service.exception.MolecularProfileNotFoundException; +import org.cbioportal.legacy.web.config.PublicApiTags; +import org.cbioportal.legacy.web.config.annotation.PublicApi; +import org.cbioportal.legacy.web.parameter.Direction; +import org.cbioportal.legacy.web.parameter.HeaderKeyConstants; +import org.cbioportal.legacy.web.parameter.MutationFilter; +import org.cbioportal.legacy.web.parameter.MutationMultipleStudyFilter; +import org.cbioportal.legacy.web.parameter.PagingConstants; +import org.cbioportal.legacy.web.parameter.Projection; +import org.cbioportal.legacy.web.parameter.SampleMolecularIdentifier; +import org.cbioportal.legacy.web.parameter.sort.MutationSortBy; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestAttribute; +import org.springframework.web.bind.annotation.RequestBody; +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.bind.annotation.RestController; + +@PublicApi +@RestController() +@RequestMapping("/api") +@Validated +@Tag(name = PublicApiTags.MUTATIONS, description = " ") +public class MutationController { + + @Autowired private MutationService mutationService; + + @PreAuthorize( + "hasPermission(#molecularProfileId, 'MolecularProfileId', T(org.cbioportal.legacy.utils.security.AccessLevel).READ)") + @RequestMapping( + value = "/molecular-profiles/{molecularProfileId}/mutations", + method = RequestMethod.GET, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(description = "Get mutations in a molecular profile by Sample List ID") + @ApiResponse( + responseCode = "200", + description = "OK", + content = @Content(array = @ArraySchema(schema = @Schema(implementation = Mutation.class)))) + public ResponseEntity> getMutationsInMolecularProfileBySampleListId( + @Parameter(required = true, description = "Molecular Profile ID e.g. acc_tcga_mutations") + @PathVariable + String molecularProfileId, + @Parameter(required = true, description = "Sample List ID e.g. acc_tcga_all") @RequestParam + String sampleListId, + @Parameter(description = "Entrez Gene ID") @RequestParam(required = false) + Integer entrezGeneId, + @Parameter(description = "Level of detail of the response") + @RequestParam(defaultValue = "SUMMARY") + Projection projection, + @Parameter(description = "Page size of the result list") + @Max(PagingConstants.MAX_PAGE_SIZE) + @Min(PagingConstants.MIN_PAGE_SIZE) + @RequestParam(defaultValue = PagingConstants.DEFAULT_PAGE_SIZE) + Integer pageSize, + @Parameter(description = "Page number of the result list") + @Min(PagingConstants.MIN_PAGE_NUMBER) + @RequestParam(defaultValue = PagingConstants.DEFAULT_PAGE_NUMBER) + Integer pageNumber, + @Parameter(description = "Name of the property that the result list is sorted by") + @RequestParam(required = false) + MutationSortBy sortBy, + @Parameter(description = "Direction of the sort") @RequestParam(defaultValue = "ASC") + Direction direction) + throws MolecularProfileNotFoundException { + + if (projection == Projection.META) { + HttpHeaders responseHeaders = new HttpHeaders(); + MutationMeta mutationMeta = + mutationService.getMetaMutationsInMolecularProfileBySampleListId( + molecularProfileId, + sampleListId, + entrezGeneId == null ? null : Arrays.asList(entrezGeneId)); + responseHeaders.add(HeaderKeyConstants.TOTAL_COUNT, mutationMeta.getTotalCount().toString()); + responseHeaders.add( + HeaderKeyConstants.SAMPLE_COUNT, mutationMeta.getSampleCount().toString()); + return new ResponseEntity<>(responseHeaders, HttpStatus.OK); + } else { + return new ResponseEntity<>( + mutationService.getMutationsInMolecularProfileBySampleListId( + molecularProfileId, + sampleListId, + entrezGeneId == null ? null : Arrays.asList(entrezGeneId), + false, + projection.name(), + pageSize, + pageNumber, + sortBy == null ? null : sortBy.getOriginalValue(), + direction.name()), + HttpStatus.OK); + } + } + + @PreAuthorize( + "hasPermission(#molecularProfileId, 'MolecularProfileId', T(org.cbioportal.legacy.utils.security.AccessLevel).READ)") + @RequestMapping( + value = "/molecular-profiles/{molecularProfileId}/mutations/fetch", + method = RequestMethod.POST, + consumes = MediaType.APPLICATION_JSON_VALUE, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(description = "Fetch mutations in a molecular profile") + @ApiResponse( + responseCode = "200", + description = "OK", + content = @Content(array = @ArraySchema(schema = @Schema(implementation = Mutation.class)))) + public ResponseEntity> fetchMutationsInMolecularProfile( + @Parameter(required = true, description = "Molecular Profile ID e.g. acc_tcga_mutations") + @PathVariable + String molecularProfileId, + @Parameter( + required = true, + description = "List of Sample IDs/Sample List ID and Entrez Gene IDs") + @Valid + @RequestBody + MutationFilter mutationFilter, + @Parameter(description = "Level of detail of the response") + @RequestParam(defaultValue = "SUMMARY") + Projection projection, + @Parameter(description = "Page size of the result list") + @Max(PagingConstants.MAX_PAGE_SIZE) + @Min(PagingConstants.MIN_PAGE_SIZE) + @RequestParam(defaultValue = PagingConstants.DEFAULT_PAGE_SIZE) + Integer pageSize, + @Parameter(description = "Page number of the result list") + @Min(PagingConstants.MIN_PAGE_NUMBER) + @RequestParam(defaultValue = PagingConstants.DEFAULT_PAGE_NUMBER) + Integer pageNumber, + @Parameter(description = "Name of the property that the result list is sorted by") + @RequestParam(required = false) + MutationSortBy sortBy, + @Parameter(description = "Direction of the sort") @RequestParam(defaultValue = "ASC") + Direction direction) + throws MolecularProfileNotFoundException { + + if (projection == Projection.META) { + HttpHeaders responseHeaders = new HttpHeaders(); + MutationMeta mutationMeta; + + if (mutationFilter.getSampleListId() != null) { + mutationMeta = + mutationService.getMetaMutationsInMolecularProfileBySampleListId( + molecularProfileId, + mutationFilter.getSampleListId(), + mutationFilter.getEntrezGeneIds()); + } else { + mutationMeta = + mutationService.fetchMetaMutationsInMolecularProfile( + molecularProfileId, + mutationFilter.getSampleIds(), + mutationFilter.getEntrezGeneIds()); + } + responseHeaders.add(HeaderKeyConstants.TOTAL_COUNT, mutationMeta.getTotalCount().toString()); + responseHeaders.add( + HeaderKeyConstants.SAMPLE_COUNT, mutationMeta.getSampleCount().toString()); + return new ResponseEntity<>(responseHeaders, HttpStatus.OK); + } else { + List mutations; + if (mutationFilter.getSampleListId() != null) { + mutations = + mutationService.getMutationsInMolecularProfileBySampleListId( + molecularProfileId, + mutationFilter.getSampleListId(), + mutationFilter.getEntrezGeneIds(), + false, + projection.name(), + pageSize, + pageNumber, + sortBy == null ? null : sortBy.getOriginalValue(), + direction.name()); + } else { + mutations = + mutationService.fetchMutationsInMolecularProfile( + molecularProfileId, + mutationFilter.getSampleIds(), + mutationFilter.getEntrezGeneIds(), + false, + projection.name(), + pageSize, + pageNumber, + sortBy == null ? null : sortBy.getOriginalValue(), + direction.name()); + } + + return new ResponseEntity<>(mutations, HttpStatus.OK); + } + } + + @PreAuthorize( + "hasPermission(#involvedCancerStudies, 'Collection', T(org.cbioportal.legacy.utils.security.AccessLevel).READ)") + @RequestMapping( + value = "/mutations/fetch", + method = RequestMethod.POST, + consumes = MediaType.APPLICATION_JSON_VALUE, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(description = "Fetch mutations in multiple molecular profiles by sample IDs") + @ApiResponse( + responseCode = "200", + description = "OK", + content = @Content(array = @ArraySchema(schema = @Schema(implementation = Mutation.class)))) + public ResponseEntity> fetchMutationsInMultipleMolecularProfiles( + @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface + @RequestAttribute(required = false, value = "involvedCancerStudies") + Collection involvedCancerStudies, + @Parameter( + hidden = + true) // prevent reference to this attribute in the swagger-ui interface. this + // attribute is needed for the @PreAuthorize tag above. + @Valid + @RequestAttribute(required = false, value = "interceptedMutationMultipleStudyFilter") + MutationMultipleStudyFilter interceptedMutationMultipleStudyFilter, + @Parameter( + required = true, + description = + "List of Molecular Profile IDs or List of Molecular Profile ID / Sample ID pairs," + + " and List of Entrez Gene IDs") + @Valid + @RequestBody(required = false) + MutationMultipleStudyFilter mutationMultipleStudyFilter, + @Parameter(description = "Level of detail of the response") + @RequestParam(defaultValue = "SUMMARY") + Projection projection, + @Parameter(description = "Page size of the result list") + @Max(PagingConstants.MAX_PAGE_SIZE) + @Min(PagingConstants.MIN_PAGE_SIZE) + @RequestParam(defaultValue = PagingConstants.DEFAULT_PAGE_SIZE) + Integer pageSize, + @Parameter(description = "Page number of the result list") + @Min(PagingConstants.MIN_PAGE_NUMBER) + @RequestParam(defaultValue = PagingConstants.DEFAULT_PAGE_NUMBER) + Integer pageNumber, + @Parameter(description = "Name of the property that the result list is sorted by") + @RequestParam(required = false) + MutationSortBy sortBy, + @Parameter(description = "Direction of the sort") @RequestParam(defaultValue = "ASC") + Direction direction) { + + if (projection == Projection.META) { + HttpHeaders responseHeaders = new HttpHeaders(); + MutationMeta mutationMeta; + + if (interceptedMutationMultipleStudyFilter.getMolecularProfileIds() != null) { + mutationMeta = + mutationService.getMetaMutationsInMultipleMolecularProfiles( + interceptedMutationMultipleStudyFilter.getMolecularProfileIds(), + null, + interceptedMutationMultipleStudyFilter.getEntrezGeneIds()); + } else { + + List molecularProfileIds = new ArrayList<>(); + List sampleIds = new ArrayList<>(); + extractMolecularProfileAndSampleIds( + interceptedMutationMultipleStudyFilter, molecularProfileIds, sampleIds); + mutationMeta = + mutationService.getMetaMutationsInMultipleMolecularProfiles( + molecularProfileIds, + sampleIds, + interceptedMutationMultipleStudyFilter.getEntrezGeneIds()); + } + responseHeaders.add(HeaderKeyConstants.TOTAL_COUNT, mutationMeta.getTotalCount().toString()); + responseHeaders.add( + HeaderKeyConstants.SAMPLE_COUNT, mutationMeta.getSampleCount().toString()); + return new ResponseEntity<>(responseHeaders, HttpStatus.OK); + } else { + List mutations; + if (interceptedMutationMultipleStudyFilter.getMolecularProfileIds() != null) { + mutations = + mutationService.getMutationsInMultipleMolecularProfiles( + interceptedMutationMultipleStudyFilter.getMolecularProfileIds(), + null, + interceptedMutationMultipleStudyFilter.getEntrezGeneIds(), + projection.name(), + pageSize, + pageNumber, + sortBy == null ? null : sortBy.getOriginalValue(), + direction.name()); + } else { + + List molecularProfileIds = new ArrayList<>(); + List sampleIds = new ArrayList<>(); + extractMolecularProfileAndSampleIds( + interceptedMutationMultipleStudyFilter, molecularProfileIds, sampleIds); + mutations = + mutationService.getMutationsInMultipleMolecularProfiles( + molecularProfileIds, + sampleIds, + interceptedMutationMultipleStudyFilter.getEntrezGeneIds(), + projection.name(), + pageSize, + pageNumber, + sortBy == null ? null : sortBy.getOriginalValue(), + direction.name()); + } + + return new ResponseEntity<>(mutations, HttpStatus.OK); + } + } + + private void extractMolecularProfileAndSampleIds( + MutationMultipleStudyFilter mutationMultipleStudyFilter, + List molecularProfileIds, + List sampleIds) { + + for (SampleMolecularIdentifier sampleMolecularIdentifier : + mutationMultipleStudyFilter.getSampleMolecularIdentifiers()) { + + molecularProfileIds.add(sampleMolecularIdentifier.getMolecularProfileId()); + sampleIds.add(sampleMolecularIdentifier.getSampleId()); + } + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/MutationCountController.java b/src/main/java/org/cbioportal/legacy/web/MutationCountController.java new file mode 100644 index 00000000000..fa67b75d0e8 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/MutationCountController.java @@ -0,0 +1,72 @@ +package org.cbioportal.legacy.web; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.ArraySchema; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.constraints.Size; +import java.util.ArrayList; +import java.util.List; +import org.cbioportal.legacy.model.MutationCountByPosition; +import org.cbioportal.legacy.service.MutationService; +import org.cbioportal.legacy.web.config.InternalApiTags; +import org.cbioportal.legacy.web.config.annotation.InternalApi; +import org.cbioportal.legacy.web.parameter.MutationPositionIdentifier; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RestController; + +@InternalApi +@RestController +@Validated +@Tag(name = InternalApiTags.MUTATIONS_COUNT, description = " ") +public class MutationCountController { + + public static final int MUTATION_MAX_PAGE_SIZE = 10000000; + + @Autowired private MutationService mutationService; + + @RequestMapping( + value = "/api/mutation-counts-by-position/fetch", + method = RequestMethod.POST, + consumes = MediaType.APPLICATION_JSON_VALUE, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(description = "Fetch mutation counts in all studies by gene and position") + @ApiResponse( + responseCode = "200", + description = "OK", + content = + @Content( + array = + @ArraySchema(schema = @Schema(implementation = MutationCountByPosition.class)))) + public ResponseEntity> fetchMutationCountsByPosition( + @Parameter(required = true, description = "List of Mutation Position Identifiers") + @Size(min = 1, max = MUTATION_MAX_PAGE_SIZE) + @RequestBody + List mutationPositionIdentifiers) { + + List entrezGeneIds = new ArrayList<>(); + List proteinPosStarts = new ArrayList<>(); + List proteinPosEnds = new ArrayList<>(); + for (MutationPositionIdentifier mutationPositionIdentifier : mutationPositionIdentifiers) { + + entrezGeneIds.add(mutationPositionIdentifier.getEntrezGeneId()); + proteinPosStarts.add(mutationPositionIdentifier.getProteinPosStart()); + proteinPosEnds.add(mutationPositionIdentifier.getProteinPosEnd()); + } + + return new ResponseEntity<>( + mutationService.fetchMutationCountsByPosition( + entrezGeneIds, proteinPosStarts, proteinPosEnds), + HttpStatus.OK); + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/MutationSpectrumController.java b/src/main/java/org/cbioportal/legacy/web/MutationSpectrumController.java new file mode 100644 index 00000000000..66f166b5bbf --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/MutationSpectrumController.java @@ -0,0 +1,74 @@ +package org.cbioportal.legacy.web; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.ArraySchema; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import java.util.List; +import org.cbioportal.legacy.model.MutationSpectrum; +import org.cbioportal.legacy.service.MutationSpectrumService; +import org.cbioportal.legacy.service.exception.MolecularProfileNotFoundException; +import org.cbioportal.legacy.web.config.annotation.InternalApi; +import org.cbioportal.legacy.web.parameter.MutationSpectrumFilter; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RestController; + +@InternalApi +@RestController() +@RequestMapping("/api") +@Validated +@Tag(name = "Mutation Spectrums", description = " ") +public class MutationSpectrumController { + + @Autowired private MutationSpectrumService mutationSpectrumService; + + @PreAuthorize( + "hasPermission(#molecularProfileId, 'MolecularProfileId', T(org.cbioportal.legacy.utils.security.AccessLevel).READ)") + @RequestMapping( + value = "/molecular-profiles/{molecularProfileId}/mutation-spectrums/fetch", + method = RequestMethod.POST, + consumes = MediaType.APPLICATION_JSON_VALUE, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(description = "Fetch mutation spectrums in a molecular profile") + @ApiResponse( + responseCode = "200", + description = "OK", + content = + @Content(array = @ArraySchema(schema = @Schema(implementation = MutationSpectrum.class)))) + public ResponseEntity> fetchMutationSpectrums( + @Parameter(required = true, description = "Molecular Profile ID e.g. acc_tcga_mutations") + @PathVariable + String molecularProfileId, + @Parameter(required = true, description = "List of Sample IDs/Sample List ID") + @Valid + @RequestBody + MutationSpectrumFilter mutationSpectrumFilter) + throws MolecularProfileNotFoundException { + + List mutationSpectrums; + if (mutationSpectrumFilter.getSampleListId() != null) { + mutationSpectrums = + mutationSpectrumService.getMutationSpectrums( + molecularProfileId, mutationSpectrumFilter.getSampleListId()); + } else { + mutationSpectrums = + mutationSpectrumService.fetchMutationSpectrums( + molecularProfileId, mutationSpectrumFilter.getSampleIds()); + } + + return new ResponseEntity<>(mutationSpectrums, HttpStatus.OK); + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/NamespaceAttributeController.java b/src/main/java/org/cbioportal/legacy/web/NamespaceAttributeController.java new file mode 100644 index 00000000000..b8f2949ce9a --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/NamespaceAttributeController.java @@ -0,0 +1,51 @@ +package org.cbioportal.legacy.web; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.ArraySchema; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.tags.Tag; +import java.util.List; +import org.cbioportal.legacy.model.NamespaceAttribute; +import org.cbioportal.legacy.service.NamespaceAttributeService; +import org.cbioportal.legacy.web.config.PublicApiTags; +import org.cbioportal.legacy.web.config.annotation.PublicApi; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@PublicApi +@RestController() +@RequestMapping("/api") +@Tag(name = PublicApiTags.NAMESPACE_ATTRIBUTES, description = " ") +public class NamespaceAttributeController { + + private final NamespaceAttributeService namespaceAttributeService; + + @Autowired + public NamespaceAttributeController(NamespaceAttributeService namespaceAttributeService) { + this.namespaceAttributeService = namespaceAttributeService; + } + + @PostMapping(path = "/namespace-attributes/fetch") + @Operation(description = "Fetch namespace attributes") + @ApiResponse( + responseCode = "200", + description = "OK", + content = + @Content( + array = @ArraySchema(schema = @Schema(implementation = NamespaceAttribute.class)))) + public ResponseEntity> fetchNamespace( + @Parameter(required = true, description = "List of Study IDs") @RequestBody + List studyIds) { + + return new ResponseEntity<>( + namespaceAttributeService.fetchNamespaceAttributes(studyIds), HttpStatus.OK); + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/NamespaceAttributeCountController.java b/src/main/java/org/cbioportal/legacy/web/NamespaceAttributeCountController.java new file mode 100644 index 00000000000..5085730584e --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/NamespaceAttributeCountController.java @@ -0,0 +1,97 @@ +package org.cbioportal.legacy.web; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.ArraySchema; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import org.cbioportal.legacy.model.NamespaceAttribute; +import org.cbioportal.legacy.model.NamespaceAttributeCount; +import org.cbioportal.legacy.service.NamespaceAttributeService; +import org.cbioportal.legacy.web.config.InternalApiTags; +import org.cbioportal.legacy.web.config.annotation.InternalApi; +import org.cbioportal.legacy.web.parameter.NamespaceAttributeCountFilter; +import org.cbioportal.legacy.web.parameter.SampleIdentifier; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestAttribute; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@InternalApi +@RestController() +@RequestMapping("/api") +@Validated +@Tag(name = InternalApiTags.NAMESPACE_ATTRIBUTES_COUNT, description = " ") +public class NamespaceAttributeCountController { + + private final NamespaceAttributeService namespaceAttributeService; + + @Autowired + public NamespaceAttributeCountController(NamespaceAttributeService namespaceAttributeService) { + this.namespaceAttributeService = namespaceAttributeService; + } + + @PreAuthorize( + "hasPermission(#involvedCancerStudies, 'Collection', T(org.cbioportal.utils.security.AccessLevel).READ)") + @PostMapping( + path = "/namespace-attributes/counts/fetch", + consumes = MediaType.APPLICATION_JSON_VALUE, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation( + description = + "Get counts for namespace attributes according to their data availability for selected samples/patients") + @ApiResponse( + responseCode = "200", + description = "OK", + content = + @Content( + array = + @ArraySchema(schema = @Schema(implementation = NamespaceAttributeCount.class)))) + public ResponseEntity> getNamespaceAttributeCounts( + @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface + @RequestAttribute(required = false, value = "involvedCancerStudies") + Collection involvedCancerStudies, + @Parameter( + hidden = + true) // prevent reference to this attribute in the swagger-ui interface. this + // attribute is needed for the @PreAuthorize tag above. + @Valid + @RequestAttribute(required = false, value = "interceptedNamespaceAttributeCountFilter") + NamespaceAttributeCountFilter interceptedNamespaceAttributeCountFilter, + @Parameter(required = true, description = "List of SampleIdentifiers and NamespaceAttributes") + @Valid + @RequestBody(required = false) + NamespaceAttributeCountFilter namespaceAttributeCountFilter) { + + List namespaceAttributeCountList; + List sampleIdentifiers = + interceptedNamespaceAttributeCountFilter.getSampleIdentifiers(); + List namespaceAttributes = + interceptedNamespaceAttributeCountFilter.getNamespaceAttributes(); + List studyIds = new ArrayList<>(); + List sampleIds = new ArrayList<>(); + for (SampleIdentifier sampleIdentifier : sampleIdentifiers) { + studyIds.add(sampleIdentifier.getStudyId()); + sampleIds.add(sampleIdentifier.getSampleId()); + } + + namespaceAttributeCountList = + namespaceAttributeService.fetchNamespaceAttributeCountsBySampleIds( + studyIds, sampleIds, namespaceAttributes); + + return new ResponseEntity<>(namespaceAttributeCountList, HttpStatus.OK); + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/NamespaceDataController.java b/src/main/java/org/cbioportal/legacy/web/NamespaceDataController.java new file mode 100644 index 00000000000..ce0964ece66 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/NamespaceDataController.java @@ -0,0 +1,95 @@ +package org.cbioportal.legacy.web; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.ArraySchema; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import org.cbioportal.legacy.model.NamespaceAttribute; +import org.cbioportal.legacy.model.NamespaceData; +import org.cbioportal.legacy.service.NamespaceDataService; +import org.cbioportal.legacy.web.config.InternalApiTags; +import org.cbioportal.legacy.web.config.annotation.InternalApi; +import org.cbioportal.legacy.web.parameter.NamespaceComparisonFilter; +import org.cbioportal.legacy.web.parameter.SampleIdentifier; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestAttribute; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@InternalApi +@RestController() +@RequestMapping("/api") +@Validated +@Tag(name = InternalApiTags.NAMESPACE_DATA, description = " ") +public class NamespaceDataController { + + private final NamespaceDataService namespaceDataService; + + @Autowired + public NamespaceDataController(NamespaceDataService namespaceDataService) { + this.namespaceDataService = namespaceDataService; + } + + @PreAuthorize( + "hasPermission(#involvedCancerStudies, 'Collection', T(org.cbioportal.utils.security.AccessLevel).READ)") + @PostMapping( + value = "/namespace-data/fetch", + consumes = MediaType.APPLICATION_JSON_VALUE, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation( + description = "Get namespace data for comparison page for the selected samples and values") + @ApiResponse( + responseCode = "200", + description = "OK", + content = + @Content(array = @ArraySchema(schema = @Schema(implementation = NamespaceData.class)))) + public ResponseEntity> getNamespaceDataForComparison( + @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface + @RequestAttribute(required = false, value = "involvedCancerStudies") + Collection involvedCancerStudies, + @Parameter( + hidden = + true) // prevent reference to this attribute in the swagger-ui interface. this + // attribute is needed for the @PreAuthorize tag above. + @Valid + @RequestAttribute(required = false, value = "interceptedNamespaceComparisonFilter") + NamespaceComparisonFilter interceptedNamespaceComparisonFilter, + @Parameter( + required = true, + description = "List of SampleIdentifiers, list of values and a NamespaceAttribute") + @Valid + @RequestBody(required = false) + NamespaceComparisonFilter namespaceComparisonFilter) { + + List namespaceDataList; + List sampleIdentifiers = namespaceComparisonFilter.getSampleIdentifiers(); + NamespaceAttribute namespaceAttribute = namespaceComparisonFilter.getNamespaceAttribute(); + List values = namespaceComparisonFilter.getValues(); + List studyIds = new ArrayList<>(); + List sampleIds = new ArrayList<>(); + for (SampleIdentifier sampleIdentifier : sampleIdentifiers) { + studyIds.add(sampleIdentifier.getStudyId()); + sampleIds.add(sampleIdentifier.getSampleId()); + } + + namespaceDataList = + namespaceDataService.fetchNamespaceDataForComparison( + studyIds, sampleIds, namespaceAttribute, values); + + return new ResponseEntity<>(namespaceDataList, HttpStatus.OK); + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/OAuth2DataAccessTokenController.java b/src/main/java/org/cbioportal/legacy/web/OAuth2DataAccessTokenController.java new file mode 100644 index 00000000000..1ce660015ba --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/OAuth2DataAccessTokenController.java @@ -0,0 +1,219 @@ +/* + * Copyright (c) 2020 The Hyve B.V. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS + * FOR A PARTICULAR PURPOSE. The software and documentation provided hereunder + * is on an "as is" basis, and Memorial Sloan-Kettering Cancer Center has no + * obligations to provide maintenance, support, updates, enhancements or + * modifications. In no event shall Memorial Sloan-Kettering Cancer Center be + * liable to any party for direct, indirect, special, incidental or + * consequential damages, including lost profits, arising out of the use of this + * software and its documentation, even if Memorial Sloan-Kettering Cancer + * Center has been advised of the possibility of such damage. + */ + +/* + * This file is part of cBioPortal. + * + * cBioPortal is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package org.cbioportal.legacy.web; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.ArraySchema; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.PostConstruct; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; +import java.util.List; +import org.apache.commons.lang3.StringUtils; +import org.cbioportal.legacy.model.DataAccessToken; +import org.cbioportal.legacy.service.DataAccessTokenService; +import org.cbioportal.legacy.service.exception.DataAccessTokenNoUserIdentityException; +import org.cbioportal.legacy.service.exception.DataAccessTokenProhibitedUserException; +import org.cbioportal.legacy.utils.config.annotation.ConditionalOnProperty; +import org.cbioportal.legacy.web.config.annotation.InternalApi; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.client.HttpClientErrorException; + +@InternalApi +@Validated +@Tag(name = "Data Access Tokens", description = " ") +@RestController +@ConditionalOnProperty(name = "dat.method", havingValue = "oauth2") +public class OAuth2DataAccessTokenController { + + @Value("${dat.oauth2.userAuthorizationUri}") + private String userAuthorizationUri; + + @Value("${dat.oauth2.redirectUri}") + private String redirectUri; + + @Value("${dat.oauth2.clientId}") + private String clientId; + + @Value("${dat.filter_user_role:}") // default is empty string + private String userRoleToAccessToken; + + @Autowired private DataAccessTokenService tokenService; + private String authorizationUrl; + private String fileName = "cbioportal_data_access_token.txt"; + + @PostConstruct + public void postConstruct() throws UnsupportedEncodingException { + + String scopeEncoded = + URLEncoder.encode("openid offline_access", StandardCharsets.UTF_8.toString()); + String clientIdEncoded = URLEncoder.encode(clientId, StandardCharsets.UTF_8.toString()); + String redirUriEncode = URLEncoder.encode(redirectUri, StandardCharsets.UTF_8.toString()); + + authorizationUrl = + String.format( + "%s?response_type=%s&scope=%s&client_id=%s&redirect_uri=%s", + userAuthorizationUri, "code", scopeEncoded, clientIdEncoded, redirUriEncode); + } + + // This is the entrypoint for the cBioPortal frontend to download a single user token. + // Redirect the browser to the authorizationUrl. + @RequestMapping(method = RequestMethod.GET, value = "/api/data-access-token") + @Operation(description = "Create a new data access token") + @ApiResponse( + responseCode = "200", + description = "OK", + content = @Content(schema = @Schema(implementation = String.class))) + public ResponseEntity downloadDataAccessToken( + Authentication authentication, HttpServletRequest request, HttpServletResponse response) + throws IOException { + + isUserAuthorizedToAccess(authentication); + + // redirect to authentication endpoint + HttpHeaders headers = new HttpHeaders(); + headers.add("Location", authorizationUrl); + return new ResponseEntity<>(headers, HttpStatus.FOUND); + } + + // retrieve and trigger download OAuth2 offline token + @RequestMapping(method = RequestMethod.GET, value = "/api/data-access-token/oauth2") + @Parameter(hidden = true) + @ApiResponse( + responseCode = "200", + description = "OK", + content = @Content(schema = @Schema(implementation = String.class))) + public ResponseEntity downloadOAuth2DataAccessToken( + HttpServletRequest request, HttpServletResponse response) throws IOException { + + String accessCode = request.getParameter("code"); + DataAccessToken offlineToken = tokenService.createDataAccessToken(accessCode); + + if (offlineToken == null) { + throw new DataAccessTokenProhibitedUserException(); + } + + // add header to trigger download of the token by the browser + response.setHeader("Content-Disposition", "attachment; filename=" + fileName); + + return new ResponseEntity<>(offlineToken.toString(), HttpStatus.OK); + } + + @RequestMapping( + method = RequestMethod.POST, + value = "/api/data-access-tokens", + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(description = "Get all data access tokens") + @ApiResponse( + responseCode = "200", + description = "OK", + content = @Content(schema = @Schema(implementation = DataAccessToken.class))) + public ResponseEntity createDataAccessToken(Authentication authentication) + throws HttpClientErrorException { + throw new UnsupportedOperationException( + "this endpoint is does not apply to OAuth2 data access token method."); + } + + @RequestMapping(method = RequestMethod.GET, value = "/api/data-access-tokens") + @Operation(description = "Retrieve all data access tokens") + @ApiResponse( + responseCode = "200", + description = "OK", + content = + @Content(array = @ArraySchema(schema = @Schema(implementation = DataAccessToken.class)))) + public ResponseEntity> getAllDataAccessTokens( + HttpServletRequest request, Authentication authentication) { + throw new UnsupportedOperationException( + "this endpoint is does not apply to OAuth2 data access token method."); + } + + @RequestMapping(method = RequestMethod.GET, value = "/api/data-access-tokens/{token}") + @Operation(description = "Retrieve an existing data access token") + @ApiResponse( + responseCode = "200", + description = "OK", + content = @Content(schema = @Schema(implementation = DataAccessToken.class))) + public ResponseEntity getDataAccessToken( + @Parameter(required = true, description = "token") @PathVariable String token) { + throw new UnsupportedOperationException( + "this endpoint is does not apply to OAuth2 data access token method."); + } + + @RequestMapping(method = RequestMethod.DELETE, value = "/api/data-access-tokens") + @Operation(description = "Delete all data access tokens") + public void revokeAllDataAccessTokens(Authentication authentication) { + throw new UnsupportedOperationException( + "this endpoint is does not apply to OAuth2 data access token method."); + } + + @RequestMapping(method = RequestMethod.DELETE, value = "/api/data-access-tokens/{token}") + @Operation(description = "Delete a data access token") + public void revokeDataAccessToken( + @Parameter(required = true, description = "token") @PathVariable String token) { + throw new UnsupportedOperationException( + "this endpoint is does not apply to OAuth2 data access token method."); + } + + private void isUserAuthorizedToAccess(Authentication authentication) { + if (authentication == null || !authentication.isAuthenticated()) { + throw new DataAccessTokenNoUserIdentityException(); + } + + if (StringUtils.isNotEmpty(userRoleToAccessToken) + && !authentication + .getAuthorities() + .contains(new SimpleGrantedAuthority(userRoleToAccessToken))) { + throw new DataAccessTokenProhibitedUserException(); + } + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/PatientController.java b/src/main/java/org/cbioportal/legacy/web/PatientController.java new file mode 100644 index 00000000000..bd2c428f47f --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/PatientController.java @@ -0,0 +1,246 @@ +package org.cbioportal.legacy.web; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.ArraySchema; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import jakarta.validation.constraints.Max; +import jakarta.validation.constraints.Min; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import org.cbioportal.legacy.model.Patient; +import org.cbioportal.legacy.service.PatientService; +import org.cbioportal.legacy.service.exception.PatientNotFoundException; +import org.cbioportal.legacy.service.exception.StudyNotFoundException; +import org.cbioportal.legacy.web.config.PublicApiTags; +import org.cbioportal.legacy.web.config.annotation.PublicApi; +import org.cbioportal.legacy.web.parameter.Direction; +import org.cbioportal.legacy.web.parameter.HeaderKeyConstants; +import org.cbioportal.legacy.web.parameter.PagingConstants; +import org.cbioportal.legacy.web.parameter.PatientFilter; +import org.cbioportal.legacy.web.parameter.PatientIdentifier; +import org.cbioportal.legacy.web.parameter.Projection; +import org.cbioportal.legacy.web.parameter.sort.PatientSortBy; +import org.cbioportal.legacy.web.util.UniqueKeyExtractor; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestAttribute; +import org.springframework.web.bind.annotation.RequestBody; +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.bind.annotation.RestController; + +@PublicApi +@RestController() +@RequestMapping("/api") +@Validated +@Tag(name = PublicApiTags.PATIENTS, description = " ") +public class PatientController { + + @Autowired private PatientService patientService; + + @RequestMapping( + value = "/patients", + method = RequestMethod.GET, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(description = "Get all patients") + @ApiResponse( + responseCode = "200", + description = "OK", + content = @Content(array = @ArraySchema(schema = @Schema(implementation = Patient.class)))) + public ResponseEntity> getAllPatients( + @Parameter(description = "Search keyword that applies to ID of the patients") + @RequestParam(required = false) + String keyword, + @Parameter(description = "Level of detail of the response") + @RequestParam(defaultValue = "SUMMARY") + Projection projection, + @Parameter(description = "Page size of the result list") + @Max(PagingConstants.MAX_PAGE_SIZE) + @Min(PagingConstants.MIN_PAGE_SIZE) + @RequestParam(defaultValue = PagingConstants.DEFAULT_PAGE_SIZE) + Integer pageSize, + @Parameter(description = "Page number of the result list") + @Min(PagingConstants.MIN_PAGE_NUMBER) + @RequestParam(defaultValue = PagingConstants.DEFAULT_PAGE_NUMBER) + Integer pageNumber, + @Parameter(description = "Name of the property that the result list is sorted by") + @RequestParam(required = false) + PatientSortBy sortBy, + @Parameter(description = "Direction of the sort") @RequestParam(defaultValue = "ASC") + Direction direction) + throws StudyNotFoundException { + + if (projection == Projection.META) { + HttpHeaders responseHeaders = new HttpHeaders(); + responseHeaders.add( + HeaderKeyConstants.TOTAL_COUNT, + patientService.getMetaPatients(keyword).getTotalCount().toString()); + return new ResponseEntity<>(responseHeaders, HttpStatus.OK); + } else { + return new ResponseEntity<>( + patientService.getAllPatients( + keyword, + projection.name(), + pageSize, + pageNumber, + sortBy == null ? null : sortBy.getOriginalValue(), + direction.name()), + HttpStatus.OK); + } + } + + @PreAuthorize( + "hasPermission(#studyId, 'CancerStudyId', T(org.cbioportal.legacy.utils.security.AccessLevel).READ)") + @RequestMapping( + value = "/studies/{studyId}/patients", + method = RequestMethod.GET, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(description = "Get all patients in a study") + @ApiResponse( + responseCode = "200", + description = "OK", + content = @Content(array = @ArraySchema(schema = @Schema(implementation = Patient.class)))) + public ResponseEntity> getAllPatientsInStudy( + @Parameter(required = true, description = "Study ID e.g. acc_tcga") @PathVariable + String studyId, + @Parameter(description = "Level of detail of the response") + @RequestParam(defaultValue = "SUMMARY") + Projection projection, + @Parameter(description = "Page size of the result list") + @Max(PagingConstants.MAX_PAGE_SIZE) + @Min(PagingConstants.MIN_PAGE_SIZE) + @RequestParam(defaultValue = PagingConstants.DEFAULT_PAGE_SIZE) + Integer pageSize, + @Parameter(description = "Page number of the result list") + @Min(PagingConstants.MIN_PAGE_NUMBER) + @RequestParam(defaultValue = PagingConstants.DEFAULT_PAGE_NUMBER) + Integer pageNumber, + @Parameter(description = "Name of the property that the result list is sorted by") + @RequestParam(required = false) + PatientSortBy sortBy, + @Parameter(description = "Direction of the sort") @RequestParam(defaultValue = "ASC") + Direction direction) + throws StudyNotFoundException { + + if (projection == Projection.META) { + HttpHeaders responseHeaders = new HttpHeaders(); + responseHeaders.add( + HeaderKeyConstants.TOTAL_COUNT, + patientService.getMetaPatientsInStudy(studyId).getTotalCount().toString()); + return new ResponseEntity<>(responseHeaders, HttpStatus.OK); + } else { + return new ResponseEntity<>( + patientService.getAllPatientsInStudy( + studyId, + projection.name(), + pageSize, + pageNumber, + sortBy == null ? null : sortBy.getOriginalValue(), + direction.name()), + HttpStatus.OK); + } + } + + @PreAuthorize( + "hasPermission(#studyId, 'CancerStudyId', T(org.cbioportal.legacy.utils.security.AccessLevel).READ)") + @RequestMapping( + value = "/studies/{studyId}/patients/{patientId}", + method = RequestMethod.GET, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(description = "Get a patient in a study") + @ApiResponse( + responseCode = "200", + description = "OK", + content = @Content(schema = @Schema(implementation = Patient.class))) + public ResponseEntity getPatientInStudy( + @Parameter(required = true, description = "Study ID e.g. acc_tcga") @PathVariable + String studyId, + @Parameter(required = true, description = "Patient ID e.g. TCGA-OR-A5J2") @PathVariable + String patientId) + throws PatientNotFoundException, StudyNotFoundException { + + return new ResponseEntity<>( + patientService.getPatientInStudy(studyId, patientId), HttpStatus.OK); + } + + @PreAuthorize( + "hasPermission(#involvedCancerStudies, 'Collection', T(org.cbioportal.legacy.utils.security.AccessLevel).READ)") + @RequestMapping( + value = "/patients/fetch", + method = RequestMethod.POST, + consumes = MediaType.APPLICATION_JSON_VALUE, + produces = MediaType.APPLICATION_JSON_VALUE) + @ApiResponse( + responseCode = "200", + description = "OK", + content = @Content(array = @ArraySchema(schema = @Schema(implementation = Patient.class)))) + public ResponseEntity> fetchPatients( + @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface + @RequestAttribute(required = false, value = "involvedCancerStudies") + Collection involvedCancerStudies, + @Parameter( + hidden = + true) // prevent reference to this attribute in the swagger-ui interface. this + // attribute is needed for the @PreAuthorize tag above. + @Valid + @RequestAttribute(required = false, value = "interceptedPatientFilter") + PatientFilter interceptedPatientFilter, + @Parameter(required = true, description = "List of patient identifiers") + @Valid + @RequestBody(required = false) + PatientFilter patientFilter, + @Parameter(description = "Level of detail of the response") + @RequestParam(defaultValue = "SUMMARY") + Projection projection) { + + List studyIds = new ArrayList<>(); + List patientIds = new ArrayList<>(); + + if (projection == Projection.META) { + HttpHeaders responseHeaders = new HttpHeaders(); + if (interceptedPatientFilter.getPatientIdentifiers() != null) { + extractStudyAndPatientIds(interceptedPatientFilter, studyIds, patientIds); + } else { + UniqueKeyExtractor.extractUniqueKeys( + interceptedPatientFilter.getUniquePatientKeys(), studyIds, patientIds); + } + responseHeaders.add( + HeaderKeyConstants.TOTAL_COUNT, + patientService.fetchMetaPatients(studyIds, patientIds).getTotalCount().toString()); + return new ResponseEntity<>(responseHeaders, HttpStatus.OK); + } else { + if (interceptedPatientFilter.getPatientIdentifiers() != null) { + extractStudyAndPatientIds(interceptedPatientFilter, studyIds, patientIds); + } else { + UniqueKeyExtractor.extractUniqueKeys( + interceptedPatientFilter.getUniquePatientKeys(), studyIds, patientIds); + } + // TODO: since we are already extracting the studyIds in the interceptor, we might not need to + // use the service here + return new ResponseEntity<>( + patientService.fetchPatients(studyIds, patientIds, projection.name()), HttpStatus.OK); + } + } + + private void extractStudyAndPatientIds( + PatientFilter patientFilter, List studyIds, List patientIds) { + + for (PatientIdentifier patientIdentifier : patientFilter.getPatientIdentifiers()) { + studyIds.add(patientIdentifier.getStudyId()); + patientIds.add(patientIdentifier.getPatientId()); + } + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/PublicVirtualStudiesController.java b/src/main/java/org/cbioportal/legacy/web/PublicVirtualStudiesController.java new file mode 100644 index 00000000000..b701fadc753 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/PublicVirtualStudiesController.java @@ -0,0 +1,147 @@ +package org.cbioportal.legacy.web; + +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import java.util.List; +import java.util.NoSuchElementException; +import java.util.Set; +import org.cbioportal.legacy.service.CancerTypeService; +import org.cbioportal.legacy.service.exception.AccessForbiddenException; +import org.cbioportal.legacy.service.exception.CancerTypeNotFoundException; +import org.cbioportal.legacy.service.util.SessionServiceRequestHandler; +import org.cbioportal.legacy.web.parameter.VirtualStudy; +import org.cbioportal.legacy.web.parameter.VirtualStudyData; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestHeader; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; + +@Controller +@RequestMapping("/api/public_virtual_studies") +public class PublicVirtualStudiesController { + + private static final Logger LOG = LoggerFactory.getLogger(PublicVirtualStudiesController.class); + + public static final String ALL_USERS = "*"; + + private final String requiredPublisherApiKey; + + private final SessionServiceRequestHandler sessionServiceRequestHandler; + + private final CancerTypeService cancerTypeService; + + public PublicVirtualStudiesController( + @Value("${session.endpoint.publisher-api-key:}") String requiredPublisherApiKey, + SessionServiceRequestHandler sessionServiceRequestHandler, + CancerTypeService cancerTypeService) { + this.requiredPublisherApiKey = requiredPublisherApiKey; + this.sessionServiceRequestHandler = sessionServiceRequestHandler; + this.cancerTypeService = cancerTypeService; + } + + @GetMapping + @ApiResponse( + responseCode = "200", + description = "OK", + content = @Content(schema = @Schema(implementation = VirtualStudy.class))) + public ResponseEntity> getPublicVirtualStudies() { + List virtualStudies = + sessionServiceRequestHandler.getVirtualStudiesAccessibleToUser(ALL_USERS); + return new ResponseEntity<>(virtualStudies, HttpStatus.OK); + } + + @PostMapping("/{id}") + @ApiResponse( + responseCode = "200", + description = "OK", + content = @Content(schema = @Schema(implementation = VirtualStudy.class))) + public ResponseEntity publishVirtualStudy( + @PathVariable String id, + @RequestHeader(value = "X-PUBLISHER-API-KEY") String providedPublisherApiKey, + @RequestParam(required = false) String typeOfCancerId, + @RequestParam(required = false) String pmid) { + ensureProvidedPublisherApiKeyCorrect(providedPublisherApiKey); + publishVirtualStudy(id, typeOfCancerId, pmid); + return ResponseEntity.ok().build(); + } + + @DeleteMapping("/{id}") + @ApiResponse(responseCode = "200", description = "OK") + public ResponseEntity unPublishVirtualStudy( + @PathVariable String id, + @RequestHeader(value = "X-PUBLISHER-API-KEY") String providedPublisherApiKey) { + ensureProvidedPublisherApiKeyCorrect(providedPublisherApiKey); + unPublishVirtualStudy(id); + return ResponseEntity.ok().build(); + } + + /** + * Publishes virtual study optionally updating metadata fields + * + * @param id - id of public virtual study to publish + * @param typeOfCancerId - if specified (not null) update type of cancer of published virtual + * study + * @param pmid - if specified (not null) update PubMed ID of published virtual study + */ + private void publishVirtualStudy(String id, String typeOfCancerId, String pmid) { + VirtualStudy virtualStudyDataToPublish = sessionServiceRequestHandler.getVirtualStudyById(id); + VirtualStudyData virtualStudyData = virtualStudyDataToPublish.getData(); + updateStudyMetadataFieldsIfSpecified(virtualStudyData, typeOfCancerId, pmid); + virtualStudyData.setUsers(Set.of(ALL_USERS)); + sessionServiceRequestHandler.updateVirtualStudy(virtualStudyDataToPublish); + } + + /** + * Un-publish virtual study + * + * @param id - id of public virtual study to un-publish + */ + private void unPublishVirtualStudy(String id) { + VirtualStudy virtualStudyToUnPublish = sessionServiceRequestHandler.getVirtualStudyById(id); + if (virtualStudyToUnPublish == null) { + throw new NoSuchElementException( + "The virtual study with id=" + id + " has not been found in the public list."); + } + VirtualStudyData virtualStudyData = virtualStudyToUnPublish.getData(); + Set users = virtualStudyData.getUsers(); + if (users == null || users.isEmpty() || !users.contains(ALL_USERS)) { + throw new NoSuchElementException( + "The virtual study with id=" + id + " has not been found in the public list."); + } + virtualStudyData.setUsers(Set.of(virtualStudyData.getOwner())); + sessionServiceRequestHandler.updateVirtualStudy(virtualStudyToUnPublish); + } + + private void ensureProvidedPublisherApiKeyCorrect(String providedPublisherApiKey) { + if (requiredPublisherApiKey.isBlank() + || !requiredPublisherApiKey.equals(providedPublisherApiKey)) { + throw new AccessForbiddenException("The provided publisher API key is not correct."); + } + } + + private void updateStudyMetadataFieldsIfSpecified( + VirtualStudyData virtualStudyData, String typeOfCancerId, String pmid) { + if (typeOfCancerId != null) { + try { + cancerTypeService.getCancerType(typeOfCancerId); + virtualStudyData.setTypeOfCancerId(typeOfCancerId); + } catch (CancerTypeNotFoundException e) { + LOG.error("No cancer type with id={} were found.", typeOfCancerId); + throw new IllegalArgumentException("The cancer type is not valid: " + typeOfCancerId); + } + } + if (pmid != null) { + virtualStudyData.setPmid(pmid); + } + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/ReferenceGenomeGeneController.java b/src/main/java/org/cbioportal/legacy/web/ReferenceGenomeGeneController.java new file mode 100644 index 00000000000..b2aaa48241c --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/ReferenceGenomeGeneController.java @@ -0,0 +1,130 @@ +package org.cbioportal.legacy.web; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.ArraySchema; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.constraints.Size; +import java.util.List; +import java.util.stream.Collectors; +import org.cbioportal.legacy.model.ReferenceGenomeGene; +import org.cbioportal.legacy.service.GeneMemoizerService; +import org.cbioportal.legacy.service.ReferenceGenomeGeneService; +import org.cbioportal.legacy.service.exception.GeneNotFoundException; +import org.cbioportal.legacy.web.config.InternalApiTags; +import org.cbioportal.legacy.web.config.annotation.InternalApi; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RestController; + +@InternalApi +@RestController +@Validated +@Tag(name = InternalApiTags.REFERENCE_GENOME_GENES, description = " ") +public class ReferenceGenomeGeneController { + private static final int GENE_MAX_PAGE_SIZE = 100000; + private static final String GENE_DEFAULT_PAGE_SIZE = "100000"; + + @Autowired private ReferenceGenomeGeneService referenceGenomeGeneService; + + @Autowired private GeneMemoizerService geneMemoizerService; + + /** + * The memoization logic in this method is a temporary fix to make this work until Ehcache is + * working correctly on cbioportal.org. This endpoint creates a large response and seems to bloat + * the webserver's heap size, leading to poor performance and crashes. The caching seems to + * improve processor load, heap size and response time. + */ + @RequestMapping( + value = "/api/reference-genome-genes/{genomeName}", + method = RequestMethod.GET, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(description = "Get all reference genes") + @ApiResponse( + responseCode = "200", + description = "OK", + content = + @Content( + array = @ArraySchema(schema = @Schema(implementation = ReferenceGenomeGene.class)))) + public ResponseEntity> getAllReferenceGenomeGenes( + @Parameter(required = true, description = "Name of Reference Genome hg19") @PathVariable + String genomeName) { + + List genes = geneMemoizerService.fetchGenes(genomeName); + if (genes == null) { + genes = referenceGenomeGeneService.fetchAllReferenceGenomeGenes(genomeName); + geneMemoizerService.cacheGenes(genes, genomeName); + } + return new ResponseEntity<>(genes, HttpStatus.OK); + } + + @RequestMapping( + value = "/api/reference-genome-genes/{genomeName}/{geneId}", + method = RequestMethod.GET, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(description = "Get a gene of a reference genome of interest") + @ApiResponse( + responseCode = "200", + description = "OK", + content = @Content(schema = @Schema(implementation = ReferenceGenomeGene.class))) + public ResponseEntity getReferenceGenomeGene( + @Parameter(required = true, description = "Name of Reference Genome hg19") @PathVariable + String genomeName, + @Parameter(required = true, description = "Entrez Gene ID 207") @PathVariable Integer geneId) + throws GeneNotFoundException { + + return new ResponseEntity<>( + referenceGenomeGeneService.getReferenceGenomeGene(geneId, genomeName), HttpStatus.OK); + } + + @RequestMapping( + value = "/api/reference-genome-genes/{genomeName}/fetch", + method = RequestMethod.POST, + consumes = MediaType.APPLICATION_JSON_VALUE, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(description = "Fetch genes of reference genome of interest") + @ApiResponse( + responseCode = "200", + description = "OK", + content = + @Content( + array = @ArraySchema(schema = @Schema(implementation = ReferenceGenomeGene.class)))) + public ResponseEntity> fetchReferenceGenomeGenes( + @Parameter(required = true, description = "Name of Reference Genome hg19") @PathVariable + String genomeName, + @Parameter(required = true, description = "List of Gene IDs") + @Size(min = 1, max = GENE_MAX_PAGE_SIZE) + @RequestBody + List geneIds) { + + if (isInteger(geneIds.get(0))) { + List newIds = + geneIds.stream().map(s -> Integer.parseInt(s)).collect(Collectors.toList()); + return new ResponseEntity<>( + referenceGenomeGeneService.fetchGenesByGenomeName(newIds, genomeName), HttpStatus.OK); + } else { + return new ResponseEntity<>( + referenceGenomeGeneService.fetchGenesByHugoGeneSymbolsAndGenomeName(geneIds, genomeName), + HttpStatus.OK); + } + } + + private boolean isInteger(String s) { + try { + Integer.parseInt(s); + } catch (NumberFormatException | NullPointerException e) { + return false; + } + return true; + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/ResourceDataController.java b/src/main/java/org/cbioportal/legacy/web/ResourceDataController.java new file mode 100644 index 00000000000..cca78afc462 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/ResourceDataController.java @@ -0,0 +1,289 @@ +package org.cbioportal.legacy.web; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.ArraySchema; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.constraints.Max; +import jakarta.validation.constraints.Min; +import java.util.List; +import java.util.Objects; +import org.cbioportal.legacy.model.ResourceData; +import org.cbioportal.legacy.service.ResourceDataService; +import org.cbioportal.legacy.service.exception.PatientNotFoundException; +import org.cbioportal.legacy.service.exception.SampleNotFoundException; +import org.cbioportal.legacy.service.exception.StudyNotFoundException; +import org.cbioportal.legacy.web.config.InternalApiTags; +import org.cbioportal.legacy.web.config.annotation.InternalApi; +import org.cbioportal.legacy.web.parameter.Direction; +import org.cbioportal.legacy.web.parameter.PagingConstants; +import org.cbioportal.legacy.web.parameter.Projection; +import org.cbioportal.legacy.web.parameter.sort.ResourceDataSortBy; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.context.ApplicationContext; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.PathVariable; +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.bind.annotation.RestController; + +@InternalApi +@RestController() +@RequestMapping("/api") +@Validated +@Tag(name = InternalApiTags.RESOURCE_DATA, description = " ") +public class ResourceDataController { + + public static final int RESOURCE_DATA_MAX_PAGE_SIZE = 10000000; + private static final String RESOURCE_DATA_DEFAULT_PAGE_SIZE = "10000000"; + + @Autowired private ResourceDataService resourceDataService; + + @Autowired private ApplicationContext applicationContext; + ResourceDataController instance; + + private ResourceDataController getInstance() { + if (Objects.isNull(instance)) { + instance = applicationContext.getBean(ResourceDataController.class); + } + return instance; + } + + @PreAuthorize( + "hasPermission(#studyId, 'CancerStudyId', T(org.cbioportal.legacy.utils.security.AccessLevel).READ)") + @RequestMapping( + value = "/studies/{studyId}/samples/{sampleId}/resource-data", + method = RequestMethod.GET, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(description = "Get all resource data of a sample in a study") + @ApiResponse( + responseCode = "200", + description = "OK", + content = + @Content(array = @ArraySchema(schema = @Schema(implementation = ResourceData.class)))) + public ResponseEntity> getAllResourceDataOfSampleInStudy( + @Parameter(required = true, description = "Study ID e.g. acc_tcga") @PathVariable + String studyId, + @Parameter(required = true, description = "Sample ID e.g. TCGA-OR-A5J2-01") @PathVariable + String sampleId, + @Parameter(description = "Resource ID") @RequestParam(required = false) String resourceId, + @Parameter(description = "Level of detail of the response") + @RequestParam(defaultValue = "SUMMARY") + Projection projection, + @Parameter(description = "Page size of the result list") + @Max(RESOURCE_DATA_MAX_PAGE_SIZE) + @Min(PagingConstants.MIN_PAGE_SIZE) + @RequestParam(defaultValue = RESOURCE_DATA_DEFAULT_PAGE_SIZE) + Integer pageSize, + @Parameter(description = "Page number of the result list") + @Min(PagingConstants.MIN_PAGE_NUMBER) + @RequestParam(defaultValue = PagingConstants.DEFAULT_PAGE_NUMBER) + Integer pageNumber, + @Parameter(description = "Name of the property that the result list is sorted by") + @RequestParam(required = false) + ResourceDataSortBy sortBy, + @Parameter(description = "Direction of the sort") @RequestParam(defaultValue = "ASC") + Direction direction) + throws SampleNotFoundException, StudyNotFoundException { + + if (projection == Projection.META) { + throw new UnsupportedOperationException("Requested API is not implemented yet"); + } else { + return new ResponseEntity<>( + resourceDataService.getAllResourceDataOfSampleInStudy( + studyId, + sampleId, + resourceId, + projection.name(), + pageSize, + pageNumber, + sortBy == null ? null : sortBy.getOriginalValue(), + direction.name()), + HttpStatus.OK); + } + } + + @PreAuthorize( + "hasPermission(#studyId, 'CancerStudyId', T(org.cbioportal.legacy.utils.security.AccessLevel).READ)") + @RequestMapping( + value = "/studies/{studyId}/patients/{patientId}/resource-data", + method = RequestMethod.GET, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(description = "Get all resource data of a patient in a study") + @ApiResponse( + responseCode = "200", + description = "OK", + content = + @Content(array = @ArraySchema(schema = @Schema(implementation = ResourceData.class)))) + public ResponseEntity> getAllResourceDataOfPatientInStudy( + @Parameter(required = true, description = "Study ID e.g. acc_tcga") @PathVariable + String studyId, + @Parameter(required = true, description = "Patient ID e.g. TCGA-OR-A5J2") @PathVariable + String patientId, + @Parameter(description = "Resource ID") @RequestParam(required = false) String resourceId, + @Parameter(description = "Level of detail of the response") + @RequestParam(defaultValue = "SUMMARY") + Projection projection, + @Parameter(description = "Page size of the result list") + @Max(RESOURCE_DATA_MAX_PAGE_SIZE) + @Min(PagingConstants.MIN_PAGE_SIZE) + @RequestParam(defaultValue = RESOURCE_DATA_DEFAULT_PAGE_SIZE) + Integer pageSize, + @Parameter(description = "Page number of the result list") + @Min(PagingConstants.MIN_PAGE_NUMBER) + @RequestParam(defaultValue = PagingConstants.DEFAULT_PAGE_NUMBER) + Integer pageNumber, + @Parameter(description = "Name of the property that the result list is sorted by") + @RequestParam(required = false) + ResourceDataSortBy sortBy, + @Parameter(description = "Direction of the sort") @RequestParam(defaultValue = "ASC") + Direction direction) + throws PatientNotFoundException, StudyNotFoundException { + + if (projection == Projection.META) { + throw new UnsupportedOperationException("Requested API is not implemented yet"); + } else { + return new ResponseEntity<>( + resourceDataService.getAllResourceDataOfPatientInStudy( + studyId, + patientId, + resourceId, + projection.name(), + pageSize, + pageNumber, + sortBy == null ? null : sortBy.getOriginalValue(), + direction.name()), + HttpStatus.OK); + } + } + + @PreAuthorize( + "hasPermission(#studyId, 'CancerStudyId', T(org.cbioportal.legacy.utils.security.AccessLevel).READ)") + @RequestMapping( + value = "/studies/{studyId}/resource-data", + method = RequestMethod.GET, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(description = "Get all resource data for a study") + @ApiResponse( + responseCode = "200", + description = "OK", + content = + @Content(array = @ArraySchema(schema = @Schema(implementation = ResourceData.class)))) + public ResponseEntity> getAllStudyResourceDataInStudy( + @Parameter(required = true, description = "Study ID e.g. acc_tcga") @PathVariable + String studyId, + @Parameter(description = "Resource ID") @RequestParam(required = false) String resourceId, + @Parameter(description = "Level of detail of the response") + @RequestParam(defaultValue = "SUMMARY") + Projection projection, + @Parameter(description = "Page size of the result list") + @Max(RESOURCE_DATA_MAX_PAGE_SIZE) + @Min(PagingConstants.MIN_PAGE_SIZE) + @RequestParam(defaultValue = RESOURCE_DATA_DEFAULT_PAGE_SIZE) + Integer pageSize, + @Parameter(description = "Page number of the result list") + @Min(PagingConstants.MIN_PAGE_NUMBER) + @RequestParam(defaultValue = PagingConstants.DEFAULT_PAGE_NUMBER) + Integer pageNumber, + @Parameter(description = "Name of the property that the result list is sorted by") + @RequestParam(required = false) + ResourceDataSortBy sortBy, + @Parameter(description = "Direction of the sort") @RequestParam(defaultValue = "ASC") + Direction direction) + throws StudyNotFoundException { + + if (projection == Projection.META) { + throw new UnsupportedOperationException("Requested API is not implemented yet"); + } else { + return new ResponseEntity<>( + resourceDataService.getAllResourceDataForStudy( + studyId, + resourceId, + projection.name(), + pageSize, + pageNumber, + sortBy == null ? null : sortBy.getOriginalValue(), + direction.name()), + HttpStatus.OK); + } + } + + @PreAuthorize( + "hasPermission(#studyId, 'CancerStudyId', T(org.cbioportal.legacy.utils.security.AccessLevel).READ)") + @RequestMapping( + value = "/studies/{studyId}/resource-data-all", + method = RequestMethod.GET, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation( + description = "Get all resource data for for all patients and all samples within a study") + @ApiResponse( + responseCode = "200", + description = "OK", + content = + @Content(array = @ArraySchema(schema = @Schema(implementation = ResourceData.class)))) + public ResponseEntity> getAllStudyResourceDataInStudyPatientSample( + @Parameter(required = true, description = "Study ID e.g. acc_tcga") @PathVariable + String studyId, + @Parameter(description = "Resource ID") @RequestParam(required = false) String resourceId, + @Parameter(description = "Level of detail of the response") + @RequestParam(defaultValue = "SUMMARY") + Projection projection, + @Parameter(description = "Page size of the result list") + @Max(RESOURCE_DATA_MAX_PAGE_SIZE) + @Min(PagingConstants.MIN_PAGE_SIZE) + @RequestParam(defaultValue = RESOURCE_DATA_DEFAULT_PAGE_SIZE) + Integer pageSize, + @Parameter(description = "Page number of the result list") + @Min(PagingConstants.MIN_PAGE_NUMBER) + @RequestParam(defaultValue = PagingConstants.DEFAULT_PAGE_NUMBER) + Integer pageNumber, + @Parameter(description = "Name of the property that the result list is sorted by") + @RequestParam(required = false) + ResourceDataSortBy sortBy, + @Parameter(description = "Direction of the sort") @RequestParam(defaultValue = "ASC") + Direction direction) + throws StudyNotFoundException { + + if (projection == Projection.META) { + throw new UnsupportedOperationException("Requested API is not implemented yet"); + } else { + return new ResponseEntity<>( + this.getInstance() + .cacheableFetchAllResourceDataForStudyPatientSample( + studyId, + resourceId, + projection.name(), + pageSize, + pageNumber, + sortBy == null ? null : sortBy.getOriginalValue(), + direction.name()), + HttpStatus.OK); + } + } + + @Cacheable( + cacheResolver = "staticRepositoryCacheOneResolver", + condition = "@cacheEnabledConfig.getEnabled()") + public List cacheableFetchAllResourceDataForStudyPatientSample( + String studyId, + String resourceId, + String projectionName, + Integer pageSize, + Integer pageNumber, + String sortBy, + String directionName) + throws StudyNotFoundException { + + return resourceDataService.getAllResourceDataForStudyPatientSample( + studyId, resourceId, projectionName, pageSize, pageNumber, sortBy, directionName); + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/ResourceDefinitionController.java b/src/main/java/org/cbioportal/legacy/web/ResourceDefinitionController.java new file mode 100644 index 00000000000..16629dc976b --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/ResourceDefinitionController.java @@ -0,0 +1,145 @@ +package org.cbioportal.legacy.web; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.ArraySchema; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.constraints.Max; +import jakarta.validation.constraints.Min; +import jakarta.validation.constraints.Size; +import java.util.List; +import org.cbioportal.legacy.model.ResourceDefinition; +import org.cbioportal.legacy.service.ResourceDefinitionService; +import org.cbioportal.legacy.service.exception.ResourceDefinitionNotFoundException; +import org.cbioportal.legacy.service.exception.StudyNotFoundException; +import org.cbioportal.legacy.web.config.InternalApiTags; +import org.cbioportal.legacy.web.config.annotation.InternalApi; +import org.cbioportal.legacy.web.parameter.Direction; +import org.cbioportal.legacy.web.parameter.PagingConstants; +import org.cbioportal.legacy.web.parameter.Projection; +import org.cbioportal.legacy.web.parameter.sort.ResourceDefinitionSortBy; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +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.bind.annotation.RestController; + +@InternalApi +@RestController() +@RequestMapping("/api") +@Validated +@Tag(name = InternalApiTags.RESOURCE_DEFINITIONS, description = " ") +public class ResourceDefinitionController { + + @Autowired private ResourceDefinitionService resourceDefinitionService; + + @PreAuthorize( + "hasPermission(#studyId, 'CancerStudyId', T(org.cbioportal.legacy.utils.security.AccessLevel).READ)") + @RequestMapping( + value = "/studies/{studyId}/resource-definitions", + method = RequestMethod.GET, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(description = "Get all resource definitions in the specified study") + @ApiResponse( + responseCode = "200", + description = "OK", + content = + @Content( + array = @ArraySchema(schema = @Schema(implementation = ResourceDefinition.class)))) + public ResponseEntity> getAllResourceDefinitionsInStudy( + @Parameter(required = true, description = "Study ID e.g. acc_tcga") @PathVariable + String studyId, + @Parameter(description = "Level of detail of the response") + @RequestParam(defaultValue = "SUMMARY") + Projection projection, + @Parameter(description = "Page size of the result list") + @Max(PagingConstants.MAX_PAGE_SIZE) + @Min(PagingConstants.MIN_PAGE_SIZE) + @RequestParam(defaultValue = PagingConstants.DEFAULT_PAGE_SIZE) + Integer pageSize, + @Parameter(description = "Page number of the result list") + @Min(PagingConstants.MIN_PAGE_NUMBER) + @RequestParam(defaultValue = PagingConstants.DEFAULT_PAGE_NUMBER) + Integer pageNumber, + @Parameter(description = "Name of the property that the result list is sorted by") + @RequestParam(required = false) + ResourceDefinitionSortBy sortBy, + @Parameter(description = "Direction of the sort") @RequestParam(defaultValue = "ASC") + Direction direction) + throws StudyNotFoundException { + + if (projection == Projection.META) { + throw new UnsupportedOperationException("Requested API is not implemented yet"); + } else { + return new ResponseEntity<>( + resourceDefinitionService.getAllResourceDefinitionsInStudy( + studyId, + projection.name(), + pageSize, + pageNumber, + sortBy == null ? null : sortBy.getOriginalValue(), + direction.name()), + HttpStatus.OK); + } + } + + @PreAuthorize( + "hasPermission(#studyId, 'CancerStudyId', T(org.cbioportal.legacy.utils.security.AccessLevel).READ)") + @RequestMapping( + value = "/studies/{studyId}/resource-definitions/{resourceId}", + method = RequestMethod.GET, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(description = "Get specified resource definition") + @ApiResponse( + responseCode = "200", + description = "OK", + content = @Content(schema = @Schema(implementation = ResourceDefinition.class))) + public ResponseEntity getResourceDefinitionInStudy( + @Parameter(required = true, description = "Study ID e.g. acc_tcga") @PathVariable + String studyId, + @Parameter(required = true, description = "Resource ID") @PathVariable String resourceId) + throws StudyNotFoundException, ResourceDefinitionNotFoundException { + + return new ResponseEntity<>( + resourceDefinitionService.getResourceDefinition(studyId, resourceId), HttpStatus.OK); + } + + @PreAuthorize( + "hasPermission(#studyIds, 'Collection', T(org.cbioportal.legacy.utils.security.AccessLevel).READ)") + @RequestMapping( + value = "/resource-definitions/fetch", + method = RequestMethod.POST, + consumes = MediaType.APPLICATION_JSON_VALUE, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(description = "Get all resource definitions for specified studies") + @ApiResponse( + responseCode = "200", + description = "OK", + content = + @Content( + array = @ArraySchema(schema = @Schema(implementation = ResourceDefinition.class)))) + public ResponseEntity> fetchResourceDefinitions( + @Parameter(required = true, description = "List of Study IDs") + @Size(min = 1, max = PagingConstants.MAX_PAGE_SIZE) + @RequestBody + List studyIds, + @Parameter(description = "Level of detail of the response") + @RequestParam(defaultValue = "SUMMARY") + Projection projection) + throws StudyNotFoundException { + + return new ResponseEntity<>( + resourceDefinitionService.fetchResourceDefinitions(studyIds, projection.name()), + HttpStatus.OK); + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/SamlAndBasicLoginController.java b/src/main/java/org/cbioportal/legacy/web/SamlAndBasicLoginController.java new file mode 100644 index 00000000000..3f868dc0405 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/SamlAndBasicLoginController.java @@ -0,0 +1,32 @@ +package org.cbioportal.legacy.web; + +import jakarta.servlet.http.HttpServletRequest; +import org.cbioportal.legacy.service.FrontendPropertiesService; +import org.cbioportal.legacy.service.FrontendPropertiesServiceImpl; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.http.MediaType; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.GetMapping; + +@Controller +@ConditionalOnProperty(value = "authenticate", havingValue = "saml_plus_basic") +public class SamlAndBasicLoginController { + + private final FrontendPropertiesService frontendPropertiesService; + + @Autowired + SamlAndBasicLoginController(FrontendPropertiesService frontendPropertiesService) { + this.frontendPropertiesService = frontendPropertiesService; + } + + @GetMapping(value = "/restful_login", produces = MediaType.APPLICATION_JSON_VALUE) + public String showRestfulLoginPage(HttpServletRequest request, Model model) { + model.addAttribute( + "skin_title", + frontendPropertiesService.getFrontendProperty( + FrontendPropertiesServiceImpl.FrontendProperty.skin_title)); + return "restful_login"; + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/SampleController.java b/src/main/java/org/cbioportal/legacy/web/SampleController.java new file mode 100644 index 00000000000..62aaf26a1b9 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/SampleController.java @@ -0,0 +1,373 @@ +package org.cbioportal.legacy.web; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.ArraySchema; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import jakarta.validation.constraints.Max; +import jakarta.validation.constraints.Min; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; +import java.util.stream.Collectors; +import org.cbioportal.legacy.model.CancerStudy; +import org.cbioportal.legacy.model.Sample; +import org.cbioportal.legacy.model.meta.BaseMeta; +import org.cbioportal.legacy.service.SampleListService; +import org.cbioportal.legacy.service.SampleService; +import org.cbioportal.legacy.service.StudyService; +import org.cbioportal.legacy.service.exception.PatientNotFoundException; +import org.cbioportal.legacy.service.exception.SampleListNotFoundException; +import org.cbioportal.legacy.service.exception.SampleNotFoundException; +import org.cbioportal.legacy.service.exception.StudyNotFoundException; +import org.cbioportal.legacy.utils.security.AccessLevel; +import org.cbioportal.legacy.utils.security.PortalSecurityConfig; +import org.cbioportal.legacy.web.config.PublicApiTags; +import org.cbioportal.legacy.web.config.annotation.PublicApi; +import org.cbioportal.legacy.web.parameter.Direction; +import org.cbioportal.legacy.web.parameter.HeaderKeyConstants; +import org.cbioportal.legacy.web.parameter.PagingConstants; +import org.cbioportal.legacy.web.parameter.Projection; +import org.cbioportal.legacy.web.parameter.SampleFilter; +import org.cbioportal.legacy.web.parameter.SampleIdentifier; +import org.cbioportal.legacy.web.parameter.sort.SampleSortBy; +import org.cbioportal.legacy.web.util.UniqueKeyExtractor; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestAttribute; +import org.springframework.web.bind.annotation.RequestBody; +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.bind.annotation.RestController; + +@PublicApi +@RestController() +@RequestMapping("/api") +@Validated +@Tag(name = PublicApiTags.SAMPLES, description = " ") +public class SampleController { + + public static final int SAMPLE_MAX_PAGE_SIZE = 10000000; + private static final String SAMPLE_DEFAULT_PAGE_SIZE = "10000000"; + + @Value("${authenticate}") + private String authenticate; + + @Autowired private SampleService sampleService; + + @Autowired private SampleListService sampleListService; + + @Autowired private StudyService studyService; + + private boolean usingAuth() { + return !authenticate.isEmpty() + && !authenticate.equals("false") + && !authenticate.contains("optional_oauth2"); + } + + @RequestMapping( + value = "/samples", + method = RequestMethod.GET, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(description = "Get all samples matching keyword") + @ApiResponse( + responseCode = "200", + description = "OK", + content = @Content(array = @ArraySchema(schema = @Schema(implementation = Sample.class)))) + public ResponseEntity> getSamplesByKeyword( + @Parameter(description = "Search keyword that applies to the study ID") + @RequestParam(required = false) + String keyword, + @Parameter(description = "Level of detail of the response") + @RequestParam(defaultValue = "SUMMARY") + Projection projection, + @Parameter(description = "Page size of the result list") + @Max(PagingConstants.MAX_PAGE_SIZE) + @Min(PagingConstants.MIN_PAGE_SIZE) + @RequestParam(defaultValue = PagingConstants.DEFAULT_PAGE_SIZE) + Integer pageSize, + @Parameter(description = "Page number of the result list") + @Min(PagingConstants.MIN_PAGE_NUMBER) + @RequestParam(defaultValue = PagingConstants.DEFAULT_PAGE_NUMBER) + Integer pageNumber, + @Parameter(description = "Name of the property that the result list is sorted by") + @RequestParam(required = false) + SampleSortBy sortBy, + @Parameter(description = "Direction of the sort") @RequestParam(defaultValue = "ASC") + Direction direction) { + String sort = sortBy == null ? null : sortBy.getOriginalValue(); + List studyIds = null; + if (PortalSecurityConfig.userAuthorizationEnabled(authenticate)) { + /* + If using auth, filter the list of samples returned using the list of study ids the + user has access to. If the user has access to no studies, the endpoint should not 403, + but instead return an empty list. + */ + studyIds = + studyService + .getAllStudies( + null, + Projection.SUMMARY.name(), // force to summary so that post filter doesn't NPE + PagingConstants.MAX_PAGE_SIZE, + 0, + null, + direction.name(), + null, + AccessLevel.READ) + .stream() + .map(CancerStudy::getCancerStudyIdentifier) + .collect(Collectors.toList()); + } + + if (projection == Projection.META) { + HttpHeaders httpHeaders = new HttpHeaders(); + httpHeaders.add( + HeaderKeyConstants.TOTAL_COUNT, + sampleService.getMetaSamples(keyword, studyIds).getTotalCount().toString()); + return new ResponseEntity<>(httpHeaders, HttpStatus.OK); + } + return new ResponseEntity<>( + sampleService.getAllSamples( + keyword, studyIds, projection.name(), pageSize, pageNumber, sort, direction.name()), + HttpStatus.OK); + } + + @PreAuthorize( + "hasPermission(#studyId, 'CancerStudyId', T(org.cbioportal.legacy.utils.security.AccessLevel).READ)") + @RequestMapping( + value = "/studies/{studyId}/samples", + method = RequestMethod.GET, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(description = "Get all samples in a study") + @ApiResponse( + responseCode = "200", + description = "OK", + content = @Content(array = @ArraySchema(schema = @Schema(implementation = Sample.class)))) + public ResponseEntity> getAllSamplesInStudy( + @Parameter(required = true, description = "Study ID e.g. acc_tcga") @PathVariable + String studyId, + @Parameter(description = "Level of detail of the response") + @RequestParam(defaultValue = "SUMMARY") + Projection projection, + @Parameter(description = "Page size of the result list") + @Max(SAMPLE_MAX_PAGE_SIZE) + @Min(PagingConstants.MIN_PAGE_SIZE) + @RequestParam(defaultValue = SAMPLE_DEFAULT_PAGE_SIZE) + Integer pageSize, + @Parameter(description = "Page number of the result list") + @Min(PagingConstants.MIN_PAGE_NUMBER) + @RequestParam(defaultValue = PagingConstants.DEFAULT_PAGE_NUMBER) + Integer pageNumber, + @Parameter(description = "Name of the property that the result list is sorted by") + @RequestParam(required = false) + SampleSortBy sortBy, + @Parameter(description = "Direction of the sort") @RequestParam(defaultValue = "ASC") + Direction direction) + throws StudyNotFoundException { + + if (projection == Projection.META) { + HttpHeaders responseHeaders = new HttpHeaders(); + responseHeaders.add( + HeaderKeyConstants.TOTAL_COUNT, + sampleService.getMetaSamplesInStudy(studyId).getTotalCount().toString()); + return new ResponseEntity<>(responseHeaders, HttpStatus.OK); + } else { + return new ResponseEntity<>( + sampleService.getAllSamplesInStudy( + studyId, + projection.name(), + pageSize, + pageNumber, + sortBy == null ? null : sortBy.getOriginalValue(), + direction.name()), + HttpStatus.OK); + } + } + + @PreAuthorize( + "hasPermission(#studyId, 'CancerStudyId', T(org.cbioportal.legacy.utils.security.AccessLevel).READ)") + @RequestMapping( + value = "/studies/{studyId}/samples/{sampleId}", + method = RequestMethod.GET, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(description = "Get a sample in a study") + @ApiResponse( + responseCode = "200", + description = "OK", + content = @Content(schema = @Schema(implementation = Sample.class))) + public ResponseEntity getSampleInStudy( + @Parameter(required = true, description = "Study ID e.g. acc_tcga") @PathVariable + String studyId, + @Parameter(required = true, description = "Sample ID e.g. TCGA-OR-A5J2-01") @PathVariable + String sampleId) + throws SampleNotFoundException, StudyNotFoundException { + + return new ResponseEntity<>(sampleService.getSampleInStudy(studyId, sampleId), HttpStatus.OK); + } + + @PreAuthorize( + "hasPermission(#studyId, 'CancerStudyId', T(org.cbioportal.legacy.utils.security.AccessLevel).READ)") + @RequestMapping( + value = "/studies/{studyId}/patients/{patientId}/samples", + method = RequestMethod.GET, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(description = "Get all samples of a patient in a study") + @ApiResponse( + responseCode = "200", + description = "OK", + content = @Content(array = @ArraySchema(schema = @Schema(implementation = Sample.class)))) + public ResponseEntity> getAllSamplesOfPatientInStudy( + @Parameter(required = true, description = "Study ID e.g. acc_tcga") @PathVariable + String studyId, + @Parameter(required = true, description = "Patient ID e.g. TCGA-OR-A5J2") @PathVariable + String patientId, + @Parameter(description = "Level of detail of the response") + @RequestParam(defaultValue = "SUMMARY") + Projection projection, + @Parameter(description = "Page size of the result list") + @Max(SAMPLE_MAX_PAGE_SIZE) + @Min(PagingConstants.MIN_PAGE_SIZE) + @RequestParam(defaultValue = SAMPLE_DEFAULT_PAGE_SIZE) + Integer pageSize, + @Parameter(description = "Page number of the result list") + @Min(PagingConstants.MIN_PAGE_NUMBER) + @RequestParam(defaultValue = PagingConstants.DEFAULT_PAGE_NUMBER) + Integer pageNumber, + @Parameter(description = "Name of the property that the result list is sorted by") + @RequestParam(required = false) + SampleSortBy sortBy, + @Parameter(description = "Direction of the sort") @RequestParam(defaultValue = "ASC") + Direction direction) + throws PatientNotFoundException, StudyNotFoundException { + + if (projection == Projection.META) { + HttpHeaders responseHeaders = new HttpHeaders(); + responseHeaders.add( + HeaderKeyConstants.TOTAL_COUNT, + sampleService + .getMetaSamplesOfPatientInStudy(studyId, patientId) + .getTotalCount() + .toString()); + return new ResponseEntity<>(responseHeaders, HttpStatus.OK); + } else { + return new ResponseEntity<>( + sampleService.getAllSamplesOfPatientInStudy( + studyId, + patientId, + projection.name(), + pageSize, + pageNumber, + sortBy == null ? null : sortBy.getOriginalValue(), + direction.name()), + HttpStatus.OK); + } + } + + @PreAuthorize( + "hasPermission(#involvedCancerStudies, 'Collection', T(org.cbioportal.legacy.utils.security.AccessLevel).READ)") + @RequestMapping( + value = "/samples/fetch", + method = RequestMethod.POST, + consumes = MediaType.APPLICATION_JSON_VALUE, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(description = "Fetch samples by ID") + @ApiResponse( + responseCode = "200", + description = "OK", + content = @Content(array = @ArraySchema(schema = @Schema(implementation = Sample.class)))) + public ResponseEntity> fetchSamples( + @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface + @RequestAttribute(required = false, value = "involvedCancerStudies") + Collection involvedCancerStudies, + @Parameter( + hidden = + true) // prevent reference to this attribute in the swagger-ui interface. this + // attribute is needed for the @PreAuthorize tag above. + @Valid + @RequestAttribute(required = false, value = "interceptedSampleFilter") + SampleFilter interceptedSampleFilter, + @Parameter(required = true, description = "List of sample identifiers") + @Valid + @RequestBody(required = false) + SampleFilter sampleFilter, + @Parameter(description = "Level of detail of the response") + @RequestParam(defaultValue = "SUMMARY") + Projection projection) + throws SampleListNotFoundException { + + List studyIds = new ArrayList<>(); + List sampleIds = new ArrayList<>(); + + if (projection == Projection.META) { + HttpHeaders responseHeaders = new HttpHeaders(); + BaseMeta baseMeta; + + if (interceptedSampleFilter.getSampleListIds() != null) { + baseMeta = sampleService.fetchMetaSamples(interceptedSampleFilter.getSampleListIds()); + } else { + if (interceptedSampleFilter.getSampleIdentifiers() != null) { + extractStudyAndSampleIds(interceptedSampleFilter, studyIds, sampleIds); + } else { + UniqueKeyExtractor.extractUniqueKeys( + interceptedSampleFilter.getUniqueSampleKeys(), studyIds, sampleIds); + } + baseMeta = sampleService.fetchMetaSamples(studyIds, sampleIds); + } + responseHeaders.add(HeaderKeyConstants.TOTAL_COUNT, baseMeta.getTotalCount().toString()); + return new ResponseEntity<>(responseHeaders, HttpStatus.OK); + } else { + List samples; + if (interceptedSampleFilter.getSampleListIds() != null) { + List sampleListIds = interceptedSampleFilter.getSampleListIds(); + + samples = new ArrayList(); + + for (String sampleListId : sampleListIds) { + // check that all sample lists exist (this method throws an exception if one does not) + sampleListService.getSampleList(sampleListId); + } + + for (String sampleListId : sampleListIds) { + // fetch by sampleId so that we get cache at level of id instead list of ids + samples.addAll( + sampleService.fetchSamples(Arrays.asList(sampleListId), projection.name())); + } + + // samples = sampleService.fetchSamples(sampleListIds, projection.name()); + + } else { + if (interceptedSampleFilter.getSampleIdentifiers() != null) { + extractStudyAndSampleIds(interceptedSampleFilter, studyIds, sampleIds); + } else { + UniqueKeyExtractor.extractUniqueKeys( + interceptedSampleFilter.getUniqueSampleKeys(), studyIds, sampleIds); + } + samples = sampleService.fetchSamples(studyIds, sampleIds, projection.name()); + } + + return new ResponseEntity<>(samples, HttpStatus.OK); + } + } + + private void extractStudyAndSampleIds( + SampleFilter sampleFilter, List studyIds, List sampleIds) { + + for (SampleIdentifier sampleIdentifier : sampleFilter.getSampleIdentifiers()) { + studyIds.add(sampleIdentifier.getStudyId()); + sampleIds.add(sampleIdentifier.getSampleId()); + } + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/SampleListController.java b/src/main/java/org/cbioportal/legacy/web/SampleListController.java new file mode 100644 index 00000000000..0770247f02c --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/SampleListController.java @@ -0,0 +1,209 @@ +package org.cbioportal.legacy.web; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.ArraySchema; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.constraints.Max; +import jakarta.validation.constraints.Min; +import jakarta.validation.constraints.Size; +import java.util.List; +import org.cbioportal.legacy.model.SampleList; +import org.cbioportal.legacy.service.SampleListService; +import org.cbioportal.legacy.service.exception.SampleListNotFoundException; +import org.cbioportal.legacy.service.exception.StudyNotFoundException; +import org.cbioportal.legacy.web.config.PublicApiTags; +import org.cbioportal.legacy.web.config.annotation.PublicApi; +import org.cbioportal.legacy.web.parameter.Direction; +import org.cbioportal.legacy.web.parameter.HeaderKeyConstants; +import org.cbioportal.legacy.web.parameter.PagingConstants; +import org.cbioportal.legacy.web.parameter.Projection; +import org.cbioportal.legacy.web.parameter.sort.SampleListSortBy; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +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.bind.annotation.RestController; + +@PublicApi +@RestController() +@RequestMapping("/api") +@Validated +@Tag(name = PublicApiTags.SAMPLE_LISTS, description = " ") +public class SampleListController { + + @Autowired private SampleListService sampleListService; + + @RequestMapping( + value = "/sample-lists", + method = RequestMethod.GET, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(description = "Get all sample lists") + @ApiResponse( + responseCode = "200", + description = "OK", + content = @Content(array = @ArraySchema(schema = @Schema(implementation = SampleList.class)))) + public ResponseEntity> getAllSampleLists( + @Parameter(description = "Level of detail of the response") + @RequestParam(defaultValue = "SUMMARY") + Projection projection, + @Parameter(description = "Page size of the result list") + @Max(PagingConstants.MAX_PAGE_SIZE) + @Min(PagingConstants.MIN_PAGE_SIZE) + @RequestParam(defaultValue = PagingConstants.DEFAULT_PAGE_SIZE) + Integer pageSize, + @Parameter(description = "Page number of the result list") + @Min(PagingConstants.MIN_PAGE_NUMBER) + @RequestParam(defaultValue = PagingConstants.DEFAULT_PAGE_NUMBER) + Integer pageNumber, + @Parameter(description = "Name of the property that the result list is sorted by") + @RequestParam(required = false) + SampleListSortBy sortBy, + @Parameter(description = "Direction of the sort") @RequestParam(defaultValue = "ASC") + Direction direction) { + + if (projection == Projection.META) { + HttpHeaders responseHeaders = new HttpHeaders(); + responseHeaders.add( + HeaderKeyConstants.TOTAL_COUNT, + sampleListService.getMetaSampleLists().getTotalCount().toString()); + return new ResponseEntity<>(responseHeaders, HttpStatus.OK); + } else { + return new ResponseEntity<>( + sampleListService.getAllSampleLists( + projection.name(), + pageSize, + pageNumber, + sortBy == null ? null : sortBy.getOriginalValue(), + direction.name()), + HttpStatus.OK); + } + } + + @PreAuthorize( + "hasPermission(#sampleListId, 'SampleListId', T(org.cbioportal.legacy.utils.security.AccessLevel).READ)") + @RequestMapping( + value = "/sample-lists/{sampleListId}", + method = RequestMethod.GET, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(description = "Get sample list") + @ApiResponse( + responseCode = "200", + description = "OK", + content = @Content(schema = @Schema(implementation = SampleList.class))) + public ResponseEntity getSampleList( + @Parameter(required = true, description = "Sample List ID e.g. acc_tcga_all") @PathVariable + String sampleListId) + throws SampleListNotFoundException { + + return new ResponseEntity<>(sampleListService.getSampleList(sampleListId), HttpStatus.OK); + } + + @PreAuthorize( + "hasPermission(#studyId, 'CancerStudyId', T(org.cbioportal.legacy.utils.security.AccessLevel).READ)") + @RequestMapping( + value = "/studies/{studyId}/sample-lists", + method = RequestMethod.GET, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(description = "Get all sample lists in a study") + @ApiResponse( + responseCode = "200", + description = "OK", + content = @Content(array = @ArraySchema(schema = @Schema(implementation = SampleList.class)))) + public ResponseEntity> getAllSampleListsInStudy( + @Parameter(required = true, description = "Study ID e.g. acc_tcga") @PathVariable + String studyId, + @Parameter(description = "Level of detail of the response") + @RequestParam(defaultValue = "SUMMARY") + Projection projection, + @Parameter(description = "Page size of the result list") + @Max(PagingConstants.MAX_PAGE_SIZE) + @Min(PagingConstants.MIN_PAGE_SIZE) + @RequestParam(defaultValue = PagingConstants.DEFAULT_PAGE_SIZE) + Integer pageSize, + @Parameter(description = "Page number of the result list") + @Min(PagingConstants.MIN_PAGE_NUMBER) + @RequestParam(defaultValue = PagingConstants.DEFAULT_PAGE_NUMBER) + Integer pageNumber, + @Parameter(description = "Name of the property that the result list is sorted by") + @RequestParam(required = false) + SampleListSortBy sortBy, + @Parameter(description = "Direction of the sort") @RequestParam(defaultValue = "ASC") + Direction direction) + throws StudyNotFoundException { + + if (projection == Projection.META) { + HttpHeaders responseHeaders = new HttpHeaders(); + responseHeaders.add( + HeaderKeyConstants.TOTAL_COUNT, + sampleListService.getMetaSampleListsInStudy(studyId).getTotalCount().toString()); + return new ResponseEntity<>(responseHeaders, HttpStatus.OK); + } else { + return new ResponseEntity<>( + sampleListService.getAllSampleListsInStudy( + studyId, + projection.name(), + pageSize, + pageNumber, + sortBy == null ? null : sortBy.getOriginalValue(), + direction.name()), + HttpStatus.OK); + } + } + + @PreAuthorize( + "hasPermission(#sampleListId, 'SampleListId', T(org.cbioportal.legacy.utils.security.AccessLevel).READ)") + @RequestMapping( + value = "/sample-lists/{sampleListId}/sample-ids", + method = RequestMethod.GET, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(description = "Get all sample IDs in a sample list") + @ApiResponse( + responseCode = "200", + description = "OK", + content = @Content(array = @ArraySchema(schema = @Schema(implementation = String.class)))) + public ResponseEntity> getAllSampleIdsInSampleList( + @Parameter(required = true, description = "Sample List ID e.g. acc_tcga_all") @PathVariable + String sampleListId) + throws SampleListNotFoundException { + + return new ResponseEntity<>( + sampleListService.getAllSampleIdsInSampleList(sampleListId), HttpStatus.OK); + } + + @PreAuthorize( + "hasPermission(#sampleListIds, 'Collection', T(org.cbioportal.legacy.utils.security.AccessLevel).READ)") + @RequestMapping( + value = "/sample-lists/fetch", + method = RequestMethod.POST, + consumes = MediaType.APPLICATION_JSON_VALUE, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(description = "Fetch sample lists by ID") + @ApiResponse( + responseCode = "200", + description = "OK", + content = @Content(array = @ArraySchema(schema = @Schema(implementation = SampleList.class)))) + public ResponseEntity> fetchSampleLists( + @Parameter(required = true, description = "List of sample list IDs") + @Size(min = 1, max = PagingConstants.MAX_PAGE_SIZE) + @RequestBody + List sampleListIds, + @Parameter(description = "Level of detail of the response") + @RequestParam(defaultValue = "SUMMARY") + Projection projection) { + + return new ResponseEntity<>( + sampleListService.fetchSampleLists(sampleListIds, projection.name()), HttpStatus.OK); + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/ServerStatusController.java b/src/main/java/org/cbioportal/legacy/web/ServerStatusController.java new file mode 100644 index 00000000000..0ab59ad1cb5 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/ServerStatusController.java @@ -0,0 +1,40 @@ +package org.cbioportal.legacy.web; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.cbioportal.legacy.service.ServerStatusService; +import org.cbioportal.legacy.service.impl.ServerStatusServiceImpl.ServerStatusMessage; +import org.cbioportal.legacy.web.config.annotation.PublicApi; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RestController; + +@PublicApi +@RestController +@Validated +@Tag(name = "Server running status", description = "This end point does not require authentication") +public class ServerStatusController { + + @Autowired private ServerStatusService serverStatusService; + + @RequestMapping( + value = "/api/health", + method = RequestMethod.GET, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(description = "Get the running status of the server") + @ApiResponse( + responseCode = "200", + description = "OK", + content = @Content(schema = @Schema(implementation = ServerStatusMessage.class))) + public ResponseEntity getServerStatus() { + return new ResponseEntity<>(serverStatusService.getServerStatus(), HttpStatus.OK); + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/SessionServiceController.java b/src/main/java/org/cbioportal/legacy/web/SessionServiceController.java new file mode 100644 index 00000000000..8363453ce0f --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/SessionServiceController.java @@ -0,0 +1,538 @@ +package org.cbioportal.legacy.web; + +import static org.cbioportal.legacy.web.PublicVirtualStudiesController.ALL_USERS; + +import com.fasterxml.jackson.annotation.JsonInclude.Include; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.google.common.collect.ImmutableMap; +import io.swagger.v3.oas.annotations.media.ArraySchema; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.validation.constraints.Size; +import java.io.IOException; +import java.io.Serializable; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.Set; +import java.util.stream.Collectors; +import org.cbioportal.legacy.service.util.CustomAttributeWithData; +import org.cbioportal.legacy.service.util.CustomDataSession; +import org.cbioportal.legacy.service.util.SessionServiceRequestHandler; +import org.cbioportal.legacy.utils.removeme.Session; +import org.cbioportal.legacy.web.parameter.CustomGeneList; +import org.cbioportal.legacy.web.parameter.CustomGeneListData; +import org.cbioportal.legacy.web.parameter.PageSettings; +import org.cbioportal.legacy.web.parameter.PageSettingsData; +import org.cbioportal.legacy.web.parameter.PageSettingsIdentifier; +import org.cbioportal.legacy.web.parameter.PagingConstants; +import org.cbioportal.legacy.web.parameter.ResultsPageSettings; +import org.cbioportal.legacy.web.parameter.SampleIdentifier; +import org.cbioportal.legacy.web.parameter.SessionPage; +import org.cbioportal.legacy.web.parameter.StudyPageSettings; +import org.cbioportal.legacy.web.parameter.VirtualStudy; +import org.cbioportal.legacy.web.parameter.VirtualStudyData; +import org.cbioportal.legacy.web.parameter.VirtualStudySamples; +import org.cbioportal.legacy.web.util.StudyViewFilterApplier; +import org.json.simple.JSONObject; +import org.json.simple.parser.JSONParser; +import org.json.simple.parser.ParseException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.security.authentication.AnonymousAuthenticationToken; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.client.HttpClientErrorException; + +@Controller +@RequestMapping("/api/session") +public class SessionServiceController { + + private static final Logger LOG = LoggerFactory.getLogger(SessionServiceController.class); + + SessionServiceRequestHandler sessionServiceRequestHandler; + + private ObjectMapper sessionServiceObjectMapper; + + private StudyViewFilterApplier studyViewFilterApplier; + + public SessionServiceController( + SessionServiceRequestHandler sessionServiceRequestHandler, + ObjectMapper sessionServiceObjectMapper, + StudyViewFilterApplier studyViewFilterApplier) { + this.sessionServiceRequestHandler = sessionServiceRequestHandler; + this.sessionServiceObjectMapper = sessionServiceObjectMapper; + this.studyViewFilterApplier = studyViewFilterApplier; + } + + private static Map> pageToSettingsDataClass = + ImmutableMap.of( + SessionPage.study_view, StudyPageSettings.class, + SessionPage.results_view, ResultsPageSettings.class); + + private boolean isAuthorized() { + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + return !(authentication == null || (authentication instanceof AnonymousAuthenticationToken)); + } + + private String userName() { + return SecurityContextHolder.getContext().getAuthentication().getName(); + } + + private boolean sameOrigin(Set set1, Set set2) { + if (set1 == null || set2 == null) { + return false; + } + if (set1.size() != set2.size()) { + return false; + } + return set1.containsAll(set2); + } + + private ResponseEntity addSession( + Session.SessionType type, Optional operation, JSONObject body) { + try { + Serializable payload; + if (type.equals(Session.SessionType.virtual_study) + || type.equals(Session.SessionType.group)) { + // JSON from file to Object + VirtualStudyData virtualStudyData = + sessionServiceObjectMapper.readValue(body.toString(), VirtualStudyData.class); + // TODO sanitize what's supplied. e.g. anonymous user should not specify the users field! + + if (isAuthorized()) { + String userName = userName(); + if (userName.equals(ALL_USERS)) { + throw new IllegalStateException( + "Illegal username " + ALL_USERS + " for assigning virtual studies."); + } + virtualStudyData.setOwner(userName); + if ((operation.isPresent() && operation.get().equals(SessionOperation.save)) + || type.equals(Session.SessionType.group)) { + virtualStudyData.setUsers(Collections.singleton(userName)); + } + } + + // use basic authentication for session service if set + payload = virtualStudyData; + } else if (type.equals(Session.SessionType.settings)) { + if (!(isAuthorized())) { + return new ResponseEntity<>(HttpStatus.SERVICE_UNAVAILABLE); + } + Class pageDataClass = + pageToSettingsDataClass.get(SessionPage.valueOf((String) body.get("page"))); + PageSettingsData pageSettings = + sessionServiceObjectMapper.readValue(body.toString(), pageDataClass); + pageSettings.setOwner(userName()); + payload = pageSettings; + + } else if (type.equals(Session.SessionType.custom_data)) { + // JSON from file to Object + CustomAttributeWithData customData = + sessionServiceObjectMapper.readValue(body.toString(), CustomAttributeWithData.class); + + if (isAuthorized()) { + customData.setOwner(userName()); + customData.setUsers(Collections.singleton(userName())); + } + + // use basic authentication for session service if set + payload = customData; + } else if (type.equals(Session.SessionType.custom_gene_list)) { + if (!(isAuthorized())) { + return new ResponseEntity<>(HttpStatus.SERVICE_UNAVAILABLE); + } + CustomGeneListData customGeneListData = + sessionServiceObjectMapper.readValue(body.toString(), CustomGeneListData.class); + customGeneListData.setUsers(Collections.singleton(userName())); + payload = customGeneListData; + } else { + payload = body; + } + // returns {"id":"5799648eef86c0e807a2e965"} + // using HashMap because converter is MappingJackson2HttpMessageConverter + // (Jackson 2 is on classpath) + // was String when default converter StringHttpMessageConverter was used + return sessionServiceRequestHandler.createSession(type, payload); + + } catch (IOException e) { + LOG.error("Error occurred", e); + return new ResponseEntity<>(HttpStatus.BAD_REQUEST); + } + } + + @RequestMapping(value = "/{type}/{id}", method = RequestMethod.GET) + @ApiResponse( + responseCode = "200", + description = "OK", + content = @Content(schema = @Schema(implementation = Session.class))) + public ResponseEntity getSession( + @PathVariable Session.SessionType type, @PathVariable String id) { + + try { + String sessionDataJson = sessionServiceRequestHandler.getSessionDataJson(type, id); + Session session; + switch (type) { + case virtual_study: + VirtualStudy virtualStudy = + sessionServiceObjectMapper.readValue(sessionDataJson, VirtualStudy.class); + VirtualStudyData virtualStudyData = virtualStudy.getData(); + if (Boolean.TRUE.equals(virtualStudyData.getDynamic())) { + populateVirtualStudySamples(virtualStudyData); + } + session = virtualStudy; + break; + case settings: + session = sessionServiceObjectMapper.readValue(sessionDataJson, PageSettings.class); + break; + case custom_data: + session = sessionServiceObjectMapper.readValue(sessionDataJson, CustomDataSession.class); + break; + case custom_gene_list: + session = sessionServiceObjectMapper.readValue(sessionDataJson, CustomGeneList.class); + break; + default: + session = sessionServiceObjectMapper.readValue(sessionDataJson, Session.class); + } + return new ResponseEntity<>(session, HttpStatus.OK); + } catch (HttpClientErrorException.NotFound exception) { + LOG.error("Session not found", exception); + return new ResponseEntity<>(HttpStatus.NOT_FOUND); + } catch (Exception exception) { + LOG.error("Error occurred", exception); + return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR); + } + } + + /** + * This method populates the `virtualStudyData` object with a new set of sample IDs retrieved as + * the result of executing a query based on virtual study view filters. It first applies the + * filters defined within the study view, runs the query to fetch the relevant sample IDs, and + * then updates the virtualStudyData to reflect these fresh results. This ensures that the virtual + * study contains the latest sample IDs. + * + * @param virtualStudyData + */ + private void populateVirtualStudySamples(VirtualStudyData virtualStudyData) { + List sampleIdentifiers = + studyViewFilterApplier.apply(virtualStudyData.getStudyViewFilter()); + Set virtualStudySamples = extractVirtualStudySamples(sampleIdentifiers); + virtualStudyData.setStudies(virtualStudySamples); + } + + /** + * Transforms list of sample identifiers to set of virtual study samples + * + * @param sampleIdentifiers + */ + private Set extractVirtualStudySamples( + List sampleIdentifiers) { + Map> sampleIdsByStudyId = groupSampleIdsByStudyId(sampleIdentifiers); + return sampleIdsByStudyId.entrySet().stream() + .map( + entry -> { + VirtualStudySamples vss = new VirtualStudySamples(); + vss.setId(entry.getKey()); + vss.setSamples(entry.getValue()); + return vss; + }) + .collect(Collectors.toSet()); + } + + /** + * Groups sample IDs by their study ID + * + * @param sampleIdentifiers + */ + private Map> groupSampleIdsByStudyId( + List sampleIdentifiers) { + return sampleIdentifiers.stream() + .collect( + Collectors.groupingBy( + SampleIdentifier::getStudyId, + Collectors.mapping(SampleIdentifier::getSampleId, Collectors.toSet()))); + } + + @RequestMapping(value = "/virtual_study", method = RequestMethod.GET) + @ApiResponse( + responseCode = "200", + description = "OK", + content = + @Content(array = @ArraySchema(schema = @Schema(implementation = VirtualStudy.class)))) + public ResponseEntity> getUserStudies() throws JsonProcessingException { + + if (sessionServiceRequestHandler.isSessionServiceEnabled() && isAuthorized()) { + try { + List virtualStudyList = + sessionServiceRequestHandler.getVirtualStudiesAccessibleToUser(userName()); + return new ResponseEntity<>(virtualStudyList, HttpStatus.OK); + } catch (Exception exception) { + LOG.error("Error occurred", exception); + return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR); + } + } + return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR); + } + + @RequestMapping(value = "/{type}", method = RequestMethod.POST) + @ApiResponse( + responseCode = "200", + description = "OK", + content = @Content(schema = @Schema(implementation = Session.class))) + public ResponseEntity addSession( + @PathVariable Session.SessionType type, @RequestBody JSONObject body) throws IOException { + // FIXME? anonymous user can create sessions. Do we really want that? + // https://github.com/cBioPortal/cbioportal/issues/10843 + return addSession(type, Optional.empty(), body); + } + + @RequestMapping(value = "/virtual_study/save", method = RequestMethod.POST) + @ApiResponse( + responseCode = "200", + description = "OK", + content = @Content(schema = @Schema(implementation = Session.class))) + public ResponseEntity addUserSavedVirtualStudy(@RequestBody JSONObject body) + throws IOException { + // FIXME? anonymous user can create virtual studies. Do we really want that? + // https://github.com/cBioPortal/cbioportal/issues/10843 + return addSession(Session.SessionType.virtual_study, Optional.of(SessionOperation.save), body); + } + + @RequestMapping( + value = "/{type:virtual_study|group|custom_data|custom_gene_list}/{operation}/{id}", + method = RequestMethod.GET) + public void updateUsersInSession( + @PathVariable Session.SessionType type, + @PathVariable String id, + @PathVariable Operation operation, + HttpServletResponse response) + throws IOException { + + if (sessionServiceRequestHandler.isSessionServiceEnabled() && isAuthorized()) { + Serializable payload; + if (type.equals(Session.SessionType.custom_data)) { + String virtualStudyStr = + sessionServiceObjectMapper.writeValueAsString(getSession(type, id).getBody()); + CustomDataSession customDataSession = + sessionServiceObjectMapper.readValue(virtualStudyStr, CustomDataSession.class); + CustomAttributeWithData customAttributeWithData = customDataSession.getData(); + Set users = customAttributeWithData.getUsers(); + updateUserList(operation, users); + customAttributeWithData.setUsers(users); + payload = customAttributeWithData; + } else if (type.equals(Session.SessionType.custom_gene_list)) { + String customGeneListStr = + sessionServiceObjectMapper.writeValueAsString(getSession(type, id).getBody()); + CustomGeneList customGeneList = + sessionServiceObjectMapper.readValue(customGeneListStr, CustomGeneList.class); + CustomGeneListData customGeneListData = customGeneList.getData(); + Set users = customGeneListData.getUsers(); + updateUserList(operation, users); + customGeneListData.setUsers(users); + payload = customGeneListData; + } else { + String virtualStudyStr = + sessionServiceObjectMapper.writeValueAsString(getSession(type, id).getBody()); + VirtualStudy virtualStudy = + sessionServiceObjectMapper.readValue(virtualStudyStr, VirtualStudy.class); + VirtualStudyData virtualStudyData = virtualStudy.getData(); + Set users = virtualStudyData.getUsers(); + updateUserList(operation, users); + virtualStudyData.setUsers(users); + payload = virtualStudyData; + } + + sessionServiceRequestHandler.updateUsers(type, id, payload); + + response.sendError(HttpStatus.OK.value()); + } else { + response.sendError(HttpStatus.SERVICE_UNAVAILABLE.value()); + } + } + + private void updateUserList(Operation operation, Set users) { + switch (operation) { + case add: + { + users.add(userName()); + break; + } + case delete: + { + users.remove(userName()); + break; + } + } + } + + @RequestMapping(value = "/groups/fetch", method = RequestMethod.POST) + @ApiResponse( + responseCode = "200", + description = "OK", + content = + @Content(array = @ArraySchema(schema = @Schema(implementation = VirtualStudy.class)))) + public ResponseEntity> fetchUserGroups( + @Size(min = 1, max = PagingConstants.MAX_PAGE_SIZE) @RequestBody List studyIds) + throws IOException { + + if (sessionServiceRequestHandler.isSessionServiceEnabled() && isAuthorized()) { + List virtualStudyList = + sessionServiceRequestHandler.getVirtualStudiesForUser(userName(), studyIds); + return new ResponseEntity<>(virtualStudyList, HttpStatus.OK); + } + return new ResponseEntity<>(HttpStatus.SERVICE_UNAVAILABLE); + } + + @RequestMapping(value = "/settings", method = RequestMethod.POST) + public void updateUserPageSettings( + @RequestBody PageSettingsData settingsData, HttpServletResponse response) { + + try { + ObjectMapper objectMapper = + new ObjectMapper() + .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) + .setSerializationInclusion(Include.NON_NULL); + if (sessionServiceRequestHandler.isSessionServiceEnabled() && isAuthorized()) { + PageSettings pageSettings = + sessionServiceRequestHandler.getRecentlyUpdatePageSettings( + userName(), settingsData.getOrigin(), settingsData.getPage().name()); + JSONParser parser = new JSONParser(); + JSONObject jsonObject = + (JSONObject) parser.parse(objectMapper.writeValueAsString(settingsData)); + + if (pageSettings == null) { + addSession(Session.SessionType.settings, Optional.empty(), jsonObject); + } else { + updatedPageSettingSession(pageSettings, settingsData, response); + } + response.setStatus(HttpStatus.OK.value()); + } else { + response.setStatus(HttpStatus.SERVICE_UNAVAILABLE.value()); + } + } catch (IOException | ParseException e) { + LOG.error("Error occurred", e); + response.setStatus(HttpStatus.BAD_REQUEST.value()); + } + } + + // updates only allowed for type page settings session + private void updatedPageSettingSession( + PageSettings pageSettings, @RequestBody PageSettingsData body, HttpServletResponse response) + throws IOException { + + if (isAuthorized()) { + + PageSettingsData pageSettingsData = pageSettings.getData(); + // only allow owner to update his session and see if the origin(studies) are same + if (userName().equals(pageSettingsData.getOwner()) + && sameOrigin(pageSettingsData.getOrigin(), body.getOrigin())) { + + body.setCreated(pageSettingsData.getCreated()); + body.setOwner(pageSettingsData.getOwner()); + body.setOrigin(pageSettingsData.getOrigin()); + + Session.SessionType type = + pageSettings.getType() == null ? Session.SessionType.settings : pageSettings.getType(); + sessionServiceRequestHandler.updatePageSettings(type, pageSettings.getId(), body); + response.setStatus(HttpStatus.OK.value()); + } else { + response.setStatus(HttpStatus.UNAUTHORIZED.value()); + } + } else { + response.setStatus(HttpStatus.SERVICE_UNAVAILABLE.value()); + } + } + + @RequestMapping(value = "/settings/fetch", method = RequestMethod.POST) + @ApiResponse( + responseCode = "200", + description = "OK", + content = @Content(schema = @Schema(implementation = PageSettingsData.class))) + public ResponseEntity getPageSettings( + @RequestBody PageSettingsIdentifier pageSettingsIdentifier) { + + try { + if (sessionServiceRequestHandler.isSessionServiceEnabled() && isAuthorized()) { + PageSettings pageSettings = + sessionServiceRequestHandler.getRecentlyUpdatePageSettings( + userName(), + pageSettingsIdentifier.getOrigin(), + pageSettingsIdentifier.getPage().name()); + return new ResponseEntity<>( + pageSettings == null ? null : pageSettings.getData(), HttpStatus.OK); + } + return new ResponseEntity<>(HttpStatus.SERVICE_UNAVAILABLE); + } catch (Exception e) { + LOG.error("Error occurred", e); + return new ResponseEntity<>(HttpStatus.BAD_REQUEST); + } + } + + @RequestMapping(value = "/custom_data/fetch", method = RequestMethod.POST) + @ApiResponse( + responseCode = "200", + description = "OK", + content = + @Content( + array = @ArraySchema(schema = @Schema(implementation = CustomDataSession.class)))) + public ResponseEntity> fetchCustomProperties( + @Size(min = 1, max = PagingConstants.MAX_PAGE_SIZE) @RequestBody List studyIds) + throws IOException { + + if (sessionServiceRequestHandler.isSessionServiceEnabled() && isAuthorized()) { + List customDataSessionList = + sessionServiceRequestHandler.getCustomDataSessionForUser(userName(), studyIds); + return new ResponseEntity<>(customDataSessionList, HttpStatus.OK); + } + return new ResponseEntity<>(HttpStatus.SERVICE_UNAVAILABLE); + } + + @RequestMapping(value = "/custom_gene_list/save", method = RequestMethod.POST) + @ApiResponse( + responseCode = "200", + description = "OK", + content = @Content(schema = @Schema(implementation = Session.class))) + public ResponseEntity addUserSavedCustomGeneList(@RequestBody JSONObject body) + throws IOException { + return addSession( + Session.SessionType.custom_gene_list, Optional.of(SessionOperation.save), body); + } + + @RequestMapping(value = "/custom_gene_list", method = RequestMethod.GET) + @ApiResponse( + responseCode = "200", + description = "OK", + content = + @Content(array = @ArraySchema(schema = @Schema(implementation = CustomGeneList.class)))) + public ResponseEntity> fetchCustomGeneList() throws IOException { + + if (sessionServiceRequestHandler.isSessionServiceEnabled() && isAuthorized()) { + List customGeneLists = + sessionServiceRequestHandler.getCustomGeneListsForUser(userName()); + return new ResponseEntity<>(customGeneLists, HttpStatus.OK); + } + return new ResponseEntity<>(HttpStatus.SERVICE_UNAVAILABLE); + } +} + +enum Operation { + add, + delete; +} + +enum SessionOperation { + save, + share; +} diff --git a/src/main/java/org/cbioportal/legacy/web/SignificantCopyNumberRegionController.java b/src/main/java/org/cbioportal/legacy/web/SignificantCopyNumberRegionController.java new file mode 100644 index 00000000000..39d6dae64d5 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/SignificantCopyNumberRegionController.java @@ -0,0 +1,98 @@ +package org.cbioportal.legacy.web; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.ArraySchema; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.constraints.Max; +import jakarta.validation.constraints.Min; +import java.util.List; +import org.cbioportal.legacy.model.Gistic; +import org.cbioportal.legacy.service.SignificantCopyNumberRegionService; +import org.cbioportal.legacy.service.exception.StudyNotFoundException; +import org.cbioportal.legacy.web.config.annotation.InternalApi; +import org.cbioportal.legacy.web.parameter.Direction; +import org.cbioportal.legacy.web.parameter.HeaderKeyConstants; +import org.cbioportal.legacy.web.parameter.PagingConstants; +import org.cbioportal.legacy.web.parameter.Projection; +import org.cbioportal.legacy.web.parameter.sort.SignificantCopyNumberRegionSortBy; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.PathVariable; +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.bind.annotation.RestController; + +@InternalApi +@RestController() +@RequestMapping("/api") +@Validated +@Tag(name = "Significant Copy Number Regions", description = " ") +public class SignificantCopyNumberRegionController { + + @Autowired private SignificantCopyNumberRegionService significantCopyNumberRegionService; + + @PreAuthorize( + "hasPermission(#studyId, 'CancerStudyId', T(org.cbioportal.legacy.utils.security.AccessLevel).READ)") + @RequestMapping( + value = "/studies/{studyId}/significant-copy-number-regions", + method = RequestMethod.GET, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(description = "Get significant copy number alteration regions in a study") + @ApiResponse( + responseCode = "200", + description = "OK", + content = @Content(array = @ArraySchema(schema = @Schema(implementation = Gistic.class)))) + public ResponseEntity> getSignificantCopyNumberRegions( + @Parameter(required = true, description = "Study ID e.g. acc_tcga") @PathVariable + String studyId, + @Parameter(description = "Level of detail of the response") + @RequestParam(defaultValue = "SUMMARY") + Projection projection, + @Parameter(description = "Page size of the result list") + @Max(PagingConstants.MAX_PAGE_SIZE) + @Min(PagingConstants.MIN_PAGE_SIZE) + @RequestParam(defaultValue = PagingConstants.DEFAULT_PAGE_SIZE) + Integer pageSize, + @Parameter(description = "Page number of the result list") + @Min(PagingConstants.MIN_PAGE_NUMBER) + @RequestParam(defaultValue = PagingConstants.DEFAULT_PAGE_NUMBER) + Integer pageNumber, + @Parameter(description = "Name of the property that the result list is sorted by") + @RequestParam(required = false) + SignificantCopyNumberRegionSortBy sortBy, + @Parameter(description = "Direction of the sort") @RequestParam(defaultValue = "ASC") + Direction direction) + throws StudyNotFoundException { + + if (projection == Projection.META) { + HttpHeaders responseHeaders = new HttpHeaders(); + responseHeaders.add( + HeaderKeyConstants.TOTAL_COUNT, + significantCopyNumberRegionService + .getMetaSignificantCopyNumberRegions(studyId) + .getTotalCount() + .toString()); + return new ResponseEntity<>(responseHeaders, HttpStatus.OK); + } else { + return new ResponseEntity<>( + significantCopyNumberRegionService.getSignificantCopyNumberRegions( + studyId, + projection.name(), + pageSize, + pageNumber, + sortBy == null ? null : sortBy.getOriginalValue(), + direction.name()), + HttpStatus.OK); + } + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/SignificantlyMutatedGenesController.java b/src/main/java/org/cbioportal/legacy/web/SignificantlyMutatedGenesController.java new file mode 100644 index 00000000000..26b1222784e --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/SignificantlyMutatedGenesController.java @@ -0,0 +1,98 @@ +package org.cbioportal.legacy.web; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.ArraySchema; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.constraints.Max; +import jakarta.validation.constraints.Min; +import java.util.List; +import org.cbioportal.legacy.model.MutSig; +import org.cbioportal.legacy.service.SignificantlyMutatedGeneService; +import org.cbioportal.legacy.service.exception.StudyNotFoundException; +import org.cbioportal.legacy.web.config.annotation.InternalApi; +import org.cbioportal.legacy.web.parameter.Direction; +import org.cbioportal.legacy.web.parameter.HeaderKeyConstants; +import org.cbioportal.legacy.web.parameter.PagingConstants; +import org.cbioportal.legacy.web.parameter.Projection; +import org.cbioportal.legacy.web.parameter.sort.SignificantlyMutatedGeneSortBy; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.PathVariable; +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.bind.annotation.RestController; + +@InternalApi +@RestController() +@RequestMapping("/api") +@Validated +@Tag(name = "Significantly Mutated Genes", description = " ") +public class SignificantlyMutatedGenesController { + + @Autowired private SignificantlyMutatedGeneService significantlyMutatedGeneService; + + @PreAuthorize( + "hasPermission(#studyId, 'CancerStudyId', T(org.cbioportal.legacy.utils.security.AccessLevel).READ)") + @RequestMapping( + value = "/studies/{studyId}/significantly-mutated-genes", + method = RequestMethod.GET, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(description = "Get significantly mutated genes in a study") + @ApiResponse( + responseCode = "200", + description = "OK", + content = @Content(array = @ArraySchema(schema = @Schema(implementation = MutSig.class)))) + public ResponseEntity> getSignificantlyMutatedGenes( + @Parameter(required = true, description = "Study ID e.g. acc_tcga") @PathVariable + String studyId, + @Parameter(description = "Level of detail of the response") + @RequestParam(defaultValue = "SUMMARY") + Projection projection, + @Parameter(description = "Page size of the result list") + @Max(PagingConstants.MAX_PAGE_SIZE) + @Min(PagingConstants.MIN_PAGE_SIZE) + @RequestParam(defaultValue = PagingConstants.DEFAULT_PAGE_SIZE) + Integer pageSize, + @Parameter(description = "Page number of the result list") + @Min(PagingConstants.MIN_PAGE_NUMBER) + @RequestParam(defaultValue = PagingConstants.DEFAULT_PAGE_NUMBER) + Integer pageNumber, + @Parameter(description = "Name of the property that the result list is sorted by") + @RequestParam(required = false) + SignificantlyMutatedGeneSortBy sortBy, + @Parameter(description = "Direction of the sort") @RequestParam(defaultValue = "ASC") + Direction direction) + throws StudyNotFoundException { + + if (projection == Projection.META) { + HttpHeaders responseHeaders = new HttpHeaders(); + responseHeaders.add( + HeaderKeyConstants.TOTAL_COUNT, + significantlyMutatedGeneService + .getMetaSignificantlyMutatedGenes(studyId) + .getTotalCount() + .toString()); + return new ResponseEntity<>(responseHeaders, HttpStatus.OK); + } else { + return new ResponseEntity<>( + significantlyMutatedGeneService.getSignificantlyMutatedGenes( + studyId, + projection.name(), + pageSize, + pageNumber, + sortBy == null ? null : sortBy.getOriginalValue(), + direction.name()), + HttpStatus.OK); + } + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/StaticDataTimestampController.java b/src/main/java/org/cbioportal/legacy/web/StaticDataTimestampController.java new file mode 100644 index 00000000000..254cf1711ec --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/StaticDataTimestampController.java @@ -0,0 +1,43 @@ +package org.cbioportal.legacy.web; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.tags.Tag; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import org.cbioportal.legacy.service.StaticDataTimestampService; +import org.cbioportal.legacy.web.config.annotation.InternalApi; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RestController; + +@InternalApi +@RestController +@Validated +@Tag(name = "Timestamps", description = " ") +public class StaticDataTimestampController { + public static final List TIMESTAMP_TABLES = + Arrays.asList("gene", "reference_genome_gene"); + @Autowired private StaticDataTimestampService service; + + @RequestMapping( + value = "/api/timestamps", + method = RequestMethod.GET, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(description = "Get the last time each static resource was updated") + @ApiResponse( + responseCode = "200", + description = "OK", + content = @Content(schema = @Schema(implementation = Object.class))) + public ResponseEntity> getAllTimestamps() { + return new ResponseEntity<>(service.getTimestamps(TIMESTAMP_TABLES), HttpStatus.OK); + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/StructuralVariantController.java b/src/main/java/org/cbioportal/legacy/web/StructuralVariantController.java new file mode 100644 index 00000000000..d4ce1410d5c --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/StructuralVariantController.java @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2018 The Hyve B.V. + * This code is licensed under the GNU Affero General Public License (AGPL), + * version 3, or (at your option) any later version. + */ + +/* + * This file is part of cBioPortal. + * + * cBioPortal is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package org.cbioportal.legacy.web; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.ArraySchema; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import org.cbioportal.legacy.model.StructuralVariant; +import org.cbioportal.legacy.service.StructuralVariantService; +import org.cbioportal.legacy.web.config.InternalApiTags; +import org.cbioportal.legacy.web.config.annotation.InternalApi; +import org.cbioportal.legacy.web.parameter.StructuralVariantFilter; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.RequestAttribute; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RestController; + +@InternalApi +@RestController() +@RequestMapping("/api") +@Validated +@Tag(name = InternalApiTags.STRUCTURAL_VARIANTS, description = " ") +public class StructuralVariantController { + @Autowired private StructuralVariantService structuralVariantService; + + @PreAuthorize( + "hasPermission(#involvedCancerStudies, 'Collection', T(org.cbioportal.legacy.utils.security.AccessLevel).READ)") + @RequestMapping( + value = "/structural-variant/fetch", + method = RequestMethod.POST, + consumes = MediaType.APPLICATION_JSON_VALUE, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation( + description = + "Fetch structural variants for entrezGeneIds and molecularProfileIds or sampleMolecularIdentifiers") + @ApiResponse( + responseCode = "200", + description = "OK", + content = + @Content( + array = @ArraySchema(schema = @Schema(implementation = StructuralVariant.class)))) + public ResponseEntity> fetchStructuralVariants( + @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface + @RequestAttribute(required = false, value = "involvedCancerStudies") + Collection involvedCancerStudies, + @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface + @Valid + @RequestAttribute(required = false, value = "interceptedStructuralVariantFilter") + StructuralVariantFilter interceptedStructuralVariantFilter, + @Parameter( + required = true, + description = + "List of entrezGeneIds, structural variant queries and molecularProfileIds or sampleMolecularIdentifiers") + @Valid + @RequestBody(required = false) + StructuralVariantFilter structuralVariantFilter) { + + List molecularProfileIds = new ArrayList<>(); + List sampleIds = new ArrayList<>(); + + if (interceptedStructuralVariantFilter.getSampleMolecularIdentifiers() != null) { + interceptedStructuralVariantFilter + .getSampleMolecularIdentifiers() + .forEach( + sampleMolecularIdentifier -> { + sampleIds.add(sampleMolecularIdentifier.getSampleId()); + molecularProfileIds.add(sampleMolecularIdentifier.getMolecularProfileId()); + }); + } else { + molecularProfileIds.addAll(interceptedStructuralVariantFilter.getMolecularProfileIds()); + } + List structuralVariantList = + structuralVariantService.fetchStructuralVariants( + molecularProfileIds, + sampleIds, + interceptedStructuralVariantFilter.getEntrezGeneIds(), + interceptedStructuralVariantFilter.getStructuralVariantQueries()); + + return new ResponseEntity<>(structuralVariantList, HttpStatus.OK); + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/StudyController.java b/src/main/java/org/cbioportal/legacy/web/StudyController.java new file mode 100644 index 00000000000..56d5cdc50b4 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/StudyController.java @@ -0,0 +1,266 @@ +package org.cbioportal.legacy.web; + +import com.fasterxml.jackson.core.JsonParseException; +import com.fasterxml.jackson.databind.JsonMappingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.ArraySchema; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.PostConstruct; +import jakarta.validation.constraints.Max; +import jakarta.validation.constraints.Min; +import jakarta.validation.constraints.Size; +import java.io.IOException; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import org.cbioportal.legacy.model.CancerStudy; +import org.cbioportal.legacy.model.CancerStudyTags; +import org.cbioportal.legacy.service.StudyService; +import org.cbioportal.legacy.service.exception.StudyNotFoundException; +import org.cbioportal.legacy.utils.security.AccessLevel; +import org.cbioportal.legacy.utils.security.PortalSecurityConfig; +import org.cbioportal.legacy.web.config.PublicApiTags; +import org.cbioportal.legacy.web.config.annotation.PublicApi; +import org.cbioportal.legacy.web.parameter.Direction; +import org.cbioportal.legacy.web.parameter.HeaderKeyConstants; +import org.cbioportal.legacy.web.parameter.PagingConstants; +import org.cbioportal.legacy.web.parameter.Projection; +import org.cbioportal.legacy.web.parameter.sort.StudySortBy; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.security.access.prepost.PreFilter; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +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.bind.annotation.RestController; + +@PublicApi +@RestController() +@RequestMapping("/api") +@Validated +@Tag(name = PublicApiTags.STUDIES, description = " ") +public class StudyController { + + @Value("${app.name:unknown}") + private String appName; + + @Value("${authenticate}") + private String authenticate; + + @Value("${skin.home_page.show_unauthorized_studies:false}") + private boolean showUnauthorizedStudiesOnHomePage; + + @Autowired private StudyService studyService; + + // This is a stop-gap solution because this endpoint needs caching + // Right now this method has spontaneous performance problems + // for the default query. We felt the best stop gap would be + // to just manually cache that one response. + private static List defaultResponse; + + @PostConstruct + private void warmDefaultResponseCache() { + if (!PortalSecurityConfig.userAuthorizationEnabled(authenticate)) { + defaultResponse = + studyService.getAllStudies( + null, + Projection.SUMMARY.name(), + 10000000, + 0, + null, + Direction.ASC.name(), + null, + AccessLevel.READ); + } + } + + @RequestMapping( + value = "/studies", + method = RequestMethod.GET, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(description = "Get all studies") + @ApiResponse( + responseCode = "200", + description = "OK", + content = + @Content(array = @ArraySchema(schema = @Schema(implementation = CancerStudy.class)))) + public ResponseEntity> getAllStudies( + @Parameter(description = "Search keyword that applies to name and cancer type of the studies") + @RequestParam(required = false) + String keyword, + @Parameter(description = "Level of detail of the response") + @RequestParam(defaultValue = "SUMMARY") + Projection projection, + @Parameter(description = "Page size of the result list") + @Max(PagingConstants.MAX_PAGE_SIZE) + @Min(PagingConstants.MIN_PAGE_SIZE) + @RequestParam(defaultValue = PagingConstants.DEFAULT_PAGE_SIZE) + Integer pageSize, + @Parameter(description = "Page number of the result list") + @Min(PagingConstants.MIN_PAGE_NUMBER) + @RequestParam(defaultValue = PagingConstants.DEFAULT_PAGE_NUMBER) + Integer pageNumber, + @Parameter(description = "Name of the property that the result list is sorted by") + @RequestParam(required = false) + StudySortBy sortBy, + @Parameter(description = "Direction of the sort") @RequestParam(defaultValue = "ASC") + Direction direction) { + + Authentication authentication = null; + // Only use this feature on the public portal and make sure it is never used + // on portals using auth, as in auth setting, different users will have different + // results. + if (!PortalSecurityConfig.userAuthorizationEnabled(authenticate) + && appName.equals("public-portal") + && keyword == null + && projection == Projection.SUMMARY + && pageSize == 10000000 + && pageNumber == 0 + && sortBy == null + && direction == Direction.ASC) { + return new ResponseEntity<>(defaultResponse, HttpStatus.OK); + } else authentication = SecurityContextHolder.getContext().getAuthentication(); + + if (projection == Projection.META) { + HttpHeaders responseHeaders = new HttpHeaders(); + responseHeaders.add( + HeaderKeyConstants.TOTAL_COUNT, + studyService.getMetaStudies(keyword).getTotalCount().toString()); + return new ResponseEntity<>(responseHeaders, HttpStatus.OK); + } else { + return new ResponseEntity<>( + studyService.getAllStudies( + keyword, + projection.name(), + pageSize, + pageNumber, + sortBy == null ? null : sortBy.getOriginalValue(), + direction.name(), + authentication, + getAccessLevel()), + HttpStatus.OK); + } + } + + @PreAuthorize( + "hasPermission(#studyId, 'CancerStudyId', T(org.cbioportal.legacy.utils.security.AccessLevel).READ)") + @RequestMapping( + value = "/studies/{studyId}", + method = RequestMethod.GET, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(description = "Get a study") + @ApiResponse( + responseCode = "200", + description = "OK", + content = @Content(schema = @Schema(implementation = CancerStudy.class))) + public ResponseEntity getStudy( + @Parameter(required = true, description = "Study ID e.g. acc_tcga") @PathVariable + String studyId) + throws StudyNotFoundException { + + return new ResponseEntity<>(studyService.getStudy(studyId), HttpStatus.OK); + } + + @PreAuthorize( + "hasPermission(#studyIds, 'Collection', T(org.cbioportal.legacy.utils.security.AccessLevel).READ)") + @RequestMapping( + value = "/studies/fetch", + method = RequestMethod.POST, + consumes = MediaType.APPLICATION_JSON_VALUE, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(description = "Fetch studies by IDs") + @ApiResponse( + responseCode = "200", + description = "OK", + content = + @Content(array = @ArraySchema(schema = @Schema(implementation = CancerStudy.class)))) + public ResponseEntity> fetchStudies( + @Parameter(required = true, description = "List of Study IDs") + @Size(min = 1, max = PagingConstants.MAX_PAGE_SIZE) + @RequestBody + List studyIds, + @Parameter(description = "Level of detail of the response") + @RequestParam(defaultValue = "SUMMARY") + Projection projection) { + + if (projection == Projection.META) { + HttpHeaders responseHeaders = new HttpHeaders(); + responseHeaders.add( + HeaderKeyConstants.TOTAL_COUNT, + studyService.fetchMetaStudies(studyIds).getTotalCount().toString()); + return new ResponseEntity<>(responseHeaders, HttpStatus.OK); + } else { + return new ResponseEntity<>( + studyService.fetchStudies(studyIds, projection.name()), HttpStatus.OK); + } + } + + @RequestMapping( + value = "/studies/{studyId}/tags", + method = RequestMethod.GET, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(description = "Get the tags of a study") + @ApiResponse( + responseCode = "200", + description = "OK", + content = @Content(schema = @Schema(implementation = Object.class))) + public ResponseEntity getTags( + @Parameter(required = true, description = "Study ID e.g. acc_tcga") @PathVariable + String studyId) + throws JsonParseException, JsonMappingException, IOException { + + Map map = new HashMap(); + ObjectMapper mapper = new ObjectMapper(); + CancerStudyTags cancerStudyTags = studyService.getTags(studyId, getAccessLevel()); + if (cancerStudyTags != null) { // If tags is null an empty map is returned + map = mapper.readValue(cancerStudyTags.getTags(), Map.class); + } + + return new ResponseEntity<>(map, HttpStatus.OK); + } + + @PreAuthorize( + "hasPermission(#studyIds, 'Collection', T(org.cbioportal.legacy.utils.security.AccessLevel).READ)") + @PreFilter( + "hasPermission(#studyIds, 'Collection', T(org.cbioportal.legacy.utils.security.AccessLevel).READ)") + @RequestMapping( + value = "/studies/tags/fetch", + method = RequestMethod.POST, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(description = "Get the study tags by IDs") + @ApiResponse( + responseCode = "200", + description = "OK", + content = + @Content(array = @ArraySchema(schema = @Schema(implementation = CancerStudyTags.class)))) + public ResponseEntity> getTagsForMultipleStudies( + @Parameter(required = true, description = "List of Study IDs") @RequestBody + List studyIds) { + + List cancerStudyTags = studyService.getTagsForMultipleStudies(studyIds); + + return new ResponseEntity<>(cancerStudyTags, HttpStatus.OK); + } + + private AccessLevel getAccessLevel() { + return PortalSecurityConfig.userAuthorizationEnabled(authenticate) + && showUnauthorizedStudiesOnHomePage + ? AccessLevel.LIST + : AccessLevel.READ; + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/StudyViewController.java b/src/main/java/org/cbioportal/legacy/web/StudyViewController.java new file mode 100644 index 00000000000..cc3a101817f --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/StudyViewController.java @@ -0,0 +1,1714 @@ +package org.cbioportal.legacy.web; + +import static java.util.stream.Collectors.toSet; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.ArraySchema; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import jakarta.validation.constraints.Max; +import jakarta.validation.constraints.Min; +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Set; +import java.util.function.Function; +import java.util.stream.Collectors; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.math.NumberUtils; +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.apache.commons.math3.stat.correlation.PearsonsCorrelation; +import org.apache.commons.math3.stat.correlation.SpearmansCorrelation; +import org.apache.commons.math3.util.Pair; +import org.cbioportal.legacy.model.AlterationCountByGene; +import org.cbioportal.legacy.model.AlterationCountByStructuralVariant; +import org.cbioportal.legacy.model.AlterationFilter; +import org.cbioportal.legacy.model.CaseListDataCount; +import org.cbioportal.legacy.model.ClinicalAttribute; +import org.cbioportal.legacy.model.ClinicalData; +import org.cbioportal.legacy.model.ClinicalDataBin; +import org.cbioportal.legacy.model.ClinicalDataCountItem; +import org.cbioportal.legacy.model.ClinicalEventTypeCount; +import org.cbioportal.legacy.model.ClinicalViolinPlotData; +import org.cbioportal.legacy.model.CopyNumberCountByGene; +import org.cbioportal.legacy.model.DensityPlotBin; +import org.cbioportal.legacy.model.DensityPlotData; +import org.cbioportal.legacy.model.GenericAssayDataBin; +import org.cbioportal.legacy.model.GenericAssayDataCountItem; +import org.cbioportal.legacy.model.GenomicDataBin; +import org.cbioportal.legacy.model.GenomicDataCount; +import org.cbioportal.legacy.model.GenomicDataCountItem; +import org.cbioportal.legacy.model.NamespaceAttribute; +import org.cbioportal.legacy.model.NamespaceDataCountItem; +import org.cbioportal.legacy.model.Patient; +import org.cbioportal.legacy.model.Sample; +import org.cbioportal.legacy.model.SampleClinicalDataCollection; +import org.cbioportal.legacy.model.SampleList; +import org.cbioportal.legacy.service.ClinicalAttributeService; +import org.cbioportal.legacy.service.ClinicalDataService; +import org.cbioportal.legacy.service.ClinicalEventService; +import org.cbioportal.legacy.service.PatientService; +import org.cbioportal.legacy.service.SampleListService; +import org.cbioportal.legacy.service.SampleService; +import org.cbioportal.legacy.service.StudyViewService; +import org.cbioportal.legacy.service.ViolinPlotService; +import org.cbioportal.legacy.service.exception.StudyNotFoundException; +import org.cbioportal.legacy.service.util.ClinicalAttributeUtil; +import org.cbioportal.legacy.web.config.annotation.InternalApi; +import org.cbioportal.legacy.web.parameter.ClinicalDataBinCountFilter; +import org.cbioportal.legacy.web.parameter.ClinicalDataBinFilter; +import org.cbioportal.legacy.web.parameter.ClinicalDataCountFilter; +import org.cbioportal.legacy.web.parameter.ClinicalDataFilter; +import org.cbioportal.legacy.web.parameter.DataBinMethod; +import org.cbioportal.legacy.web.parameter.Direction; +import org.cbioportal.legacy.web.parameter.GenericAssayDataBinCountFilter; +import org.cbioportal.legacy.web.parameter.GenericAssayDataCountFilter; +import org.cbioportal.legacy.web.parameter.GenericAssayDataFilter; +import org.cbioportal.legacy.web.parameter.GenomicDataBinCountFilter; +import org.cbioportal.legacy.web.parameter.GenomicDataCountFilter; +import org.cbioportal.legacy.web.parameter.GenomicDataFilter; +import org.cbioportal.legacy.web.parameter.HeaderKeyConstants; +import org.cbioportal.legacy.web.parameter.MutationOption; +import org.cbioportal.legacy.web.parameter.NamespaceDataCountFilter; +import org.cbioportal.legacy.web.parameter.NamespaceDataFilter; +import org.cbioportal.legacy.web.parameter.PagingConstants; +import org.cbioportal.legacy.web.parameter.Projection; +import org.cbioportal.legacy.web.parameter.SampleIdentifier; +import org.cbioportal.legacy.web.parameter.StudyViewFilter; +import org.cbioportal.legacy.web.util.ClinicalDataBinUtil; +import org.cbioportal.legacy.web.util.ClinicalDataFetcher; +import org.cbioportal.legacy.web.util.StudyViewFilterApplier; +import org.cbioportal.legacy.web.util.StudyViewFilterUtil; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.context.ApplicationContext; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestAttribute; +import org.springframework.web.bind.annotation.RequestBody; +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.bind.annotation.RestController; + +@InternalApi +@RestController() +@RequestMapping("/api") +@Validated +@Tag(name = "Study View", description = " ") +public class StudyViewController { + + public static final int CLINICAL_TAB_MAX_PAGE_SIZE = 1000000; + + @Autowired private ApplicationContext applicationContext; + StudyViewController instance; + + @Autowired private StudyViewFilterApplier studyViewFilterApplier; + @Autowired private ClinicalDataService clinicalDataService; + @Autowired private ClinicalDataFetcher clinicalDataFetcher; + @Autowired private SampleService sampleService; + @Autowired private PatientService patientService; + @Autowired private StudyViewFilterUtil studyViewFilterUtil; + @Autowired private ClinicalAttributeService clinicalAttributeService; + @Autowired private ViolinPlotService violinPlotService; + @Autowired private ClinicalAttributeUtil clinicalAttributeUtil; + @Autowired private SampleListService sampleListService; + @Autowired private StudyViewService studyViewService; + @Autowired private ClinicalDataBinUtil clinicalDataBinUtil; + @Autowired private ClinicalEventService clinicalEventService; + + private StudyViewController getInstance() { + if (Objects.isNull(instance)) { + instance = applicationContext.getBean(StudyViewController.class); + } + return instance; + } + + @PreAuthorize( + "hasPermission(#involvedCancerStudies, 'Collection', T(org.cbioportal.legacy.utils.security.AccessLevel).READ)") + @RequestMapping( + value = "/clinical-data-counts/fetch", + method = RequestMethod.POST, + consumes = MediaType.APPLICATION_JSON_VALUE, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(description = "Fetch clinical data counts by study view filter") + @ApiResponse( + responseCode = "200", + description = "OK", + content = + @Content( + array = @ArraySchema(schema = @Schema(implementation = ClinicalDataCountItem.class)))) + public ResponseEntity> fetchClinicalDataCounts( + @Parameter(required = true, description = "Clinical data count filter") + @Valid + @RequestBody(required = false) + ClinicalDataCountFilter clinicalDataCountFilter, + @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface + @RequestAttribute(required = false, value = "involvedCancerStudies") + Collection involvedCancerStudies, + @Parameter( + hidden = + true) // prevent reference to this attribute in the swagger-ui interface. this + // attribute is needed for the @PreAuthorize tag above. + @Valid + @RequestAttribute(required = false, value = "interceptedClinicalDataCountFilter") + ClinicalDataCountFilter interceptedClinicalDataCountFilter) { + + List attributes = interceptedClinicalDataCountFilter.getAttributes(); + StudyViewFilter studyViewFilter = interceptedClinicalDataCountFilter.getStudyViewFilter(); + + if (attributes.size() == 1) { + studyViewFilterUtil.removeSelfFromFilter(attributes.get(0).getAttributeId(), studyViewFilter); + } + boolean unfilteredQuery = studyViewFilterUtil.isUnfilteredQuery(studyViewFilter); + List result = + this.getInstance() + .cachedClinicalDataCounts(interceptedClinicalDataCountFilter, unfilteredQuery); + return new ResponseEntity<>(result, HttpStatus.OK); + } + + @Cacheable( + cacheResolver = "staticRepositoryCacheOneResolver", + condition = "@cacheEnabledConfig.getEnabled() && #unfilteredQuery") + public List cachedClinicalDataCounts( + ClinicalDataCountFilter interceptedClinicalDataCountFilter, boolean unfilteredQuery) { + List attributes = interceptedClinicalDataCountFilter.getAttributes(); + StudyViewFilter studyViewFilter = interceptedClinicalDataCountFilter.getStudyViewFilter(); + if (attributes.size() == 1) { + studyViewFilterUtil.removeSelfFromFilter(attributes.get(0).getAttributeId(), studyViewFilter); + } + List filteredSampleIdentifiers = + studyViewFilterApplier.apply(studyViewFilter); + + if (filteredSampleIdentifiers.isEmpty()) { + return new ArrayList<>(); + } + List studyIds = new ArrayList<>(); + List sampleIds = new ArrayList<>(); + studyViewFilterUtil.extractStudyAndSampleIds(filteredSampleIdentifiers, studyIds, sampleIds); + + List result = + clinicalDataService.fetchClinicalDataCounts( + studyIds, + sampleIds, + attributes.stream().map(a -> a.getAttributeId()).collect(Collectors.toList())); + + return result; + } + + @PreAuthorize( + "hasPermission(#involvedCancerStudies, 'Collection', T(org.cbioportal.legacy.utils.security.AccessLevel).READ)") + @RequestMapping( + value = "/clinical-data-bin-counts/fetch", + method = RequestMethod.POST, + consumes = MediaType.APPLICATION_JSON_VALUE, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(description = "Fetch clinical data bin counts by study view filter") + @ApiResponse( + responseCode = "200", + description = "OK", + content = + @Content(array = @ArraySchema(schema = @Schema(implementation = ClinicalDataBin.class)))) + public ResponseEntity> fetchClinicalDataBinCounts( + @Parameter(description = "Method for data binning") @RequestParam(defaultValue = "DYNAMIC") + DataBinMethod dataBinMethod, + @Parameter(required = true, description = "Clinical data bin count filter") + @Valid + @RequestBody(required = false) + ClinicalDataBinCountFilter clinicalDataBinCountFilter, + @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface + @RequestAttribute(required = false, value = "involvedCancerStudies") + Collection involvedCancerStudies, + @Parameter( + hidden = + true) // prevent reference to this attribute in the swagger-ui interface. this + // attribute is needed for the @PreAuthorize tag above. + @Valid + @RequestAttribute(required = false, value = "interceptedClinicalDataBinCountFilter") + ClinicalDataBinCountFilter interceptedClinicalDataBinCountFilter) { + StudyViewFilter studyViewFilter = + clinicalDataBinUtil.removeSelfFromFilter(interceptedClinicalDataBinCountFilter); + boolean unfilteredQuery = studyViewFilterUtil.isUnfilteredQuery(studyViewFilter); + List clinicalDataBins = + this.getInstance() + .cachableFetchClinicalDataBinCounts( + dataBinMethod, interceptedClinicalDataBinCountFilter, unfilteredQuery); + + return new ResponseEntity<>(clinicalDataBins, HttpStatus.OK); + } + + @Cacheable( + cacheResolver = "staticRepositoryCacheOneResolver", + condition = "@cacheEnabledConfig.getEnabled() && #unfilteredQuery") + public List cachableFetchClinicalDataBinCounts( + DataBinMethod dataBinMethod, + ClinicalDataBinCountFilter interceptedClinicalDataBinCountFilter, + boolean unfilteredQuery) { + return clinicalDataBinUtil.fetchClinicalDataBinCounts( + dataBinMethod, + interceptedClinicalDataBinCountFilter, + // we don't need to remove filter again since we already did it in the previous step + false); + } + + @PreAuthorize( + "hasPermission(#involvedCancerStudies, 'Collection', T(org.cbioportal.legacy.utils.security.AccessLevel).READ)") + @RequestMapping( + value = "/custom-data-bin-counts/fetch", + method = RequestMethod.POST, + consumes = MediaType.APPLICATION_JSON_VALUE, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(description = "Fetch custom data bin counts by study view filter") + @ApiResponse( + responseCode = "200", + description = "OK", + content = + @Content(array = @ArraySchema(schema = @Schema(implementation = ClinicalDataBin.class)))) + public ResponseEntity> fetchCustomDataBinCounts( + @Parameter(description = "Method for data binning") @RequestParam(defaultValue = "DYNAMIC") + DataBinMethod dataBinMethod, + @Parameter(required = true, description = "Clinical data bin count filter") + @Valid + @RequestBody(required = false) + ClinicalDataBinCountFilter clinicalDataBinCountFilter, + @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface + @RequestAttribute(required = false, value = "involvedCancerStudies") + Collection involvedCancerStudies, + @Parameter( + hidden = + true) // prevent reference to this attribute in the swagger-ui interface. this + // attribute is needed for the @PreAuthorize tag above. + @Valid + @RequestAttribute(required = false, value = "interceptedClinicalDataBinCountFilter") + ClinicalDataBinCountFilter interceptedClinicalDataBinCountFilter) { + // TODO code shared with ClinicalDataController.fetchCustomDataCounts + List attributes = interceptedClinicalDataBinCountFilter.getAttributes(); + StudyViewFilter studyViewFilter = interceptedClinicalDataBinCountFilter.getStudyViewFilter(); + if (attributes.size() == 1) { + studyViewFilterUtil.removeSelfCustomDataFromFilter( + attributes.get(0).getAttributeId(), studyViewFilter); + } + List filteredSampleIdentifiers = + studyViewFilterApplier.apply(studyViewFilter); + + if (filteredSampleIdentifiers.isEmpty()) { + return new ResponseEntity<>(new ArrayList<>(), HttpStatus.OK); + } + + final List clinicalDataBins = + clinicalDataBinUtil.fetchCustomDataBinCounts( + dataBinMethod, interceptedClinicalDataBinCountFilter, false); + + return new ResponseEntity<>(clinicalDataBins, HttpStatus.OK); + } + + @PreAuthorize( + "hasPermission(#involvedCancerStudies, 'Collection',T(org.cbioportal.legacy.utils.security.AccessLevel).READ)") + @RequestMapping( + value = "/mutated-genes/fetch", + method = RequestMethod.POST, + consumes = MediaType.APPLICATION_JSON_VALUE, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(description = "Fetch mutated genes by study view filter") + @ApiResponse( + responseCode = "200", + description = "OK", + content = + @Content( + array = @ArraySchema(schema = @Schema(implementation = AlterationCountByGene.class)))) + public ResponseEntity> fetchMutatedGenes( + @Parameter(required = true, description = "Study view filter") + @Valid + @RequestBody(required = false) + StudyViewFilter studyViewFilter, + @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface + @RequestAttribute(required = false, value = "involvedCancerStudies") + Collection involvedCancerStudies, + @Parameter( + hidden = + true) // prevent reference to this attribute in the swagger-ui interface. this + // attribute is needed for the @PreAuthorize tag above. + @Valid + @RequestAttribute(required = false, value = "interceptedStudyViewFilter") + StudyViewFilter interceptedStudyViewFilter) + throws StudyNotFoundException { + boolean unfilteredQuery = studyViewFilterUtil.isUnfilteredQuery(interceptedStudyViewFilter); + List alterationCountByGenes = + this.getInstance().cachedFetchMutatedGenes(interceptedStudyViewFilter, unfilteredQuery); + return new ResponseEntity<>(alterationCountByGenes, HttpStatus.OK); + } + + @Cacheable( + cacheResolver = "staticRepositoryCacheOneResolver", + condition = "@cacheEnabledConfig.getEnabled() && #unfilteredQuery") + public List cachedFetchMutatedGenes( + StudyViewFilter interceptedStudyViewFilter, boolean unfilteredQuery) + throws StudyNotFoundException { + AlterationFilter annotationFilters = interceptedStudyViewFilter.getAlterationFilter(); + + List sampleIdentifiers = + studyViewFilterApplier.apply(interceptedStudyViewFilter); + List alterationCountByGenes = new ArrayList<>(); + if (CollectionUtils.isNotEmpty(sampleIdentifiers)) { + List studyIds = new ArrayList<>(); + List sampleIds = new ArrayList<>(); + studyViewFilterUtil.extractStudyAndSampleIds(sampleIdentifiers, studyIds, sampleIds); + alterationCountByGenes = + studyViewService.getMutationAlterationCountByGenes( + studyIds, sampleIds, annotationFilters); + } + return alterationCountByGenes; + } + + @PreAuthorize( + "hasPermission(#involvedCancerStudies, 'Collection', T(org.cbioportal.legacy.utils.security.AccessLevel).READ)") + @RequestMapping( + value = "/structuralvariant-genes/fetch", + method = RequestMethod.POST, + consumes = MediaType.APPLICATION_JSON_VALUE, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(description = "Fetch structural variant genes by study view filter") + @ApiResponse( + responseCode = "200", + description = "OK", + content = + @Content( + array = @ArraySchema(schema = @Schema(implementation = AlterationCountByGene.class)))) + public ResponseEntity> fetchStructuralVariantGenes( + @Parameter(required = true, description = "Study view filter") + @Valid + @RequestBody(required = false) + StudyViewFilter studyViewFilter, + @Parameter( + hidden = + true) // prevent reference to this attribute in the swagger-ui interface. This + // attribute is needed for the @PreAuthorize tag above. + @RequestAttribute(required = false, value = "involvedCancerStudies") + Collection involvedCancerStudies, + @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface. + @Valid + @RequestAttribute(required = false, value = "interceptedStudyViewFilter") + StudyViewFilter interceptedStudyViewFilter) + throws StudyNotFoundException { + + boolean unfilteredQuery = studyViewFilterUtil.isUnfilteredQuery(interceptedStudyViewFilter); + List alterationCountByGenes = + this.getInstance() + .cacheableFetchStructuralVariantGenes(interceptedStudyViewFilter, unfilteredQuery); + return new ResponseEntity<>(alterationCountByGenes, HttpStatus.OK); + } + + @Cacheable( + cacheResolver = "staticRepositoryCacheOneResolver", + condition = "@cacheEnabledConfig.getEnabled() && #unfilteredQuery") + public List cacheableFetchStructuralVariantGenes( + StudyViewFilter interceptedStudyViewFilter, boolean unfilteredQuery) + throws StudyNotFoundException { + AlterationFilter annotationFilters = interceptedStudyViewFilter.getAlterationFilter(); + + List sampleIdentifiers = + studyViewFilterApplier.apply(interceptedStudyViewFilter); + List alterationCountByGenes = new ArrayList<>(); + if (CollectionUtils.isNotEmpty(sampleIdentifiers)) { + List studyIds = new ArrayList<>(); + List sampleIds = new ArrayList<>(); + studyViewFilterUtil.extractStudyAndSampleIds(sampleIdentifiers, studyIds, sampleIds); + alterationCountByGenes = + studyViewService.getStructuralVariantAlterationCountByGenes( + studyIds, sampleIds, annotationFilters); + } + return alterationCountByGenes; + } + + @PreAuthorize( + "hasPermission(#involvedCancerStudies, 'Collection', T(org.cbioportal.legacy.utils.security.AccessLevel).READ)") + @RequestMapping( + value = "/structuralvariant-counts/fetch", + method = RequestMethod.POST, + consumes = MediaType.APPLICATION_JSON_VALUE, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(description = "Fetch structural variant genes by study view filter") + @ApiResponse( + responseCode = "200", + description = "OK", + content = + @Content( + array = + @ArraySchema( + schema = @Schema(implementation = AlterationCountByStructuralVariant.class)))) + public ResponseEntity> fetchStructuralVariantCounts( + @Parameter(required = true, description = "Study view filter") + @Valid + @RequestBody(required = false) + StudyViewFilter studyViewFilter, + @Parameter( + hidden = + true) // prevent reference to this attribute in the swagger-ui interface. This + // attribute is needed for the @PreAuthorize tag above. + @RequestAttribute(required = false, value = "involvedCancerStudies") + Collection involvedCancerStudies, + @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface. + @Valid + @RequestAttribute(required = false, value = "interceptedStudyViewFilter") + StudyViewFilter interceptedStudyViewFilter) + throws StudyNotFoundException { + + boolean unfilteredQuery = studyViewFilterUtil.isUnfilteredQuery(interceptedStudyViewFilter); + List alterationCountByStructuralVariants = + this.getInstance() + .cacheableFetchStructuralVariantCounts(interceptedStudyViewFilter, unfilteredQuery); + return new ResponseEntity<>(alterationCountByStructuralVariants, HttpStatus.OK); + } + + @Cacheable( + cacheResolver = "staticRepositoryCacheOneResolver", + condition = "@cacheEnabledConfig.getEnabled() && #unfilteredQuery") + public List cacheableFetchStructuralVariantCounts( + StudyViewFilter interceptedStudyViewFilter, boolean unfilteredQuery) { + + List sampleIdentifiers = + studyViewFilterApplier.apply(interceptedStudyViewFilter); + if (CollectionUtils.isNotEmpty(sampleIdentifiers)) { + List studyIds = new ArrayList<>(); + List sampleIds = new ArrayList<>(); + studyViewFilterUtil.extractStudyAndSampleIds(sampleIdentifiers, studyIds, sampleIds); + return studyViewService.getStructuralVariantAlterationCounts( + studyIds, sampleIds, interceptedStudyViewFilter.getAlterationFilter()); + } + return new ArrayList<>(); + } + + @PreAuthorize( + "hasPermission(#involvedCancerStudies, 'Collection', T(org.cbioportal.legacy.utils.security.AccessLevel).READ)") + @RequestMapping( + value = "/cna-genes/fetch", + method = RequestMethod.POST, + consumes = MediaType.APPLICATION_JSON_VALUE, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(description = "Fetch CNA genes by study view filter") + @ApiResponse( + responseCode = "200", + description = "OK", + content = + @Content( + array = @ArraySchema(schema = @Schema(implementation = CopyNumberCountByGene.class)))) + public ResponseEntity> fetchCNAGenes( + @Parameter(required = true, description = "Study view filter") + @Valid + @RequestBody(required = false) + StudyViewFilter studyViewFilter, + @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface + @RequestAttribute(required = false, value = "involvedCancerStudies") + Collection involvedCancerStudies, + @Parameter( + hidden = + true) // prevent reference to this attribute in the swagger-ui interface. this + // attribute is needed for the @PreAuthorize tag above. + @Valid + @RequestAttribute(required = false, value = "interceptedStudyViewFilter") + StudyViewFilter interceptedStudyViewFilter) + throws StudyNotFoundException { + boolean unfilteredQuery = studyViewFilterUtil.isUnfilteredQuery(interceptedStudyViewFilter); + List copyNumberCountByGenes = + this.getInstance().cacheableFetchCNAGenes(interceptedStudyViewFilter, unfilteredQuery); + return new ResponseEntity<>(copyNumberCountByGenes, HttpStatus.OK); + } + + @Cacheable( + cacheResolver = "staticRepositoryCacheOneResolver", + condition = "@cacheEnabledConfig.getEnabled() && #unfilteredQuery") + public List cacheableFetchCNAGenes( + StudyViewFilter interceptedStudyViewFilter, boolean unfilteredQuery) + throws StudyNotFoundException { + AlterationFilter alterationFilter = interceptedStudyViewFilter.getAlterationFilter(); + + List sampleIdentifiers = + studyViewFilterApplier.apply(interceptedStudyViewFilter); + List copyNumberCountByGenes = new ArrayList<>(); + if (CollectionUtils.isNotEmpty(sampleIdentifiers)) { + List studyIds = new ArrayList<>(); + List sampleIds = new ArrayList<>(); + studyViewFilterUtil.extractStudyAndSampleIds(sampleIdentifiers, studyIds, sampleIds); + copyNumberCountByGenes = + studyViewService.getCNAAlterationCountByGenes(studyIds, sampleIds, alterationFilter); + } + return copyNumberCountByGenes; + } + + @PreAuthorize( + "hasPermission(#involvedCancerStudies, 'Collection', T(org.cbioportal.legacy.utils.security.AccessLevel).READ)") + @RequestMapping( + value = "/filtered-samples/fetch", + method = RequestMethod.POST, + consumes = MediaType.APPLICATION_JSON_VALUE, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(description = "Fetch sample IDs by study view filter") + @ApiResponse( + responseCode = "200", + description = "OK", + content = @Content(array = @ArraySchema(schema = @Schema(implementation = Sample.class)))) + public ResponseEntity> fetchFilteredSamples( + @Parameter(description = "Whether to negate the study view filters") + @RequestParam(defaultValue = "false") + boolean negateFilters, + @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface + @RequestAttribute(required = false, value = "involvedCancerStudies") + Collection involvedCancerStudies, + @Parameter( + hidden = + true) // prevent reference to this attribute in the swagger-ui interface. this + // attribute is needed for the @PreAuthorize tag above. + @Valid + @RequestAttribute(required = false, value = "interceptedStudyViewFilter") + StudyViewFilter interceptedStudyViewFilter, + @Parameter(required = true, description = "Study view filter") + @Valid + @RequestBody(required = false) + StudyViewFilter studyViewFilter) { + + List studyIds = new ArrayList<>(); + List sampleIds = new ArrayList<>(); + + studyViewFilterUtil.extractStudyAndSampleIds( + studyViewFilterApplier.apply(interceptedStudyViewFilter, negateFilters), + studyIds, + sampleIds); + + List result = new ArrayList<>(); + if (!sampleIds.isEmpty()) { + result = sampleService.fetchSamples(studyIds, sampleIds, Projection.ID.name()); + } + return new ResponseEntity<>(result, HttpStatus.OK); + } + + @PreAuthorize( + "hasPermission(#involvedCancerStudies, 'Collection', T(org.cbioportal.legacy.utils.security.AccessLevel).READ)") + @RequestMapping( + value = "/molecular-profile-sample-counts/fetch", + method = RequestMethod.POST, + consumes = MediaType.APPLICATION_JSON_VALUE, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(description = "Fetch sample counts by study view filter") + @ApiResponse( + responseCode = "200", + description = "OK", + content = + @Content(array = @ArraySchema(schema = @Schema(implementation = GenomicDataCount.class)))) + public ResponseEntity> fetchMolecularProfileSampleCounts( + @Parameter(required = true, description = "Study view filter") + @Valid + @RequestBody(required = false) + StudyViewFilter studyViewFilter, + @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface + @RequestAttribute(required = false, value = "involvedCancerStudies") + Collection involvedCancerStudies, + @Parameter( + hidden = + true) // prevent reference to this attribute in the swagger-ui interface. this + // attribute is needed for the @PreAuthorize tag above. + @Valid + @RequestAttribute(required = false, value = "interceptedStudyViewFilter") + StudyViewFilter interceptedStudyViewFilter) { + boolean unfilteredQuery = studyViewFilterUtil.isUnfilteredQuery(interceptedStudyViewFilter); + List sampleCounts = + this.getInstance() + .cacheableFetchMolecularProfileSampleCounts( + interceptedStudyViewFilter, unfilteredQuery); + return new ResponseEntity<>(sampleCounts, HttpStatus.OK); + } + + @Cacheable( + cacheResolver = "staticRepositoryCacheOneResolver", + condition = "@cacheEnabledConfig.getEnabled() && #unfilteredQuery") + public List cacheableFetchMolecularProfileSampleCounts( + StudyViewFilter interceptedStudyViewFilter, boolean unfilteredQuery) { + List sampleIdentifiers = + studyViewFilterApplier.apply(interceptedStudyViewFilter); + List genomicDataCounts = new ArrayList<>(); + if (CollectionUtils.isNotEmpty(sampleIdentifiers)) { + List studyIds = new ArrayList<>(); + List sampleIds = new ArrayList<>(); + studyViewFilterUtil.extractStudyAndSampleIds(sampleIdentifiers, studyIds, sampleIds); + genomicDataCounts = studyViewService.getGenomicDataCounts(studyIds, sampleIds); + } + return genomicDataCounts; + } + + private static boolean isLogScalePossibleForAttribute(String clinicalAttributeId) { + return clinicalAttributeId.equals("MUTATION_COUNT"); + } + + private static double logScale(double val) { + return Math.log(1 + val); + } + + private static double parseValueLog(ClinicalData c) { + return StudyViewController.logScale(Double.parseDouble(c.getAttrValue())); + } + + private static double parseValueLinear(ClinicalData c) { + return Double.parseDouble(c.getAttrValue()); + } + + @PreAuthorize( + "hasPermission(#involvedCancerStudies, 'Collection', T(org.cbioportal.legacy.utils.security.AccessLevel).READ)") + @RequestMapping( + value = "/clinical-data-density-plot/fetch", + method = RequestMethod.POST, + consumes = MediaType.APPLICATION_JSON_VALUE, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(description = "Fetch clinical data density plot bins by study view filter") + @ApiResponse( + responseCode = "200", + description = "OK", + content = @Content(schema = @Schema(implementation = DensityPlotData.class))) + @Validated + public ResponseEntity fetchClinicalDataDensityPlot( + @Parameter(required = true, description = "Clinical Attribute ID of the X axis") @RequestParam + String xAxisAttributeId, + @Parameter(description = "Number of the bins in X axis") @RequestParam(defaultValue = "50") + Integer xAxisBinCount, + @Parameter(description = "Starting point of the X axis, if different than smallest value") + @RequestParam(required = false) + BigDecimal xAxisStart, + @Parameter(description = "Starting point of the X axis, if different than largest value") + @RequestParam(required = false) + BigDecimal xAxisEnd, + @Parameter(required = true, description = "Clinical Attribute ID of the Y axis") @RequestParam + String yAxisAttributeId, + @Parameter(description = "Number of the bins in Y axis") @RequestParam(defaultValue = "50") + Integer yAxisBinCount, + @Parameter(description = "Starting point of the Y axis, if different than smallest value") + @RequestParam(required = false) + BigDecimal yAxisStart, + @Parameter(description = "Starting point of the Y axis, if different than largest value") + @RequestParam(required = false) + BigDecimal yAxisEnd, + @Parameter(description = "Use log scale for X axis") + @RequestParam(required = false, defaultValue = "false") + Boolean xAxisLogScale, + @Schema(defaultValue = "false") + @Parameter(description = "Use log scale for Y axis") + @RequestParam(required = false, defaultValue = "false") + Boolean yAxisLogScale, + @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface + @RequestAttribute(required = false, value = "involvedCancerStudies") + Collection involvedCancerStudies, + @Parameter( + hidden = + true) // prevent reference to this attribute in the swagger-ui interface. this + // attribute is needed for the @PreAuthorize tag above. + @Valid + @RequestAttribute(required = false, value = "interceptedStudyViewFilter") + StudyViewFilter interceptedStudyViewFilter, + @Parameter(required = true, description = "Study view filter") @RequestBody(required = false) + StudyViewFilter studyViewFilter) { + + List studyIds = new ArrayList<>(); + List sampleIds = new ArrayList<>(); + studyViewFilterUtil.extractStudyAndSampleIds( + studyViewFilterApplier.apply(interceptedStudyViewFilter), studyIds, sampleIds); + DensityPlotData result = new DensityPlotData(); + result.setBins(new ArrayList<>()); + if (sampleIds.isEmpty()) { + return new ResponseEntity<>(result, HttpStatus.OK); + } + + List sampleAttributeIds = new ArrayList<>(); + List patientAttributeIds = new ArrayList<>(); + + List clinicalAttributes = + clinicalAttributeService.getClinicalAttributesByStudyIdsAndAttributeIds( + studyIds, Arrays.asList(xAxisAttributeId, yAxisAttributeId)); + + clinicalAttributeUtil.extractCategorizedClinicalAttributes( + clinicalAttributes, sampleAttributeIds, patientAttributeIds, patientAttributeIds); + + List patientIds = new ArrayList<>(); + List studyIdsOfPatients = new ArrayList<>(); + Map>> patientToSamples = null; + + if (CollectionUtils.isNotEmpty(patientAttributeIds)) { + List samples = + sampleService.fetchSamples(studyIds, sampleIds, Projection.DETAILED.name()); + List patients = patientService.getPatientsOfSamples(studyIds, sampleIds); + patientIds = patients.stream().map(Patient::getStableId).toList(); + studyIdsOfPatients = patients.stream().map(Patient::getCancerStudyIdentifier).toList(); + patientToSamples = + samples.stream() + .collect( + Collectors.groupingBy( + Sample::getPatientStableId, + Collectors.groupingBy(Sample::getCancerStudyIdentifier))); + } + + List clinicalDataList = + clinicalDataFetcher.fetchClinicalData( + studyIds, + sampleIds, + patientIds, + studyIdsOfPatients, + sampleAttributeIds, + patientAttributeIds, + null); + + List sampleClinicalDataList; + // put all clinical data into sample form + if (CollectionUtils.isNotEmpty(patientAttributeIds)) { + sampleClinicalDataList = new ArrayList<>(); + for (ClinicalData d : clinicalDataList) { + if (d.getSampleId() == null) { + // null sample id means its a patient data, + // we need to distribute the value to samples + List samplesForPatient = + patientToSamples.get(d.getPatientId()).get(d.getStudyId()); + if (samplesForPatient != null) { + for (Sample s : samplesForPatient) { + ClinicalData newData = new ClinicalData(); + newData.setAttrId(d.getAttrId()); + newData.setPatientId(d.getPatientId()); + newData.setStudyId(d.getStudyId()); + newData.setAttrValue(d.getAttrValue()); + newData.setSampleId(s.getStableId()); + sampleClinicalDataList.add(newData); + } + } else { + // patient has no samples - this shouldn't happen and could affect the integrity + // of the data analysis + return new ResponseEntity<>(null, HttpStatus.INTERNAL_SERVER_ERROR); + } + } else { + // if its a sample data, just add it to the list + sampleClinicalDataList.add(d); + } + } + } else { + sampleClinicalDataList = clinicalDataList; + } + + // clinicalDataMap is a map sampleId->studyId->data + Map>> clinicalDataMap = + sampleClinicalDataList.stream() + .collect( + Collectors.groupingBy( + ClinicalData::getSampleId, Collectors.groupingBy(ClinicalData::getStudyId))); + + List filteredClinicalDataList = new ArrayList<>(); + clinicalDataMap.forEach( + (k, v) -> + v.forEach( + (m, n) -> { + if ( + // n.size() == 2 means we have clinical data for the sample for both of the + // queried attributes + n.size() == 2 + && + // check if both of the sample data are numerical + NumberUtils.isCreatable(n.get(0).getAttrValue()) + && NumberUtils.isCreatable(n.get(1).getAttrValue())) { + filteredClinicalDataList.addAll(n); + } + })); + if (filteredClinicalDataList.isEmpty()) { + return new ResponseEntity<>(result, HttpStatus.OK); + } + + Map> partition = + filteredClinicalDataList.stream() + .collect(Collectors.partitioningBy(c -> c.getAttrId().equals(xAxisAttributeId))); + + boolean useXLogScale = + xAxisLogScale && StudyViewController.isLogScalePossibleForAttribute(xAxisAttributeId); + boolean useYLogScale = + yAxisLogScale && StudyViewController.isLogScalePossibleForAttribute(yAxisAttributeId); + + double[] xValues = + partition.get(true).stream() + .mapToDouble( + useXLogScale + ? StudyViewController::parseValueLog + : StudyViewController::parseValueLinear) + .toArray(); + double[] yValues = + partition.get(false).stream() + .mapToDouble( + useYLogScale + ? StudyViewController::parseValueLog + : StudyViewController::parseValueLinear) + .toArray(); + double[] xValuesCopy = Arrays.copyOf(xValues, xValues.length); + double[] yValuesCopy = Arrays.copyOf(yValues, yValues.length); + Arrays.sort(xValuesCopy); + Arrays.sort(yValuesCopy); + + double xAxisStartValue = + xAxisStart == null + ? xValuesCopy[0] + : (useXLogScale + ? StudyViewController.logScale(xAxisStart.doubleValue()) + : xAxisStart.doubleValue()); + double xAxisEndValue = + xAxisEnd == null + ? xValuesCopy[xValuesCopy.length - 1] + : (useXLogScale + ? StudyViewController.logScale(xAxisEnd.doubleValue()) + : xAxisEnd.doubleValue()); + double yAxisStartValue = + yAxisStart == null + ? yValuesCopy[0] + : (useYLogScale + ? StudyViewController.logScale(yAxisStart.doubleValue()) + : yAxisStart.doubleValue()); + double yAxisEndValue = + yAxisEnd == null + ? yValuesCopy[yValuesCopy.length - 1] + : (useYLogScale + ? StudyViewController.logScale(yAxisEnd.doubleValue()) + : yAxisEnd.doubleValue()); + double xAxisBinInterval = (xAxisEndValue - xAxisStartValue) / xAxisBinCount; + double yAxisBinInterval = (yAxisEndValue - yAxisStartValue) / yAxisBinCount; + List bins = result.getBins(); + for (int i = 0; i < xAxisBinCount; i++) { + for (int j = 0; j < yAxisBinCount; j++) { + DensityPlotBin densityPlotBin = new DensityPlotBin(); + densityPlotBin.setBinX(BigDecimal.valueOf(xAxisStartValue + (i * xAxisBinInterval))); + densityPlotBin.setBinY(BigDecimal.valueOf(yAxisStartValue + (j * yAxisBinInterval))); + densityPlotBin.setCount(0); + bins.add(densityPlotBin); + } + } + + for (int i = 0; i < xValues.length; i++) { + double xValue = xValues[i]; + double yValue = yValues[i]; + int xBinIndex = (int) ((xValue - xAxisStartValue) / xAxisBinInterval); + int yBinIndex = (int) ((yValue - yAxisStartValue) / yAxisBinInterval); + int index = + (int) + (((xBinIndex - (xBinIndex == xAxisBinCount ? 1 : 0)) * yAxisBinCount) + + (yBinIndex - (yBinIndex == yAxisBinCount ? 1 : 0))); + DensityPlotBin densityPlotBin = bins.get(index); + densityPlotBin.setCount(densityPlotBin.getCount() + 1); + BigDecimal xValueBigDecimal = BigDecimal.valueOf(xValue); + BigDecimal yValueBigDecimal = BigDecimal.valueOf(yValue); + if (densityPlotBin.getMinX() != null) { + if (densityPlotBin.getMinX().compareTo(xValueBigDecimal) > 0) { + densityPlotBin.setMinX(xValueBigDecimal); + } + } else { + densityPlotBin.setMinX(xValueBigDecimal); + } + if (densityPlotBin.getMaxX() != null) { + if (densityPlotBin.getMaxX().compareTo(xValueBigDecimal) < 0) { + densityPlotBin.setMaxX(xValueBigDecimal); + } + } else { + densityPlotBin.setMaxX(xValueBigDecimal); + } + if (densityPlotBin.getMinY() != null) { + if (densityPlotBin.getMinY().compareTo(yValueBigDecimal) > 0) { + densityPlotBin.setMinY(yValueBigDecimal); + } + } else { + densityPlotBin.setMinY(yValueBigDecimal); + } + if (densityPlotBin.getMaxY() != null) { + if (densityPlotBin.getMaxY().compareTo(yValueBigDecimal) < 0) { + densityPlotBin.setMaxY(yValueBigDecimal); + } + } else { + densityPlotBin.setMaxY(yValueBigDecimal); + } + } + + if (xValues.length > 1) { + // need at least 2 entries in each to compute correlation + result.setPearsonCorr(new PearsonsCorrelation().correlation(xValues, yValues)); + result.setSpearmanCorr(new SpearmansCorrelation().correlation(xValues, yValues)); + } else { + // if less than 1 entry, just set 0 correlation + result.setSpearmanCorr(0.0); + result.setPearsonCorr(0.0); + } + + // filter out empty bins + result.setBins( + result.getBins().stream() + .filter((bin) -> (bin.getCount() > 0)) + .collect(Collectors.toList())); + + return new ResponseEntity<>(result, HttpStatus.OK); + } + + @PreAuthorize( + "hasPermission(#involvedCancerStudies, 'Collection', T(org.cbioportal.legacy.utils.security.AccessLevel).READ)") + @RequestMapping( + value = "/clinical-data-violin-plots/fetch", + method = RequestMethod.POST, + consumes = MediaType.APPLICATION_JSON_VALUE, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation( + description = + "Fetch violin plot curves per categorical clinical data value, filtered by study view filter") + @ApiResponse( + responseCode = "200", + description = "OK", + content = @Content(schema = @Schema(implementation = ClinicalViolinPlotData.class))) + public ResponseEntity fetchClinicalDataViolinPlots( + @Parameter( + required = true, + description = "Clinical Attribute ID of the categorical attribute") + @RequestParam + String categoricalAttributeId, + @Parameter(required = true, description = "Clinical Attribute ID of the numerical attribute") + @RequestParam + String numericalAttributeId, + @Parameter( + description = + "Starting point of the violin plot axis, if different than smallest value") + @RequestParam(required = false) + BigDecimal axisStart, + @Parameter( + description = + "Ending point of the violin plot axis, if different than largest value") + @RequestParam(required = false) + BigDecimal axisEnd, + @Parameter(description = "Number of points in the curve") + @RequestParam(required = false, defaultValue = "100") + BigDecimal numCurvePoints, + @Parameter(description = "Use log scale for the numerical attribute") + @RequestParam(required = false, defaultValue = "false") + Boolean logScale, + @Parameter(description = "Sigma stepsize multiplier") + @RequestParam(required = false, defaultValue = "1") + BigDecimal sigmaMultiplier, + @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface + @RequestAttribute(required = false, value = "involvedCancerStudies") + Collection involvedCancerStudies, + @Parameter( + hidden = + true) // prevent reference to this attribute in the swagger-ui interface. this + // attribute is needed for the @PreAuthorize tag above. + @Valid + @RequestAttribute(required = false, value = "interceptedStudyViewFilter") + StudyViewFilter interceptedStudyViewFilter, + @Parameter(required = true, description = "Study view filter") + @Valid + @RequestBody(required = false) + StudyViewFilter studyViewFilter) { + + ClinicalViolinPlotData result = new ClinicalViolinPlotData(); + + List studyIds = new ArrayList<>(); + List sampleIds = new ArrayList<>(); + // first get samples that are filtered by all current filters - this will give us + // the by-row sample counts + studyViewFilterUtil.extractStudyAndSampleIds( + studyViewFilterApplier.apply(interceptedStudyViewFilter), studyIds, sampleIds); + List filteredSamples = + sampleService.fetchSamples(studyIds, sampleIds, Projection.DETAILED.name()); + + List studyIdsWithoutNumericalFilter = new ArrayList<>(); + List sampleIdsWithoutNumericalFilter = new ArrayList<>(); + // next, get samples that are filtered without the numerical filter - this will + // give us the violin plot data + if (interceptedStudyViewFilter.getClinicalDataFilters() != null) { + // Remove numerical clinical data filter, if there is one + interceptedStudyViewFilter.getClinicalDataFilters().stream() + .filter(f -> f.getAttributeId().equals(numericalAttributeId)) + .findAny() + .ifPresent(f -> interceptedStudyViewFilter.getClinicalDataFilters().remove(f)); + } + studyViewFilterUtil.extractStudyAndSampleIds( + studyViewFilterApplier.apply(interceptedStudyViewFilter), + studyIdsWithoutNumericalFilter, + sampleIdsWithoutNumericalFilter); + + if (sampleIds.isEmpty()) { + return new ResponseEntity<>(result, HttpStatus.OK); + } + + List sampleAttributeIds = new ArrayList<>(); + List patientAttributeIds = new ArrayList<>(); + + List clinicalAttributes = + clinicalAttributeService.getClinicalAttributesByStudyIdsAndAttributeIds( + studyIds, Arrays.asList(categoricalAttributeId, numericalAttributeId)); + + clinicalAttributeUtil.extractCategorizedClinicalAttributes( + clinicalAttributes, sampleAttributeIds, patientAttributeIds, patientAttributeIds); + + List patientIds = new ArrayList<>(); + List studyIdsOfPatients = new ArrayList<>(); + Map>> patientToSamples = null; + + if (CollectionUtils.isNotEmpty(patientAttributeIds)) { + List samplesWithoutNumericalFilter = + sampleService.fetchSamples( + studyIdsWithoutNumericalFilter, + sampleIdsWithoutNumericalFilter, + Projection.DETAILED.name()); + List patients = + patientService.getPatientsOfSamples( + studyIdsWithoutNumericalFilter, sampleIdsWithoutNumericalFilter); + patientIds = patients.stream().map(Patient::getStableId).toList(); + studyIdsOfPatients = patients.stream().map(Patient::getCancerStudyIdentifier).toList(); + patientToSamples = + samplesWithoutNumericalFilter.stream() + .collect( + Collectors.groupingBy( + Sample::getPatientStableId, + Collectors.groupingBy(Sample::getCancerStudyIdentifier))); + } + + List clinicalDataList = + clinicalDataFetcher.fetchClinicalData( + studyIdsWithoutNumericalFilter, + sampleIdsWithoutNumericalFilter, + patientIds, + studyIdsOfPatients, + sampleAttributeIds, + patientAttributeIds, + null); + + List sampleClinicalDataList; + // put all clinical data into sample form + if (CollectionUtils.isNotEmpty(patientAttributeIds)) { + sampleClinicalDataList = new ArrayList<>(); + for (ClinicalData d : clinicalDataList) { + if (d.getSampleId() == null) { + // null sample id means its a patient data, + // we need to distribute the value to samples + List samplesForPatient = + patientToSamples.get(d.getPatientId()).get(d.getStudyId()); + if (samplesForPatient != null) { + for (Sample s : samplesForPatient) { + ClinicalData newData = new ClinicalData(); + newData.setInternalId(s.getInternalId()); + newData.setAttrId(d.getAttrId()); + newData.setPatientId(d.getPatientId()); + newData.setStudyId(d.getStudyId()); + newData.setAttrValue(d.getAttrValue()); + newData.setSampleId(s.getStableId()); + sampleClinicalDataList.add(newData); + } + } else { + // patient has no samples - this shouldn't happen and could affect the integrity + // of the data analysis + return new ResponseEntity<>(null, HttpStatus.INTERNAL_SERVER_ERROR); + } + } else { + // if its a sample data, just add it to the list + sampleClinicalDataList.add(d); + } + } + } else { + sampleClinicalDataList = clinicalDataList; + } + + boolean useLogScale = + logScale && StudyViewController.isLogScalePossibleForAttribute(numericalAttributeId); + + Set sampleIdsSet = + filteredSamples.stream().map(s -> s.getInternalId()).collect(toSet()); + result = + violinPlotService.getClinicalViolinPlotData( + sampleClinicalDataList, + sampleIdsSet, + axisStart, + axisEnd, + numCurvePoints, + useLogScale, + sigmaMultiplier, + interceptedStudyViewFilter); + + return new ResponseEntity<>(result, HttpStatus.OK); + } + + @PreAuthorize( + "hasPermission(#involvedCancerStudies, 'Collection', T(org.cbioportal.legacy.utils.security.AccessLevel).READ)") + @RequestMapping( + value = "/sample-lists-counts/fetch", + method = RequestMethod.POST, + consumes = MediaType.APPLICATION_JSON_VALUE, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(description = "Fetch case list sample counts by study view filter") + public List fetchCaseListCounts( + @Parameter(required = true, description = "Study view filter") + @Valid + @RequestBody(required = false) + StudyViewFilter studyViewFilter, + @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface + @RequestAttribute(required = false, value = "involvedCancerStudies") + Collection involvedCancerStudies, + @Parameter( + hidden = + true) // prevent reference to this attribute in the swagger-ui interface. this + // attribute is needed for the @PreAuthorize tag above. + @Valid + @RequestAttribute(required = false, value = "interceptedStudyViewFilter") + StudyViewFilter interceptedStudyViewFilter) { + + List studyIds = new ArrayList<>(); + List sampleIds = new ArrayList<>(); + List filteredSampleIdentifiers = + studyViewFilterApplier.apply(interceptedStudyViewFilter); + studyViewFilterUtil.extractStudyAndSampleIds(filteredSampleIdentifiers, studyIds, sampleIds); + List sampleLists = + sampleListService.getAllSampleListsInStudies(studyIds, Projection.DETAILED.name()); + + HashMap sampleCountBySampleListId = new HashMap(); + + Map filteredSampleSet = + filteredSampleIdentifiers.stream() + .collect( + Collectors.toMap( + sampleidentifier -> + studyViewFilterUtil.getCaseUniqueKey( + sampleidentifier.getStudyId(), sampleidentifier.getSampleId()), + Function.identity())); + + for (SampleList sampleList : sampleLists) { + for (String sampleId : sampleList.getSampleIds()) { + if (filteredSampleSet.containsKey( + studyViewFilterUtil.getCaseUniqueKey( + sampleList.getCancerStudyIdentifier(), sampleId))) { + Integer count = sampleCountBySampleListId.getOrDefault(sampleList.getStableId(), 0); + sampleCountBySampleListId.put(sampleList.getStableId(), count + 1); + } + } + } + + return studyViewFilterUtil.categorizeSampleLists(sampleLists).entrySet().stream() + .map( + entry -> { + CaseListDataCount dataCount = new CaseListDataCount(); + dataCount.setValue(entry.getKey()); + + Integer count = + entry.getValue().stream() + .mapToInt( + sampleList -> { + return sampleCountBySampleListId.getOrDefault( + sampleList.getStableId(), 0); + }) + .sum(); + + dataCount.setCount(count); + dataCount.setLabel(entry.getValue().get(0).getName()); + + return dataCount; + }) + .filter(dataCount -> dataCount.getCount() > 0) + .toList(); + } + + @PreAuthorize( + "hasPermission(#involvedCancerStudies, 'Collection', T(org.cbioportal.legacy.utils.security.AccessLevel).READ)") + @RequestMapping( + value = "/genomic-data-bin-counts/fetch", + method = RequestMethod.POST, + consumes = MediaType.APPLICATION_JSON_VALUE, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(description = "Fetch genomic data bin counts by study view filter") + @ApiResponse( + responseCode = "200", + description = "OK", + content = + @Content(array = @ArraySchema(schema = @Schema(implementation = GenomicDataBin.class)))) + public ResponseEntity> fetchGenomicDataBinCounts( + @Parameter(description = "Method for data binning") @RequestParam(defaultValue = "DYNAMIC") + DataBinMethod dataBinMethod, + @Parameter(required = true, description = "Genomic data bin count filter") + @Valid + @RequestBody(required = false) + GenomicDataBinCountFilter genomicDataBinCountFilter, + @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface + @RequestAttribute(required = false, value = "involvedCancerStudies") + Collection involvedCancerStudies, + @Parameter( + hidden = + true) // prevent reference to this attribute in the swagger-ui interface. this + // attribute is needed for the @PreAuthorize tag above. + @Valid + @RequestAttribute(required = false, value = "interceptedGenomicDataBinCountFilter") + GenomicDataBinCountFilter interceptedGenomicDataBinCountFilter) { + + return new ResponseEntity<>( + studyViewFilterApplier.getDataBins(dataBinMethod, interceptedGenomicDataBinCountFilter), + HttpStatus.OK); + } + + @PreAuthorize( + "hasPermission(#involvedCancerStudies, 'Collection', T(org.cbioportal.legacy.utils.security.AccessLevel).READ)") + @RequestMapping( + value = "/genomic-data-counts/fetch", + method = RequestMethod.POST, + consumes = MediaType.APPLICATION_JSON_VALUE, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(description = "Fetch genomic data counts by GenomicDataCountFilter") + @ApiResponse( + responseCode = "200", + description = "OK", + content = + @Content( + array = @ArraySchema(schema = @Schema(implementation = GenomicDataCountItem.class)))) + public ResponseEntity> fetchGenomicDataCounts( + @Parameter(required = true, description = "Genomic data count filter") + @Valid + @RequestBody(required = false) + GenomicDataCountFilter genomicDataCountFilter, + @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface + @RequestAttribute(required = false, value = "involvedCancerStudies") + Collection involvedCancerStudies, + @Parameter(required = true, description = "Intercepted Genomic Data Count Filter") + @Valid + @RequestAttribute(required = false, value = "interceptedGenomicDataCountFilter") + GenomicDataCountFilter interceptedGenomicDataCountFilter) + throws StudyNotFoundException { + List genomicDataFilters = + interceptedGenomicDataCountFilter.getGenomicDataFilters(); + StudyViewFilter studyViewFilter = interceptedGenomicDataCountFilter.getStudyViewFilter(); + // when there is only one filter, it means study view is doing a single chart filter operation + // remove filter from studyViewFilter to return all data counts + // the reason we do this is to make sure after chart get filtered, user can still see unselected + // portion of the chart + if (genomicDataFilters.size() == 1) { + studyViewFilterUtil.removeSelfFromGenomicDataFilter( + genomicDataFilters.get(0).getHugoGeneSymbol(), + genomicDataFilters.get(0).getProfileType(), + studyViewFilter); + } + List filteredSampleIdentifiers = + studyViewFilterApplier.apply(studyViewFilter); + + if (filteredSampleIdentifiers.isEmpty()) { + return new ResponseEntity<>(new ArrayList<>(), HttpStatus.OK); + } + + List studyIds = new ArrayList<>(); + List sampleIds = new ArrayList<>(); + studyViewFilterUtil.extractStudyAndSampleIds(filteredSampleIdentifiers, studyIds, sampleIds); + + List result = + studyViewService.getCNAAlterationCountsByGeneSpecific( + studyIds, + sampleIds, + genomicDataFilters.stream() + .map( + genomicDataFilter -> + new Pair<>( + genomicDataFilter.getHugoGeneSymbol(), + genomicDataFilter.getProfileType())) + .collect(Collectors.toList())); + + return new ResponseEntity<>(result, HttpStatus.OK); + } + + @PreAuthorize( + "hasPermission(#involvedCancerStudies, 'Collection', T(org.cbioportal.legacy.utils.security.AccessLevel).READ)") + @RequestMapping( + value = "/generic-assay-data-counts/fetch", + method = RequestMethod.POST, + consumes = MediaType.APPLICATION_JSON_VALUE, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(description = "Fetch generic assay data counts by study view filter") + @ApiResponse( + responseCode = "200", + description = "OK", + content = + @Content( + array = + @ArraySchema(schema = @Schema(implementation = GenericAssayDataCountItem.class)))) + public ResponseEntity> fetchGenericAssayDataCounts( + @Parameter(required = true, description = "Generic assay data count filter") + @Valid + @RequestBody(required = false) + GenericAssayDataCountFilter genericAssayDataCountFilter, + @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface + @RequestAttribute(required = false, value = "involvedCancerStudies") + Collection involvedCancerStudies, + @Parameter( + hidden = + true) // prevent reference to this attribute in the swagger-ui interface. this + // attribute is needed for the @PreAuthorize tag above. + @Valid + @RequestAttribute(required = false, value = "interceptedGenericAssayDataCountFilter") + GenericAssayDataCountFilter interceptedGenericAssayDataCountFilter) { + + List gaFilters = + interceptedGenericAssayDataCountFilter.getGenericAssayDataFilters(); + StudyViewFilter studyViewFilter = interceptedGenericAssayDataCountFilter.getStudyViewFilter(); + // when there is only one filter, it means study view is doing a single chart filter operation + // remove filter from studyViewFilter to return all data counts + // the reason we do this is to make sure after chart get filtered, user can still see unselected + // portion of the chart + if (gaFilters.size() == 1) { + studyViewFilterUtil.removeSelfFromGenericAssayFilter( + gaFilters.get(0).getStableId(), studyViewFilter); + } + List filteredSampleIdentifiers = + studyViewFilterApplier.apply(studyViewFilter); + + if (filteredSampleIdentifiers.isEmpty()) { + return new ResponseEntity<>(new ArrayList<>(), HttpStatus.OK); + } + + List studyIds = new ArrayList<>(); + List sampleIds = new ArrayList<>(); + studyViewFilterUtil.extractStudyAndSampleIds(filteredSampleIdentifiers, studyIds, sampleIds); + + List result = + studyViewService.fetchGenericAssayDataCounts( + sampleIds, + studyIds, + gaFilters.stream().map(GenericAssayDataFilter::getStableId).toList(), + gaFilters.stream() + .map(GenericAssayDataFilter::getProfileType) + .collect(Collectors.toList())); + + return new ResponseEntity<>(result, HttpStatus.OK); + } + + @PreAuthorize( + "hasPermission(#involvedCancerStudies, 'Collection', T(org.cbioportal.legacy.utils.security.AccessLevel).READ)") + @RequestMapping( + value = "/generic-assay-data-bin-counts/fetch", + method = RequestMethod.POST, + consumes = MediaType.APPLICATION_JSON_VALUE, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(description = "Fetch generic assay data bin counts by study view filter") + @ApiResponse( + responseCode = "200", + description = "OK", + content = + @Content( + array = @ArraySchema(schema = @Schema(implementation = GenericAssayDataBin.class)))) + public ResponseEntity> fetchGenericAssayDataBinCounts( + @Parameter(description = "Method for data binning") @RequestParam(defaultValue = "DYNAMIC") + DataBinMethod dataBinMethod, + @Parameter(required = true, description = "Generic assay data bin count filter") + @Valid + @RequestBody(required = false) + GenericAssayDataBinCountFilter genericAssayDataBinCountFilter, + @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface + @RequestAttribute(required = false, value = "involvedCancerStudies") + Collection involvedCancerStudies, + @Parameter( + hidden = + true) // prevent reference to this attribute in the swagger-ui interface. this + // attribute is needed for the @PreAuthorize tag above. + @Valid + @RequestAttribute(required = false, value = "interceptedGenericAssayDataBinCountFilter") + GenericAssayDataBinCountFilter interceptedGenericAssayDataBinCountFilter) { + + return new ResponseEntity<>( + studyViewFilterApplier.getDataBins( + dataBinMethod, interceptedGenericAssayDataBinCountFilter), + HttpStatus.OK); + } + + @PreAuthorize( + "hasPermission(#involvedCancerStudies, 'Collection', T(org.cbioportal.legacy.utils.security.AccessLevel).READ)") + @RequestMapping( + value = "/clinical-data-table/fetch", + method = RequestMethod.POST, + consumes = MediaType.APPLICATION_JSON_VALUE, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(description = "Fetch clinical data for the Clinical Tab of Study View") + @ApiResponse( + responseCode = "200", + description = "OK", + content = @Content(schema = @Schema(implementation = SampleClinicalDataCollection.class))) + public ResponseEntity fetchClinicalDataClinicalTable( + @Parameter(required = true, description = "Study view filter") + @Valid + @RequestBody(required = false) + StudyViewFilter studyViewFilter, + @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface + @RequestAttribute(required = false, value = "involvedCancerStudies") + Collection involvedCancerStudies, + @Parameter( + hidden = + true) // prevent reference to this attribute in the swagger-ui interface. this + // attribute is needed for the @PreAuthorize tag above. + @Valid + @RequestAttribute(required = false, value = "interceptedStudyViewFilter") + StudyViewFilter interceptedStudyViewFilter, + @Parameter(description = "Page size of the result list") + @Max(CLINICAL_TAB_MAX_PAGE_SIZE) + @Min(PagingConstants.NO_PAGING_PAGE_SIZE) + @RequestParam(defaultValue = PagingConstants.DEFAULT_NO_PAGING_PAGE_SIZE) + Integer pageSize, + @Parameter(description = "Page number of the result list. Zero represents the first page.") + @Min(PagingConstants.MIN_PAGE_NUMBER) + @RequestParam(defaultValue = PagingConstants.DEFAULT_PAGE_NUMBER) + Integer pageNumber, + @Parameter( + description = + "Search term to filter sample rows. Samples are returned " + + "with a partial match to the search term for any sample clinical attribute.") + @RequestParam(defaultValue = "") + String searchTerm, + @Parameter(description = "sampleId, patientId, or the ATTR_ID to sorted by") + @RequestParam(required = false) + // TODO: Can we narrow down this string to a specific enum? + String sortBy, + @Parameter(description = "Direction of the sort") @RequestParam(defaultValue = "ASC") + Direction direction) { + + boolean unfilteredQuery = studyViewFilterUtil.isUnfilteredQuery(interceptedStudyViewFilter); + ImmutablePair sampleClinicalData = + cachedClinicalDataTableData( + interceptedStudyViewFilter, + unfilteredQuery, + pageNumber, + pageSize, + sortBy, + searchTerm, + direction.name()); + + // Because of pagination, the total number of sample matches can be larger than the items in the + // requested page. + SampleClinicalDataCollection aggregatedClinicalDataByUniqueSampleKey = + sampleClinicalData.getLeft(); + Integer totalNumberOfResults = sampleClinicalData.getRight(); + + HttpHeaders responseHeaders = new HttpHeaders(); + responseHeaders.add(HeaderKeyConstants.TOTAL_COUNT, String.valueOf(totalNumberOfResults)); + return new ResponseEntity<>( + aggregatedClinicalDataByUniqueSampleKey, responseHeaders, HttpStatus.OK); + } + + // Only cache when: + // 1) the request concerns the entire study + // 2) no sorting/searching + // 3) requesting the first page + @Cacheable( + cacheResolver = "staticRepositoryCacheOneResolver", + condition = + "@cacheEnabledConfig.getEnabled() && #unfilteredQuery && (#sortBy == null || #sortBy.isEmpty()) && (#searchTerm == null || #searchTerm.isEmpty()) && #pageNumber == 0") + public ImmutablePair cachedClinicalDataTableData( + StudyViewFilter interceptedStudyViewFilter, + boolean unfilteredQuery, + Integer pageNumber, + Integer pageSize, + String sortBy, + String searchTerm, + String sortDirection) { + + List sampleStudyIds = new ArrayList<>(); + List sampleIds = new ArrayList<>(); + List filteredSampleIdentifiers = + studyViewFilterApplier.apply(interceptedStudyViewFilter); + studyViewFilterUtil.extractStudyAndSampleIds( + filteredSampleIdentifiers, sampleStudyIds, sampleIds); + + return clinicalDataService.fetchSampleClinicalTable( + sampleStudyIds, sampleIds, pageSize, pageNumber, searchTerm, sortBy, sortDirection); + } + + @PreAuthorize( + "hasPermission(#involvedCancerStudies, 'Collection', T(org.cbioportal.legacy.utils.security.AccessLevel).READ)") + @RequestMapping( + value = "/clinical-event-type-counts/fetch", + method = RequestMethod.POST, + consumes = MediaType.APPLICATION_JSON_VALUE, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(description = "Get Counts of Clinical Event Types by Study View Filter") + @ApiResponse( + responseCode = "200", + description = "OK", + content = + @Content( + array = + @ArraySchema(schema = @Schema(implementation = ClinicalEventTypeCount.class)))) + public ResponseEntity> getClinicalEventTypeCounts( + @Parameter(required = true, description = "Study view filter") + @Valid + @RequestBody(required = false) + StudyViewFilter studyViewFilter, + @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface + @RequestAttribute(required = false, value = "involvedCancerStudies") + Collection involvedCancerStudies, + @Parameter( + hidden = + true) // prevent reference to this attribute in the swagger-ui interface. this + // attribute is needed for the @PreAuthorize tag above. + @Valid + @RequestAttribute(required = false, value = "interceptedStudyViewFilter") + StudyViewFilter interceptedStudyViewFilter) { + boolean unfilteredQuery = studyViewFilterUtil.isUnfilteredQuery(interceptedStudyViewFilter); + List eventTypeCounts = + this.getInstance() + .cachedClinicalEventTypeCounts(interceptedStudyViewFilter, unfilteredQuery); + return new ResponseEntity<>(eventTypeCounts, HttpStatus.OK); + } + + @Cacheable( + cacheResolver = "staticRepositoryCacheOneResolver", + condition = "@cacheEnabledConfig.getEnabled() && #unfilteredQuery") + public List cachedClinicalEventTypeCounts( + StudyViewFilter interceptedStudyViewFilter, boolean unfilteredQuery) { + List filteredSampleIdentifiers = + studyViewFilterApplier.apply(interceptedStudyViewFilter); + List sampleIds = new ArrayList<>(); + List studyIds = new ArrayList<>(); + studyViewFilterUtil.extractStudyAndSampleIds(filteredSampleIdentifiers, studyIds, sampleIds); + return clinicalEventService.getClinicalEventTypeCounts(studyIds, sampleIds); + } + + @PreAuthorize( + "hasPermission(#involvedCancerStudies, 'Collection', T(org.cbioportal.legacy.utils.security.AccessLevel).READ)") + @RequestMapping( + value = "/mutation-data-counts/fetch", + method = RequestMethod.POST, + consumes = MediaType.APPLICATION_JSON_VALUE, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(description = "Fetch mutation data counts by GenomicDataCountFilter") + @ApiResponse( + responseCode = "200", + description = "OK", + content = + @Content( + array = @ArraySchema(schema = @Schema(implementation = GenomicDataCountItem.class)))) + public ResponseEntity> fetchMutationDataCounts( + @Parameter(description = "Level of detail of the response") + @RequestParam(defaultValue = "SUMMARY") + Projection projection, + @Parameter(required = true, description = "Genomic data count filter") + @Valid + @RequestBody(required = false) + GenomicDataCountFilter genomicDataCountFilter, + @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface + @RequestAttribute(required = false, value = "involvedCancerStudies") + Collection involvedCancerStudies, + @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface + @Valid + @RequestAttribute(required = false, value = "interceptedGenomicDataCountFilter") + GenomicDataCountFilter interceptedGenomicDataCountFilter) { + List genomicDataFilters = + interceptedGenomicDataCountFilter.getGenomicDataFilters(); + StudyViewFilter studyViewFilter = interceptedGenomicDataCountFilter.getStudyViewFilter(); + // when there is only one filter, it means study view is doing a single chart filter operation + // remove filter from studyViewFilter to return all data counts + // the reason we do this is to make sure after chart get filtered, user can still see unselected + // portion of the chart + if (genomicDataFilters.size() == 1 && projection == Projection.SUMMARY) { + studyViewFilterUtil.removeSelfFromMutationDataFilter( + genomicDataFilters.get(0).getHugoGeneSymbol(), + genomicDataFilters.get(0).getProfileType(), + MutationOption.MUTATED, + studyViewFilter); + } + + List filteredSampleIdentifiers = + studyViewFilterApplier.apply(studyViewFilter); + + if (filteredSampleIdentifiers.isEmpty()) { + return new ResponseEntity<>(new ArrayList<>(), HttpStatus.OK); + } + + List studyIds = new ArrayList<>(); + List sampleIds = new ArrayList<>(); + studyViewFilterUtil.extractStudyAndSampleIds(filteredSampleIdentifiers, studyIds, sampleIds); + + List result; + + result = + projection == Projection.SUMMARY + ? studyViewService.getMutationCountsByGeneSpecific( + studyIds, + sampleIds, + genomicDataFilters.stream() + .map( + genomicDataFilter -> + new Pair<>( + genomicDataFilter.getHugoGeneSymbol(), + genomicDataFilter.getProfileType())) + .toList(), + studyViewFilter.getAlterationFilter()) + : studyViewService.getMutationTypeCountsByGeneSpecific( + studyIds, + sampleIds, + genomicDataFilters.stream() + .map( + genomicDataFilter -> + new Pair<>( + genomicDataFilter.getHugoGeneSymbol(), + genomicDataFilter.getProfileType())) + .toList()); + + return new ResponseEntity<>(result, HttpStatus.OK); + } + + @PreAuthorize( + "hasPermission(#involvedCancerStudies, 'Collection', T(org.cbioportal.utils.security.AccessLevel).READ)") + @PostMapping( + value = "/namespace-data-counts/fetch", + consumes = MediaType.APPLICATION_JSON_VALUE, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(description = "Fetch namespace data counts by study view filter") + @ApiResponse( + responseCode = "200", + description = "OK", + content = + @Content( + array = + @ArraySchema(schema = @Schema(implementation = NamespaceDataCountItem.class)))) + public ResponseEntity> fetchNamespaceDataCounts( + @Parameter(required = true, description = "Namespace data count filter") + @Valid + @RequestBody(required = false) + NamespaceDataCountFilter namespaceDataCountFilter, + @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface + @RequestAttribute(required = false, value = "involvedCancerStudies") + Collection involvedCancerStudies, + @Parameter(hidden = true) + @Valid + @RequestAttribute(required = false, value = "interceptedNamespaceDataCountFilter") + NamespaceDataCountFilter interceptedNamespaceDataCountFilter) { + + List namespaceDataFilters = + interceptedNamespaceDataCountFilter.getAttributes(); + StudyViewFilter studyViewFilter = interceptedNamespaceDataCountFilter.getStudyViewFilter(); + + List filteredSampleIdentifiers = + studyViewFilterApplier.apply(studyViewFilter); + + if (filteredSampleIdentifiers.isEmpty()) { + return new ResponseEntity<>(new ArrayList<>(), HttpStatus.OK); + } + + List studyIds = new ArrayList<>(); + List sampleIds = new ArrayList<>(); + studyViewFilterUtil.extractStudyAndSampleIds(filteredSampleIdentifiers, studyIds, sampleIds); + + List result = + studyViewService.fetchNamespaceDataCounts( + studyIds, + sampleIds, + namespaceDataFilters.stream() + .map( + namespaceDataFilter -> + new NamespaceAttribute( + namespaceDataFilter.getOuterKey(), namespaceDataFilter.getInnerKey())) + .toList()); + + return new ResponseEntity<>(result, HttpStatus.OK); + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/SurvivalController.java b/src/main/java/org/cbioportal/legacy/web/SurvivalController.java new file mode 100644 index 00000000000..81697fa87d9 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/SurvivalController.java @@ -0,0 +1,93 @@ +package org.cbioportal.legacy.web; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.ArraySchema; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import org.cbioportal.legacy.model.ClinicalData; +import org.cbioportal.legacy.service.ClinicalEventService; +import org.cbioportal.legacy.web.config.annotation.InternalApi; +import org.cbioportal.legacy.web.parameter.PatientIdentifier; +import org.cbioportal.legacy.web.parameter.SurvivalRequest; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.RequestAttribute; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RestController; + +@InternalApi +@RestController() +@RequestMapping("/api") +@Validated +@Tag(name = "Survival", description = " ") +public class SurvivalController { + private final ClinicalEventService clinicalEventService; + + @Autowired + public SurvivalController(ClinicalEventService clinicalEventService) { + this.clinicalEventService = clinicalEventService; + } + + @PreAuthorize( + "hasPermission(#involvedCancerStudies, 'Collection', T(org.cbioportal.legacy.utils.security.AccessLevel).READ)") + @RequestMapping( + value = "/survival-data/fetch", + method = RequestMethod.POST, + consumes = MediaType.APPLICATION_JSON_VALUE, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(description = "Fetch survival data") + @ApiResponse( + responseCode = "200", + description = "OK", + content = + @Content(array = @ArraySchema(schema = @Schema(implementation = ClinicalData.class)))) + public ResponseEntity> fetchSurvivalData( + @Parameter(required = true, description = "Survival Data Request") + @Valid + @RequestBody(required = false) + SurvivalRequest survivalRequest, + @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface + @RequestAttribute(required = false, value = "involvedCancerStudies") + Collection involvedCancerStudies, + @Parameter(hidden = true) + // prevent reference to this attribute in the swagger-ui interface. this attribute is + // needed for the @PreAuthorize tag above. + @Valid + @RequestAttribute(required = false, value = "interceptedSurvivalRequest") + SurvivalRequest interceptedSurvivalRequest) { + + return new ResponseEntity<>(cachedSurvivalData(interceptedSurvivalRequest), HttpStatus.OK); + } + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + public List cachedSurvivalData(SurvivalRequest interceptedSurvivalRequest) { + List studyIds = new ArrayList<>(); + List patientIds = new ArrayList<>(); + for (PatientIdentifier patientIdentifier : interceptedSurvivalRequest.getPatientIdentifiers()) { + studyIds.add(patientIdentifier.getStudyId()); + patientIds.add(patientIdentifier.getPatientId()); + } + + return clinicalEventService.getSurvivalData( + studyIds, + patientIds, + interceptedSurvivalRequest.getAttributeIdPrefix(), + interceptedSurvivalRequest); + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/TestController.java b/src/main/java/org/cbioportal/legacy/web/TestController.java new file mode 100644 index 00000000000..ef2c41fbcb5 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/TestController.java @@ -0,0 +1,13 @@ +package org.cbioportal.legacy.web; + +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +public class TestController { + + @GetMapping("/api/hello") + public String index() { + return "Greetings from Spring Boot!"; + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/TreatmentController.java b/src/main/java/org/cbioportal/legacy/web/TreatmentController.java new file mode 100644 index 00000000000..217bcb89ab4 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/TreatmentController.java @@ -0,0 +1,241 @@ +package org.cbioportal.legacy.web; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.ArraySchema; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import jakarta.validation.constraints.Size; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Objects; +import java.util.Set; +import org.cbioportal.legacy.model.ClinicalEventKeyCode; +import org.cbioportal.legacy.model.PatientTreatmentRow; +import org.cbioportal.legacy.model.SampleTreatmentRow; +import org.cbioportal.legacy.service.TreatmentService; +import org.cbioportal.legacy.web.config.annotation.InternalApi; +import org.cbioportal.legacy.web.parameter.PagingConstants; +import org.cbioportal.legacy.web.parameter.SampleIdentifier; +import org.cbioportal.legacy.web.parameter.StudyViewFilter; +import org.cbioportal.legacy.web.util.StudyViewFilterApplier; +import org.cbioportal.legacy.web.util.StudyViewFilterUtil; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.context.ApplicationContext; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.RequestAttribute; +import org.springframework.web.bind.annotation.RequestBody; +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.bind.annotation.RestController; + +@InternalApi +@RestController() +@RequestMapping("/api") +@Validated +@Tag(name = "Treatments", description = " ") +public class TreatmentController { + @Autowired private ApplicationContext applicationContext; + TreatmentController instance; + + @Autowired private StudyViewFilterUtil studyViewFilterUtil; + @Autowired private StudyViewFilterUtil filterUtil; + + @Autowired private TreatmentService treatmentService; + + @Autowired private StudyViewFilterApplier studyViewFilterApplier; + + private TreatmentController getInstance() { + if (Objects.isNull(instance)) { + instance = applicationContext.getBean(TreatmentController.class); + } + return instance; + } + + @PreAuthorize( + "hasPermission(#involvedCancerStudies, 'Collection', T(org.cbioportal.legacy.utils.security.AccessLevel).READ)") + @RequestMapping( + value = "/treatments/patient", + method = RequestMethod.POST, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(description = "Get all patient level treatments") + @ApiResponse( + responseCode = "200", + description = "OK", + content = + @Content( + array = @ArraySchema(schema = @Schema(implementation = PatientTreatmentRow.class)))) + public ResponseEntity> getAllPatientTreatments( + @Parameter(required = false) + @RequestParam(name = "tier", required = false, defaultValue = "Agent") + ClinicalEventKeyCode tier, + @Parameter(required = true, description = "Study view filter") + @Valid + @RequestBody(required = false) + StudyViewFilter studyViewFilter, + @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface + @RequestAttribute(required = false, value = "involvedCancerStudies") + Collection involvedCancerStudies, + @Parameter( + hidden = + true) // prevent reference to this attribute in the swagger-ui interface. this + // attribute is needed for the @PreAuthorize tag above. + @Valid + @RequestAttribute(required = false, value = "interceptedStudyViewFilter") + StudyViewFilter interceptedStudyViewFilter) { + boolean unfilteredQuery = studyViewFilterUtil.isUnfilteredQuery(interceptedStudyViewFilter); + List treatments = + this.getInstance() + .cachableGetAllPatientTreatments(tier, interceptedStudyViewFilter, unfilteredQuery); + return new ResponseEntity<>(treatments, HttpStatus.OK); + } + + @Cacheable( + cacheResolver = "staticRepositoryCacheOneResolver", + condition = "@cacheEnabledConfig.getEnabled() && #unfilteredQuery") + public List cachableGetAllPatientTreatments( + ClinicalEventKeyCode tier, + StudyViewFilter interceptedStudyViewFilter, + boolean unfilteredQuery) { + List sampleIdentifiers = + studyViewFilterApplier.apply(interceptedStudyViewFilter); + List sampleIds = new ArrayList<>(); + List studyIds = new ArrayList<>(); + filterUtil.extractStudyAndSampleIds(sampleIdentifiers, studyIds, sampleIds); + + return treatmentService.getAllPatientTreatmentRows(sampleIds, studyIds, tier); + } + + @PreAuthorize( + "hasPermission(#involvedCancerStudies, 'Collection', T(org.cbioportal.legacy.utils.security.AccessLevel).READ)") + @RequestMapping( + value = "/treatments/sample", + method = RequestMethod.POST, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(description = "Get all sample level treatments") + @ApiResponse( + responseCode = "200", + description = "OK", + content = + @Content( + array = @ArraySchema(schema = @Schema(implementation = SampleTreatmentRow.class)))) + public ResponseEntity> getAllSampleTreatments( + @Schema(defaultValue = "Agent") + @Parameter(required = false) + @RequestParam(name = "tier", required = false, defaultValue = "Agent") + ClinicalEventKeyCode tier, + @Parameter(required = true, description = "Study view filter") + @Valid + @RequestBody(required = false) + StudyViewFilter studyViewFilter, + @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface + @RequestAttribute(required = false, value = "involvedCancerStudies") + Collection involvedCancerStudies, + @Parameter( + hidden = + true) // prevent reference to this attribute in the swagger-ui interface. this + // attribute is needed for the @PreAuthorize tag above. + @Valid + @RequestAttribute(required = false, value = "interceptedStudyViewFilter") + StudyViewFilter interceptedStudyViewFilter) { + boolean unfilteredQuery = studyViewFilterUtil.isUnfilteredQuery(interceptedStudyViewFilter); + List treatments = + this.getInstance() + .cacheableGetAllSampleTreatments(tier, interceptedStudyViewFilter, unfilteredQuery); + return new ResponseEntity<>(treatments, HttpStatus.OK); + } + + @Cacheable( + cacheResolver = "staticRepositoryCacheOneResolver", + condition = "@cacheEnabledConfig.getEnabled() && #unfilteredQuery") + public List cacheableGetAllSampleTreatments( + ClinicalEventKeyCode tier, + StudyViewFilter interceptedStudyViewFilter, + boolean unfilteredQuery) { + List sampleIdentifiers = + studyViewFilterApplier.apply(interceptedStudyViewFilter); + List sampleIds = new ArrayList<>(); + List studyIds = new ArrayList<>(); + filterUtil.extractStudyAndSampleIds(sampleIdentifiers, studyIds, sampleIds); + + return treatmentService.getAllSampleTreatmentRows(sampleIds, studyIds, tier); + } + + @PreAuthorize( + "hasPermission(#studyIds, 'Collection', T(org.cbioportal.legacy.utils.security.AccessLevel).READ)") + @RequestMapping( + value = "/treatments/display-patient", + method = RequestMethod.POST, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(description = "Should patient level treatments be displayed") + @ApiResponse( + responseCode = "200", + description = "OK", + content = @Content(schema = @Schema(implementation = Boolean.class))) + public ResponseEntity getContainsTreatmentData( + @Schema(defaultValue = "Agent") + @Parameter(required = false) + @RequestParam(name = "tier", required = false, defaultValue = "Agent") + ClinicalEventKeyCode tier, + @Parameter(required = true, description = "List of Study IDs") + @Size(min = 1, max = PagingConstants.MAX_PAGE_SIZE) + @RequestBody + Set studyIds) { + Boolean containsTreatmentData = + this.getInstance().cacheableGetContainsTreatmentData(studyIds, tier); + return new ResponseEntity<>(containsTreatmentData, HttpStatus.OK); + } + + // Caching enabled for any number of studies as the requests contains only studyIds and the + // response is a boolean + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + public Boolean cacheableGetContainsTreatmentData( + Set studyIds, ClinicalEventKeyCode tier) { + return treatmentService.containsTreatmentData(new ArrayList<>(studyIds), tier); + } + + @PreAuthorize( + "hasPermission(#studyIds, 'Collection', T(org.cbioportal.legacy.utils.security.AccessLevel).READ)") + @RequestMapping( + value = "/treatments/display-sample", + method = RequestMethod.POST, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(description = "Should sample level treatments be displayed") + @ApiResponse( + responseCode = "200", + description = "OK", + content = @Content(schema = @Schema(implementation = Boolean.class))) + public ResponseEntity getContainsSampleTreatmentData( + @Schema(defaultValue = "Agent") + @Parameter(required = false) + @RequestParam(name = "tier", required = false, defaultValue = "Agent") + ClinicalEventKeyCode tier, + @Parameter(required = true, description = "List of Study IDs") + @Size(min = 1, max = PagingConstants.MAX_PAGE_SIZE) + @RequestBody + Set studyIds) { + Boolean containsTreatmentData = + this.getInstance().cacheableGetContainsSampleTreatmentData(studyIds, tier); + return new ResponseEntity<>(containsTreatmentData, HttpStatus.OK); + } + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + public Boolean cacheableGetContainsSampleTreatmentData( + Set studyIds, ClinicalEventKeyCode tier) { + return treatmentService.containsSampleTreatmentData(new ArrayList<>(studyIds), tier); + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/VariantCountController.java b/src/main/java/org/cbioportal/legacy/web/VariantCountController.java new file mode 100644 index 00000000000..5327ca979b9 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/VariantCountController.java @@ -0,0 +1,77 @@ +package org.cbioportal.legacy.web; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.ArraySchema; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.constraints.Size; +import java.util.ArrayList; +import java.util.List; +import org.cbioportal.legacy.model.VariantCount; +import org.cbioportal.legacy.service.VariantCountService; +import org.cbioportal.legacy.service.exception.MolecularProfileNotFoundException; +import org.cbioportal.legacy.web.config.annotation.InternalApi; +import org.cbioportal.legacy.web.parameter.VariantCountIdentifier; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RestController; + +@InternalApi +@RestController() +@RequestMapping("/api") +@Validated +@Tag(name = "Variant Counts", description = " ") +public class VariantCountController { + + private static final int VARIANT_COUNT_MAX_PAGE_SIZE = 50000; + + @Autowired private VariantCountService variantCountService; + + @PreAuthorize( + "hasPermission(#molecularProfileId, 'MolecularProfileId', T(org.cbioportal.legacy.utils.security.AccessLevel).READ)") + @RequestMapping( + value = "/molecular-profiles/{molecularProfileId}/variant-counts/fetch", + method = RequestMethod.POST, + consumes = MediaType.APPLICATION_JSON_VALUE, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(description = "Get counts of specific variants within a mutation molecular profile") + @ApiResponse( + responseCode = "200", + description = "OK", + content = + @Content(array = @ArraySchema(schema = @Schema(implementation = VariantCount.class)))) + public ResponseEntity> fetchVariantCounts( + @Parameter(required = true, description = "Molecular Profile ID e.g. acc_tcga_mutations") + @PathVariable + String molecularProfileId, + @Parameter(required = true, description = "List of variant count identifiers") + @Size(min = 1, max = VARIANT_COUNT_MAX_PAGE_SIZE) + @RequestBody + List variantCountIdentifiers) + throws MolecularProfileNotFoundException { + + List entrezGeneIds = new ArrayList<>(); + List keywords = new ArrayList<>(); + + for (VariantCountIdentifier variantCountIdentifier : variantCountIdentifiers) { + + entrezGeneIds.add(variantCountIdentifier.getEntrezGeneId()); + keywords.add(variantCountIdentifier.getKeyword()); + } + + return new ResponseEntity<>( + variantCountService.fetchVariantCounts(molecularProfileId, entrezGeneIds, keywords), + HttpStatus.OK); + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/columnar/BasicDataBinner.java b/src/main/java/org/cbioportal/legacy/web/columnar/BasicDataBinner.java new file mode 100644 index 00000000000..5ca88074bfe --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/columnar/BasicDataBinner.java @@ -0,0 +1,420 @@ +package org.cbioportal.legacy.web.columnar; + +import static java.util.Collections.emptyList; +import static java.util.stream.Collectors.toMap; + +import java.util.*; +import java.util.stream.Collectors; +import org.cbioportal.legacy.model.Binnable; +import org.cbioportal.legacy.model.ClinicalData; +import org.cbioportal.legacy.model.ClinicalDataBin; +import org.cbioportal.legacy.model.ClinicalDataCount; +import org.cbioportal.legacy.model.ClinicalDataCountItem; +import org.cbioportal.legacy.model.DataBin; +import org.cbioportal.legacy.model.GenericAssayDataBin; +import org.cbioportal.legacy.model.GenomicDataBin; +import org.cbioportal.legacy.service.CustomDataService; +import org.cbioportal.legacy.service.StudyViewColumnarService; +import org.cbioportal.legacy.service.util.CustomDataSession; +import org.cbioportal.legacy.utils.config.annotation.ConditionalOnProperty; +import org.cbioportal.legacy.web.columnar.util.CustomDataFilterUtil; +import org.cbioportal.legacy.web.columnar.util.NewClinicalDataBinUtil; +import org.cbioportal.legacy.web.parameter.ClinicalDataBinCountFilter; +import org.cbioportal.legacy.web.parameter.ClinicalDataBinFilter; +import org.cbioportal.legacy.web.parameter.ClinicalDataType; +import org.cbioportal.legacy.web.parameter.DataBinCountFilter; +import org.cbioportal.legacy.web.parameter.DataBinFilter; +import org.cbioportal.legacy.web.parameter.DataBinMethod; +import org.cbioportal.legacy.web.parameter.GenericAssayDataBinCountFilter; +import org.cbioportal.legacy.web.parameter.GenericAssayDataBinFilter; +import org.cbioportal.legacy.web.parameter.GenomicDataBinCountFilter; +import org.cbioportal.legacy.web.parameter.GenomicDataBinFilter; +import org.cbioportal.legacy.web.parameter.SampleIdentifier; +import org.cbioportal.legacy.web.parameter.StudyViewFilter; +import org.cbioportal.legacy.web.util.DataBinner; +import org.cbioportal.legacy.web.util.StudyViewFilterUtil; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Component; + +// BasicDataBinner is a generalized class derived from ClinicalDataBinner +// BasicDataBinner should eventually deprecate ClinicalDataBinner +// we are using BasicDataBinner for genomic data, generic assay, and custom data bin counts now +// but BasicDataBinner can support clinical data counts too +// after we switched clinical data counts to use this, then We can remove ClinicalDataBinner +@Component +@Deprecated(forRemoval = true) +@ConditionalOnProperty(name = "clickhouse_mode", havingValue = "test") +public class BasicDataBinner { + private final StudyViewColumnarService studyViewColumnarService; + private final DataBinner dataBinner; + private final CustomDataFilterUtil customDataFilterUtil; + private final CustomDataService customDataService; + private final StudyViewFilterUtil studyViewFilterUtil; + + @Autowired + public BasicDataBinner( + StudyViewColumnarService studyViewColumnarService, + DataBinner dataBinner, + CustomDataFilterUtil customDataFilterUtil, + CustomDataService customDataService, + StudyViewFilterUtil studyViewFilterUtil) { + this.studyViewColumnarService = studyViewColumnarService; + this.dataBinner = dataBinner; + this.customDataFilterUtil = customDataFilterUtil; + this.customDataService = customDataService; + this.studyViewFilterUtil = studyViewFilterUtil; + } + + // convert from counts to clinical data + private List convertCountsToData(List clinicalDataCounts) { + return clinicalDataCounts.stream() + .map(NewClinicalDataBinUtil::generateClinicalDataFromClinicalDataCount) + .flatMap(Collection::stream) + .toList(); + } + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + public + List getDataBins( + DataBinMethod dataBinMethod, T dataBinCountFilter, boolean shouldRemoveSelfFromFilter) { + // get data bin filters based on the type of the filter + // either Genomic data or Generic Assay data or custom data or clinical data + List dataBinFilters = fetchDataBinFilters(dataBinCountFilter); + StudyViewFilter studyViewFilter = dataBinCountFilter.getStudyViewFilter(); + // define result variables + List resultDataBins = Collections.emptyList(); + // if no data bin filters or no study view filer object is passed in + // return empty result + if (dataBinFilters.isEmpty() || studyViewFilter == null) { + return resultDataBins; + } + + if (shouldRemoveSelfFromFilter && dataBinFilters.size() == 1) { + removeSelfFromFilter(dataBinFilters.get(0), studyViewFilter); + } + + List uniqueKeys = dataBinFilters.stream().map(this::getDataBinFilterUniqueKey).toList(); + + // a new StudyView filter to partially filter by study and sample ids only + // we need this additional partial filter because we always need to know the bins generated for + // the initial state + // which allows us to keep the number of bins and bin ranges consistent even if there are + // additional data filters. + // we only want to update the counts for each bin, we don't want to regenerate the bins for the + // filtered data. + // NOTE: partial filter is only needed when dataBinMethod == DataBinMethod.STATIC but that's + // always the case + // for the frontend implementation. we can't really use dataBinMethod == DataBinMethod.DYNAMIC + // because of the + // complication it brings to the frontend visualization and filtering + StudyViewFilter partialFilter = new StudyViewFilter(); + partialFilter.setStudyIds(studyViewFilter.getStudyIds()); + partialFilter.setSampleIdentifiers(studyViewFilter.getSampleIdentifiers()); + + // we need to fetch data for the partial filter in order to generate the bins for initial state + // we use the filtered data to calculate the counts for each bin, we do not regenerate bins for + // the filtered data + List unfilteredClinicalDataCounts; + List filteredClinicalDataCounts; + Map attributeDatatypeMap; + switch (dataBinCountFilter) { + // TODO: first case is to support clinical data, but clinical data is not using this now. We + // should update controller to use this method later + case ClinicalDataBinCountFilter clinicalDataBinCountFilter + when !customDataService.getCustomDataSessions(uniqueKeys).isEmpty() -> { + Map customDataSessions = + customDataService.getCustomDataSessions(uniqueKeys); + List unfilteredSampleIdentifiers = + studyViewColumnarService.getFilteredSamples(partialFilter).stream() + .map( + sample -> + studyViewFilterUtil.buildSampleIdentifier( + sample.getCancerStudyIdentifier(), sample.getStableId())) + .toList(); + unfilteredClinicalDataCounts = + customDataFilterUtil.getCustomDataCounts( + unfilteredSampleIdentifiers, customDataSessions); + List filteredSampleIdentifiers = + studyViewColumnarService.getFilteredSamples(studyViewFilter).stream() + .map( + sample -> + studyViewFilterUtil.buildSampleIdentifier( + sample.getCancerStudyIdentifier(), sample.getStableId())) + .toList(); + filteredClinicalDataCounts = + customDataFilterUtil.getCustomDataCounts(filteredSampleIdentifiers, customDataSessions); + attributeDatatypeMap = + customDataSessions.entrySet().stream() + .collect(toMap(Map.Entry::getKey, NewClinicalDataBinUtil::getDataType)); + } + case ClinicalDataBinCountFilter clinicalDataBinCountFilter -> { + unfilteredClinicalDataCounts = + studyViewColumnarService.getClinicalDataCounts(partialFilter, uniqueKeys); + filteredClinicalDataCounts = + studyViewColumnarService.getClinicalDataCounts(studyViewFilter, uniqueKeys); + attributeDatatypeMap = + studyViewColumnarService.getClinicalAttributeDatatypeMap(studyViewFilter); + } + case GenomicDataBinCountFilter genomicDataBinCountFilter -> { + unfilteredClinicalDataCounts = + studyViewColumnarService.getGenomicDataBinCounts( + partialFilter, genomicDataBinCountFilter.getGenomicDataBinFilters()); + filteredClinicalDataCounts = + studyViewColumnarService.getGenomicDataBinCounts( + studyViewFilter, genomicDataBinCountFilter.getGenomicDataBinFilters()); + attributeDatatypeMap = Collections.emptyMap(); + } + case GenericAssayDataBinCountFilter genericAssayDataBinCountFilter -> { + unfilteredClinicalDataCounts = + studyViewColumnarService.getGenericAssayDataBinCounts( + partialFilter, genericAssayDataBinCountFilter.getGenericAssayDataBinFilters()); + filteredClinicalDataCounts = + studyViewColumnarService.getGenericAssayDataBinCounts( + studyViewFilter, genericAssayDataBinCountFilter.getGenericAssayDataBinFilters()); + attributeDatatypeMap = Collections.emptyMap(); + } + default -> { + unfilteredClinicalDataCounts = Collections.emptyList(); + filteredClinicalDataCounts = Collections.emptyList(); + attributeDatatypeMap = Collections.emptyMap(); + } + } + + // TODO ignoring conflictingPatientAttributeIds for now + List unfilteredClinicalData = + convertCountsToData( + unfilteredClinicalDataCounts.stream().flatMap(c -> c.getCounts().stream()).toList()); + List filteredClinicalData = + convertCountsToData( + filteredClinicalDataCounts.stream().flatMap(c -> c.getCounts().stream()).toList()); + + Map> unfilteredClinicalDataByAttributeId = + unfilteredClinicalData.stream().collect(Collectors.groupingBy(Binnable::getAttrId)); + + Map> filteredClinicalDataByAttributeId = + filteredClinicalData.stream().collect(Collectors.groupingBy(Binnable::getAttrId)); + + // TODO: need to update attributeDatatypeMap to include patient level data for Generic Assay + // Profiles + if (dataBinMethod == DataBinMethod.STATIC) { + if (!unfilteredClinicalData.isEmpty()) { + resultDataBins = + calculateStaticDataBins( + dataBinner, + dataBinFilters, + attributeDatatypeMap, + unfilteredClinicalDataByAttributeId, + filteredClinicalDataByAttributeId); + } + } + // TODO: need to update attributeDatatypeMap to include patient level data for Generic Assay + // Profiles + else { // dataBinMethod == DataBinMethod.DYNAMIC + // TODO we should consider removing dynamic binning support + // we never use dynamic binning in the frontend because number of bins and the bin ranges can + // change + // each time there is a new filter which makes the frontend implementation complicated + if (!filteredClinicalData.isEmpty()) { + resultDataBins = + calculateDynamicDataBins( + dataBinner, + dataBinFilters, + attributeDatatypeMap, + filteredClinicalDataByAttributeId); + } + } + + return resultDataBins; + } + + private void removeSelfFromFilter( + S dataBinFilter, StudyViewFilter studyViewFilter) { + switch (dataBinFilter) { + case ClinicalDataBinFilter clinicalDataBinFilter -> { + if (studyViewFilter.getClinicalDataFilters() != null) { + studyViewFilter + .getClinicalDataFilters() + .removeIf(f -> f.getAttributeId().equals(clinicalDataBinFilter.getAttributeId())); + } + if (studyViewFilter.getCustomDataFilters() != null) { + studyViewFilter + .getCustomDataFilters() + .removeIf(f -> f.getAttributeId().equals(clinicalDataBinFilter.getAttributeId())); + } + } + case GenomicDataBinFilter genomicDataBinFilter + when studyViewFilter.getGenomicDataFilters() != null -> + studyViewFilter + .getGenomicDataFilters() + .removeIf( + f -> + f.getHugoGeneSymbol().equals(genomicDataBinFilter.getHugoGeneSymbol()) + && f.getProfileType().equals(genomicDataBinFilter.getProfileType())); + case GenericAssayDataBinFilter genericAssayDataBinFilter + when studyViewFilter.getGenericAssayDataFilters() != null -> + studyViewFilter + .getGenericAssayDataFilters() + .removeIf( + f -> + f.getStableId().equals(genericAssayDataBinFilter.getStableId()) + && f.getProfileType().equals(genericAssayDataBinFilter.getProfileType())); + default -> { + // Do not remove any filters + } + } + } + + private List fetchDataBinFilters( + T dataBinCountFilter) { + switch (dataBinCountFilter) { + case ClinicalDataBinCountFilter clinicalDataBinCountFilter -> { + return (List) clinicalDataBinCountFilter.getAttributes(); + } + case GenomicDataBinCountFilter genomicDataBinCountFilter -> { + return (List) genomicDataBinCountFilter.getGenomicDataBinFilters(); + } + case GenericAssayDataBinCountFilter genericAssayDataBinCountFilter -> { + return (List) genericAssayDataBinCountFilter.getGenericAssayDataBinFilters(); + } + default -> { + return new ArrayList<>(); + } + } + } + + private String getDataBinFilterUniqueKey(S dataBinFilter) { + switch (dataBinFilter) { + case ClinicalDataBinFilter clinicalDataBinFilter -> { + return clinicalDataBinFilter.getAttributeId(); + } + case GenomicDataBinFilter genomicDataBinFilter -> { + return genomicDataBinFilter.getHugoGeneSymbol() + genomicDataBinFilter.getProfileType(); + } + case GenericAssayDataBinFilter genericAssayDataBinFilter -> { + return genericAssayDataBinFilter.getStableId() + genericAssayDataBinFilter.getProfileType(); + } + default -> { + return null; + } + } + } + + private List calculateStaticDataBins( + DataBinner dataBinner, + List dataBinFilters, + Map attributeDatatypeMap, + Map> unfilteredClinicalDataByAttributeId, + Map> filteredClinicalDataByAttributeId) { + List result = new ArrayList<>(); + + for (T dataBinFilter : dataBinFilters) { + // if there is data for requested attribute + if (attributeDatatypeMap.isEmpty() + || attributeDatatypeMap.containsKey(getDataBinFilterUniqueKey(dataBinFilter))) { + List dataBins = + dataBinner + .calculateClinicalDataBins( + dataBinFilter, + filteredClinicalDataByAttributeId.getOrDefault( + getDataBinFilterUniqueKey(dataBinFilter), emptyList()), + unfilteredClinicalDataByAttributeId.getOrDefault( + getDataBinFilterUniqueKey(dataBinFilter), emptyList())) + .stream() + .map(dataBin -> (U) transform(dataBinFilter, dataBin)) + .toList(); + + result.addAll(dataBins); + } + } + + return result; + } + + private List calculateDynamicDataBins( + DataBinner dataBinner, + List dataBinFilters, + Map attributeDatatypeMap, + Map> filteredClinicalDataByAttributeId) { + List result = new ArrayList<>(); + + for (T dataBinFilter : dataBinFilters) { + // if there is data for requested attribute + if (attributeDatatypeMap.isEmpty() + || attributeDatatypeMap.containsKey(getDataBinFilterUniqueKey(dataBinFilter))) { + List dataBins = + dataBinner + .calculateDataBins( + dataBinFilter, + filteredClinicalDataByAttributeId.getOrDefault( + getDataBinFilterUniqueKey(dataBinFilter), emptyList())) + .stream() + .map(dataBin -> (U) transform(dataBinFilter, dataBin)) + .toList(); + result.addAll(dataBins); + } + } + + return result; + } + + private T transform( + S dataBinFilter, DataBin dataBin) { + switch (dataBinFilter) { + case ClinicalDataBinFilter clinicalDataBinFilter -> { + return (T) dataBinToClinicalDataBin(clinicalDataBinFilter, dataBin); + } + case GenomicDataBinFilter genomicDataBinFilter -> { + return (T) dataBintoGenomicDataBin(genomicDataBinFilter, dataBin); + } + case GenericAssayDataBinFilter genericAssayDataBinFilter -> { + return (T) dataBintoGenericAssayDataBin(genericAssayDataBinFilter, dataBin); + } + default -> { + return null; + } + } + } + + private ClinicalDataBin dataBinToClinicalDataBin( + ClinicalDataBinFilter attribute, DataBin dataBin) { + ClinicalDataBin clinicalDataBin = new ClinicalDataBin(); + clinicalDataBin.setAttributeId(attribute.getAttributeId()); + setCommonDataBinProperties(dataBin, clinicalDataBin); + return clinicalDataBin; + } + + private GenomicDataBin dataBintoGenomicDataBin( + GenomicDataBinFilter genomicDataBinFilter, DataBin dataBin) { + GenomicDataBin genomicDataBin = new GenomicDataBin(); + genomicDataBin.setHugoGeneSymbol(genomicDataBinFilter.getHugoGeneSymbol()); + genomicDataBin.setProfileType(genomicDataBinFilter.getProfileType()); + setCommonDataBinProperties(dataBin, genomicDataBin); + return genomicDataBin; + } + + private GenericAssayDataBin dataBintoGenericAssayDataBin( + GenericAssayDataBinFilter genericAssayDataBinFilter, DataBin dataBin) { + GenericAssayDataBin genericAssayDataBin = new GenericAssayDataBin(); + genericAssayDataBin.setStableId(genericAssayDataBinFilter.getStableId()); + genericAssayDataBin.setProfileType(genericAssayDataBinFilter.getProfileType()); + setCommonDataBinProperties(dataBin, genericAssayDataBin); + return genericAssayDataBin; + } + + private void setCommonDataBinProperties( + DataBin originalDataBin, U targetDatabin) { + targetDatabin.setCount(originalDataBin.getCount()); + if (originalDataBin.getSpecialValue() != null) { + targetDatabin.setSpecialValue(originalDataBin.getSpecialValue()); + } + if (originalDataBin.getStart() != null) { + targetDatabin.setStart(originalDataBin.getStart()); + } + if (originalDataBin.getEnd() != null) { + targetDatabin.setEnd(originalDataBin.getEnd()); + } + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/columnar/ClinicalDataBinner.java b/src/main/java/org/cbioportal/legacy/web/columnar/ClinicalDataBinner.java new file mode 100644 index 00000000000..4de53ae1179 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/columnar/ClinicalDataBinner.java @@ -0,0 +1,129 @@ +package org.cbioportal.legacy.web.columnar; + +import java.util.*; +import java.util.stream.Collectors; +import org.cbioportal.legacy.model.Binnable; +import org.cbioportal.legacy.model.ClinicalData; +import org.cbioportal.legacy.model.ClinicalDataBin; +import org.cbioportal.legacy.model.ClinicalDataCount; +import org.cbioportal.legacy.model.ClinicalDataCountItem; +import org.cbioportal.legacy.service.StudyViewColumnarService; +import org.cbioportal.legacy.utils.config.annotation.ConditionalOnProperty; +import org.cbioportal.legacy.web.columnar.util.NewClinicalDataBinUtil; +import org.cbioportal.legacy.web.parameter.ClinicalDataBinCountFilter; +import org.cbioportal.legacy.web.parameter.ClinicalDataBinFilter; +import org.cbioportal.legacy.web.parameter.ClinicalDataType; +import org.cbioportal.legacy.web.parameter.DataBinMethod; +import org.cbioportal.legacy.web.parameter.StudyViewFilter; +import org.cbioportal.legacy.web.util.DataBinner; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Component; + +@Component +@Deprecated(forRemoval = true) +@ConditionalOnProperty(name = "clickhouse_mode", havingValue = "test") +public class ClinicalDataBinner { + private final StudyViewColumnarService studyViewColumnarService; + private final DataBinner dataBinner; + + @Autowired + public ClinicalDataBinner( + StudyViewColumnarService studyViewColumnarService, DataBinner dataBinner) { + this.studyViewColumnarService = studyViewColumnarService; + this.dataBinner = dataBinner; + } + + private List convertCountsToData(List clinicalDataCounts) { + return clinicalDataCounts.stream() + .map(NewClinicalDataBinUtil::generateClinicalDataFromClinicalDataCount) + .flatMap(Collection::stream) + .toList(); + } + + @Cacheable( + cacheResolver = "staticRepositoryCacheOneResolver", + condition = "@cacheEnabledConfig.getEnabled()") + public List fetchClinicalDataBinCounts( + DataBinMethod dataBinMethod, + ClinicalDataBinCountFilter dataBinCountFilter, + boolean shouldRemoveSelfFromFilter) { + List attributes = dataBinCountFilter.getAttributes(); + StudyViewFilter studyViewFilter = dataBinCountFilter.getStudyViewFilter(); + + if (shouldRemoveSelfFromFilter) { + studyViewFilter = NewClinicalDataBinUtil.removeSelfFromFilter(dataBinCountFilter); + } + + List attributeIds = + attributes.stream().map(ClinicalDataBinFilter::getAttributeId).collect(Collectors.toList()); + + // a new StudyView filter to partially filter by study and sample ids only + // we need this additional partial filter because we always need to know the bins generated for + // the initial state + // which allows us to keep the number of bins and bin ranges consistent even if there are + // additional data filters. + // we only want to update the counts for each bin, we don't want to regenerate the bins for the + // filtered data. + // NOTE: partial filter is only needed when dataBinMethod == DataBinMethod.STATIC but that's + // always the case + // for the frontend implementation. we can't really use dataBinMethod == DataBinMethod.DYNAMIC + // because of the + // complication it brings to the frontend visualization and filtering + StudyViewFilter partialFilter = new StudyViewFilter(); + partialFilter.setStudyIds(studyViewFilter.getStudyIds()); + partialFilter.setSampleIdentifiers(studyViewFilter.getSampleIdentifiers()); + + // we need the clinical data for the partial filter in order to generate the bins for initial + // state + // we use the filtered data to calculate the counts for each bin, we do not regenerate bins for + // the filtered data + List unfilteredClinicalDataCounts = + studyViewColumnarService.getClinicalDataCounts(partialFilter, attributeIds); + List filteredClinicalDataCounts = + studyViewColumnarService.getClinicalDataCounts(studyViewFilter, attributeIds); + + // TODO ignoring conflictingPatientAttributeIds for now + List unfilteredClinicalData = + convertCountsToData( + unfilteredClinicalDataCounts.stream().flatMap(c -> c.getCounts().stream()).toList()); + List filteredClinicalData = + convertCountsToData( + filteredClinicalDataCounts.stream().flatMap(c -> c.getCounts().stream()).toList()); + + Map attributeDatatypeMap = + studyViewColumnarService.getClinicalAttributeDatatypeMap(studyViewFilter); + + Map> unfilteredClinicalDataByAttributeId = + unfilteredClinicalData.stream().collect(Collectors.groupingBy(Binnable::getAttrId)); + + Map> filteredClinicalDataByAttributeId = + filteredClinicalData.stream().collect(Collectors.groupingBy(Binnable::getAttrId)); + + List clinicalDataBins = Collections.emptyList(); + + if (dataBinMethod == DataBinMethod.STATIC) { + if (!unfilteredClinicalData.isEmpty()) { + clinicalDataBins = + NewClinicalDataBinUtil.calculateStaticDataBins( + dataBinner, + attributes, + attributeDatatypeMap, + unfilteredClinicalDataByAttributeId, + filteredClinicalDataByAttributeId); + } + } else { // dataBinMethod == DataBinMethod.DYNAMIC + // TODO we should consider removing dynamic binning support + // we never use dynamic binning in the frontend because number of bins and the bin ranges can + // change + // each time there is a new filter which makes the frontend implementation complicated + if (!filteredClinicalData.isEmpty()) { + clinicalDataBins = + NewClinicalDataBinUtil.calculateDynamicDataBins( + dataBinner, attributes, attributeDatatypeMap, filteredClinicalDataByAttributeId); + } + } + + return clinicalDataBins; + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/columnar/util/ClinicalDataXyPlotUtil.java b/src/main/java/org/cbioportal/legacy/web/columnar/util/ClinicalDataXyPlotUtil.java new file mode 100644 index 00000000000..5501227b99b --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/columnar/util/ClinicalDataXyPlotUtil.java @@ -0,0 +1,80 @@ +package org.cbioportal.legacy.web.columnar.util; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import org.cbioportal.legacy.model.ClinicalData; +import org.cbioportal.legacy.model.Sample; + +@Deprecated(forRemoval = true) +public class ClinicalDataXyPlotUtil { + public static List combineClinicalDataForXyPlot( + List sampleClinicalDataList, + List patientClinicalDataList, + List samples, + boolean shouldFilterNonEmptyClinicalData) { + List combinedClinicalDataList; + + if (shouldFilterNonEmptyClinicalData) { + sampleClinicalDataList = filterNonEmptyClinicalData(sampleClinicalDataList); + patientClinicalDataList = filterNonEmptyClinicalData(patientClinicalDataList); + } + + if (patientClinicalDataList.isEmpty()) { + combinedClinicalDataList = sampleClinicalDataList; + } else { + combinedClinicalDataList = + Stream.concat( + sampleClinicalDataList.stream(), + convertPatientClinicalDataToSampleClinicalData(patientClinicalDataList, samples) + .stream()) + .toList(); + } + + return combinedClinicalDataList; + } + + public static List filterNonEmptyClinicalData(List clinicalData) { + return clinicalData.stream().filter(data -> !data.getAttrValue().isEmpty()).toList(); + } + + public static List convertPatientClinicalDataToSampleClinicalData( + List patientClinicalDataList, List samplesWithoutNumericalFilter) { + List sampleClinicalDataList = new ArrayList<>(); + + Map>> patientToSamples = + samplesWithoutNumericalFilter.stream() + .collect( + Collectors.groupingBy( + Sample::getPatientStableId, + Collectors.groupingBy(Sample::getCancerStudyIdentifier))); + + // put all clinical data into sample form + for (ClinicalData d : patientClinicalDataList) { + List samplesForPatient = patientToSamples.get(d.getPatientId()).get(d.getStudyId()); + if (samplesForPatient != null) { + for (Sample s : samplesForPatient) { + ClinicalData newData = new ClinicalData(); + + newData.setInternalId(s.getInternalId()); + newData.setAttrId(d.getAttrId()); + newData.setPatientId(d.getPatientId()); + newData.setStudyId(d.getStudyId()); + newData.setAttrValue(d.getAttrValue()); + newData.setSampleId(s.getStableId()); + + sampleClinicalDataList.add(newData); + } + } else { + // TODO ignoring for now rather than throwing an error + // patient has no samples - this shouldn't happen and could affect the integrity + // of the data analysis + // return new ResponseEntity<>(null, HttpStatus.INTERNAL_SERVER_ERROR); + } + } + + return sampleClinicalDataList; + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/columnar/util/CustomDataFilterUtil.java b/src/main/java/org/cbioportal/legacy/web/columnar/util/CustomDataFilterUtil.java new file mode 100644 index 00000000000..989f49f220b --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/columnar/util/CustomDataFilterUtil.java @@ -0,0 +1,440 @@ +package org.cbioportal.legacy.web.columnar.util; + +import com.google.common.collect.Range; +import java.math.BigDecimal; +import java.util.*; +import java.util.function.Function; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.collections4.map.MultiKeyMap; +import org.cbioportal.legacy.model.ClinicalDataCountItem; +import org.cbioportal.legacy.model.Patient; +import org.cbioportal.legacy.service.CustomDataService; +import org.cbioportal.legacy.service.PatientService; +import org.cbioportal.legacy.service.util.CustomDataSession; +import org.cbioportal.legacy.web.parameter.ClinicalDataFilter; +import org.cbioportal.legacy.web.parameter.CustomSampleIdentifier; +import org.cbioportal.legacy.web.parameter.DataFilterValue; +import org.cbioportal.legacy.web.parameter.SampleIdentifier; +import org.cbioportal.legacy.web.parameter.StudyViewFilter; +import org.cbioportal.legacy.web.util.CustomDatatype; +import org.cbioportal.legacy.web.util.DataBinHelper; +import org.cbioportal.legacy.web.util.StudyViewFilterUtil; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +@Deprecated(forRemoval = true) +@Component +public class CustomDataFilterUtil { + private final StudyViewFilterUtil studyViewFilterUtil; + private final CustomDataService customDataService; + private final PatientService patientService; + + @Autowired + public CustomDataFilterUtil( + StudyViewFilterUtil studyViewFilterUtil, + CustomDataService customDataService, + PatientService patientService) { + this.studyViewFilterUtil = studyViewFilterUtil; + this.customDataService = customDataService; + this.patientService = patientService; + } + + public List extractInvolvedCancerStudies(final StudyViewFilter studyViewFilter) { + List involvedCancerStudies; + + if (studyViewFilter.getStudyIds() != null && !studyViewFilter.getStudyIds().isEmpty()) { + involvedCancerStudies = studyViewFilter.getStudyIds(); + } else if (studyViewFilter.getSampleIdentifiers() != null + && !studyViewFilter.getSampleIdentifiers().isEmpty()) { + Set studyIdSet = new HashSet<>(); + for (SampleIdentifier sampleIdentifier : studyViewFilter.getSampleIdentifiers()) { + studyIdSet.add(sampleIdentifier.getStudyId()); + } + involvedCancerStudies = studyIdSet.stream().toList(); + } else { + involvedCancerStudies = Collections.emptyList(); + } + + return involvedCancerStudies; + } + + public List extractCustomDataSamples( + final StudyViewFilter studyViewFilter) { + if (studyViewFilter == null) { + return null; + } + + if (CollectionUtils.isEmpty(studyViewFilter.getCustomDataFilters())) { + return null; + } + + final List customSamplesFromProperty = + studyViewFilter.getCustomDataFilters().stream() + .flatMap( + filter -> { + List samples = filter.getSamples(); + return (samples != null) ? samples.stream() : Stream.empty(); + }) + .toList(); + + if (!customSamplesFromProperty.isEmpty()) { + return extractCustomDataSamplesWithoutSession(studyViewFilter, customSamplesFromProperty); + } else { + return extractCustomDataSamplesWithSession(studyViewFilter); + } + } + + private List extractCustomDataSamplesWithSession( + final StudyViewFilter studyViewFilter) { + List customSampleIdentifiers = new ArrayList<>(); + + final List attributeIds = + studyViewFilter.getCustomDataFilters().stream() + .map(ClinicalDataFilter::getAttributeId) + .collect(Collectors.toList()); + + final Map customDataSessions = + customDataService.getCustomDataSessions(attributeIds); + + Map customDataSessionById = + customDataSessions.values().stream() + .collect(Collectors.toMap(CustomDataSession::getId, Function.identity())); + + MultiKeyMap customDataByStudySampleSession = new MultiKeyMap<>(); + + customDataSessionById + .values() + .forEach( + customDataSession -> + customDataSession + .getData() + .getData() + .forEach( + datum -> { + String value = datum.getValue().toUpperCase(); + if (value.equals("NAN") || value.equals("N/A")) { + value = "NA"; + } + CustomSampleIdentifier customSampleIdentifier = + new CustomSampleIdentifier(); + customSampleIdentifier.setStudyId(datum.getStudyId()); + customSampleIdentifier.setSampleId(datum.getSampleId()); + customSampleIdentifiers.add(customSampleIdentifier); + customDataByStudySampleSession.put( + datum.getStudyId(), + datum.getSampleId(), + customDataSession.getId(), + value); + })); + + List equalityFilters = new ArrayList<>(); + List intervalFilters = new ArrayList<>(); + + studyViewFilter + .getCustomDataFilters() + .forEach( + filter -> { + String attributeId = filter.getAttributeId(); + if (!customDataSessionById.containsKey(attributeId)) { + return; + } + if (customDataSessionById + .get(attributeId) + .getData() + .getDatatype() + .equals(CustomDatatype.STRING.name())) { + equalityFilters.add(filter); + } else { + intervalFilters.add(filter); + } + }); + + List filtered = new ArrayList<>(); + customSampleIdentifiers.forEach( + customSampleIdentifier -> { + int equalityFilterCount = + studyViewFilterUtil.getFilteredCountByDataEquality( + equalityFilters, + customDataByStudySampleSession, + customSampleIdentifier.getSampleId(), + customSampleIdentifier.getStudyId(), + false); + int intervalFilterCount = + getFilteredCountByDataInterval( + intervalFilters, + customDataByStudySampleSession, + customSampleIdentifier.getSampleId(), + customSampleIdentifier.getStudyId()); + if (equalityFilterCount == equalityFilters.size() + && intervalFilterCount == intervalFilters.size()) { + filtered.add(customSampleIdentifier); + } else { + customSampleIdentifier.setIsFilteredOut(true); + filtered.add(customSampleIdentifier); + } + }); + + return filtered; + } + + private List extractCustomDataSamplesWithoutSession( + final StudyViewFilter studyViewFilter, + List customSamplesFromProperty) { + List customSampleIdentifiers = + new ArrayList<>(customSamplesFromProperty); + + List equalityFilters = new ArrayList<>(); + List intervalFilters = new ArrayList<>(); + + studyViewFilter + .getCustomDataFilters() + .forEach( + filter -> { + if (filter.getDatatype().equals(CustomDatatype.STRING.name())) { + equalityFilters.add(filter); + } else { + intervalFilters.add(filter); + } + }); + + MultiKeyMap customDataByStudySampleName = new MultiKeyMap<>(); + + studyViewFilter.getCustomDataFilters().stream() + .forEach( + filter -> + filter + .getSamples() + .forEach( + datum -> { + String value = datum.getValue().toUpperCase(); + if (value.equals("NAN") || value.equals("N/A")) { + value = "NA"; + } + customDataByStudySampleName.put( + datum.getStudyId(), + datum.getSampleId(), + filter.getDisplayName(), + value); + })); + + List filtered = new ArrayList<>(); + customSampleIdentifiers.forEach( + customSampleIdentifier -> { + int equalityFilterCount = + getFilteredCountByDataEqualityWithStudySampleNameMap( + equalityFilters, + customDataByStudySampleName, + customSampleIdentifier.getSampleId(), + customSampleIdentifier.getStudyId(), + false); + int intervalFilterCount = + getFilteredCountByDataIntervalWithStudySampleNameMap( + intervalFilters, + customDataByStudySampleName, + customSampleIdentifier.getSampleId(), + customSampleIdentifier.getStudyId()); + if (equalityFilterCount == equalityFilters.size() + && intervalFilterCount == intervalFilters.size()) { + filtered.add(customSampleIdentifier); + } else { + customSampleIdentifier.setIsFilteredOut(true); + filtered.add(customSampleIdentifier); + } + }); + return filtered; + } + + private Integer getFilteredCountByDataEqualityWithStudySampleNameMap( + List attributes, + MultiKeyMap clinicalDataMap, + String entityId, + String studyId, + boolean negateFilters) { + Integer count = 0; + for (ClinicalDataFilter s : attributes) { + List filteredValues = + s.getValues().stream().map(DataFilterValue::getValue).collect(Collectors.toList()); + filteredValues.replaceAll(String::toUpperCase); + if (clinicalDataMap.containsKey(studyId, entityId, s.getDisplayName())) { + String value = clinicalDataMap.get(studyId, entityId, s.getDisplayName()); + if (negateFilters ^ filteredValues.contains(value)) { + count++; + } + } else if (negateFilters ^ filteredValues.contains("NA")) { + count++; + } + } + return count; + } + + private Integer getFilteredCountByDataInterval( + List attributes, + MultiKeyMap clinicalDataMap, + String entityId, + String studyId) { + int count = 0; + + for (ClinicalDataFilter filter : attributes) { + if (clinicalDataMap.containsKey(studyId, entityId, filter.getAttributeId())) { + String attrValue = (String) clinicalDataMap.get(studyId, entityId, filter.getAttributeId()); + Range rangeValue = calculateRangeValueForAttr(attrValue); + + // find range filters + List> ranges = + filter.getValues().stream() + .map(this::calculateRangeValueForFilter) + .filter(Objects::nonNull) + .collect(Collectors.toList()); + + // find special value filters + List specialValues = + filter.getValues().stream() + .filter(f -> f.getValue() != null) + .map(f -> f.getValue().toUpperCase()) + .collect(Collectors.toList()); + + if (rangeValue != null) { + if (ranges.stream().anyMatch(r -> r.encloses(rangeValue))) { + count++; + } + } else if (specialValues.contains(attrValue.toUpperCase())) { + count++; + } + } else if (containsNA(filter)) { + count++; + } + } + + return count; + } + + private Integer getFilteredCountByDataIntervalWithStudySampleNameMap( + List attributes, + MultiKeyMap clinicalDataMap, + String entityId, + String studyId) { + int count = 0; + + for (ClinicalDataFilter filter : attributes) { + if (clinicalDataMap.containsKey(studyId, entityId, filter.getDisplayName())) { + String attrValue = clinicalDataMap.get(studyId, entityId, filter.getDisplayName()); + Range rangeValue = calculateRangeValueForAttr(attrValue); + + // find range filters + List> ranges = + filter.getValues().stream() + .map(this::calculateRangeValueForFilter) + .filter(Objects::nonNull) + .toList(); + + // find special value filters + List specialValues = + filter.getValues().stream() + .filter(f -> f.getValue() != null) + .map(f -> f.getValue().toUpperCase()) + .toList(); + + if ((rangeValue != null && ranges.stream().anyMatch(r -> r.encloses(rangeValue))) + || (rangeValue == null && specialValues.contains(attrValue.toUpperCase()))) { + count++; + } + } else if (Boolean.TRUE.equals(containsNA(filter))) { + count++; + } + } + + return count; + } + + private Range calculateRangeValueForAttr(String attrValue) { + if (attrValue == null) { + return null; + } + + BigDecimal min = null; + BigDecimal max = null; + + String value = attrValue.trim(); + + String lte = "<="; + String lt = "<"; + String gte = ">="; + String gt = ">"; + + boolean startInclusive = true; + boolean endInclusive = true; + + try { + if (value.startsWith(lte)) { + max = new BigDecimal(value.substring(lte.length())); + } else if (value.startsWith(lt)) { + max = new BigDecimal(value.substring(lt.length())); + endInclusive = false; + } else if (value.startsWith(gte)) { + min = new BigDecimal(value.substring(gte.length())); + } else if (value.startsWith(gt)) { + min = new BigDecimal(value.substring(gt.length())); + startInclusive = false; + } else { + min = max = new BigDecimal(attrValue); + } + } catch (Exception e) { + // invalid range -- TODO: also support ranges like 20-30? + return null; + } + + return DataBinHelper.calcRange(min, startInclusive, max, endInclusive); + } + + private Range calculateRangeValueForFilter(DataFilterValue filterValue) { + BigDecimal start = filterValue.getStart(); + BigDecimal end = filterValue.getEnd(); + + // default: (start, end] + boolean startInclusive = false; + boolean endInclusive = true; + + // special case: end == start (both inclusive) + if (end != null && end.equals(start)) { + startInclusive = true; + } + + return DataBinHelper.calcRange(start, startInclusive, end, endInclusive); + } + + private Boolean containsNA(ClinicalDataFilter filter) { + return filter.getValues().stream() + .anyMatch(r -> r.getValue() != null && r.getValue().toUpperCase().equals("NA")); + } + + public List getCustomDataCounts( + List filteredSampleIdentifiers, + Map customDataSessions) { + Map customSamplesMap = + filteredSampleIdentifiers.stream() + .collect( + Collectors.toMap( + sampleIdentifier -> + studyViewFilterUtil.getCaseUniqueKey( + sampleIdentifier.getStudyId(), sampleIdentifier.getSampleId()), + Function.identity())); + + List studyIds = new ArrayList<>(); + List sampleIds = new ArrayList<>(); + studyViewFilterUtil.extractStudyAndSampleIds(filteredSampleIdentifiers, studyIds, sampleIds); + + long patientCustomDataSessionsCount = + customDataSessions.values().stream() + .filter(customDataSession -> customDataSession.getData().getPatientAttribute()) + .count(); + List patients = new ArrayList<>(); + if (patientCustomDataSessionsCount > 0) { + patients.addAll(patientService.getPatientsOfSamples(studyIds, sampleIds)); + } + + return studyViewFilterUtil.getClinicalDataCountsFromCustomData( + customDataSessions.values(), customSamplesMap, patients); + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/columnar/util/NewClinicalDataBinUtil.java b/src/main/java/org/cbioportal/legacy/web/columnar/util/NewClinicalDataBinUtil.java new file mode 100644 index 00000000000..9b11b52358a --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/columnar/util/NewClinicalDataBinUtil.java @@ -0,0 +1,178 @@ +package org.cbioportal.legacy.web.columnar.util; + +import static java.util.Collections.emptyList; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import org.cbioportal.legacy.model.Binnable; +import org.cbioportal.legacy.model.ClinicalData; +import org.cbioportal.legacy.model.ClinicalDataBin; +import org.cbioportal.legacy.model.ClinicalDataCount; +import org.cbioportal.legacy.model.DataBin; +import org.cbioportal.legacy.service.util.CustomDataSession; +import org.cbioportal.legacy.web.parameter.ClinicalDataBinCountFilter; +import org.cbioportal.legacy.web.parameter.ClinicalDataBinFilter; +import org.cbioportal.legacy.web.parameter.ClinicalDataType; +import org.cbioportal.legacy.web.parameter.StudyViewFilter; +import org.cbioportal.legacy.web.util.DataBinner; + +@Deprecated(forRemoval = true) +public class NewClinicalDataBinUtil { + public static StudyViewFilter removeSelfFromFilter( + ClinicalDataBinCountFilter dataBinCountFilter) { + List attributes = dataBinCountFilter.getAttributes(); + StudyViewFilter studyViewFilter = dataBinCountFilter.getStudyViewFilter(); + + if (attributes.size() == 1) { + NewStudyViewFilterUtil.removeClinicalDataFilter( + attributes.getFirst().getAttributeId(), studyViewFilter.getClinicalDataFilters()); + } + + return studyViewFilter; + } + + public static StudyViewFilter removeSelfCustomDataFromFilter( + ClinicalDataBinCountFilter dataBinCountFilter) { + List attributes = dataBinCountFilter.getAttributes(); + StudyViewFilter studyViewFilter = dataBinCountFilter.getStudyViewFilter(); + + if (attributes.size() == 1) { + NewStudyViewFilterUtil.removeClinicalDataFilter( + attributes.getFirst().getAttributeId(), studyViewFilter.getCustomDataFilters()); + } + + return studyViewFilter; + } + + public static ClinicalDataBin dataBinToClinicalDataBin( + ClinicalDataBinFilter attribute, DataBin dataBin) { + ClinicalDataBin clinicalDataBin = new ClinicalDataBin(); + clinicalDataBin.setAttributeId(attribute.getAttributeId()); + clinicalDataBin.setCount(dataBin.getCount()); + if (dataBin.getEnd() != null) { + clinicalDataBin.setEnd(dataBin.getEnd()); + } + if (dataBin.getSpecialValue() != null) { + clinicalDataBin.setSpecialValue(dataBin.getSpecialValue()); + } + if (dataBin.getStart() != null) { + clinicalDataBin.setStart(dataBin.getStart()); + } + return clinicalDataBin; + } + + public static Map toAttributeDatatypeMap( + List sampleAttributeIds, + List patientAttributeIds, + List conflictingPatientAttributeIds) { + Map attributeDatatypeMap = new HashMap<>(); + + sampleAttributeIds.forEach( + attribute -> { + attributeDatatypeMap.put(attribute, ClinicalDataType.SAMPLE); + }); + patientAttributeIds.forEach( + attribute -> { + attributeDatatypeMap.put(attribute, ClinicalDataType.PATIENT); + }); + conflictingPatientAttributeIds.forEach( + attribute -> { + attributeDatatypeMap.put(attribute, ClinicalDataType.SAMPLE); + }); + + return attributeDatatypeMap; + } + + public static List calculateStaticDataBins( + DataBinner dataBinner, + List attributes, + Map attributeDatatypeMap, + Map> unfilteredClinicalDataByAttributeId, + Map> filteredClinicalDataByAttributeId) { + List clinicalDataBins = new ArrayList<>(); + + for (ClinicalDataBinFilter attribute : attributes) { + if (attributeDatatypeMap.containsKey(attribute.getAttributeId())) { + List dataBins = + dataBinner + .calculateClinicalDataBins( + attribute, + filteredClinicalDataByAttributeId.getOrDefault( + attribute.getAttributeId(), emptyList()), + unfilteredClinicalDataByAttributeId.getOrDefault( + attribute.getAttributeId(), emptyList())) + .stream() + .map(dataBin -> dataBinToClinicalDataBin(attribute, dataBin)) + .toList(); + + clinicalDataBins.addAll(dataBins); + } + } + + return clinicalDataBins; + } + + public static List calculateDynamicDataBins( + DataBinner dataBinner, + List attributes, + Map attributeDatatypeMap, + Map> filteredClinicalDataByAttributeId) { + List clinicalDataBins = new ArrayList<>(); + + for (ClinicalDataBinFilter attribute : attributes) { + + // if there is clinical data for requested attribute + if (attributeDatatypeMap.containsKey(attribute.getAttributeId())) { + List dataBins = + dataBinner + .calculateDataBins( + attribute, + filteredClinicalDataByAttributeId.getOrDefault( + attribute.getAttributeId(), emptyList())) + .stream() + .map(dataBin -> dataBinToClinicalDataBin(attribute, dataBin)) + .toList(); + clinicalDataBins.addAll(dataBins); + } + } + + return clinicalDataBins; + } + + /** + * Generate a list of ClinicalData from the given data count instance. Size of the generated list + * is equal to 'dataCount.count', and each ClinicalData in the list contains the same value + * 'dataCount.value' + * + *

This method improves the performance of the data binning because it allows us to fetch only + * the clinical data counts data which is a lot more compact and faster to generated than the + * actual clinical data. We only need the attribute id and the value of the clinical data to + * generate data bins. Constructing the clinical data in memory by using clinical data counts + * significantly improves the performance, and it also allows us to use the exact same SQL used by + * the clinical data counts endpoint. + * + * @param dataCount ClinicalDataCount instance containing the count and the value + * @return a list of ClinicalData with size 'dataCount.count' and value 'dataCount.value' + */ + public static List generateClinicalDataFromClinicalDataCount( + ClinicalDataCount dataCount) { + List data = new ArrayList<>(dataCount.getCount()); + + for (int i = 0; i < dataCount.getCount(); i++) { + ClinicalData d = new ClinicalData(); + d.setAttrId(dataCount.getAttributeId()); + d.setAttrValue(dataCount.getValue()); + data.add(d); + } + + return data; + } + + public static ClinicalDataType getDataType(Map.Entry entry) { + return Boolean.TRUE.equals(entry.getValue().getData().getPatientAttribute()) + ? ClinicalDataType.PATIENT + : ClinicalDataType.SAMPLE; + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/columnar/util/NewStudyViewFilterUtil.java b/src/main/java/org/cbioportal/legacy/web/columnar/util/NewStudyViewFilterUtil.java new file mode 100644 index 00000000000..b0bf24b9761 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/columnar/util/NewStudyViewFilterUtil.java @@ -0,0 +1,62 @@ +package org.cbioportal.legacy.web.columnar.util; + +import java.util.List; +import org.cbioportal.legacy.web.parameter.ClinicalDataFilter; +import org.cbioportal.legacy.web.parameter.MutationOption; +import org.cbioportal.legacy.web.parameter.SampleIdentifier; +import org.cbioportal.legacy.web.parameter.StudyViewFilter; + +@Deprecated(forRemoval = true) +public abstract class NewStudyViewFilterUtil { + + private NewStudyViewFilterUtil() {} + + public static void removeClinicalDataFilter( + String attributeId, List dataFilterList) { + if (dataFilterList != null) { + dataFilterList.removeIf(f -> f.getAttributeId().equals(attributeId)); + } + } + + public static void removeSelfFromGenomicDataFilter( + String hugoGeneSymbol, String profileType, StudyViewFilter studyViewFilter) { + if (studyViewFilter != null && studyViewFilter.getGenomicDataFilters() != null) { + studyViewFilter + .getGenomicDataFilters() + .removeIf( + f -> + f.getHugoGeneSymbol().equals(hugoGeneSymbol) + && f.getProfileType().equals(profileType)); + } + } + + public static void removeSelfFromGenericAssayFilter( + String stableId, StudyViewFilter studyViewFilter) { + if (studyViewFilter != null && studyViewFilter.getGenericAssayDataFilters() != null) { + studyViewFilter.getGenericAssayDataFilters().removeIf(f -> f.getStableId().equals(stableId)); + } + } + + public static void removeSelfFromMutationDataFilter( + String hugoGeneSymbol, + String profileType, + MutationOption categorization, + StudyViewFilter studyViewFilter) { + if (studyViewFilter != null && studyViewFilter.getMutationDataFilters() != null) { + studyViewFilter + .getMutationDataFilters() + .removeIf( + f -> + f.getHugoGeneSymbol().equals(hugoGeneSymbol) + && f.getProfileType().equals(profileType) + && f.getCategorization().equals(categorization)); + } + } + + public static SampleIdentifier buildSampleIdentifier(String studyId, String sampleId) { + SampleIdentifier sampleIdentifier = new SampleIdentifier(); + sampleIdentifier.setStudyId(studyId); + sampleIdentifier.setSampleId(sampleId); + return sampleIdentifier; + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/config/CustomObjectMapper.java b/src/main/java/org/cbioportal/legacy/web/config/CustomObjectMapper.java new file mode 100644 index 00000000000..88c3815cea0 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/config/CustomObjectMapper.java @@ -0,0 +1,157 @@ +/* + * Copyright (c) 2016 Memorial Sloan-Kettering Cancer Center. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS + * FOR A PARTICULAR PURPOSE. The software and documentation provided hereunder + * is on an "as is" basis, and Memorial Sloan-Kettering Cancer Center has no + * obligations to provide maintenance, support, updates, enhancements or + * modifications. In no event shall Memorial Sloan-Kettering Cancer Center be + * liable to any party for direct, indirect, special, incidental or + * consequential damages, including lost profits, arising out of the use of this + * software and its documentation, even if Memorial Sloan-Kettering Cancer + * Center has been advised of the possibility of such damage. + */ + +/* + * This file is part of cBioPortal. + * + * cBioPortal is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package org.cbioportal.legacy.web.config; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; +import java.util.HashMap; +import java.util.Map; +import org.cbioportal.legacy.model.CancerStudy; +import org.cbioportal.legacy.model.ClinicalAttribute; +import org.cbioportal.legacy.model.ClinicalAttributeCount; +import org.cbioportal.legacy.model.ClinicalData; +import org.cbioportal.legacy.model.ClinicalDataCount; +import org.cbioportal.legacy.model.ClinicalEvent; +import org.cbioportal.legacy.model.ClinicalEventData; +import org.cbioportal.legacy.model.CopyNumberSeg; +import org.cbioportal.legacy.model.DataAccessToken; +import org.cbioportal.legacy.model.DiscreteCopyNumberData; +import org.cbioportal.legacy.model.Gene; +import org.cbioportal.legacy.model.GenePanel; +import org.cbioportal.legacy.model.GenePanelToGene; +import org.cbioportal.legacy.model.Geneset; +import org.cbioportal.legacy.model.GenesetCorrelation; +import org.cbioportal.legacy.model.GenesetMolecularData; +import org.cbioportal.legacy.model.Gistic; +import org.cbioportal.legacy.model.GisticToGene; +import org.cbioportal.legacy.model.MolecularProfile; +import org.cbioportal.legacy.model.MutSig; +import org.cbioportal.legacy.model.Mutation; +import org.cbioportal.legacy.model.MutationSpectrum; +import org.cbioportal.legacy.model.NamespaceDataCount; +import org.cbioportal.legacy.model.Patient; +import org.cbioportal.legacy.model.ResourceDefinition; +import org.cbioportal.legacy.model.Sample; +import org.cbioportal.legacy.model.SampleList; +import org.cbioportal.legacy.model.StructuralVariant; +import org.cbioportal.legacy.model.TypeOfCancer; +import org.cbioportal.legacy.service.util.CustomAttributeWithData; +import org.cbioportal.legacy.service.util.CustomDataSession; +import org.cbioportal.legacy.utils.removeme.Session; +import org.cbioportal.legacy.web.mixin.CancerStudyMixin; +import org.cbioportal.legacy.web.mixin.ClinicalAttributeCountMixin; +import org.cbioportal.legacy.web.mixin.ClinicalAttributeMixin; +import org.cbioportal.legacy.web.mixin.ClinicalDataCountMixin; +import org.cbioportal.legacy.web.mixin.ClinicalDataMixin; +import org.cbioportal.legacy.web.mixin.ClinicalEventDataMixin; +import org.cbioportal.legacy.web.mixin.ClinicalEventMixin; +import org.cbioportal.legacy.web.mixin.CopyNumberSegMixin; +import org.cbioportal.legacy.web.mixin.DataAccessTokenMixin; +import org.cbioportal.legacy.web.mixin.DiscreteCopyNumberDataMixin; +import org.cbioportal.legacy.web.mixin.GeneMixin; +import org.cbioportal.legacy.web.mixin.GenePanelMixin; +import org.cbioportal.legacy.web.mixin.GenePanelToGeneMixin; +import org.cbioportal.legacy.web.mixin.GenesetCorrelationMixin; +import org.cbioportal.legacy.web.mixin.GenesetMixin; +import org.cbioportal.legacy.web.mixin.GenesetMolecularDataMixin; +import org.cbioportal.legacy.web.mixin.GisticMixin; +import org.cbioportal.legacy.web.mixin.GisticToGeneMixin; +import org.cbioportal.legacy.web.mixin.MolecularProfileMixin; +import org.cbioportal.legacy.web.mixin.MutSigMixin; +import org.cbioportal.legacy.web.mixin.MutationMixin; +import org.cbioportal.legacy.web.mixin.MutationSpectrumMixin; +import org.cbioportal.legacy.web.mixin.NamespaceDataCountMixin; +import org.cbioportal.legacy.web.mixin.PatientMixin; +import org.cbioportal.legacy.web.mixin.ResourceDefinitionMixin; +import org.cbioportal.legacy.web.mixin.SampleListMixin; +import org.cbioportal.legacy.web.mixin.SampleMixin; +import org.cbioportal.legacy.web.mixin.SessionDataMixin; +import org.cbioportal.legacy.web.mixin.SessionMixin; +import org.cbioportal.legacy.web.mixin.StructuralVariantMixin; +import org.cbioportal.legacy.web.mixin.TypeOfCancerMixin; +import org.cbioportal.legacy.web.parameter.PageSettings; +import org.cbioportal.legacy.web.parameter.PageSettingsData; +import org.cbioportal.legacy.web.parameter.StudyPageSettings; +import org.cbioportal.legacy.web.parameter.VirtualStudy; +import org.cbioportal.legacy.web.parameter.VirtualStudyData; + +// This bean automatically registers with MappingJackson2HttpMessageConverter +// By marking it @Primary it will displace the default ObjectMapper +// See: https://www.baeldung.com/spring-boot-customize-jackson-objectmapper#1-objectmapper +public class CustomObjectMapper extends ObjectMapper { + + public CustomObjectMapper() { + super.setSerializationInclusion(JsonInclude.Include.NON_NULL); + super.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING); + Map, Class> mixinMap = new HashMap<>(); + mixinMap.put(CancerStudy.class, CancerStudyMixin.class); + mixinMap.put(ClinicalAttribute.class, ClinicalAttributeMixin.class); + mixinMap.put(ClinicalAttributeCount.class, ClinicalAttributeCountMixin.class); + mixinMap.put(ClinicalData.class, ClinicalDataMixin.class); + mixinMap.put(ClinicalDataCount.class, ClinicalDataCountMixin.class); + mixinMap.put(ClinicalEvent.class, ClinicalEventMixin.class); + mixinMap.put(ClinicalEventData.class, ClinicalEventDataMixin.class); + mixinMap.put(CopyNumberSeg.class, CopyNumberSegMixin.class); + mixinMap.put(DataAccessToken.class, DataAccessTokenMixin.class); + mixinMap.put(DiscreteCopyNumberData.class, DiscreteCopyNumberDataMixin.class); + mixinMap.put(StructuralVariant.class, StructuralVariantMixin.class); + mixinMap.put(Gene.class, GeneMixin.class); + mixinMap.put(GenePanel.class, GenePanelMixin.class); + mixinMap.put(GenePanelToGene.class, GenePanelToGeneMixin.class); + mixinMap.put(Geneset.class, GenesetMixin.class); + mixinMap.put(GenesetMolecularData.class, GenesetMolecularDataMixin.class); + mixinMap.put(GenesetCorrelation.class, GenesetCorrelationMixin.class); + mixinMap.put(MolecularProfile.class, MolecularProfileMixin.class); + mixinMap.put(Gistic.class, GisticMixin.class); + mixinMap.put(GisticToGene.class, GisticToGeneMixin.class); + mixinMap.put(Mutation.class, MutationMixin.class); + mixinMap.put(MutationSpectrum.class, MutationSpectrumMixin.class); + mixinMap.put(MutSig.class, MutSigMixin.class); + mixinMap.put(NamespaceDataCount.class, NamespaceDataCountMixin.class); + mixinMap.put(PageSettings.class, SessionMixin.class); + mixinMap.put(PageSettingsData.class, SessionDataMixin.class); + mixinMap.put(Patient.class, PatientMixin.class); + mixinMap.put(Sample.class, SampleMixin.class); + mixinMap.put(SampleList.class, SampleListMixin.class); + mixinMap.put(Session.class, SessionMixin.class); + mixinMap.put(StudyPageSettings.class, SessionDataMixin.class); + mixinMap.put(TypeOfCancer.class, TypeOfCancerMixin.class); + mixinMap.put(ResourceDefinition.class, ResourceDefinitionMixin.class); + mixinMap.put(VirtualStudy.class, SessionMixin.class); + mixinMap.put(VirtualStudyData.class, SessionDataMixin.class); + mixinMap.put(CustomAttributeWithData.class, SessionDataMixin.class); + mixinMap.put(CustomDataSession.class, SessionMixin.class); + super.setMixIns(mixinMap); + } +} diff --git a/src/main/java/org/cbioportal/web/config/DataAccessTokenConfig.java b/src/main/java/org/cbioportal/legacy/web/config/DataAccessTokenConfig.java similarity index 100% rename from src/main/java/org/cbioportal/web/config/DataAccessTokenConfig.java rename to src/main/java/org/cbioportal/legacy/web/config/DataAccessTokenConfig.java diff --git a/src/main/java/org/cbioportal/legacy/web/config/InternalApiTags.java b/src/main/java/org/cbioportal/legacy/web/config/InternalApiTags.java new file mode 100644 index 00000000000..f7e64aebc79 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/config/InternalApiTags.java @@ -0,0 +1,15 @@ +package org.cbioportal.legacy.web.config; + +public class InternalApiTags { + public static final String CLINICAL_EVENTS = "Clinical Events"; + public static final String CLINICAL_ATTRIBUTES_COUNT = "Clinical Attributes Count"; + public static final String DISCRETE_COPY_NUMBER_ALTERATION_COUNTS = + "Discrete Copy Number Alteration Counts"; + public static final String MUTATIONS_COUNT = "Mutations Count"; + public static final String NAMESPACE_DATA = "Namespace Data"; + public static final String NAMESPACE_ATTRIBUTES_COUNT = "Namespace Attributes Count"; + public static final String REFERENCE_GENOME_GENES = "Reference Genome Genes"; + public static final String RESOURCE_DEFINITIONS = "Resource Definitions"; + public static final String RESOURCE_DATA = "Resource Data"; + public static final String STRUCTURAL_VARIANTS = "Structural Variants"; +} diff --git a/src/main/java/org/cbioportal/legacy/web/config/JacksonConfig.java b/src/main/java/org/cbioportal/legacy/web/config/JacksonConfig.java new file mode 100644 index 00000000000..7bbc00a749e --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/config/JacksonConfig.java @@ -0,0 +1,15 @@ +package org.cbioportal.legacy.web.config; + +import com.fasterxml.jackson.databind.ObjectMapper; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Primary; + +@Configuration +public class JacksonConfig { + @Bean + @Primary + public ObjectMapper objectMapper() { + return new CustomObjectMapper(); + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/config/MethodValidationConfig.java b/src/main/java/org/cbioportal/legacy/web/config/MethodValidationConfig.java new file mode 100644 index 00000000000..326b501eeab --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/config/MethodValidationConfig.java @@ -0,0 +1,22 @@ +package org.cbioportal.legacy.web.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean; +import org.springframework.validation.beanvalidation.MethodValidationPostProcessor; + +@Configuration +public class MethodValidationConfig { + + @Bean + public MethodValidationPostProcessor methodValidationPostProcessor() { + MethodValidationPostProcessor processor = new MethodValidationPostProcessor(); + processor.setValidator(validatorFactoryBean()); + return processor; + } + + @Bean + public LocalValidatorFactoryBean validatorFactoryBean() { + return new LocalValidatorFactoryBean(); + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/config/PublicApiTags.java b/src/main/java/org/cbioportal/legacy/web/config/PublicApiTags.java new file mode 100644 index 00000000000..f28356cc485 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/config/PublicApiTags.java @@ -0,0 +1,23 @@ +package org.cbioportal.legacy.web.config; + +public class PublicApiTags { + public static final String CANCER_TYPES = "Cancer Types"; + public static final String STUDIES = "Studies"; + public static final String PATIENTS = "Patients"; + public static final String SAMPLES = "Samples"; + public static final String SAMPLE_LISTS = "Sample Lists"; + public static final String CLINICAL_ATTRIBUTES = "Clinical Attributes"; + public static final String CLINICAL_DATA = "Clinical Data"; + public static final String MOLECULAR_DATA = "Molecular Data"; + public static final String MOLECULAR_PROFILES = "Molecular Profiles"; + public static final String MUTATIONS = "Mutations"; + public static final String NAMESPACE_ATTRIBUTES = "Namespace Attributes"; + public static final String DISCRETE_COPY_NUMBER_ALTERATIONS = "Discrete Copy Number Alterations"; + public static final String COPY_NUMBER_SEGMENTS = "Copy Number Segments"; + public static final String GENES = "Genes"; + public static final String GENE_PANELS = "Gene Panels"; + public static final String GENE_PANEL_DATA = "Gene Panel Data"; + public static final String GENERIC_ASSAYS = "Generic Assays"; + public static final String GENERIC_ASSAY_DATA = "Generic Assay Data"; + public static final String INFO = "Info"; +} diff --git a/src/main/java/org/cbioportal/legacy/web/config/SwaggerConfig.java b/src/main/java/org/cbioportal/legacy/web/config/SwaggerConfig.java new file mode 100644 index 00000000000..1ca44f963bc --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/config/SwaggerConfig.java @@ -0,0 +1,100 @@ +package org.cbioportal.legacy.web.config; + +import com.fasterxml.jackson.databind.ObjectMapper; +import io.swagger.v3.core.converter.ModelConverters; +import io.swagger.v3.core.jackson.ModelResolver; +import io.swagger.v3.oas.models.ExternalDocumentation; +import io.swagger.v3.oas.models.OpenAPI; +import io.swagger.v3.oas.models.info.Contact; +import io.swagger.v3.oas.models.info.Info; +import io.swagger.v3.oas.models.info.License; +import java.lang.annotation.Annotation; +import java.util.stream.Stream; +import org.cbioportal.legacy.web.config.annotation.InternalApi; +import org.cbioportal.legacy.web.config.annotation.PublicApi; +import org.springdoc.core.customizers.OperationCustomizer; +import org.springdoc.core.models.GroupedOpenApi; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.method.HandlerMethod; + +@Configuration +public class SwaggerConfig { + + @Bean + public GroupedOpenApi publicApi() { + return GroupedOpenApi.builder() + .group("public") + .addOpenApiMethodFilter( + method -> method.getDeclaringClass().isAnnotationPresent(PublicApi.class)) + .addOperationCustomizer(customizeOperation()) + .pathsToMatch("/api/**") + .build(); + } + + @Bean + public GroupedOpenApi internalApi() { + return GroupedOpenApi.builder() + .group("internal") + .addOpenApiMethodFilter( + method -> method.getDeclaringClass().isAnnotationPresent(InternalApi.class)) + .addOperationCustomizer(customizeOperation()) + .pathsToMatch("/api/**") + .build(); + } + + @Bean + public OpenAPI springShopOpenAPI(ObjectMapper customObjectMapper) { + ModelConverters.getInstance().addConverter(new ModelResolver(customObjectMapper)); + return new OpenAPI() + .info( + new Info() + .title("cBioPortal web Public API [Alpha]") + .description( + "A web service for supplying JSON formatted data to cBioPortal clients. " + + "Please note that this API is currently in beta and subject to change.") + .version( + "1.0 (beta). Backwards compatibility will be maintained (after 1.0 release)") + .license( + new License() + .name("License") + .url("https://github.com/cBioPortal/cbioportal/blob/master/LICENSE")) + .contact( + new Contact() + .name("cbioportal") + .url("https://www.cbioportal.org") + .email("cbioportal@googlegroups.com"))) + .externalDocs( + new ExternalDocumentation() + .description("SpringShop Wiki Documentation") + .url("https://springshop.wiki.github.org/docs")); + } + + @Bean + public OperationCustomizer customizeOperation() { + return (operation, handlerMethod) -> { + // TODO: Add HTTP Action to EndPoint should remove eventually + String httpMethod = extractHttpMethod(handlerMethod); + String originalOperationId = operation.getOperationId(); + String newOperationId = originalOperationId + "Using" + httpMethod; + + operation.setOperationId(newOperationId); + return operation; + }; + } + + private String extractHttpMethod(HandlerMethod handlerMethod) { + Annotation[] declaredAnnotations = handlerMethod.getMethod().getDeclaredAnnotations(); + for (var annotation : declaredAnnotations) { + if (annotation instanceof RequestMapping requestMapping) { + return Stream.of(requestMapping.method()) + .findFirst() + .map(RequestMethod::toString) + .orElse(""); + } + } + return ""; + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/config/WebServletContextListener.java b/src/main/java/org/cbioportal/legacy/web/config/WebServletContextListener.java new file mode 100644 index 00000000000..b2af75603b2 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/config/WebServletContextListener.java @@ -0,0 +1,98 @@ +package org.cbioportal.legacy.web.config; + +import jakarta.servlet.ServletContextEvent; +import jakarta.servlet.ServletContextListener; +import java.io.*; +import java.util.Properties; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.util.ObjectUtils; + +/** Created by Hongxin Zhang on 11/15/19. */ +public class WebServletContextListener implements ServletContextListener, InitializingBean { + private Boolean showOncokb; + + private String oncokbToken; + + private String oncokbURL; + + private Properties properties; + + private static final String DEFAULT_ONCOKB_URL = "https://public.api.oncokb.org/api/v1"; + + @Override + public void contextDestroyed(ServletContextEvent arg0) { + System.out.println("ServletContextListener destroyed"); + } + + // Run this before web application is started + @Override + public void contextInitialized(ServletContextEvent arg0) { + this.properties = loadProperties(getResourceStream("application.properties")); + + this.showOncokb = Boolean.parseBoolean(getProperty("show.oncokb", "true")); + this.oncokbToken = getProperty("oncokb.token", ""); + this.oncokbURL = getProperty("oncokb.public_api.url", ""); + + if (this.showOncokb) { + checkOncokbInfo(); + } + } + + @Override + public void afterPropertiesSet() throws Exception {} + + private void checkOncokbInfo() { + if (ObjectUtils.isEmpty(this.oncokbToken) + && (ObjectUtils.isEmpty(this.oncokbURL) + || this.oncokbURL.equalsIgnoreCase(DEFAULT_ONCOKB_URL))) { + System.out.println( + "----------------------------------------------------------------------------------------------------------------"); + // oncokb.org is deprecated, www.oncokb.org should be used + System.out.println( + "-- You are connecting to the OncoKB public instance which does not include any therapeutic information."); + System.out.println( + "-- Please consider obtaining a license to support future OncoKB development by following https://docs.cbioportal.org/2.4-integration-with-other-webservices/oncokb-data-access."); + System.out.println("-- Thank you."); + System.out.println( + "----------------------------------------------------------------------------------------------------------------"); + } + } + + private String getProperty(String key, String defaultValue) { + String propertyValue = this.properties.getProperty(key, defaultValue); + return System.getProperty(key, propertyValue); + } + + private InputStream getResourceStream(String propertiesFileName) { + String resourceFilename = null; + InputStream resourceFIS = null; + + try { + String home = System.getenv("PORTAL_HOME"); + if (home != null) { + resourceFilename = home + File.separator + propertiesFileName; + resourceFIS = new FileInputStream(resourceFilename); + } + } catch (FileNotFoundException e) { + } + + if (resourceFIS == null) { + resourceFIS = this.getClass().getClassLoader().getResourceAsStream(propertiesFileName); + } + + return resourceFIS; + } + + private Properties loadProperties(InputStream resourceInputStream) { + Properties properties = new Properties(); + + try { + properties.load(resourceInputStream); + resourceInputStream.close(); + } catch (IOException e) { + System.out.println("Error loading properties file: " + e.getMessage()); + } + + return properties; + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/config/annotation/InternalApi.java b/src/main/java/org/cbioportal/legacy/web/config/annotation/InternalApi.java new file mode 100644 index 00000000000..c7e2063fdc1 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/config/annotation/InternalApi.java @@ -0,0 +1,7 @@ +package org.cbioportal.legacy.web.config.annotation; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +@Retention(RetentionPolicy.RUNTIME) +public @interface InternalApi {} diff --git a/src/main/java/org/cbioportal/legacy/web/config/annotation/PublicApi.java b/src/main/java/org/cbioportal/legacy/web/config/annotation/PublicApi.java new file mode 100644 index 00000000000..96e6285459c --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/config/annotation/PublicApi.java @@ -0,0 +1,7 @@ +package org.cbioportal.legacy.web.config.annotation; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +@Retention(RetentionPolicy.RUNTIME) +public @interface PublicApi {} diff --git a/src/main/java/org/cbioportal/legacy/web/error/ErrorResponse.java b/src/main/java/org/cbioportal/legacy/web/error/ErrorResponse.java new file mode 100644 index 00000000000..1ab1b433373 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/error/ErrorResponse.java @@ -0,0 +1,18 @@ +package org.cbioportal.legacy.web.error; + +public class ErrorResponse { + + private String message; + + public ErrorResponse(String message) { + this.message = message; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/error/GlobalExceptionHandler.java b/src/main/java/org/cbioportal/legacy/web/error/GlobalExceptionHandler.java new file mode 100644 index 00000000000..68cd3f51b81 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/error/GlobalExceptionHandler.java @@ -0,0 +1,256 @@ +package org.cbioportal.legacy.web.error; + +import jakarta.validation.ConstraintViolation; +import jakarta.validation.ConstraintViolationException; +import jakarta.validation.ElementKind; +import jakarta.validation.Path; +import java.util.Iterator; +import java.util.NoSuchElementException; +import org.cbioportal.legacy.service.exception.AccessForbiddenException; +import org.cbioportal.legacy.service.exception.CacheNotFoundException; +import org.cbioportal.legacy.service.exception.CacheOperationException; +import org.cbioportal.legacy.service.exception.CancerTypeNotFoundException; +import org.cbioportal.legacy.service.exception.ClinicalAttributeNotFoundException; +import org.cbioportal.legacy.service.exception.DataAccessTokenNoUserIdentityException; +import org.cbioportal.legacy.service.exception.DataAccessTokenProhibitedUserException; +import org.cbioportal.legacy.service.exception.GeneNotFoundException; +import org.cbioportal.legacy.service.exception.GenePanelNotFoundException; +import org.cbioportal.legacy.service.exception.GeneWithMultipleEntrezIdsException; +import org.cbioportal.legacy.service.exception.GenericAssayNotFoundException; +import org.cbioportal.legacy.service.exception.GenesetNotFoundException; +import org.cbioportal.legacy.service.exception.MolecularProfileNotFoundException; +import org.cbioportal.legacy.service.exception.PatientNotFoundException; +import org.cbioportal.legacy.service.exception.ResourceDefinitionNotFoundException; +import org.cbioportal.legacy.service.exception.SampleListNotFoundException; +import org.cbioportal.legacy.service.exception.SampleNotFoundException; +import org.cbioportal.legacy.service.exception.StudyNotFoundException; +import org.cbioportal.legacy.service.exception.TokenNotFoundException; +import org.springframework.beans.TypeMismatchException; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.http.converter.HttpMessageNotReadableException; +import org.springframework.jdbc.BadSqlGrammarException; +import org.springframework.security.access.AccessDeniedException; +import org.springframework.validation.FieldError; +import org.springframework.web.bind.MethodArgumentNotValidException; +import org.springframework.web.bind.MissingServletRequestParameterException; +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.bind.annotation.ExceptionHandler; + +// TODO +// - consider extending extends ResponseEntityExceptionHandler +// - check controllers for not catching exceptions themselves +@ControllerAdvice("org.cbioportal.legacy.web") +public class GlobalExceptionHandler { + + @ExceptionHandler(UnsupportedOperationException.class) + public ResponseEntity handleUnsupportedOperation() { + return new ResponseEntity<>( + new ErrorResponse("Requested API is not implemented yet"), HttpStatus.NOT_IMPLEMENTED); + } + + @ExceptionHandler(StudyNotFoundException.class) + public ResponseEntity handleStudyNotFound(StudyNotFoundException ex) { + return new ResponseEntity<>( + new ErrorResponse("Study not found: " + ex.getStudyId()), HttpStatus.NOT_FOUND); + } + + @ExceptionHandler(PatientNotFoundException.class) + public ResponseEntity handlePatientNotFound(PatientNotFoundException ex) { + return new ResponseEntity<>( + new ErrorResponse( + "Patient not found in study " + ex.getStudyId() + ": " + ex.getPatientId()), + HttpStatus.NOT_FOUND); + } + + @ExceptionHandler(CancerTypeNotFoundException.class) + public ResponseEntity handleCancerTypeNotFound(CancerTypeNotFoundException ex) { + return new ResponseEntity<>( + new ErrorResponse("Cancer type not found: " + ex.getCancerTypeId()), HttpStatus.NOT_FOUND); + } + + @ExceptionHandler(MolecularProfileNotFoundException.class) + public ResponseEntity handleMolecularProfileNotFound( + MolecularProfileNotFoundException ex) { + return new ResponseEntity<>( + new ErrorResponse("Molecular profile not found: " + ex.getMolecularProfileId()), + HttpStatus.NOT_FOUND); + } + + @ExceptionHandler(SampleNotFoundException.class) + public ResponseEntity handleSampleNotFound(SampleNotFoundException ex) { + return new ResponseEntity<>( + new ErrorResponse("Sample not found in study " + ex.getStudyId() + ": " + ex.getSampleId()), + HttpStatus.NOT_FOUND); + } + + @ExceptionHandler(GeneNotFoundException.class) + public ResponseEntity handleGeneNotFound(GeneNotFoundException ex) { + return new ResponseEntity<>( + new ErrorResponse("Gene not found: " + ex.getGeneId()), HttpStatus.NOT_FOUND); + } + + @ExceptionHandler(GeneWithMultipleEntrezIdsException.class) + public ResponseEntity handleGeneWithMultipleEntrezIdsException( + GeneWithMultipleEntrezIdsException ex) { + return new ResponseEntity<>( + new ErrorResponse("Gene data error: multiple Entrez gene IDs for " + ex.getGeneId()), + HttpStatus.INTERNAL_SERVER_ERROR); + } + + @ExceptionHandler(GenesetNotFoundException.class) + public ResponseEntity handleGenesetNotFound(GenesetNotFoundException ex) { + return new ResponseEntity<>( + new ErrorResponse("Gene set not found: " + ex.getGenesetId()), HttpStatus.NOT_FOUND); + } + + @ExceptionHandler(SampleListNotFoundException.class) + public ResponseEntity handleSampleListNotFound(SampleListNotFoundException ex) { + return new ResponseEntity<>( + new ErrorResponse("Sample list not found: " + ex.getSampleListId()), HttpStatus.NOT_FOUND); + } + + @ExceptionHandler(ClinicalAttributeNotFoundException.class) + public ResponseEntity handleClinicalAttributeNotFound( + ClinicalAttributeNotFoundException ex) { + return new ResponseEntity<>( + new ErrorResponse( + "Clinical attribute not found in study " + + ex.getStudyId() + + ": " + + ex.getClinicalAttributeId()), + HttpStatus.NOT_FOUND); + } + + @ExceptionHandler(GenePanelNotFoundException.class) + public ResponseEntity handleGenePanelNotFound(GenePanelNotFoundException ex) { + return new ResponseEntity<>( + new ErrorResponse("Gene panel not found: " + ex.getGenePanelId()), HttpStatus.NOT_FOUND); + } + + @ExceptionHandler(MissingServletRequestParameterException.class) + public ResponseEntity handleMissingServletRequestParameter( + MissingServletRequestParameterException ex) { + return new ResponseEntity<>( + new ErrorResponse("Request parameter is missing: " + ex.getParameterName()), + HttpStatus.BAD_REQUEST); + } + + @ExceptionHandler(TypeMismatchException.class) + public ResponseEntity handleTypeMismatch(TypeMismatchException ex) { + return new ResponseEntity<>( + new ErrorResponse("Request parameter type mismatch: " + ex.getMostSpecificCause()), + HttpStatus.BAD_REQUEST); + } + + @ExceptionHandler(HttpMessageNotReadableException.class) + public ResponseEntity handleHttpMessageNotReadable( + HttpMessageNotReadableException ex) { + return new ResponseEntity<>( + new ErrorResponse("There is an error in the JSON format of the request payload"), + HttpStatus.BAD_REQUEST); + } + + @ExceptionHandler(ConstraintViolationException.class) + public ResponseEntity handleConstraintViolation(ConstraintViolationException ex) { + ConstraintViolation constraintViolation = ex.getConstraintViolations().iterator().next(); + Iterator iterator = constraintViolation.getPropertyPath().iterator(); + String parameterName = null; + + while (iterator.hasNext()) { + Path.Node node = iterator.next(); + if (node.getKind() == ElementKind.PARAMETER) { + parameterName = node.getName(); + break; + } + } + return new ResponseEntity<>( + new ErrorResponse(parameterName + " " + constraintViolation.getMessage()), + HttpStatus.BAD_REQUEST); + } + + @ExceptionHandler(MethodArgumentNotValidException.class) + public ResponseEntity handleMethodArgumentNotValid( + MethodArgumentNotValidException ex) { + + FieldError fieldError = ex.getBindingResult().getFieldError(); + return new ResponseEntity<>( + new ErrorResponse(fieldError.getField() + " " + fieldError.getDefaultMessage()), + HttpStatus.BAD_REQUEST); + } + + @ExceptionHandler(AccessDeniedException.class) + public ResponseEntity handleAccessDeniedException(AccessDeniedException ex) { + return new ResponseEntity<>( + new ErrorResponse("Access to the specified resource has been forbidden"), + HttpStatus.FORBIDDEN); + } + + @ExceptionHandler(DataAccessTokenNoUserIdentityException.class) + public ResponseEntity handleDataAccessTokenNoUserIdentityException() { + ErrorResponse response = + new ErrorResponse("No authenticated identity found while processing request"); + return new ResponseEntity<>(response, HttpStatus.UNAUTHORIZED); + } + + @ExceptionHandler(DataAccessTokenProhibitedUserException.class) + public ResponseEntity handleDataAccessTokenProhibitedUserException() { + ErrorResponse response = new ErrorResponse("You are prohibited from using Data Access Tokens"); + return new ResponseEntity<>(response, HttpStatus.UNAUTHORIZED); + } + + @ExceptionHandler(AccessForbiddenException.class) + public ResponseEntity handleAccessForbiddenException() { + ErrorResponse response = new ErrorResponse("The access is forbidden."); + return new ResponseEntity<>(response, HttpStatus.UNAUTHORIZED); + } + + @ExceptionHandler(TokenNotFoundException.class) + public ResponseEntity handleTokenNotFoundException() { + ErrorResponse response = new ErrorResponse("Specified token cannot be found"); + return new ResponseEntity<>(response, HttpStatus.NOT_FOUND); + } + + @ExceptionHandler(CacheNotFoundException.class) + public ResponseEntity handleCacheNotFoundException(CacheNotFoundException ex) { + return new ResponseEntity<>( + new ErrorResponse("No cache found with name " + ex.getCacheName()), HttpStatus.NOT_FOUND); + } + + @ExceptionHandler(CacheOperationException.class) + public ResponseEntity handleCacheOperationException(CacheNotFoundException ex) { + ErrorResponse response = + new ErrorResponse( + "Error evicting caches. Please try again or validate correct operation of your configured caching implementation."); + return new ResponseEntity<>(response, HttpStatus.INTERNAL_SERVER_ERROR); + } + + @ExceptionHandler(GenericAssayNotFoundException.class) + public ResponseEntity handleGenericAssayNotFound( + GenericAssayNotFoundException ex) { + + return new ResponseEntity<>( + new ErrorResponse("stableId not found: " + ex.getStableId()), HttpStatus.NOT_FOUND); + } + + @ExceptionHandler(ResourceDefinitionNotFoundException.class) + public ResponseEntity handleResourceDefinitionNotFound( + ResourceDefinitionNotFoundException ex) { + return new ResponseEntity<>( + new ErrorResponse("Resource not found: " + ex.getResourceId()), HttpStatus.NOT_FOUND); + } + + @ExceptionHandler(BadSqlGrammarException.class) + public ResponseEntity handleBadSqlGrammar(BadSqlGrammarException ex) { + ex.printStackTrace(); // we still want this to show up in the logs + return new ResponseEntity<>( + new ErrorResponse( + "SQL exception. If you are a maintainer of this instance, see logs for details."), + HttpStatus.INTERNAL_SERVER_ERROR); + } + + @ExceptionHandler(NoSuchElementException.class) + public ResponseEntity handleNoSuchElementException(NoSuchElementException ex) { + return new ResponseEntity<>(new ErrorResponse(ex.getMessage()), HttpStatus.NOT_FOUND); + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/interceptor/UniqueKeyInterceptor.java b/src/main/java/org/cbioportal/legacy/web/interceptor/UniqueKeyInterceptor.java new file mode 100644 index 00000000000..d8735d8b640 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/interceptor/UniqueKeyInterceptor.java @@ -0,0 +1,129 @@ +package org.cbioportal.legacy.web.interceptor; + +import static org.cbioportal.legacy.utils.Encoder.calculateBase64; + +import java.util.List; +import org.cbioportal.legacy.model.Alteration; +import org.cbioportal.legacy.model.ClinicalData; +import org.cbioportal.legacy.model.ClinicalEvent; +import org.cbioportal.legacy.model.CopyNumberSeg; +import org.cbioportal.legacy.model.GenePanelData; +import org.cbioportal.legacy.model.MolecularData; +import org.cbioportal.legacy.model.MrnaPercentile; +import org.cbioportal.legacy.model.MutationSpectrum; +import org.cbioportal.legacy.model.NumericGeneMolecularData; +import org.cbioportal.legacy.model.Patient; +import org.cbioportal.legacy.model.ResourceData; +import org.cbioportal.legacy.model.Sample; +import org.cbioportal.legacy.model.StructuralVariant; +import org.springframework.core.MethodParameter; +import org.springframework.http.MediaType; +import org.springframework.http.converter.json.MappingJacksonValue; +import org.springframework.http.server.ServerHttpRequest; +import org.springframework.http.server.ServerHttpResponse; +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.servlet.mvc.method.annotation.AbstractMappingJacksonResponseBodyAdvice; + +@ControllerAdvice("org.cbioportal.legacy.web") +public class UniqueKeyInterceptor extends AbstractMappingJacksonResponseBodyAdvice { + + @Override + protected void beforeBodyWriteInternal( + MappingJacksonValue mappingJacksonValue, + MediaType mediaType, + MethodParameter methodParameter, + ServerHttpRequest serverHttpRequest, + ServerHttpResponse serverHttpResponse) { + Object value = mappingJacksonValue.getValue(); + if (value instanceof List) { + List list = (List) value; + for (Object object : list) { + if (object instanceof Alteration) { + Alteration alteration = (Alteration) object; + alteration.setUniqueSampleKey( + calculateBase64(alteration.getSampleId(), alteration.getStudyId())); + alteration.setUniquePatientKey( + calculateBase64(alteration.getPatientId(), alteration.getStudyId())); + } else if (object instanceof ClinicalData) { + ClinicalData clinicalData = (ClinicalData) object; + if (clinicalData.getSampleId() != null) { + clinicalData.setUniqueSampleKey( + calculateBase64(clinicalData.getSampleId(), clinicalData.getStudyId())); + } + clinicalData.setUniquePatientKey( + calculateBase64(clinicalData.getPatientId(), clinicalData.getStudyId())); + } else if (object instanceof ClinicalEvent) { + ClinicalEvent clinicalEvent = (ClinicalEvent) object; + clinicalEvent.setUniquePatientKey( + calculateBase64(clinicalEvent.getPatientId(), clinicalEvent.getStudyId())); + } else if (object instanceof CopyNumberSeg) { + CopyNumberSeg copyNumberSeg = (CopyNumberSeg) object; + copyNumberSeg.setUniqueSampleKey( + calculateBase64( + copyNumberSeg.getSampleStableId(), copyNumberSeg.getCancerStudyIdentifier())); + copyNumberSeg.setUniquePatientKey( + calculateBase64( + copyNumberSeg.getPatientId(), copyNumberSeg.getCancerStudyIdentifier())); + } else if (object instanceof GenePanelData) { + GenePanelData genePanelData = (GenePanelData) object; + genePanelData.setUniqueSampleKey( + calculateBase64(genePanelData.getSampleId(), genePanelData.getStudyId())); + genePanelData.setUniquePatientKey( + calculateBase64(genePanelData.getPatientId(), genePanelData.getStudyId())); + } else if (object instanceof MolecularData) { + MolecularData molecularData = (MolecularData) object; + molecularData.setUniqueSampleKey( + calculateBase64(molecularData.getSampleId(), molecularData.getStudyId())); + molecularData.setUniquePatientKey( + calculateBase64(molecularData.getPatientId(), molecularData.getStudyId())); + } else if (object instanceof MrnaPercentile) { + MrnaPercentile mrnaPercentile = (MrnaPercentile) object; + mrnaPercentile.setUniqueSampleKey( + calculateBase64(mrnaPercentile.getSampleId(), mrnaPercentile.getStudyId())); + mrnaPercentile.setUniquePatientKey( + calculateBase64(mrnaPercentile.getPatientId(), mrnaPercentile.getStudyId())); + } else if (object instanceof MutationSpectrum) { + MutationSpectrum mutationSpectrum = (MutationSpectrum) object; + mutationSpectrum.setUniqueSampleKey( + calculateBase64(mutationSpectrum.getSampleId(), mutationSpectrum.getStudyId())); + mutationSpectrum.setUniquePatientKey( + calculateBase64(mutationSpectrum.getPatientId(), mutationSpectrum.getStudyId())); + } else if (object instanceof NumericGeneMolecularData) { + NumericGeneMolecularData numericGeneMolecularData = (NumericGeneMolecularData) object; + numericGeneMolecularData.setUniqueSampleKey( + calculateBase64( + numericGeneMolecularData.getSampleId(), numericGeneMolecularData.getStudyId())); + numericGeneMolecularData.setUniquePatientKey( + calculateBase64( + numericGeneMolecularData.getPatientId(), numericGeneMolecularData.getStudyId())); + } else if (object instanceof Patient) { + Patient patient = (Patient) object; + patient.setUniquePatientKey( + calculateBase64(patient.getStableId(), patient.getCancerStudyIdentifier())); + } else if (object instanceof Sample) { + Sample sample = (Sample) object; + sample.setUniqueSampleKey( + calculateBase64(sample.getStableId(), sample.getCancerStudyIdentifier())); + sample.setUniquePatientKey( + calculateBase64(sample.getPatientStableId(), sample.getCancerStudyIdentifier())); + } else if (object instanceof StructuralVariant) { + StructuralVariant structuralVariant = (StructuralVariant) object; + structuralVariant.setUniqueSampleKey( + calculateBase64(structuralVariant.getSampleId(), structuralVariant.getStudyId())); + structuralVariant.setUniquePatientKey( + calculateBase64(structuralVariant.getPatientId(), structuralVariant.getStudyId())); + } else if (object instanceof ResourceData) { + ResourceData resourceData = (ResourceData) object; + if (resourceData.getSampleId() != null) { + resourceData.setUniqueSampleKey( + calculateBase64(resourceData.getSampleId(), resourceData.getStudyId())); + } + if (resourceData.getPatientId() != null) { + resourceData.setUniquePatientKey( + calculateBase64(resourceData.getPatientId(), resourceData.getStudyId())); + } + } + } + } + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/mixin/CancerStudyMixin.java b/src/main/java/org/cbioportal/legacy/web/mixin/CancerStudyMixin.java new file mode 100644 index 00000000000..bbce069479d --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/mixin/CancerStudyMixin.java @@ -0,0 +1,27 @@ +package org.cbioportal.legacy.web.mixin; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.Date; +import org.cbioportal.legacy.model.TypeOfCancer; + +public class CancerStudyMixin { + + @JsonIgnore private Integer cancerStudyId; + + @JsonProperty("studyId") + private String cancerStudyIdentifier; + + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss") + private Date importDate; + + @JsonProperty("cancerTypeId") + private String typeOfCancerId; + + @JsonProperty("cancerType") + private TypeOfCancer typeOfCancer; + + @JsonProperty("referenceGenome") + private String referenceGenome; +} diff --git a/src/main/java/org/cbioportal/legacy/web/mixin/ClinicalAttributeCountMixin.java b/src/main/java/org/cbioportal/legacy/web/mixin/ClinicalAttributeCountMixin.java new file mode 100644 index 00000000000..f9ad22c8343 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/mixin/ClinicalAttributeCountMixin.java @@ -0,0 +1,9 @@ +package org.cbioportal.legacy.web.mixin; + +import com.fasterxml.jackson.annotation.JsonProperty; + +public class ClinicalAttributeCountMixin { + + @JsonProperty("clinicalAttributeId") + private String attrId; +} diff --git a/src/main/java/org/cbioportal/legacy/web/mixin/ClinicalAttributeMixin.java b/src/main/java/org/cbioportal/legacy/web/mixin/ClinicalAttributeMixin.java new file mode 100644 index 00000000000..1c68f181058 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/mixin/ClinicalAttributeMixin.java @@ -0,0 +1,15 @@ +package org.cbioportal.legacy.web.mixin; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; + +public class ClinicalAttributeMixin { + + @JsonProperty("clinicalAttributeId") + private String attrId; + + @JsonIgnore private Integer cancerStudyId; + + @JsonProperty("studyId") + private String cancerStudyIdentifier; +} diff --git a/src/main/java/org/cbioportal/legacy/web/mixin/ClinicalDataCountMixin.java b/src/main/java/org/cbioportal/legacy/web/mixin/ClinicalDataCountMixin.java new file mode 100644 index 00000000000..8dc1dce9d86 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/mixin/ClinicalDataCountMixin.java @@ -0,0 +1,8 @@ +package org.cbioportal.legacy.web.mixin; + +import com.fasterxml.jackson.annotation.JsonIgnore; + +public class ClinicalDataCountMixin { + + @JsonIgnore private String attributeId; +} diff --git a/src/main/java/org/cbioportal/legacy/web/mixin/ClinicalDataMixin.java b/src/main/java/org/cbioportal/legacy/web/mixin/ClinicalDataMixin.java new file mode 100644 index 00000000000..23c0c62dde7 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/mixin/ClinicalDataMixin.java @@ -0,0 +1,15 @@ +package org.cbioportal.legacy.web.mixin; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; + +public class ClinicalDataMixin { + + @JsonIgnore private Integer internalId; + + @JsonProperty("clinicalAttributeId") + private String attrId; + + @JsonProperty("value") + private String attrValue; +} diff --git a/src/main/java/org/cbioportal/legacy/web/mixin/ClinicalEventDataMixin.java b/src/main/java/org/cbioportal/legacy/web/mixin/ClinicalEventDataMixin.java new file mode 100644 index 00000000000..422dad3add7 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/mixin/ClinicalEventDataMixin.java @@ -0,0 +1,8 @@ +package org.cbioportal.legacy.web.mixin; + +import com.fasterxml.jackson.annotation.JsonIgnore; + +public class ClinicalEventDataMixin { + + @JsonIgnore private Long clinicalEventId; +} diff --git a/src/main/java/org/cbioportal/legacy/web/mixin/ClinicalEventMixin.java b/src/main/java/org/cbioportal/legacy/web/mixin/ClinicalEventMixin.java new file mode 100644 index 00000000000..80623a00bf8 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/mixin/ClinicalEventMixin.java @@ -0,0 +1,15 @@ +package org.cbioportal.legacy.web.mixin; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; + +public class ClinicalEventMixin { + + @JsonIgnore private Long clinicalEventId; + + @JsonProperty("startNumberOfDaysSinceDiagnosis") + private Integer startDate; + + @JsonProperty("endNumberOfDaysSinceDiagnosis") + private Integer stopDate; +} diff --git a/src/main/java/org/cbioportal/legacy/web/mixin/CopyNumberSegMixin.java b/src/main/java/org/cbioportal/legacy/web/mixin/CopyNumberSegMixin.java new file mode 100644 index 00000000000..a807d168f58 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/mixin/CopyNumberSegMixin.java @@ -0,0 +1,24 @@ +package org.cbioportal.legacy.web.mixin; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; + +public class CopyNumberSegMixin { + + @JsonIgnore private Long segId; + @JsonIgnore private Integer cancerStudyId; + + @JsonProperty("studyId") + private String cancerStudyIdentifier; + + @JsonIgnore private Integer sampleId; + + @JsonProperty("sampleId") + private String sampleStableId; + + @JsonProperty("numberOfProbes") + private Integer numProbes; + + @JsonProperty("chromosome") + private String chr; +} diff --git a/src/main/java/org/cbioportal/legacy/web/mixin/DataAccessTokenMixin.java b/src/main/java/org/cbioportal/legacy/web/mixin/DataAccessTokenMixin.java new file mode 100644 index 00000000000..37a830cc1c3 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/mixin/DataAccessTokenMixin.java @@ -0,0 +1,13 @@ +package org.cbioportal.legacy.web.mixin; + +import com.fasterxml.jackson.annotation.JsonFormat; +import java.util.Date; + +public class DataAccessTokenMixin { + + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss") + private Date expiration; + + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss") + private Date creation; +} diff --git a/src/main/java/org/cbioportal/legacy/web/mixin/DiscreteCopyNumberDataMixin.java b/src/main/java/org/cbioportal/legacy/web/mixin/DiscreteCopyNumberDataMixin.java new file mode 100644 index 00000000000..1c5d9efe1ac --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/mixin/DiscreteCopyNumberDataMixin.java @@ -0,0 +1,9 @@ +package org.cbioportal.legacy.web.mixin; + +import com.fasterxml.jackson.annotation.JsonProperty; + +public class DiscreteCopyNumberDataMixin { + + @JsonProperty("namespaceColumns") + private Object annotationJson; +} diff --git a/src/main/java/org/cbioportal/legacy/web/mixin/GeneMixin.java b/src/main/java/org/cbioportal/legacy/web/mixin/GeneMixin.java new file mode 100644 index 00000000000..98ef3e8a835 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/mixin/GeneMixin.java @@ -0,0 +1,3 @@ +package org.cbioportal.legacy.web.mixin; + +public class GeneMixin {} diff --git a/src/main/java/org/cbioportal/legacy/web/mixin/GenePanelMixin.java b/src/main/java/org/cbioportal/legacy/web/mixin/GenePanelMixin.java new file mode 100644 index 00000000000..fd7f98b84a0 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/mixin/GenePanelMixin.java @@ -0,0 +1,12 @@ +package org.cbioportal.legacy.web.mixin; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; + +public class GenePanelMixin { + + @JsonIgnore private Integer internalId; + + @JsonProperty("genePanelId") + private String stableId; +} diff --git a/src/main/java/org/cbioportal/legacy/web/mixin/GenePanelToGeneMixin.java b/src/main/java/org/cbioportal/legacy/web/mixin/GenePanelToGeneMixin.java new file mode 100644 index 00000000000..0609ada87c0 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/mixin/GenePanelToGeneMixin.java @@ -0,0 +1,8 @@ +package org.cbioportal.legacy.web.mixin; + +import com.fasterxml.jackson.annotation.JsonIgnore; + +public class GenePanelToGeneMixin { + + @JsonIgnore private String genePanelId; +} diff --git a/src/main/java/org/cbioportal/legacy/web/mixin/GenesetCorrelationMixin.java b/src/main/java/org/cbioportal/legacy/web/mixin/GenesetCorrelationMixin.java new file mode 100644 index 00000000000..c326a2a395a --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/mixin/GenesetCorrelationMixin.java @@ -0,0 +1,12 @@ +package org.cbioportal.legacy.web.mixin; + +import com.fasterxml.jackson.annotation.JsonProperty; + +public class GenesetCorrelationMixin { + + @JsonProperty("expressionGeneticProfileId") + private String expressionMolecularProfileId; + + @JsonProperty("zScoreGeneticProfileId") + private String zScoreMolecularProfileId; +} diff --git a/src/main/java/org/cbioportal/legacy/web/mixin/GenesetMixin.java b/src/main/java/org/cbioportal/legacy/web/mixin/GenesetMixin.java new file mode 100644 index 00000000000..2f5bf3c9ba5 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/mixin/GenesetMixin.java @@ -0,0 +1,8 @@ +package org.cbioportal.legacy.web.mixin; + +import com.fasterxml.jackson.annotation.JsonIgnore; + +public class GenesetMixin { + + @JsonIgnore private Integer internalId; +} diff --git a/src/main/java/org/cbioportal/legacy/web/mixin/GenesetMolecularDataMixin.java b/src/main/java/org/cbioportal/legacy/web/mixin/GenesetMolecularDataMixin.java new file mode 100644 index 00000000000..539c73eefbe --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/mixin/GenesetMolecularDataMixin.java @@ -0,0 +1,9 @@ +package org.cbioportal.legacy.web.mixin; + +import com.fasterxml.jackson.annotation.JsonProperty; + +public class GenesetMolecularDataMixin { + + @JsonProperty("geneticProfileId") + private String molecularProfileId; +} diff --git a/src/main/java/org/cbioportal/legacy/web/mixin/GisticMixin.java b/src/main/java/org/cbioportal/legacy/web/mixin/GisticMixin.java new file mode 100644 index 00000000000..e6746a9d1b5 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/mixin/GisticMixin.java @@ -0,0 +1,12 @@ +package org.cbioportal.legacy.web.mixin; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; + +public class GisticMixin { + + @JsonIgnore private Long gisticRoiId; + + @JsonProperty("studyId") + private String cancerStudyId; +} diff --git a/src/main/java/org/cbioportal/legacy/web/mixin/GisticToGeneMixin.java b/src/main/java/org/cbioportal/legacy/web/mixin/GisticToGeneMixin.java new file mode 100644 index 00000000000..a9f0a2633be --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/mixin/GisticToGeneMixin.java @@ -0,0 +1,8 @@ +package org.cbioportal.legacy.web.mixin; + +import com.fasterxml.jackson.annotation.JsonIgnore; + +public class GisticToGeneMixin { + + @JsonIgnore private Long gisticRoiId; +} diff --git a/src/main/java/org/cbioportal/legacy/web/mixin/MolecularProfileMixin.java b/src/main/java/org/cbioportal/legacy/web/mixin/MolecularProfileMixin.java new file mode 100644 index 00000000000..6824b5e7a40 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/mixin/MolecularProfileMixin.java @@ -0,0 +1,21 @@ +package org.cbioportal.legacy.web.mixin; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; +import org.cbioportal.legacy.model.CancerStudy; + +public class MolecularProfileMixin { + + @JsonIgnore private Integer molecularProfileId; + + @JsonProperty("molecularProfileId") + private String stableId; + + @JsonIgnore private Integer cancerStudyId; + + @JsonProperty("studyId") + private String cancerStudyIdentifier; + + @JsonProperty("study") + private CancerStudy cancerStudy; +} diff --git a/src/main/java/org/cbioportal/legacy/web/mixin/MutSigMixin.java b/src/main/java/org/cbioportal/legacy/web/mixin/MutSigMixin.java new file mode 100644 index 00000000000..ea1fd1acbf1 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/mixin/MutSigMixin.java @@ -0,0 +1,17 @@ +package org.cbioportal.legacy.web.mixin; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; + +public class MutSigMixin { + + @JsonIgnore private Integer cancerStudyId; + + @JsonProperty("studyId") + private String cancerStudyIdentifier; + + @JsonIgnore private Integer numbasescovered; + + @JsonProperty("numberOfMutations") + private Integer nummutations; +} diff --git a/src/main/java/org/cbioportal/legacy/web/mixin/MutationMixin.java b/src/main/java/org/cbioportal/legacy/web/mixin/MutationMixin.java new file mode 100644 index 00000000000..c81a9073e75 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/mixin/MutationMixin.java @@ -0,0 +1,26 @@ +package org.cbioportal.legacy.web.mixin; + +import com.fasterxml.jackson.annotation.JsonProperty; +import io.swagger.v3.oas.annotations.media.Schema; + +public class MutationMixin { + + @JsonProperty("variantAllele") + private String tumorSeqAllele; + + @JsonProperty("refseqMrnaId") + private String refseqMrnaId; + + @JsonProperty("proteinPosStart") + private Integer proteinPosStart; + + @JsonProperty("proteinPosEnd") + private Integer proteinPosEnd; + + @JsonProperty("chr") + private String chr; + + @Schema(type = "java.util.Map") + @JsonProperty("namespaceColumns") + private Object annotationJSON; +} diff --git a/src/main/java/org/cbioportal/legacy/web/mixin/MutationSpectrumMixin.java b/src/main/java/org/cbioportal/legacy/web/mixin/MutationSpectrumMixin.java new file mode 100644 index 00000000000..299ff880569 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/mixin/MutationSpectrumMixin.java @@ -0,0 +1,24 @@ +package org.cbioportal.legacy.web.mixin; + +import com.fasterxml.jackson.annotation.JsonProperty; + +public class MutationSpectrumMixin { + + @JsonProperty("CtoA") + private Integer ctoA; + + @JsonProperty("CtoG") + private Integer ctoG; + + @JsonProperty("CtoT") + private Integer ctoT; + + @JsonProperty("TtoA") + private Integer ttoA; + + @JsonProperty("TtoC") + private Integer ttoC; + + @JsonProperty("TtoG") + private Integer ttoG; +} diff --git a/src/main/java/org/cbioportal/legacy/web/mixin/NamespaceDataCountMixin.java b/src/main/java/org/cbioportal/legacy/web/mixin/NamespaceDataCountMixin.java new file mode 100644 index 00000000000..e6f8e7d8bb1 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/mixin/NamespaceDataCountMixin.java @@ -0,0 +1,9 @@ +package org.cbioportal.legacy.web.mixin; + +import com.fasterxml.jackson.annotation.JsonIgnore; + +public class NamespaceDataCountMixin { + + @JsonIgnore private String outerKey; + @JsonIgnore private String innerKey; +} diff --git a/src/main/java/org/cbioportal/legacy/web/mixin/PatientMixin.java b/src/main/java/org/cbioportal/legacy/web/mixin/PatientMixin.java new file mode 100644 index 00000000000..486d9ae550b --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/mixin/PatientMixin.java @@ -0,0 +1,17 @@ +package org.cbioportal.legacy.web.mixin; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; + +public class PatientMixin { + + @JsonIgnore private Integer internalId; + + @JsonProperty("patientId") + private String stableId; + + @JsonIgnore private Integer cancerStudyId; + + @JsonProperty("studyId") + private String cancerStudyIdentifier; +} diff --git a/src/main/java/org/cbioportal/legacy/web/mixin/ReferenceGenomeGeneMixin.java b/src/main/java/org/cbioportal/legacy/web/mixin/ReferenceGenomeGeneMixin.java new file mode 100644 index 00000000000..44d0afbfb41 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/mixin/ReferenceGenomeGeneMixin.java @@ -0,0 +1,7 @@ +package org.cbioportal.legacy.web.mixin; + +import com.fasterxml.jackson.annotation.JsonIgnore; + +public class ReferenceGenomeGeneMixin { + @JsonIgnore private Integer referenceGenomeId; +} diff --git a/src/main/java/org/cbioportal/legacy/web/mixin/ResourceDefinitionMixin.java b/src/main/java/org/cbioportal/legacy/web/mixin/ResourceDefinitionMixin.java new file mode 100644 index 00000000000..b11c7836de4 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/mixin/ResourceDefinitionMixin.java @@ -0,0 +1,9 @@ +package org.cbioportal.legacy.web.mixin; + +import com.fasterxml.jackson.annotation.JsonProperty; + +public class ResourceDefinitionMixin { + + @JsonProperty("studyId") + private String cancerStudyIdentifier; +} diff --git a/src/main/java/org/cbioportal/legacy/web/mixin/SampleListMixin.java b/src/main/java/org/cbioportal/legacy/web/mixin/SampleListMixin.java new file mode 100644 index 00000000000..eae6f81affb --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/mixin/SampleListMixin.java @@ -0,0 +1,20 @@ +package org.cbioportal.legacy.web.mixin; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; +import org.cbioportal.legacy.model.CancerStudy; + +public class SampleListMixin { + + @JsonIgnore private Integer listId; + + @JsonProperty("sampleListId") + private String stableId; + + @JsonIgnore private Integer cancerStudyId; + + @JsonProperty("studyId") + private String cancerStudyIdentifier; + + @JsonIgnore private CancerStudy cancerStudy; +} diff --git a/src/main/java/org/cbioportal/legacy/web/mixin/SampleMixin.java b/src/main/java/org/cbioportal/legacy/web/mixin/SampleMixin.java new file mode 100644 index 00000000000..81b74fbf2ad --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/mixin/SampleMixin.java @@ -0,0 +1,23 @@ +package org.cbioportal.legacy.web.mixin; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; +import org.cbioportal.legacy.model.Patient; + +public class SampleMixin { + + @JsonIgnore private Integer internalId; + + @JsonProperty("sampleId") + private String stableId; + + @JsonIgnore private Integer patientId; + + @JsonProperty("patientId") + private String patientStableId; + + @JsonIgnore private Patient patient; + + @JsonProperty("studyId") + private String cancerStudyIdentifier; +} diff --git a/src/main/java/org/cbioportal/legacy/web/mixin/SessionDataMixin.java b/src/main/java/org/cbioportal/legacy/web/mixin/SessionDataMixin.java new file mode 100644 index 00000000000..2386c6e5650 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/mixin/SessionDataMixin.java @@ -0,0 +1,12 @@ +package org.cbioportal.legacy.web.mixin; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import java.util.Set; + +public class SessionDataMixin { + @JsonIgnore private String owner; + @JsonIgnore private Long created; + @JsonIgnore private Float version; + @JsonIgnore private Set users; + @JsonIgnore private Long lastUpdated; +} diff --git a/src/main/java/org/cbioportal/legacy/web/mixin/SessionMixin.java b/src/main/java/org/cbioportal/legacy/web/mixin/SessionMixin.java new file mode 100644 index 00000000000..9bf724122a4 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/mixin/SessionMixin.java @@ -0,0 +1,10 @@ +package org.cbioportal.legacy.web.mixin; + +import com.fasterxml.jackson.annotation.JsonIgnore; + +public class SessionMixin { + + @JsonIgnore private String source; + @JsonIgnore private String type; + @JsonIgnore private String checksum; +} diff --git a/src/main/java/org/cbioportal/legacy/web/mixin/StructuralVariantMixin.java b/src/main/java/org/cbioportal/legacy/web/mixin/StructuralVariantMixin.java new file mode 100644 index 00000000000..da96f6d847f --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/mixin/StructuralVariantMixin.java @@ -0,0 +1,9 @@ +package org.cbioportal.legacy.web.mixin; + +import com.fasterxml.jackson.annotation.*; + +public class StructuralVariantMixin { + + @JsonProperty("namespaceColumns") + private Object annotationJson; +} diff --git a/src/main/java/org/cbioportal/legacy/web/mixin/TypeOfCancerMixin.java b/src/main/java/org/cbioportal/legacy/web/mixin/TypeOfCancerMixin.java new file mode 100644 index 00000000000..88bd43611f8 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/mixin/TypeOfCancerMixin.java @@ -0,0 +1,9 @@ +package org.cbioportal.legacy.web.mixin; + +import com.fasterxml.jackson.annotation.JsonProperty; + +public class TypeOfCancerMixin { + + @JsonProperty("cancerTypeId") + private String typeOfCancerId; +} diff --git a/src/main/java/org/cbioportal/legacy/web/parameter/BinsGeneratorConfig.java b/src/main/java/org/cbioportal/legacy/web/parameter/BinsGeneratorConfig.java new file mode 100644 index 00000000000..6331f61676f --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/parameter/BinsGeneratorConfig.java @@ -0,0 +1,25 @@ +package org.cbioportal.legacy.web.parameter; + +import java.math.BigDecimal; + +public class BinsGeneratorConfig { + + private BigDecimal binSize; + private BigDecimal anchorValue; + + public BigDecimal getBinSize() { + return binSize; + } + + public void setBinSize(BigDecimal binSize) { + this.binSize = binSize; + } + + public BigDecimal getAnchorValue() { + return anchorValue; + } + + public void setAnchorValue(BigDecimal anchorValue) { + this.anchorValue = anchorValue; + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/parameter/CategorizedClinicalDataCountFilter.java b/src/main/java/org/cbioportal/legacy/web/parameter/CategorizedClinicalDataCountFilter.java new file mode 100644 index 00000000000..706287864fa --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/parameter/CategorizedClinicalDataCountFilter.java @@ -0,0 +1,75 @@ +package org.cbioportal.legacy.web.parameter; + +import java.util.List; + +public final class CategorizedClinicalDataCountFilter { + + public static Builder getBuilder() { + return new Builder(); + } + + private final List sampleNumericalClinicalDataFilters; + private final List sampleCategoricalClinicalDataFilters; + private final List patientNumericalClinicalDataFilters; + private final List patientCategoricalClinicalDataFilters; + + private CategorizedClinicalDataCountFilter(Builder builder) { + this.sampleCategoricalClinicalDataFilters = builder.sampleCategoricalClinicalDataFilters; + this.sampleNumericalClinicalDataFilters = builder.sampleNumericalClinicalDataFilters; + this.patientCategoricalClinicalDataFilters = builder.patientCategoricalClinicalDataFilters; + this.patientNumericalClinicalDataFilters = builder.patientNumericalClinicalDataFilters; + } + + public List getSampleNumericalClinicalDataFilters() { + return sampleNumericalClinicalDataFilters; + } + + public List getSampleCategoricalClinicalDataFilters() { + return sampleCategoricalClinicalDataFilters; + } + + public List getPatientNumericalClinicalDataFilters() { + return patientNumericalClinicalDataFilters; + } + + public List getPatientCategoricalClinicalDataFilters() { + return patientCategoricalClinicalDataFilters; + } + + public static class Builder { + private List sampleNumericalClinicalDataFilters; + private List sampleCategoricalClinicalDataFilters; + private List patientNumericalClinicalDataFilters; + private List patientCategoricalClinicalDataFilters; + + private Builder() {} + + public Builder setSampleCategoricalClinicalDataFilters( + List sampleCategoricalClinicalDataFilters) { + this.sampleCategoricalClinicalDataFilters = sampleCategoricalClinicalDataFilters; + return this; + } + + public Builder setSampleNumericalClinicalDataFilters( + List sampleNumericalClinicalDataFilters) { + this.sampleNumericalClinicalDataFilters = sampleNumericalClinicalDataFilters; + return this; + } + + public Builder setPatientCategoricalClinicalDataFilters( + List patientCategoricalClinicalDataFilters) { + this.patientCategoricalClinicalDataFilters = patientCategoricalClinicalDataFilters; + return this; + } + + public Builder setPatientNumericalClinicalDataFilters( + List patientNumericalClinicalDataFilters) { + this.patientNumericalClinicalDataFilters = patientNumericalClinicalDataFilters; + return this; + } + + public CategorizedClinicalDataCountFilter build() { + return new CategorizedClinicalDataCountFilter(this); + } + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/parameter/CategorizedGenericAssayDataCountFilter.java b/src/main/java/org/cbioportal/legacy/web/parameter/CategorizedGenericAssayDataCountFilter.java new file mode 100644 index 00000000000..2f3ad4ccf35 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/parameter/CategorizedGenericAssayDataCountFilter.java @@ -0,0 +1,156 @@ +package org.cbioportal.legacy.web.parameter; + +import java.util.List; +import java.util.Map; +import org.cbioportal.legacy.model.MolecularProfile; +import org.cbioportal.legacy.persistence.enums.DataSource; +import org.springframework.lang.Nullable; + +// TODO Remove +public final class CategorizedGenericAssayDataCountFilter { + + public static Builder getBuilder() { + return new Builder(); + } + + public static Builder getBuilder( + @Nullable Map> genericAssayProfilesMap, + StudyViewFilter studyViewFilter) { + if (genericAssayProfilesMap == null) { + return new Builder(); + } + return new Builder(genericAssayProfilesMap, studyViewFilter); + } + + private final List sampleNumericalGenericAssayDataFilters; + private final List sampleCategoricalGenericAssayDataFilters; + private final List patientNumericalGenericAssayDataFilters; + private final List patientCategoricalGenericAssayDataFilters; + + private CategorizedGenericAssayDataCountFilter(Builder builder) { + this.sampleCategoricalGenericAssayDataFilters = + builder.sampleCategoricalGenericAssayDataFilters; + this.sampleNumericalGenericAssayDataFilters = builder.sampleNumericalGenericAssayDataFilters; + this.patientCategoricalGenericAssayDataFilters = + builder.patientCategoricalGenericAssayDataFilters; + this.patientNumericalGenericAssayDataFilters = builder.patientNumericalGenericAssayDataFilters; + } + + public List getSampleNumericalGenericAssayDataFilters() { + return sampleNumericalGenericAssayDataFilters; + } + + public List getSampleCategoricalGenericAssayDataFilters() { + return sampleCategoricalGenericAssayDataFilters; + } + + public List getPatientNumericalGenericAssayDataFilters() { + return patientNumericalGenericAssayDataFilters; + } + + public List getPatientCategoricalGenericAssayDataFilters() { + return patientCategoricalGenericAssayDataFilters; + } + + public static class Builder { + private List sampleNumericalGenericAssayDataFilters; + private List sampleCategoricalGenericAssayDataFilters; + private List patientNumericalGenericAssayDataFilters; + private List patientCategoricalGenericAssayDataFilters; + + private Builder() {} + + private Builder( + Map> genericAssayProfilesMap, + StudyViewFilter studyViewFilter) { + if ((studyViewFilter.getGenericAssayDataFilters() == null + || genericAssayProfilesMap.isEmpty())) { + return; + } + + // No BINARY in the database yet + if (genericAssayProfilesMap.containsKey(DataSource.SAMPLE)) { + List sampleNumericalProfileTypes = + genericAssayProfilesMap.get(DataSource.SAMPLE).stream() + .filter(profile -> profile.getDatatype().equals("LIMIT-VALUE")) + .map( + profile -> + profile.getStableId().replace(profile.getCancerStudyIdentifier() + "_", "")) + .toList(); + sampleNumericalGenericAssayDataFilters = + studyViewFilter.getGenericAssayDataFilters().stream() + .filter( + genericAssayDataFilter -> + sampleNumericalProfileTypes.contains( + genericAssayDataFilter.getProfileType())) + .toList(); + List sampleCategoricalProfileTypes = + genericAssayProfilesMap.get(DataSource.SAMPLE).stream() + .filter( + profile -> + profile.getDatatype().equals("CATEGORICAL") + || profile.getDatatype().equals("BINARY")) + .map( + profile -> + profile.getStableId().replace(profile.getCancerStudyIdentifier() + "_", "")) + .toList(); + sampleCategoricalGenericAssayDataFilters = + studyViewFilter.getGenericAssayDataFilters().stream() + .filter( + genericAssayDataFilter -> + sampleCategoricalProfileTypes.contains( + genericAssayDataFilter.getProfileType())) + .toList(); + } + + // patient level profile only have categorical for now + if (genericAssayProfilesMap.containsKey(DataSource.PATIENT)) { + List patientCategoricalProfileTypes = + genericAssayProfilesMap.get(DataSource.PATIENT).stream() + .filter( + profile -> + profile.getDatatype().equals("CATEGORICAL") + || profile.getDatatype().equals("BINARY")) + .map( + profile -> + profile.getStableId().replace(profile.getCancerStudyIdentifier() + "_", "")) + .toList(); + patientCategoricalGenericAssayDataFilters = + studyViewFilter.getGenericAssayDataFilters().stream() + .filter( + genericAssayDataFilter -> + patientCategoricalProfileTypes.contains( + genericAssayDataFilter.getProfileType())) + .toList(); + } + } + + public Builder setSampleCategoricalGenericAssayDataFilters( + List sampleCategoricalGenericAssayDataFilters) { + this.sampleCategoricalGenericAssayDataFilters = sampleCategoricalGenericAssayDataFilters; + return this; + } + + public Builder setSampleNumericalGenericAssayDataFilters( + List sampleNumericalGenericAssayDataFilters) { + this.sampleNumericalGenericAssayDataFilters = sampleNumericalGenericAssayDataFilters; + return this; + } + + public Builder setPatientCategoricalGenericAssayDataFilters( + List patientCategoricalGenericAssayDataFilters) { + this.patientCategoricalGenericAssayDataFilters = patientCategoricalGenericAssayDataFilters; + return this; + } + + public Builder setPatientNumericalGenericAssayDataFilters( + List patientNumericalGenericAssayDataFilters) { + this.patientNumericalGenericAssayDataFilters = patientNumericalGenericAssayDataFilters; + return this; + } + + public CategorizedGenericAssayDataCountFilter build() { + return new CategorizedGenericAssayDataCountFilter(this); + } + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/parameter/ClinicalAttributeCountFilter.java b/src/main/java/org/cbioportal/legacy/web/parameter/ClinicalAttributeCountFilter.java new file mode 100644 index 00000000000..78db4954bb7 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/parameter/ClinicalAttributeCountFilter.java @@ -0,0 +1,35 @@ +package org.cbioportal.legacy.web.parameter; + +import jakarta.validation.constraints.AssertTrue; +import jakarta.validation.constraints.Size; +import java.io.Serializable; +import java.util.List; + +public class ClinicalAttributeCountFilter implements Serializable { + + @Size(min = 1, max = PagingConstants.MAX_PAGE_SIZE) + private List sampleIdentifiers; + + private String sampleListId; + + @AssertTrue + private boolean isEitherSampleListIdOrSampleIdsPresent() { + return sampleListId != null ^ sampleIdentifiers != null; + } + + public List getSampleIdentifiers() { + return sampleIdentifiers; + } + + public void setSampleIdentifiers(List sampleIdentifiers) { + this.sampleIdentifiers = sampleIdentifiers; + } + + public String getSampleListId() { + return sampleListId; + } + + public void setSampleListId(String sampleListId) { + this.sampleListId = sampleListId; + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/parameter/ClinicalDataBinCountFilter.java b/src/main/java/org/cbioportal/legacy/web/parameter/ClinicalDataBinCountFilter.java new file mode 100644 index 00000000000..da0fdf3950b --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/parameter/ClinicalDataBinCountFilter.java @@ -0,0 +1,17 @@ +package org.cbioportal.legacy.web.parameter; + +import java.io.Serializable; +import java.util.List; + +public class ClinicalDataBinCountFilter extends DataBinCountFilter implements Serializable { + + private List attributes; + + public List getAttributes() { + return attributes; + } + + public void setAttributes(List attributes) { + this.attributes = attributes; + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/parameter/ClinicalDataBinFilter.java b/src/main/java/org/cbioportal/legacy/web/parameter/ClinicalDataBinFilter.java new file mode 100644 index 00000000000..723018099d6 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/parameter/ClinicalDataBinFilter.java @@ -0,0 +1,18 @@ +package org.cbioportal.legacy.web.parameter; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import java.io.Serializable; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class ClinicalDataBinFilter extends DataBinFilter implements Serializable { + + private String attributeId; + + public String getAttributeId() { + return attributeId; + } + + public void setAttributeId(String attributeId) { + this.attributeId = attributeId; + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/parameter/ClinicalDataCountFilter.java b/src/main/java/org/cbioportal/legacy/web/parameter/ClinicalDataCountFilter.java new file mode 100644 index 00000000000..7a71160075a --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/parameter/ClinicalDataCountFilter.java @@ -0,0 +1,26 @@ +package org.cbioportal.legacy.web.parameter; + +import java.io.Serializable; +import java.util.List; + +public class ClinicalDataCountFilter implements Serializable { + + private List attributes; + private StudyViewFilter studyViewFilter; + + public List getAttributes() { + return attributes; + } + + public void setAttributes(List attributes) { + this.attributes = attributes; + } + + public StudyViewFilter getStudyViewFilter() { + return studyViewFilter; + } + + public void setStudyViewFilter(StudyViewFilter studyViewFilter) { + this.studyViewFilter = studyViewFilter; + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/parameter/ClinicalDataFilter.java b/src/main/java/org/cbioportal/legacy/web/parameter/ClinicalDataFilter.java new file mode 100644 index 00000000000..c69573eb1ec --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/parameter/ClinicalDataFilter.java @@ -0,0 +1,46 @@ +package org.cbioportal.legacy.web.parameter; + +import io.swagger.v3.oas.annotations.Hidden; +import java.io.Serializable; +import java.util.List; + +public class ClinicalDataFilter extends DataFilter implements Serializable { + + private String attributeId; + + @Hidden private List samples; + @Hidden private String datatype; + @Hidden private String displayName; + + public String getAttributeId() { + return attributeId; + } + + public void setAttributeId(String attributeId) { + this.attributeId = attributeId; + } + + public List getSamples() { + return samples; + } + + public void setSamples(List samples) { + this.samples = samples; + } + + public String getDatatype() { + return datatype; + } + + public void setDatatype(String datatype) { + this.datatype = datatype; + } + + public String getDisplayName() { + return displayName; + } + + public void setDisplayName(String displayName) { + this.displayName = displayName; + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/parameter/ClinicalDataIdentifier.java b/src/main/java/org/cbioportal/legacy/web/parameter/ClinicalDataIdentifier.java new file mode 100644 index 00000000000..f8c3c858d2c --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/parameter/ClinicalDataIdentifier.java @@ -0,0 +1,25 @@ +package org.cbioportal.legacy.web.parameter; + +import java.io.Serializable; + +public class ClinicalDataIdentifier implements Serializable { + + private String entityId; + private String studyId; + + public String getEntityId() { + return entityId; + } + + public void setEntityId(String entityId) { + this.entityId = entityId; + } + + public String getStudyId() { + return studyId; + } + + public void setStudyId(String studyId) { + this.studyId = studyId; + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/parameter/ClinicalDataMultiStudyFilter.java b/src/main/java/org/cbioportal/legacy/web/parameter/ClinicalDataMultiStudyFilter.java new file mode 100644 index 00000000000..978787aa565 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/parameter/ClinicalDataMultiStudyFilter.java @@ -0,0 +1,33 @@ +package org.cbioportal.legacy.web.parameter; + +import static org.cbioportal.legacy.web.parameter.PagingConstants.MAX_PAGE_SIZE; + +import jakarta.validation.constraints.Size; +import java.io.Serializable; +import java.util.List; +import org.cbioportal.legacy.web.ClinicalDataController; + +public class ClinicalDataMultiStudyFilter implements Serializable { + + @Size(min = 1, max = ClinicalDataController.CLINICAL_DATA_MAX_PAGE_SIZE) + private List identifiers; + + @Size(min = 1, max = MAX_PAGE_SIZE) + private List attributeIds; + + public List getIdentifiers() { + return identifiers; + } + + public void setIdentifiers(List identifiers) { + this.identifiers = identifiers; + } + + public List getAttributeIds() { + return attributeIds; + } + + public void setAttributeIds(List attributeIds) { + this.attributeIds = attributeIds; + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/parameter/ClinicalDataSingleStudyFilter.java b/src/main/java/org/cbioportal/legacy/web/parameter/ClinicalDataSingleStudyFilter.java new file mode 100644 index 00000000000..4110a7d4c15 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/parameter/ClinicalDataSingleStudyFilter.java @@ -0,0 +1,32 @@ +package org.cbioportal.legacy.web.parameter; + +import static org.cbioportal.legacy.web.parameter.PagingConstants.MAX_PAGE_SIZE; + +import jakarta.validation.constraints.Size; +import java.util.List; +import org.cbioportal.legacy.web.ClinicalDataController; + +public class ClinicalDataSingleStudyFilter { + + @Size(min = 1, max = ClinicalDataController.CLINICAL_DATA_MAX_PAGE_SIZE) + private List ids; + + @Size(min = 1, max = MAX_PAGE_SIZE) + private List attributeIds; + + public List getIds() { + return ids; + } + + public void setIds(List ids) { + this.ids = ids; + } + + public List getAttributeIds() { + return attributeIds; + } + + public void setAttributeIds(List attributeIds) { + this.attributeIds = attributeIds; + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/parameter/ClinicalDataType.java b/src/main/java/org/cbioportal/legacy/web/parameter/ClinicalDataType.java new file mode 100644 index 00000000000..f8a4d7f8c36 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/parameter/ClinicalDataType.java @@ -0,0 +1,6 @@ +package org.cbioportal.legacy.web.parameter; + +public enum ClinicalDataType { + SAMPLE, + PATIENT; +} diff --git a/src/main/java/org/cbioportal/legacy/web/parameter/ClinicalEventAttributeRequest.java b/src/main/java/org/cbioportal/legacy/web/parameter/ClinicalEventAttributeRequest.java new file mode 100644 index 00000000000..528829e128a --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/parameter/ClinicalEventAttributeRequest.java @@ -0,0 +1,30 @@ +package org.cbioportal.legacy.web.parameter; + +import jakarta.validation.constraints.Size; +import java.io.Serializable; +import java.util.List; +import java.util.Set; + +public class ClinicalEventAttributeRequest implements Serializable { + + @Size(min = 1, max = PagingConstants.MAX_PAGE_SIZE) + private List patientIdentifiers; + + private Set clinicalEventRequests; + + public List getPatientIdentifiers() { + return patientIdentifiers; + } + + public void setPatientIdentifiers(List patientIdentifiers) { + this.patientIdentifiers = patientIdentifiers; + } + + public Set getClinicalEventRequests() { + return clinicalEventRequests; + } + + public void setClinicalEventRequests(Set clinicalEventRequests) { + this.clinicalEventRequests = clinicalEventRequests; + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/parameter/ClinicalEventRequest.java b/src/main/java/org/cbioportal/legacy/web/parameter/ClinicalEventRequest.java new file mode 100644 index 00000000000..79738f212e7 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/parameter/ClinicalEventRequest.java @@ -0,0 +1,29 @@ +package org.cbioportal.legacy.web.parameter; + +import jakarta.validation.constraints.NotNull; +import java.io.Serializable; +import java.util.List; +import org.cbioportal.legacy.model.ClinicalEventData; + +public class ClinicalEventRequest implements Serializable { + + @NotNull private String eventType; + + private List attributes; + + public String getEventType() { + return eventType; + } + + public void setEventType(String eventType) { + this.eventType = eventType; + } + + public List getAttributes() { + return attributes; + } + + public void setAttributes(List attributes) { + this.attributes = attributes; + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/parameter/ClinicalEventRequestIdentifier.java b/src/main/java/org/cbioportal/legacy/web/parameter/ClinicalEventRequestIdentifier.java new file mode 100644 index 00000000000..ed2934507c9 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/parameter/ClinicalEventRequestIdentifier.java @@ -0,0 +1,30 @@ +package org.cbioportal.legacy.web.parameter; + +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Size; +import java.io.Serializable; +import java.util.Set; + +public class ClinicalEventRequestIdentifier implements Serializable { + + @Size(max = PagingConstants.MAX_PAGE_SIZE) + private Set clinicalEventRequests; + + @NotNull private OccurrencePosition position; + + public Set getClinicalEventRequests() { + return clinicalEventRequests; + } + + public void setClinicalEventRequests(Set clinicalEventRequests) { + this.clinicalEventRequests = clinicalEventRequests; + } + + public OccurrencePosition getPosition() { + return position; + } + + public void setPosition(OccurrencePosition position) { + this.position = position; + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/parameter/ClinicalTrackConfig.java b/src/main/java/org/cbioportal/legacy/web/parameter/ClinicalTrackConfig.java new file mode 100644 index 00000000000..daf69881cc9 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/parameter/ClinicalTrackConfig.java @@ -0,0 +1,35 @@ +package org.cbioportal.legacy.web.parameter; + +import com.fasterxml.jackson.annotation.JsonInclude; +import java.io.Serializable; + +@JsonInclude(JsonInclude.Include.ALWAYS) +class ClinicalTrackConfig implements Serializable { + private String stableId; + private String sortOrder; + private Boolean gapOn; + + public String getStableId() { + return stableId; + } + + public void setStableId(String stableId) { + this.stableId = stableId; + } + + public String getSortOrder() { + return sortOrder; + } + + public void setSortOrder(String sortOrder) { + this.sortOrder = sortOrder; + } + + public Boolean getGapOn() { + return gapOn; + } + + public void setGapOn(Boolean gapOn) { + this.gapOn = gapOn; + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/parameter/CoExpressionFilter.java b/src/main/java/org/cbioportal/legacy/web/parameter/CoExpressionFilter.java new file mode 100644 index 00000000000..67157128ede --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/parameter/CoExpressionFilter.java @@ -0,0 +1,57 @@ +package org.cbioportal.legacy.web.parameter; + +import jakarta.validation.constraints.AssertTrue; +import jakarta.validation.constraints.Size; +import java.util.List; + +public class CoExpressionFilter { + + @Size(min = 1, max = PagingConstants.MAX_PAGE_SIZE) + private List sampleIds; + + private String sampleListId; + private Integer entrezGeneId; + private String genesetId; + + @AssertTrue + private boolean isEitherSampleListIdOrSampleIdsPresent() { + return sampleListId != null ^ sampleIds != null; + } + + @AssertTrue + private boolean isEitherEntrezGeneIdOrGenesetIdPresent() { + return entrezGeneId != null ^ genesetId != null; + } + + public List getSampleIds() { + return sampleIds; + } + + public void setSampleIds(List sampleIds) { + this.sampleIds = sampleIds; + } + + public String getSampleListId() { + return sampleListId; + } + + public void setSampleListId(String sampleListId) { + this.sampleListId = sampleListId; + } + + public Integer getEntrezGeneId() { + return entrezGeneId; + } + + public void setEntrezGeneId(Integer entrezGeneId) { + this.entrezGeneId = entrezGeneId; + } + + public String getGenesetId() { + return genesetId; + } + + public void setGenesetId(String genesetId) { + this.genesetId = genesetId; + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/parameter/CopyNumberCountIdentifier.java b/src/main/java/org/cbioportal/legacy/web/parameter/CopyNumberCountIdentifier.java new file mode 100644 index 00000000000..439b28bef71 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/parameter/CopyNumberCountIdentifier.java @@ -0,0 +1,23 @@ +package org.cbioportal.legacy.web.parameter; + +public class CopyNumberCountIdentifier { + + private Integer entrezGeneId; + private Integer alteration; + + public Integer getEntrezGeneId() { + return entrezGeneId; + } + + public void setEntrezGeneId(Integer entrezGeneId) { + this.entrezGeneId = entrezGeneId; + } + + public Integer getAlteration() { + return alteration; + } + + public void setAlteration(Integer alteration) { + this.alteration = alteration; + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/parameter/CustomGeneList.java b/src/main/java/org/cbioportal/legacy/web/parameter/CustomGeneList.java new file mode 100644 index 00000000000..bc27190714b --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/parameter/CustomGeneList.java @@ -0,0 +1,43 @@ +package org.cbioportal.legacy.web.parameter; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.databind.ObjectMapper; +import java.io.IOException; +import org.cbioportal.legacy.utils.removeme.Session; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class CustomGeneList extends Session { + + private final Logger LOG = LoggerFactory.getLogger(CustomGeneList.class); + private CustomGeneListData data; + + @Override + public void setData(Object data) { + ObjectMapper mapper = new ObjectMapper(); + try { + this.data = mapper.readValue(mapper.writeValueAsString(data), CustomGeneListData.class); + } catch (IOException e) { + LOG.error("Error occurred", e); + } + } + + @Override + public CustomGeneListData getData() { + return data; + } + + @JsonIgnore + @Override + public String getSource() { + return super.getSource(); + } + + @JsonIgnore + @Override + public SessionType getType() { + return super.getType(); + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/parameter/CustomGeneListData.java b/src/main/java/org/cbioportal/legacy/web/parameter/CustomGeneListData.java new file mode 100644 index 00000000000..b8fab3d96e5 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/parameter/CustomGeneListData.java @@ -0,0 +1,47 @@ +package org.cbioportal.legacy.web.parameter; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import java.io.Serializable; +import java.util.HashSet; +import java.util.Set; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class CustomGeneListData implements Serializable { + + private String name; + private String description; + private Set geneList = new HashSet<>(); + private Set users = new HashSet<>(); + + public Set getUsers() { + return users; + } + + public void setUsers(Set users) { + this.users = users; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public Set getGeneList() { + return geneList; + } + + public void setGeneList(Set geneList) { + this.geneList = geneList; + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/parameter/CustomSampleIdentifier.java b/src/main/java/org/cbioportal/legacy/web/parameter/CustomSampleIdentifier.java new file mode 100644 index 00000000000..8d1ba6e554d --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/parameter/CustomSampleIdentifier.java @@ -0,0 +1,36 @@ +package org.cbioportal.legacy.web.parameter; + +import java.io.Serializable; + +public class CustomSampleIdentifier extends SampleIdentifier implements Serializable { + + private boolean isFilteredOut = false; + private String value; + private String uniqueSampleId; + + public boolean getIsFilteredOut() { + return isFilteredOut; + } + + public void setIsFilteredOut(boolean isFilteredOut) { + this.isFilteredOut = isFilteredOut; + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + + // Generating unique SampleId by concatenating studyId and sampleId + public String getUniqueSampleId() { + // Assuming studyId and sampleId are available in SampleIdentifier + // Concatenate with "_" in between if both values are not null + if (getStudyId() != null && getSampleId() != null) { + return getStudyId() + "_" + getSampleId(); + } + return null; // or return null if either studyId or sampleId is null + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/parameter/DataBinCountFilter.java b/src/main/java/org/cbioportal/legacy/web/parameter/DataBinCountFilter.java new file mode 100644 index 00000000000..058bec930e9 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/parameter/DataBinCountFilter.java @@ -0,0 +1,16 @@ +package org.cbioportal.legacy.web.parameter; + +import java.io.Serializable; + +public class DataBinCountFilter implements Serializable { + + private StudyViewFilter studyViewFilter; + + public StudyViewFilter getStudyViewFilter() { + return studyViewFilter; + } + + public void setStudyViewFilter(StudyViewFilter studyViewFilter) { + this.studyViewFilter = studyViewFilter; + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/parameter/DataBinFilter.java b/src/main/java/org/cbioportal/legacy/web/parameter/DataBinFilter.java new file mode 100644 index 00000000000..d2af3d0ae3e --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/parameter/DataBinFilter.java @@ -0,0 +1,100 @@ +package org.cbioportal.legacy.web.parameter; + +import jakarta.validation.constraints.AssertTrue; +import java.io.Serializable; +import java.math.BigDecimal; +import java.util.List; +import org.springframework.validation.annotation.Validated; + +@Validated +public class DataBinFilter implements Serializable { + + public enum BinMethod { + MEDIAN, + QUARTILE, + CUSTOM, + GENERATE; + } + + private Boolean disableLogScale = false; + private List customBins; // needed for 'Custom bins' frontend option + + // FIXME: Code added for backwards compatibility. + // Replace by commented out line after merge of PR: + // https://github.com/cBioPortal/cbioportal-frontend/pull/4102 + private BinMethod binMethod = BinMethod.CUSTOM; + // private BinMethod binMethod; // needed for 'Median split' and + // 'Quartile' frontend options + + private BinsGeneratorConfig binsGeneratorConfig; // needed for 'Generate Bins' frontend option + private BigDecimal start; + private BigDecimal end; + + public Boolean getDisableLogScale() { + return disableLogScale; + } + + public void setDisableLogScale(Boolean disableLogScale) { + this.disableLogScale = disableLogScale; + } + + public List getCustomBins() { + return customBins; + } + + public void setCustomBins(List customBins) { + this.customBins = customBins; + } + + public BigDecimal getStart() { + return start; + } + + public void setStart(BigDecimal start) { + this.start = start; + } + + public BigDecimal getEnd() { + return end; + } + + public void setEnd(BigDecimal end) { + this.end = end; + } + + public BinMethod getBinMethod() { + return binMethod; + } + + public void setBinMethod(BinMethod binMethod) { + this.binMethod = binMethod; + } + + public BinsGeneratorConfig getBinsGeneratorConfig() { + return binsGeneratorConfig; + } + + public void setBinsGeneratorConfig(BinsGeneratorConfig binsGeneratorConfig) { + this.binsGeneratorConfig = binsGeneratorConfig; + } + + // TODO: make this work + @AssertTrue + private boolean rangeIsCoveringCustomBins() { + if (this.customBins != null && (start != null || end != null)) { + boolean valid = true; + for (BigDecimal bin : this.customBins) { + if (start != null && start.compareTo(bin) > 0) { + valid = false; + break; + } + if (end != null && end.compareTo(bin) < 0) { + valid = false; + break; + } + } + return valid; + } + return true; + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/parameter/DataBinMethod.java b/src/main/java/org/cbioportal/legacy/web/parameter/DataBinMethod.java new file mode 100644 index 00000000000..50549eb29b9 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/parameter/DataBinMethod.java @@ -0,0 +1,20 @@ +package org.cbioportal.legacy.web.parameter; + +/** + * STATIC and DYNAMIC binning relate to the way bin boundaries are derived from numerical data of a + * sample cohort defined by a Study View Filter (SVF). + * + *

When binning in STATIC mode, the binning ignores any filter in the SVF on the attribute that + * is the subject of binning. In effect, it bins all values of the cohort. This mode is important to + * drive frontend behavior where histograms show bins related to the entire data range, but + * highlight the currently selected/filtered data in blue (non-selected data bins in grey). In + * effect, this way the non-selected data influences the boundaries of the data bins, irrespective + * of the selected attribute range. + * + *

When binning in DYNAMIC mode, only the attribute data is binned that is defined by the SVF. + * The non-selected rest of the data does not influence the bin boundaries. + */ +public enum DataBinMethod { + STATIC, + DYNAMIC +} diff --git a/src/main/java/org/cbioportal/legacy/web/parameter/DataFilter.java b/src/main/java/org/cbioportal/legacy/web/parameter/DataFilter.java new file mode 100644 index 00000000000..deca88a0d5b --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/parameter/DataFilter.java @@ -0,0 +1,17 @@ +package org.cbioportal.legacy.web.parameter; + +import java.io.Serializable; +import java.util.List; + +public class DataFilter implements Serializable { + + private List values; + + public List getValues() { + return values; + } + + public void setValues(List values) { + this.values = values; + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/parameter/DataFilterValue.java b/src/main/java/org/cbioportal/legacy/web/parameter/DataFilterValue.java new file mode 100644 index 00000000000..be0335bb317 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/parameter/DataFilterValue.java @@ -0,0 +1,46 @@ +package org.cbioportal.legacy.web.parameter; + +import java.io.Serializable; +import java.math.BigDecimal; + +public class DataFilterValue implements Serializable { + + private BigDecimal start; + private BigDecimal end; + private String value; + + public DataFilterValue() {} + + public DataFilterValue(BigDecimal start, BigDecimal end) { + this.start = start; + this.end = end; + } + + public DataFilterValue(String value) { + this.value = value; + } + + public BigDecimal getStart() { + return start; + } + + public void setStart(BigDecimal start) { + this.start = start; + } + + public BigDecimal getEnd() { + return end; + } + + public void setEnd(BigDecimal end) { + this.end = end; + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/parameter/Direction.java b/src/main/java/org/cbioportal/legacy/web/parameter/Direction.java new file mode 100644 index 00000000000..b31ece31d1c --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/parameter/Direction.java @@ -0,0 +1,6 @@ +package org.cbioportal.legacy.web.parameter; + +public enum Direction { + ASC, + DESC +} diff --git a/src/main/java/org/cbioportal/legacy/web/parameter/DiscreteCopyNumberEventType.java b/src/main/java/org/cbioportal/legacy/web/parameter/DiscreteCopyNumberEventType.java new file mode 100644 index 00000000000..9b88a82d64f --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/parameter/DiscreteCopyNumberEventType.java @@ -0,0 +1,24 @@ +package org.cbioportal.legacy.web.parameter; + +import java.util.Arrays; +import java.util.List; + +public enum DiscreteCopyNumberEventType { + HOMDEL_AND_AMP(-2, 2), + HOMDEL(-2), + AMP(2), + GAIN(1), + HETLOSS(-1), + DIPLOID(0), + ALL(-2, -1, 0, 1, 2); + + private List alterationTypes; + + DiscreteCopyNumberEventType(Integer... alterationTypes) { + this.alterationTypes = Arrays.asList(alterationTypes); + } + + public List getAlterationTypes() { + return alterationTypes; + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/parameter/DiscreteCopyNumberFilter.java b/src/main/java/org/cbioportal/legacy/web/parameter/DiscreteCopyNumberFilter.java new file mode 100644 index 00000000000..9f6523edcf2 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/parameter/DiscreteCopyNumberFilter.java @@ -0,0 +1,47 @@ +package org.cbioportal.legacy.web.parameter; + +import jakarta.validation.constraints.AssertTrue; +import jakarta.validation.constraints.Size; +import java.util.List; + +public class DiscreteCopyNumberFilter { + + private static final int DISCRETE_COPY_NUMBER_MAX_PAGE_SIZE = 50000; + + @Size(min = 1, max = PagingConstants.MAX_PAGE_SIZE) + private List sampleIds; + + private String sampleListId; + + @Size(min = 1, max = DISCRETE_COPY_NUMBER_MAX_PAGE_SIZE) + private List entrezGeneIds; + + @AssertTrue + private boolean isEitherSampleListIdOrSampleIdsPresent() { + return sampleListId != null ^ sampleIds != null; + } + + public List getSampleIds() { + return sampleIds; + } + + public void setSampleIds(List sampleIds) { + this.sampleIds = sampleIds; + } + + public String getSampleListId() { + return sampleListId; + } + + public void setSampleListId(String sampleListId) { + this.sampleListId = sampleListId; + } + + public List getEntrezGeneIds() { + return entrezGeneIds; + } + + public void setEntrezGeneIds(List entrezGeneIds) { + this.entrezGeneIds = entrezGeneIds; + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/parameter/EnrichmentFilter.java b/src/main/java/org/cbioportal/legacy/web/parameter/EnrichmentFilter.java new file mode 100644 index 00000000000..fb64291356a --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/parameter/EnrichmentFilter.java @@ -0,0 +1,32 @@ +package org.cbioportal.legacy.web.parameter; + +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Size; +import java.util.List; + +public class EnrichmentFilter { + + @NotNull + @Size(min = 1) + private List alteredIds; + + @NotNull + @Size(min = 1) + private List unalteredIds; + + public List getAlteredIds() { + return alteredIds; + } + + public void setAlteredIds(List alteredIds) { + this.alteredIds = alteredIds; + } + + public List getUnalteredIds() { + return unalteredIds; + } + + public void setUnalteredIds(List unalteredIds) { + this.unalteredIds = unalteredIds; + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/parameter/GeneFilter.java b/src/main/java/org/cbioportal/legacy/web/parameter/GeneFilter.java new file mode 100644 index 00000000000..ffd194fb158 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/parameter/GeneFilter.java @@ -0,0 +1,110 @@ +package org.cbioportal.legacy.web.parameter; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import jakarta.validation.constraints.AssertTrue; +import java.io.Serializable; +import java.util.*; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.stream.Collectors; +import org.apache.commons.collections4.CollectionUtils; +import org.cbioportal.legacy.model.CNA; + +public class GeneFilter implements Serializable { + + private Set molecularProfileIds; + private List> geneQueries; + + private final String GENE_QUERY_PATTERN = + "^(\\w+)[\\s]*?(?:\\:(?:[\\s]*(?:(AMP)|(GAIN)|(DIPLOID)|(HETLOSS)|(HOMDEL))\\b)+)?$"; + + public class SingleGeneQuery implements Serializable { + private String hugoGeneSymbol; + private List alterations; + + public String getHugoGeneSymbol() { + return hugoGeneSymbol; + } + + public void setHugoGeneSymbol(String hugoGeneSymbol) { + this.hugoGeneSymbol = hugoGeneSymbol; + } + + public List getAlterations() { + return alterations; + } + + public void setAlterations(List alterations) { + this.alterations = alterations; + } + } + + @AssertTrue + private boolean isValid() { + if (!CollectionUtils.isEmpty(geneQueries) && !CollectionUtils.isEmpty(molecularProfileIds)) { + return geneQueries.stream() + .flatMap( + geneQuery -> + geneQuery.stream() + .map( + query -> { + Pattern pattern = Pattern.compile(GENE_QUERY_PATTERN); + Matcher matcher = pattern.matcher(query.trim()); + return matcher.matches(); + })) + .reduce(Boolean.TRUE, Boolean::logicalAnd); + } + return false; + } + + public Set getMolecularProfileIds() { + return molecularProfileIds; + } + + public void setMolecularProfileIds(Set molecularProfileIds) { + this.molecularProfileIds = molecularProfileIds; + } + + public List> getGeneQueries() { + return geneQueries; + } + + public void setGeneQueries(List> geneQueries) { + this.geneQueries = geneQueries; + } + + @JsonIgnore + public List> getSingleGeneQueries() { + + return geneQueries.stream() + .map( + geneQuery -> { + List singleGeneQueries = new ArrayList(); + + geneQuery.stream() + .forEach( + query -> { + Pattern pattern = Pattern.compile(GENE_QUERY_PATTERN); + Matcher matcher = pattern.matcher(query.trim()); + + if (matcher.find()) { + + String hugoGeneSymbol = matcher.group(1); + Set alterations = new HashSet<>(); + for (int count = 2; count <= matcher.groupCount(); count++) { + if (matcher.group(count) != null) { + alterations.add(CNA.valueOf(matcher.group(count))); + } + } + SingleGeneQuery singleGeneQuery = new SingleGeneQuery(); + singleGeneQuery.setHugoGeneSymbol(hugoGeneSymbol); + singleGeneQuery.setAlterations(new ArrayList<>(alterations)); + singleGeneQueries.add(singleGeneQuery); + } + }); + + return singleGeneQueries; + }) + .collect(Collectors.toList()); + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/parameter/GeneIdType.java b/src/main/java/org/cbioportal/legacy/web/parameter/GeneIdType.java new file mode 100644 index 00000000000..3ebefd53ed8 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/parameter/GeneIdType.java @@ -0,0 +1,6 @@ +package org.cbioportal.legacy.web.parameter; + +public enum GeneIdType { + ENTREZ_GENE_ID, + HUGO_GENE_SYMBOL +} diff --git a/src/main/java/org/cbioportal/legacy/web/parameter/GenePanelDataFilter.java b/src/main/java/org/cbioportal/legacy/web/parameter/GenePanelDataFilter.java new file mode 100644 index 00000000000..02e92476d40 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/parameter/GenePanelDataFilter.java @@ -0,0 +1,33 @@ +package org.cbioportal.legacy.web.parameter; + +import jakarta.validation.constraints.AssertTrue; +import jakarta.validation.constraints.Size; +import java.util.List; + +public class GenePanelDataFilter { + @Size(min = 1, max = PagingConstants.MAX_PAGE_SIZE) + private List sampleIds; + + private String sampleListId; + + @AssertTrue + private boolean isEitherSampleListIdOrSampleIdsPresent() { + return sampleListId != null ^ sampleIds != null; + } + + public List getSampleIds() { + return sampleIds; + } + + public void setSampleIds(List sampleIds) { + this.sampleIds = sampleIds; + } + + public String getSampleListId() { + return sampleListId; + } + + public void setSampleListId(String sampleListId) { + this.sampleListId = sampleListId; + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/parameter/GenePanelDataMultipleStudyFilter.java b/src/main/java/org/cbioportal/legacy/web/parameter/GenePanelDataMultipleStudyFilter.java new file mode 100644 index 00000000000..8d6e79917a2 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/parameter/GenePanelDataMultipleStudyFilter.java @@ -0,0 +1,37 @@ +package org.cbioportal.legacy.web.parameter; + +import jakarta.validation.constraints.AssertTrue; +import jakarta.validation.constraints.Size; +import java.io.Serializable; +import java.util.List; + +public class GenePanelDataMultipleStudyFilter implements Serializable { + + @Size(min = 0, max = PagingConstants.MAX_PAGE_SIZE) + private List sampleMolecularIdentifiers; + + @Size(min = 0, max = PagingConstants.MAX_PAGE_SIZE) + private List molecularProfileIds; + + @AssertTrue + private boolean isEitherMolecularProfileIdsOrSampleMolecularIdentifiersPresent() { + return molecularProfileIds != null ^ sampleMolecularIdentifiers != null; + } + + public List getSampleMolecularIdentifiers() { + return sampleMolecularIdentifiers; + } + + public void setSampleMolecularIdentifiers( + List sampleMolecularIdentifiers) { + this.sampleMolecularIdentifiers = sampleMolecularIdentifiers; + } + + public List getMolecularProfileIds() { + return molecularProfileIds; + } + + public void setMolecularProfileIds(List molecularProfileIds) { + this.molecularProfileIds = molecularProfileIds; + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/parameter/GenericAssayDataBinCountFilter.java b/src/main/java/org/cbioportal/legacy/web/parameter/GenericAssayDataBinCountFilter.java new file mode 100644 index 00000000000..752669f3840 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/parameter/GenericAssayDataBinCountFilter.java @@ -0,0 +1,18 @@ +package org.cbioportal.legacy.web.parameter; + +import java.io.Serializable; +import java.util.List; + +public class GenericAssayDataBinCountFilter extends DataBinCountFilter implements Serializable { + + private List genericAssayDataBinFilters; + + public List getGenericAssayDataBinFilters() { + return genericAssayDataBinFilters; + } + + public void setGenericAssayDataBinFilters( + List genericAssayDataBinFilters) { + this.genericAssayDataBinFilters = genericAssayDataBinFilters; + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/parameter/GenericAssayDataBinFilter.java b/src/main/java/org/cbioportal/legacy/web/parameter/GenericAssayDataBinFilter.java new file mode 100644 index 00000000000..d45812d9425 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/parameter/GenericAssayDataBinFilter.java @@ -0,0 +1,24 @@ +package org.cbioportal.legacy.web.parameter; + +import java.io.Serializable; + +public class GenericAssayDataBinFilter extends DataBinFilter implements Serializable { + private String stableId; + private String profileType; + + public String getStableId() { + return stableId; + } + + public void setStableId(String stableId) { + this.stableId = stableId; + } + + public String getProfileType() { + return profileType; + } + + public void setProfileType(String profileType) { + this.profileType = profileType; + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/parameter/GenericAssayDataCountFilter.java b/src/main/java/org/cbioportal/legacy/web/parameter/GenericAssayDataCountFilter.java new file mode 100644 index 00000000000..b7a8250e8a5 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/parameter/GenericAssayDataCountFilter.java @@ -0,0 +1,26 @@ +package org.cbioportal.legacy.web.parameter; + +import java.io.Serializable; +import java.util.List; + +public class GenericAssayDataCountFilter implements Serializable { + + private List genericAssayDataFilters; + private StudyViewFilter studyViewFilter; + + public List getGenericAssayDataFilters() { + return genericAssayDataFilters; + } + + public void setGenericAssayDataFilters(List genericAssayDataFilters) { + this.genericAssayDataFilters = genericAssayDataFilters; + } + + public StudyViewFilter getStudyViewFilter() { + return studyViewFilter; + } + + public void setStudyViewFilter(StudyViewFilter studyViewFilter) { + this.studyViewFilter = studyViewFilter; + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/parameter/GenericAssayDataFilter.java b/src/main/java/org/cbioportal/legacy/web/parameter/GenericAssayDataFilter.java new file mode 100644 index 00000000000..61c9f7476e5 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/parameter/GenericAssayDataFilter.java @@ -0,0 +1,31 @@ +package org.cbioportal.legacy.web.parameter; + +import java.io.Serializable; + +public class GenericAssayDataFilter extends DataFilter implements Serializable { + private String stableId; + private String profileType; + + public GenericAssayDataFilter() {} + + public GenericAssayDataFilter(String stableId, String profileType) { + this.stableId = stableId; + this.profileType = profileType; + } + + public String getStableId() { + return stableId; + } + + public void setStableId(String stableId) { + this.stableId = stableId; + } + + public String getProfileType() { + return profileType; + } + + public void setProfileType(String profileType) { + this.profileType = profileType; + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/parameter/GenericAssayDataMultipleStudyFilter.java b/src/main/java/org/cbioportal/legacy/web/parameter/GenericAssayDataMultipleStudyFilter.java new file mode 100644 index 00000000000..80e3c273444 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/parameter/GenericAssayDataMultipleStudyFilter.java @@ -0,0 +1,48 @@ +package org.cbioportal.legacy.web.parameter; + +import jakarta.validation.constraints.AssertTrue; +import jakarta.validation.constraints.Size; +import java.io.Serializable; +import java.util.List; + +public class GenericAssayDataMultipleStudyFilter implements Serializable { + + @Size(min = 1, max = PagingConstants.MAX_PAGE_SIZE) + private List sampleMolecularIdentifiers; + + @Size(min = 1, max = PagingConstants.MAX_PAGE_SIZE) + private List molecularProfileIds; + + @Size(min = 1, max = PagingConstants.MAX_PAGE_SIZE) + private List genericAssayStableIds; + + @AssertTrue + private boolean isEitherMolecularProfileIdsOrSampleMolecularIdentifiersPresent() { + return molecularProfileIds != null ^ sampleMolecularIdentifiers != null; + } + + public List getSampleMolecularIdentifiers() { + return sampleMolecularIdentifiers; + } + + public void setSampleMolecularIdentifiers( + List sampleMolecularIdentifiers) { + this.sampleMolecularIdentifiers = sampleMolecularIdentifiers; + } + + public List getMolecularProfileIds() { + return molecularProfileIds; + } + + public void setMolecularProfileIds(List molecularProfileIds) { + this.molecularProfileIds = molecularProfileIds; + } + + public List getGenericAssayStableIds() { + return genericAssayStableIds; + } + + public void setGenericAssayStableIds(List genericAssayStableIds) { + this.genericAssayStableIds = genericAssayStableIds; + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/parameter/GenericAssayFilter.java b/src/main/java/org/cbioportal/legacy/web/parameter/GenericAssayFilter.java new file mode 100644 index 00000000000..a9d85889205 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/parameter/GenericAssayFilter.java @@ -0,0 +1,45 @@ +package org.cbioportal.legacy.web.parameter; + +import jakarta.validation.constraints.AssertTrue; +import jakarta.validation.constraints.Size; +import java.util.List; + +public class GenericAssayFilter { + + @Size(min = 1, max = PagingConstants.MAX_PAGE_SIZE) + private List sampleIds; + + private String sampleListId; + + @Size(min = 1, max = PagingConstants.MAX_PAGE_SIZE) + private List genericAssayStableId; + + @AssertTrue + private boolean isEitherSampleListIdOrSampleIdsPresent() { + return sampleListId != null ^ sampleIds != null; + } + + public List getSampleIds() { + return sampleIds; + } + + public void setSampleIds(List sampleIds) { + this.sampleIds = sampleIds; + } + + public String getSampleListId() { + return sampleListId; + } + + public void setSampleListId(String sampleListId) { + this.sampleListId = sampleListId; + } + + public List getGenericAssayStableIds() { + return genericAssayStableId; + } + + public void setGenericAssayStableIds(List genericAssayStableId) { + this.genericAssayStableId = genericAssayStableId; + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/parameter/GenericAssayMetaFilter.java b/src/main/java/org/cbioportal/legacy/web/parameter/GenericAssayMetaFilter.java new file mode 100644 index 00000000000..4fc840cf163 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/parameter/GenericAssayMetaFilter.java @@ -0,0 +1,30 @@ +package org.cbioportal.legacy.web.parameter; + +import jakarta.validation.constraints.Size; +import java.io.Serializable; +import java.util.List; + +public class GenericAssayMetaFilter implements Serializable { + + @Size(min = 1, max = PagingConstants.MAX_PAGE_SIZE) + private List molecularProfileIds; + + @Size(min = 1, max = PagingConstants.MAX_PAGE_SIZE) + private List genericAssayStableIds; + + public List getMolecularProfileIds() { + return molecularProfileIds; + } + + public void setMolecularProfileIds(List molecularProfileIds) { + this.molecularProfileIds = molecularProfileIds; + } + + public List getGenericAssayStableIds() { + return genericAssayStableIds; + } + + public void setGenericAssayStableIds(List genericAssayStableIds) { + this.genericAssayStableIds = genericAssayStableIds; + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/parameter/GenesetDataFilterCriteria.java b/src/main/java/org/cbioportal/legacy/web/parameter/GenesetDataFilterCriteria.java new file mode 100644 index 00000000000..8cd2dffec99 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/parameter/GenesetDataFilterCriteria.java @@ -0,0 +1,43 @@ +package org.cbioportal.legacy.web.parameter; + +import java.util.List; + +/** + * Wrapper class for specifying filter criteria for GeneticData items in the GeneticDataController + * services. + * + * @author pieter + */ +public class GenesetDataFilterCriteria { + + // The list of identifiers for the gene sets of interest. + private List genesetIds; + // Identifier of pre-defined sample list with samples to query. E.g. brca_tcga_all + private String sampleListId; + // Full list of samples or patients to query, E.g. list with TCGA-AR-A1AR-01, TCGA-BH-A1EO-01... + private List sampleIds; + + public List getGenesetIds() { + return genesetIds; + } + + public void setGenesetIds(List genesetIds) { + this.genesetIds = genesetIds; + } + + public String getSampleListId() { + return sampleListId; + } + + public void setSampleListId(String sampleListId) { + this.sampleListId = sampleListId; + } + + public List getSampleIds() { + return sampleIds; + } + + public void setSampleIds(List sampleIds) { + this.sampleIds = sampleIds; + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/parameter/GenomicDataBinCountFilter.java b/src/main/java/org/cbioportal/legacy/web/parameter/GenomicDataBinCountFilter.java new file mode 100644 index 00000000000..c36184edcc0 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/parameter/GenomicDataBinCountFilter.java @@ -0,0 +1,17 @@ +package org.cbioportal.legacy.web.parameter; + +import java.io.Serializable; +import java.util.List; + +public class GenomicDataBinCountFilter extends DataBinCountFilter implements Serializable { + + private List genomicDataBinFilters; + + public List getGenomicDataBinFilters() { + return genomicDataBinFilters; + } + + public void setGenomicDataBinFilters(List genomicDataBinFilters) { + this.genomicDataBinFilters = genomicDataBinFilters; + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/parameter/GenomicDataBinFilter.java b/src/main/java/org/cbioportal/legacy/web/parameter/GenomicDataBinFilter.java new file mode 100644 index 00000000000..d2f6048a554 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/parameter/GenomicDataBinFilter.java @@ -0,0 +1,24 @@ +package org.cbioportal.legacy.web.parameter; + +import java.io.Serializable; + +public class GenomicDataBinFilter extends DataBinFilter implements Serializable { + private String hugoGeneSymbol; + private String profileType; + + public String getHugoGeneSymbol() { + return hugoGeneSymbol; + } + + public void setHugoGeneSymbol(String hugoGeneSymbol) { + this.hugoGeneSymbol = hugoGeneSymbol; + } + + public String getProfileType() { + return profileType; + } + + public void setProfileType(String profileType) { + this.profileType = profileType; + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/parameter/GenomicDataCountFilter.java b/src/main/java/org/cbioportal/legacy/web/parameter/GenomicDataCountFilter.java new file mode 100644 index 00000000000..64577431e28 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/parameter/GenomicDataCountFilter.java @@ -0,0 +1,26 @@ +package org.cbioportal.legacy.web.parameter; + +import java.io.Serializable; +import java.util.List; + +public class GenomicDataCountFilter implements Serializable { + + private List genomicDataFilters; + private StudyViewFilter studyViewFilter; + + public List getGenomicDataFilters() { + return genomicDataFilters; + } + + public void setGenomicDataFilters(List genomicDataFilters) { + this.genomicDataFilters = genomicDataFilters; + } + + public StudyViewFilter getStudyViewFilter() { + return studyViewFilter; + } + + public void setStudyViewFilter(StudyViewFilter studyViewFilter) { + this.studyViewFilter = studyViewFilter; + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/parameter/GenomicDataFilter.java b/src/main/java/org/cbioportal/legacy/web/parameter/GenomicDataFilter.java new file mode 100644 index 00000000000..7eaae6a6542 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/parameter/GenomicDataFilter.java @@ -0,0 +1,39 @@ +package org.cbioportal.legacy.web.parameter; + +import java.io.Serializable; +import java.util.List; + +public class GenomicDataFilter extends DataFilter implements Serializable { + private String hugoGeneSymbol; + private String profileType; + + public GenomicDataFilter() {} + + public GenomicDataFilter(String hugoGeneSymbol, String profileType) { + this.hugoGeneSymbol = hugoGeneSymbol; + this.profileType = profileType; + } + + public GenomicDataFilter( + String hugoGeneSymbol, String profileType, List values) { + this.hugoGeneSymbol = hugoGeneSymbol; + this.profileType = profileType; + this.setValues(values); + } + + public String getHugoGeneSymbol() { + return hugoGeneSymbol; + } + + public void setHugoGeneSymbol(String hugoGeneSymbol) { + this.hugoGeneSymbol = hugoGeneSymbol; + } + + public String getProfileType() { + return profileType; + } + + public void setProfileType(String profileType) { + this.profileType = profileType; + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/parameter/Group.java b/src/main/java/org/cbioportal/legacy/web/parameter/Group.java new file mode 100644 index 00000000000..cd651f0480b --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/parameter/Group.java @@ -0,0 +1,29 @@ +package org.cbioportal.legacy.web.parameter; + +import jakarta.validation.constraints.Size; +import java.io.Serializable; +import java.util.List; + +public class Group implements Serializable { + + @Size(min = 1, max = PagingConstants.MAX_PAGE_SIZE) + private List sampleIdentifiers; + + private String name; + + public List getSampleIdentifiers() { + return sampleIdentifiers; + } + + public void setSampleIdentifiers(List sampleIdentifiers) { + this.sampleIdentifiers = sampleIdentifiers; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/parameter/GroupFilter.java b/src/main/java/org/cbioportal/legacy/web/parameter/GroupFilter.java new file mode 100644 index 00000000000..a86bfa74c49 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/parameter/GroupFilter.java @@ -0,0 +1,21 @@ +package org.cbioportal.legacy.web.parameter; + +import jakarta.validation.Valid; +import jakarta.validation.constraints.Size; +import java.io.Serializable; +import java.util.List; + +public class GroupFilter implements Serializable { + + @Size(min = 2) + @Valid + private List groups; + + public List getGroups() { + return groups; + } + + public void setGroups(List groups) { + this.groups = groups; + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/parameter/HeaderKeyConstants.java b/src/main/java/org/cbioportal/legacy/web/parameter/HeaderKeyConstants.java new file mode 100644 index 00000000000..22ba8ef689e --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/parameter/HeaderKeyConstants.java @@ -0,0 +1,9 @@ +package org.cbioportal.legacy.web.parameter; + +/* When changing these edit them in portal/src/main/webapp/WEB-INF/web.xml as + * well to expose the CORS headers */ +public class HeaderKeyConstants { + + public static final String TOTAL_COUNT = "total-count"; + public static final String SAMPLE_COUNT = "sample-count"; +} diff --git a/src/main/java/org/cbioportal/legacy/web/parameter/MolecularDataFilter.java b/src/main/java/org/cbioportal/legacy/web/parameter/MolecularDataFilter.java new file mode 100644 index 00000000000..16fff57108f --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/parameter/MolecularDataFilter.java @@ -0,0 +1,45 @@ +package org.cbioportal.legacy.web.parameter; + +import jakarta.validation.constraints.AssertTrue; +import jakarta.validation.constraints.Size; +import java.util.List; + +public class MolecularDataFilter { + + @Size(min = 1, max = PagingConstants.MAX_PAGE_SIZE) + private List sampleIds; + + private String sampleListId; + + @Size(min = 1, max = PagingConstants.MAX_PAGE_SIZE) + private List entrezGeneIds; + + @AssertTrue + private boolean isEitherSampleListIdOrSampleIdsPresent() { + return sampleListId != null ^ sampleIds != null; + } + + public List getSampleIds() { + return sampleIds; + } + + public void setSampleIds(List sampleIds) { + this.sampleIds = sampleIds; + } + + public String getSampleListId() { + return sampleListId; + } + + public void setSampleListId(String sampleListId) { + this.sampleListId = sampleListId; + } + + public List getEntrezGeneIds() { + return entrezGeneIds; + } + + public void setEntrezGeneIds(List entrezGeneIds) { + this.entrezGeneIds = entrezGeneIds; + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/parameter/MolecularDataMultipleStudyFilter.java b/src/main/java/org/cbioportal/legacy/web/parameter/MolecularDataMultipleStudyFilter.java new file mode 100644 index 00000000000..35b1afd4e25 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/parameter/MolecularDataMultipleStudyFilter.java @@ -0,0 +1,48 @@ +package org.cbioportal.legacy.web.parameter; + +import jakarta.validation.constraints.AssertTrue; +import jakarta.validation.constraints.Size; +import java.io.Serializable; +import java.util.List; + +public class MolecularDataMultipleStudyFilter implements Serializable { + + @Size(min = 1, max = PagingConstants.MAX_PAGE_SIZE) + private List sampleMolecularIdentifiers; + + @Size(min = 1, max = PagingConstants.MAX_PAGE_SIZE) + private List molecularProfileIds; + + @Size(min = 1, max = PagingConstants.MAX_PAGE_SIZE) + private List entrezGeneIds; + + @AssertTrue + private boolean isEitherMolecularProfileIdsOrSampleMolecularIdentifiersPresent() { + return molecularProfileIds != null ^ sampleMolecularIdentifiers != null; + } + + public List getSampleMolecularIdentifiers() { + return sampleMolecularIdentifiers; + } + + public void setSampleMolecularIdentifiers( + List sampleMolecularIdentifiers) { + this.sampleMolecularIdentifiers = sampleMolecularIdentifiers; + } + + public List getMolecularProfileIds() { + return molecularProfileIds; + } + + public void setMolecularProfileIds(List molecularProfileIds) { + this.molecularProfileIds = molecularProfileIds; + } + + public List getEntrezGeneIds() { + return entrezGeneIds; + } + + public void setEntrezGeneIds(List entrezGeneIds) { + this.entrezGeneIds = entrezGeneIds; + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/parameter/MolecularProfileCasesGroupAndAlterationTypeFilter.java b/src/main/java/org/cbioportal/legacy/web/parameter/MolecularProfileCasesGroupAndAlterationTypeFilter.java new file mode 100644 index 00000000000..25046b21731 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/parameter/MolecularProfileCasesGroupAndAlterationTypeFilter.java @@ -0,0 +1,33 @@ +package org.cbioportal.legacy.web.parameter; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.Size; +import java.io.Serializable; +import java.util.List; +import org.cbioportal.legacy.model.AlterationFilter; + +public class MolecularProfileCasesGroupAndAlterationTypeFilter implements Serializable { + + private AlterationFilter alterationEventTypes; + + @Size(min = 1, max = PagingConstants.MAX_PAGE_SIZE) + @Schema + private List molecularProfileCasesGroupFilter; + + public List getMolecularProfileCasesGroupFilter() { + return this.molecularProfileCasesGroupFilter; + } + + public void setMolecularProfileCasesGroupFilter( + List molecularProfileCasesGroupFilter) { + this.molecularProfileCasesGroupFilter = molecularProfileCasesGroupFilter; + } + + public AlterationFilter getAlterationEventTypes() { + return this.alterationEventTypes; + } + + public void setAlterationEventTypes(AlterationFilter alterationEventTypes) { + this.alterationEventTypes = alterationEventTypes; + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/parameter/MolecularProfileCasesGroupFilter.java b/src/main/java/org/cbioportal/legacy/web/parameter/MolecularProfileCasesGroupFilter.java new file mode 100644 index 00000000000..91eeadd0705 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/parameter/MolecularProfileCasesGroupFilter.java @@ -0,0 +1,34 @@ +package org.cbioportal.legacy.web.parameter; + +import jakarta.validation.constraints.Size; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import org.cbioportal.legacy.model.MolecularProfileCaseIdentifier; + +public class MolecularProfileCasesGroupFilter { + + @Size(min = 1, max = PagingConstants.MAX_PAGE_SIZE) + private List MolecularProfileCaseIdentifiers; + + private String name; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public List getMolecularProfileCaseIdentifiers() { + return MolecularProfileCaseIdentifiers; + } + + public void setMolecularProfileCaseIdentifiers( + List molecularProfileCaseIdentifiers) { + + MolecularProfileCaseIdentifiers = + new ArrayList<>(new HashSet<>(molecularProfileCaseIdentifiers)); + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/parameter/MolecularProfileFilter.java b/src/main/java/org/cbioportal/legacy/web/parameter/MolecularProfileFilter.java new file mode 100644 index 00000000000..6ddc40fb3b4 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/parameter/MolecularProfileFilter.java @@ -0,0 +1,37 @@ +package org.cbioportal.legacy.web.parameter; + +import jakarta.validation.constraints.AssertTrue; +import jakarta.validation.constraints.Size; +import java.io.Serializable; +import java.util.List; +import java.util.Set; + +public class MolecularProfileFilter implements Serializable { + + @Size(min = 1, max = PagingConstants.MAX_PAGE_SIZE) + private List studyIds; + + @Size(min = 1, max = PagingConstants.MAX_PAGE_SIZE) + private Set molecularProfileIds; + + @AssertTrue + private boolean isEitherStudyIdsOrMolecularProfileIdsPresent() { + return studyIds != null ^ molecularProfileIds != null; + } + + public List getStudyIds() { + return studyIds; + } + + public void setStudyIds(List studyIds) { + this.studyIds = studyIds; + } + + public Set getMolecularProfileIds() { + return molecularProfileIds; + } + + public void setMolecularProfileIds(Set molecularProfileIds) { + this.molecularProfileIds = molecularProfileIds; + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/parameter/MutationDataFilter.java b/src/main/java/org/cbioportal/legacy/web/parameter/MutationDataFilter.java new file mode 100644 index 00000000000..5cf853ebc42 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/parameter/MutationDataFilter.java @@ -0,0 +1,53 @@ +package org.cbioportal.legacy.web.parameter; + +import static com.fasterxml.jackson.annotation.JsonInclude.Include.NON_NULL; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import jakarta.validation.constraints.NotNull; +import java.io.Serializable; +import java.util.List; + +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(NON_NULL) +public class MutationDataFilter implements Serializable { + private String hugoGeneSymbol; + private String profileType; + + @NotNull + private MutationOption categorization; // filter by either having mutations or by mutation types + + private List> values; + + public String getHugoGeneSymbol() { + return hugoGeneSymbol; + } + + public void setHugoGeneSymbol(String hugoGeneSymbol) { + this.hugoGeneSymbol = hugoGeneSymbol; + } + + public String getProfileType() { + return profileType; + } + + public void setProfileType(String profileType) { + this.profileType = profileType; + } + + public MutationOption getCategorization() { + return categorization; + } + + public void setCategorization(MutationOption categorization) { + this.categorization = categorization; + } + + public List> getValues() { + return values; + } + + public void setValues(List> values) { + this.values = values; + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/parameter/MutationFilter.java b/src/main/java/org/cbioportal/legacy/web/parameter/MutationFilter.java new file mode 100644 index 00000000000..5c8f24aba02 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/parameter/MutationFilter.java @@ -0,0 +1,45 @@ +package org.cbioportal.legacy.web.parameter; + +import jakarta.validation.constraints.AssertTrue; +import jakarta.validation.constraints.Size; +import java.util.List; + +public class MutationFilter { + + @Size(min = 1, max = PagingConstants.MAX_PAGE_SIZE) + private List sampleIds; + + private String sampleListId; + + @Size(min = 1, max = PagingConstants.MAX_PAGE_SIZE) + private List entrezGeneIds; + + @AssertTrue + private boolean isEitherSampleListIdOrSampleIdsPresent() { + return sampleListId != null ^ sampleIds != null; + } + + public List getSampleIds() { + return sampleIds; + } + + public void setSampleIds(List sampleIds) { + this.sampleIds = sampleIds; + } + + public String getSampleListId() { + return sampleListId; + } + + public void setSampleListId(String sampleListId) { + this.sampleListId = sampleListId; + } + + public List getEntrezGeneIds() { + return entrezGeneIds; + } + + public void setEntrezGeneIds(List entrezGeneIds) { + this.entrezGeneIds = entrezGeneIds; + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/parameter/MutationMultipleStudyFilter.java b/src/main/java/org/cbioportal/legacy/web/parameter/MutationMultipleStudyFilter.java new file mode 100644 index 00000000000..4d84698bc35 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/parameter/MutationMultipleStudyFilter.java @@ -0,0 +1,47 @@ +package org.cbioportal.legacy.web.parameter; + +import jakarta.validation.constraints.AssertTrue; +import jakarta.validation.constraints.Size; +import java.io.Serializable; +import java.util.List; + +public class MutationMultipleStudyFilter implements Serializable { + + @Size(min = 1, max = PagingConstants.MAX_PAGE_SIZE) + private List sampleMolecularIdentifiers; + + private List molecularProfileIds; + + @Size(min = 1, max = PagingConstants.MAX_PAGE_SIZE) + private List entrezGeneIds; + + @AssertTrue + private boolean isEitherMolecularProfileIdsOrSampleMolecularIdentifiersPresent() { + return molecularProfileIds != null ^ sampleMolecularIdentifiers != null; + } + + public List getSampleMolecularIdentifiers() { + return sampleMolecularIdentifiers; + } + + public void setSampleMolecularIdentifiers( + List sampleMolecularIdentifiers) { + this.sampleMolecularIdentifiers = sampleMolecularIdentifiers; + } + + public List getMolecularProfileIds() { + return molecularProfileIds; + } + + public void setMolecularProfileIds(List molecularProfileIds) { + this.molecularProfileIds = molecularProfileIds; + } + + public List getEntrezGeneIds() { + return entrezGeneIds; + } + + public void setEntrezGeneIds(List entrezGeneIds) { + this.entrezGeneIds = entrezGeneIds; + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/parameter/MutationOption.java b/src/main/java/org/cbioportal/legacy/web/parameter/MutationOption.java new file mode 100644 index 00000000000..6f0315abb0c --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/parameter/MutationOption.java @@ -0,0 +1,6 @@ +package org.cbioportal.legacy.web.parameter; + +public enum MutationOption { + MUTATED, // fetch mutation data with MUTATED, NOT_MUTATED, NOT_PROFILED in MutationFilterOption + MUTATION_TYPE // fetch mutation data with mutation types +} diff --git a/src/main/java/org/cbioportal/legacy/web/parameter/MutationPositionIdentifier.java b/src/main/java/org/cbioportal/legacy/web/parameter/MutationPositionIdentifier.java new file mode 100644 index 00000000000..85a038468b7 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/parameter/MutationPositionIdentifier.java @@ -0,0 +1,32 @@ +package org.cbioportal.legacy.web.parameter; + +public class MutationPositionIdentifier { + + private Integer entrezGeneId; + private Integer proteinPosStart; + private Integer proteinPosEnd; + + public Integer getEntrezGeneId() { + return entrezGeneId; + } + + public void setEntrezGeneId(Integer entrezGeneId) { + this.entrezGeneId = entrezGeneId; + } + + public Integer getProteinPosStart() { + return proteinPosStart; + } + + public void setProteinPosStart(Integer proteinPosStart) { + this.proteinPosStart = proteinPosStart; + } + + public Integer getProteinPosEnd() { + return proteinPosEnd; + } + + public void setProteinPosEnd(Integer proteinPosEnd) { + this.proteinPosEnd = proteinPosEnd; + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/parameter/MutationSpectrumFilter.java b/src/main/java/org/cbioportal/legacy/web/parameter/MutationSpectrumFilter.java new file mode 100644 index 00000000000..0dfcf19acfd --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/parameter/MutationSpectrumFilter.java @@ -0,0 +1,34 @@ +package org.cbioportal.legacy.web.parameter; + +import jakarta.validation.constraints.AssertTrue; +import jakarta.validation.constraints.Size; +import java.util.List; + +public class MutationSpectrumFilter { + + @Size(min = 1, max = PagingConstants.MAX_PAGE_SIZE) + private List sampleIds; + + private String sampleListId; + + @AssertTrue + private boolean isEitherSampleListIdOrSampleIdsPresent() { + return sampleListId != null ^ sampleIds != null; + } + + public List getSampleIds() { + return sampleIds; + } + + public void setSampleIds(List sampleIds) { + this.sampleIds = sampleIds; + } + + public String getSampleListId() { + return sampleListId; + } + + public void setSampleListId(String sampleListId) { + this.sampleListId = sampleListId; + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/parameter/NamespaceAttributeCountFilter.java b/src/main/java/org/cbioportal/legacy/web/parameter/NamespaceAttributeCountFilter.java new file mode 100644 index 00000000000..6b37f8f2d0a --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/parameter/NamespaceAttributeCountFilter.java @@ -0,0 +1,36 @@ +package org.cbioportal.legacy.web.parameter; + +import jakarta.validation.constraints.AssertTrue; +import jakarta.validation.constraints.Size; +import java.io.Serializable; +import java.util.List; +import org.cbioportal.legacy.model.NamespaceAttribute; + +public class NamespaceAttributeCountFilter implements Serializable { + + @Size(min = 1, max = PagingConstants.MAX_PAGE_SIZE) + private List sampleIdentifiers; + + private List namespaceAttributes; + + @AssertTrue + private boolean isBothSampleIdentifiersAndNamespaceAttributesPresent() { + return sampleIdentifiers != null && namespaceAttributes != null; + } + + public List getSampleIdentifiers() { + return sampleIdentifiers; + } + + public void setSampleIdentifiers(List sampleIdentifiers) { + this.sampleIdentifiers = sampleIdentifiers; + } + + public List getNamespaceAttributes() { + return namespaceAttributes; + } + + public void setNamespaceAttributes(List namespaceAttributes) { + this.namespaceAttributes = namespaceAttributes; + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/parameter/NamespaceComparisonFilter.java b/src/main/java/org/cbioportal/legacy/web/parameter/NamespaceComparisonFilter.java new file mode 100644 index 00000000000..c2272c4ff91 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/parameter/NamespaceComparisonFilter.java @@ -0,0 +1,45 @@ +package org.cbioportal.legacy.web.parameter; + +import jakarta.validation.constraints.AssertTrue; +import jakarta.validation.constraints.Size; +import java.io.Serializable; +import java.util.List; +import org.cbioportal.legacy.model.NamespaceAttribute; + +public class NamespaceComparisonFilter implements Serializable { + + @Size(min = 1, max = PagingConstants.MAX_PAGE_SIZE) + private List sampleIdentifiers; + + private NamespaceAttribute namespaceAttribute; + private List values; + + @AssertTrue + private boolean isBothSampleIdentifiersAndNamespaceAttributePresent() { + return sampleIdentifiers != null && namespaceAttribute != null; + } + + public List getSampleIdentifiers() { + return sampleIdentifiers; + } + + public void setSampleIdentifiers(List sampleIdentifiers) { + this.sampleIdentifiers = sampleIdentifiers; + } + + public NamespaceAttribute getNamespaceAttribute() { + return namespaceAttribute; + } + + public void setNamespaceAttribute(NamespaceAttribute namespaceAttribute) { + this.namespaceAttribute = namespaceAttribute; + } + + public List getValues() { + return values; + } + + public void setValues(List values) { + this.values = values; + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/parameter/NamespaceDataCountFilter.java b/src/main/java/org/cbioportal/legacy/web/parameter/NamespaceDataCountFilter.java new file mode 100644 index 00000000000..c58da61bcab --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/parameter/NamespaceDataCountFilter.java @@ -0,0 +1,26 @@ +package org.cbioportal.legacy.web.parameter; + +import java.io.Serializable; +import java.util.List; + +public class NamespaceDataCountFilter implements Serializable { + + private List attributes; + private StudyViewFilter studyViewFilter; + + public List getAttributes() { + return attributes; + } + + public void setAttributes(List attributes) { + this.attributes = attributes; + } + + public StudyViewFilter getStudyViewFilter() { + return studyViewFilter; + } + + public void setStudyViewFilter(StudyViewFilter studyViewFilter) { + this.studyViewFilter = studyViewFilter; + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/parameter/NamespaceDataFilter.java b/src/main/java/org/cbioportal/legacy/web/parameter/NamespaceDataFilter.java new file mode 100644 index 00000000000..e9d1c74e465 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/parameter/NamespaceDataFilter.java @@ -0,0 +1,35 @@ +package org.cbioportal.legacy.web.parameter; + +import java.io.Serializable; +import java.util.List; + +public class NamespaceDataFilter implements Serializable { + + private String outerKey; + private String innerKey; + private List> values; + + public List> getValues() { + return values; + } + + public void setValues(List> values) { + this.values = values; + } + + public String getOuterKey() { + return outerKey; + } + + public void setOuterKey(String outerKey) { + this.outerKey = outerKey; + } + + public String getInnerKey() { + return innerKey; + } + + public void setInnerKey(String innerKey) { + this.innerKey = innerKey; + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/parameter/OccurrencePosition.java b/src/main/java/org/cbioportal/legacy/web/parameter/OccurrencePosition.java new file mode 100644 index 00000000000..b8239c20b47 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/parameter/OccurrencePosition.java @@ -0,0 +1,6 @@ +package org.cbioportal.legacy.web.parameter; + +public enum OccurrencePosition { + FIRST, + LAST +} diff --git a/src/main/java/org/cbioportal/legacy/web/parameter/PageSettings.java b/src/main/java/org/cbioportal/legacy/web/parameter/PageSettings.java new file mode 100644 index 00000000000..93563d7c1bb --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/parameter/PageSettings.java @@ -0,0 +1,43 @@ +package org.cbioportal.legacy.web.parameter; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.databind.ObjectMapper; +import java.io.IOException; +import org.cbioportal.legacy.utils.removeme.Session; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class PageSettings extends Session { + + private final Logger LOG = LoggerFactory.getLogger(PageSettings.class); + private PageSettingsData data; + + @Override + public void setData(Object data) { + ObjectMapper mapper = new ObjectMapper(); + try { + this.data = mapper.readValue(mapper.writeValueAsString(data), PageSettingsData.class); + } catch (IOException e) { + LOG.error("Error occurred", e); + } + } + + @Override + public PageSettingsData getData() { + return data; + } + + @JsonIgnore + @Override + public String getSource() { + return super.getSource(); + } + + @JsonIgnore + @Override + public SessionType getType() { + return super.getType(); + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/parameter/PageSettingsData.java b/src/main/java/org/cbioportal/legacy/web/parameter/PageSettingsData.java new file mode 100644 index 00000000000..70b83a4a3a1 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/parameter/PageSettingsData.java @@ -0,0 +1,70 @@ +package org.cbioportal.legacy.web.parameter; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonInclude.Include; +import com.fasterxml.jackson.annotation.JsonSubTypes; +import com.fasterxml.jackson.annotation.JsonTypeInfo; +import jakarta.validation.constraints.NotNull; +import java.io.Serializable; +import java.util.Set; + +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonTypeInfo( + use = JsonTypeInfo.Id.NAME, + include = JsonTypeInfo.As.EXISTING_PROPERTY, + property = "page", + visible = true) +@JsonSubTypes({ + @JsonSubTypes.Type(value = ResultsPageSettings.class, name = "results_view"), + @JsonSubTypes.Type(value = StudyPageSettings.class, name = "study_view") +}) +@JsonInclude(Include.NON_NULL) +public abstract class PageSettingsData implements Serializable { + + @NotNull private SessionPage page; + private String owner = "anonymous"; + @NotNull private Set origin; + private Long created = System.currentTimeMillis(); + private Long lastUpdated = System.currentTimeMillis(); + + public SessionPage getPage() { + return page; + } + + public void setPage(SessionPage page) { + this.page = page; + } + + public String getOwner() { + return owner; + } + + public void setOwner(String owner) { + this.owner = owner; + } + + public void setOrigin(Set origin) { + this.origin = origin; + } + + public Long getCreated() { + return created; + } + + public void setCreated(Long created) { + this.created = created; + } + + public Long getLastUpdated() { + return lastUpdated; + } + + public void setLastUpdated(Long lastUpdated) { + this.lastUpdated = lastUpdated; + } + + public Set getOrigin() { + return this.origin; + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/parameter/PageSettingsIdentifier.java b/src/main/java/org/cbioportal/legacy/web/parameter/PageSettingsIdentifier.java new file mode 100644 index 00000000000..5b0a8c89a41 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/parameter/PageSettingsIdentifier.java @@ -0,0 +1,31 @@ +package org.cbioportal.legacy.web.parameter; + +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Size; +import java.io.Serializable; +import java.util.Set; + +public class PageSettingsIdentifier implements Serializable { + + @NotNull private SessionPage page; + + @Size(min = 1, max = PagingConstants.MAX_PAGE_SIZE) + // type of it should be similar to PageSettingsData -> origin + Set origin; + + public SessionPage getPage() { + return page; + } + + public void setPage(SessionPage page) { + this.page = page; + } + + public Set getOrigin() { + return origin; + } + + public void setOrigin(Set origin) { + this.origin = origin; + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/parameter/PagingConstants.java b/src/main/java/org/cbioportal/legacy/web/parameter/PagingConstants.java new file mode 100644 index 00000000000..e58ea76fbe2 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/parameter/PagingConstants.java @@ -0,0 +1,14 @@ +package org.cbioportal.legacy.web.parameter; + +public class PagingConstants { + + public static final String DEFAULT_PAGE_SIZE = "10000000"; + public static final int MAX_PAGE_SIZE = 10000000; + public static final int MIN_PAGE_SIZE = 1; + + public static final String DEFAULT_NO_PAGING_PAGE_SIZE = "0"; + public static final int NO_PAGING_PAGE_SIZE = 0; + + public static final String DEFAULT_PAGE_NUMBER = "0"; + public static final int MIN_PAGE_NUMBER = 0; +} diff --git a/src/main/java/org/cbioportal/legacy/web/parameter/PatientFilter.java b/src/main/java/org/cbioportal/legacy/web/parameter/PatientFilter.java new file mode 100644 index 00000000000..7749fd6e797 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/parameter/PatientFilter.java @@ -0,0 +1,36 @@ +package org.cbioportal.legacy.web.parameter; + +import jakarta.validation.constraints.AssertTrue; +import jakarta.validation.constraints.Size; +import java.io.Serializable; +import java.util.List; + +public class PatientFilter implements Serializable { + + @Size(min = 1, max = PagingConstants.MAX_PAGE_SIZE) + private List patientIdentifiers; + + @Size(min = 1, max = PagingConstants.MAX_PAGE_SIZE) + private List uniquePatientKeys; + + @AssertTrue + private boolean isEitherPatientIdentifiersOrUniquePatientKeysPresent() { + return patientIdentifiers != null ^ uniquePatientKeys != null; + } + + public List getPatientIdentifiers() { + return patientIdentifiers; + } + + public void setPatientIdentifiers(List patientIdentifiers) { + this.patientIdentifiers = patientIdentifiers; + } + + public List getUniquePatientKeys() { + return uniquePatientKeys; + } + + public void setUniquePatientKeys(List uniquePatientKeys) { + this.uniquePatientKeys = uniquePatientKeys; + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/parameter/PatientIdentifier.java b/src/main/java/org/cbioportal/legacy/web/parameter/PatientIdentifier.java new file mode 100644 index 00000000000..ec325ef1862 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/parameter/PatientIdentifier.java @@ -0,0 +1,25 @@ +package org.cbioportal.legacy.web.parameter; + +import java.io.Serializable; + +public class PatientIdentifier implements Serializable { + + private String patientId; + private String studyId; + + public String getPatientId() { + return patientId; + } + + public void setPatientId(String patientId) { + this.patientId = patientId; + } + + public String getStudyId() { + return studyId; + } + + public void setStudyId(String studyId) { + this.studyId = studyId; + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/parameter/Projection.java b/src/main/java/org/cbioportal/legacy/web/parameter/Projection.java new file mode 100644 index 00000000000..905df36b1b4 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/parameter/Projection.java @@ -0,0 +1,8 @@ +package org.cbioportal.legacy.web.parameter; + +public enum Projection { + ID, + SUMMARY, + DETAILED, + META +} diff --git a/src/main/java/org/cbioportal/legacy/web/parameter/ResultsPageSettings.java b/src/main/java/org/cbioportal/legacy/web/parameter/ResultsPageSettings.java new file mode 100644 index 00000000000..059aa5150ee --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/parameter/ResultsPageSettings.java @@ -0,0 +1,27 @@ +package org.cbioportal.legacy.web.parameter; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonInclude.Include; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(Include.ALWAYS) +public class ResultsPageSettings extends PageSettingsData implements Serializable { + + /** + * Configuration of clinical tracks Use lowercase instead of camelCase to be compatible with url + * query param + */ + private List clinicallist = new ArrayList<>(); + + public List getClinicallist() { + return clinicallist; + } + + public void setClinicallist(List clinicallist) { + this.clinicallist = clinicallist; + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/parameter/SampleFilter.java b/src/main/java/org/cbioportal/legacy/web/parameter/SampleFilter.java new file mode 100644 index 00000000000..b4a1222d8f7 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/parameter/SampleFilter.java @@ -0,0 +1,48 @@ +package org.cbioportal.legacy.web.parameter; + +import jakarta.validation.constraints.AssertTrue; +import jakarta.validation.constraints.Size; +import java.io.Serializable; +import java.util.List; +import org.cbioportal.legacy.web.SampleController; + +public class SampleFilter implements Serializable { + + @Size(min = 1, max = SampleController.SAMPLE_MAX_PAGE_SIZE) + private List sampleIdentifiers; + + @Size(min = 1, max = PagingConstants.MAX_PAGE_SIZE) + private List sampleListIds; + + @Size(min = 1, max = SampleController.SAMPLE_MAX_PAGE_SIZE) + private List uniqueSampleKeys; + + @AssertTrue + private boolean isOnlyOneTypeOfFilterPresent() { + return sampleIdentifiers != null ^ sampleListIds != null ^ uniqueSampleKeys != null; + } + + public List getSampleIdentifiers() { + return sampleIdentifiers; + } + + public void setSampleIdentifiers(List sampleIdentifiers) { + this.sampleIdentifiers = sampleIdentifiers; + } + + public List getSampleListIds() { + return sampleListIds; + } + + public void setSampleListIds(List sampleListIds) { + this.sampleListIds = sampleListIds; + } + + public List getUniqueSampleKeys() { + return uniqueSampleKeys; + } + + public void setUniqueSampleKeys(List uniqueSampleKeys) { + this.uniqueSampleKeys = uniqueSampleKeys; + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/parameter/SampleIdentifier.java b/src/main/java/org/cbioportal/legacy/web/parameter/SampleIdentifier.java new file mode 100644 index 00000000000..4530439becd --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/parameter/SampleIdentifier.java @@ -0,0 +1,46 @@ +package org.cbioportal.legacy.web.parameter; + +import java.io.Serializable; +import java.util.Objects; + +public class SampleIdentifier implements Serializable { + + private String sampleId; + private String studyId; + + public String getSampleId() { + return sampleId; + } + + public void setSampleId(String sampleId) { + this.sampleId = sampleId; + } + + public String getStudyId() { + return studyId; + } + + public void setStudyId(String studyId) { + this.studyId = studyId; + } + + @Override + public String toString() { + return getSampleId() + getStudyId(); + } + + @Override + public boolean equals(Object o) { + if (o == this) return true; + if (!(o instanceof SampleIdentifier)) { + return false; + } + SampleIdentifier user = (SampleIdentifier) o; + return Objects.equals(sampleId, user.sampleId) && Objects.equals(studyId, user.studyId); + } + + @Override + public int hashCode() { + return Objects.hash(sampleId, studyId); + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/parameter/SampleMolecularIdentifier.java b/src/main/java/org/cbioportal/legacy/web/parameter/SampleMolecularIdentifier.java new file mode 100644 index 00000000000..847b183a09e --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/parameter/SampleMolecularIdentifier.java @@ -0,0 +1,25 @@ +package org.cbioportal.legacy.web.parameter; + +import java.io.Serializable; + +public class SampleMolecularIdentifier implements Serializable { + + private String sampleId; + private String molecularProfileId; + + public String getSampleId() { + return sampleId; + } + + public void setSampleId(String sampleId) { + this.sampleId = sampleId; + } + + public String getMolecularProfileId() { + return molecularProfileId; + } + + public void setMolecularProfileId(String molecularProfileId) { + this.molecularProfileId = molecularProfileId; + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/parameter/SessionPage.java b/src/main/java/org/cbioportal/legacy/web/parameter/SessionPage.java new file mode 100644 index 00000000000..e8e6848d438 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/parameter/SessionPage.java @@ -0,0 +1,6 @@ +package org.cbioportal.legacy.web.parameter; + +public enum SessionPage { + results_view, + study_view; +} diff --git a/src/main/java/org/cbioportal/legacy/web/parameter/StructuralVariantFilter.java b/src/main/java/org/cbioportal/legacy/web/parameter/StructuralVariantFilter.java new file mode 100644 index 00000000000..a7e8e8323ec --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/parameter/StructuralVariantFilter.java @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2018 The Hyve B.V. + * This code is licensed under the GNU Affero General Public License (AGPL), + * version 3, or (at your option) any later version. + */ + +/* + * This file is part of cBioPortal. + * + * cBioPortal is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package org.cbioportal.legacy.web.parameter; + +import jakarta.validation.Valid; +import jakarta.validation.constraints.AssertTrue; +import jakarta.validation.constraints.Size; +import java.io.Serializable; +import java.util.List; +import org.apache.commons.collections4.CollectionUtils; +import org.cbioportal.legacy.model.StructuralVariantQuery; + +public class StructuralVariantFilter implements Serializable { + + @Size(max = PagingConstants.MAX_PAGE_SIZE) + private List sampleMolecularIdentifiers; + + @Size(max = PagingConstants.MAX_PAGE_SIZE) + private List molecularProfileIds; + + @Size(max = PagingConstants.MAX_PAGE_SIZE) + private List entrezGeneIds; + + @Valid + @Size(max = PagingConstants.MAX_PAGE_SIZE) + private List structuralVariantQueries; + + @AssertTrue + private boolean isEitherMolecularProfileIdsOrSampleMolecularIdentifiersPresent() { + return !CollectionUtils.isEmpty(molecularProfileIds) + ^ !CollectionUtils.isEmpty(sampleMolecularIdentifiers); + } + + public List getMolecularProfileIds() { + return molecularProfileIds; + } + + public void setMolecularProfileIds(List molecularProfileIds) { + this.molecularProfileIds = molecularProfileIds; + } + + public List getEntrezGeneIds() { + return entrezGeneIds; + } + + public void setEntrezGeneIds(List entrezGeneIds) { + this.entrezGeneIds = entrezGeneIds; + } + + public List getSampleMolecularIdentifiers() { + return sampleMolecularIdentifiers; + } + + public void setSampleMolecularIdentifiers( + List sampleMolecularIdentifiers) { + this.sampleMolecularIdentifiers = sampleMolecularIdentifiers; + } + + public List getStructuralVariantQueries() { + return structuralVariantQueries; + } + + public void setStructuralVariantQueries(List structuralVariantQueries) { + this.structuralVariantQueries = structuralVariantQueries; + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/parameter/StudyPageSettings.java b/src/main/java/org/cbioportal/legacy/web/parameter/StudyPageSettings.java new file mode 100644 index 00000000000..1b33babe37b --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/parameter/StudyPageSettings.java @@ -0,0 +1,34 @@ +package org.cbioportal.legacy.web.parameter; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonInclude.Include; +import java.io.Serializable; +import java.util.Map; + +/** + * @author kalletlak + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(Include.NON_NULL) +public class StudyPageSettings extends PageSettingsData implements Serializable { + + private Object chartSettings; + private Map groupColors; + + public Object getChartSettings() { + return chartSettings; + } + + public void setChartSettings(Object chartSettings) { + this.chartSettings = chartSettings; + } + + public Map getGroupColors() { + return groupColors; + } + + public void setGroupColors(Map groupColors) { + this.groupColors = groupColors; + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/parameter/StudyViewFilter.java b/src/main/java/org/cbioportal/legacy/web/parameter/StudyViewFilter.java new file mode 100644 index 00000000000..1dbf3c267d0 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/parameter/StudyViewFilter.java @@ -0,0 +1,266 @@ +package org.cbioportal.legacy.web.parameter; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonInclude.Include; +import jakarta.validation.Valid; +import jakarta.validation.constraints.AssertTrue; +import jakarta.validation.constraints.Size; +import java.io.Serializable; +import java.util.HashSet; +import java.util.List; +import java.util.Objects; +import java.util.Set; +import java.util.stream.Collectors; +import org.cbioportal.legacy.model.AlterationFilter; +import org.cbioportal.legacy.model.GeneFilter; +import org.cbioportal.legacy.model.StudyViewStructuralVariantFilter; +import org.cbioportal.legacy.web.parameter.filter.AndedPatientTreatmentFilters; +import org.cbioportal.legacy.web.parameter.filter.AndedSampleTreatmentFilters; + +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(Include.NON_NULL) +public class StudyViewFilter implements Serializable { + + @Size(min = 1) + private List sampleIdentifiers; + + @Size(min = 1) + private List studyIds; + + private List clinicalDataFilters; + private List geneFilters; + @Valid private List structuralVariantFilters; + private AndedSampleTreatmentFilters sampleTreatmentFilters; + private AndedSampleTreatmentFilters sampleTreatmentGroupFilters; + private AndedSampleTreatmentFilters sampleTreatmentTargetFilters; + private AndedPatientTreatmentFilters patientTreatmentFilters; + private AndedPatientTreatmentFilters patientTreatmentGroupFilters; + private AndedPatientTreatmentFilters patientTreatmentTargetFilters; + private List> genomicProfiles; + private List genomicDataFilters; + private List genericAssayDataFilters; + private List> caseLists; + private List customDataFilters; + private AlterationFilter alterationFilter; + private List clinicalEventFilters; + private List mutationDataFilters; + private List namespaceDataFilters; + + @AssertTrue + private boolean isEitherSampleIdentifiersOrStudyIdsPresent() { + return sampleIdentifiers != null ^ studyIds != null; + } + + @AssertTrue + private boolean isEitherValueOrRangePresentInClinicalDataIntervalFilters() { + return validateDataFilters(clinicalDataFilters); + } + + @AssertTrue + private boolean isEitherValueOrRangePresentInGenomicDataIntervalFilters() { + return validateDataFilters(genomicDataFilters); + } + + @AssertTrue + private boolean isEitherValueOrRangePresentInGenericAssayDataIntervalFilters() { + return validateDataFilters(genericAssayDataFilters); + } + + @AssertTrue + private boolean isEitherValueOrRangePresentInCustomDataFilters() { + return validateDataFilters(customDataFilters); + } + + private boolean validateDataFilters(List dataFilters) { + long invalidCount = 0; + + if (dataFilters != null) { + invalidCount = + dataFilters.stream() + .flatMap(f -> f.getValues().stream()) + .filter(Objects::nonNull) + .filter(v -> v.getValue() != null == (v.getStart() != null || v.getEnd() != null)) + .count(); + } + + return invalidCount == 0; + } + + public List getSampleIdentifiers() { + return sampleIdentifiers; + } + + public void setSampleIdentifiers(List sampleIdentifiers) { + this.sampleIdentifiers = sampleIdentifiers; + } + + public List getStudyIds() { + return studyIds; + } + + public void setStudyIds(List studyIds) { + this.studyIds = studyIds; + } + + public Set getUniqueStudyIds() { + Set uniqueStudyIds = new HashSet<>(); + if (sampleIdentifiers != null && !sampleIdentifiers.isEmpty()) { + uniqueStudyIds.addAll( + sampleIdentifiers.stream().map(SampleIdentifier::getStudyId).collect(Collectors.toSet())); + } + if (studyIds != null && !studyIds.isEmpty()) { + uniqueStudyIds.addAll(studyIds); + } + return uniqueStudyIds; + } + + public List getClinicalDataFilters() { + return clinicalDataFilters; + } + + public void setClinicalDataFilters(List clinicalDataFilters) { + this.clinicalDataFilters = clinicalDataFilters; + } + + public List getGeneFilters() { + return geneFilters; + } + + public void setGeneFilters(List geneFilters) { + this.geneFilters = geneFilters; + } + + public List getStructuralVariantFilters() { + return structuralVariantFilters; + } + + public void setStructuralVariantFilters( + List structuralVariantFilters) { + this.structuralVariantFilters = structuralVariantFilters; + } + + public List> getGenomicProfiles() { + return genomicProfiles; + } + + public void setGenomicProfiles(List> genomicProfiles) { + this.genomicProfiles = genomicProfiles; + } + + public List getGenomicDataFilters() { + return genomicDataFilters; + } + + public void setGenomicDataFilters(List genomicDataFilters) { + this.genomicDataFilters = genomicDataFilters; + } + + public AndedSampleTreatmentFilters getSampleTreatmentFilters() { + return sampleTreatmentFilters; + } + + public void setSampleTreatmentFilters(AndedSampleTreatmentFilters sampleTreatmentFilters) { + this.sampleTreatmentFilters = sampleTreatmentFilters; + } + + public AndedPatientTreatmentFilters getPatientTreatmentFilters() { + return patientTreatmentFilters; + } + + public void setPatientTreatmentFilters(AndedPatientTreatmentFilters patientTreatmentFilters) { + this.patientTreatmentFilters = patientTreatmentFilters; + } + + public List> getCaseLists() { + return caseLists; + } + + public void setCaseLists(List> caseLists) { + this.caseLists = caseLists; + } + + public List getGenericAssayDataFilters() { + return genericAssayDataFilters; + } + + public void setGenericAssayDataFilters(List genericAssayDataFilters) { + this.genericAssayDataFilters = genericAssayDataFilters; + } + + public List getCustomDataFilters() { + return customDataFilters; + } + + public void setCustomDataFilters(List customDataFilters) { + this.customDataFilters = customDataFilters; + } + + public AlterationFilter getAlterationFilter() { + return alterationFilter; + } + + public void setAlterationFilter(AlterationFilter alterationFilter) { + this.alterationFilter = alterationFilter; + } + + public AndedSampleTreatmentFilters getSampleTreatmentGroupFilters() { + return sampleTreatmentGroupFilters; + } + + public void setSampleTreatmentGroupFilters( + AndedSampleTreatmentFilters sampleTreatmentGroupFilters) { + this.sampleTreatmentGroupFilters = sampleTreatmentGroupFilters; + } + + public AndedPatientTreatmentFilters getPatientTreatmentGroupFilters() { + return patientTreatmentGroupFilters; + } + + public void setPatientTreatmentGroupFilters( + AndedPatientTreatmentFilters patientTreatmentGroupFilters) { + this.patientTreatmentGroupFilters = patientTreatmentGroupFilters; + } + + public AndedSampleTreatmentFilters getSampleTreatmentTargetFilters() { + return sampleTreatmentTargetFilters; + } + + public void setSampleTreatmentTargetFilters( + AndedSampleTreatmentFilters sampleTreatmentTargetFilters) { + this.sampleTreatmentTargetFilters = sampleTreatmentTargetFilters; + } + + public AndedPatientTreatmentFilters getPatientTreatmentTargetFilters() { + return patientTreatmentTargetFilters; + } + + public void setPatientTreatmentTargetFilters( + AndedPatientTreatmentFilters patientTreatmentTagetFilters) { + this.patientTreatmentTargetFilters = patientTreatmentTagetFilters; + } + + public List getClinicalEventFilters() { + return clinicalEventFilters; + } + + public void setClinicalEventFilters(List clinicalEventFilters) { + this.clinicalEventFilters = clinicalEventFilters; + } + + public List getMutationDataFilters() { + return mutationDataFilters; + } + + public void setMutationDataFilters(List mutationDataFilters) { + this.mutationDataFilters = mutationDataFilters; + } + + public List getNamespaceDataFilters() { + return namespaceDataFilters; + } + + public void setNamespaceDataFilters(List namespaceDataFilters) { + this.namespaceDataFilters = namespaceDataFilters; + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/parameter/SurvivalRequest.java b/src/main/java/org/cbioportal/legacy/web/parameter/SurvivalRequest.java new file mode 100644 index 00000000000..25dd3b13b20 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/parameter/SurvivalRequest.java @@ -0,0 +1,64 @@ +package org.cbioportal.legacy.web.parameter; + +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Size; +import java.io.Serializable; +import java.util.List; + +public class SurvivalRequest implements Serializable { + + @Size(min = 1, max = PagingConstants.MAX_PAGE_SIZE) + private List patientIdentifiers; + + @NotNull private String attributeIdPrefix; + + @Valid private ClinicalEventRequestIdentifier startEventRequestIdentifier; + + @Valid private ClinicalEventRequestIdentifier endEventRequestIdentifier; + + @Valid private ClinicalEventRequestIdentifier censoredEventRequestIdentifier; + + public List getPatientIdentifiers() { + return patientIdentifiers; + } + + public void setPatientIdentifiers(List patientIdentifiers) { + this.patientIdentifiers = patientIdentifiers; + } + + public String getAttributeIdPrefix() { + return attributeIdPrefix; + } + + public void setAttributeIdPrefix(String attributeIdPrefix) { + this.attributeIdPrefix = attributeIdPrefix; + } + + public ClinicalEventRequestIdentifier getStartEventRequestIdentifier() { + return startEventRequestIdentifier; + } + + public void setStartEventRequestIdentifier( + ClinicalEventRequestIdentifier startEventRequestIdentifier) { + this.startEventRequestIdentifier = startEventRequestIdentifier; + } + + public ClinicalEventRequestIdentifier getEndEventRequestIdentifier() { + return endEventRequestIdentifier; + } + + public void setEndEventRequestIdentifier( + ClinicalEventRequestIdentifier endEventRequestIdentifier) { + this.endEventRequestIdentifier = endEventRequestIdentifier; + } + + public ClinicalEventRequestIdentifier getCensoredEventRequestIdentifier() { + return censoredEventRequestIdentifier; + } + + public void setCensoredEventRequestIdentifier( + ClinicalEventRequestIdentifier censoredEventRequestIdentifier) { + this.censoredEventRequestIdentifier = censoredEventRequestIdentifier; + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/parameter/VariantCountIdentifier.java b/src/main/java/org/cbioportal/legacy/web/parameter/VariantCountIdentifier.java new file mode 100644 index 00000000000..612a79423cf --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/parameter/VariantCountIdentifier.java @@ -0,0 +1,23 @@ +package org.cbioportal.legacy.web.parameter; + +public class VariantCountIdentifier { + + private Integer entrezGeneId; + private String keyword; + + public Integer getEntrezGeneId() { + return entrezGeneId; + } + + public void setEntrezGeneId(Integer entrezGeneId) { + this.entrezGeneId = entrezGeneId; + } + + public String getKeyword() { + return keyword; + } + + public void setKeyword(String keyword) { + this.keyword = keyword; + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/parameter/VirtualStudy.java b/src/main/java/org/cbioportal/legacy/web/parameter/VirtualStudy.java new file mode 100644 index 00000000000..6d1be2239fc --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/parameter/VirtualStudy.java @@ -0,0 +1,43 @@ +package org.cbioportal.legacy.web.parameter; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.databind.ObjectMapper; +import java.io.IOException; +import org.cbioportal.legacy.utils.removeme.Session; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class VirtualStudy extends Session { + + private final Logger LOG = LoggerFactory.getLogger(VirtualStudy.class); + private VirtualStudyData data; + + @Override + public void setData(Object data) { + ObjectMapper mapper = new ObjectMapper(); + try { + this.data = mapper.readValue(mapper.writeValueAsString(data), VirtualStudyData.class); + } catch (IOException e) { + LOG.error("Error occurred", e); + } + } + + @Override + public VirtualStudyData getData() { + return data; + } + + @JsonIgnore + @Override + public String getSource() { + return super.getSource(); + } + + @JsonIgnore + @Override + public SessionType getType() { + return super.getType(); + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/parameter/VirtualStudyData.java b/src/main/java/org/cbioportal/legacy/web/parameter/VirtualStudyData.java new file mode 100644 index 00000000000..67032e86603 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/parameter/VirtualStudyData.java @@ -0,0 +1,134 @@ +package org.cbioportal.legacy.web.parameter; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import java.io.Serializable; +import java.util.HashSet; +import java.util.Set; +import java.util.stream.Collectors; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class VirtualStudyData implements Serializable { + + private String name; + private String description; + private Set studies; + private StudyViewFilter studyViewFilter; + private Float version = 1.0f; + private String owner = "anonymous"; + private Set origin = new HashSet<>(); + private Long created = System.currentTimeMillis(); + private Long lastUpdated = System.currentTimeMillis(); + private Set users = new HashSet<>(); + + private String typeOfCancerId; + private String pmid; + + private Boolean dynamic; + + public String getOwner() { + return owner; + } + + public void setOwner(String owner) { + this.owner = owner; + } + + public void setOrigin(Set origin) { + this.origin = origin; + } + + public Long getCreated() { + return created; + } + + public void setCreated(Long created) { + this.created = created; + } + + public Long getLastUpdated() { + return lastUpdated; + } + + public void setLastUpdated(Long lastUpdated) { + this.lastUpdated = lastUpdated; + } + + public Set getUsers() { + return users; + } + + public void setUsers(Set users) { + this.users = users; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public Set getStudies() { + return studies; + } + + public void setStudies(Set studies) { + this.studies = studies; + } + + public Set getOrigin() { + if (this.origin == null || this.origin.size() == 0) { + return studies.stream().map(map -> map.getId()).collect(Collectors.toSet()); + } + return this.origin; + } + + public Float getVersion() { + return version; + } + + public void setVersion(Float version) { + this.version = version; + } + + public StudyViewFilter getStudyViewFilter() { + return studyViewFilter; + } + + public void setStudyViewFilter(StudyViewFilter studyViewFilter) { + this.studyViewFilter = studyViewFilter; + } + + public String getTypeOfCancerId() { + return typeOfCancerId; + } + + public void setTypeOfCancerId(String typeOfCancerId) { + this.typeOfCancerId = typeOfCancerId; + } + + public String getPmid() { + return pmid; + } + + public void setPmid(String pmid) { + this.pmid = pmid; + } + + public Boolean getDynamic() { + return dynamic; + } + + public void setDynamic(Boolean dynamic) { + this.dynamic = dynamic; + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/parameter/VirtualStudySamples.java b/src/main/java/org/cbioportal/legacy/web/parameter/VirtualStudySamples.java new file mode 100644 index 00000000000..bbe1d1ba675 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/parameter/VirtualStudySamples.java @@ -0,0 +1,25 @@ +package org.cbioportal.legacy.web.parameter; + +import java.util.Set; + +public class VirtualStudySamples { + + private String id; + private Set samples; + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public Set getSamples() { + return samples; + } + + public void setSamples(Set samples) { + this.samples = samples; + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/parameter/filter/AndedPatientTreatmentFilters.java b/src/main/java/org/cbioportal/legacy/web/parameter/filter/AndedPatientTreatmentFilters.java new file mode 100644 index 00000000000..96a7eb9ee35 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/parameter/filter/AndedPatientTreatmentFilters.java @@ -0,0 +1,27 @@ +package org.cbioportal.legacy.web.parameter.filter; + +import java.io.Serializable; +import java.util.List; +import java.util.Map; +import java.util.Set; +import org.cbioportal.legacy.web.parameter.SampleIdentifier; + +public class AndedPatientTreatmentFilters implements Serializable { + private List filters; + + public boolean filter(SampleIdentifier sampleId, Map> treatments) { + if (filters == null || filters.isEmpty()) { + return true; + } + + return filters.stream().allMatch(f -> f.filter(sampleId, treatments)); + } + + public List getFilters() { + return filters; + } + + public void setFilters(List filters) { + this.filters = filters; + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/parameter/filter/AndedSampleTreatmentFilters.java b/src/main/java/org/cbioportal/legacy/web/parameter/filter/AndedSampleTreatmentFilters.java new file mode 100644 index 00000000000..5b5eba12f7e --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/parameter/filter/AndedSampleTreatmentFilters.java @@ -0,0 +1,27 @@ +package org.cbioportal.legacy.web.parameter.filter; + +import java.io.Serializable; +import java.util.List; +import java.util.Map; +import java.util.Set; +import org.cbioportal.legacy.web.parameter.SampleIdentifier; + +public class AndedSampleTreatmentFilters implements Serializable { + private List filters; + + public boolean filter(SampleIdentifier sampleId, Map> treatments) { + if (filters == null || filters.isEmpty()) { + return true; + } + + return filters.stream().allMatch(f -> f.filter(sampleId, treatments)); + } + + public List getFilters() { + return filters; + } + + public void setFilters(List filters) { + this.filters = filters; + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/parameter/filter/OredPatientTreatmentFilters.java b/src/main/java/org/cbioportal/legacy/web/parameter/filter/OredPatientTreatmentFilters.java new file mode 100644 index 00000000000..2e5e2094d7f --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/parameter/filter/OredPatientTreatmentFilters.java @@ -0,0 +1,27 @@ +package org.cbioportal.legacy.web.parameter.filter; + +import java.io.Serializable; +import java.util.List; +import java.util.Map; +import java.util.Set; +import org.cbioportal.legacy.web.parameter.SampleIdentifier; + +public class OredPatientTreatmentFilters implements Serializable { + private List filters; + + public boolean filter(SampleIdentifier sampleId, Map> treatments) { + if (filters == null || filters.isEmpty()) { + return true; + } + + return filters.stream().anyMatch(f -> f.filter(sampleId, treatments)); + } + + public List getFilters() { + return filters; + } + + public void setFilters(List filters) { + this.filters = filters; + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/parameter/filter/OredSampleTreatmentFilters.java b/src/main/java/org/cbioportal/legacy/web/parameter/filter/OredSampleTreatmentFilters.java new file mode 100644 index 00000000000..6f7b01370d0 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/parameter/filter/OredSampleTreatmentFilters.java @@ -0,0 +1,27 @@ +package org.cbioportal.legacy.web.parameter.filter; + +import java.io.Serializable; +import java.util.List; +import java.util.Map; +import java.util.Set; +import org.cbioportal.legacy.web.parameter.SampleIdentifier; + +public class OredSampleTreatmentFilters implements Serializable { + private List filters; // ored + + public boolean filter(SampleIdentifier sampleId, Map> treatments) { + if (filters == null || filters.isEmpty()) { + return true; + } + + return filters.stream().anyMatch(f -> f.filter(sampleId, treatments)); + } + + public List getFilters() { + return filters; + } + + public void setFilters(List filters) { + this.filters = filters; + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/parameter/filter/PatientTreatmentFilter.java b/src/main/java/org/cbioportal/legacy/web/parameter/filter/PatientTreatmentFilter.java new file mode 100644 index 00000000000..1c2c690aefc --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/parameter/filter/PatientTreatmentFilter.java @@ -0,0 +1,30 @@ +package org.cbioportal.legacy.web.parameter.filter; + +import java.io.Serializable; +import java.util.Map; +import java.util.Set; +import org.cbioportal.legacy.web.parameter.SampleIdentifier; + +public class PatientTreatmentFilter implements Serializable { + private String treatment; + + /** + * A sampleId should be included if the treatment row that corresponds to the treatment and time + * in this filter contains that sampleId. + * + * @param sampleId sample.STABLE_ID + * @param treatments key is PatientTreatmentRow::calculateKey + */ + public boolean filter(SampleIdentifier sampleId, Map> treatments) { + Set row = treatments.get(treatment); + return row != null && row.contains(sampleId.toString()); + } + + public String getTreatment() { + return treatment; + } + + public void setTreatment(String treatment) { + this.treatment = treatment; + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/parameter/filter/SampleTreatmentFilter.java b/src/main/java/org/cbioportal/legacy/web/parameter/filter/SampleTreatmentFilter.java new file mode 100644 index 00000000000..eca69e398f5 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/parameter/filter/SampleTreatmentFilter.java @@ -0,0 +1,40 @@ +package org.cbioportal.legacy.web.parameter.filter; + +import java.io.Serializable; +import java.util.Map; +import java.util.Set; +import org.cbioportal.legacy.model.TemporalRelation; +import org.cbioportal.legacy.web.parameter.SampleIdentifier; + +public class SampleTreatmentFilter implements Serializable { + private String treatment; + private TemporalRelation time; + + /** + * A sample should be included if the treatment row that corresponds to the treatment and time in + * this filter contains that sample. + * + * @param sampleId sample.STABLE_ID + * @param treatments key is SampleTreatmentRow::calculateKey + */ + public boolean filter(SampleIdentifier sampleId, Map> treatments) { + Set row = treatments.get(treatment + time.name()); + return row != null && row.contains(sampleId.toString()); + } + + public String getTreatment() { + return treatment; + } + + public void setTreatment(String treatment) { + this.treatment = treatment; + } + + public TemporalRelation getTime() { + return time; + } + + public void setTime(TemporalRelation time) { + this.time = time; + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/parameter/sort/CancerTypeSortBy.java b/src/main/java/org/cbioportal/legacy/web/parameter/sort/CancerTypeSortBy.java new file mode 100644 index 00000000000..9345ae12660 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/parameter/sort/CancerTypeSortBy.java @@ -0,0 +1,19 @@ +package org.cbioportal.legacy.web.parameter.sort; + +public enum CancerTypeSortBy { + cancerTypeId("typeOfCancerId"), + name("name"), + dedicatedColor("dedicatedColor"), + shortName("shortName"), + parent("parent"); + + private String originalValue; + + CancerTypeSortBy(String originalValue) { + this.originalValue = originalValue; + } + + public String getOriginalValue() { + return originalValue; + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/parameter/sort/ClinicalAttributeSortBy.java b/src/main/java/org/cbioportal/legacy/web/parameter/sort/ClinicalAttributeSortBy.java new file mode 100644 index 00000000000..8fda84010c2 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/parameter/sort/ClinicalAttributeSortBy.java @@ -0,0 +1,21 @@ +package org.cbioportal.legacy.web.parameter.sort; + +public enum ClinicalAttributeSortBy { + clinicalAttributeId("attrId"), + displayName("displayName"), + description("description"), + datatype("datatype"), + patientAttribute("patientAttribute"), + priority("priority"), + studyId("cancerStudyIdentifier"); + + private String originalValue; + + ClinicalAttributeSortBy(String originalValue) { + this.originalValue = originalValue; + } + + public String getOriginalValue() { + return originalValue; + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/parameter/sort/ClinicalDataSortBy.java b/src/main/java/org/cbioportal/legacy/web/parameter/sort/ClinicalDataSortBy.java new file mode 100644 index 00000000000..54179dfbdf8 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/parameter/sort/ClinicalDataSortBy.java @@ -0,0 +1,16 @@ +package org.cbioportal.legacy.web.parameter.sort; + +public enum ClinicalDataSortBy { + clinicalAttributeId("attrId"), + value("attrValue"); + + private String originalValue; + + ClinicalDataSortBy(String originalValue) { + this.originalValue = originalValue; + } + + public String getOriginalValue() { + return originalValue; + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/parameter/sort/ClinicalEventSortBy.java b/src/main/java/org/cbioportal/legacy/web/parameter/sort/ClinicalEventSortBy.java new file mode 100644 index 00000000000..723a9cb1ccc --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/parameter/sort/ClinicalEventSortBy.java @@ -0,0 +1,17 @@ +package org.cbioportal.legacy.web.parameter.sort; + +public enum ClinicalEventSortBy { + eventType("eventType"), + startNumberOfDaysSinceDiagnosis("startDate"), + endNumberOfDaysSinceDiagnosis("stopDate"); + + private String originalValue; + + ClinicalEventSortBy(String originalValue) { + this.originalValue = originalValue; + } + + public String getOriginalValue() { + return originalValue; + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/parameter/sort/CopyNumberSegmentSortBy.java b/src/main/java/org/cbioportal/legacy/web/parameter/sort/CopyNumberSegmentSortBy.java new file mode 100644 index 00000000000..7cec044c882 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/parameter/sort/CopyNumberSegmentSortBy.java @@ -0,0 +1,19 @@ +package org.cbioportal.legacy.web.parameter.sort; + +public enum CopyNumberSegmentSortBy { + chromosome("chr"), + start("start"), + end("end"), + numberOfProbes("numProbes"), + segmentMean("segmentMean"); + + private String originalValue; + + CopyNumberSegmentSortBy(String originalValue) { + this.originalValue = originalValue; + } + + public String getOriginalValue() { + return originalValue; + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/parameter/sort/DiscreteCopyNumberSortBy.java b/src/main/java/org/cbioportal/legacy/web/parameter/sort/DiscreteCopyNumberSortBy.java new file mode 100644 index 00000000000..f2efabd4967 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/parameter/sort/DiscreteCopyNumberSortBy.java @@ -0,0 +1,16 @@ +package org.cbioportal.legacy.web.parameter.sort; + +public enum DiscreteCopyNumberSortBy { + entrezGeneId("entrezGeneId"), + alteration("alteration"); + + private String originalValue; + + DiscreteCopyNumberSortBy(String originalValue) { + this.originalValue = originalValue; + } + + public String getOriginalValue() { + return originalValue; + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/parameter/sort/GenePanelSortBy.java b/src/main/java/org/cbioportal/legacy/web/parameter/sort/GenePanelSortBy.java new file mode 100644 index 00000000000..062b5c69262 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/parameter/sort/GenePanelSortBy.java @@ -0,0 +1,16 @@ +package org.cbioportal.legacy.web.parameter.sort; + +public enum GenePanelSortBy { + genePanelId("stableId"), + description("description"); + + private String originalValue; + + GenePanelSortBy(String originalValue) { + this.originalValue = originalValue; + } + + public String getOriginalValue() { + return originalValue; + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/parameter/sort/GeneSortBy.java b/src/main/java/org/cbioportal/legacy/web/parameter/sort/GeneSortBy.java new file mode 100644 index 00000000000..8bd81790bb7 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/parameter/sort/GeneSortBy.java @@ -0,0 +1,19 @@ +package org.cbioportal.legacy.web.parameter.sort; + +public enum GeneSortBy { + entrezGeneId("entrezGeneId"), + hugoGeneSymbol("hugoGeneSymbol"), + type("type"), + cytoband("cytoband"), + length("length"); + + private String originalValue; + + GeneSortBy(String originalValue) { + this.originalValue = originalValue; + } + + public String getOriginalValue() { + return originalValue; + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/parameter/sort/MolecularProfileSortBy.java b/src/main/java/org/cbioportal/legacy/web/parameter/sort/MolecularProfileSortBy.java new file mode 100644 index 00000000000..4407a0c3f6e --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/parameter/sort/MolecularProfileSortBy.java @@ -0,0 +1,20 @@ +package org.cbioportal.legacy.web.parameter.sort; + +public enum MolecularProfileSortBy { + molecularProfileId("stableId"), + molecularAlterationType("geneticAlterationType"), + datatype("datatype"), + name("name"), + description("description"), + showProfileInAnalysisTab("showProfileInAnalysisTab"); + + private String originalValue; + + MolecularProfileSortBy(String originalValue) { + this.originalValue = originalValue; + } + + public String getOriginalValue() { + return originalValue; + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/parameter/sort/MutationSortBy.java b/src/main/java/org/cbioportal/legacy/web/parameter/sort/MutationSortBy.java new file mode 100644 index 00000000000..77aaf1bdcfa --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/parameter/sort/MutationSortBy.java @@ -0,0 +1,35 @@ +package org.cbioportal.legacy.web.parameter.sort; + +public enum MutationSortBy { + entrezGeneId("entrezGeneId"), + center("center"), + mutationStatus("mutationStatus"), + validationStatus("validationStatus"), + tumorAltCount("tumorAltCount"), + tumorRefCount("tumorRefCount"), + normalAltCount("normalAltCount"), + normalRefCount("normalRefCount"), + aminoAcidChange("aminoAcidChange"), + startPosition("startPosition"), + endPosition("endPosition"), + referenceAllele("referenceAllele"), + variantAllele("tumorSeqAllele"), + proteinChange("proteinChange"), + mutationType("mutationType"), + ncbiBuild("ncbiBuild"), + variantType("variantType"), + refseqMrnaId("refseqMrnaId"), + proteinPosStart("proteinPosStart"), + proteinPosEnd("proteinPosEnd"), + keyword("keyword"); + + private String originalValue; + + MutationSortBy(String originalValue) { + this.originalValue = originalValue; + } + + public String getOriginalValue() { + return originalValue; + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/parameter/sort/PatientSortBy.java b/src/main/java/org/cbioportal/legacy/web/parameter/sort/PatientSortBy.java new file mode 100644 index 00000000000..6e8557d418d --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/parameter/sort/PatientSortBy.java @@ -0,0 +1,15 @@ +package org.cbioportal.legacy.web.parameter.sort; + +public enum PatientSortBy { + patientId("stableId"); + + private String originalValue; + + PatientSortBy(String originalValue) { + this.originalValue = originalValue; + } + + public String getOriginalValue() { + return originalValue; + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/parameter/sort/ResourceDataSortBy.java b/src/main/java/org/cbioportal/legacy/web/parameter/sort/ResourceDataSortBy.java new file mode 100644 index 00000000000..54f240d5883 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/parameter/sort/ResourceDataSortBy.java @@ -0,0 +1,16 @@ +package org.cbioportal.legacy.web.parameter.sort; + +public enum ResourceDataSortBy { + ResourceId("resourceId"), + url("url"); + + private String originalValue; + + ResourceDataSortBy(String originalValue) { + this.originalValue = originalValue; + } + + public String getOriginalValue() { + return originalValue; + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/parameter/sort/ResourceDefinitionSortBy.java b/src/main/java/org/cbioportal/legacy/web/parameter/sort/ResourceDefinitionSortBy.java new file mode 100644 index 00000000000..220c77930d1 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/parameter/sort/ResourceDefinitionSortBy.java @@ -0,0 +1,22 @@ +package org.cbioportal.legacy.web.parameter.sort; + +public enum ResourceDefinitionSortBy { + resourceId("resourceId"), + displayName("displayName"), + description("description"), + resourceType("resourceType"), + priority("priority"), + openByDefault("openByDefault"), + studyId("cancerStudyIdentifier"), + customMetaData("customMetaData"); + + private String originalValue; + + ResourceDefinitionSortBy(String originalValue) { + this.originalValue = originalValue; + } + + public String getOriginalValue() { + return originalValue; + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/parameter/sort/SampleListSortBy.java b/src/main/java/org/cbioportal/legacy/web/parameter/sort/SampleListSortBy.java new file mode 100644 index 00000000000..df823081561 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/parameter/sort/SampleListSortBy.java @@ -0,0 +1,19 @@ +package org.cbioportal.legacy.web.parameter.sort; + +public enum SampleListSortBy { + sampleListId("stableId"), + category("category"), + studyId("cancerStudyIdentifier"), + name("name"), + description("description"); + + private String originalValue; + + SampleListSortBy(String originalValue) { + this.originalValue = originalValue; + } + + public String getOriginalValue() { + return originalValue; + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/parameter/sort/SampleSortBy.java b/src/main/java/org/cbioportal/legacy/web/parameter/sort/SampleSortBy.java new file mode 100644 index 00000000000..f8e73ae1531 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/parameter/sort/SampleSortBy.java @@ -0,0 +1,16 @@ +package org.cbioportal.legacy.web.parameter.sort; + +public enum SampleSortBy { + sampleId("stableId"), + sampleType("sampleType"); + + private String originalValue; + + SampleSortBy(String originalValue) { + this.originalValue = originalValue; + } + + public String getOriginalValue() { + return originalValue; + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/parameter/sort/SignificantCopyNumberRegionSortBy.java b/src/main/java/org/cbioportal/legacy/web/parameter/sort/SignificantCopyNumberRegionSortBy.java new file mode 100644 index 00000000000..0c3cc9ff1d1 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/parameter/sort/SignificantCopyNumberRegionSortBy.java @@ -0,0 +1,20 @@ +package org.cbioportal.legacy.web.parameter.sort; + +public enum SignificantCopyNumberRegionSortBy { + chromosome("chromosome"), + cytoband("cytoband"), + widePeakStart("widePeakStart"), + widePeakEnd("widePeakEnd"), + qValue("qValue"), + amp("amp"); + + private String originalValue; + + SignificantCopyNumberRegionSortBy(String originalValue) { + this.originalValue = originalValue; + } + + public String getOriginalValue() { + return originalValue; + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/parameter/sort/SignificantlyMutatedGeneSortBy.java b/src/main/java/org/cbioportal/legacy/web/parameter/sort/SignificantlyMutatedGeneSortBy.java new file mode 100644 index 00000000000..bceaa1d8ee9 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/parameter/sort/SignificantlyMutatedGeneSortBy.java @@ -0,0 +1,20 @@ +package org.cbioportal.legacy.web.parameter.sort; + +public enum SignificantlyMutatedGeneSortBy { + entrezGeneId("entrezGeneId"), + hugoGeneSymbol("hugoGeneSymbol"), + rank("rank"), + numberOfMutations("nummutations"), + pValue("pValue"), + qValue("qValue"); + + private String originalValue; + + SignificantlyMutatedGeneSortBy(String originalValue) { + this.originalValue = originalValue; + } + + public String getOriginalValue() { + return originalValue; + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/parameter/sort/StudySortBy.java b/src/main/java/org/cbioportal/legacy/web/parameter/sort/StudySortBy.java new file mode 100644 index 00000000000..a4f3c57fbdc --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/parameter/sort/StudySortBy.java @@ -0,0 +1,24 @@ +package org.cbioportal.legacy.web.parameter.sort; + +public enum StudySortBy { + studyId("cancerStudyIdentifier"), + cancerTypeId("typeOfCancerId"), + name("name"), + description("description"), + publicStudy("public"), + pmid("pmid"), + citation("citation"), + groups("groups"), + status("status"), + importDate("importDate"); + + private String originalValue; + + StudySortBy(String originalValue) { + this.originalValue = originalValue; + } + + public String getOriginalValue() { + return originalValue; + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/studyview/CustomDataController.java b/src/main/java/org/cbioportal/legacy/web/studyview/CustomDataController.java new file mode 100644 index 00000000000..c62613f5589 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/studyview/CustomDataController.java @@ -0,0 +1,129 @@ +package org.cbioportal.legacy.web.studyview; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.ArraySchema; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.function.Function; +import java.util.stream.Collectors; +import org.cbioportal.legacy.model.ClinicalDataCountItem; +import org.cbioportal.legacy.model.Patient; +import org.cbioportal.legacy.service.CustomDataService; +import org.cbioportal.legacy.service.PatientService; +import org.cbioportal.legacy.service.util.CustomDataSession; +import org.cbioportal.legacy.web.config.annotation.InternalApi; +import org.cbioportal.legacy.web.parameter.ClinicalDataCountFilter; +import org.cbioportal.legacy.web.parameter.ClinicalDataFilter; +import org.cbioportal.legacy.web.parameter.SampleIdentifier; +import org.cbioportal.legacy.web.parameter.StudyViewFilter; +import org.cbioportal.legacy.web.util.StudyViewFilterApplier; +import org.cbioportal.legacy.web.util.StudyViewFilterUtil; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.RequestAttribute; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RestController; + +@InternalApi +@RestController() +@RequestMapping("/api") +@Validated +@Tag(name = "Study View", description = " ") +public class CustomDataController { + + @Autowired private StudyViewFilterApplier studyViewFilterApplier; + @Autowired private StudyViewFilterUtil studyViewFilterUtil; + @Autowired private CustomDataService customDataService; + @Autowired private PatientService patientService; + + @PreAuthorize( + "hasPermission(#involvedCancerStudies, 'Collection', T(org.cbioportal.legacy.utils.security.AccessLevel).READ)") + @RequestMapping( + value = "/custom-data-counts/fetch", + method = RequestMethod.POST, + consumes = MediaType.APPLICATION_JSON_VALUE, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(description = "Fetch custom data counts by study view filter") + @ApiResponse( + responseCode = "200", + description = "OK", + content = + @Content( + array = @ArraySchema(schema = @Schema(implementation = ClinicalDataCountItem.class)))) + public ResponseEntity> fetchCustomDataCounts( + @Parameter(required = true, description = "Custom data count filter") + @Valid + @RequestBody(required = false) + ClinicalDataCountFilter clinicalDataCountFilter, + @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui + // interface + @RequestAttribute(required = false, value = "involvedCancerStudies") + Collection involvedCancerStudies, + @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui + // interface. this attribute is needed for the + // @PreAuthorize tag above. + @Valid + @RequestAttribute(required = false, value = "interceptedClinicalDataCountFilter") + ClinicalDataCountFilter interceptedClinicalDataCountFilter) { + + List attributes = interceptedClinicalDataCountFilter.getAttributes(); + StudyViewFilter studyViewFilter = interceptedClinicalDataCountFilter.getStudyViewFilter(); + if (attributes.size() == 1) { + studyViewFilterUtil.removeSelfCustomDataFromFilter( + attributes.get(0).getAttributeId(), studyViewFilter); + } + List filteredSampleIdentifiers = + studyViewFilterApplier.apply(studyViewFilter); + + if (filteredSampleIdentifiers.isEmpty()) { + return new ResponseEntity<>(new ArrayList<>(), HttpStatus.OK); + } + + final List attributeIds = + attributes.stream().map(ClinicalDataFilter::getAttributeId).collect(Collectors.toList()); + Map customDataSessionsMap = + customDataService.getCustomDataSessions(attributeIds); + + Map filteredSamplesMap = + filteredSampleIdentifiers.stream() + .collect( + Collectors.toMap( + sampleIdentifier -> + studyViewFilterUtil.getCaseUniqueKey( + sampleIdentifier.getStudyId(), sampleIdentifier.getSampleId()), + Function.identity())); + + List studyIds = new ArrayList<>(); + List sampleIds = new ArrayList<>(); + studyViewFilterUtil.extractStudyAndSampleIds(filteredSampleIdentifiers, studyIds, sampleIds); + + long patientCustomDataSessionsCount = + customDataSessionsMap.values().stream() + .filter(customDataSession -> customDataSession.getData().getPatientAttribute()) + .count(); + List patients = new ArrayList<>(); + if (patientCustomDataSessionsCount > 0) { + patients.addAll(patientService.getPatientsOfSamples(studyIds, sampleIds)); + } + + List result = + studyViewFilterUtil.getClinicalDataCountsFromCustomData( + customDataSessionsMap.values(), filteredSamplesMap, patients); + + return new ResponseEntity<>(result, HttpStatus.OK); + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/util/BinningData.java b/src/main/java/org/cbioportal/legacy/web/util/BinningData.java new file mode 100644 index 00000000000..d539031faba --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/util/BinningData.java @@ -0,0 +1,30 @@ +package org.cbioportal.legacy.web.util; + +import static java.util.Collections.unmodifiableList; + +import java.util.Collection; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import org.cbioportal.legacy.model.Binnable; + +public class BinningData { + public final List samples; + public final List patients; + public final List conflictingPatientAttributes; + private final List allData; + + public BinningData(List samples, List patients, List conflictingPatientAttributes) { + this.samples = unmodifiableList(samples); + this.patients = unmodifiableList(patients); + this.conflictingPatientAttributes = unmodifiableList(conflictingPatientAttributes); + this.allData = + Stream.of(this.samples, this.patients, this.conflictingPatientAttributes) + .flatMap(Collection::stream) + .collect(Collectors.toList()); + } + + public List getAllData() { + return allData; + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/util/BinningIds.java b/src/main/java/org/cbioportal/legacy/web/util/BinningIds.java new file mode 100644 index 00000000000..b81f13869a9 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/util/BinningIds.java @@ -0,0 +1,70 @@ +package org.cbioportal.legacy.web.util; + +import java.util.ArrayList; +import java.util.List; + +/** All IDs relevant for binning of clinical (and custom clinical) data */ +public class BinningIds { + private List studyIds = new ArrayList<>(); + private List sampleIds = new ArrayList<>(); + private List patientIds = new ArrayList<>(); + private List studyIdsOfPatients = new ArrayList<>(); + private List uniqueSampleKeys = new ArrayList<>(); + private List uniquePatientKeys = new ArrayList<>(); + private List sampleAttributeIds = new ArrayList<>(); + private List patientAttributeIds = new ArrayList<>(); + private List conflictingPatientAttributeIds = new ArrayList<>(); + + public BinningIds() {} + + /** Create shallow clone */ + public BinningIds(BinningIds toClone) { + this(); + this.studyIds = new ArrayList<>(toClone.getStudyIds()); + this.sampleIds = new ArrayList<>(toClone.getSampleIds()); + this.patientIds = new ArrayList<>(toClone.getPatientIds()); + this.studyIdsOfPatients = new ArrayList<>(toClone.getStudyIdsOfPatients()); + this.uniqueSampleKeys = new ArrayList<>(toClone.getUniqueSampleKeys()); + this.uniquePatientKeys = new ArrayList<>(toClone.getUniquePatientKeys()); + this.sampleAttributeIds = new ArrayList<>(toClone.getSampleAttributeIds()); + this.patientAttributeIds = new ArrayList<>(toClone.getPatientAttributeIds()); + this.conflictingPatientAttributeIds = + new ArrayList<>(toClone.getConflictingPatientAttributeIds()); + } + + public List getStudyIds() { + return studyIds; + } + + public List getSampleIds() { + return sampleIds; + } + + public List getPatientIds() { + return patientIds; + } + + public List getStudyIdsOfPatients() { + return studyIdsOfPatients; + } + + public List getUniqueSampleKeys() { + return uniqueSampleKeys; + } + + public List getUniquePatientKeys() { + return uniquePatientKeys; + } + + public List getSampleAttributeIds() { + return sampleAttributeIds; + } + + public List getPatientAttributeIds() { + return patientAttributeIds; + } + + public List getConflictingPatientAttributeIds() { + return conflictingPatientAttributeIds; + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/util/ClinicalDataBinUtil.java b/src/main/java/org/cbioportal/legacy/web/util/ClinicalDataBinUtil.java new file mode 100644 index 00000000000..5f716784d19 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/util/ClinicalDataBinUtil.java @@ -0,0 +1,416 @@ +package org.cbioportal.legacy.web.util; + +import static java.util.Collections.emptyList; +import static java.util.stream.Collectors.toList; +import static java.util.stream.Collectors.toMap; + +import java.util.*; +import java.util.function.Function; +import java.util.stream.Collectors; +import org.cbioportal.legacy.model.Binnable; +import org.cbioportal.legacy.model.ClinicalAttribute; +import org.cbioportal.legacy.model.ClinicalData; +import org.cbioportal.legacy.model.ClinicalDataBin; +import org.cbioportal.legacy.service.AttributeByStudyService; +import org.cbioportal.legacy.service.CustomDataService; +import org.cbioportal.legacy.service.util.BinnableCustomDataValue; +import org.cbioportal.legacy.service.util.CustomAttributeWithData; +import org.cbioportal.legacy.service.util.CustomDataSession; +import org.cbioportal.legacy.service.util.CustomDataValue; +import org.cbioportal.legacy.web.columnar.util.NewClinicalDataBinUtil; +import org.cbioportal.legacy.web.parameter.ClinicalDataBinCountFilter; +import org.cbioportal.legacy.web.parameter.ClinicalDataBinFilter; +import org.cbioportal.legacy.web.parameter.ClinicalDataType; +import org.cbioportal.legacy.web.parameter.DataBinMethod; +import org.cbioportal.legacy.web.parameter.SampleIdentifier; +import org.cbioportal.legacy.web.parameter.StudyViewFilter; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +@Component +public class ClinicalDataBinUtil { + + @Autowired private AttributeByStudyService clinicalAttributeService; + @Autowired private StudyViewFilterApplier studyViewFilterApplier; + @Autowired private ClinicalDataFetcher clinicalDataFetcher; + @Autowired private DataBinner dataBinner; + @Autowired private StudyViewFilterUtil studyViewFilterUtil; + @Autowired private CustomDataService customDataService; + @Autowired private IdPopulator idPopulator; + + public StudyViewFilter removeSelfFromFilter(ClinicalDataBinCountFilter dataBinCountFilter) { + return NewClinicalDataBinUtil.removeSelfFromFilter(dataBinCountFilter); + } + + public List fetchClinicalDataBinCounts( + DataBinMethod dataBinMethod, ClinicalDataBinCountFilter dataBinCountFilter) { + return this.fetchClinicalDataBinCounts( + dataBinMethod, + dataBinCountFilter, + // by default call the method to remove self from filter + true); + } + + public List fetchClinicalDataBinCounts( + DataBinMethod dataBinMethod, + ClinicalDataBinCountFilter dataBinCountFilter, + boolean shouldRemoveSelfFromFilter) { + StudyViewFilter studyViewFilter = + toStudyViewFilter(dataBinCountFilter, shouldRemoveSelfFromFilter); + List unfilteredSamples = filterByStudyAndSample(studyViewFilter); + List attributeIds = toAttributeIds(dataBinCountFilter.getAttributes()); + List clinicalAttributes = + fetchClinicalAttributes(attributeIds, unfilteredSamples); + BinningIds binningIds = idPopulator.populateIdLists(unfilteredSamples, clinicalAttributes); + Map attributeByDatatype = toAttributeDatatypeMap(binningIds); + BinningData unfilteredData = + (BinningData) (BinningData) fetchBinningData(binningIds); + return createBins( + dataBinMethod, + dataBinCountFilter, + studyViewFilter, + attributeByDatatype, + clinicalAttributes, + binningIds, + unfilteredSamples, + unfilteredData); + } + + public List fetchCustomDataBinCounts( + DataBinMethod dataBinMethod, + ClinicalDataBinCountFilter dataBinCountFilter, + boolean shouldRemoveSelfFromFilter) { + List attributeIds = toAttributeIds(dataBinCountFilter.getAttributes()); + Map customDataSessions = + customDataService.getCustomDataSessions(attributeIds); + Map> customDataByAttributeId = + createCustomDataByAttributeId(customDataSessions); + Map customAttributeByDatatype = + createCustomAttributeDatatypeMap(customDataSessions); + + StudyViewFilter studyViewFilter = + toStudyViewFilter(dataBinCountFilter, shouldRemoveSelfFromFilter); + List unfilteredSamples = filterByStudyAndSample(studyViewFilter); + List customDataAttributes = toCustomAttributes(customDataSessions); + + BinningIds unfilteredIds = idPopulator.populateIdLists(unfilteredSamples, customDataAttributes); + BinningData unfilteredData = + fetchCustomBinningData(customDataByAttributeId, unfilteredIds); + + return createBins( + dataBinMethod, + dataBinCountFilter, + studyViewFilter, + customAttributeByDatatype, + customDataAttributes, + unfilteredIds, + unfilteredSamples, + unfilteredData); + } + + private List createBins( + DataBinMethod dataBinMethod, + ClinicalDataBinCountFilter dataBinCountFilter, + StudyViewFilter studyViewFilter, + Map clinicalDataAttributeDatatypeMap, + List clinicalAttributes, + BinningIds unfilteredIds, + List unfilteredSampleIds, + BinningData unfilteredData) { + List filteredSampleIds = + filterSampleIds(studyViewFilter, unfilteredSampleIds); + + BinningIds filteredIds; + List filteredClinicalData; + if (filteredSampleIds.equals(unfilteredSampleIds)) { + // if filtered and unfiltered samples are exactly the same, no need to fetch clinical data + // again: + filteredIds = new BinningIds(unfilteredIds); + filteredClinicalData = unfilteredData.getAllData(); + } else { + filteredIds = idPopulator.populateIdLists(filteredSampleIds, clinicalAttributes); + filteredClinicalData = filterClinicalData(unfilteredData, filteredIds); + } + + List attributes = dataBinCountFilter.getAttributes(); + if (dataBinMethod == DataBinMethod.STATIC) { + if (unfilteredSampleIds.isEmpty() || unfilteredData.getAllData().isEmpty()) { + return emptyList(); + } + return calculateStaticDataBins( + attributes, + clinicalDataAttributeDatatypeMap, + toClinicalDataByAttributeId(unfilteredData.getAllData()), + toClinicalDataByAttributeId(filteredClinicalData), + unfilteredIds.getUniqueSampleKeys(), + unfilteredIds.getUniquePatientKeys(), + filteredIds.getUniqueSampleKeys(), + filteredIds.getUniquePatientKeys()); + } else { // dataBinMethod == DataBinMethod.DYNAMIC + if (filteredClinicalData.isEmpty()) { + return emptyList(); + } + return calculateDynamicDataBins( + attributes, + clinicalDataAttributeDatatypeMap, + toClinicalDataByAttributeId(filteredClinicalData), + filteredIds.getUniqueSampleKeys(), + filteredIds.getUniquePatientKeys()); + } + } + + private List toCustomAttributes( + Map customDataSessions) { + return customDataSessions.entrySet().stream() + .map(e -> toClinicalAttribute(e.getKey(), e.getValue().getData())) + .collect(toList()); + } + + private ClinicalAttribute toClinicalAttribute(String key, CustomAttributeWithData data) { + ClinicalAttribute result = new ClinicalAttribute(); + result.setPatientAttribute(data.getPatientAttribute()); + result.setAttrId(key); + result.setDatatype(data.getDatatype()); + return result; + } + + private Map> toClinicalDataByAttributeId(List unfilteredData) { + return unfilteredData.stream().collect(Collectors.groupingBy(Binnable::getAttrId)); + } + + private List filterClinicalData( + BinningData unfilteredData, BinningIds filteredIds) { + return studyViewFilterUtil.filterClinicalData( + unfilteredData.samples, + unfilteredData.patients, + unfilteredData.conflictingPatientAttributes, + filteredIds.getStudyIds(), + filteredIds.getSampleIds(), + filteredIds.getStudyIdsOfPatients(), + filteredIds.getPatientIds(), + filteredIds.getSampleAttributeIds(), + filteredIds.getPatientAttributeIds(), + filteredIds.getConflictingPatientAttributeIds()); + } + + private List filterSampleIds( + StudyViewFilter studyViewFilter, List unfilteredSampleIds) { + return studyViewFilterUtil.shouldSkipFilterForClinicalDataBins(studyViewFilter) + ? unfilteredSampleIds + : studyViewFilterApplier.apply(studyViewFilter); + } + + private List toAttributeIds(List dataBinCountFilter) { + return dataBinCountFilter.stream().map(ClinicalDataBinFilter::getAttributeId).collect(toList()); + } + + private StudyViewFilter toStudyViewFilter( + ClinicalDataBinCountFilter dataBinCountFilter, boolean shouldRemoveSelfFromFilter) { + StudyViewFilter studyViewFilter = dataBinCountFilter.getStudyViewFilter(); + + if (shouldRemoveSelfFromFilter) { + studyViewFilter = removeSelfFromFilter(dataBinCountFilter); + } + return studyViewFilter; + } + + private Map> createCustomDataByAttributeId( + Map customDataSessions) { + return customDataSessions.entrySet().stream() + .collect( + toMap( + Map.Entry::getKey, + entry -> + entry.getValue().getData().getData().stream() + .map(mapCustomToBinnable(entry)) + .collect(toList()))); + } + + private BinningData fetchBinningData(BinningIds binningIds) { + List samples = + clinicalDataFetcher.fetchClinicalDataForSamples( + binningIds.getStudyIds(), + binningIds.getSampleIds(), + binningIds.getSampleAttributeIds()); + + List patients = + clinicalDataFetcher.fetchClinicalDataForPatients( + binningIds.getStudyIdsOfPatients(), + binningIds.getPatientIds(), + binningIds.getPatientAttributeIds()); + + List conflictingPatientAttributes = + clinicalDataFetcher.fetchClinicalDataForConflictingPatientAttributes( + binningIds.getStudyIdsOfPatients(), + binningIds.getPatientIds(), + binningIds.getConflictingPatientAttributeIds()); + return new BinningData<>(samples, patients, conflictingPatientAttributes); + } + + private BinningData fetchCustomBinningData( + Map> clinicalDataByAttributeId, BinningIds binningIds) { + List clinicalDataForPatients = + clinicalDataByAttributeId.values().stream() + .filter(e -> e.get(0).isPatientAttribute()) + .flatMap(List::stream) + .collect(toList()); + + List clinicalDataForSamples = + clinicalDataByAttributeId.values().stream() + .filter(e -> !e.get(0).isPatientAttribute()) + .flatMap(List::stream) + .collect(toList()); + + List unfilteredClinicalDataForConflictingPatientAttributes = + clinicalDataFetcher.fetchClinicalDataForConflictingPatientAttributes( + binningIds.getStudyIdsOfPatients(), + binningIds.getPatientIds(), + binningIds.getConflictingPatientAttributeIds()); + return new BinningData<>( + clinicalDataForSamples, + clinicalDataForPatients, + (List) + (List) unfilteredClinicalDataForConflictingPatientAttributes); + } + + private Function mapCustomToBinnable( + Map.Entry entry) { + return customDataValue -> { + final String attributeId = entry.getKey(); + final Boolean patientAttribute = entry.getValue().getData().getPatientAttribute(); + return new BinnableCustomDataValue(customDataValue, attributeId, patientAttribute); + }; + } + + public List calculateStaticDataBins( + List attributes, + Map attributeDatatypeMap, + Map> unfilteredClinicalDataByAttributeId, + Map> filteredClinicalDataByAttributeId, + List unfilteredUniqueSampleKeys, + List unfilteredUniquePatientKeys, + List filteredUniqueSampleKeys, + List filteredUniquePatientKeys) { + List clinicalDataBins = new ArrayList<>(); + + for (ClinicalDataBinFilter attribute : attributes) { + if (attributeDatatypeMap.containsKey(attribute.getAttributeId())) { + ClinicalDataType clinicalDataType = attributeDatatypeMap.get(attribute.getAttributeId()); + List filteredIds = + clinicalDataType == ClinicalDataType.PATIENT + ? filteredUniquePatientKeys + : filteredUniqueSampleKeys; + List unfilteredIds = + clinicalDataType == ClinicalDataType.PATIENT + ? unfilteredUniquePatientKeys + : unfilteredUniqueSampleKeys; + + List dataBins = + dataBinner + .calculateClinicalDataBins( + attribute, + clinicalDataType, + filteredClinicalDataByAttributeId.getOrDefault( + attribute.getAttributeId(), emptyList()), + unfilteredClinicalDataByAttributeId.getOrDefault( + attribute.getAttributeId(), emptyList()), + filteredIds, + unfilteredIds) + .stream() + .map(dataBin -> NewClinicalDataBinUtil.dataBinToClinicalDataBin(attribute, dataBin)) + .toList(); + + clinicalDataBins.addAll(dataBins); + } + } + + return clinicalDataBins; + } + + public List calculateDynamicDataBins( + List attributes, + Map attributeDatatypeMap, + Map> filteredClinicalDataByAttributeId, + List filteredUniqueSampleKeys, + List filteredUniquePatientKeys) { + List clinicalDataBins = new ArrayList<>(); + + for (ClinicalDataBinFilter attribute : attributes) { + + // if there is clinical data for requested attribute + if (attributeDatatypeMap.containsKey(attribute.getAttributeId())) { + ClinicalDataType clinicalDataType = attributeDatatypeMap.get(attribute.getAttributeId()); + List filteredIds = + clinicalDataType == ClinicalDataType.PATIENT + ? filteredUniquePatientKeys + : filteredUniqueSampleKeys; + + List dataBins = + dataBinner + .calculateDataBins( + attribute, + clinicalDataType, + filteredClinicalDataByAttributeId.getOrDefault( + attribute.getAttributeId(), emptyList()), + filteredIds) + .stream() + .map(dataBin -> NewClinicalDataBinUtil.dataBinToClinicalDataBin(attribute, dataBin)) + .toList(); + clinicalDataBins.addAll(dataBins); + } + } + + return clinicalDataBins; + } + + private Map toAttributeDatatypeMap(BinningIds binningIds) { + return toAttributeDatatypeMap( + binningIds.getSampleAttributeIds(), + binningIds.getPatientAttributeIds(), + binningIds.getConflictingPatientAttributeIds()); + } + + public Map toAttributeDatatypeMap( + List sampleAttributeIds, + List patientAttributeIds, + List conflictingPatientAttributeIds) { + return NewClinicalDataBinUtil.toAttributeDatatypeMap( + sampleAttributeIds, patientAttributeIds, conflictingPatientAttributeIds); + } + + private Map createCustomAttributeDatatypeMap( + Map customDataSessions) { + return customDataSessions.entrySet().stream() + .collect(toMap(Map.Entry::getKey, ClinicalDataBinUtil::getDataType)); + } + + public List filterByStudyAndSample(StudyViewFilter studyViewFilter) { + StudyViewFilter filter = null; + + // only filter by study id and sample identifiers + if (studyViewFilter != null) { + filter = new StudyViewFilter(); + filter.setStudyIds(studyViewFilter.getStudyIds()); + filter.setSampleIdentifiers(studyViewFilter.getSampleIdentifiers()); + } + + return studyViewFilterApplier.apply(filter); + } + + private static ClinicalDataType getDataType(Map.Entry entry) { + return entry.getValue().getData().getPatientAttribute() + ? ClinicalDataType.PATIENT + : ClinicalDataType.SAMPLE; + } + + private List fetchClinicalAttributes( + List attributeIds, List unfilteredSamples) { + + List studyIds = new ArrayList<>(); + List sampleIds = new ArrayList<>(); + studyViewFilterUtil.extractStudyAndSampleIds(unfilteredSamples, studyIds, sampleIds); + + return clinicalAttributeService.getClinicalAttributesByStudyIdsAndAttributeIds( + studyIds, attributeIds); + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/util/ClinicalDataEnrichmentUtil.java b/src/main/java/org/cbioportal/legacy/web/util/ClinicalDataEnrichmentUtil.java new file mode 100644 index 00000000000..982898e1e30 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/util/ClinicalDataEnrichmentUtil.java @@ -0,0 +1,315 @@ +package org.cbioportal.legacy.web.util; + +import com.datumbox.framework.common.dataobjects.AssociativeArray; +import com.datumbox.framework.common.dataobjects.DataTable2D; +import com.datumbox.framework.common.dataobjects.FlatDataCollection; +import com.datumbox.framework.common.dataobjects.TransposeDataCollection; +import com.datumbox.framework.core.statistics.distributions.ContinuousDistributions; +import com.datumbox.framework.core.statistics.nonparametrics.independentsamples.Chisquare; +import com.datumbox.framework.core.statistics.nonparametrics.independentsamples.KruskalWallis; +import java.math.BigDecimal; +import java.util.*; +import java.util.function.Supplier; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import org.apache.commons.lang3.math.NumberUtils; +import org.cbioportal.legacy.model.ClinicalAttribute; +import org.cbioportal.legacy.model.ClinicalData; +import org.cbioportal.legacy.model.ClinicalDataCount; +import org.cbioportal.legacy.model.ClinicalDataCountItem; +import org.cbioportal.legacy.model.ClinicalDataEnrichment; +import org.cbioportal.legacy.model.Sample; +import org.cbioportal.legacy.service.ClinicalDataService; +import org.cbioportal.legacy.service.util.ClinicalAttributeUtil; +import org.cbioportal.legacy.web.parameter.ClinicalDataType; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +/** + * @author kalletlak + */ +@Component +public class ClinicalDataEnrichmentUtil { + + @Autowired private ClinicalDataService clinicalDataService; + @Autowired private ClinicalAttributeUtil clinicalAttributeUtil; + + @Value("${comparison.categorical_na_values:NA}") + private String ComparisonCategoricalNaValuesString; + + public List createEnrichmentsForNumericData( + List attributes, List> groupedSamples) { + List clinicalEnrichments = new ArrayList(); + + List filteredAttributes = + attributes.stream() + .filter(attribute -> attribute.getDatatype().equals("NUMBER")) + .collect(Collectors.toList()); + + List sampleAttributeIds = new ArrayList<>(); + List patientAttributeIds = new ArrayList<>(); + List conflictingPatientAttributeIds = new ArrayList<>(); + + clinicalAttributeUtil.extractCategorizedClinicalAttributes( + filteredAttributes, + sampleAttributeIds, + patientAttributeIds, + conflictingPatientAttributeIds); + String testName = groupedSamples.size() == 2 ? "Wilcoxon Test" : "Kruskal Wallis Test"; + + // list of values for all NUMBER datatype attributes and for all sample groups + List>> dataByGroupAndByAttribute = + groupedSamples.stream() + .map( + groupSamples -> + getNumericClinicalData( + new ArrayList<>(sampleAttributeIds), + new ArrayList<>(patientAttributeIds), + new ArrayList<>(conflictingPatientAttributeIds), + groupSamples)) + .collect(Collectors.toList()); + + filteredAttributes.forEach( + clinicalAttribute -> { + String attributeId = clinicalAttribute.getAttrId(); + TransposeDataCollection transposeDataCollection = new TransposeDataCollection(); + int index = 0; + for (Map> entry : dataByGroupAndByAttribute) { + if (entry.containsKey(attributeId)) { + Collection values = + entry.get(attributeId).stream().collect(Collectors.toList()); + // add only groups having values + if (values.size() > 0) { + transposeDataCollection.put(index++, new FlatDataCollection(values)); + } + } + } + + Supplier> valuesStreamSupplier = + () -> + transposeDataCollection.values().stream() + .flatMap(Collection::stream) + .map(x -> (Double) x); + + List distinctValues = + valuesStreamSupplier.get().distinct().collect(Collectors.toList()); + + // perform test only if there are more than one group and + // there are atleast two distinct values + if (transposeDataCollection.keySet().size() > 1 && distinctValues.size() > 1) { + double pValue = KruskalWallis.getPvalue(transposeDataCollection); + if (!Double.isNaN(pValue)) { // this happens when all the values are zero + ClinicalDataEnrichment clinicalEnrichment = new ClinicalDataEnrichment(); + clinicalEnrichment.setClinicalAttribute(clinicalAttribute); + clinicalEnrichment.setpValue(BigDecimal.valueOf(pValue)); + clinicalEnrichment.setScore( + BigDecimal.valueOf( + ContinuousDistributions.chisquareInverseCdf( + pValue, transposeDataCollection.keySet().size() - 1))); + clinicalEnrichment.setMethod(testName); + clinicalEnrichments.add(clinicalEnrichment); + } + } + }); + return clinicalEnrichments; + } + + public List createEnrichmentsForCategoricalData( + List attributes, List> groupedSamples) { + List clinicalEnrichments = new ArrayList(); + + List filteredAttributes = + attributes.stream() + .filter(attribute -> attribute.getDatatype().equals("STRING")) + .collect(Collectors.toList()); + + List filteredAttributeIds = + filteredAttributes.stream().map(ClinicalAttribute::getAttrId).collect(Collectors.toList()); + + // ClinicalDataCountItem for all STRING datatype attributes and for all sample groups + List> dataCountsByGroupAndByAttribute = + groupedSamples.stream() + .map(groupSamples -> getClinicalDataCounts(filteredAttributeIds, groupSamples)) + .collect(Collectors.toList()); + + filteredAttributes.forEach( + clinicalAttribute -> { + String attributeId = clinicalAttribute.getAttrId(); + + // get counts for all categories in all group for a given attribute + List> categoryCountsByGroup = + dataCountsByGroupAndByAttribute.stream() + .map( + e -> { + if (e.containsKey(attributeId)) { + return e.get(attributeId).getCounts().stream() + .collect( + Collectors.toMap( + ClinicalDataCount::getValue, ClinicalDataCount::getCount)); + } + return new HashMap(); + }) + .collect(Collectors.toList()); + + Set allPossibleCategories = + categoryCountsByGroup.stream() + .flatMap(x -> x.keySet().stream()) + .collect(Collectors.toSet()); + + if (allPossibleCategories.size() > 1) { + DataTable2D dataTable = new DataTable2D(); + int groupIndex = 0; + for (Map groupCategoryCounts : categoryCountsByGroup) { + Map allCategoryCounts = + allPossibleCategories.stream() + .collect( + Collectors.toMap( + category -> category, + category -> { + return groupCategoryCounts.containsKey(category) + ? groupCategoryCounts.get(category) + : 0; + })); + + // filter group if all the categories values are 0 + if (isValidGroupdData(new ArrayList<>(allCategoryCounts.values()))) { + AssociativeArray categoryCounts = new AssociativeArray(); + categoryCounts.putAll(allCategoryCounts); + dataTable.put(groupIndex++, categoryCounts); + } + } + + if (dataTable.size() > 1 && dataTable.isValid()) { + double pValue = Chisquare.getPvalue(dataTable); + ClinicalDataEnrichment clinicalEnrichment = new ClinicalDataEnrichment(); + clinicalEnrichment.setClinicalAttribute(clinicalAttribute); + clinicalEnrichment.setpValue(BigDecimal.valueOf(pValue)); + clinicalEnrichment.setScore( + BigDecimal.valueOf((Double) Chisquare.getScoreValue(dataTable))); + clinicalEnrichment.setMethod("Chi-squared Test"); + clinicalEnrichments.add(clinicalEnrichment); + } + } + }); + + return clinicalEnrichments; + } + + /** + * get data for all NUMBER datatype attributes for given samples + * + * @param attributes + * @param samples + * @return + */ + private Map> getNumericClinicalData( + List sampleAttributeIds, + List patientAttributeIds, + List conflictingPatientAttributeIds, + List samples) { + + List studyIds = new ArrayList<>(); + List sampleIds = new ArrayList<>(); + List patientIds = new ArrayList<>(); + for (Sample sample : samples) { + studyIds.add(sample.getCancerStudyIdentifier()); + sampleIds.add(sample.getStableId()); + patientIds.add(sample.getPatientStableId()); + } + + Map> dataByAttribute = new HashMap<>(); + + List clinicalDatas = new ArrayList(); + if (!sampleAttributeIds.isEmpty()) { + clinicalDatas.addAll( + clinicalDataService.fetchClinicalData( + studyIds, sampleIds, sampleAttributeIds, ClinicalDataType.SAMPLE.name(), "SUMMARY")); + } + + if (!patientAttributeIds.isEmpty()) { + clinicalDatas.addAll( + clinicalDataService.fetchClinicalData( + studyIds, + patientIds, + patientAttributeIds, + ClinicalDataType.PATIENT.name(), + "SUMMARY")); + } + + if (!conflictingPatientAttributeIds.isEmpty()) { + clinicalDatas.addAll( + clinicalDataService.getPatientClinicalDataDetailedToSample( + studyIds, patientIds, conflictingPatientAttributeIds)); + } + + dataByAttribute = + clinicalDatas.stream() + // filter are non numeric data to fix + // https://github.com/cBioPortal/cbioportal/issues/6228 + .filter(x -> NumberUtils.isCreatable(x.getAttrValue())) + .collect( + Collectors.groupingBy( + x -> x.getAttrId(), + Collectors.mapping( + x -> Double.valueOf(x.getAttrValue()), Collectors.toList()))); + + return dataByAttribute; + } + + /** + * get data category counts for all STRING datatype attributes for given samples + * + * @param attributes + * @param samples + * @return + */ + private Map getClinicalDataCounts( + List attributeIds, List samples) { + + List studyIds = new ArrayList<>(); + List sampleIds = new ArrayList<>(); + for (Sample sample : samples) { + studyIds.add(sample.getCancerStudyIdentifier()); + sampleIds.add(sample.getStableId()); + } + + List clinicalDataCountItems = + clinicalDataService.fetchClinicalDataCounts(studyIds, sampleIds, attributeIds); + + return clinicalDataCountItems.stream() + // Exclude NA category + .map( + clinicalDataCountItem -> { + List filteredClinicalDataCount = + clinicalDataCountItem.getCounts().stream() + .filter( + clinicalDataCount -> { + if (ComparisonCategoricalNaValuesString != null) { + String[] ComparisonCategoricalNaValues = + ComparisonCategoricalNaValuesString.split("\\|"); + for (String naValue : ComparisonCategoricalNaValues) { + if (clinicalDataCount.getValue().equalsIgnoreCase(naValue)) { + return false; + } + } + } + return true; + }) + .collect(Collectors.toList()); + clinicalDataCountItem.setCounts(filteredClinicalDataCount); + return clinicalDataCountItem; + }) + .collect( + Collectors.toMap( + clinicalDataCountItem -> clinicalDataCountItem.getAttributeId(), + clinicalDataCountItem -> clinicalDataCountItem)); + } + + // For categorical values, group data is valid if all the values are not 0 + private boolean isValidGroupdData(List values) { + return values.stream() + .map(value -> (value == 0 ? false : true)) + .reduce(false, (value1, value2) -> value1 || value2); + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/util/ClinicalDataEqualityFilterApplier.java b/src/main/java/org/cbioportal/legacy/web/util/ClinicalDataEqualityFilterApplier.java new file mode 100644 index 00000000000..2676dd3ae0c --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/util/ClinicalDataEqualityFilterApplier.java @@ -0,0 +1,57 @@ +package org.cbioportal.legacy.web.util; + +import java.util.ArrayList; +import java.util.List; +import org.apache.commons.collections4.map.MultiKeyMap; +import org.cbioportal.legacy.model.ClinicalData; +import org.cbioportal.legacy.service.ClinicalDataService; +import org.cbioportal.legacy.service.PatientService; +import org.cbioportal.legacy.web.parameter.ClinicalDataFilter; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +@Component +public class ClinicalDataEqualityFilterApplier extends ClinicalDataFilterApplier { + @Autowired + public ClinicalDataEqualityFilterApplier( + PatientService patientService, + ClinicalDataService clinicalDataService, + StudyViewFilterUtil studyViewFilterUtil) { + super(patientService, clinicalDataService, studyViewFilterUtil); + } + + @Autowired private StudyViewFilterUtil studyViewFilterUtil; + + @Override + public Integer apply( + List attributes, + MultiKeyMap clinicalDataMap, + String entityId, + String studyId, + boolean negateFilters) { + return studyViewFilterUtil.getFilteredCountByDataEquality( + attributes, clinicalDataMap, entityId, studyId, negateFilters); + } + + public static MultiKeyMap> buildClinicalDataMap( + List clinicalDatas) { + MultiKeyMap> clinicalDataMap = new MultiKeyMap<>(); + + clinicalDatas.forEach( + clinicalData -> { + if (!clinicalDataMap.containsKey( + clinicalData.getStudyId(), clinicalData.getSampleId(), clinicalData.getAttrId())) { + clinicalDataMap.put( + clinicalData.getStudyId(), + clinicalData.getSampleId(), + clinicalData.getAttrId(), + new ArrayList<>()); + } + clinicalDataMap + .get(clinicalData.getStudyId(), clinicalData.getSampleId(), clinicalData.getAttrId()) + .add(clinicalData.getAttrValue()); + }); + + return clinicalDataMap; + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/util/ClinicalDataFetcher.java b/src/main/java/org/cbioportal/legacy/web/util/ClinicalDataFetcher.java new file mode 100644 index 00000000000..07a139e3c98 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/util/ClinicalDataFetcher.java @@ -0,0 +1,95 @@ +package org.cbioportal.legacy.web.util; + +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import org.apache.commons.collections4.CollectionUtils; +import org.cbioportal.legacy.model.ClinicalData; +import org.cbioportal.legacy.service.ClinicalDataService; +import org.cbioportal.legacy.web.parameter.ClinicalDataType; +import org.cbioportal.legacy.web.parameter.Projection; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +@Component +public class ClinicalDataFetcher { + + @Autowired private ClinicalDataService clinicalDataService; + + public List fetchClinicalDataForSamples( + List studyIds, List sampleIds, List sampleAttributeIds) { + List filteredClinicalDataForSamples = Collections.emptyList(); + + if (CollectionUtils.isNotEmpty(sampleAttributeIds)) { + filteredClinicalDataForSamples = + clinicalDataService.fetchClinicalData( + studyIds, + sampleIds, + sampleAttributeIds, + ClinicalDataType.SAMPLE.name(), + Projection.SUMMARY.name()); + } + + return filteredClinicalDataForSamples; + } + + public List fetchClinicalDataForPatients( + List studyIdsOfPatients, List patientIds, List patientAttributeIds) { + List filteredClinicalDataForPatients = Collections.emptyList(); + + if (CollectionUtils.isNotEmpty(patientAttributeIds)) { + filteredClinicalDataForPatients = + clinicalDataService.fetchClinicalData( + studyIdsOfPatients, + patientIds, + patientAttributeIds, + ClinicalDataType.PATIENT.name(), + Projection.SUMMARY.name()); + } + + return filteredClinicalDataForPatients; + } + + public List fetchClinicalDataForConflictingPatientAttributes( + List studyIdsOfPatients, + List patientIds, + List conflictingPatientAttributes) { + List filteredClinicalDataForPatients = Collections.emptyList(); + + if (CollectionUtils.isNotEmpty(conflictingPatientAttributes)) { + filteredClinicalDataForPatients = + clinicalDataService.getPatientClinicalDataDetailedToSample( + studyIdsOfPatients, patientIds, conflictingPatientAttributes); + } + + return filteredClinicalDataForPatients; + } + + public List fetchClinicalData( + List studyIds, + List sampleIds, + List patientIds, + List studyIdsOfPatients, + List sampleAttributeIds, + List patientAttributeIds, + List conflictingPatientAttributes) { + List unfilteredClinicalDataForSamples = + fetchClinicalDataForSamples(studyIds, sampleIds, sampleAttributeIds); + + List unfilteredClinicalDataForPatients = + fetchClinicalDataForPatients(studyIdsOfPatients, patientIds, patientAttributeIds); + + List unfilteredClinicalDataForConflictingPatientAttributes = + fetchClinicalDataForConflictingPatientAttributes( + studyIdsOfPatients, patientIds, conflictingPatientAttributes); + + return Stream.of( + unfilteredClinicalDataForSamples, + unfilteredClinicalDataForPatients, + unfilteredClinicalDataForConflictingPatientAttributes) + .flatMap(Collection::stream) + .collect(Collectors.toList()); + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/util/ClinicalDataFilterApplier.java b/src/main/java/org/cbioportal/legacy/web/util/ClinicalDataFilterApplier.java new file mode 100644 index 00000000000..69d8170acbd --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/util/ClinicalDataFilterApplier.java @@ -0,0 +1,108 @@ +package org.cbioportal.legacy.web.util; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; +import org.apache.commons.collections4.map.MultiKeyMap; +import org.cbioportal.legacy.model.ClinicalData; +import org.cbioportal.legacy.model.Patient; +import org.cbioportal.legacy.service.ClinicalDataService; +import org.cbioportal.legacy.service.PatientService; +import org.cbioportal.legacy.web.parameter.ClinicalDataFilter; +import org.cbioportal.legacy.web.parameter.Projection; +import org.cbioportal.legacy.web.parameter.SampleIdentifier; + +public abstract class ClinicalDataFilterApplier implements DataFilterApplier { + private PatientService patientService; + private ClinicalDataService clinicalDataService; + protected StudyViewFilterUtil studyViewFilterUtil; + + public ClinicalDataFilterApplier( + PatientService patientService, + ClinicalDataService clinicalDataService, + StudyViewFilterUtil studyViewFilterUtil) { + this.patientService = patientService; + this.clinicalDataService = clinicalDataService; + this.studyViewFilterUtil = studyViewFilterUtil; + } + + @Override + public List apply( + List sampleIdentifiers, + List clinicalDataFilters, + boolean negateFilters) { + if (!clinicalDataFilters.isEmpty() && !sampleIdentifiers.isEmpty()) { + List studyIds = new ArrayList<>(); + List sampleIds = new ArrayList<>(); + + studyViewFilterUtil.extractStudyAndSampleIds(sampleIdentifiers, studyIds, sampleIds); + + List patients = patientService.getPatientsOfSamples(studyIds, sampleIds); + List patientIds = + patients.stream().map(Patient::getStableId).collect(Collectors.toList()); + List studyIdsOfPatients = + patients.stream().map(Patient::getCancerStudyIdentifier).collect(Collectors.toList()); + + List attributeIds = + clinicalDataFilters.stream() + .map(ClinicalDataFilter::getAttributeId) + .collect(Collectors.toList()); + + List clinicalDataList = new ArrayList(); + + List sampleClinicalDataList = + clinicalDataService.fetchClinicalData( + studyIds, sampleIds, attributeIds, "SAMPLE", Projection.SUMMARY.name()); + clinicalDataList.addAll(sampleClinicalDataList); + + List patientClinicalDataList = + clinicalDataService.getPatientClinicalDataDetailedToSample( + studyIdsOfPatients, patientIds, attributeIds); + clinicalDataList.addAll(patientClinicalDataList); + + clinicalDataList.forEach( + c -> { + c.setAttrValue(c.getAttrValue().toUpperCase()); + if (c.getAttrValue().equals("NAN") || c.getAttrValue().equals("N/A")) { + c.setAttrValue("NA"); + } + }); + + MultiKeyMap clinicalDataMap = new MultiKeyMap(); + for (ClinicalData clinicalData : clinicalDataList) { + clinicalDataMap.put( + clinicalData.getStudyId(), + clinicalData.getSampleId(), + clinicalData.getAttrId(), + clinicalData.getAttrValue()); + } + + List newSampleIdentifiers = new ArrayList<>(); + sampleIdentifiers.forEach( + sampleIdentifier -> { + int count = + apply( + clinicalDataFilters, + clinicalDataMap, + sampleIdentifier.getSampleId(), + sampleIdentifier.getStudyId(), + negateFilters); + + if (count == clinicalDataFilters.size()) { + newSampleIdentifiers.add(sampleIdentifier); + } + }); + + return newSampleIdentifiers; + } + return sampleIdentifiers; + } + + // Must be overridden by child classes + protected abstract Integer apply( + List attributes, + MultiKeyMap clinicalDataMap, + String entityId, + String studyId, + boolean negateFilters); +} diff --git a/src/main/java/org/cbioportal/legacy/web/util/ClinicalDataIntervalFilterApplier.java b/src/main/java/org/cbioportal/legacy/web/util/ClinicalDataIntervalFilterApplier.java new file mode 100644 index 00000000000..108652bb082 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/util/ClinicalDataIntervalFilterApplier.java @@ -0,0 +1,145 @@ +package org.cbioportal.legacy.web.util; + +import com.google.common.collect.Range; +import java.math.BigDecimal; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; +import org.apache.commons.collections4.map.MultiKeyMap; +import org.cbioportal.legacy.model.ClinicalData; +import org.cbioportal.legacy.service.ClinicalDataService; +import org.cbioportal.legacy.service.PatientService; +import org.cbioportal.legacy.web.parameter.ClinicalDataFilter; +import org.cbioportal.legacy.web.parameter.DataFilterValue; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +@Component +public class ClinicalDataIntervalFilterApplier extends ClinicalDataFilterApplier { + + @Autowired + public ClinicalDataIntervalFilterApplier( + PatientService patientService, + ClinicalDataService clinicalDataService, + StudyViewFilterUtil studyViewFilterUtil) { + super(patientService, clinicalDataService, studyViewFilterUtil); + } + + @Override + public Integer apply( + List attributes, + MultiKeyMap clinicalDataMap, + String entityId, + String studyId, + boolean negateFilters) { + int count = 0; + + for (ClinicalDataFilter filter : attributes) { + if (clinicalDataMap.containsKey(studyId, entityId, filter.getAttributeId())) { + String attrValue = (String) clinicalDataMap.get(studyId, entityId, filter.getAttributeId()); + Range rangeValue = calculateRangeValueForAttr(attrValue); + + // find range filters + List> ranges = + filter.getValues().stream() + .map(this::calculateRangeValueForFilter) + .filter(Objects::nonNull) + .collect(Collectors.toList()); + + // find special value filters + List specialValues = + filter.getValues().stream() + .filter(f -> f.getValue() != null) + .map(f -> f.getValue().toUpperCase()) + .collect(Collectors.toList()); + + if (rangeValue != null) { + if (negateFilters ^ ranges.stream().anyMatch(r -> r.encloses(rangeValue))) { + count++; + } + } else if (negateFilters ^ specialValues.contains(attrValue.toUpperCase())) { + count++; + } + } else if (negateFilters ^ containsNA(filter)) { + count++; + } + } + + return count; + } + + private Range calculateRangeValueForAttr(String attrValue) { + if (attrValue == null) { + return null; + } + + BigDecimal min = null; + BigDecimal max = null; + + String value = attrValue.trim(); + + String lte = "<="; + String lt = "<"; + String gte = ">="; + String gt = ">"; + + boolean startInclusive = true; + boolean endInclusive = true; + + try { + if (value.startsWith(lte)) { + max = new BigDecimal(value.substring(lte.length())); + } else if (value.startsWith(lt)) { + max = new BigDecimal(value.substring(lt.length())); + endInclusive = false; + } else if (value.startsWith(gte)) { + min = new BigDecimal(value.substring(gte.length())); + } else if (value.startsWith(gt)) { + min = new BigDecimal(value.substring(gt.length())); + startInclusive = false; + } else { + min = max = new BigDecimal(attrValue); + } + } catch (Exception e) { + // invalid range -- TODO: also support ranges like 20-30? + return null; + } + + return DataBinHelper.calcRange(min, startInclusive, max, endInclusive); + } + + private Range calculateRangeValueForFilter(DataFilterValue filterValue) { + BigDecimal start = filterValue.getStart(); + BigDecimal end = filterValue.getEnd(); + + // default: (start, end] + boolean startInclusive = false; + boolean endInclusive = true; + + // special case: end == start (both inclusive) + if (end != null && end.equals(start)) { + startInclusive = true; + } + + return DataBinHelper.calcRange(start, startInclusive, end, endInclusive); + } + + private Boolean containsNA(ClinicalDataFilter filter) { + return filter.getValues().stream() + .anyMatch(r -> r.getValue() != null && r.getValue().toUpperCase().equals("NA")); + } + + public static MultiKeyMap buildClinicalDataMap(List clinicalDatas) { + MultiKeyMap clinicalDataMap = new MultiKeyMap<>(); + + clinicalDatas.forEach( + clinicalData -> + clinicalDataMap.put( + clinicalData.getStudyId(), + clinicalData.getSampleId(), + clinicalData.getAttrId(), + clinicalData.getAttrValue())); + + return clinicalDataMap; + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/util/CustomDataFilterApplier.java b/src/main/java/org/cbioportal/legacy/web/util/CustomDataFilterApplier.java new file mode 100644 index 00000000000..781a72f6146 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/util/CustomDataFilterApplier.java @@ -0,0 +1,140 @@ +package org.cbioportal.legacy.web.util; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.function.Function; +import java.util.stream.Collectors; +import org.apache.commons.collections4.map.MultiKeyMap; +import org.cbioportal.legacy.service.CustomDataService; +import org.cbioportal.legacy.service.util.CustomDataSession; +import org.cbioportal.legacy.web.parameter.ClinicalDataFilter; +import org.cbioportal.legacy.web.parameter.SampleIdentifier; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +@Component +public class CustomDataFilterApplier implements DataFilterApplier { + + private CustomDataService customDataService; + + private ClinicalDataEqualityFilterApplier equalityFilterApplier; + private ClinicalDataIntervalFilterApplier intervalFilterApplier; + + @Autowired + public CustomDataFilterApplier( + CustomDataService customDataService, + ClinicalDataEqualityFilterApplier equalityFilterApplier, + ClinicalDataIntervalFilterApplier intervalFilterApplier) { + this.customDataService = customDataService; + this.equalityFilterApplier = equalityFilterApplier; + this.intervalFilterApplier = intervalFilterApplier; + } + + @Override + public List apply( + List sampleIdentifiers, + List dataFilters, + boolean negateFilters) { + if (dataFilters.isEmpty() || sampleIdentifiers.isEmpty()) { + return sampleIdentifiers; + } + + final List attributeIds = + dataFilters.stream().map(ClinicalDataFilter::getAttributeId).collect(Collectors.toList()); + + final Map customDataSessions = + customDataService.getCustomDataSessions(attributeIds); + + Map customDataSessionById = + customDataSessions.values().stream() + .collect(Collectors.toMap(CustomDataSession::getId, Function.identity())); + + /* + Custom data entry with: + - key1: studyId; + - key2: sampleId; + - key3: sessionId. + */ + MultiKeyMap customDataByStudySampleSession = new MultiKeyMap<>(); + + customDataSessionById + .values() + .forEach( + customDataSession -> + customDataSession + .getData() + .getData() + .forEach( + datum -> { + String value = datum.getValue().toUpperCase(); + if (value.equals("NAN") || value.equals("N/A")) { + value = "NA"; + } + customDataByStudySampleSession.put( + datum.getStudyId(), + datum.getSampleId(), + customDataSession.getId(), + value); + })); + + return filterCustomData( + dataFilters, + negateFilters, + sampleIdentifiers, + customDataSessionById, + customDataByStudySampleSession); + } + + private List filterCustomData( + List customDataFilters, + boolean negateFilters, + List sampleIdentifiers, + Map customDataSessionById, + MultiKeyMap clinicalDataMap) { + List equalityFilters = new ArrayList<>(); + List intervalFilters = new ArrayList<>(); + + customDataFilters.forEach( + filter -> { + String attributeId = filter.getAttributeId(); + if (!customDataSessionById.containsKey(attributeId)) { + return; + } + if (customDataSessionById + .get(attributeId) + .getData() + .getDatatype() + .equals(CustomDatatype.STRING.name())) { + equalityFilters.add(filter); + } else { + intervalFilters.add(filter); + } + }); + + List filtered = new ArrayList<>(); + sampleIdentifiers.forEach( + sampleIdentifier -> { + int equalityFilterCount = + equalityFilterApplier.apply( + equalityFilters, + clinicalDataMap, + sampleIdentifier.getSampleId(), + sampleIdentifier.getStudyId(), + negateFilters); + int intervalFilterCount = + intervalFilterApplier.apply( + intervalFilters, + clinicalDataMap, + sampleIdentifier.getSampleId(), + sampleIdentifier.getStudyId(), + negateFilters); + if (equalityFilterCount == equalityFilters.size() + && intervalFilterCount == intervalFilters.size()) { + filtered.add(sampleIdentifier); + } + }); + + return filtered; + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/util/CustomDatatype.java b/src/main/java/org/cbioportal/legacy/web/util/CustomDatatype.java new file mode 100644 index 00000000000..49d62111fd6 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/util/CustomDatatype.java @@ -0,0 +1,9 @@ +package org.cbioportal.legacy.web.util; + +public enum CustomDatatype { + /** Categorical data */ + STRING, + + /** Numerical data */ + NUMBER +} diff --git a/src/main/java/org/cbioportal/legacy/web/util/DataBinHelper.java b/src/main/java/org/cbioportal/legacy/web/util/DataBinHelper.java new file mode 100644 index 00000000000..b7353d26e85 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/util/DataBinHelper.java @@ -0,0 +1,530 @@ +package org.cbioportal.legacy.web.util; + +import com.google.common.collect.Range; +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.ListIterator; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; +import org.cbioportal.legacy.model.DataBin; +import org.springframework.util.Assert; + +public class DataBinHelper { + + public static DataBin calcUpperOutlierBin(List gteValues, List gtValues) { + BigDecimal gteMin = gteValues.size() > 0 ? Collections.min(gteValues) : null; + BigDecimal gtMin = gtValues.size() > 0 ? Collections.min(gtValues) : null; + BigDecimal min; + String value; + + if (gtMin == null && gteMin == null) { + // no special outlier + min = null; + value = ">"; + } else if (gtMin == null || (gteMin != null && gteMin.compareTo(gtMin) < 0)) { + min = gteMin; + value = ">="; + } else { + min = gtMin; + value = ">"; + } + + DataBin dataBin = new DataBin(); + + dataBin.setCount(gteValues.size() + gtValues.size()); + dataBin.setSpecialValue(value); + dataBin.setStart(min); + + return dataBin; + } + + public static DataBin calcLowerOutlierBin(List lteValues, List ltValues) { + BigDecimal lteMax = lteValues.size() > 0 ? Collections.max(lteValues) : null; + BigDecimal ltMax = ltValues.size() > 0 ? Collections.max(ltValues) : null; + BigDecimal max; + String specialValue; + + if (ltMax == null && lteMax == null) { + max = null; + specialValue = "<="; + } else if (lteMax == null || (ltMax != null && lteMax.compareTo(ltMax) < 0)) { + max = ltMax; + specialValue = "<"; + } else { + max = lteMax; + specialValue = "<="; + } + + DataBin dataBin = new DataBin(); + + dataBin.setCount(lteValues.size() + ltValues.size()); + dataBin.setSpecialValue(specialValue); + dataBin.setEnd(max); + + return dataBin; + } + + public static List calcQuartileBoundaries(List sortedValues) { + // Edge case: some of Q1, Q2, and Q3 are the same value. + // Solution: reduce bins to represent unique values only. + // Note: cannot use stream.distinct() because BigDecimal does + // not play nice with this (e.g., "2.5E+2" is not identical to "250" + // when using Object.equals()) + final BigDecimal q1 = calcQ1(sortedValues); + final BigDecimal q2 = calcMedian(sortedValues); + final BigDecimal q3 = calcQ3(sortedValues); + List boundaries = new ArrayList<>(); + boundaries.add(q1); + // Check Q1 smaller than Q2 + if (q1.compareTo(q2) < 0) { + boundaries.add(q2); + } + // Check Q2 smaller than Q3 + if (q2.compareTo(q3) < 0) { + boundaries.add(q3); + } + return boundaries; + } + + public static Range calcBoxRange(List sortedValues) { + if (sortedValues == null || sortedValues.size() == 0) { + return null; + } + + // Find a generous IQR. This is generous because if (values.length / 4) + // is not an int, then really you should average the two elements on either + // side to find q1 and q3. + Range interquartileRange = calcInterquartileRangeApproximation(sortedValues); + + BigDecimal q1 = interquartileRange.lowerEndpoint(); + BigDecimal q3 = interquartileRange.upperEndpoint(); + BigDecimal iqr = q3.subtract(q1); + BigDecimal iqrOneAndHalf = iqr.multiply(new BigDecimal("1.5")); + BigDecimal q1LowerBoundry = q1.subtract(iqrOneAndHalf); + BigDecimal q3upperBoundry = q3.add(iqrOneAndHalf); + + // Then find min and max values + BigDecimal maxValue; + BigDecimal minValue; + + if (sortedValues.get(0).compareTo(sortedValues.get(sortedValues.size() - 1)) == 0) { + // if the first and last values are the same, no need to do any other calculation + // we simply set min and max to the same value + minValue = sortedValues.get(0); + maxValue = minValue; + } else if (q3.compareTo(new BigDecimal("0.001")) != -1 + && q3.compareTo(new BigDecimal("1")) < 0) { + // maxValue = Number((q3 + iqr * 1.5).toFixed(3)); + // minValue = Number((q1 - iqr * 1.5).toFixed(3)); + maxValue = q3upperBoundry.setScale(3, BigDecimal.ROUND_HALF_UP); + minValue = q1LowerBoundry.setScale(3, BigDecimal.ROUND_HALF_UP); + } else if (q3.compareTo(BigDecimal.valueOf(0.001)) < 0) { + // get IQR for very small number(<0.001) + maxValue = q3upperBoundry; + minValue = q1LowerBoundry; + } else { + maxValue = q3upperBoundry.setScale(1, RoundingMode.CEILING); + minValue = q1LowerBoundry.setScale(1, RoundingMode.FLOOR); + } + + if (minValue.compareTo(sortedValues.get(0)) < 0) { + minValue = sortedValues.get(0); + } + + if (maxValue.compareTo(sortedValues.get(sortedValues.size() - 1)) > 0) { + maxValue = sortedValues.get(sortedValues.size() - 1); + } + + return Range.closed(minValue, maxValue); + } + + public static Range calcInterquartileRangeApproximation( + List sortedValues) { + Range iqr = null; + + if (sortedValues.size() > 0) { + BigDecimal q1 = valueCloseToQ1(sortedValues); + BigDecimal q3 = valueCloseToQ3(sortedValues); + BigDecimal max = sortedValues.get(sortedValues.size() - 1); + + // if iqr == 0 AND max == q3 then recursively try finding a non-zero iqr approximation. + if (q1.compareTo(q3) == 0 && max.compareTo(q3) == 0) { + // filter out max and try again + iqr = + calcInterquartileRangeApproximation( + sortedValues.stream() + .filter(d -> d.compareTo(max) < 0) + .collect(Collectors.toList())); + } + + // if range is still empty use the original q1 and q3 values + if (iqr == null || iqr.isEmpty()) { + iqr = Range.closedOpen(q1, q3); + } + } + + return iqr; + } + + public static BigDecimal calcQ1(List sortedValues) { + if (sortedValues == null || sortedValues.isEmpty()) { + return null; + } + // Stop is one position before the median array index. + int stopIndex = (int) (sortedValues.size() * 0.5) - 1; + return calcMedian(sortedValues, 0, stopIndex); + } + + public static BigDecimal calcMedian(List sortedValues) { + return (sortedValues == null || sortedValues.isEmpty()) + ? null + : calcMedian(sortedValues, 0, sortedValues.size() - 1); + } + + public static BigDecimal calcQ3(List sortedValues) { + if (sortedValues == null || sortedValues.isEmpty()) { + return null; + } + // Start one position after the median array index. + int startIndex = (int) (sortedValues.size() * 0.5); + if (sortedValues.size() % 2 != 0) { + startIndex += 1; + } + return calcMedian(sortedValues, startIndex, sortedValues.size() - 1); + } + + private static BigDecimal calcMedian(List sortedValues, int start, int stop) { + if (sortedValues == null || sortedValues.isEmpty()) { + return null; + } + final List values = sortedValues.subList(start, stop + 1); + double index = values.size() * 0.5; + BigDecimal value = values.get((int) index); + if (values.size() % 2 != 0) { + return value; + } else { + BigDecimal valueBelow = values.get((int) index - 1); + return value.add(valueBelow).divide(new BigDecimal("2.0")); + } + } + + public static BigDecimal valueCloseToQ1(List sortedValues) { + return (sortedValues == null || sortedValues.isEmpty()) + ? null + : sortedValues.get((int) (sortedValues.size() * 0.25)); + } + + public static BigDecimal valueCloseToQ3(List sortedValues) { + return (sortedValues == null || sortedValues.isEmpty()) + ? null + : sortedValues.get((int) (sortedValues.size() * 0.75)); + } + + public static List filterIntervals( + List intervals, BigDecimal lowerOutlier, BigDecimal upperOutlier) { + // remove values that fall outside the lower and upper outlier limits + return intervals.stream() + .filter( + d -> + (lowerOutlier == null || d.compareTo(lowerOutlier) > 0) + && (upperOutlier == null || d.compareTo(upperOutlier) < 0)) + .collect(Collectors.toList()); + } + + public static List initDataBins( + List values, + List intervals, + BigDecimal lowerOutlier, + BigDecimal upperOutlier) { + return initDataBins(values, filterIntervals(intervals, lowerOutlier, upperOutlier)); + } + + public static List initDataBins(List values, List intervals) { + List dataBins = initDataBins(intervals); + + calcCounts(dataBins, values); + + return dataBins; + } + + public static List initDataBins(List intervalValues) { + List dataBins = new ArrayList<>(); + + for (int i = 0; i < intervalValues.size() - 1; i++) { + DataBin dataBin = new DataBin(); + + dataBin.setCount(0); + dataBin.setStart(intervalValues.get(i)); + dataBin.setEnd(intervalValues.get(i + 1)); + + dataBins.add(dataBin); + } + + return dataBins; + } + + public static List trim(List dataBins) { + List toRemove = new ArrayList<>(); + + // find out leading empty bins + for (DataBin dataBin : dataBins) { + if (dataBin.getCount() == null || dataBin.getCount() <= 0) { + toRemove.add(dataBin); + } else { + break; + } + } + + // find out trailing empty bins + ListIterator iterator = dataBins.listIterator(dataBins.size()); + + while (iterator.hasPrevious()) { + DataBin dataBin = iterator.previous(); + + if (dataBin.getCount() == null || dataBin.getCount() <= 0) { + toRemove.add(dataBin); + } else { + break; + } + } + + List trimmed = new ArrayList<>(dataBins); + trimmed.removeAll(toRemove); + + return trimmed; + } + + public static void calcCounts(List dataBins, List values) { + Map, DataBin> rangeMap = + dataBins.stream().collect(Collectors.toMap(DataBinHelper::calcRange, b -> b)); + + // TODO complexity here is O(n x m), find a better way to do this + for (Range range : rangeMap.keySet()) { + for (BigDecimal value : values) { + // check if the value falls within the data bin range + if (range != null && range.contains(value)) { + DataBin dataBin = rangeMap.get(range); + dataBin.setCount(dataBin.getCount() + 1); + } + } + } + } + + public static Range calcRange(DataBin dataBin) { + boolean startInclusive = ">=".equals(dataBin.getSpecialValue()); + boolean endInclusive = !"<".equals(dataBin.getSpecialValue()); + + // special condition (start == end) + if (dataBin.getStart() != null + && dataBin.getEnd() != null + && dataBin.getStart().compareTo(dataBin.getEnd()) == 0) { + startInclusive = endInclusive = true; + } + + return calcRange(dataBin.getStart(), startInclusive, dataBin.getEnd(), endInclusive); + } + + public static Range calcRange(String operator, BigDecimal value) { + boolean startInclusive = ">=".equals(operator); + BigDecimal start = operator.contains(">") ? value : null; + boolean endInclusive = !"<".equals(operator); + BigDecimal end = operator.contains("<") ? value : null; + + return calcRange(start, startInclusive, end, endInclusive); + } + + public static boolean isNA(String value) { + return value.equalsIgnoreCase("NA") + || value.equalsIgnoreCase("NAN") + || value.equalsIgnoreCase("N/A"); + } + + public static boolean isSmallData(List sortedValues) { + BigDecimal median = sortedValues.get((int) Math.ceil((sortedValues.size() * (1.0 / 2.0)))); + + return median.compareTo(new BigDecimal("0.001")) < 0 + && median.compareTo(new BigDecimal("-0.001")) > 0 + && median.compareTo(new BigDecimal("0")) != 0; + } + + public static String extractOperator(String value) { + int length = 0; + + if (value.trim().startsWith(">=") || value.trim().startsWith("<=")) { + length = 2; + } else if (value.trim().startsWith(">") || value.trim().startsWith("<")) { + length = 1; + } + + return value.trim().substring(0, length); + } + + public static Integer calcExponent(BigDecimal value) { + return value.precision() - value.scale() - 1; + } + + public static String stripOperator(String value) { + int length = 0; + + if (value.trim().startsWith(">=") || value.trim().startsWith("<=")) { + length = 2; + } else if (value.trim().startsWith(">") || value.trim().startsWith("<")) { + length = 1; + } + + return value.trim().substring(length); + } + + public static boolean isAgeAttribute(String attributeId) { + return attributeId != null && attributeId.matches("(^AGE$)|(^AGE_.*)|(.*_AGE_.*)|(.*_AGE&)"); + } + + public static Range calcRange( + BigDecimal start, boolean startInclusive, BigDecimal end, boolean endInclusive) { + // check for invalid filter (no start or end provided) + if (start == null && end == null) { + return null; + } else if (start == null) { + if (endInclusive) { + return Range.atMost(end); + } else { + return Range.lessThan(end); + } + } else if (end == null) { + if (startInclusive) { + return Range.atLeast(start); + } else { + return Range.greaterThan(start); + } + } else if (startInclusive) { + if (endInclusive) { + return Range.closed(start, end); + } else { + return Range.closedOpen(start, end); + } + } else { + if (endInclusive) { + return Range.openClosed(start, end); + } else { + return Range.open(start, end); + } + } + } + + public static Set findDistinctValues( + DataBin numericalBin, List numericalValues) { + Range range = calcRange(numericalBin); + + return numericalValues.stream().filter(range::contains).collect(Collectors.toSet()); + } + + public static Set> findDistinctSpecialRanges( + DataBin numericalBin, List> rangeValues) { + Range range = calcRange(numericalBin); + + return rangeValues.stream().filter(range::encloses).collect(Collectors.toSet()); + } + + public static List convertToDistinctBins( + List dataBins, + List numericalValues, + List> rangeValues) { + List distinctBins = new ArrayList<>(); + + for (DataBin bin : dataBins) { + Set distinctValues = findDistinctValues(bin, numericalValues); + Set> distinctRanges = findDistinctSpecialRanges(bin, rangeValues); + + // if the bin contains only one distinct value and no range value then create a distinct bin + if (distinctRanges.size() == 0 + && distinctValues.size() == 1 + && areAllIntegers(distinctValues)) { + BigDecimal distinctValue = distinctValues.iterator().next(); + + DataBin distinctBin = new DataBin(); + distinctBin.setCount(bin.getCount()); + distinctBin.setStart(distinctValue); + distinctBin.setEnd(distinctValue); + + distinctBins.add(distinctBin); + } + // else keep the bin as is + else { + distinctBins.add(bin); + } + } + + // all bins except the outlier bins has to be distinct, + // otherwise return the original input bins (no conversion) + if (areAllDistinctExceptOutliers(distinctBins)) { + return distinctBins; + } else { + return dataBins; + } + } + + public static Boolean areAllDistinctExceptOutliers(List dataBins) { + return dataBins.stream() + .filter(b -> b.getStart() != null && b.getEnd() != null) + .map(b -> b.getStart().equals(b.getEnd())) + .reduce((a, b) -> a && b) + .orElse(false); + } + + public static Boolean areAllIntegers(Set uniqueValues) { + return uniqueValues.stream() + .map(value -> value.stripTrailingZeros().scale() <= 0) + .reduce((a, b) -> a && b) + .orElse(false); + } + + public static List generateBins( + List sortedNumericalValues, BigDecimal binSize, BigDecimal anchorValue) { + + Assert.notNull(sortedNumericalValues, "sortedNumerical values is null!"); + Assert.notNull(binSize, "binSize values is null!"); + Assert.notNull(anchorValue, "anchorValue values is null!"); + + if (sortedNumericalValues.isEmpty()) { + return null; + } + + // Assumes that elements are sorted in ascending order + BigDecimal minValue = sortedNumericalValues.get(0); + BigDecimal maxValue = sortedNumericalValues.get(sortedNumericalValues.size() - 1); + Assert.isTrue( + minValue.compareTo(maxValue) < 1, + "minValue larger than maxValue. Input is not sorted in ascending order!"); + + List bins = new ArrayList<>(); + + // Calculate the lower boundary. + BigDecimal deltaL = anchorValue.subtract(minValue); + BigDecimal remainderL = deltaL.remainder(binSize); + // remainder() is not modulo; correct for this. + if (remainderL.compareTo(new BigDecimal(0)) < 0) { + remainderL = remainderL.add(binSize); + } + BigDecimal lowerBound = minValue.add(remainderL); + + // While the bound smaller than the maxValue keep adding boundaries. + while (lowerBound.compareTo(maxValue) < 0) { + bins.add(lowerBound); + lowerBound = lowerBound.add(binSize); + } + + return bins; + } + + private BigDecimal min(List numericalValues) { + return numericalValues.size() > 0 ? Collections.min(numericalValues) : null; + } + + private BigDecimal max(List numericalValues) { + return numericalValues.size() > 0 ? Collections.max(numericalValues) : null; + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/util/DataBinner.java b/src/main/java/org/cbioportal/legacy/web/util/DataBinner.java new file mode 100644 index 00000000000..7f170510880 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/util/DataBinner.java @@ -0,0 +1,693 @@ +package org.cbioportal.legacy.web.util; + +import com.google.common.collect.Range; +import java.math.BigDecimal; +import java.util.*; +import java.util.function.Predicate; +import java.util.stream.Collectors; +import org.apache.commons.lang3.math.NumberUtils; +import org.cbioportal.legacy.model.Binnable; +import org.cbioportal.legacy.model.DataBin; +import org.cbioportal.legacy.web.parameter.BinsGeneratorConfig; +import org.cbioportal.legacy.web.parameter.ClinicalDataBinFilter; +import org.cbioportal.legacy.web.parameter.ClinicalDataType; +import org.cbioportal.legacy.web.parameter.DataBinFilter; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +@Component +public class DataBinner { + private static final Integer DEFAULT_DISTINCT_VALUE_THRESHOLD = 10; + + @Autowired private DiscreteDataBinner discreteDataBinner; + @Autowired private LinearDataBinner linearDataBinner; + @Autowired private ScientificSmallDataBinner scientificSmallDataBinner; + @Autowired private LogScaleDataBinner logScaleDataBinner; + + /** + * This method should only be invoked by legacy endpoints because it requires sample/patient ids. + * + * @deprecated + */ + @Deprecated + public List calculateClinicalDataBins( + T dataBinFilter, + ClinicalDataType clinicalDataType, + List filteredClinicalData, + List unfilteredClinicalData, + List filteredIds, + List unfilteredIds) { + // calculate data bins for unfiltered clinical data + List dataBins = + calculateDataBins(dataBinFilter, clinicalDataType, unfilteredClinicalData, unfilteredIds); + + // recount + return recalcBinCount(dataBins, clinicalDataType, filteredClinicalData, filteredIds); + } + + public List calculateClinicalDataBins( + T dataBinFilter, List filteredClinicalData, List unfilteredClinicalData) { + // calculate data bins for unfiltered clinical data + // we need this additional calculation to know the bins generated for the initial state. + // this allows us to keep the number of bins and bin ranges consistent. + // we only want to update the counts for each bin, we don't want to regenerate the bins for the + // filtered data. + List dataBins = calculateDataBins(dataBinFilter, unfilteredClinicalData); + + // recount + return recalcBinCount(dataBins, filteredClinicalData, countNAs(filteredClinicalData)); + } + + /** + * This method should only be invoked by legacy endpoints because it requires sample/patient ids. + * + * @deprecated + */ + @Deprecated + public List recalcBinCount( + List dataBins, + ClinicalDataType clinicalDataType, + List clinicalData, + List caseIds) { + return recalcBinCount( + dataBins, clinicalData, countNAs(clinicalData, clinicalDataType, caseIds)); + } + + public List recalcBinCount( + List dataBins, List clinicalData, Long naCount) { + List numericalValues = + clinicalData == null ? Collections.emptyList() : filterNumericalValues(clinicalData); + List nonNumericalValues = + clinicalData == null ? Collections.emptyList() : filterNonNumericalValues(clinicalData); + List> ranges = + clinicalData == null ? Collections.emptyList() : filterSpecialRanges(clinicalData); + + for (DataBin dataBin : dataBins) { + // reset count + dataBin.setCount(0); + + // calculate range + Range range = DataBinHelper.calcRange(dataBin); + + if (range != null) { + for (BigDecimal value : numericalValues) { + if (range.contains(value)) { + dataBin.setCount(dataBin.getCount() + 1); + } + } + + for (Range r : ranges) { + if (range.encloses(r)) { + dataBin.setCount(dataBin.getCount() + 1); + } + } + } else { // if no range then it means non numerical data bin + for (String value : nonNumericalValues) { + if (value.equalsIgnoreCase(dataBin.getSpecialValue())) { + dataBin.setCount(dataBin.getCount() + 1); + } + } + } + if ("NA".equalsIgnoreCase(dataBin.getSpecialValue())) { + dataBin.setCount(naCount.intValue()); + } + } + + return dataBins; + } + + /** + * This method should only be invoked by legacy endpoints because it requires sample/patient ids. + * + * @deprecated + */ + @Deprecated + public List calculateDataBins( + T dataBinFilter, + ClinicalDataType clinicalDataType, + List clinicalData, + List caseIds) { + return calculateDataBins( + dataBinFilter, clinicalDataType, clinicalData, caseIds, DEFAULT_DISTINCT_VALUE_THRESHOLD); + } + + public List calculateDataBins( + T dataBinFilter, List clinicalData) { + return calculateDataBins(dataBinFilter, clinicalData, DEFAULT_DISTINCT_VALUE_THRESHOLD); + } + + public List calculateDataBins( + T dataBinFilter, List clinicalData, Integer distinctValueThreshold) { + DataBin naDataBin = calcNaDataBin(clinicalData); + + return calculateDataBins(dataBinFilter, clinicalData, naDataBin, distinctValueThreshold); + } + + /** + * This method should only be invoked by legacy endpoints because it requires sample/patient ids. + * + * @deprecated + */ + @Deprecated + public List calculateDataBins( + T dataBinFilter, + ClinicalDataType clinicalDataType, + List clinicalData, + List caseIds, + Integer distinctValueThreshold) { + DataBin naDataBin = calcNaDataBin(clinicalData, clinicalDataType, caseIds); + + return calculateDataBins(dataBinFilter, clinicalData, naDataBin, distinctValueThreshold); + } + + public List calculateDataBins( + T dataBinFilter, + List clinicalData, + DataBin naDataBin, + Integer distinctValueThreshold) { + boolean numericalOnly = false; + + Range range = + dataBinFilter.getStart() == null && dataBinFilter.getEnd() == null + ? Range.all() + : DataBinHelper.calcRange(dataBinFilter.getStart(), true, dataBinFilter.getEnd(), true); + + if (range.hasUpperBound()) { + clinicalData = filterSmallerThanUpperBound(clinicalData, range.upperEndpoint()); + numericalOnly = true; + } + + if (range.hasLowerBound()) { + clinicalData = filterBiggerThanLowerBound(clinicalData, range.lowerEndpoint()); + numericalOnly = true; + } + + DataBin upperOutlierBin = calcUpperOutlierBin(clinicalData); + DataBin lowerOutlierBin = calcLowerOutlierBin(clinicalData); + Collection numericalBins = + calcNumericalClinicalDataBins( + dataBinFilter, + clinicalData, + dataBinFilter.getCustomBins(), + dataBinFilter.getBinMethod(), + dataBinFilter.getBinsGeneratorConfig(), + lowerOutlierBin, + upperOutlierBin, + dataBinFilter.getDisableLogScale(), + distinctValueThreshold); + + List dataBins = new ArrayList<>(); + + if (!lowerOutlierBin.getCount().equals(0)) { + dataBins.add(lowerOutlierBin); + } + + dataBins.addAll(numericalBins); + + if (!upperOutlierBin.getCount().equals(0)) { + dataBins.add(upperOutlierBin); + } + + // remove leading and trailing empty bins before adding non numerical ones + dataBins = DataBinHelper.trim(dataBins); + + // in some cases every numerical bin actually contains only a single discrete value + // convert interval bins to distinct (single value) bins in these cases + dataBins = + DataBinHelper.convertToDistinctBins( + dataBins, filterNumericalValues(clinicalData), filterSpecialRanges(clinicalData)); + + if (!numericalOnly) { + // add non numerical and NA data bins + + dataBins.addAll(calcNonNumericalClinicalDataBins(clinicalData)); + + if (!naDataBin.getCount().equals(0)) { + dataBins.add(naDataBin); + } + } + + return dataBins; + } + + public List> filterSpecialRanges(List clinicalData) { + return clinicalData.stream() + .map(Binnable::getAttrValue) + .filter( + s -> + (s.contains(">") || s.contains("<")) + && + // ignore any invalid values such as >10PY, <20%, etc. + NumberUtils.isCreatable(DataBinHelper.stripOperator(s))) + .map( + v -> + DataBinHelper.calcRange( + // only use "<" or ">" to make sure that we only generate open ranges + DataBinHelper.extractOperator(v).substring(0, 1), + new BigDecimal(DataBinHelper.stripOperator(v)))) + .collect(Collectors.toList()); + } + + public Collection calcNonNumericalClinicalDataBins(List clinicalData) { + return calcNonNumericalDataBins(filterNonNumericalValues(clinicalData)); + } + + public List filterNonNumericalValues(List clinicalData) { + // filter out numerical values and 'NA's + return clinicalData.stream() + .map(Binnable::getAttrValue) + .filter( + s -> !NumberUtils.isCreatable(DataBinHelper.stripOperator(s)) && !DataBinHelper.isNA(s)) + .collect(Collectors.toList()); + } + + public Collection calcNonNumericalDataBins(List nonNumericalValues) { + Map map = new LinkedHashMap<>(); + + for (String value : nonNumericalValues) { + DataBin dataBin = + map.computeIfAbsent( + value.trim().toUpperCase(), + key -> { + DataBin bin = new DataBin(); + bin.setSpecialValue(value.trim()); + bin.setCount(0); + return bin; + }); + + dataBin.setCount(dataBin.getCount() + 1); + } + + return map.values(); + } + + public Collection calcNumericalClinicalDataBins( + DataBinFilter dataBinFilter, + List clinicalData, + List customBins, + DataBinFilter.BinMethod binMethod, + BinsGeneratorConfig binsGeneratorConfig, + DataBin lowerOutlierBin, + DataBin upperOutlierBin, + Boolean disableLogScale, + Integer distinctValueThreshold) { + return calcNumericalDataBins( + dataBinFilter, + filterNumericalValues(clinicalData), + customBins, + binMethod, + binsGeneratorConfig, + lowerOutlierBin, + upperOutlierBin, + disableLogScale, + distinctValueThreshold); + } + + public List filterNumericalValues(List clinicalData) { + // filter out invalid values + return clinicalData.stream() + .filter(c -> NumberUtils.isCreatable(c.getAttrValue())) + .map(c -> new BigDecimal(c.getAttrValue())) + .collect(Collectors.toList()); + } + + public Collection calcNumericalDataBins( + DataBinFilter dataBinFilter, + List numericalValues, + List customBins, + DataBinFilter.BinMethod binMethod, + BinsGeneratorConfig binsGeneratorConfig, + DataBin lowerOutlierBin, + DataBin upperOutlierBin, + Boolean disableLogScale, + Integer distinctValueThreshold) { + + Predicate isLowerOutlier = + d -> + (lowerOutlierBin != null + && lowerOutlierBin.getEnd() != null + && (lowerOutlierBin.getSpecialValue() != null + && lowerOutlierBin.getSpecialValue().contains("=") + ? d.compareTo(lowerOutlierBin.getEnd()) != 1 + : d.compareTo(lowerOutlierBin.getEnd()) == -1)); + + Predicate isUpperOutlier = + d -> + (upperOutlierBin != null + && upperOutlierBin.getStart() != null + && (upperOutlierBin.getSpecialValue() != null + && upperOutlierBin.getSpecialValue().contains("=") + ? d.compareTo(upperOutlierBin.getStart()) != -1 + : d.compareTo(upperOutlierBin.getStart()) == 1)); + + Predicate isNotOutlier = d -> !isUpperOutlier.test(d) && !isLowerOutlier.test(d); + + List sortedNumericalValues = new ArrayList<>(numericalValues); + Collections.sort(sortedNumericalValues); + + Range boxRange = DataBinHelper.calcBoxRange(sortedNumericalValues); + + // remove initial outliers + List withoutOutliers = + sortedNumericalValues.stream().filter(isNotOutlier).collect(Collectors.toList()); + + // calculate data bins for the rest of the values + List dataBins = null; + + Set uniqueValues = new LinkedHashSet<>(withoutOutliers); + + if (0 < uniqueValues.size() && uniqueValues.size() <= distinctValueThreshold) { + // No data intervals when the number of distinct values less than or equal to the threshold. + // In this case, number of bins = number of distinct data values + dataBins = discreteDataBinner.calculateDataBins(withoutOutliers, uniqueValues); + } else if (!withoutOutliers.isEmpty()) { + + if (DataBinFilter.BinMethod.CUSTOM == binMethod && customBins != null) { + // adjust custom bins w.r.t. outliers (if any) + customBins = this.adjustCustomBins(customBins, lowerOutlierBin, upperOutlierBin); + dataBins = linearDataBinner.calculateDataBins(customBins, numericalValues); + } else if (DataBinFilter.BinMethod.GENERATE == binMethod && binsGeneratorConfig != null) { + List bins = + DataBinHelper.generateBins( + sortedNumericalValues, + binsGeneratorConfig.getBinSize(), + binsGeneratorConfig.getAnchorValue()); + dataBins = linearDataBinner.calculateDataBins(bins, numericalValues); + } else if (DataBinFilter.BinMethod.MEDIAN == binMethod) { + // NOOP - handled later + } else if (DataBinFilter.BinMethod.QUARTILE == binMethod) { + List boundaries = DataBinHelper.calcQuartileBoundaries(sortedNumericalValues); + dataBins = linearDataBinner.calculateDataBins(boundaries, numericalValues); + } else if (boxRange + .upperEndpoint() + .subtract(boxRange.lowerEndpoint()) + .compareTo(new BigDecimal(1000)) + == 1 + && (disableLogScale == null || !disableLogScale)) { + dataBins = + logScaleDataBinner.calculateDataBins( + boxRange, withoutOutliers, lowerOutlierBin.getEnd(), upperOutlierBin.getStart()); + } else if (DataBinHelper.isSmallData(sortedNumericalValues)) { + dataBins = + scientificSmallDataBinner.calculateDataBins( + sortedNumericalValues, + withoutOutliers, + lowerOutlierBin.getEnd(), + upperOutlierBin.getStart()); + + // override box range with data bin min & max values (ignoring actual box range for now) + if (!dataBins.isEmpty()) { + boxRange = + Range.closed(dataBins.get(0).getStart(), dataBins.get(dataBins.size() - 1).getEnd()); + } + } else { + Boolean areAllIntegers = DataBinHelper.areAllIntegers(uniqueValues); + + if (areAllIntegers) { + boxRange = + Range.closed( + new BigDecimal(boxRange.lowerEndpoint().longValue()), + new BigDecimal(boxRange.upperEndpoint().longValue())); + } + + BigDecimal lowerOutlier = + lowerOutlierBin.getEnd() == null + ? boxRange.lowerEndpoint() + : boxRange.lowerEndpoint().max(lowerOutlierBin.getEnd()); + BigDecimal upperOutlier = + upperOutlierBin.getStart() == null + ? boxRange.upperEndpoint() + : boxRange.upperEndpoint().min(upperOutlierBin.getStart()); + + Optional attributeId = + dataBinFilter instanceof ClinicalDataBinFilter + ? Optional.of(((ClinicalDataBinFilter) dataBinFilter).getAttributeId()) + : Optional.empty(); + + dataBins = + linearDataBinner.calculateDataBins( + areAllIntegers, boxRange, withoutOutliers, lowerOutlier, upperOutlier, attributeId); + } + + if (DataBinFilter.BinMethod.MEDIAN == binMethod + // In edge cases all quartile values can be identical (all + // values are in the outlier bins). + || (DataBinFilter.BinMethod.QUARTILE == binMethod && dataBins.size() == 0)) { + BigDecimal median = DataBinHelper.calcMedian(sortedNumericalValues); + lowerOutlierBin.setEnd(median); + upperOutlierBin.setStart(median); + // Covers the situation where there is a single custom boundary (i.e. there are only outlier + // bins). + } else if (DataBinFilter.BinMethod.CUSTOM == binMethod + && customBins != null + && customBins.size() == 1) { + lowerOutlierBin.setEnd(customBins.get(0)); + upperOutlierBin.setStart(customBins.get(0)); + } + + // adjust the outlier limits: + // + // - when there is no special outlier values within the original data (like "<=20", ">80") + // then prioritize dataBin values over box range values + // + // - when there is special outlier values within the original data, + // then prioritize special outlier values over dataBin values + + if (lowerOutlierBin.getEnd() == null) { + + BigDecimal end = + dataBins != null && !dataBins.isEmpty() + ? dataBins.get(0).getStart() + : boxRange.lowerEndpoint(); + + lowerOutlierBin.setEnd(end); + } else if (dataBins != null && !dataBins.isEmpty()) { + if (dataBins.get(0).getStart().compareTo(lowerOutlierBin.getEnd()) == 1) { + lowerOutlierBin.setEnd(dataBins.get(0).getStart()); + } else { + dataBins.get(0).setStart(lowerOutlierBin.getEnd()); + } + } + + if (upperOutlierBin.getStart() == null) { + BigDecimal start = + dataBins != null && !dataBins.isEmpty() + ? dataBins.get(dataBins.size() - 1).getEnd() + : boxRange.upperEndpoint(); + + upperOutlierBin.setStart(start); + } else if (dataBins != null && !dataBins.isEmpty()) { + if (dataBins.get(dataBins.size() - 1).getEnd().compareTo(upperOutlierBin.getStart()) + == -1) { + upperOutlierBin.setStart(dataBins.get(dataBins.size() - 1).getEnd()); + } else { + dataBins.get(dataBins.size() - 1).setEnd(upperOutlierBin.getStart()); + } + } + } + + // update upper and lower outlier counts + List upperOutliers = + sortedNumericalValues.stream().filter(isUpperOutlier).collect(Collectors.toList()); + List lowerOutliers = + sortedNumericalValues.stream().filter(isLowerOutlier).collect(Collectors.toList()); + + if (upperOutliers.size() > 0) { + upperOutlierBin.setCount(upperOutlierBin.getCount() + upperOutliers.size()); + } + + if (lowerOutliers.size() > 0) { + lowerOutlierBin.setCount(lowerOutlierBin.getCount() + lowerOutliers.size()); + } + + if (dataBins == null) { + dataBins = Collections.emptyList(); + } + + return dataBins; + } + + public List doubleValuesForSpecialOutliers( + List clinicalData, String operator) { + return ( + // find the ones starting with the operator + clinicalData.stream() + .filter(c -> c.getAttrValue().trim().startsWith(operator)) + // strip the operator + .map(c -> c.getAttrValue().trim().substring(operator.length())) + // filter out invalid values + .filter(NumberUtils::isCreatable) + // parse the numerical value as a BigDecimal instance + .map(integer -> new BigDecimal(integer)) + // collect as list + .collect(Collectors.toList())); + } + + public List filterSmallerThanUpperBound(List clinicalData, BigDecimal value) { + return (clinicalData.stream() + .filter( + c -> + NumberUtils.isCreatable(c.getAttrValue()) + && new BigDecimal(c.getAttrValue()).compareTo(value) != 1) + .collect(Collectors.toList())); + } + + public List filterBiggerThanLowerBound(List clinicalData, BigDecimal value) { + return (clinicalData.stream() + .filter( + c -> + NumberUtils.isCreatable(c.getAttrValue()) + && new BigDecimal(c.getAttrValue()).compareTo(value) != -1) + // collect as list + .collect(Collectors.toList())); + } + + public DataBin calcUpperOutlierBin(List clinicalData) { + DataBin dataBin = + DataBinHelper.calcUpperOutlierBin( + doubleValuesForSpecialOutliers(clinicalData, ">="), + doubleValuesForSpecialOutliers(clinicalData, ">")); + + // for consistency always set operator to ">" + dataBin.setSpecialValue(">"); + + return dataBin; + } + + public DataBin calcLowerOutlierBin(List clinicalData) { + DataBin dataBin = + DataBinHelper.calcLowerOutlierBin( + doubleValuesForSpecialOutliers(clinicalData, "<="), + doubleValuesForSpecialOutliers(clinicalData, "<")); + + // for consistency always set operator to "<=" + dataBin.setSpecialValue("<="); + + return dataBin; + } + + /** + * We cannot do an exact calculation for values below/above the special outlier values. We need to + * adjust custom bins for those cases. + * + *

example: assume we have special values <18 and >90 in our dataset custom bins => [10, 15, + * 40, 70, 95, 100] adjusted custom bins => [18, 40, 70, 90] + */ + public List adjustCustomBins( + List customBins, DataBin lowerOutlierBin, DataBin upperOutlierBin) { + BigDecimal lowerBound = lowerOutlierBin.getEnd(); + BigDecimal upperBound = upperOutlierBin.getStart(); + + // filter out values less than lower bound and greater than the upper bound + List binsWithinBounds = + customBins.stream() + .filter(bin -> lowerBound == null || bin.compareTo(lowerBound) != -1) + .filter(bin -> upperBound == null || bin.compareTo(upperBound) != 1) + .collect(Collectors.toList()); + + // we need to add back lower bound if we removed values below the lower bound from the original + // bin list + if (customBins.stream() + .anyMatch(bin -> lowerBound != null && bin.compareTo(lowerBound) == -1)) { + binsWithinBounds.add(0, lowerBound); + } + + // we need to add back upper bound if we removed values above the upper bound from the original + // bin list + if (customBins.stream().anyMatch(bin -> upperBound != null && bin.compareTo(upperBound) == 1)) { + binsWithinBounds.add(upperBound); + } + + return binsWithinBounds; + } + + /** + * NA count is: Number of clinical data marked actually as "NA" + Number of patients/samples + * without clinical data. Assuming that clinical data is for a single attribute. + * + *

This method should only be invoked by legacy endpoints because it requires sample/patient + * ids. + * + * @param clinicalData clinical data list for a single attribute + * @param caseIds sample/patient ids + * @return 'NA' clinical data count as a DataBin instance + * @deprecated + */ + @Deprecated + public DataBin calcNaDataBin( + List clinicalData, ClinicalDataType clinicalDataType, List caseIds) { + DataBin bin = initNaDataBin(); + bin.setCount(countNAs(clinicalData, clinicalDataType, caseIds).intValue()); + + return bin; + } + + /** + * This function assumes that all the NA values are already in the provided clinical data list. + * + * @param clinicalData clinical data list for a single attribute + * @return 'NA' clinical data count as a DataBin instance + */ + public DataBin calcNaDataBin(List clinicalData) { + DataBin bin = initNaDataBin(); + bin.setCount(countNAs(clinicalData).intValue()); + + return bin; + } + + public DataBin initNaDataBin() { + DataBin bin = new DataBin(); + bin.setSpecialValue("NA"); + return bin; + } + + /** + * This method should only be invoked by legacy endpoints because it requires sample/patient ids + * + * @deprecated + */ + @Deprecated + public Long countNAs( + List clinicalData, ClinicalDataType clinicalDataType, List caseIds) { + // Calculate the number of clinical data marked actually as "NA", "NAN", or "N/A" + + Long count = countNAs(clinicalData); + + // Calculate number of patients/samples without clinical data + + Set uniqueClinicalDataIds; + + if (clinicalData != null) { + uniqueClinicalDataIds = + clinicalData.stream() + .filter(Objects::nonNull) + .map(datum -> computeUniqueCaseId(datum, clinicalDataType)) + .collect(Collectors.toSet()); + } else { + uniqueClinicalDataIds = Collections.emptySet(); + } + + Set uniqueInputIds = new HashSet<>(caseIds); + + // remove the ids with existing clinical data, + // size of the difference (of two sets) is the count we need + uniqueInputIds.removeAll(uniqueClinicalDataIds); + count += uniqueInputIds.size(); + + return count; + } + + /** Calculate number of clinical data marked actually as "NA", "NAN", or "N/A" */ + public Long countNAs(List clinicalData) { + return clinicalData == null + ? 0 + : clinicalData.stream().filter(c -> DataBinHelper.isNA(c.getAttrValue())).count(); + } + + private String computeUniqueCaseId(Binnable clinicalData, ClinicalDataType clinicalDataType) { + return clinicalData.getStudyId() + + (clinicalDataType == ClinicalDataType.PATIENT + ? clinicalData.getPatientId() + : clinicalData.getSampleId()); + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/util/DataFilterApplier.java b/src/main/java/org/cbioportal/legacy/web/util/DataFilterApplier.java new file mode 100644 index 00000000000..3e4ab973727 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/util/DataFilterApplier.java @@ -0,0 +1,11 @@ +package org.cbioportal.legacy.web.util; + +import java.util.List; +import org.cbioportal.legacy.web.parameter.DataFilter; +import org.cbioportal.legacy.web.parameter.SampleIdentifier; + +public interface DataFilterApplier { + + List apply( + List sampleIdentifiers, List dataFilters, boolean negateFilters); +} diff --git a/src/main/java/org/cbioportal/legacy/web/util/DensityPlotParameters.java b/src/main/java/org/cbioportal/legacy/web/util/DensityPlotParameters.java new file mode 100644 index 00000000000..a22bd10ff87 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/util/DensityPlotParameters.java @@ -0,0 +1,136 @@ +package org.cbioportal.legacy.web.util; + +import java.math.BigDecimal; + +public class DensityPlotParameters { + private final Integer xAxisBinCount; + private final Integer yAxisBinCount; + private final BigDecimal xAxisStart; + private final BigDecimal xAxisEnd; + private final BigDecimal yAxisStart; + private final BigDecimal yAxisEnd; + private final Boolean xAxisLogScale; + private final Boolean yAxisLogScale; + private final String xAxisAttributeId; + private final String yAxisAttributeId; + + DensityPlotParameters(Builder builder) { + this.xAxisBinCount = builder.xAxisBinCount; + this.yAxisBinCount = builder.yAxisBinCount; + this.xAxisStart = builder.xAxisStart; + this.xAxisEnd = builder.xAxisEnd; + this.yAxisStart = builder.yAxisStart; + this.yAxisEnd = builder.yAxisEnd; + this.xAxisAttributeId = builder.xAxisAttributeId; + this.yAxisAttributeId = builder.yAxisAttributeId; + this.xAxisLogScale = builder.xAxisLogScale; + this.yAxisLogScale = builder.yAxisLogScale; + } + + public Integer getXAxisBinCount() { + return xAxisBinCount; + } + + public Integer getYAxisBinCount() { + return yAxisBinCount; + } + + public BigDecimal getXAxisStart() { + return xAxisStart; + } + + public BigDecimal getXAxisEnd() { + return xAxisEnd; + } + + public BigDecimal getYAxisStart() { + return yAxisStart; + } + + public BigDecimal getYAxisEnd() { + return yAxisEnd; + } + + public Boolean getXAxisLogScale() { + return xAxisLogScale; + } + + public Boolean getYAxisLogScale() { + return yAxisLogScale; + } + + public String getXAxisAttributeId() { + return xAxisAttributeId; + } + + public String getYAxisAttributeId() { + return yAxisAttributeId; + } + + public static class Builder { + private Integer xAxisBinCount; + private Integer yAxisBinCount; + private BigDecimal xAxisStart; + private BigDecimal xAxisEnd; + private BigDecimal yAxisStart; + private BigDecimal yAxisEnd; + private Boolean xAxisLogScale; + private Boolean yAxisLogScale; + private String xAxisAttributeId; + private String yAxisAttributeId; + + public Builder xAxisBinCount(Integer xAxisBinCount) { + this.xAxisBinCount = xAxisBinCount; + return this; + } + + public Builder yAxisBinCount(Integer yAxisBinCount) { + this.yAxisBinCount = yAxisBinCount; + return this; + } + + public Builder xAxisStart(BigDecimal xAxisStart) { + this.xAxisStart = xAxisStart; + return this; + } + + public Builder xAxisEnd(BigDecimal xAxisEnd) { + this.xAxisEnd = xAxisEnd; + return this; + } + + public Builder yAxisStart(BigDecimal yAxisStart) { + this.yAxisStart = yAxisStart; + return this; + } + + public Builder yAxisEnd(BigDecimal yAxisEnd) { + this.yAxisEnd = yAxisEnd; + return this; + } + + public Builder xAxisLogScale(Boolean xAxisLogScale) { + this.xAxisLogScale = xAxisLogScale; + return this; + } + + public Builder yAxisLogScale(Boolean yAxisLogScale) { + this.yAxisLogScale = yAxisLogScale; + return this; + } + + public Builder xAxisAttributeId(String xAxisAttributeId) { + this.xAxisAttributeId = xAxisAttributeId; + return this; + } + + public Builder yAxisAttributeId(String yAxisAttributeId) { + this.yAxisAttributeId = yAxisAttributeId; + return this; + } + + public DensityPlotParameters build() { + return new DensityPlotParameters(this); + } + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/util/DiscreteDataBinner.java b/src/main/java/org/cbioportal/legacy/web/util/DiscreteDataBinner.java new file mode 100644 index 00000000000..7507744f38b --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/util/DiscreteDataBinner.java @@ -0,0 +1,37 @@ +package org.cbioportal.legacy.web.util; + +import java.math.BigDecimal; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; +import org.cbioportal.legacy.model.DataBin; +import org.springframework.stereotype.Component; + +@Component +public class DiscreteDataBinner { + + public List calculateDataBins(List values, Set uniqueValues) { + List dataBins = initDataBins(uniqueValues); + + DataBinHelper.calcCounts(dataBins, values); + + return dataBins; + } + + public List initDataBins(Set uniqueValues) { + return uniqueValues.stream() + .map( + d -> { + DataBin dataBin = new DataBin(); + + dataBin.setCount(0); + + // set both start and end to the same value + dataBin.setStart(d); + dataBin.setEnd(d); + + return dataBin; + }) + .collect(Collectors.toList()); + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/util/GoogleAnalyticsInterceptor.java b/src/main/java/org/cbioportal/legacy/web/util/GoogleAnalyticsInterceptor.java new file mode 100644 index 00000000000..8800cdca1fe --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/util/GoogleAnalyticsInterceptor.java @@ -0,0 +1,124 @@ +package org.cbioportal.legacy.web.util; + +import jakarta.annotation.PostConstruct; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import java.util.Arrays; +import java.util.concurrent.CompletableFuture; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; +import org.springframework.http.*; +import org.springframework.stereotype.Component; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.web.client.RestClientException; +import org.springframework.web.client.RestTemplate; +import org.springframework.web.servlet.HandlerInterceptor; + +// TODO: Double check, needed to convert HandlerInterceptorAdapter to HandlerInterceptor +@Component +@ConditionalOnExpression( + "!'${google.analytics.tracking.code.api:}'.isEmpty() || !'${google.analytics.application.client.id:}'.isEmpty()") +public class GoogleAnalyticsInterceptor implements HandlerInterceptor { + + private static final Logger LOG = LoggerFactory.getLogger(GoogleAnalyticsInterceptor.class); + + @Value("${google.analytics.tracking.code.api:}") + private String trackingId; + + @Value("${google.analytics.application.client.id:}") + private String clientId; + + private static HttpHeaders defaultHeaders; + private static LinkedMultiValueMap globalURIVariables; + private boolean missingGoogleAnalyticsCredentials; + + @PostConstruct + private void initializeDefaultParams() { + + missingGoogleAnalyticsCredentials = trackingId.isEmpty() || clientId.isEmpty(); + if (missingGoogleAnalyticsCredentials) { + if (LOG.isInfoEnabled()) { + LOG.info("@PostContruct:"); + LOG.info("Google Analytics tracking id: {}", trackingId); + LOG.info("Google Analytics client id: {}", clientId); + } + return; + } + + defaultHeaders = new HttpHeaders(); + defaultHeaders.setAccept(Arrays.asList(MediaType.ALL)); + defaultHeaders.setContentType(MediaType.APPLICATION_FORM_URLENCODED); + defaultHeaders.set( + HttpHeaders.USER_AGENT, + "cBioPortal API Reporting/1.0 via org.cbioportal.web.util.GoogleAnalyticsInterceptor"); + + globalURIVariables = new LinkedMultiValueMap<>(); + globalURIVariables.add("v", "1"); + globalURIVariables.add("dt", "request logged by GoogleAnalyticsInterceptor"); + globalURIVariables.add("t", "pageview"); + globalURIVariables.add("tid", trackingId); + globalURIVariables.add("cid", clientId); + globalURIVariables.add("dh", "cbioportal.org"); + } + + @Override + public void afterCompletion( + HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) { + + if (invalidAfterCompletionArgs(response)) { + return; + } + + CompletableFuture.runAsync( + () -> { + LinkedMultiValueMap thisTasksURIVariables = new LinkedMultiValueMap<>(); + thisTasksURIVariables.putAll(globalURIVariables); + thisTasksURIVariables.add("dp", request.getRequestURI()); + HttpEntity> requestEntity = + new HttpEntity<>(thisTasksURIVariables, defaultHeaders); + try { + RestTemplate restTemplate = new RestTemplate(); + ResponseEntity responseEntity = + restTemplate.exchange( + "https://www.google-analytics.com/collect", + HttpMethod.POST, + requestEntity, + String.class); + HttpStatusCode responseStatus = responseEntity.getStatusCode(); + if (responseStatus.is2xxSuccessful()) { + if (LOG.isInfoEnabled()) { + LOG.info( + "CompletableFuture.runAsync(): POST request successfully sent to Google Analytics: "); + LOG.info(requestEntity.toString()); + } + } else { + if (LOG.isInfoEnabled()) { + LOG.info( + "CompletableFuture.runAsync(): POST request to Google Analytics failed. HTTP status code: " + + Integer.toString(responseStatus.value())); + } + } + } catch (RestClientException e) { + e.printStackTrace(); + } + }); + } + + // TODO I think this bean should not be created when no Google analytics are configured. + private boolean invalidAfterCompletionArgs(HttpServletResponse response) { + if (missingGoogleAnalyticsCredentials || response.getHeader("referer") != null) { + if (LOG.isInfoEnabled()) { + LOG.info("afterCompletion() cannot be completed:"); + if (missingGoogleAnalyticsCredentials) { + LOG.info("Invalid Google Analytics credentials (see @PostConstruct log entry)"); + } else { + LOG.info("Response referer is not null"); + } + } + return true; + } + return false; + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/util/GzippedInputStreamRequestWrapper.java b/src/main/java/org/cbioportal/legacy/web/util/GzippedInputStreamRequestWrapper.java new file mode 100644 index 00000000000..d95342ecfee --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/util/GzippedInputStreamRequestWrapper.java @@ -0,0 +1,96 @@ +package org.cbioportal.legacy.web.util; + +import jakarta.servlet.ReadListener; +import jakarta.servlet.ServletInputStream; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequestWrapper; +import java.io.*; +import java.util.zip.GZIPInputStream; + +public class GzippedInputStreamRequestWrapper extends HttpServletRequestWrapper { + public static final int BUFFER_SIZE = 1024; + private final ByteArrayInputStream inputStream; + + GzippedInputStreamRequestWrapper(final HttpServletRequest request, int maxInflatedRequestBodySize) + throws IOException { + super(request); + inputStream = inflate(request.getInputStream(), maxInflatedRequestBodySize); + } + + @Override + public ServletInputStream getInputStream() throws IOException { + return new ServletInputStream() { + @Override + public int read() { + return inputStream.read(); + } + + @Override + public int readLine(byte[] b, int off, int len) throws IOException { + return super.readLine(b, off, len); + } + + @Override + public boolean isFinished() { + return true; + } + + @Override + public boolean isReady() { + return false; + } + + @Override + public void setReadListener(ReadListener readListener) {} + + @Override + public int read(byte[] bytes) throws IOException { + return super.read(bytes); + } + + @Override + public int read(byte[] bytes, int i, int i1) throws IOException { + return super.read(bytes, i, i1); + } + + @Override + public void close() throws IOException { + super.close(); + inputStream.close(); + } + }; + } + + @Override + public BufferedReader getReader() throws IOException { + return new BufferedReader(new InputStreamReader(getInputStream())); + } + + /** + * Inflates the compressed input stream all at once. Previously, we wrapped the compressed + * ServletInputStream stream with a GZIPInputStream, and read from that gradually. For some + * reason, that approach resulted in very long inflation times. By reading out everything from the + * GZIPInputStream here in the constructor, we managed to get down to the sub second performance + * you would expect with gzipping. + */ + private ByteArrayInputStream inflate( + ServletInputStream requestStream, int maxInflatedRequestBodySize) throws IOException { + GZIPInputStream gzipInputStream = new GZIPInputStream(requestStream, BUFFER_SIZE); + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + byte[] buffer = new byte[BUFFER_SIZE]; + int len; + long byteCount = 0; + + while ((len = gzipInputStream.read(buffer)) > 0) { + outputStream.write(buffer, 0, len); + byteCount += BUFFER_SIZE; + + if (byteCount > maxInflatedRequestBodySize) { + throw new IOException( + "Inflated request body too large (> " + maxInflatedRequestBodySize + " bytes)"); + } + } + + return new ByteArrayInputStream(outputStream.toByteArray()); + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/util/HttpRequestUtils.java b/src/main/java/org/cbioportal/legacy/web/util/HttpRequestUtils.java new file mode 100644 index 00000000000..51f78edb881 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/util/HttpRequestUtils.java @@ -0,0 +1,33 @@ +package org.cbioportal.legacy.web.util; + +import jakarta.servlet.http.HttpServletRequest; +import java.util.Enumeration; +import org.json.simple.JSONObject; +import org.springframework.stereotype.Component; + +@Component +public class HttpRequestUtils { + + public JSONObject getPostData(HttpServletRequest request) { + // To support posted query data (when data would exceed URL length), + // write all post params to json on page where it can be consumed. + JSONObject paramsJson = new JSONObject(); + if (request.getMethod().equals("POST")) { + Enumeration parameterNames = request.getParameterNames(); + while (parameterNames.hasMoreElements()) { + String parameterName = parameterNames.nextElement(); + paramsJson.put(parameterName, request.getParameter(parameterName)); + } + } + return paramsJson; + } + + public String getBaseUrl(HttpServletRequest request) { + String currentUrl = request.getRequestURL().toString(); + String contextPath = request.getContextPath(); + String baseURL = + currentUrl.substring(0, currentUrl.length() - request.getRequestURI().length()) + + contextPath; + return baseURL.replaceAll("https?://", ""); + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/util/IdPopulator.java b/src/main/java/org/cbioportal/legacy/web/util/IdPopulator.java new file mode 100644 index 00000000000..1000bf15ff7 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/util/IdPopulator.java @@ -0,0 +1,56 @@ +package org.cbioportal.legacy.web.util; + +import java.util.List; +import org.cbioportal.legacy.model.ClinicalAttribute; +import org.cbioportal.legacy.service.PatientService; +import org.cbioportal.legacy.service.util.ClinicalAttributeUtil; +import org.cbioportal.legacy.web.parameter.SampleIdentifier; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +@Component +public class IdPopulator { + + @Autowired private ClinicalAttributeUtil clinicalAttributeUtil; + @Autowired private StudyViewFilterApplier studyViewFilterApplier; + @Autowired private StudyViewFilterUtil studyViewFilterUtil; + @Autowired private PatientService patientService; + + public IdPopulator() {} + + public BinningIds populateIdLists( + List samples, List clinicalAttributes) { + BinningIds binningIds = new BinningIds(); + List studyIds = binningIds.getStudyIds(); + List sampleIds = binningIds.getSampleIds(); + List patientIds = binningIds.getPatientIds(); + List studyIdsOfPatients = binningIds.getStudyIdsOfPatients(); + List uniqueSampleKeys = binningIds.getUniqueSampleKeys(); + List uniquePatientKeys = binningIds.getUniquePatientKeys(); + List sampleAttributeIds = binningIds.getSampleAttributeIds(); + List patientAttributeIds = binningIds.getPatientAttributeIds(); + List conflictingPatientAttributeIds = binningIds.getConflictingPatientAttributeIds(); + + studyViewFilterUtil.extractStudyAndSampleIds(samples, studyIds, sampleIds); + + patientService + .getPatientsOfSamples(studyIds, sampleIds) + .forEach( + patient -> { + patientIds.add(patient.getStableId()); + studyIdsOfPatients.add(patient.getCancerStudyIdentifier()); + }); + + uniqueSampleKeys.addAll(studyViewFilterApplier.getUniqkeyKeys(studyIds, sampleIds)); + uniquePatientKeys.addAll(studyViewFilterApplier.getUniqkeyKeys(studyIdsOfPatients, patientIds)); + + if (clinicalAttributes != null && !clinicalAttributes.isEmpty()) { + clinicalAttributeUtil.extractCategorizedClinicalAttributes( + clinicalAttributes, + sampleAttributeIds, + patientAttributeIds, + conflictingPatientAttributeIds); + } + return binningIds; + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/util/InvolvedCancerStudyExtractorInterceptor.java b/src/main/java/org/cbioportal/legacy/web/util/InvolvedCancerStudyExtractorInterceptor.java new file mode 100644 index 00000000000..c98dd04e83d --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/util/InvolvedCancerStudyExtractorInterceptor.java @@ -0,0 +1,1132 @@ +/* + * Copyright (c) 2019 Memorial Sloan-Kettering Cancer Center. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS + * FOR A PARTICULAR PURPOSE. The software and documentation provided hereunder + * is on an "as is" basis, and Memorial Sloan-Kettering Cancer Center has no + * obligations to provide maintenance, support, updates, enhancements or + * modifications. In no event shall Memorial Sloan-Kettering Cancer Center be + * liable to any party for direct, indirect, special, incidental or + * consequential damages, including lost profits, arising out of the use of this + * software and its documentation, even if Memorial Sloan-Kettering Cancer + * Center has been advised of the possibility of such damage. + */ + +/* + * This file is part of cBioPortal. + * + * cBioPortal is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package org.cbioportal.legacy.web.util; + +import com.fasterxml.jackson.databind.ObjectMapper; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; +import org.cbioportal.legacy.model.AlterationFilter; +import org.cbioportal.legacy.model.MolecularProfile; +import org.cbioportal.legacy.model.MolecularProfileCaseIdentifier; +import org.cbioportal.legacy.model.SampleList; +import org.cbioportal.legacy.persistence.cachemaputil.CacheMapUtil; +import org.cbioportal.legacy.web.parameter.ClinicalAttributeCountFilter; +import org.cbioportal.legacy.web.parameter.ClinicalDataBinCountFilter; +import org.cbioportal.legacy.web.parameter.ClinicalDataCountFilter; +import org.cbioportal.legacy.web.parameter.ClinicalDataIdentifier; +import org.cbioportal.legacy.web.parameter.ClinicalDataMultiStudyFilter; +import org.cbioportal.legacy.web.parameter.ClinicalEventAttributeRequest; +import org.cbioportal.legacy.web.parameter.GenePanelDataMultipleStudyFilter; +import org.cbioportal.legacy.web.parameter.GenericAssayDataBinCountFilter; +import org.cbioportal.legacy.web.parameter.GenericAssayDataCountFilter; +import org.cbioportal.legacy.web.parameter.GenericAssayDataMultipleStudyFilter; +import org.cbioportal.legacy.web.parameter.GenomicDataBinCountFilter; +import org.cbioportal.legacy.web.parameter.GenomicDataCountFilter; +import org.cbioportal.legacy.web.parameter.GroupFilter; +import org.cbioportal.legacy.web.parameter.MolecularDataMultipleStudyFilter; +import org.cbioportal.legacy.web.parameter.MolecularProfileCasesGroupAndAlterationTypeFilter; +import org.cbioportal.legacy.web.parameter.MolecularProfileCasesGroupFilter; +import org.cbioportal.legacy.web.parameter.MolecularProfileFilter; +import org.cbioportal.legacy.web.parameter.MutationMultipleStudyFilter; +import org.cbioportal.legacy.web.parameter.NamespaceAttributeCountFilter; +import org.cbioportal.legacy.web.parameter.NamespaceDataCountFilter; +import org.cbioportal.legacy.web.parameter.PatientFilter; +import org.cbioportal.legacy.web.parameter.PatientIdentifier; +import org.cbioportal.legacy.web.parameter.SampleFilter; +import org.cbioportal.legacy.web.parameter.SampleIdentifier; +import org.cbioportal.legacy.web.parameter.SampleMolecularIdentifier; +import org.cbioportal.legacy.web.parameter.StructuralVariantFilter; +import org.cbioportal.legacy.web.parameter.StudyViewFilter; +import org.cbioportal.legacy.web.parameter.SurvivalRequest; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.servlet.HandlerInterceptor; + +public class InvolvedCancerStudyExtractorInterceptor implements HandlerInterceptor { + + private ObjectMapper objectMapper = new ObjectMapper(); + + @Autowired private CacheMapUtil cacheMapUtil; + + private static final Logger LOG = + LoggerFactory.getLogger(InvolvedCancerStudyExtractorInterceptor.class); + public static final String PATIENT_FETCH_PATH = "/patients/fetch"; + public static final String SAMPLE_FETCH_PATH = "/samples/fetch"; + public static final String MOLECULAR_PROFILE_FETCH_PATH = "/molecular-profiles/fetch"; + public static final String CLINICAL_ATTRIBUTE_COUNT_FETCH_PATH = + "/clinical-attributes/counts/fetch"; + public static final String NAMESPACE_ATTRIBUTE_COUNT_FETCH_PATH = + "/namespace-attributes/counts/fetch"; + public static final String CLINICAL_DATA_FETCH_PATH = "/clinical-data/fetch"; + public static final String GENE_PANEL_DATA_FETCH_PATH = "/gene-panel-data/fetch"; + public static final String MOLECULAR_DATA_MULTIPLE_STUDY_FETCH_PATH = "/molecular-data/fetch"; + public static final String MUTATION_MULTIPLE_STUDY_FETCH_PATH = "/mutations/fetch"; + public static final String COPY_NUMBER_SEG_FETCH_PATH = "/copy-number-segments/fetch"; + public static final String STUDY_VIEW_CLINICAL_DATA_BIN_COUNTS_PATH = + "/clinical-data-bin-counts/fetch"; + public static final String STUDY_VIEW_CUSTOM_DATA_BIN_COUNTS_PATH = + "/custom-data-bin-counts/fetch"; + public static final String STUDY_VIEW_GENOMICL_DATA_BIN_COUNTS_PATH = + "/genomic-data-bin-counts/fetch"; + public static final String STUDY_VIEW_GENOMICL_DATA_COUNTS_PATH = "/genomic-data-counts/fetch"; + public static final String STUDY_VIEW_MUTATION_DATA_COUNTS_PATH = "/mutation-data-counts/fetch"; + public static final String STUDY_VIEW_GENERIC_ASSAY_DATA_BIN_COUNTS_PATH = + "/generic-assay-data-bin-counts/fetch"; + public static final String STUDY_VIEW_GENERIC_ASSAY_DATA_COUNTS_PATH = + "/generic-assay-data-counts/fetch"; + public static final String STUDY_VIEW_CLINICAL_DATA_COUNTS_PATH = "/clinical-data-counts/fetch"; + public static final String STUDY_VIEW_NAMESPACE_DATA_COUNTS_PATH = "/namespace-data-counts/fetch"; + public static final String STUDY_VIEW_CUSTOM_DATA_COUNTS_PATH = "/custom-data-counts/fetch"; + public static final String STUDY_VIEW_CLINICAL_DATA_DENSITY_PATH = + "/clinical-data-density-plot/fetch"; + public static final String STUDY_VIEW_CLINICAL_DATA_VIOLIN_PATH = + "/clinical-data-violin-plots/fetch"; + public static final String STUDY_VIEW_CNA_GENES = "/cna-genes/fetch"; + public static final String STUDY_VIEW_FILTERED_SAMPLES = "/filtered-samples/fetch"; + public static final String STUDY_VIEW_MUTATED_GENES = "/mutated-genes/fetch"; + public static final String STUDY_VIEW_STRUCTURAL_VARIANT_GENES = "/structuralvariant-genes/fetch"; + public static final String STUDY_VIEW_STRUCTURAL_VARIANT_COUNTS = + "/structuralvariant-counts/fetch"; + public static final String STUDY_VIEW_SAMPLE_COUNTS = "/sample-counts/fetch"; + public static final String STUDY_VIEW_SAMPLE_LIST_COUNTS_PATH = "/sample-lists-counts/fetch"; + public static final String STUDY_VIEW_CLINICAL_TABLE_DATA_FETCH_PATH = + "/clinical-data-table/fetch"; + public static final String STUDY_VIEW_PROFILE_SAMPLE_COUNTS_PATH = + "/molecular-profile-sample-counts/fetch"; + public static final String CLINICAL_DATA_ENRICHMENT_FETCH_PATH = + "/clinical-data-enrichments/fetch"; + public static final String MUTATION_ENRICHMENT_FETCH_PATH = "/mutation-enrichments/fetch"; + public static final String COPY_NUMBER_ENRICHMENT_FETCH_PATH = "/copy-number-enrichments/fetch"; + public static final String EXPRESSION_ENRICHMENT_FETCH_PATH = "/expression-enrichments/fetch"; + public static final String ALTERATION_ENRICHMENT_FETCH_PATH = "/alteration-enrichments/fetch"; + public static final String TREATMENT_FETCH_PATH = "/treatments/fetch"; + public static final String STRUCTURAL_VARIANT_FETCH_PATH = "/structural-variant/fetch"; + public static final String GENERIC_ASSAY_DATA_MULTIPLE_STUDY_FETCH_PATH = + "/generic_assay_data/fetch"; + public static final String TREATMENTS_PATIENT_PATH = "/treatments/patient"; + public static final String TREATMENTS_SAMPLE_PATH = "/treatments/sample"; + public static final String GENERIC_ASSAY_ENRICHMENT_FETCH_PATH = + "/generic-assay-enrichments/fetch"; + public static final String GENERIC_ASSAY_CATEGORICAL_ENRICHMENT_FETCH_PATH = + "/generic-assay-categorical-enrichments/fetch"; + public static final String GENERIC_ASSAY_BINARY_ENRICHMENT_FETCH_PATH = + "/generic-assay-binary-enrichments/fetch"; + public static final String CLINICAL_EVENT_TYPE_COUNT_FETCH_PATH = + "/clinical-event-type-counts/fetch"; + public static final String SURVIVAL_DATA_FETCH_PATH = "/survival-data/fetch"; + public static final String CLINICAL_EVENT_META_FETCH_PATH = "/clinical-events-meta/fetch"; + public static final String TREATMENTS_PATIENT_COUNT_FETCH_PATH = + "/treatments/patient-counts/fetch"; + public static final String TREATMENTS_SAMPLE_COUNT_FETCH_PATH = "/treatments/sample-counts/fetch"; + + @Override + public boolean preHandle( + HttpServletRequest request, HttpServletResponse response, Object handler) { + if (!request.getMethod().equals("POST")) { + return true; // no attribute extraction needed because all user supplied filter objects are in + // POST requests + } + // TODO when reimplemeting different dispatcherservlets with different context roots + // reset this to 'String requestPathInfo = request.getPathInfo();' + String requestPathInfo = + request.getPathInfo() == null ? request.getServletPath() : request.getPathInfo(); + requestPathInfo = requestPathInfo.replaceFirst("^/api", ""); + // requestPathInfo = StringUtils.removeStart(requestPathInfo, "/column-store"); + if (requestPathInfo.equals(PATIENT_FETCH_PATH)) { + return extractAttributesFromPatientFilter(request); + } else if (requestPathInfo.equals(SAMPLE_FETCH_PATH)) { + return extractAttributesFromSampleFilter(request); + } else if (requestPathInfo.equals(MOLECULAR_PROFILE_FETCH_PATH)) { + return extractAttributesFromMolecularProfileFilter(request); + } else if (requestPathInfo.equals(CLINICAL_ATTRIBUTE_COUNT_FETCH_PATH)) { + return extractAttributesFromClinicalAttributeCountFilter(request); + } else if (requestPathInfo.equals(NAMESPACE_ATTRIBUTE_COUNT_FETCH_PATH)) { + return extractAttributesFromNamespaceAttributeCountFilter(request); + } else if (requestPathInfo.equals(CLINICAL_DATA_FETCH_PATH)) { + return extractAttributesFromClinicalDataMultiStudyFilter(request); + } else if (requestPathInfo.equals(GENE_PANEL_DATA_FETCH_PATH)) { + return extractAttributesFromGenePanelDataMultipleStudyFilter(request); + } else if (requestPathInfo.equals(MOLECULAR_DATA_MULTIPLE_STUDY_FETCH_PATH)) { + return extractAttributesFromMolecularDataMultipleStudyFilter(request); + } else if (requestPathInfo.equals(MUTATION_MULTIPLE_STUDY_FETCH_PATH)) { + return extractAttributesFromMutationMultipleStudyFilter(request); + } else if (requestPathInfo.equals(COPY_NUMBER_SEG_FETCH_PATH)) { + return extractAttributesFromSampleIdentifiers(request); + } else if (Arrays.asList( + STUDY_VIEW_CLINICAL_DATA_BIN_COUNTS_PATH, STUDY_VIEW_CUSTOM_DATA_BIN_COUNTS_PATH) + .contains(requestPathInfo)) { + return extractAttributesFromClinicalDataBinCountFilter(request); + } else if (requestPathInfo.equals(STUDY_VIEW_GENOMICL_DATA_BIN_COUNTS_PATH)) { + return extractAttributesFromGenomicDataBinCountFilter(request); + } else if (Arrays.asList( + STUDY_VIEW_GENOMICL_DATA_COUNTS_PATH, STUDY_VIEW_MUTATION_DATA_COUNTS_PATH) + .contains(requestPathInfo)) { + return extractAttributesFromGenomicDataCountFilter(request); + } else if (requestPathInfo.equals(STUDY_VIEW_GENERIC_ASSAY_DATA_BIN_COUNTS_PATH)) { + return extractAttributesFromGenericAssayDataBinCountFilter(request); + } else if (requestPathInfo.equals(STUDY_VIEW_GENERIC_ASSAY_DATA_COUNTS_PATH)) { + return extractAttributesFromGenericAssayDataCountFilter(request); + } else if (Arrays.asList( + STUDY_VIEW_CLINICAL_DATA_COUNTS_PATH, STUDY_VIEW_CUSTOM_DATA_COUNTS_PATH) + .contains(requestPathInfo)) { + return extractAttributesFromClinicalDataCountFilter(request); + } else if (requestPathInfo.equals(STUDY_VIEW_NAMESPACE_DATA_COUNTS_PATH)) { + return extractAttributesFromNamespaceDataCountFilter(request); + } else if (Arrays.asList( + STUDY_VIEW_CLINICAL_DATA_DENSITY_PATH, + STUDY_VIEW_CLINICAL_DATA_VIOLIN_PATH, + STUDY_VIEW_CNA_GENES, + STUDY_VIEW_FILTERED_SAMPLES, + STUDY_VIEW_MUTATED_GENES, + STUDY_VIEW_STRUCTURAL_VARIANT_GENES, + STUDY_VIEW_STRUCTURAL_VARIANT_COUNTS, + STUDY_VIEW_SAMPLE_COUNTS, + STUDY_VIEW_SAMPLE_LIST_COUNTS_PATH, + STUDY_VIEW_CLINICAL_TABLE_DATA_FETCH_PATH, + TREATMENTS_PATIENT_PATH, + TREATMENTS_SAMPLE_PATH, + STUDY_VIEW_PROFILE_SAMPLE_COUNTS_PATH, + CLINICAL_EVENT_TYPE_COUNT_FETCH_PATH, + TREATMENTS_PATIENT_COUNT_FETCH_PATH, + TREATMENTS_SAMPLE_COUNT_FETCH_PATH) + .contains(requestPathInfo)) { + return extractAttributesFromStudyViewFilter(request); + } else if (requestPathInfo.equals(CLINICAL_DATA_ENRICHMENT_FETCH_PATH)) { + return extractAttributesFromGroupFilter(request); + } else if (requestPathInfo.equals(MUTATION_ENRICHMENT_FETCH_PATH) + || requestPathInfo.equals(COPY_NUMBER_ENRICHMENT_FETCH_PATH) + || requestPathInfo.equals(EXPRESSION_ENRICHMENT_FETCH_PATH) + || requestPathInfo.equals(GENERIC_ASSAY_ENRICHMENT_FETCH_PATH) + || requestPathInfo.equals(GENERIC_ASSAY_CATEGORICAL_ENRICHMENT_FETCH_PATH) + || requestPathInfo.equals(GENERIC_ASSAY_BINARY_ENRICHMENT_FETCH_PATH)) { + return extractAttributesFromMolecularProfileCasesGroups(request); + } else if (requestPathInfo.equals(ALTERATION_ENRICHMENT_FETCH_PATH)) { + return extractAttributesFromMolecularProfileCasesGroupsAndAlterationTypes(request); + } else if (requestPathInfo.equals(STRUCTURAL_VARIANT_FETCH_PATH)) { + return extractAttributesFromStructuralVariantFilter(request); + } else if (requestPathInfo.equals(GENERIC_ASSAY_DATA_MULTIPLE_STUDY_FETCH_PATH)) { + return extractAttributesFromGenericAssayDataMultipleStudyFilter(request); + } else if (requestPathInfo.equals(SURVIVAL_DATA_FETCH_PATH)) { + return extractCancerStudyIdsFromSurvivalRequest(request); + } else if (requestPathInfo.equals(CLINICAL_EVENT_META_FETCH_PATH)) { + return extractCancerStudyIdsFromClinicalEventAttributeRequest(request); + } + return true; + } + + private boolean extractAttributesFromPatientFilter(HttpServletRequest request) { + try { + PatientFilter patientFilter = + objectMapper.readValue(request.getInputStream(), PatientFilter.class); + LOG.debug("extracted patientFilter: {}", patientFilter); + LOG.debug("setting interceptedPatientFilter to {}", patientFilter); + request.setAttribute("interceptedPatientFilter", patientFilter); + if (cacheMapUtil.hasCacheEnabled()) { + Collection cancerStudyIdCollection = + extractCancerStudyIdsFromPatientFilter(patientFilter); + LOG.debug("setting involvedCancerStudies to {}", cancerStudyIdCollection); + request.setAttribute("involvedCancerStudies", cancerStudyIdCollection); + } + } catch (Exception e) { + LOG.error("exception thrown during extraction of patientFilter: {}", e.getMessage()); + return false; + } + return true; + } + + private Collection extractCancerStudyIdsFromPatientFilter(PatientFilter patientFilter) { + // use hashset as the study list in the patientFilter will usually be populated with many + // duplicate values + Set studyIdSet = new HashSet<>(); + if (patientFilter.getPatientIdentifiers() != null) { + for (PatientIdentifier patientIdentifier : patientFilter.getPatientIdentifiers()) { + studyIdSet.add(patientIdentifier.getStudyId()); + } + } else { + UniqueKeyExtractor.extractUniqueKeys(patientFilter.getUniquePatientKeys(), studyIdSet); + } + return studyIdSet; + } + + private boolean extractAttributesFromSampleFilter(HttpServletRequest request) { + try { + SampleFilter sampleFilter = + objectMapper.readValue(request.getInputStream(), SampleFilter.class); + LOG.debug("extracted sampleFilter: {}", sampleFilter); + LOG.debug("setting interceptedSampleFilter to {}", sampleFilter); + request.setAttribute("interceptedSampleFilter", sampleFilter); + if (cacheMapUtil.hasCacheEnabled()) { + Collection cancerStudyIdCollection = + extractCancerStudyIdsFromSampleFilter(sampleFilter); + LOG.debug("setting involvedCancerStudies to {}", cancerStudyIdCollection); + request.setAttribute("involvedCancerStudies", cancerStudyIdCollection); + } + } catch (Exception e) { + LOG.error("exception thrown during extraction of sampleFilter: {}", e.getMessage()); + return false; + } + return true; + } + + private Collection extractCancerStudyIdsFromSampleFilter(SampleFilter sampleFilter) { + // use hashset as the study list in the sampleFilter will usually be populated with many + // duplicate values + Set studyIdSet = new HashSet<>(); + if (sampleFilter.getSampleListIds() != null) { + extractCancerStudyIdsFromSampleListIds(sampleFilter.getSampleListIds(), studyIdSet); + } else if (sampleFilter.getSampleIdentifiers() != null) { + extractCancerStudyIdsFromSampleIdentifiers(sampleFilter.getSampleIdentifiers(), studyIdSet); + } else { + UniqueKeyExtractor.extractUniqueKeys(sampleFilter.getUniqueSampleKeys(), studyIdSet); + } + return studyIdSet; + } + + private boolean extractAttributesFromMolecularProfileFilter(HttpServletRequest request) { + try { + MolecularProfileFilter molecularProfileFilter = + objectMapper.readValue(request.getInputStream(), MolecularProfileFilter.class); + LOG.debug("extracted molecularProfileFilter: {}", molecularProfileFilter); + LOG.debug("setting interceptedMolecularProfileFilter to {}", molecularProfileFilter); + request.setAttribute("interceptedMolecularProfileFilter", molecularProfileFilter); + if (cacheMapUtil.hasCacheEnabled()) { + Collection cancerStudyIdCollection = + extractCancerStudyIdsFromMolecularProfileFilter(molecularProfileFilter); + LOG.debug("setting involvedCancerStudies to {}", cancerStudyIdCollection); + request.setAttribute("involvedCancerStudies", cancerStudyIdCollection); + } + } catch (Exception e) { + LOG.error("exception thrown during extraction of molecularProfileFilter: {}", e.getMessage()); + return false; + } + return true; + } + + private Collection extractCancerStudyIdsFromMolecularProfileFilter( + MolecularProfileFilter molecularProfileFilter) { + // use hashset as the study list in the molecularProfileFilter may be populated with many + // duplicate values + Set studyIdSet = new HashSet<>(); + if (molecularProfileFilter.getStudyIds() != null) { + studyIdSet.addAll(molecularProfileFilter.getStudyIds()); + } else { + extractCancerStudyIdsFromMolecularProfileIds( + molecularProfileFilter.getMolecularProfileIds(), studyIdSet); + } + return studyIdSet; + } + + private boolean extractAttributesFromClinicalAttributeCountFilter(HttpServletRequest request) { + try { + ClinicalAttributeCountFilter clinicalAttributeCountFilter = + objectMapper.readValue(request.getInputStream(), ClinicalAttributeCountFilter.class); + LOG.debug("extracted clinicalAttributeCountFilter: {}", clinicalAttributeCountFilter); + LOG.debug( + "setting interceptedClinicalAttributeCountFilter to {}", clinicalAttributeCountFilter); + request.setAttribute("interceptedClinicalAttributeCountFilter", clinicalAttributeCountFilter); + if (cacheMapUtil.hasCacheEnabled()) { + Collection cancerStudyIdCollection = + extractCancerStudyIdsFromClinicalAttributeCountFilter(clinicalAttributeCountFilter); + LOG.debug("setting involvedCancerStudies to {}", cancerStudyIdCollection); + request.setAttribute("involvedCancerStudies", cancerStudyIdCollection); + } + } catch (Exception e) { + LOG.error( + "exception thrown during extraction of clinicalAttributeCountFilter: {}", e.getMessage()); + return false; + } + return true; + } + + private Collection extractCancerStudyIdsFromClinicalAttributeCountFilter( + ClinicalAttributeCountFilter clinicalAttributeCountFilter) { + // use hashset as the study list in the clinicalAttributeCountFilter may be populated with many + // duplicate values + Set studyIdSet = new HashSet<>(); + if (clinicalAttributeCountFilter.getSampleListId() != null) { + extractCancerStudyIdsFromSampleListIds( + Collections.singletonList(clinicalAttributeCountFilter.getSampleListId()), studyIdSet); + } else { + extractCancerStudyIdsFromSampleIdentifiers( + clinicalAttributeCountFilter.getSampleIdentifiers(), studyIdSet); + } + return studyIdSet; + } + + private boolean extractAttributesFromNamespaceAttributeCountFilter(HttpServletRequest request) { + try { + NamespaceAttributeCountFilter namespaceAttributeCountFilter = + objectMapper.readValue(request.getInputStream(), NamespaceAttributeCountFilter.class); + LOG.debug("extracted namespaceAttributeCountFilter: {}", namespaceAttributeCountFilter); + LOG.debug( + "setting interceptedNamespaceAttributeCountFilter to {}", namespaceAttributeCountFilter); + request.setAttribute( + "interceptedNamespaceAttributeCountFilter", namespaceAttributeCountFilter); + if (cacheMapUtil.hasCacheEnabled()) { + Collection cancerStudyIdCollection = + extractCancerStudyIdsFromNamespaceAttributeCountFilter(namespaceAttributeCountFilter); + LOG.debug("setting involvedCancerStudies to {}", cancerStudyIdCollection); + request.setAttribute("involvedCancerStudies", cancerStudyIdCollection); + } + } catch (Exception e) { + LOG.error( + "exception thrown during extraction of clinicalAttributeCountFilter: {}", e.getMessage()); + return false; + } + return true; + } + + private Collection extractCancerStudyIdsFromNamespaceAttributeCountFilter( + NamespaceAttributeCountFilter namespaceAttributeCountFilter) { + // use hashset as the study list in the namespaceAttributeCountFilter may be populated with many + // duplicate values + Set studyIdSet = new HashSet<>(); + extractCancerStudyIdsFromSampleIdentifiers( + namespaceAttributeCountFilter.getSampleIdentifiers(), studyIdSet); + return studyIdSet; + } + + private boolean extractAttributesFromClinicalDataMultiStudyFilter(HttpServletRequest request) { + try { + ClinicalDataMultiStudyFilter clinicalDataMultiStudyFilter = + objectMapper.readValue(request.getInputStream(), ClinicalDataMultiStudyFilter.class); + LOG.debug("extracted clinicalDataMultiStudyFilter: {}", clinicalDataMultiStudyFilter); + LOG.debug( + "setting interceptedClinicalDataMultiStudyFilter to {}", clinicalDataMultiStudyFilter); + request.setAttribute("interceptedClinicalDataMultiStudyFilter", clinicalDataMultiStudyFilter); + if (cacheMapUtil.hasCacheEnabled()) { + Collection cancerStudyIdCollection = + extractCancerStudyIdsFromClinicalDataMultiStudyFilter(clinicalDataMultiStudyFilter); + LOG.debug("setting involvedCancerStudies to {}", cancerStudyIdCollection); + request.setAttribute("involvedCancerStudies", cancerStudyIdCollection); + } + } catch (Exception e) { + LOG.error( + "exception thrown during extraction of clinicalDataMultiStudyFilter: {}", e.getMessage()); + return false; + } + return true; + } + + private Collection extractCancerStudyIdsFromClinicalDataMultiStudyFilter( + ClinicalDataMultiStudyFilter clinicalDataMultiStudyFilter) { + // use hashset as the study list in the clinicalDataMultiStudyFilter may be populated with many + // duplicate values + Set studyIdSet = new HashSet<>(); + for (ClinicalDataIdentifier clinicalDataIdentifier : + clinicalDataMultiStudyFilter.getIdentifiers()) { + studyIdSet.add(clinicalDataIdentifier.getStudyId()); + } + return studyIdSet; + } + + private boolean extractAttributesFromGenePanelDataMultipleStudyFilter( + HttpServletRequest request) { + try { + GenePanelDataMultipleStudyFilter genePanelDataMultipleStudyFilter = + objectMapper.readValue(request.getInputStream(), GenePanelDataMultipleStudyFilter.class); + LOG.debug("extracted genePanelDataMultipleStudyFilter: {}", genePanelDataMultipleStudyFilter); + LOG.debug( + "setting interceptedGenePanelDataMultipleStudyFilter to {}", + genePanelDataMultipleStudyFilter); + request.setAttribute( + "interceptedGenePanelDataMultipleStudyFilter", genePanelDataMultipleStudyFilter); + if (cacheMapUtil.hasCacheEnabled()) { + Collection cancerStudyIdCollection = + extractCancerStudyIdsFromGenePanelDataMultipleStudyFilter( + genePanelDataMultipleStudyFilter); + LOG.debug("setting involvedCancerStudies to {}", cancerStudyIdCollection); + request.setAttribute("involvedCancerStudies", cancerStudyIdCollection); + } + } catch (Exception e) { + LOG.error( + "exception thrown during extraction of genePanelSampleMolecularIdentifiers: {}", + e.getMessage()); + return false; + } + return true; + } + + private Collection extractCancerStudyIdsFromGenePanelDataMultipleStudyFilter( + GenePanelDataMultipleStudyFilter genePanelDataMultipleStudyFilter) { + Set studyIdSet = new HashSet<>(); + if (genePanelDataMultipleStudyFilter.getMolecularProfileIds() != null) { + extractCancerStudyIdsFromMolecularProfileIds( + genePanelDataMultipleStudyFilter.getMolecularProfileIds(), studyIdSet); + } else { + extractCancerStudyIdsFromSampleMolecularIdentifiers( + genePanelDataMultipleStudyFilter.getSampleMolecularIdentifiers(), studyIdSet); + } + return studyIdSet; + } + + private boolean extractAttributesFromMolecularDataMultipleStudyFilter( + HttpServletRequest request) { + try { + MolecularDataMultipleStudyFilter molecularDataMultipleStudyFilter = + objectMapper.readValue(request.getInputStream(), MolecularDataMultipleStudyFilter.class); + LOG.debug("extracted molecularDataMultipleStudyFilter: {}", molecularDataMultipleStudyFilter); + LOG.debug( + "setting interceptedMolecularDataMultipleStudyFilter to {}", + molecularDataMultipleStudyFilter); + request.setAttribute( + "interceptedMolecularDataMultipleStudyFilter", molecularDataMultipleStudyFilter); + if (cacheMapUtil.hasCacheEnabled()) { + Collection cancerStudyIdCollection = + extractCancerStudyIdsFromMolecularDataMultipleStudyFilter( + molecularDataMultipleStudyFilter); + LOG.debug("setting involvedCancerStudies to {}", cancerStudyIdCollection); + request.setAttribute("involvedCancerStudies", cancerStudyIdCollection); + } + } catch (Exception e) { + LOG.error( + "exception thrown during extraction of molecularDataMultipleStudyFilter: {}", + e.getMessage()); + return false; + } + return true; + } + + private Collection extractCancerStudyIdsFromMolecularDataMultipleStudyFilter( + MolecularDataMultipleStudyFilter molecularDataMultipleStudyFilter) { + Set studyIdSet = new HashSet<>(); + if (molecularDataMultipleStudyFilter.getMolecularProfileIds() != null) { + extractCancerStudyIdsFromMolecularProfileIds( + molecularDataMultipleStudyFilter.getMolecularProfileIds(), studyIdSet); + } else { + extractCancerStudyIdsFromSampleMolecularIdentifiers( + molecularDataMultipleStudyFilter.getSampleMolecularIdentifiers(), studyIdSet); + } + return studyIdSet; + } + + private boolean extractAttributesFromGenericAssayDataMultipleStudyFilter( + HttpServletRequest request) { + try { + GenericAssayDataMultipleStudyFilter genericAssayDataMultipleStudyFilter = + objectMapper.readValue( + request.getInputStream(), GenericAssayDataMultipleStudyFilter.class); + LOG.debug( + "extracted genericAssayDataMultipleStudyFilter: {}", genericAssayDataMultipleStudyFilter); + LOG.debug( + "setting interceptedGenericAssayDataMultipleStudyFilter to {}", + genericAssayDataMultipleStudyFilter); + request.setAttribute( + "interceptedGenericAssayDataMultipleStudyFilter", genericAssayDataMultipleStudyFilter); + if (cacheMapUtil.hasCacheEnabled()) { + Collection cancerStudyIdCollection = + extractCancerStudyIdsFromGenericAssayDataMultipleStudyFilter( + genericAssayDataMultipleStudyFilter); + LOG.debug("setting involvedCancerStudies to {}", cancerStudyIdCollection); + request.setAttribute("involvedCancerStudies", cancerStudyIdCollection); + } + } catch (Exception e) { + LOG.error( + "exception thrown during extraction of genericAssayDataMultipleStudyFilter: {}", + e.getMessage()); + return false; + } + return true; + } + + private Collection extractCancerStudyIdsFromGenericAssayDataMultipleStudyFilter( + GenericAssayDataMultipleStudyFilter genericAssayDataMultipleStudyFilter) { + Set studyIdSet = new HashSet<>(); + if (genericAssayDataMultipleStudyFilter.getMolecularProfileIds() != null) { + extractCancerStudyIdsFromMolecularProfileIds( + genericAssayDataMultipleStudyFilter.getMolecularProfileIds(), studyIdSet); + } else { + extractCancerStudyIdsFromSampleMolecularIdentifiers( + genericAssayDataMultipleStudyFilter.getSampleMolecularIdentifiers(), studyIdSet); + } + return studyIdSet; + } + + private boolean extractAttributesFromMutationMultipleStudyFilter(HttpServletRequest request) { + try { + MutationMultipleStudyFilter mutationMultipleStudyFilter = + objectMapper.readValue(request.getInputStream(), MutationMultipleStudyFilter.class); + LOG.debug("extracted mutationMultipleStudyFilter: {}", mutationMultipleStudyFilter); + LOG.debug( + "setting interceptedMutationMultipleStudyFilter to {}", mutationMultipleStudyFilter); + request.setAttribute("interceptedMutationMultipleStudyFilter", mutationMultipleStudyFilter); + if (cacheMapUtil.hasCacheEnabled()) { + Collection cancerStudyIdCollection = + extractCancerStudyIdsFromMutationMultipleStudyFilter(mutationMultipleStudyFilter); + LOG.debug("setting involvedCancerStudies to {}", cancerStudyIdCollection); + request.setAttribute("involvedCancerStudies", cancerStudyIdCollection); + } + } catch (Exception e) { + LOG.error( + "exception thrown during extraction of mutationMultipleStudyFilter: {}", e.getMessage()); + return false; + } + return true; + } + + private Set extractCancerStudyIdsFromMutationMultipleStudyFilter( + MutationMultipleStudyFilter mutationMultipleStudyFilter) { + Set studyIdSet = new HashSet<>(); + if (mutationMultipleStudyFilter.getMolecularProfileIds() != null) { + extractCancerStudyIdsFromMolecularProfileIds( + mutationMultipleStudyFilter.getMolecularProfileIds(), studyIdSet); + } else { + extractCancerStudyIdsFromSampleMolecularIdentifiers( + mutationMultipleStudyFilter.getSampleMolecularIdentifiers(), studyIdSet); + } + return studyIdSet; + } + + private boolean extractAttributesFromSampleIdentifiers(HttpServletRequest request) { + try { + List sampleIdentifiers = + Arrays.asList(objectMapper.readValue(request.getInputStream(), SampleIdentifier[].class)); + LOG.debug("extracted sampleIdentifiers: {}", sampleIdentifiers); + LOG.debug("setting interceptedSampleIdentifiers to {}", sampleIdentifiers); + request.setAttribute("interceptedSampleIdentifiers", sampleIdentifiers); + if (cacheMapUtil.hasCacheEnabled()) { + Collection cancerStudyIdCollection = + extractCancerStudyIdsFromSampleIdentifiers(sampleIdentifiers); + LOG.debug("setting involvedCancerStudies to {}", cancerStudyIdCollection); + request.setAttribute("involvedCancerStudies", cancerStudyIdCollection); + } + } catch (Exception e) { + LOG.error("exception thrown during extraction of sampleIdentifiers: {}", e.getMessage()); + return false; + } + return true; + } + + private boolean extractAttributesFromClinicalDataBinCountFilter(HttpServletRequest request) { + try { + ClinicalDataBinCountFilter clinicalDataBinCountFilter = + objectMapper.readValue(request.getInputStream(), ClinicalDataBinCountFilter.class); + LOG.debug("extracted clinicalDataBinCountFilter: {}", clinicalDataBinCountFilter); + LOG.debug("setting interceptedClinicalDataBinCountFilter to {}", clinicalDataBinCountFilter); + request.setAttribute("interceptedClinicalDataBinCountFilter", clinicalDataBinCountFilter); + if (cacheMapUtil.hasCacheEnabled()) { + Collection cancerStudyIdCollection = + extractCancerStudyIdsFromClinicalDataBinCountFilter(clinicalDataBinCountFilter); + LOG.debug("setting involvedCancerStudies to {}", cancerStudyIdCollection); + request.setAttribute("involvedCancerStudies", cancerStudyIdCollection); + } + } catch (Exception e) { + LOG.error( + "exception thrown during extraction of clinicalDataBinCountFilter: {}", e.getMessage()); + return false; + } + return true; + } + + private boolean extractAttributesFromGenomicDataBinCountFilter(HttpServletRequest request) { + try { + GenomicDataBinCountFilter genomicDataBinCountFilter = + objectMapper.readValue(request.getInputStream(), GenomicDataBinCountFilter.class); + LOG.debug("extracted genomicDataBinCountFilter: {}", genomicDataBinCountFilter); + LOG.debug("setting interceptedGenomicDataBinCountFilter to {}", genomicDataBinCountFilter); + request.setAttribute("interceptedGenomicDataBinCountFilter", genomicDataBinCountFilter); + if (cacheMapUtil.hasCacheEnabled()) { + Collection cancerStudyIdCollection = + extractCancerStudyIdsFromGenomicDataBinCountFilter(genomicDataBinCountFilter); + LOG.debug("setting involvedCancerStudies to {}", cancerStudyIdCollection); + request.setAttribute("involvedCancerStudies", cancerStudyIdCollection); + } + } catch (Exception e) { + LOG.error( + "exception thrown during extraction of genomicDataBinCountFilter: {}", e.getMessage()); + return false; + } + return true; + } + + private boolean extractAttributesFromGenomicDataCountFilter(HttpServletRequest request) { + try { + GenomicDataCountFilter genomicDataCountFilter = + objectMapper.readValue(request.getInputStream(), GenomicDataCountFilter.class); + LOG.debug("extracted genomicDataCountFilter: {}", genomicDataCountFilter); + LOG.debug("setting interceptedGenomicDataCountFilter to {}", genomicDataCountFilter); + request.setAttribute("interceptedGenomicDataCountFilter", genomicDataCountFilter); + if (cacheMapUtil.hasCacheEnabled()) { + Collection cancerStudyIdCollection = + extractCancerStudyIdsFromGenomicDataCountFilter(genomicDataCountFilter); + LOG.debug("setting involvedCancerStudies to {}", cancerStudyIdCollection); + request.setAttribute("involvedCancerStudies", cancerStudyIdCollection); + } + } catch (Exception e) { + LOG.error("exception thrown during extraction of genomicDataCountFilter: {}", e.getMessage()); + return false; + } + return true; + } + + private boolean extractAttributesFromGenericAssayDataBinCountFilter(HttpServletRequest request) { + try { + GenericAssayDataBinCountFilter genericAssayDataBinCountFilter = + objectMapper.readValue(request.getInputStream(), GenericAssayDataBinCountFilter.class); + LOG.debug("extracted genericAssayDataBinCountFilter: {}", genericAssayDataBinCountFilter); + LOG.debug( + "setting interceptedGenericAssayDataBinCountFilter to {}", + genericAssayDataBinCountFilter); + request.setAttribute( + "interceptedGenericAssayDataBinCountFilter", genericAssayDataBinCountFilter); + if (cacheMapUtil.hasCacheEnabled()) { + Collection cancerStudyIdCollection = + extractCancerStudyIdsFromGenericAssayDataBinCountFilter(genericAssayDataBinCountFilter); + LOG.debug("setting involvedCancerStudies to {}", cancerStudyIdCollection); + request.setAttribute("involvedCancerStudies", cancerStudyIdCollection); + } + } catch (Exception e) { + LOG.error( + "exception thrown during extraction of genericAssayDataBinCountFilter: {}", + e.getMessage()); + return false; + } + return true; + } + + private boolean extractAttributesFromGenericAssayDataCountFilter(HttpServletRequest request) { + try { + GenericAssayDataCountFilter genericAssayDataCountFilter = + objectMapper.readValue(request.getInputStream(), GenericAssayDataCountFilter.class); + LOG.debug("extracted genericAssayDataCountFilter: {}", genericAssayDataCountFilter); + LOG.debug( + "setting interceptedGenericAssayDataCountFilter to {}", genericAssayDataCountFilter); + request.setAttribute("interceptedGenericAssayDataCountFilter", genericAssayDataCountFilter); + if (cacheMapUtil.hasCacheEnabled()) { + Collection cancerStudyIdCollection = + extractCancerStudyIdsFromGenericAssayDataCountFilter(genericAssayDataCountFilter); + LOG.debug("setting involvedCancerStudies to {}", cancerStudyIdCollection); + request.setAttribute("involvedCancerStudies", cancerStudyIdCollection); + } + } catch (Exception e) { + LOG.error( + "exception thrown during extraction of genericAssayDataCountFilter: {}", e.getMessage()); + return false; + } + return true; + } + + private boolean extractAttributesFromClinicalDataCountFilter(HttpServletRequest request) { + try { + ClinicalDataCountFilter clinicalDataCountFilter = + objectMapper.readValue(request.getInputStream(), ClinicalDataCountFilter.class); + LOG.debug("extracted clinicalDataBinCountFilter: {}", clinicalDataCountFilter); + LOG.debug("setting interceptedClinicalDataCountFilter to {}", clinicalDataCountFilter); + request.setAttribute("interceptedClinicalDataCountFilter", clinicalDataCountFilter); + if (cacheMapUtil.hasCacheEnabled()) { + Collection cancerStudyIdCollection = + extractCancerStudyIdsFromClinicalDataCountFilter(clinicalDataCountFilter); + LOG.debug("setting involvedCancerStudies to {}", cancerStudyIdCollection); + request.setAttribute("involvedCancerStudies", cancerStudyIdCollection); + } + } catch (Exception e) { + LOG.error( + "exception thrown during extraction of clinicalDataBinCountFilter: {}", e.getMessage()); + return false; + } + return true; + } + + private boolean extractAttributesFromNamespaceDataCountFilter(HttpServletRequest request) { + try { + NamespaceDataCountFilter namespaceDataCountFilter = + objectMapper.readValue(request.getInputStream(), NamespaceDataCountFilter.class); + LOG.debug("extracted namespaceDataCountFilter: {}", namespaceDataCountFilter); + LOG.debug("setting interceptedNamespaceDataCountFilter to {}", namespaceDataCountFilter); + request.setAttribute("interceptedNamespaceDataCountFilter", namespaceDataCountFilter); + if (cacheMapUtil.hasCacheEnabled()) { + Collection cancerStudyIdCollection = + extractCancerStudyIdsFromNamespaceDataCountFilter(namespaceDataCountFilter); + LOG.debug("setting involvedCancerStudies to {}", cancerStudyIdCollection); + request.setAttribute("involvedCancerStudies", cancerStudyIdCollection); + } + } catch (Exception e) { + LOG.error( + "exception thrown during extraction of namespaceDataCountFilter: {}", e.getMessage()); + return false; + } + return true; + } + + private boolean extractAttributesFromGroupFilter(HttpServletRequest request) { + try { + GroupFilter groupFilter = objectMapper.readValue(request.getInputStream(), GroupFilter.class); + LOG.debug("extracted groupFilter: {}", groupFilter); + LOG.debug("setting interceptedGroupFilter to {}", groupFilter); + request.setAttribute("interceptedGroupFilter", groupFilter); + if (cacheMapUtil.hasCacheEnabled()) { + List sampleIdentifiers = + groupFilter.getGroups().stream() + .flatMap(group -> group.getSampleIdentifiers().stream()) + .collect(Collectors.toList()); + Collection cancerStudyIdCollection = + extractCancerStudyIdsFromSampleIdentifiers(sampleIdentifiers); + LOG.debug("setting involvedCancerStudies to {}", cancerStudyIdCollection); + request.setAttribute("involvedCancerStudies", cancerStudyIdCollection); + } + } catch (Exception e) { + LOG.error("exception thrown during extraction of groupFilter: {}", e.getMessage()); + return false; + } + return true; + } + + private boolean extractAttributesFromStudyViewFilter(HttpServletRequest request) { + try { + StudyViewFilter studyViewFilter = + objectMapper.readValue(request.getInputStream(), StudyViewFilter.class); + if (studyViewFilter.getAlterationFilter() == null) { + // For backwards compatibility an inactive filter is set + // when the AlterationFilter is not part of the request. + studyViewFilter.setAlterationFilter(new AlterationFilter()); + } + if (studyViewFilter.getStructuralVariantFilters() == null) { + // For backwards compatibility an inactive filter is set + // when the StructuralVariantFilters are not part of the request. + studyViewFilter.setStructuralVariantFilters(new ArrayList<>()); + } + LOG.debug("extracted studyViewFilter: {}", studyViewFilter); + LOG.debug("setting interceptedStudyViewFilter to {}", studyViewFilter); + request.setAttribute("interceptedStudyViewFilter", studyViewFilter); + if (cacheMapUtil.hasCacheEnabled()) { + Collection cancerStudyIdCollection = + extractCancerStudyIdsFromStudyViewFilter(studyViewFilter); + LOG.debug("setting involvedCancerStudies to {}", cancerStudyIdCollection); + request.setAttribute("involvedCancerStudies", cancerStudyIdCollection); + } + } catch (Exception e) { + LOG.error("exception thrown during extraction of studyViewFilter: {}", e.getMessage()); + return false; + } + return true; + } + + private boolean extractAttributesFromMolecularProfileCasesGroups(HttpServletRequest request) { + try { + List molecularProfileCasesGroupFilters = + Arrays.asList( + objectMapper.readValue( + request.getInputStream(), MolecularProfileCasesGroupFilter[].class)); + LOG.debug( + "extracted molecularProfileCasesGroupFilters: {}", molecularProfileCasesGroupFilters); + LOG.debug( + "setting interceptedMolecularProfileCasesGroupFilters to {}", + molecularProfileCasesGroupFilters); + request.setAttribute( + "interceptedMolecularProfileCasesGroupFilters", molecularProfileCasesGroupFilters); + if (cacheMapUtil.hasCacheEnabled()) { + Collection cancerStudyIdCollection = + extractCancerStudyIdsFromMolecularProfileCasesGroups(molecularProfileCasesGroupFilters); + LOG.debug("setting involvedCancerStudies to {}", cancerStudyIdCollection); + request.setAttribute("involvedCancerStudies", cancerStudyIdCollection); + } + } catch (Exception e) { + LOG.error( + "exception thrown during extraction of molecularProfileCasesGroupFilters: {}", + e.getMessage()); + return false; + } + return true; + } + + private boolean extractAttributesFromMolecularProfileCasesGroupsAndAlterationTypes( + HttpServletRequest request) { + try { + MolecularProfileCasesGroupAndAlterationTypeFilter + molecularProfileCasesAndAlterationTypesGroupFilters = + objectMapper.readValue( + request.getInputStream(), + MolecularProfileCasesGroupAndAlterationTypeFilter.class); + List molecularProfileCasesGroupFilters = + molecularProfileCasesAndAlterationTypesGroupFilters.getMolecularProfileCasesGroupFilter(); + LOG.debug( + "extracted molecularProfileCasesGroupFilters: {}", molecularProfileCasesGroupFilters); + LOG.debug( + "setting interceptedMolecularProfileCasesGroupFilters to {}", + molecularProfileCasesGroupFilters); + request.setAttribute( + "interceptedMolecularProfileCasesGroupFilters", molecularProfileCasesGroupFilters); + if (molecularProfileCasesAndAlterationTypesGroupFilters.getAlterationEventTypes() != null) { + AlterationFilter alterationEnrichmentEventTypes = + molecularProfileCasesAndAlterationTypesGroupFilters.getAlterationEventTypes(); + LOG.debug("extracted alterationEventTypes: {}", alterationEnrichmentEventTypes); + LOG.debug("setting alterationEventTypes to {}", alterationEnrichmentEventTypes); + request.setAttribute("alterationEventTypes", alterationEnrichmentEventTypes); + } + if (cacheMapUtil.hasCacheEnabled()) { + Collection cancerStudyIdCollection = + extractCancerStudyIdsFromMolecularProfileCasesGroups(molecularProfileCasesGroupFilters); + LOG.debug("setting involvedCancerStudies to {}", cancerStudyIdCollection); + request.setAttribute("involvedCancerStudies", cancerStudyIdCollection); + } + } catch (Exception e) { + LOG.error( + "exception thrown during extraction of molecularProfileCasesGroupFilters: {}", + e.getMessage()); + return false; + } + return true; + } + + private boolean extractAttributesFromStructuralVariantFilter(HttpServletRequest request) { + try { + StructuralVariantFilter structuralVariantFilter = + objectMapper.readValue(request.getInputStream(), StructuralVariantFilter.class); + LOG.debug("extracted structuralVariantFilter: {}", structuralVariantFilter); + if (structuralVariantFilter.getStructuralVariantQueries() == null) { + // For backwards compatibility an empty set of queries is inferred + // when the StructuralVariantFilter is not part of the request. + structuralVariantFilter.setStructuralVariantQueries(new ArrayList<>()); + } + LOG.debug("setting interceptedStructuralVariantFilter to {}", structuralVariantFilter); + request.setAttribute("interceptedStructuralVariantFilter", structuralVariantFilter); + if (cacheMapUtil.hasCacheEnabled()) { + Collection cancerStudyIdCollection = + extractCancerStudyIdsFromStructuralVariantFilter(structuralVariantFilter); + LOG.debug("setting involvedCancerStudies to {}", cancerStudyIdCollection); + request.setAttribute("involvedCancerStudies", cancerStudyIdCollection); + } + } catch (Exception e) { + LOG.error( + "exception thrown during extraction of structuralVariantFilter: {}", e.getMessage()); + return false; + } + return true; + } + + private Collection extractCancerStudyIdsFromStructuralVariantFilter( + StructuralVariantFilter structuralVariantFilter) { + Set studyIdSet = new HashSet<>(); + if (structuralVariantFilter.getSampleMolecularIdentifiers() != null) { + // controller handler will preferentially use SampleMolecularIdentifiers if they are present + // in the filter + extractCancerStudyIdsFromSampleMolecularIdentifiers( + structuralVariantFilter.getSampleMolecularIdentifiers(), studyIdSet); + } else { + // otherwise, handler will use the list of MolecularProfileIds in the filter + if (structuralVariantFilter.getMolecularProfileIds() != null) { + extractCancerStudyIdsFromMolecularProfileIds( + structuralVariantFilter.getMolecularProfileIds(), studyIdSet); + } + } + return studyIdSet; + } + + private Set extractCancerStudyIdsFromSampleIdentifiers( + Collection sampleIdentifiers) { + Set studyIdSet = new HashSet<>(); + extractCancerStudyIdsFromSampleIdentifiers(sampleIdentifiers, studyIdSet); + return studyIdSet; + } + + private void extractCancerStudyIdsFromSampleIdentifiers( + Collection sampleIdentifiers, Set studyIdSet) { + for (SampleIdentifier sampleIdentifier : sampleIdentifiers) { + studyIdSet.add(sampleIdentifier.getStudyId()); + } + } + + private void extractCancerStudyIdsFromSampleListIds( + List sampleListIds, Set studyIdSet) { + for (String sampleListId : sampleListIds) { + SampleList sampleList = cacheMapUtil.getSampleListMap().get(sampleListId); + studyIdSet.add(sampleList.getCancerStudyIdentifier()); + } + } + + private void extractCancerStudyIdsFromMolecularProfileIds( + Collection molecularProfileIds, Set studyIdSet) { + for (String molecularProfileId : molecularProfileIds) { + MolecularProfile molecularProfile = + cacheMapUtil.getMolecularProfileMap().get(molecularProfileId); + studyIdSet.add(molecularProfile.getCancerStudyIdentifier()); + } + } + + private void extractCancerStudyIdsFromSampleMolecularIdentifiers( + List sampleMolecularIdentifiers, Set studyIdSet) { + // use hashset as the study list in sampleMolecularIdentifiers may be populated with duplicate + // values + Set molecularProfileIds = new HashSet<>(); + for (SampleMolecularIdentifier sampleMolecularIdentifier : sampleMolecularIdentifiers) { + molecularProfileIds.add(sampleMolecularIdentifier.getMolecularProfileId()); + } + extractCancerStudyIdsFromMolecularProfileIds(molecularProfileIds, studyIdSet); + } + + private Set extractCancerStudyIdsFromClinicalDataBinCountFilter( + ClinicalDataBinCountFilter clinicalDataBinCountFilter) { + if (clinicalDataBinCountFilter.getStudyViewFilter() != null) { + return extractCancerStudyIdsFromStudyViewFilter( + clinicalDataBinCountFilter.getStudyViewFilter()); + } + return new HashSet<>(); + } + + private Set extractCancerStudyIdsFromGenomicDataBinCountFilter( + GenomicDataBinCountFilter genomicDataBinCountFilter) { + if (genomicDataBinCountFilter.getStudyViewFilter() != null) { + return extractCancerStudyIdsFromStudyViewFilter( + genomicDataBinCountFilter.getStudyViewFilter()); + } + return new HashSet<>(); + } + + private Set extractCancerStudyIdsFromGenomicDataCountFilter( + GenomicDataCountFilter genomicDataCountFilter) { + if (genomicDataCountFilter.getStudyViewFilter() != null) { + return extractCancerStudyIdsFromStudyViewFilter(genomicDataCountFilter.getStudyViewFilter()); + } + return new HashSet(); + } + + private Set extractCancerStudyIdsFromGenericAssayDataBinCountFilter( + GenericAssayDataBinCountFilter genericAssayDataBinCountFilter) { + if (genericAssayDataBinCountFilter.getStudyViewFilter() != null) { + return extractCancerStudyIdsFromStudyViewFilter( + genericAssayDataBinCountFilter.getStudyViewFilter()); + } + return new HashSet<>(); + } + + private Set extractCancerStudyIdsFromGenericAssayDataCountFilter( + GenericAssayDataCountFilter genericAssayDataCountFilter) { + if (genericAssayDataCountFilter.getStudyViewFilter() != null) { + return extractCancerStudyIdsFromStudyViewFilter( + genericAssayDataCountFilter.getStudyViewFilter()); + } + return new HashSet<>(); + } + + private Set extractCancerStudyIdsFromClinicalDataCountFilter( + ClinicalDataCountFilter clinicalDataCountFilter) { + if (clinicalDataCountFilter.getStudyViewFilter() != null) { + return extractCancerStudyIdsFromStudyViewFilter(clinicalDataCountFilter.getStudyViewFilter()); + } + return new HashSet<>(); + } + + private Set extractCancerStudyIdsFromNamespaceDataCountFilter( + NamespaceDataCountFilter namespaceDataCountFilter) { + if (namespaceDataCountFilter.getStudyViewFilter() != null) { + return extractCancerStudyIdsFromStudyViewFilter( + namespaceDataCountFilter.getStudyViewFilter()); + } + return new HashSet<>(); + } + + private Set extractCancerStudyIdsFromStudyViewFilter(StudyViewFilter studyViewFilter) { + Set studyIdSet = new HashSet<>(); + if (studyViewFilter.getSampleIdentifiers() != null + && !studyViewFilter.getSampleIdentifiers().isEmpty()) { + extractCancerStudyIdsFromSampleIdentifiers( + studyViewFilter.getSampleIdentifiers(), studyIdSet); + } else { + studyIdSet.addAll(studyViewFilter.getStudyIds()); + } + return studyIdSet; + } + + private Set extractCancerStudyIdsFromMolecularProfileCasesGroups( + Collection molecularProfileCasesGroupFilters) { + Set molecularProfileIds = + molecularProfileCasesGroupFilters.stream() + .flatMap( + group -> { + return group.getMolecularProfileCaseIdentifiers().stream() + .map(MolecularProfileCaseIdentifier::getMolecularProfileId); + }) + .collect(Collectors.toSet()); + Set studyIdSet = new HashSet<>(); + extractCancerStudyIdsFromMolecularProfileIds(molecularProfileIds, studyIdSet); + return studyIdSet; + } + + private boolean extractCancerStudyIdsFromSurvivalRequest(HttpServletRequest request) { + try { + SurvivalRequest survivalRequest = + objectMapper.readValue(request.getInputStream(), SurvivalRequest.class); + LOG.debug("extracted survivalRequest: {}", survivalRequest); + LOG.debug("setting interceptedSurvivalRequest to {}", survivalRequest); + request.setAttribute("interceptedSurvivalRequest", survivalRequest); + if (cacheMapUtil.hasCacheEnabled()) { + Collection cancerStudyIdCollection = + survivalRequest.getPatientIdentifiers().stream() + .map(PatientIdentifier::getStudyId) + .collect(Collectors.toSet()); + LOG.debug("setting involvedCancerStudies to {}", cancerStudyIdCollection); + request.setAttribute("involvedCancerStudies", cancerStudyIdCollection); + } + } catch (Exception e) { + LOG.error("exception thrown during extraction of survivalRequest: {}", e.getMessage()); + return false; + } + return true; + } + + private boolean extractCancerStudyIdsFromClinicalEventAttributeRequest( + HttpServletRequest request) { + try { + ClinicalEventAttributeRequest clinicalEventAttributeRequest = + objectMapper.readValue(request.getInputStream(), ClinicalEventAttributeRequest.class); + LOG.debug("extracted clinicalEventAttributeRequest: {}", clinicalEventAttributeRequest); + LOG.debug( + "setting interceptedClinicalEventAttributeRequest to {}", clinicalEventAttributeRequest); + request.setAttribute( + "interceptedClinicalEventAttributeRequest", clinicalEventAttributeRequest); + if (cacheMapUtil.hasCacheEnabled()) { + Collection cancerStudyIdCollection = + clinicalEventAttributeRequest.getPatientIdentifiers().stream() + .map(PatientIdentifier::getStudyId) + .collect(Collectors.toSet()); + LOG.debug("setting involvedCancerStudies to {}", cancerStudyIdCollection); + request.setAttribute("involvedCancerStudies", cancerStudyIdCollection); + } + } catch (Exception e) { + LOG.error( + "exception thrown during extraction of clinicalEventAttributeRequest: {}", + e.getMessage()); + return false; + } + return true; + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/util/LinearDataBinner.java b/src/main/java/org/cbioportal/legacy/web/util/LinearDataBinner.java new file mode 100644 index 00000000000..71c3f5390ff --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/util/LinearDataBinner.java @@ -0,0 +1,144 @@ +package org.cbioportal.legacy.web.util; + +import com.google.common.collect.Range; +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Optional; +import java.util.stream.Collectors; +import org.cbioportal.legacy.model.DataBin; +import org.springframework.stereotype.Component; + +@Component +public class LinearDataBinner { + public static final Double[] POSSIBLE_INTERVALS = { + 0.001, 0.002, 0.0025, 0.005, 0.01, 0.02, 0.025, 0.05, 0.1, 0.2, 0.25, 0.5, 1.0, 2.0, 5.0, 10.0, + 20.0, 25.0, 50.0, 100.0, 200.0, 250.0, 500.0, 1000.0, 2000.0, 2500.0, 5000.0, 10000.0 + }; + + public static final Double[] POSSIBLE_DISCRETE_INTERVALS = { + 1.0, 2.0, 5.0, 10.0, + 20.0, 25.0, 50.0, 100.0, + 200.0, 250.0, 500.0, 1000.0, + 2000.0, 2500.0, 5000.0, 10000.0 + }; + + public static final Integer DEFAULT_INTERVAL_COUNT = 20; + + public List calculateDataBins( + boolean areAllIntegers, + Range boxRange, + List values, + BigDecimal lowerOutlier, + BigDecimal upperOutlier, + Optional attributeId) { + BigDecimal min = + lowerOutlier == null ? Collections.min(values) : Collections.min(values).max(lowerOutlier); + BigDecimal max = + upperOutlier == null ? Collections.max(values) : Collections.max(values).min(upperOutlier); + + List dataBins = initDataBins(areAllIntegers, min, max, lowerOutlier, upperOutlier); + + // special case for "AGE" attributes + if (attributeId.isPresent() + && DataBinHelper.isAgeAttribute(attributeId.get()) + && min.doubleValue() < 18 + && boxRange + .upperEndpoint() + .subtract(boxRange.lowerEndpoint()) + .divide(BigDecimal.valueOf(2)) + .compareTo(BigDecimal.valueOf(18)) + == 1 + && dataBins.get(0).getEnd().compareTo(BigDecimal.valueOf(18)) == 1) { + // force first bin to start from 18 + dataBins.get(0).setStart(BigDecimal.valueOf(18)); + } + + DataBinHelper.calcCounts(dataBins, values); + + return dataBins; + } + + public List calculateDataBins(List customBins, List values) { + List dataBins = initDataBins(customBins); + DataBinHelper.calcCounts(dataBins, values); + return dataBins; + } + + // Add boundaries that have a defined start and end value. + // Ignore boundaries for lower (<=) and upper (>) limits. + public List initDataBins(List boundaries) { + List dataBins = new ArrayList<>(); + for (int i = 0; i < boundaries.size() - 1; i++) { + DataBin dataBin = new DataBin(); + dataBin.setStart(boundaries.get(i)); + dataBin.setEnd(boundaries.get(i + 1)); + dataBin.setCount(0); + dataBins.add(dataBin); + } + return dataBins; + } + + public List initDataBins( + boolean areAllIntegers, + BigDecimal min, + BigDecimal max, + BigDecimal lowerOutlier, + BigDecimal upperOutlier) { + List dataBins = new ArrayList<>(); + + List possibleIntervals = + Arrays.asList(areAllIntegers ? POSSIBLE_DISCRETE_INTERVALS : POSSIBLE_INTERVALS).stream() + .map(val -> BigDecimal.valueOf(val)) + .collect(Collectors.toList()); + + BigDecimal interval = + calcBinInterval(possibleIntervals, max.subtract(min), DEFAULT_INTERVAL_COUNT); + + BigDecimal start = min.add(interval).subtract(min.remainder(interval)); + + // check lowerOutlier too for better tuning of start + if (lowerOutlier == null || start.subtract(interval).compareTo(lowerOutlier) == 1) { + start = start.subtract(interval); + } + + // check upperOutlier too for better tuning of end + BigDecimal end = + upperOutlier == null || max.add(interval).compareTo(upperOutlier) == -1 + ? max + : max.subtract(interval); + + for (BigDecimal d = start; d.compareTo(end) != 1; ) { + DataBin dataBin = new DataBin(); + BigDecimal newEnd = d.add(interval); + + dataBin.setStart(d); + dataBin.setEnd(newEnd); + dataBin.setCount(0); + + dataBins.add(dataBin); + + d = newEnd; + } + + return dataBins; + } + + public BigDecimal calcBinInterval( + List possibleIntervals, BigDecimal totalRange, Integer maxIntervalCount) { + BigDecimal interval = new BigDecimal("-1.0"); + + for (int i = 0; i < possibleIntervals.size(); i++) { + interval = possibleIntervals.get(i); + BigDecimal count = totalRange.divide(interval); + + if (count.doubleValue() < maxIntervalCount) { + break; + } + } + + return interval; + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/util/LogScaleDataBinner.java b/src/main/java/org/cbioportal/legacy/web/util/LogScaleDataBinner.java new file mode 100644 index 00000000000..ed1eceb6de4 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/util/LogScaleDataBinner.java @@ -0,0 +1,78 @@ +package org.cbioportal.legacy.web.util; + +import com.google.common.collect.Range; +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.List; +import org.cbioportal.legacy.model.DataBin; +import org.springframework.stereotype.Component; + +@Component +public class LogScaleDataBinner { + + public List calculateDataBins( + Range boxRange, + List values, + BigDecimal lowerOutlier, + BigDecimal upperOutlier) { + List intervals = new ArrayList<>(); + BigDecimal start = new BigDecimal("0"); + + if (boxRange.lowerEndpoint().compareTo(new BigDecimal("0")) != 0) { + double absLogValue = Math.log10(boxRange.lowerEndpoint().abs().doubleValue()); + start = + BigDecimal.valueOf( + boxRange.lowerEndpoint().compareTo(new BigDecimal("0")) == -1 + ? -Math.ceil(absLogValue) + : Math.floor(absLogValue)); + } + + if (lowerOutlier != null) { + intervals.add(lowerOutlier); + } + + for (BigDecimal exponent = start; ; exponent = exponent.add(new BigDecimal("0.5"))) { + BigDecimal value = calcIntervalValue(exponent); + + if ((lowerOutlier == null || value.compareTo(lowerOutlier) == 1) + && (upperOutlier == null || value.compareTo(upperOutlier) != 1)) { + intervals.add(value); + } + + if (value.compareTo(boxRange.upperEndpoint()) == 1) { + exponent = exponent.add(new BigDecimal("0.5")); + + if (!addOutlierInterval(intervals, exponent, upperOutlier)) { + intervals.add(upperOutlier); + } + + // we don't want to end with non-integer exponent, + // add one more interval value if possible + if (exponent.stripTrailingZeros().scale() > 0) { + exponent = exponent.add(new BigDecimal("0.5")); + addOutlierInterval(intervals, exponent, upperOutlier); + } + + break; + } + } + + return DataBinHelper.initDataBins(values, intervals); + } + + public BigDecimal calcIntervalValue(BigDecimal exponent) { + return BigDecimal.valueOf( + exponent.signum() * Math.floor(Math.pow(10, exponent.abs().doubleValue()))); + } + + private boolean addOutlierInterval( + List intervals, BigDecimal exponent, BigDecimal upperOutlier) { + BigDecimal value = calcIntervalValue(exponent); + + if (upperOutlier == null || value.compareTo(upperOutlier) != 1) { + return intervals.add(value); + } + + return false; + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/util/RequestBodyGZipFilter.java b/src/main/java/org/cbioportal/legacy/web/util/RequestBodyGZipFilter.java new file mode 100644 index 00000000000..9808382d6eb --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/util/RequestBodyGZipFilter.java @@ -0,0 +1,79 @@ +package org.cbioportal.legacy.web.util; + +import jakarta.servlet.*; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import java.io.IOException; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.HttpHeaders; +import org.springframework.stereotype.Component; + +@Component("requestBodyGZipFilter") +public class RequestBodyGZipFilter implements Filter { + /** + * We need to limit the size of the gzipped request bodies to avoid denial of memory attacks. + * Because gzip can achieve text compression rates of around 1000x, without a common sense limit + * for request body size, it would be very easy to send a request body that, when inflated, + * consumes the entirety of a server's memory. + */ + @Value("${request_gzip_body_size_bytes:80000000}") + private int maxInflatedRequestBodySize; + + @Value("${enable_request_body_gzip_compression:false}") + private boolean enabled; + + @Override + public void init(FilterConfig filterConfig) throws ServletException { + // Nothing to init (Sonar asks you to comment if you leave a method empty) + } + + /** + * Analyzes servlet request for possible gzipped body. When Content-Encoding header has "gzip" + * value and request method is POST, we read all the gzipped stream and if it has any data unzip + * it. In case when gzip Content-Encoding header specified but body is not actually in gzip format + * we will throw ZipException. + * + * @param servletRequest servlet request + * @param servletResponse servlet response + * @param chain filter chain + * @throws IOException throws when fails + * @throws ServletException thrown when fails + */ + @Override + public final void doFilter( + final ServletRequest servletRequest, + final ServletResponse servletResponse, + final FilterChain chain) + throws IOException, ServletException { + HttpServletRequest request = (HttpServletRequest) servletRequest; + HttpServletResponse response = (HttpServletResponse) servletResponse; + boolean isGzipped = + request.getHeader(HttpHeaders.CONTENT_ENCODING) != null + && request.getHeader(HttpHeaders.CONTENT_ENCODING).contains("gzip"); + boolean requestTypeSupported = "POST".equals(request.getMethod()); + + if (isGzipped) { + if (!enabled) { + throw new IllegalStateException( + "Received gzipped request body, but enable_request_body_gzip_compression is not set or is false"); + } + if (!requestTypeSupported) { + throw new IllegalStateException( + "Received request with a Content-Encoding: gzip header and a request method of: " + + request.getMethod() + + " Only POST requests are supported."); + } + + request = + new GzippedInputStreamRequestWrapper( + (HttpServletRequest) servletRequest, maxInflatedRequestBodySize); + } + + chain.doFilter(request, response); + } + + @Override + public final void destroy() { + // Nothing to destroy (Sonar asks you to comment if you leave a method empty) + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/util/ResettableHttpServletRequestFilter.java b/src/main/java/org/cbioportal/legacy/web/util/ResettableHttpServletRequestFilter.java new file mode 100644 index 00000000000..47050eaa820 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/util/ResettableHttpServletRequestFilter.java @@ -0,0 +1,40 @@ +package org.cbioportal.legacy.web.util; + +import jakarta.servlet.*; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import java.io.IOException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; +import org.springframework.web.util.ContentCachingRequestWrapper; +import org.springframework.web.util.ContentCachingResponseWrapper; + +/** + * @author ochoaa + */ +@Component +public class ResettableHttpServletRequestFilter implements Filter { + private Logger LOG = LoggerFactory.getLogger(ResettableHttpServletRequestFilter.class); + + @Override + public void init(FilterConfig aChain) throws ServletException { + // do nothing + } + + @Override + public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) + throws IOException, ServletException { + ContentCachingRequestWrapper wrappedRequest = + new ContentCachingRequestWrapper((HttpServletRequest) request); + ContentCachingResponseWrapper wrappedResponse = + new ContentCachingResponseWrapper((HttpServletResponse) response); + filterChain.doFilter(wrappedRequest, wrappedResponse); + wrappedResponse.copyBodyToResponse(); + } + + @Override + public void destroy() { + // do nothing + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/util/ScientificSmallDataBinner.java b/src/main/java/org/cbioportal/legacy/web/util/ScientificSmallDataBinner.java new file mode 100644 index 00000000000..0aeb5504625 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/util/ScientificSmallDataBinner.java @@ -0,0 +1,75 @@ +package org.cbioportal.legacy.web.util; + +import com.google.common.collect.Range; +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; +import org.cbioportal.legacy.model.DataBin; +import org.springframework.stereotype.Component; + +@Component +public class ScientificSmallDataBinner { + + public List calculateDataBins( + List sortedNumericalValues, + List valuesWithoutOutliers, + BigDecimal lowerOutlier, + BigDecimal upperOutlier) { + List exponents = + sortedNumericalValues.stream() + .map(d -> BigDecimal.valueOf(DataBinHelper.calcExponent(d))) + .filter(d -> d.compareTo(new BigDecimal("0")) != 0) + .collect(Collectors.toList()); + + Collections.sort(exponents); + + Range exponentBoxRange = DataBinHelper.calcBoxRange(exponents); + + List intervals = new ArrayList<>(); + + BigDecimal exponentRange = + exponentBoxRange == null + ? null + : exponentBoxRange.upperEndpoint().subtract(exponentBoxRange.lowerEndpoint()); + + if (exponentRange == null) { + // data set is not compatible with the scientific small data binner, + // just set one interval for the entire set + intervals.add(sortedNumericalValues.get(0)); + intervals.add(sortedNumericalValues.get(sortedNumericalValues.size() - 1)); + } else if (exponentRange.compareTo(new BigDecimal("1")) == 1) { + Integer interval = Math.round(exponentRange.floatValue() / 4); + + for (int i = exponentBoxRange.lowerEndpoint().intValue() - interval; + i <= exponentBoxRange.upperEndpoint().intValue(); + i += interval) { + intervals.add(BigDecimal.valueOf(Math.pow(10, i))); + } + } else if (exponentRange.compareTo(new BigDecimal("1")) == 0) { + intervals.add( + BigDecimal.valueOf(Math.pow(10, exponentBoxRange.lowerEndpoint().doubleValue()) / 3)); + + for (int i = exponentBoxRange.lowerEndpoint().intValue(); + i <= exponentBoxRange.upperEndpoint().intValue() + 1; + i++) { + BigDecimal powerTen = BigDecimal.valueOf(Math.pow(10, i)); + intervals.add(powerTen); + intervals.add(powerTen.multiply(new BigDecimal("3"))); + } + } else { // exponentRange == 0 + BigDecimal interval = + BigDecimal.valueOf(2 * Math.pow(10, exponentBoxRange.lowerEndpoint().doubleValue())); + + for (BigDecimal d = + BigDecimal.valueOf(Math.pow(10, exponentBoxRange.lowerEndpoint().intValue())); + d.doubleValue() <= Math.pow(10, exponentBoxRange.upperEndpoint().doubleValue() + 1); + d = d.add(interval)) { + intervals.add(d); + } + } + + return DataBinHelper.initDataBins(valuesWithoutOutliers, intervals, lowerOutlier, upperOutlier); + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/util/StudyViewFilterApplier.java b/src/main/java/org/cbioportal/legacy/web/util/StudyViewFilterApplier.java new file mode 100644 index 00000000000..3082c04b1a6 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/util/StudyViewFilterApplier.java @@ -0,0 +1,1711 @@ +package org.cbioportal.legacy.web.util; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Set; +import java.util.function.Function; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.collections4.map.MultiKeyMap; +import org.cbioportal.legacy.model.Binnable; +import org.cbioportal.legacy.model.ClinicalAttribute; +import org.cbioportal.legacy.model.ClinicalData; +import org.cbioportal.legacy.model.DataBin; +import org.cbioportal.legacy.model.DiscreteCopyNumberData; +import org.cbioportal.legacy.model.Gene; +import org.cbioportal.legacy.model.GeneFilter; +import org.cbioportal.legacy.model.GeneFilterQuery; +import org.cbioportal.legacy.model.GenePanel; +import org.cbioportal.legacy.model.GenePanelData; +import org.cbioportal.legacy.model.GenePanelToGene; +import org.cbioportal.legacy.model.GenericAssayDataBin; +import org.cbioportal.legacy.model.GenomicDataBin; +import org.cbioportal.legacy.model.MolecularData; +import org.cbioportal.legacy.model.MolecularProfile; +import org.cbioportal.legacy.model.MolecularProfile.MolecularAlterationType; +import org.cbioportal.legacy.model.MolecularProfileCaseIdentifier; +import org.cbioportal.legacy.model.Mutation; +import org.cbioportal.legacy.model.MutationFilterOption; +import org.cbioportal.legacy.model.NamespaceData; +import org.cbioportal.legacy.model.Sample; +import org.cbioportal.legacy.model.SampleList; +import org.cbioportal.legacy.model.UniqueKeyBase; +import org.cbioportal.legacy.service.ClinicalAttributeService; +import org.cbioportal.legacy.service.DiscreteCopyNumberService; +import org.cbioportal.legacy.service.GenePanelService; +import org.cbioportal.legacy.service.GeneService; +import org.cbioportal.legacy.service.GenericAssayService; +import org.cbioportal.legacy.service.MolecularDataService; +import org.cbioportal.legacy.service.MolecularProfileService; +import org.cbioportal.legacy.service.MutationService; +import org.cbioportal.legacy.service.NamespaceDataService; +import org.cbioportal.legacy.service.SampleListService; +import org.cbioportal.legacy.service.SampleService; +import org.cbioportal.legacy.service.StructuralVariantService; +import org.cbioportal.legacy.service.exception.MolecularProfileNotFoundException; +import org.cbioportal.legacy.service.util.MolecularProfileUtil; +import org.cbioportal.legacy.web.parameter.ClinicalDataFilter; +import org.cbioportal.legacy.web.parameter.ClinicalDataType; +import org.cbioportal.legacy.web.parameter.DataBinCountFilter; +import org.cbioportal.legacy.web.parameter.DataBinFilter; +import org.cbioportal.legacy.web.parameter.DataBinMethod; +import org.cbioportal.legacy.web.parameter.DataFilter; +import org.cbioportal.legacy.web.parameter.DataFilterValue; +import org.cbioportal.legacy.web.parameter.DiscreteCopyNumberEventType; +import org.cbioportal.legacy.web.parameter.GeneIdType; +import org.cbioportal.legacy.web.parameter.GenericAssayDataBinCountFilter; +import org.cbioportal.legacy.web.parameter.GenericAssayDataBinFilter; +import org.cbioportal.legacy.web.parameter.GenericAssayDataFilter; +import org.cbioportal.legacy.web.parameter.GenomicDataBinCountFilter; +import org.cbioportal.legacy.web.parameter.GenomicDataBinFilter; +import org.cbioportal.legacy.web.parameter.GenomicDataFilter; +import org.cbioportal.legacy.web.parameter.MutationDataFilter; +import org.cbioportal.legacy.web.parameter.MutationOption; +import org.cbioportal.legacy.web.parameter.NamespaceDataFilter; +import org.cbioportal.legacy.web.parameter.Projection; +import org.cbioportal.legacy.web.parameter.SampleIdentifier; +import org.cbioportal.legacy.web.parameter.StudyViewFilter; +import org.cbioportal.legacy.web.util.appliers.StudyViewSubFilterApplier; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.context.ApplicationContext; +import org.springframework.stereotype.Component; + +@Component +public class StudyViewFilterApplier { + @Autowired private ApplicationContext applicationContext; + + private StudyViewFilterApplier instance; + + // This gets initialized and overwritten. We do this because Spring's unit tests + // don't know how to autowire this, even though production Spring does. If we + // don't give this an initial value, we get NPEs. + @Autowired private final List subFilterAppliers = new ArrayList<>(); + + @Autowired private SampleService sampleService; + @Autowired private MutationService mutationService; + @Autowired private DiscreteCopyNumberService discreteCopyNumberService; + @Autowired private MolecularProfileService molecularProfileService; + @Autowired private GenePanelService genePanelService; + @Autowired private ClinicalDataEqualityFilterApplier clinicalDataEqualityFilterApplier; + @Autowired private ClinicalDataIntervalFilterApplier clinicalDataIntervalFilterApplier; + @Autowired private CustomDataFilterApplier customDataFilterApplier; + @Autowired private StudyViewFilterUtil studyViewFilterUtil; + @Autowired private GeneService geneService; + @Autowired private ClinicalAttributeService clinicalAttributeService; + @Autowired private SampleListService sampleListService; + @Autowired private MolecularDataService molecularDataService; + @Autowired private NamespaceDataService namespaceDataService; + @Autowired private GenericAssayService genericAssayService; + @Autowired private DataBinner dataBinner; + @Autowired private StructuralVariantService structuralVariantService; + @Autowired private MolecularProfileUtil molecularProfileUtil; + + private StudyViewFilterApplier getInstance() { + if (Objects.isNull(instance)) { + instance = applicationContext.getBean(StudyViewFilterApplier.class); + } + return instance; + } + + Function sampleToSampleIdentifier = + new Function() { + + public SampleIdentifier apply(Sample sample) { + return studyViewFilterUtil.buildSampleIdentifier( + sample.getCancerStudyIdentifier(), sample.getStableId()); + } + }; + + public List apply(StudyViewFilter studyViewFilter) { + return this.getInstance().cachedApply(studyViewFilter); + } + + @Cacheable( + cacheResolver = "generalRepositoryCacheResolver", + condition = "@cacheEnabledConfig.getEnabled()") + public List cachedApply(StudyViewFilter studyViewFilter) { + return this.apply(studyViewFilter, false); + } + + public List apply(StudyViewFilter studyViewFilter, boolean negateFilters) { + + List sampleIdentifiers = new ArrayList<>(); + if (studyViewFilter == null) { + return sampleIdentifiers; + } + + if (studyViewFilter != null + && studyViewFilter.getSampleIdentifiers() != null + && !studyViewFilter.getSampleIdentifiers().isEmpty()) { + List studyIds = new ArrayList<>(); + List sampleIds = new ArrayList<>(); + studyViewFilterUtil.extractStudyAndSampleIds( + studyViewFilter.getSampleIdentifiers(), studyIds, sampleIds); + sampleIdentifiers = + sampleService.fetchSamples(studyIds, sampleIds, Projection.ID.name()).stream() + .map(sampleToSampleIdentifier) + .collect(Collectors.toList()); + } else { + sampleIdentifiers = + sampleService + .getAllSamplesInStudies( + studyViewFilter.getStudyIds(), Projection.ID.name(), null, null, null, null) + .stream() + .map(sampleToSampleIdentifier) + .collect(Collectors.toList()); + } + + List studyIds = + sampleIdentifiers.stream() + .map(SampleIdentifier::getStudyId) + .distinct() + .collect(Collectors.toList()); + + List clinicalDataEqualityFilters = new ArrayList<>(); + List clinicalDataIntervalFilters = new ArrayList<>(); + + List clinicalDataFilters = studyViewFilter.getClinicalDataFilters(); + + if (!CollectionUtils.isEmpty(clinicalDataFilters)) { + List attributeIds = + clinicalDataFilters.stream() + .map(ClinicalDataFilter::getAttributeId) + .collect(Collectors.toList()); + List clinicalAttributes = + clinicalAttributeService.getClinicalAttributesByStudyIdsAndAttributeIds( + studyIds, attributeIds); + + Map clinicalAttributeMap = + clinicalAttributes.stream() + .collect( + Collectors.toMap( + ClinicalAttribute::getAttrId, + Function.identity(), + (a, b) -> { + return a.getDatatype().equals("STRING") ? a : b; + })); + + clinicalDataFilters.forEach( + clinicalDataFilter -> { + String attributeId = clinicalDataFilter.getAttributeId(); + if (clinicalAttributeMap.containsKey(attributeId)) { + if (clinicalAttributeMap.get(attributeId).getDatatype().equals("STRING")) { + clinicalDataEqualityFilters.add(clinicalDataFilter); + } else { + clinicalDataIntervalFilters.add(clinicalDataFilter); + } + } + }); + } + + if (!CollectionUtils.isEmpty(clinicalDataEqualityFilters)) { + sampleIdentifiers = + equalityFilterClinicalData(sampleIdentifiers, clinicalDataEqualityFilters, negateFilters); + } + + if (!CollectionUtils.isEmpty(clinicalDataIntervalFilters)) { + sampleIdentifiers = + intervalFilterClinicalData(sampleIdentifiers, clinicalDataIntervalFilters, negateFilters); + } + + if (!CollectionUtils.isEmpty(studyViewFilter.getCustomDataFilters())) { + sampleIdentifiers = + customDataFilterApplier.apply( + sampleIdentifiers, studyViewFilter.getCustomDataFilters(), negateFilters); + } + + if (!CollectionUtils.isEmpty(studyViewFilter.getNamespaceDataFilters())) { + sampleIdentifiers = + filterNamespaceData( + sampleIdentifiers, + studyViewFilter.getNamespaceDataFilters(), + negateFilters, + clinicalDataEqualityFilterApplier); + } + + List molecularProfiles = null; + if (!CollectionUtils.isEmpty(studyViewFilter.getGeneFilters()) + || !CollectionUtils.isEmpty(studyViewFilter.getMutationDataFilters()) + || !CollectionUtils.isEmpty(studyViewFilter.getGenomicDataFilters()) + || !CollectionUtils.isEmpty(studyViewFilter.getGenericAssayDataFilters()) + || !CollectionUtils.isEmpty(studyViewFilter.getGenomicProfiles())) { + + molecularProfiles = + molecularProfileService.getMolecularProfilesInStudies(studyIds, "SUMMARY"); + } + + List genomicDataEqualityFilters = new ArrayList<>(); + List genomicDataIntervalFilters = new ArrayList<>(); + + List genomicDataFilters = studyViewFilter.getGenomicDataFilters(); + + if (!CollectionUtils.isEmpty(genomicDataFilters)) { + Map molecularProfileMapByType = + molecularProfileUtil + .categorizeMolecularProfilesByStableIdSuffixes(molecularProfiles) + .entrySet() + .stream() + .collect(Collectors.toMap(Map.Entry::getKey, e -> e.getValue().get(0))); + + genomicDataFilters.forEach( + genomicDataFilter -> { + String profileType = genomicDataFilter.getProfileType(); + if (molecularProfileMapByType.containsKey(profileType)) { + if (molecularProfileMapByType.get(profileType).getDatatype().equals("DISCRETE")) { + genomicDataEqualityFilters.add(genomicDataFilter); + } else { + genomicDataIntervalFilters.add(genomicDataFilter); + } + } + }); + } + + if (!CollectionUtils.isEmpty(genomicDataEqualityFilters)) { + sampleIdentifiers = + equalityFilterExpressionData( + sampleIdentifiers, molecularProfiles, genomicDataEqualityFilters, negateFilters); + } + + if (!CollectionUtils.isEmpty(genomicDataIntervalFilters)) { + sampleIdentifiers = + intervalFilterExpressionData( + sampleIdentifiers, molecularProfiles, genomicDataIntervalFilters, negateFilters); + } + + sampleIdentifiers = + intervalFilterExpressionData( + sampleIdentifiers, + molecularProfiles, + studyViewFilter.getGenericAssayDataFilters(), + negateFilters); + + if (!CollectionUtils.isEmpty(studyViewFilter.getGeneFilters())) { + Map molecularProfileMap = + molecularProfiles.stream() + .collect(Collectors.toMap(MolecularProfile::getStableId, Function.identity())); + List mutatedGeneFilters = new ArrayList(); + List structuralVariantGeneFilters = new ArrayList(); + List cnaGeneFilters = new ArrayList(); + + splitGeneFiltersByMolecularAlterationType( + studyViewFilter.getGeneFilters(), + molecularProfileMap, + mutatedGeneFilters, + structuralVariantGeneFilters, + cnaGeneFilters); + + if ((mutatedGeneFilters.size() + structuralVariantGeneFilters.size() + cnaGeneFilters.size()) + == studyViewFilter.getGeneFilters().size()) { + if (!mutatedGeneFilters.isEmpty()) { + sampleIdentifiers = + filterMutatedGenes(mutatedGeneFilters, molecularProfileMap, sampleIdentifiers); + } + if (!structuralVariantGeneFilters.isEmpty()) { + sampleIdentifiers = + filterStructuralVariantGenes( + structuralVariantGeneFilters, molecularProfileMap, sampleIdentifiers); + } + if (!cnaGeneFilters.isEmpty()) { + sampleIdentifiers = + filterCNAGenes(cnaGeneFilters, molecularProfileMap, sampleIdentifiers); + } + + } else { + return new ArrayList<>(); + } + } + + if (!CollectionUtils.isEmpty(studyViewFilter.getGenomicProfiles())) { + Map> groupStudySampleIdentifiers = + sampleIdentifiers.stream().collect(Collectors.groupingBy(SampleIdentifier::getStudyId)); + + Map> molecularProfileSet = + molecularProfileUtil.categorizeMolecularProfilesByStableIdSuffixes(molecularProfiles); + + List molecularProfileSampleIdentifiers = new ArrayList<>(); + + studyViewFilter.getGenomicProfiles().stream() + .forEach( + profileValues -> { + profileValues.stream() + .forEach( + profileValue -> { + molecularProfileSet.getOrDefault(profileValue, new ArrayList<>()).stream() + .forEach( + profile -> { + groupStudySampleIdentifiers + .getOrDefault( + profile.getCancerStudyIdentifier(), new ArrayList<>()) + .forEach( + sampleIdentifier -> { + MolecularProfileCaseIdentifier profileCaseIdentifier = + new MolecularProfileCaseIdentifier(); + profileCaseIdentifier.setMolecularProfileId( + profile.getStableId()); + profileCaseIdentifier.setCaseId( + sampleIdentifier.getSampleId()); + molecularProfileSampleIdentifiers.add( + profileCaseIdentifier); + }); + }); + }); + }); + + List genePanelData = + genePanelService.fetchGenePanelDataInMultipleMolecularProfiles( + molecularProfileSampleIdentifiers); + + // gene panel data is { profileId, sampleId, isProfiled } + // it tells us whether a particular sample is profiled by a given molecularprofile + // we can use the gene panel to find out what genes were profiled + for (List profileValues : studyViewFilter.getGenomicProfiles()) { + + // using the profileIds from the filter we get a map, stableId to profile entity + Map profileMap = + profileValues.stream() + .flatMap( + profileValue -> + molecularProfileSet.getOrDefault(profileValue, new ArrayList<>()).stream()) + .collect(Collectors.toMap(MolecularProfile::getStableId, Function.identity())); + + Set filteredSampleIdentifiers = new HashSet<>(); + + // for each sample/profile combo, we need to find out whether + // the profileMap contains that profile id + genePanelData.forEach( + datum -> { + if (datum.getProfiled() && profileMap.containsKey(datum.getMolecularProfileId())) { + SampleIdentifier sampleIdentifier = + studyViewFilterUtil.buildSampleIdentifier( + datum.getStudyId(), datum.getSampleId()); + filteredSampleIdentifiers.add(sampleIdentifier); + } + }); + sampleIdentifiers.retainAll(filteredSampleIdentifiers); + } + } + + if (!CollectionUtils.isEmpty(studyViewFilter.getCaseLists())) { + List sampleLists = + sampleListService.getAllSampleListsInStudies(studyIds, Projection.DETAILED.name()); + Map> groupedSampleListByListType = + studyViewFilterUtil.categorizeSampleLists(sampleLists); + + for (List sampleListTypes : studyViewFilter.getCaseLists()) { + List filteredSampleIdentifiers = + sampleListTypes.stream() + .flatMap( + sampleListType -> + groupedSampleListByListType + .getOrDefault(sampleListType, new ArrayList<>()) + .stream() + .flatMap( + sampleList -> { + return sampleList.getSampleIds().stream() + .map( + sampleId -> + studyViewFilterUtil.buildSampleIdentifier( + sampleList.getCancerStudyIdentifier(), sampleId)); + })) + .toList(); + + sampleIdentifiers.retainAll(filteredSampleIdentifiers); + } + } + + List mutationOptionDataFilters = new ArrayList<>(); + List mutationTypeDataFilters = new ArrayList<>(); + + List mutationDataFilters = studyViewFilter.getMutationDataFilters(); + + if (!CollectionUtils.isEmpty(mutationDataFilters)) { + mutationDataFilters.forEach( + mutationDataFilter -> { + if (mutationDataFilter.getCategorization() == MutationOption.MUTATED) { + mutationOptionDataFilters.add(mutationDataFilter); + } else { + mutationTypeDataFilters.add(mutationDataFilter); + } + }); + } + + if (!CollectionUtils.isEmpty(mutationOptionDataFilters)) { + sampleIdentifiers = + filterMutationData( + sampleIdentifiers, + molecularProfiles, + mutationOptionDataFilters, + negateFilters, + clinicalDataEqualityFilterApplier); + } + + if (!CollectionUtils.isEmpty(mutationTypeDataFilters)) { + sampleIdentifiers = + filterMutationData( + sampleIdentifiers, + molecularProfiles, + mutationTypeDataFilters, + negateFilters, + clinicalDataEqualityFilterApplier); + } + + return chainSubFilters(studyViewFilter, sampleIdentifiers); + } + + private List chainSubFilters( + StudyViewFilter studyViewFilter, List sampleIdentifiers) { + for (StudyViewSubFilterApplier subFilterApplier : subFilterAppliers) { + if (!sampleIdentifiers.isEmpty() && subFilterApplier.shouldApplyFilter(studyViewFilter)) { + sampleIdentifiers = subFilterApplier.filter(sampleIdentifiers, studyViewFilter); + } + } + + return sampleIdentifiers; + } + + private List intervalFilterClinicalData( + List sampleIdentifiers, + List clinicalDataIntervalFilters, + boolean negateFilters) { + return clinicalDataIntervalFilterApplier.apply( + sampleIdentifiers, clinicalDataIntervalFilters, negateFilters); + } + + private List equalityFilterClinicalData( + List sampleIdentifiers, + List clinicalDataEqualityFilters, + boolean negateFilters) { + return clinicalDataEqualityFilterApplier.apply( + sampleIdentifiers, clinicalDataEqualityFilters, negateFilters); + } + + private List filterMutatedGenes( + List mutatedGenefilters, + Map molecularProfileMap, + List sampleIdentifiers) { + + if (sampleIdentifiers == null || sampleIdentifiers.isEmpty()) { + return new ArrayList<>(); + } + + for (GeneFilter genefilter : mutatedGenefilters) { + + List filteredMolecularProfiles = + genefilter.getMolecularProfileIds().stream().map(molecularProfileMap::get).toList(); + + Map> mapByStudyId = + filteredMolecularProfiles.stream() + .collect(Collectors.groupingBy(MolecularProfile::getCancerStudyIdentifier)); + + for (List geneQueries : genefilter.getGeneQueries()) { + List studyIds = new ArrayList<>(); + List sampleIds = new ArrayList<>(); + + List hugoGeneSymbols = + geneQueries.stream().map(GeneFilterQuery::getHugoGeneSymbol).toList(); + + Map symbolToEntrezGeneId = + geneService + .fetchGenes( + new ArrayList<>(hugoGeneSymbols), + GeneIdType.HUGO_GENE_SYMBOL.name(), + Projection.SUMMARY.name()) + .stream() + .collect(Collectors.toMap(Gene::getHugoGeneSymbol, Gene::getEntrezGeneId)); + + geneQueries.removeIf(q -> !symbolToEntrezGeneId.containsKey(q.getHugoGeneSymbol())); + + geneQueries.stream() + .forEach(q -> q.setEntrezGeneId(symbolToEntrezGeneId.get(q.getHugoGeneSymbol()))); + studyViewFilterUtil.extractStudyAndSampleIds(sampleIdentifiers, studyIds, sampleIds); + + List molecularProfileIds = new ArrayList<>(); + int removedSampleCount = 0; + for (int i = 0; i < studyIds.size(); i++) { + String studyId = studyIds.get(i); + if (mapByStudyId.containsKey(studyId)) { + molecularProfileIds.add(mapByStudyId.get(studyId).get(0).getStableId()); + } else { + sampleIds.remove(i - removedSampleCount); + removedSampleCount++; + } + } + + sampleIdentifiers = + mutationService + .getMutationsInMultipleMolecularProfilesByGeneQueries( + molecularProfileIds, + sampleIds, + geneQueries, + Projection.ID.name(), + null, + null, + null, + null) + .stream() + .map( + m -> studyViewFilterUtil.buildSampleIdentifier(m.getStudyId(), m.getSampleId())) + .distinct() + .collect(Collectors.toList()); + } + } + return sampleIdentifiers; + } + + private List filterStructuralVariantGenes( + List svGenefilters, + Map molecularProfileMap, + List sampleIdentifiers) { + + if (sampleIdentifiers == null || sampleIdentifiers.isEmpty()) { + return new ArrayList<>(); + } + + for (GeneFilter genefilter : svGenefilters) { + + List filteredMolecularProfiles = + genefilter.getMolecularProfileIds().stream().map(molecularProfileMap::get).toList(); + + Map> mapByStudyId = + filteredMolecularProfiles.stream() + .collect(Collectors.groupingBy(MolecularProfile::getCancerStudyIdentifier)); + + for (List geneQueries : genefilter.getGeneQueries()) { + List studyIds = new ArrayList<>(); + List sampleIds = new ArrayList<>(); + + List hugoGeneSymbols = + geneQueries.stream().map(GeneFilterQuery::getHugoGeneSymbol).toList(); + + Map symbolToEntrezGeneId = + geneService + .fetchGenes( + new ArrayList<>(hugoGeneSymbols), + GeneIdType.HUGO_GENE_SYMBOL.name(), + Projection.SUMMARY.name()) + .stream() + .collect(Collectors.toMap(Gene::getHugoGeneSymbol, Gene::getEntrezGeneId)); + + geneQueries.removeIf(q -> !symbolToEntrezGeneId.containsKey(q.getHugoGeneSymbol())); + + geneQueries.stream() + .forEach(q -> q.setEntrezGeneId(symbolToEntrezGeneId.get(q.getHugoGeneSymbol()))); + + studyViewFilterUtil.extractStudyAndSampleIds(sampleIdentifiers, studyIds, sampleIds); + + List molecularProfileIds = new ArrayList<>(); + int removedSampleCount = 0; + for (int i = 0; i < studyIds.size(); i++) { + String studyId = studyIds.get(i); + if (mapByStudyId.containsKey(studyId)) { + molecularProfileIds.add(mapByStudyId.get(studyId).get(0).getStableId()); + } else { + sampleIds.remove(i - removedSampleCount); + removedSampleCount++; + } + } + + sampleIdentifiers = + structuralVariantService + .fetchStructuralVariantsByGeneQueries(molecularProfileIds, sampleIds, geneQueries) + .stream() + .map( + m -> studyViewFilterUtil.buildSampleIdentifier(m.getStudyId(), m.getSampleId())) + .distinct() + .collect(Collectors.toList()); + } + } + return sampleIdentifiers; + } + + private List filterCNAGenes( + List cnaGeneFilters, + Map molecularProfileMap, + List sampleIdentifiers) { + + if (sampleIdentifiers == null || sampleIdentifiers.isEmpty()) { + return new ArrayList<>(); + } + + for (GeneFilter geneFilter : cnaGeneFilters) { + + List filteredMolecularProfiles = + geneFilter.getMolecularProfileIds().stream().map(molecularProfileMap::get).toList(); + + for (List geneQueries : geneFilter.getGeneQueries()) { + + List studyIds = new ArrayList<>(); + List sampleIds = new ArrayList<>(); + studyViewFilterUtil.extractStudyAndSampleIds(sampleIdentifiers, studyIds, sampleIds); + + List molecularProfileIds = new ArrayList<>(); + Map> mapByStudyId = + filteredMolecularProfiles.stream() + .collect(Collectors.groupingBy(MolecularProfile::getCancerStudyIdentifier)); + int removedSampleCount = 0; + for (int i = 0; i < studyIds.size(); i++) { + String studyId = studyIds.get(i); + if (mapByStudyId.containsKey(studyId)) { + molecularProfileIds.add(mapByStudyId.get(studyId).get(0).getStableId()); + } else { + sampleIds.remove(i - removedSampleCount); + removedSampleCount++; + } + } + + List resultList = + DiscreteCopyNumberEventType.ALL.getAlterationTypes().stream() + .flatMap( + alterationType -> { + List filteredGeneQueries = + geneQueries.stream() + .filter( + geneQuery -> + geneQuery.getAlterations().stream() + .anyMatch( + alteration -> alteration.getCode() == alterationType)) + .collect(Collectors.toList()); + + List hugoGeneSymbols = + filteredGeneQueries.stream() + .map(GeneFilterQuery::getHugoGeneSymbol) + .toList(); + + Map symbolToEntrezGeneId = + geneService + .fetchGenes( + new ArrayList<>(hugoGeneSymbols), + GeneIdType.HUGO_GENE_SYMBOL.name(), + Projection.SUMMARY.name()) + .stream() + .collect( + Collectors.toMap(Gene::getHugoGeneSymbol, Gene::getEntrezGeneId)); + + filteredGeneQueries.removeIf( + q -> !symbolToEntrezGeneId.containsKey(q.getHugoGeneSymbol())); + + filteredGeneQueries.forEach( + q -> q.setEntrezGeneId(symbolToEntrezGeneId.get(q.getHugoGeneSymbol()))); + + List copyNumberDatas = new ArrayList<>(); + if (!filteredGeneQueries.isEmpty()) { + copyNumberDatas = + discreteCopyNumberService + .getDiscreteCopyNumbersInMultipleMolecularProfilesByGeneQueries( + molecularProfileIds, + sampleIds, + filteredGeneQueries, + Projection.ID.name()); + } + return copyNumberDatas.stream(); + }) + .toList(); + + sampleIdentifiers = + resultList.stream() + .map( + d -> studyViewFilterUtil.buildSampleIdentifier(d.getStudyId(), d.getSampleId())) + .distinct() + .collect(Collectors.toList()); + } + } + + return sampleIdentifiers; + } + + private List filterMutationData( + List sampleIdentifiers, + List molecularProfiles, + List mutationDataFilters, + boolean negateFilters, + ClinicalDataFilterApplier clinicalDataFilterApplier) { + if (CollectionUtils.isNotEmpty(mutationDataFilters) + && CollectionUtils.isNotEmpty(sampleIdentifiers)) { + List clinicalDatas = + fetchMutationDataAndTransformToClinicalDataList( + sampleIdentifiers, molecularProfiles, mutationDataFilters); + + MultiKeyMap clinicalDataMap; + if (clinicalDataFilterApplier instanceof ClinicalDataEqualityFilterApplier) { + clinicalDataMap = ClinicalDataEqualityFilterApplier.buildClinicalDataMap(clinicalDatas); + } else { + clinicalDataMap = ClinicalDataIntervalFilterApplier.buildClinicalDataMap(clinicalDatas); + } + + List newSampleIdentifiers = new ArrayList<>(); + + // loop through each mutationDataFilter and filter data + for (MutationDataFilter mutationDataFilter : mutationDataFilters) { + // loop through each list of DataFilterValue and do union or intersection selections + for (List values : mutationDataFilter.getValues()) { + ClinicalDataFilter clinicalDataFilter = new ClinicalDataFilter(); + clinicalDataFilter.setAttributeId( + mutationDataFilter.getHugoGeneSymbol() + mutationDataFilter.getProfileType()); + clinicalDataFilter.setValues(values); + + List attributes = Collections.singletonList(clinicalDataFilter); + + // union selection: filter all samples that have at least one value from a list of + // DataFilterValue, e.g. Missense_Mutation, In_Shift_Del, ... + List filteredSampleIdentifiers = + filterSampleIdentifiers( + sampleIdentifiers, + attributes, + clinicalDataMap, + clinicalDataFilterApplier, + negateFilters); + + if (newSampleIdentifiers.isEmpty()) { + newSampleIdentifiers = filteredSampleIdentifiers; + } else { + // intersection selection: retain shared samples from each selection for all + // mutationDataFilter + newSampleIdentifiers.retainAll(filteredSampleIdentifiers); + } + } + } + + return newSampleIdentifiers.stream().distinct().toList(); + } + + return sampleIdentifiers; + } + + private List filterNamespaceData( + List sampleIdentifiers, + List namespaceDataFilters, + boolean negateFilters, + ClinicalDataFilterApplier clinicalDataFilterApplier) { + + if (CollectionUtils.isNotEmpty(namespaceDataFilters) + && CollectionUtils.isNotEmpty(sampleIdentifiers)) { + + List clinicalDatas = + fetchNamespaceDataAndTransformToClinicalDataList(sampleIdentifiers, namespaceDataFilters); + + MultiKeyMap clinicalDataMap; + clinicalDataMap = ClinicalDataEqualityFilterApplier.buildClinicalDataMap(clinicalDatas); + // No interval filtering for namespaces because usage in histogram would be illogical to users + // as samples can have many different + // values i.e. cannot select samples based on bins, because they are not exclusive. + + List newSampleIdentifiers = new ArrayList<>(); + + // loop through each namespaceDataFilter and filter data + for (NamespaceDataFilter namespaceDataFilter : namespaceDataFilters) { + // loop through each list of DataFilterValue and do union or intersection selections + for (List values : namespaceDataFilter.getValues()) { + ClinicalDataFilter clinicalDataFilter = new ClinicalDataFilter(); + clinicalDataFilter.setAttributeId( + namespaceDataFilter.getOuterKey() + namespaceDataFilter.getInnerKey()); + clinicalDataFilter.setValues(values); + + List attributes = Collections.singletonList(clinicalDataFilter); + + // union selection: filter all samples that have at least one value from a list of + // DataFilterValue + List filteredSampleIdentifiers = + filterSampleIdentifiers( + sampleIdentifiers, + attributes, + clinicalDataMap, + clinicalDataFilterApplier, + negateFilters); + + if (newSampleIdentifiers.isEmpty()) { + newSampleIdentifiers = filteredSampleIdentifiers; + } else { + // intersection selection: retain shared samples from each selection for all + // namespaceDataFilter + newSampleIdentifiers.retainAll(filteredSampleIdentifiers); + } + } + } + + return newSampleIdentifiers.stream().distinct().toList(); + } + + return sampleIdentifiers; + } + + private void splitGeneFiltersByMolecularAlterationType( + List genefilters, + Map molecularProfileMap, + List mutatedGeneFilters, + List structuralVariantGeneFilters, + List cnaGeneFilters) { + + for (GeneFilter genefilter : genefilters) { + + List filteredMolecularProfiles = + genefilter.getMolecularProfileIds().stream() + // need this filter criteria since profile id might be present + // in filter but the study might already been filtered out + .filter(molecularProfileMap::containsKey) + .map(molecularProfileMap::get) + .toList(); + + Set alterationTypes = + filteredMolecularProfiles.stream() + .map(MolecularProfile::getMolecularAlterationType) + .collect(Collectors.toSet()); + + Set dataTypes = + filteredMolecularProfiles.stream() + .map(MolecularProfile::getDatatype) + .collect(Collectors.toSet()); + + Set filteredMolecularProfileIds = + filteredMolecularProfiles.stream() + .map(MolecularProfile::getStableId) + .collect(Collectors.toSet()); + genefilter.setMolecularProfileIds(filteredMolecularProfileIds); + + if (alterationTypes.size() == 1) { + MolecularAlterationType alterationType = alterationTypes.iterator().next(); + + if (alterationType.equals(MolecularAlterationType.STRUCTURAL_VARIANT)) { + structuralVariantGeneFilters.add(genefilter); + } else if (alterationType == MolecularAlterationType.MUTATION_EXTENDED) { + mutatedGeneFilters.add(genefilter); + } else if (alterationType == MolecularAlterationType.COPY_NUMBER_ALTERATION + && dataTypes.size() == 1 + && dataTypes.iterator().next().equals("DISCRETE")) { + cnaGeneFilters.add(genefilter); + } + } + } + } + + public List getUniqkeyKeys(List studyIds, List caseIds) { + List uniqkeyKeys = new ArrayList(); + for (int i = 0; i < caseIds.size(); i++) { + uniqkeyKeys.add(studyViewFilterUtil.getCaseUniqueKey(studyIds.get(i), caseIds.get(i))); + } + return uniqkeyKeys; + } + + public + List getDataBins(DataBinMethod dataBinMethod, T dataBinCountFilter) { + List dataBinFilters = fetchDataBinFilters(dataBinCountFilter); + StudyViewFilter studyViewFilter = dataBinCountFilter.getStudyViewFilter(); + + if (dataBinFilters.size() == 1) { + removeSelfFromFilter(dataBinFilters.get(0), studyViewFilter); + } + + List resultDataBins; + List filteredSampleIds = new ArrayList<>(); + List filteredStudyIds = new ArrayList<>(); + + List filteredData = + fetchData(dataBinCountFilter, studyViewFilter, filteredSampleIds, filteredStudyIds); + + List filteredUniqueSampleKeys = getUniqkeyKeys(filteredStudyIds, filteredSampleIds); + + Map> filteredClinicalDataByAttributeId = + filteredData.stream().collect(Collectors.groupingBy(Binnable::getAttrId)); + + if (dataBinMethod == DataBinMethod.STATIC) { + + StudyViewFilter filter = studyViewFilter == null ? null : new StudyViewFilter(); + if (filter != null) { + filter.setStudyIds(studyViewFilter.getStudyIds()); + filter.setSampleIdentifiers(studyViewFilter.getSampleIdentifiers()); + } + + List unfilteredSampleIds = new ArrayList<>(); + List unfilteredStudyIds = new ArrayList<>(); + List unfilteredData = + fetchData(dataBinCountFilter, filter, unfilteredSampleIds, unfilteredStudyIds); + + List unFilteredUniqueSampleKeys = + getUniqkeyKeys(unfilteredSampleIds, unfilteredStudyIds); + + Map> unfilteredDataByAttributeId = + unfilteredData.stream().collect(Collectors.groupingBy(Binnable::getAttrId)); + + resultDataBins = + dataBinFilters.stream() + .flatMap( + dataBinFilter -> { + String attributeId = + studyViewFilterUtil.getDataBinFilterUniqueKey(dataBinFilter); + return dataBinner + .calculateClinicalDataBins( + dataBinFilter, + ClinicalDataType.SAMPLE, + filteredClinicalDataByAttributeId.getOrDefault( + attributeId, Collections.emptyList()), + unfilteredDataByAttributeId.getOrDefault( + attributeId, Collections.emptyList()), + filteredUniqueSampleKeys, + unFilteredUniqueSampleKeys) + .stream() + .map(dataBin -> (U) transform(dataBinFilter, dataBin)); + }) + .collect(Collectors.toList()); + + } else { // dataBinMethod == DataBinMethod.DYNAMIC + resultDataBins = + dataBinFilters.stream() + .flatMap( + dataBinFilter -> + dataBinner + .calculateDataBins( + dataBinFilter, + ClinicalDataType.SAMPLE, + filteredClinicalDataByAttributeId.getOrDefault( + studyViewFilterUtil.getDataBinFilterUniqueKey(dataBinFilter), + Collections.emptyList()), + filteredUniqueSampleKeys) + .stream() + .map(dataBin -> (U) transform(dataBinFilter, dataBin))) + .collect(Collectors.toList()); + } + + return resultDataBins; + } + + private List fetchData( + S dataBinCountFilter, + StudyViewFilter studyViewFilter, + List sampleIds, + List studyIds) { + + List filteredSampleIdentifiers = apply(studyViewFilter); + studyViewFilterUtil.extractStudyAndSampleIds(filteredSampleIdentifiers, studyIds, sampleIds); + + List molecularProfiles = + molecularProfileService.getMolecularProfilesInStudies(studyIds, Projection.SUMMARY.name()); + + Map> molecularProfileMap = + molecularProfileUtil.categorizeMolecularProfilesByStableIdSuffixes(molecularProfiles); + + if (dataBinCountFilter instanceof GenomicDataBinCountFilter genomicDataBinCountFilter) { + List genomicDataBinFilters = + genomicDataBinCountFilter.getGenomicDataBinFilters(); + + Set hugoGeneSymbols = + genomicDataBinFilters.stream() + .map(GenomicDataBinFilter::getHugoGeneSymbol) + .collect(Collectors.toSet()); + + Map geneSymbolIdMap = + geneService + .fetchGenes( + new ArrayList<>(hugoGeneSymbols), + GeneIdType.HUGO_GENE_SYMBOL.name(), + Projection.SUMMARY.name()) + .stream() + .collect(Collectors.toMap(Gene::getHugoGeneSymbol, Gene::getEntrezGeneId)); + + return genomicDataBinFilters.stream() + .flatMap( + genomicDataBinFilter -> { + Map studyIdToMolecularProfileIdMap = + molecularProfileMap + .getOrDefault(genomicDataBinFilter.getProfileType(), new ArrayList<>()) + .stream() + .collect( + Collectors.toMap( + MolecularProfile::getCancerStudyIdentifier, + MolecularProfile::getStableId)); + + return invokeDataFunc( + sampleIds, + studyIds, + List.of( + geneSymbolIdMap.get(genomicDataBinFilter.getHugoGeneSymbol()).toString()), + studyIdToMolecularProfileIdMap, + studyViewFilterUtil.getDataBinFilterUniqueKey(genomicDataBinFilter), + fetchMolecularData); + }) + .collect(Collectors.toList()); + } else if (dataBinCountFilter + instanceof GenericAssayDataBinCountFilter genomicDataBinCountFilter) { + + List genericAssayDataBinFilters = + genomicDataBinCountFilter.getGenericAssayDataBinFilters(); + + return genericAssayDataBinFilters.stream() + .flatMap( + genericAssayDataBinFilter -> { + Map studyIdToMolecularProfileIdMap = + molecularProfileMap + .getOrDefault(genericAssayDataBinFilter.getProfileType(), new ArrayList<>()) + .stream() + .collect( + Collectors.toMap( + MolecularProfile::getCancerStudyIdentifier, + MolecularProfile::getStableId)); + + return invokeDataFunc( + sampleIds, + studyIds, + Collections.singletonList(genericAssayDataBinFilter.getStableId()), + studyIdToMolecularProfileIdMap, + studyViewFilterUtil.getDataBinFilterUniqueKey(genericAssayDataBinFilter), + fetchGenericAssayData); + }) + .collect(Collectors.toList()); + } + + return new ArrayList<>(); + } + + private Stream invokeDataFunc( + List sampleIds, + List studyIds, + List stableIds, + Map studyIdToMolecularProfileIdMap, + String attributeId, + FourParameterFunction, List, List, String, List> + dataFunc) { + + List mappedSampleIds = new ArrayList<>(); + List mappedProfileIds = new ArrayList<>(); + + for (int i = 0; i < sampleIds.size(); i++) { + String studyId = studyIds.get(i); + if (studyIdToMolecularProfileIdMap.containsKey(studyId)) { + mappedSampleIds.add(sampleIds.get(i)); + mappedProfileIds.add(studyIdToMolecularProfileIdMap.get(studyId)); + } + } + + if (mappedSampleIds.isEmpty()) { + return Stream.of(); + } + return dataFunc.apply(mappedProfileIds, mappedSampleIds, stableIds, attributeId).stream(); + } + + @FunctionalInterface + private interface FourParameterFunction { + R apply(T t, U u, V v, W w); + } + + FourParameterFunction, List, List, String, List> + fetchMolecularData = + (mappedProfileIds, mappedSampleIds, stableIds, attributeId) -> + molecularDataService + .getMolecularDataInMultipleMolecularProfiles( + mappedProfileIds, + mappedSampleIds, + stableIds.stream().map(Integer::parseInt).toList(), + Projection.SUMMARY.name()) + .stream() + .map( + geneMolecularData -> + transformDataToClinicalData( + geneMolecularData, attributeId, geneMolecularData.getValue())) + .collect(Collectors.toList()); + + FourParameterFunction, List, List, String, List> + fetchGenericAssayData = + (mappedProfileIds, mappedSampleIds, stableIds, attributeId) -> { + try { + return genericAssayService + .fetchGenericAssayData( + mappedProfileIds, mappedSampleIds, stableIds, Projection.SUMMARY.name()) + .stream() + .map( + genericAssayData -> + transformDataToClinicalData( + genericAssayData, attributeId, genericAssayData.getValue())) + .collect(Collectors.toList()); + } catch (MolecularProfileNotFoundException e) { + return new ArrayList<>(); + } + }; + + FourParameterFunction, List, List, String, List> + fetchMutationData = + (mappedProfileIds, mappedSampleIds, stableIds, attributeId) -> + mutationService + .getMutationsInMultipleMolecularProfiles( + mappedProfileIds, + mappedSampleIds, + stableIds.stream().map(Integer::parseInt).toList(), + Projection.DETAILED.name(), + null, + null, + null, + null) + .stream() + .map( + mutationData -> + transformDataToClinicalData( + mutationData, + attributeId, + mutationData.getMutationType().toUpperCase())) + .collect(Collectors.toList()); + + FourParameterFunction, List, List, String, List> + fetchMutatedData = + (mappedProfileIds, mappedSampleIds, stableIds, attributeId) -> + mutationService + .getMutationsInMultipleMolecularProfiles( + mappedProfileIds, + mappedSampleIds, + stableIds.stream().map(Integer::parseInt).toList(), + Projection.DETAILED.name(), + null, + null, + null, + null) + .stream() + .map( + mutationData -> + transformDataToClinicalData( + mutationData, attributeId, MutationFilterOption.MUTATED.name())) + .collect(Collectors.toList()); + + private List fetchDataBinFilters( + T dataBinCountFilter) { + if (dataBinCountFilter instanceof GenomicDataBinCountFilter) { + return (List) ((GenomicDataBinCountFilter) dataBinCountFilter).getGenomicDataBinFilters(); + } else if (dataBinCountFilter instanceof GenericAssayDataBinCountFilter) { + return (List) + ((GenericAssayDataBinCountFilter) dataBinCountFilter).getGenericAssayDataBinFilters(); + } + return new ArrayList<>(); + } + + private void removeSelfFromFilter( + S dataBinFilter, StudyViewFilter studyViewFilter) { + if (studyViewFilter != null) { + if (dataBinFilter instanceof GenomicDataBinFilter genomicDataBinFilter + && studyViewFilter.getGenomicDataFilters() != null) { + studyViewFilter + .getGenomicDataFilters() + .removeIf( + f -> + f.getHugoGeneSymbol().equals(genomicDataBinFilter.getHugoGeneSymbol()) + && f.getProfileType().equals(genomicDataBinFilter.getProfileType())); + } else if (dataBinFilter instanceof GenericAssayDataBinFilter genericAssayDataBinFilter + && studyViewFilter.getGenericAssayDataFilters() != null) { + studyViewFilter + .getGenericAssayDataFilters() + .removeIf( + f -> + f.getStableId().equals(genericAssayDataBinFilter.getStableId()) + && f.getProfileType().equals(genericAssayDataBinFilter.getProfileType())); + } + } + } + + private T transform( + S dataBinFilter, DataBin dataBin) { + if (dataBinFilter instanceof GenomicDataBinFilter genomicDataBinFilter) { + return (T) dataBintoGenomicDataBin(genomicDataBinFilter, dataBin); + } else if (dataBinFilter instanceof GenericAssayDataBinFilter genericAssayDataBinFilter) { + return (T) dataBintoGenericAssayDataBin(genericAssayDataBinFilter, dataBin); + } + return null; + } + + private GenomicDataBin dataBintoGenomicDataBin( + GenomicDataBinFilter genomicDataBinFilter, DataBin dataBin) { + GenomicDataBin genomicDataBin = new GenomicDataBin(); + genomicDataBin.setCount(dataBin.getCount()); + genomicDataBin.setHugoGeneSymbol(genomicDataBinFilter.getHugoGeneSymbol()); + genomicDataBin.setProfileType(genomicDataBinFilter.getProfileType()); + if (dataBin.getSpecialValue() != null) { + genomicDataBin.setSpecialValue(dataBin.getSpecialValue()); + } + if (dataBin.getStart() != null) { + genomicDataBin.setStart(dataBin.getStart()); + } + if (dataBin.getEnd() != null) { + genomicDataBin.setEnd(dataBin.getEnd()); + } + return genomicDataBin; + } + + private GenericAssayDataBin dataBintoGenericAssayDataBin( + GenericAssayDataBinFilter genericAssayDataBinFilter, DataBin dataBin) { + GenericAssayDataBin genericAssayDataBin = new GenericAssayDataBin(); + genericAssayDataBin.setCount(dataBin.getCount()); + genericAssayDataBin.setStableId(genericAssayDataBinFilter.getStableId()); + genericAssayDataBin.setProfileType(genericAssayDataBinFilter.getProfileType()); + if (dataBin.getSpecialValue() != null) { + genericAssayDataBin.setSpecialValue(dataBin.getSpecialValue()); + } + if (dataBin.getStart() != null) { + genericAssayDataBin.setStart(dataBin.getStart()); + } + if (dataBin.getEnd() != null) { + genericAssayDataBin.setEnd(dataBin.getEnd()); + } + return genericAssayDataBin; + } + + public List intervalFilterExpressionData( + List sampleIdentifiers, + List molecularProfiles, + List dataFilters, + boolean negateFilters) { + + return filterExpressionData( + sampleIdentifiers, + molecularProfiles, + dataFilters, + negateFilters, + clinicalDataIntervalFilterApplier); + } + + public List equalityFilterExpressionData( + List sampleIdentifiers, + List molecularProfiles, + List dataFilters, + boolean negateFilters) { + + return filterExpressionData( + sampleIdentifiers, + molecularProfiles, + dataFilters, + negateFilters, + clinicalDataEqualityFilterApplier); + } + + public List filterExpressionData( + List sampleIdentifiers, + List molecularProfiles, + List dataFilters, + boolean negateFilters, + ClinicalDataFilterApplier clinicalDataFilterApplier) { + if (!CollectionUtils.isEmpty(dataFilters) && !CollectionUtils.isEmpty(sampleIdentifiers)) { + List clinicalDatas = + fetchDataAndTransformToClinicalDataList( + sampleIdentifiers, molecularProfiles, dataFilters); + List attributes = transformToClinicalDataFilter(dataFilters); + + MultiKeyMap clinicalDataMap; + if (clinicalDataFilterApplier instanceof ClinicalDataEqualityFilterApplier) { + clinicalDataMap = ClinicalDataEqualityFilterApplier.buildClinicalDataMap(clinicalDatas); + } else { + clinicalDataMap = ClinicalDataIntervalFilterApplier.buildClinicalDataMap(clinicalDatas); + } + + return filterSampleIdentifiers( + sampleIdentifiers, + attributes, + clinicalDataMap, + clinicalDataFilterApplier, + negateFilters) + .stream() + .distinct() + .toList(); + } + + return sampleIdentifiers; + } + + private List fetchDataAndTransformToClinicalDataList( + List sampleIdentifiers, + List molecularProfiles, + List dataFilters) { + Map> molecularProfileMap = + molecularProfileUtil.categorizeMolecularProfilesByStableIdSuffixes(molecularProfiles); + + List studyIds = new ArrayList<>(); + List sampleIds = new ArrayList<>(); + studyViewFilterUtil.extractStudyAndSampleIds(sampleIdentifiers, studyIds, sampleIds); + + if (dataFilters.getFirst() instanceof GenomicDataFilter) { + List genomicDataIntervalFilters = (List) dataFilters; + Set hugoGeneSymbols = + genomicDataIntervalFilters.stream() + .map(GenomicDataFilter::getHugoGeneSymbol) + .collect(Collectors.toSet()); + Map geneNameIdMap = + geneService + .fetchGenes( + new ArrayList<>(hugoGeneSymbols), + GeneIdType.HUGO_GENE_SYMBOL.name(), + Projection.SUMMARY.name()) + .stream() + .collect(Collectors.toMap(Gene::getHugoGeneSymbol, Gene::getEntrezGeneId)); + + return genomicDataIntervalFilters.stream() + .flatMap( + genomicDataFilter -> { + List subMolecularProfiles = + molecularProfileMap.getOrDefault( + genomicDataFilter.getProfileType(), new ArrayList<>()); + Map studyIdToMolecularProfileIdMap = + subMolecularProfiles.stream() + .collect( + Collectors.toMap( + MolecularProfile::getCancerStudyIdentifier, + MolecularProfile::getStableId)); + + return invokeDataFunc( + sampleIds, + studyIds, + Collections.singletonList( + geneNameIdMap.get(genomicDataFilter.getHugoGeneSymbol()).toString()), + studyIdToMolecularProfileIdMap, + studyViewFilterUtil.getDataFilterUniqueKey(genomicDataFilter), + fetchMolecularData); + }) + .collect(Collectors.toList()); + + } else { + return ((List) dataFilters) + .stream() + .flatMap( + genericAssayDataFilter -> { + Map studyIdToMolecularProfileIdMap = + molecularProfileMap + .getOrDefault( + genericAssayDataFilter.getProfileType(), + new ArrayList()) + .stream() + .collect( + Collectors.toMap( + MolecularProfile::getCancerStudyIdentifier, + MolecularProfile::getStableId)); + + // get original data stream from invokeDataFunc + Stream dataStream = + invokeDataFunc( + sampleIds, + studyIds, + Collections.singletonList(genericAssayDataFilter.getStableId()), + studyIdToMolecularProfileIdMap, + studyViewFilterUtil.getDataFilterUniqueKey(genericAssayDataFilter), + fetchGenericAssayData); + // For patient level generic assay profile, only keep the one sample per patient + List profiles = + molecularProfileMap.getOrDefault( + genericAssayDataFilter.getProfileType(), new ArrayList<>()); + if (profiles.size() > 0 && profiles.get(0).getPatientLevel()) { + dataStream = + dataStream + .collect(Collectors.groupingBy(ClinicalData::getPatientId)) + .values() + .stream() + .flatMap(d -> d.stream().limit(1)); + } + // don't change anything for non patient level data + return dataStream; + }) + .collect(Collectors.toList()); + } + } + + private List fetchMutationDataAndTransformToClinicalDataList( + List sampleIdentifiers, + List molecularProfiles, + List mutationDataFilters) { + Map> molecularProfileMap = + molecularProfileUtil.categorizeMolecularProfilesByStableIdSuffixes(molecularProfiles); + + List studyIds = new ArrayList<>(); + List sampleIds = new ArrayList<>(); + studyViewFilterUtil.extractStudyAndSampleIds(sampleIdentifiers, studyIds, sampleIds); + + Set hugoGeneSymbols = + mutationDataFilters.stream() + .map(MutationDataFilter::getHugoGeneSymbol) + .collect(Collectors.toSet()); + Map geneNameIdMap = + geneService + .fetchGenes( + new ArrayList<>(hugoGeneSymbols), + GeneIdType.HUGO_GENE_SYMBOL.name(), + Projection.SUMMARY.name()) + .stream() + .collect(Collectors.toMap(Gene::getHugoGeneSymbol, Gene::getEntrezGeneId)); + + return mutationDataFilters.stream() + .flatMap( + mutationDataFilter -> { + List subMolecularProfiles = + molecularProfileMap.getOrDefault( + mutationDataFilter.getProfileType(), new ArrayList<>()); + Map studyIdToMolecularProfileIdMap = + subMolecularProfiles.stream() + .collect( + Collectors.toMap( + MolecularProfile::getCancerStudyIdentifier, + MolecularProfile::getStableId)); + + if (mutationDataFilter.getCategorization() == MutationOption.MUTATED) { + return fetchMutatedAndWildTypeData( + sampleIdentifiers, + geneNameIdMap, + mutationDataFilter, + studyIdToMolecularProfileIdMap); + } else { + // fetch mutation type data + return invokeDataFunc( + sampleIds, + studyIds, + Collections.singletonList( + geneNameIdMap.get(mutationDataFilter.getHugoGeneSymbol()).toString()), + studyIdToMolecularProfileIdMap, + studyViewFilterUtil.getMutationDataFilterUniqueKey(mutationDataFilter), + fetchMutationData); + } + }) + .collect(Collectors.toList()); + } + + private List fetchNamespaceDataAndTransformToClinicalDataList( + List sampleIdentifiers, List namespaceDataFilters) { + + List studyIds = new ArrayList<>(); + List sampleIds = new ArrayList<>(); + studyViewFilterUtil.extractStudyAndSampleIds(sampleIdentifiers, studyIds, sampleIds); + + List namespaceDataList = + namespaceDataService.fetchNamespaceData(studyIds, sampleIds, namespaceDataFilters); + + return namespaceDataList.stream() + .map( + namespaceData -> + transformDataToClinicalData( + namespaceData, + namespaceData.getOuterKey() + namespaceData.getInnerKey(), + namespaceData + .getAttrValue() + .toUpperCase() // Converting the value to full caps here because will be + // compared later to caps filterValue + )) + .collect(Collectors.toList()); + } + + private List transformToClinicalDataFilter( + List dataFilters) { + List attributes; + attributes = + dataFilters.stream() + .map( + dataFilter -> { + ClinicalDataFilter clinicalDataFilter = new ClinicalDataFilter(); + clinicalDataFilter.setAttributeId( + studyViewFilterUtil.getDataFilterUniqueKey(dataFilter)); + clinicalDataFilter.setValues(dataFilter.getValues()); + return clinicalDataFilter; + }) + .collect(Collectors.toList()); + return attributes; + } + + private List fetchProfiledMutationDataByGene( + List studyIds, List sampleIds, Integer entrezGeneId) { + List molecularProfileCaseIdentifiers = + molecularProfileService.getMutationProfileCaseIdentifiers(studyIds, sampleIds); + + List genePanelDataList = + genePanelService.fetchGenePanelDataInMultipleMolecularProfiles( + molecularProfileCaseIdentifiers); + + Function sampleIdentifierBuilder = + sample -> + studyViewFilterUtil.buildSampleIdentifier(sample.getStudyId(), sample.getSampleId()); + + Map> casesWithDataInGenePanel = new HashMap<>(); + // loop through all membership records -- ignore any where g.getGenePanelId == null + for (GenePanelData genePanelDataRecord : genePanelDataList) { + String associatedGenePanel = genePanelDataRecord.getGenePanelId(); + if (associatedGenePanel != null) { + casesWithDataInGenePanel.putIfAbsent(associatedGenePanel, new HashSet<>()); + Set casesForThisGenePanel = + casesWithDataInGenePanel.get(associatedGenePanel); + casesForThisGenePanel.add(sampleIdentifierBuilder.apply(genePanelDataRecord)); + } + } + + List genePanels = new ArrayList<>(); + if (!casesWithDataInGenePanel.isEmpty()) { + genePanels = + genePanelService.fetchGenePanels( + new ArrayList<>(casesWithDataInGenePanel.keySet()), Projection.DETAILED.name()); + } + + List genePanelData = + genePanelDataList.stream().filter(GenePanelData::getProfiled).toList(); + + Set profiledCases = + genePanelData.stream() + // there can be duplicate patient or sample id, append study id + .map(sampleIdentifierBuilder) + .collect(Collectors.toSet()); + + // here we look for cases where none of the profiles have gene panel ids + // a case with at least one profile with gene panel id is considered as a case with gene panel + // data + // so a case is considered without panel data only if none of the profiles has a gene panel id + + // first identify cases with gene panel data + Set casesWithPanelData = + genePanelData.stream() + .filter(g -> g.getGenePanelId() != null) + // there can be duplicate patient or sample id, append study id + .map(sampleIdentifierBuilder) + .collect(Collectors.toSet()); + + // find all unique cases + Set casesWithoutPanelData = + genePanelData.stream() + // there can be duplicate patient or sample id, append study id + .map(sampleIdentifierBuilder) + .collect(Collectors.toSet()); + + // removing cases with panel data from all unique cases gives us the cases without panel data + casesWithoutPanelData.removeAll(casesWithPanelData); + + List genePanelIds = + genePanels.stream() + .flatMap( + genePanel -> { + List genePanelToGenes = genePanel.getGenes(); + return genePanelToGenes.stream() + .filter( + genePanelToGene -> genePanelToGene.getEntrezGeneId().equals(entrezGeneId)) + .map(GenePanelToGene::getGenePanelId); + }) + .toList(); + + List newSampleIdentifiers = new ArrayList<>(); + // different calculations depending on if gene is linked to gene panels + if (CollectionUtils.isNotEmpty(genePanelIds)) { + // for every gene panel associated containing the gene, use the sum of unique cases + // as well as cases without panel data + for (String genePanelId : genePanelIds) { + newSampleIdentifiers.addAll(casesWithDataInGenePanel.get(genePanelId)); + } + newSampleIdentifiers.addAll(casesWithoutPanelData); + } else { + // we use profiledCasesCount instead of casesWithoutPanelData to + // prevent a divide by zero error which can happen for targeted studies + // in which certain genes have events that are not captured by the panel. + newSampleIdentifiers.addAll(profiledCases); + } + + return newSampleIdentifiers; + } + + private Stream fetchMutatedAndWildTypeData( + List sampleIdentifiers, + Map geneNameIdMap, + MutationDataFilter mutationDataFilter, + Map studyIdToMolecularProfileIdMap) { + List studyIds = new ArrayList<>(); + List sampleIds = new ArrayList<>(); + studyViewFilterUtil.extractStudyAndSampleIds(sampleIdentifiers, studyIds, sampleIds); + + // mutated + List mutatedClinicalDatas = + invokeDataFunc( + sampleIds, + studyIds, + Collections.singletonList( + geneNameIdMap.get(mutationDataFilter.getHugoGeneSymbol()).toString()), + studyIdToMolecularProfileIdMap, + studyViewFilterUtil.getMutationDataFilterUniqueKey(mutationDataFilter), + fetchMutatedData) + .toList(); + + List mutatedSampleIdentifiers = + mutatedClinicalDatas.stream() + .map( + datum -> + studyViewFilterUtil.buildSampleIdentifier( + datum.getStudyId(), datum.getSampleId())) + .toList(); + + List clinicalDatas = new ArrayList<>(mutatedClinicalDatas); + + // not profiled + List profiledSampleIdentifiers = + fetchProfiledMutationDataByGene( + studyIds, sampleIds, geneNameIdMap.get(mutationDataFilter.getHugoGeneSymbol())); + + List notProfiledSampleIdentifiers = + sampleIdentifiers.stream() + .filter(s -> profiledSampleIdentifiers.stream().noneMatch(p -> p.equals(s))) + .toList(); + + List notProfiledClinicalDatas = + studyViewFilterUtil.transformSampleIdentifiersToClinicalData( + notProfiledSampleIdentifiers, + studyViewFilterUtil.getMutationDataFilterUniqueKey(mutationDataFilter), + MutationFilterOption.NOT_PROFILED.name()); + + clinicalDatas.addAll(notProfiledClinicalDatas); + + // not mutated + List notMutatedSampleIdentifiers = + profiledSampleIdentifiers.stream() + .filter(p -> mutatedSampleIdentifiers.stream().noneMatch(m -> m.equals(p))) + .toList(); + + List notMutatedClinicalDatas = + studyViewFilterUtil.transformSampleIdentifiersToClinicalData( + notMutatedSampleIdentifiers, + studyViewFilterUtil.getMutationDataFilterUniqueKey(mutationDataFilter), + MutationFilterOption.NOT_MUTATED.name()); + + clinicalDatas.addAll(notMutatedClinicalDatas); + + return clinicalDatas.stream(); + } + + private ClinicalData transformDataToClinicalData( + S data, String attributeId, String attributeValue) { + ClinicalData clinicalData = new ClinicalData(); + + if (data instanceof MolecularData molecularData) { + clinicalData.setPatientId(molecularData.getPatientId()); + clinicalData.setSampleId(molecularData.getSampleId()); + clinicalData.setStudyId(molecularData.getStudyId()); + } else if (data instanceof Mutation mutationData) { + clinicalData.setPatientId(mutationData.getPatientId()); + clinicalData.setSampleId(mutationData.getSampleId()); + clinicalData.setStudyId(mutationData.getStudyId()); + } else if (data instanceof NamespaceData namespaceData) { + clinicalData.setSampleId(namespaceData.getSampleId()); + clinicalData.setStudyId(namespaceData.getStudyId()); + } else { + return clinicalData; + } + + clinicalData.setAttrValue(attributeValue); + clinicalData.setAttrId(attributeId); + + return clinicalData; + } + + private List filterSampleIdentifiers( + List sampleIdentifiers, + List attributes, + MultiKeyMap clinicalDataMap, + ClinicalDataFilterApplier clinicalDataFilterApplier, + boolean negateFilters) { + return sampleIdentifiers.stream() + .filter( + sampleIdentifier -> { + int count = + clinicalDataFilterApplier.apply( + attributes, + clinicalDataMap, + sampleIdentifier.getSampleId(), + sampleIdentifier.getStudyId(), + negateFilters); + return count == attributes.size(); + }) + .collect(Collectors.toList()); + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/util/StudyViewFilterUtil.java b/src/main/java/org/cbioportal/legacy/web/util/StudyViewFilterUtil.java new file mode 100644 index 00000000000..81d0dcc1185 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/util/StudyViewFilterUtil.java @@ -0,0 +1,478 @@ +package org.cbioportal.legacy.web.util; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.collections4.map.MultiKeyMap; +import org.cbioportal.legacy.model.Binnable; +import org.cbioportal.legacy.model.ClinicalData; +import org.cbioportal.legacy.model.ClinicalDataCount; +import org.cbioportal.legacy.model.ClinicalDataCountItem; +import org.cbioportal.legacy.model.Gene; +import org.cbioportal.legacy.model.Patient; +import org.cbioportal.legacy.model.SampleList; +import org.cbioportal.legacy.model.StructuralVariantFilterQuery; +import org.cbioportal.legacy.model.StructuralVariantSpecialValue; +import org.cbioportal.legacy.service.GeneService; +import org.cbioportal.legacy.service.util.CustomDataSession; +import org.cbioportal.legacy.service.util.CustomDataValue; +import org.cbioportal.legacy.web.parameter.ClinicalDataFilter; +import org.cbioportal.legacy.web.parameter.DataBinFilter; +import org.cbioportal.legacy.web.parameter.DataFilter; +import org.cbioportal.legacy.web.parameter.DataFilterValue; +import org.cbioportal.legacy.web.parameter.GeneIdType; +import org.cbioportal.legacy.web.parameter.GenericAssayDataBinFilter; +import org.cbioportal.legacy.web.parameter.GenericAssayDataFilter; +import org.cbioportal.legacy.web.parameter.GenomicDataBinFilter; +import org.cbioportal.legacy.web.parameter.GenomicDataFilter; +import org.cbioportal.legacy.web.parameter.MutationDataFilter; +import org.cbioportal.legacy.web.parameter.MutationOption; +import org.cbioportal.legacy.web.parameter.Projection; +import org.cbioportal.legacy.web.parameter.SampleIdentifier; +import org.cbioportal.legacy.web.parameter.StudyViewFilter; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +@Component +public class StudyViewFilterUtil { + + private final GeneService geneService; + + @Autowired + public StudyViewFilterUtil(GeneService geneService) { + this.geneService = geneService; + } + + public StudyViewFilterUtil() { + geneService = null; + } + + public void extractStudyAndSampleIds( + List sampleIdentifiers, List studyIds, List sampleIds) { + for (SampleIdentifier sampleIdentifier : sampleIdentifiers) { + studyIds.add(sampleIdentifier.getStudyId()); + sampleIds.add(sampleIdentifier.getSampleId()); + } + } + + public void removeSelfFromFilter(String attributeId, StudyViewFilter studyViewFilter) { + if (studyViewFilter != null && studyViewFilter.getClinicalDataFilters() != null) { + studyViewFilter + .getClinicalDataFilters() + .removeIf(f -> f.getAttributeId().equals(attributeId)); + } + } + + public void removeSelfFromGenomicDataFilter( + String hugoGeneSymbol, String profileType, StudyViewFilter studyViewFilter) { + if (studyViewFilter != null && studyViewFilter.getGenomicDataFilters() != null) { + studyViewFilter + .getGenomicDataFilters() + .removeIf( + f -> + f.getHugoGeneSymbol().equals(hugoGeneSymbol) + && f.getProfileType().equals(profileType)); + } + } + + public void removeSelfFromMutationDataFilter( + String hugoGeneSymbol, + String profileType, + MutationOption categorization, + StudyViewFilter studyViewFilter) { + if (studyViewFilter != null && studyViewFilter.getMutationDataFilters() != null) { + studyViewFilter + .getMutationDataFilters() + .removeIf( + f -> + f.getHugoGeneSymbol().equals(hugoGeneSymbol) + && f.getProfileType().equals(profileType) + && f.getCategorization().equals(categorization)); + } + } + + public void removeSelfFromGenericAssayFilter(String stableId, StudyViewFilter studyViewFilter) { + if (studyViewFilter != null && studyViewFilter.getGenericAssayDataFilters() != null) { + studyViewFilter.getGenericAssayDataFilters().removeIf(f -> f.getStableId().equals(stableId)); + } + } + + public void removeSelfCustomDataFromFilter(String attributeId, StudyViewFilter studyViewFilter) { + if (studyViewFilter != null && studyViewFilter.getCustomDataFilters() != null) { + studyViewFilter.getCustomDataFilters().removeIf(f -> f.getAttributeId().equals(attributeId)); + } + } + + public String getCaseUniqueKey(String studyId, String caseId) { + return studyId + caseId; + } + + public String getDataFilterUniqueKey(S dataFilter) { + if (dataFilter instanceof GenomicDataFilter genomicDataFilter) { + return genomicDataFilter.getHugoGeneSymbol() + genomicDataFilter.getProfileType(); + } else if (dataFilter instanceof GenericAssayDataFilter genericAssayDataFilter) { + return genericAssayDataFilter.getStableId() + genericAssayDataFilter.getProfileType(); + } + return null; + } + + public String getMutationDataFilterUniqueKey(MutationDataFilter mutationDataFilter) { + return mutationDataFilter.getHugoGeneSymbol() + mutationDataFilter.getProfileType(); + } + + public String getDataBinFilterUniqueKey(S dataBinFilter) { + if (dataBinFilter instanceof GenomicDataBinFilter genomicDataBinFilter) { + return genomicDataBinFilter.getHugoGeneSymbol() + genomicDataBinFilter.getProfileType(); + } else if (dataBinFilter instanceof GenericAssayDataBinFilter genericAssayDataBinFilter) { + return genericAssayDataBinFilter.getStableId() + genericAssayDataBinFilter.getProfileType(); + } + return null; + } + + public Map> categorizeSampleLists(List sampleLists) { + return sampleLists.stream() + .collect( + Collectors.groupingBy( + sampleList -> { + return sampleList + .getStableId() + .replace(sampleList.getCancerStudyIdentifier() + "_", ""); + })); + } + + public Integer getFilteredCountByDataEquality( + List attributes, + MultiKeyMap clinicalDataMap, + String entityId, + String studyId, + boolean negateFilters) { + Integer count = 0; + for (ClinicalDataFilter s : attributes) { + List filteredValues = + s.getValues().stream().map(DataFilterValue::getValue).collect(Collectors.toList()); + filteredValues.replaceAll(String::toUpperCase); + if (clinicalDataMap.containsKey(studyId, entityId, s.getAttributeId())) { + S value = clinicalDataMap.get(studyId, entityId, s.getAttributeId()); + if (value instanceof String) { + if (negateFilters ^ filteredValues.contains(value)) { + count++; + } + } else if (value instanceof List + && negateFilters ^ filteredValues.stream().anyMatch(((List) value)::contains)) { + count++; + } + } else if (negateFilters ^ filteredValues.contains("NA")) { + count++; + } + } + return count; + } + + public List getClinicalDataCountsFromCustomData( + Collection customDataSessions, + Map filteredSamplesMap, + List patients) { + int totalSamplesCount = filteredSamplesMap.keySet().size(); + int totalPatientsCount = patients.size(); + + return customDataSessions.stream() + .map( + customDataSession -> { + Map> groupedDatabyValue = + customDataSession.getData().getData().stream() + .filter( + datum -> + filteredSamplesMap.containsKey( + getCaseUniqueKey(datum.getStudyId(), datum.getSampleId()))) + .collect(Collectors.groupingBy(CustomDataValue::getValue)); + + ClinicalDataCountItem clinicalDataCountItem = new ClinicalDataCountItem(); + clinicalDataCountItem.setAttributeId(customDataSession.getId()); + + List clinicalDataCounts = + groupedDatabyValue.entrySet().stream() + .map( + entry -> { + long count = + entry.getValue().stream() + .map( + datum -> { + return getCaseUniqueKey( + datum.getStudyId(), + customDataSession.getData().getPatientAttribute() + ? datum.getPatientId() + : datum.getSampleId()); + }) + .distinct() + .count(); + ClinicalDataCount dataCount = new ClinicalDataCount(); + dataCount.setAttributeId(customDataSession.getId()); + dataCount.setValue(entry.getKey()); + dataCount.setCount(Math.toIntExact(count)); + return dataCount; + }) + .filter( + c -> + !c.getValue().equalsIgnoreCase("NA") + && !c.getValue().equalsIgnoreCase("NAN") + && !c.getValue().equalsIgnoreCase("N/A")) + .collect(Collectors.toList()); + + int totalCount = + clinicalDataCounts.stream().mapToInt(ClinicalDataCount::getCount).sum(); + int naCount = 0; + if (customDataSession.getData().getPatientAttribute()) { + naCount = totalPatientsCount - totalCount; + } else { + naCount = totalSamplesCount - totalCount; + } + if (naCount > 0) { + ClinicalDataCount clinicalDataCount = new ClinicalDataCount(); + clinicalDataCount.setAttributeId(customDataSession.getId()); + clinicalDataCount.setValue("NA"); + clinicalDataCount.setCount(naCount); + clinicalDataCounts.add(clinicalDataCount); + } + + clinicalDataCountItem.setCounts(clinicalDataCounts); + return clinicalDataCountItem; + }) + .collect(Collectors.toList()); + } + + public boolean isSingleStudyUnfiltered(StudyViewFilter filter) { + return isSingleStudy(filter) && isUnfilteredQuery(filter); + } + + public boolean isSingleStudy(StudyViewFilter filter) { + return filter.getStudyIds() != null && filter.getStudyIds().size() == 1; + } + + public boolean isUnfilteredQuery(StudyViewFilter filter) { + return filter.getStudyIds() != null + && (filter.getClinicalDataFilters() == null || filter.getClinicalDataFilters().isEmpty()) + && (filter.getGeneFilters() == null || filter.getGeneFilters().isEmpty()) + && (filter.getSampleTreatmentFilters() == null + || filter.getSampleTreatmentFilters().getFilters().isEmpty()) + && (filter.getPatientTreatmentFilters() == null + || filter.getPatientTreatmentFilters().getFilters().isEmpty()) + && (filter.getGenomicProfiles() == null || filter.getGenomicProfiles().isEmpty()) + && (filter.getGenomicDataFilters() == null || filter.getGenomicDataFilters().isEmpty()) + && (filter.getGenericAssayDataFilters() == null + || filter.getGenericAssayDataFilters().isEmpty()) + && (filter.getCaseLists() == null || filter.getCaseLists().isEmpty()) + && (filter.getCustomDataFilters() == null || filter.getCustomDataFilters().isEmpty()) + && (filter.getMutationDataFilters() == null || filter.getMutationDataFilters().isEmpty()) + && (filter.getNamespaceDataFilters() == null || filter.getNamespaceDataFilters().isEmpty()); + } + + public boolean shouldSkipFilterForClinicalDataBins(StudyViewFilter filter) { + // if everything other than study ids and sample identifiers is null, + // we can skip the filter for data bin calculation + return (filter != null + && filter.getClinicalDataFilters() == null + && filter.getClinicalEventFilters() == null + && filter.getMutationDataFilters() == null + && filter.getStructuralVariantFilters() == null + && filter.getGeneFilters() == null + && filter.getSampleTreatmentFilters() == null + && filter.getPatientTreatmentFilters() == null + && filter.getPatientTreatmentGroupFilters() == null + && filter.getSampleTreatmentGroupFilters() == null + && filter.getPatientTreatmentTargetFilters() == null + && filter.getSampleTreatmentTargetFilters() == null + && filter.getGenomicProfiles() == null + && filter.getGenomicDataFilters() == null + && filter.getNamespaceDataFilters() == null + && filter.getGenericAssayDataFilters() == null + && filter.getCaseLists() == null + && filter.getCustomDataFilters() == null); + } + + public List filterClinicalData( + List unfilteredClinicalDataForSamples, + List unfilteredClinicalDataForPatients, + List unfilteredClinicalDataForConflictingPatientAttributes, + List studyIds, + List sampleIds, + List studyIdsOfPatients, + List patientIds, + List sampleAttributeIds, + List patientAttributeIds, + List conflictingPatientAttributes) { + List combinedResult = new ArrayList<>(); + + Map patientIdToStudyId = null; + + if (CollectionUtils.isNotEmpty(sampleAttributeIds)) { + // create lookups for faster filtering + Map sampleIdToStudyId = mapCaseToStudy(sampleIds, studyIds); + Map sampleAttributeIdLookup = listToMap(sampleAttributeIds); + + combinedResult.addAll( + filterClinicalDataByStudyAndSampleAndAttribute( + unfilteredClinicalDataForSamples, sampleIdToStudyId, sampleAttributeIdLookup)); + } + + if (CollectionUtils.isNotEmpty(patientAttributeIds)) { + // create lookups for faster filtering + Map patientAttributeIdLookup = listToMap(patientAttributeIds); + patientIdToStudyId = mapCaseToStudy(patientIds, studyIdsOfPatients); + + combinedResult.addAll( + filterClinicalDataByStudyAndPatientAndAttribute( + unfilteredClinicalDataForPatients, patientIdToStudyId, patientAttributeIdLookup)); + } + + if (CollectionUtils.isNotEmpty(conflictingPatientAttributes)) { + // create lookups for faster filtering + Map conflictingPatientAttributeIdLookup = + listToMap(conflictingPatientAttributes); + if (patientIdToStudyId == null) { + patientIdToStudyId = mapCaseToStudy(patientIds, studyIdsOfPatients); + } + + combinedResult.addAll( + filterClinicalDataByStudyAndPatientAndAttribute( + unfilteredClinicalDataForConflictingPatientAttributes, + patientIdToStudyId, + conflictingPatientAttributeIdLookup)); + } + + return combinedResult; + } + + private Map getStringIntegerMap(List hugoGeneSymbols) { + Map symbolToEntrezGeneId = + geneService + .fetchGenes( + new ArrayList<>(hugoGeneSymbols), + GeneIdType.HUGO_GENE_SYMBOL.name(), + Projection.SUMMARY.name()) + .stream() + .collect(Collectors.toMap(Gene::getHugoGeneSymbol, Gene::getEntrezGeneId)); + return symbolToEntrezGeneId; + } + + public List resolveEntrezGeneIds( + List structVarQueries) { + + List hugoGeneSymbols = + structVarQueries.stream() + .flatMap(q -> Stream.of(q.getGene1Query(), q.getGene2Query())) + .filter(structVarIdentifier -> structVarIdentifier.getHugoSymbol() != null) + .map(structVarIdentifier -> structVarIdentifier.getHugoSymbol()) + .collect(Collectors.toList()); + + Map symbolToEntrezGeneId = getStringIntegerMap(hugoGeneSymbols); + + // Add Entrez gene ids to the queries. + structVarQueries.forEach( + structVarQuery -> { + structVarQuery + .getGene1Query() + .setEntrezId( + symbolToEntrezGeneId.getOrDefault( + structVarQuery.getGene1Query().getHugoSymbol(), null)); + structVarQuery + .getGene2Query() + .setEntrezId( + symbolToEntrezGeneId.getOrDefault( + structVarQuery.getGene2Query().getHugoSymbol(), null)); + }); + + // Remove any genes where the Entrez gene id is needed, but translation failed. + structVarQueries.removeIf( + q -> + (q.getGene1Query().getSpecialValue() != StructuralVariantSpecialValue.NO_GENE + && q.getGene1Query().getSpecialValue() != StructuralVariantSpecialValue.ANY_GENE + && q.getGene1Query().getEntrezId() == null) + || (q.getGene2Query().getSpecialValue() != StructuralVariantSpecialValue.NO_GENE + && q.getGene2Query().getSpecialValue() != StructuralVariantSpecialValue.ANY_GENE + && q.getGene2Query().getEntrezId() == null)); + + return structVarQueries; + } + + private List filterClinicalDataByStudyAndSampleAndAttribute( + List clinicalData, + Map sampleToStudyId, + Map attributeIdLookup) { + return clinicalData.stream() + .filter( + d -> + sampleToStudyId.getOrDefault(generateSampleToStudyKey(d), "").equals(d.getStudyId()) + && attributeIdLookup.getOrDefault(d.getAttrId(), false)) + .collect(Collectors.toList()); + } + + private List filterClinicalDataByStudyAndPatientAndAttribute( + List clinicalData, + Map patientToStudyId, + Map attributeIdLookup) { + return clinicalData.stream() + .filter( + d -> + patientToStudyId + .getOrDefault(generatePatientToStudyKey(d), "") + .equals(d.getStudyId()) + && attributeIdLookup.getOrDefault(d.getAttrId(), false)) + .collect(Collectors.toList()); + } + + private Map listToMap(List list) { + return list.stream().collect(Collectors.toMap(s -> s, s -> true, (s1, s2) -> s1)); + } + + private Map mapCaseToStudy(List caseIds, List studyIds) { + Map caseToStudy = new HashMap<>(); + + for (int i = 0; i < caseIds.size(); i++) { + String studyId = studyIds.get(i); + String caseId = caseIds.get(i); + String key = generateCaseToStudyKey(studyId, caseId); + caseToStudy.put(key, studyId); + } + + return caseToStudy; + } + + private String generateSampleToStudyKey(Binnable clinicalData) { + return generateCaseToStudyKey(clinicalData.getStudyId(), clinicalData.getSampleId()); + } + + private String generatePatientToStudyKey(Binnable clinicalData) { + return generateCaseToStudyKey(clinicalData.getStudyId(), clinicalData.getPatientId()); + } + + private String generateCaseToStudyKey(String studyId, String caseId) { + return studyId + ":" + caseId; + } + + public SampleIdentifier buildSampleIdentifier(String studyId, String sampleId) { + SampleIdentifier sampleIdentifier = new SampleIdentifier(); + sampleIdentifier.setStudyId(studyId); + sampleIdentifier.setSampleId(sampleId); + return sampleIdentifier; + } + + public List transformSampleIdentifiersToClinicalData( + List sampleIdentifiers, String attributeId, String attributeValue) { + return sampleIdentifiers.stream() + .map( + sampleIdentifier -> { + ClinicalData clinicalData = new ClinicalData(); + clinicalData.setAttrId(attributeId); + clinicalData.setAttrValue(attributeValue); + clinicalData.setSampleId(sampleIdentifier.getSampleId()); + clinicalData.setStudyId(sampleIdentifier.getStudyId()); + return clinicalData; + }) + .collect(Collectors.toList()); + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/util/UniqueKeyExtractor.java b/src/main/java/org/cbioportal/legacy/web/util/UniqueKeyExtractor.java new file mode 100644 index 00000000000..68c72e87245 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/util/UniqueKeyExtractor.java @@ -0,0 +1,38 @@ +package org.cbioportal.legacy.web.util; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import org.cbioportal.legacy.utils.Encoder; + +public class UniqueKeyExtractor { + + private UniqueKeyExtractor() {} + + public static Collection extractUniqueKeys(List uniqueKeys) { + Collection studyIds = new ArrayList<>(); + extractUniqueKeys(uniqueKeys, studyIds, null); + return studyIds; + } + + public static void extractUniqueKeys( + List uniqueKeys, Collection studyIdsToReturn) { + extractUniqueKeys(uniqueKeys, studyIdsToReturn, null); + } + + public static void extractUniqueKeys( + List uniqueKeys, + Collection studyIdsToReturn, + Collection patientOrSampleIdsToReturn) { + for (String uniqueKey : uniqueKeys) { + String uniqueId = Encoder.decodeBase64(uniqueKey); + String[] patientOrSampleAndStudyId = uniqueId.split(Encoder.DELIMITER); + if (patientOrSampleAndStudyId.length == 2) { + if (patientOrSampleIdsToReturn != null) { + patientOrSampleIdsToReturn.add(patientOrSampleAndStudyId[0]); + } + studyIdsToReturn.add(patientOrSampleAndStudyId[1]); + } + } + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/util/appliers/AbstractPatientTreatmentFilter.java b/src/main/java/org/cbioportal/legacy/web/util/appliers/AbstractPatientTreatmentFilter.java new file mode 100644 index 00000000000..08798c85f95 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/util/appliers/AbstractPatientTreatmentFilter.java @@ -0,0 +1,54 @@ +package org.cbioportal.legacy.web.util.appliers; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; +import org.cbioportal.legacy.model.ClinicalEventKeyCode; +import org.cbioportal.legacy.model.PatientTreatmentRow; +import org.cbioportal.legacy.service.TreatmentService; +import org.cbioportal.legacy.web.parameter.SampleIdentifier; +import org.cbioportal.legacy.web.parameter.StudyViewFilter; +import org.cbioportal.legacy.web.parameter.filter.AndedPatientTreatmentFilters; +import org.springframework.beans.factory.annotation.Autowired; + +public abstract class AbstractPatientTreatmentFilter implements StudyViewSubFilterApplier { + @Autowired TreatmentService treatmentService; + + @Autowired TreatmentRowExtractor treatmentRowExtractor; + + @Override + public List filter(List identifiers, StudyViewFilter filter) { + + if (identifiers == null || identifiers.isEmpty()) { + return new ArrayList<>(); + } + + AndedPatientTreatmentFilters filters = getFilters(filter); + + List sampleIds = + identifiers.stream().map(SampleIdentifier::getSampleId).collect(Collectors.toList()); + + List studyIds = + identifiers.stream().map(SampleIdentifier::getStudyId).collect(Collectors.toList()); + + Map> rows = + treatmentService.getAllPatientTreatmentRows(sampleIds, studyIds, getCode()).stream() + .collect( + Collectors.toMap( + PatientTreatmentRow::getTreatment, treatmentRowExtractor::extractSamples)); + + return identifiers.stream().filter(i -> filters.filter(i, rows)).collect(Collectors.toList()); + } + + protected abstract AndedPatientTreatmentFilters getFilters(StudyViewFilter filter); + + protected abstract ClinicalEventKeyCode getCode(); + + @Override + public boolean shouldApplyFilter(StudyViewFilter studyViewFilter) { + return getFilters(studyViewFilter) != null + && !getFilters(studyViewFilter).getFilters().isEmpty(); + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/util/appliers/AbstractSampleTreatmentFilter.java b/src/main/java/org/cbioportal/legacy/web/util/appliers/AbstractSampleTreatmentFilter.java new file mode 100644 index 00000000000..1b2e2305cee --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/util/appliers/AbstractSampleTreatmentFilter.java @@ -0,0 +1,52 @@ +package org.cbioportal.legacy.web.util.appliers; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; +import org.cbioportal.legacy.model.ClinicalEventKeyCode; +import org.cbioportal.legacy.model.SampleTreatmentRow; +import org.cbioportal.legacy.service.TreatmentService; +import org.cbioportal.legacy.web.parameter.SampleIdentifier; +import org.cbioportal.legacy.web.parameter.StudyViewFilter; +import org.cbioportal.legacy.web.parameter.filter.AndedSampleTreatmentFilters; +import org.springframework.beans.factory.annotation.Autowired; + +public abstract class AbstractSampleTreatmentFilter implements StudyViewSubFilterApplier { + @Autowired TreatmentService treatmentService; + + @Autowired TreatmentRowExtractor treatmentRowExtractor; + + @Override + public List filter(List identifiers, StudyViewFilter filter) { + + if (identifiers == null || identifiers.isEmpty()) { + return new ArrayList<>(); + } + + AndedSampleTreatmentFilters filters = getFilters(filter); + + List sampleIds = + identifiers.stream().map(SampleIdentifier::getSampleId).collect(Collectors.toList()); + List studyIds = + identifiers.stream().map(SampleIdentifier::getStudyId).collect(Collectors.toList()); + + Map> rows = + treatmentService.getAllSampleTreatmentRows(sampleIds, studyIds, getCode()).stream() + .collect( + Collectors.toMap(SampleTreatmentRow::key, treatmentRowExtractor::extractSamples)); + + return identifiers.stream().filter(id -> filters.filter(id, rows)).collect(Collectors.toList()); + } + + protected abstract AndedSampleTreatmentFilters getFilters(StudyViewFilter filter); + + protected abstract ClinicalEventKeyCode getCode(); + + @Override + public boolean shouldApplyFilter(StudyViewFilter studyViewFilter) { + return getFilters(studyViewFilter) != null + && !getFilters(studyViewFilter).getFilters().isEmpty(); + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/util/appliers/ClinicalEventFilterApplier.java b/src/main/java/org/cbioportal/legacy/web/util/appliers/ClinicalEventFilterApplier.java new file mode 100644 index 00000000000..af1beca86ce --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/util/appliers/ClinicalEventFilterApplier.java @@ -0,0 +1,92 @@ +package org.cbioportal.legacy.web.util.appliers; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Set; +import java.util.stream.Collectors; +import org.cbioportal.legacy.service.ClinicalEventService; +import org.cbioportal.legacy.web.parameter.DataFilter; +import org.cbioportal.legacy.web.parameter.DataFilterValue; +import org.cbioportal.legacy.web.parameter.SampleIdentifier; +import org.cbioportal.legacy.web.parameter.StudyViewFilter; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.lang.NonNull; +import org.springframework.stereotype.Component; + +@Component +public final class ClinicalEventFilterApplier implements StudyViewSubFilterApplier { + + @Autowired private ClinicalEventService clinicalEventService; + + @Override + public List filter( + @NonNull List toFilter, @NonNull StudyViewFilter filters) { + + if (toFilter == null || toFilter.isEmpty()) { + return new ArrayList<>(); + } + + List studyIds = + toFilter.stream().map(SampleIdentifier::getStudyId).collect(Collectors.toList()); + + List sampleIds = + toFilter.stream().map(SampleIdentifier::getSampleId).collect(Collectors.toList()); + + Map> samplesPerEventType = + clinicalEventService.getPatientsSamplesPerClinicalEventType(studyIds, sampleIds); + + List clinicalEventFilters = + filters.getClinicalEventFilters().stream() + .map(ClinicalEventFilter::new) + .collect(Collectors.toList()); + + return toFilter.stream() + .filter(i -> applyClinicalEventFilter(i, clinicalEventFilters, samplesPerEventType)) + .collect(Collectors.toList()); + } + + boolean applyClinicalEventFilter( + SampleIdentifier sampleIdentifier, + List eventFilters, + Map> samplesPerEventType) { + for (ClinicalEventFilter eventFilter : eventFilters) { + if (!eventFilter.filter(sampleIdentifier, samplesPerEventType)) { + return false; + } + } + return true; + } + + @Override + public boolean shouldApplyFilter(@NonNull StudyViewFilter studyViewFilter) { + return studyViewFilter.getClinicalEventFilters() != null + && !studyViewFilter.getClinicalEventFilters().isEmpty(); + } + + private static class ClinicalEventFilter { + private final List filters; + + ClinicalEventFilter(DataFilter filters) { + this.filters = filters.getValues(); + } + + public boolean filter(SampleIdentifier s, Map> samplesPerEventType) { + if (Objects.isNull(filters) || filters.isEmpty()) { + return true; + } + + for (DataFilterValue filter : filters) { + Collection samples = samplesPerEventType.get(filter.getValue()); + + if (!Objects.isNull(samples) && samples.contains(s.getSampleId())) { + return true; + } + } + + return false; + } + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/util/appliers/PatientTreatmentFilterApplier.java b/src/main/java/org/cbioportal/legacy/web/util/appliers/PatientTreatmentFilterApplier.java new file mode 100644 index 00000000000..257b0ecbca0 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/util/appliers/PatientTreatmentFilterApplier.java @@ -0,0 +1,20 @@ +package org.cbioportal.legacy.web.util.appliers; + +import org.cbioportal.legacy.model.ClinicalEventKeyCode; +import org.cbioportal.legacy.web.parameter.StudyViewFilter; +import org.cbioportal.legacy.web.parameter.filter.AndedPatientTreatmentFilters; +import org.springframework.stereotype.Component; + +@Component +public class PatientTreatmentFilterApplier extends AbstractPatientTreatmentFilter { + + @Override + protected AndedPatientTreatmentFilters getFilters(StudyViewFilter filter) { + return filter.getPatientTreatmentFilters(); + } + + @Override + protected ClinicalEventKeyCode getCode() { + return ClinicalEventKeyCode.Agent; + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/util/appliers/PatientTreatmentGroupFilterApplier.java b/src/main/java/org/cbioportal/legacy/web/util/appliers/PatientTreatmentGroupFilterApplier.java new file mode 100644 index 00000000000..25d0846acab --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/util/appliers/PatientTreatmentGroupFilterApplier.java @@ -0,0 +1,20 @@ +package org.cbioportal.legacy.web.util.appliers; + +import org.cbioportal.legacy.model.ClinicalEventKeyCode; +import org.cbioportal.legacy.web.parameter.StudyViewFilter; +import org.cbioportal.legacy.web.parameter.filter.AndedPatientTreatmentFilters; +import org.springframework.stereotype.Component; + +@Component +public class PatientTreatmentGroupFilterApplier extends AbstractPatientTreatmentFilter { + + @Override + protected AndedPatientTreatmentFilters getFilters(StudyViewFilter filter) { + return filter.getPatientTreatmentGroupFilters(); + } + + @Override + protected ClinicalEventKeyCode getCode() { + return ClinicalEventKeyCode.AgentClass; + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/util/appliers/PatientTreatmentTargetFilterApplier.java b/src/main/java/org/cbioportal/legacy/web/util/appliers/PatientTreatmentTargetFilterApplier.java new file mode 100644 index 00000000000..231e1d93644 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/util/appliers/PatientTreatmentTargetFilterApplier.java @@ -0,0 +1,20 @@ +package org.cbioportal.legacy.web.util.appliers; + +import org.cbioportal.legacy.model.ClinicalEventKeyCode; +import org.cbioportal.legacy.web.parameter.StudyViewFilter; +import org.cbioportal.legacy.web.parameter.filter.AndedPatientTreatmentFilters; +import org.springframework.stereotype.Component; + +@Component +public class PatientTreatmentTargetFilterApplier extends AbstractPatientTreatmentFilter { + + @Override + protected AndedPatientTreatmentFilters getFilters(StudyViewFilter filter) { + return filter.getPatientTreatmentTargetFilters(); + } + + @Override + protected ClinicalEventKeyCode getCode() { + return ClinicalEventKeyCode.AgentTarget; + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/util/appliers/SampleTreatmentFilterApplier.java b/src/main/java/org/cbioportal/legacy/web/util/appliers/SampleTreatmentFilterApplier.java new file mode 100644 index 00000000000..465c0b7de94 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/util/appliers/SampleTreatmentFilterApplier.java @@ -0,0 +1,20 @@ +package org.cbioportal.legacy.web.util.appliers; + +import org.cbioportal.legacy.model.ClinicalEventKeyCode; +import org.cbioportal.legacy.web.parameter.StudyViewFilter; +import org.cbioportal.legacy.web.parameter.filter.AndedSampleTreatmentFilters; +import org.springframework.stereotype.Component; + +@Component +public class SampleTreatmentFilterApplier extends AbstractSampleTreatmentFilter { + + @Override + protected AndedSampleTreatmentFilters getFilters(StudyViewFilter filter) { + return filter.getSampleTreatmentFilters(); + } + + @Override + protected ClinicalEventKeyCode getCode() { + return ClinicalEventKeyCode.Agent; + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/util/appliers/SampleTreatmentGroupFilterApplier.java b/src/main/java/org/cbioportal/legacy/web/util/appliers/SampleTreatmentGroupFilterApplier.java new file mode 100644 index 00000000000..55a6eec9017 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/util/appliers/SampleTreatmentGroupFilterApplier.java @@ -0,0 +1,19 @@ +package org.cbioportal.legacy.web.util.appliers; + +import org.cbioportal.legacy.model.ClinicalEventKeyCode; +import org.cbioportal.legacy.web.parameter.StudyViewFilter; +import org.cbioportal.legacy.web.parameter.filter.AndedSampleTreatmentFilters; +import org.springframework.stereotype.Component; + +@Component +public class SampleTreatmentGroupFilterApplier extends AbstractSampleTreatmentFilter { + @Override + protected AndedSampleTreatmentFilters getFilters(StudyViewFilter filter) { + return filter.getSampleTreatmentGroupFilters(); + } + + @Override + protected ClinicalEventKeyCode getCode() { + return ClinicalEventKeyCode.AgentClass; + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/util/appliers/SampleTreatmentTargetFilterApplier.java b/src/main/java/org/cbioportal/legacy/web/util/appliers/SampleTreatmentTargetFilterApplier.java new file mode 100644 index 00000000000..4684e27e503 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/util/appliers/SampleTreatmentTargetFilterApplier.java @@ -0,0 +1,20 @@ +package org.cbioportal.legacy.web.util.appliers; + +import org.cbioportal.legacy.model.ClinicalEventKeyCode; +import org.cbioportal.legacy.web.parameter.StudyViewFilter; +import org.cbioportal.legacy.web.parameter.filter.AndedSampleTreatmentFilters; +import org.springframework.stereotype.Component; + +@Component +public class SampleTreatmentTargetFilterApplier extends AbstractSampleTreatmentFilter { + + @Override + protected AndedSampleTreatmentFilters getFilters(StudyViewFilter filter) { + return filter.getSampleTreatmentTargetFilters(); + } + + @Override + protected ClinicalEventKeyCode getCode() { + return ClinicalEventKeyCode.AgentTarget; + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/util/appliers/StructuralVariantSubFilterApplier.java b/src/main/java/org/cbioportal/legacy/web/util/appliers/StructuralVariantSubFilterApplier.java new file mode 100644 index 00000000000..0605e91bdfb --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/util/appliers/StructuralVariantSubFilterApplier.java @@ -0,0 +1,119 @@ +package org.cbioportal.legacy.web.util.appliers; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.function.Function; +import java.util.stream.Collectors; +import org.cbioportal.legacy.model.MolecularProfile; +import org.cbioportal.legacy.model.StructuralVariantFilterQuery; +import org.cbioportal.legacy.model.StudyViewStructuralVariantFilter; +import org.cbioportal.legacy.service.MolecularProfileService; +import org.cbioportal.legacy.service.StructuralVariantService; +import org.cbioportal.legacy.web.parameter.SampleIdentifier; +import org.cbioportal.legacy.web.parameter.StudyViewFilter; +import org.cbioportal.legacy.web.util.StudyViewFilterUtil; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +@Component +public class StructuralVariantSubFilterApplier implements StudyViewSubFilterApplier { + + @Autowired private MolecularProfileService molecularProfileService; + + @Autowired private StructuralVariantService structuralVariantService; + + @Autowired private StudyViewFilterUtil studyViewFilterUtil; + + @Override + public List filter(List toFilter, StudyViewFilter filters) { + + final List structVarFilters = getStructVarFilters(filters); + + List includedStudyIds = + toFilter.stream().map(SampleIdentifier::getStudyId).distinct().collect(Collectors.toList()); + + List molecularProfiles = + molecularProfileService.getMolecularProfilesInStudies(includedStudyIds, "SUMMARY"); + + Map molecularProfileMap = + molecularProfiles.stream() + .collect(Collectors.toMap(MolecularProfile::getStableId, Function.identity())); + + List remainingSampleIdentifiers = toFilter; + + for (StudyViewStructuralVariantFilter structuralVariantFilter : structVarFilters) { + + // Collect molecular profiles referenced in gene filter. + List filteredMolecularProfiles = + structuralVariantFilter.getMolecularProfileIds().stream() + .map(molecularProfileId -> molecularProfileMap.get(molecularProfileId)) + .collect(Collectors.toList()); + + Map> mapByStudyId = + filteredMolecularProfiles.stream() + .collect(Collectors.groupingBy(MolecularProfile::getCancerStudyIdentifier)); + + for (List structVarQueries : + structuralVariantFilter.getStructVarQueries()) { + + // Remove samples in remainingSampleIdentifiers that belong to a study that is not + // accessible to the current user + // (do not appear in the molecularProfileMap argument). + final List filteredSampleIdentifiers = + remainingSampleIdentifiers.stream() + .filter(i -> mapByStudyId.containsKey(i.getStudyId())) + .collect(Collectors.toList()); + + final List molecularProfileIds = + filteredSampleIdentifiers.stream() + .map(i -> mapByStudyId.get(i.getStudyId()).get(0).getStableId()) + .distinct() + .collect(Collectors.toList()); + + final List sampleIds = + filteredSampleIdentifiers.stream() + .map(SampleIdentifier::getSampleId) + .collect(Collectors.toList()); + + final List entrezIdEnhancedSvQueries = + studyViewFilterUtil.resolveEntrezGeneIds(structVarQueries); + remainingSampleIdentifiers = + structuralVariantService + .fetchStructuralVariantsByStructVarQueries( + molecularProfileIds, sampleIds, entrezIdEnhancedSvQueries) + .stream() + .map( + m -> { + SampleIdentifier sampleIdentifier = new SampleIdentifier(); + sampleIdentifier.setSampleId(m.getSampleId()); + sampleIdentifier.setStudyId(m.getStudyId()); + return sampleIdentifier; + }) + .distinct() + .collect(Collectors.toList()); + } + } + return remainingSampleIdentifiers; + } + + @Override + public boolean shouldApplyFilter(StudyViewFilter studyViewFilter) { + return !getStructVarFilters(studyViewFilter).isEmpty(); + } + + private static List getStructVarFilters( + StudyViewFilter filters) { + final List structuralVariantFilters = + filters.getStructuralVariantFilters(); + if (structuralVariantFilters == null || structuralVariantFilters.isEmpty()) { + return new ArrayList<>(); + } + final List structVarFilters = + structuralVariantFilters.stream() + .filter( + structuralVariantFilter -> !structuralVariantFilter.getStructVarQueries().isEmpty()) + .collect(Collectors.toList()); + return structVarFilters; + } +} diff --git a/src/main/java/org/cbioportal/legacy/web/util/appliers/StudyViewSubFilterApplier.java b/src/main/java/org/cbioportal/legacy/web/util/appliers/StudyViewSubFilterApplier.java new file mode 100644 index 00000000000..4895098807f --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/util/appliers/StudyViewSubFilterApplier.java @@ -0,0 +1,11 @@ +package org.cbioportal.legacy.web.util.appliers; + +import java.util.List; +import org.cbioportal.legacy.web.parameter.SampleIdentifier; +import org.cbioportal.legacy.web.parameter.StudyViewFilter; + +public interface StudyViewSubFilterApplier { + List filter(List toFilter, StudyViewFilter filters); + + boolean shouldApplyFilter(StudyViewFilter studyViewFilter); +} diff --git a/src/main/java/org/cbioportal/legacy/web/util/appliers/TreatmentRowExtractor.java b/src/main/java/org/cbioportal/legacy/web/util/appliers/TreatmentRowExtractor.java new file mode 100644 index 00000000000..124a295d440 --- /dev/null +++ b/src/main/java/org/cbioportal/legacy/web/util/appliers/TreatmentRowExtractor.java @@ -0,0 +1,14 @@ +package org.cbioportal.legacy.web.util.appliers; + +import java.util.Set; +import java.util.stream.Collectors; +import org.cbioportal.legacy.model.ClinicalEventSample; +import org.cbioportal.legacy.model.TreatmentRow; +import org.springframework.stereotype.Service; + +@Service +public class TreatmentRowExtractor { + public Set extractSamples(TreatmentRow row) { + return row.getSamples().stream().map(ClinicalEventSample::key).collect(Collectors.toSet()); + } +} diff --git a/src/main/java/org/cbioportal/model/AlleleSpecificCopyNumber.java b/src/main/java/org/cbioportal/model/AlleleSpecificCopyNumber.java deleted file mode 100644 index 4ac94988d19..00000000000 --- a/src/main/java/org/cbioportal/model/AlleleSpecificCopyNumber.java +++ /dev/null @@ -1,79 +0,0 @@ -package org.cbioportal.model; - -import java.io.Serializable; - -public class AlleleSpecificCopyNumber implements Serializable { - - private Integer ascnIntegerCopyNumber; - private String ascnMethod; - private Float ccfExpectedCopiesUpper; - private Float ccfExpectedCopies; - private String clonal; - private Integer minorCopyNumber; - private Integer expectedAltCopies; - private Integer totalCopyNumber; - - public Integer getAscnIntegerCopyNumber() { - return ascnIntegerCopyNumber; - } - - public void setAscnIntegerCopyNumber(Integer ascnIntegerCopyNumber) { - this.ascnIntegerCopyNumber = ascnIntegerCopyNumber; - } - - public String getAscnMethod() { - return ascnMethod; - } - - public void setAscnMethod(String ascnMethod) { - this.ascnMethod = ascnMethod; - } - - public Float getCcfExpectedCopiesUpper() { - return ccfExpectedCopiesUpper; - } - - public void setCcfExpectedCopiesUpper(Float ccfExpectedCopiesUpper) { - this.ccfExpectedCopiesUpper = ccfExpectedCopiesUpper; - } - - public Float getCcfExpectedCopies() { - return ccfExpectedCopies; - } - - public void setCcfExpectedCopies(Float ccfExpectedCopies) { - this.ccfExpectedCopies = ccfExpectedCopies; - } - - public String getClonal() { - return clonal; - } - - public void setClonal(String clonal) { - this.clonal = clonal; - } - - public Integer getMinorCopyNumber() { - return minorCopyNumber; - } - - public void setMinorCopyNumber(Integer minorCopyNumber) { - this.minorCopyNumber = minorCopyNumber; - } - - public Integer getExpectedAltCopies() { - return expectedAltCopies; - } - - public void setExpectedAltCopies(Integer expectedAltCopies) { - this.expectedAltCopies = expectedAltCopies; - } - - public Integer getTotalCopyNumber() { - return totalCopyNumber; - } - - public void setTotalCopyNumber(Integer totalCopyNumber) { - this.totalCopyNumber = totalCopyNumber; - } -} diff --git a/src/main/java/org/cbioportal/model/Alteration.java b/src/main/java/org/cbioportal/model/Alteration.java deleted file mode 100644 index 1e7e6e96cde..00000000000 --- a/src/main/java/org/cbioportal/model/Alteration.java +++ /dev/null @@ -1,102 +0,0 @@ -package org.cbioportal.model; - -import jakarta.validation.constraints.NotNull; - -public class Alteration extends UniqueKeyBase { - - @NotNull - private String molecularProfileId; - @NotNull - private String sampleId; - @NotNull - private String patientId; - @NotNull - private Integer entrezGeneId; - private Gene gene; - @NotNull - private String studyId; - private String driverFilter; - private String driverFilterAnnotation; - private String driverTiersFilter; - private String driverTiersFilterAnnotation; - - public String getMolecularProfileId() { - return molecularProfileId; - } - - public void setMolecularProfileId(String molecularProfileId) { - this.molecularProfileId = molecularProfileId; - } - - public String getSampleId() { - return sampleId; - } - - public void setSampleId(String sampleId) { - this.sampleId = sampleId; - } - - public String getPatientId() { - return patientId; - } - - public void setPatientId(String patientId) { - this.patientId = patientId; - } - - public Integer getEntrezGeneId() { - return entrezGeneId; - } - - public void setEntrezGeneId(Integer entrezGeneId) { - this.entrezGeneId = entrezGeneId; - } - - public Gene getGene() { - return gene; - } - - public void setGene(Gene gene) { - this.gene = gene; - } - - public String getStudyId() { - return studyId; - } - - public void setStudyId(String studyId) { - this.studyId = studyId; - } - - public String getDriverFilter() { - return driverFilter; - } - - public void setDriverFilter(String driverFilter) { - this.driverFilter = driverFilter; - } - - public String getDriverFilterAnnotation() { - return driverFilterAnnotation; - } - - public void setDriverFilterAnnotation(String driverFilterAnnotation) { - this.driverFilterAnnotation = driverFilterAnnotation; - } - - public String getDriverTiersFilter() { - return driverTiersFilter; - } - - public void setDriverTiersFilter(String driverTiersFilter) { - this.driverTiersFilter = driverTiersFilter; - } - - public String getDriverTiersFilterAnnotation() { - return driverTiersFilterAnnotation; - } - - public void setDriverTiersFilterAnnotation(String driverTiersFilterAnnotation) { - this.driverTiersFilterAnnotation = driverTiersFilterAnnotation; - } -} diff --git a/src/main/java/org/cbioportal/model/AlterationCountBase.java b/src/main/java/org/cbioportal/model/AlterationCountBase.java deleted file mode 100644 index cbe79790563..00000000000 --- a/src/main/java/org/cbioportal/model/AlterationCountBase.java +++ /dev/null @@ -1,51 +0,0 @@ -package org.cbioportal.model; - -import java.io.Serializable; -import java.util.Set; - -public abstract class AlterationCountBase implements Serializable { - - private Integer numberOfAlteredCases; - private Integer totalCount; - private Integer numberOfProfiledCases; - private Set matchingGenePanelIds; - - public Integer getNumberOfAlteredCases() { - return numberOfAlteredCases; - } - - public void setNumberOfAlteredCases(Integer numberOfAlteredCases) { - this.numberOfAlteredCases = numberOfAlteredCases; - } - - public Integer getTotalCount() { - return totalCount; - } - - public void setTotalCount(Integer totalCount) { - this.totalCount = totalCount; - } - - public Integer getNumberOfProfiledCases() { - return numberOfProfiledCases; - } - - public void setNumberOfProfiledCases(Integer numberOfProfiledCases) { - this.numberOfProfiledCases = numberOfProfiledCases; - } - - public Set getMatchingGenePanelIds() { - return matchingGenePanelIds; - } - - public void setMatchingGenePanelIds(Set matchingGenePanelIds) { - this.matchingGenePanelIds = matchingGenePanelIds; - } - - public abstract String getUniqueEventKey(); - - public abstract String[] getHugoGeneSymbols(); - - public abstract Integer[] getEntrezGeneIds(); - -} diff --git a/src/main/java/org/cbioportal/model/AlterationCountByGene.java b/src/main/java/org/cbioportal/model/AlterationCountByGene.java deleted file mode 100644 index 0c09a79351f..00000000000 --- a/src/main/java/org/cbioportal/model/AlterationCountByGene.java +++ /dev/null @@ -1,62 +0,0 @@ -package org.cbioportal.model; - -import com.fasterxml.jackson.annotation.JsonProperty; - -import java.math.BigDecimal; - -public class AlterationCountByGene extends AlterationCountBase { - - private Integer entrezGeneId; - private String hugoGeneSymbol; - private Integer numberOfAlteredCases; - private BigDecimal qValue; - - public Integer getEntrezGeneId() { - return entrezGeneId; - } - - public void setEntrezGeneId(Integer entrezGeneId) { - this.entrezGeneId = entrezGeneId; - } - - public String getHugoGeneSymbol() { - return hugoGeneSymbol; - } - - public void setHugoGeneSymbol(String hugoGeneSymbol) { - this.hugoGeneSymbol = hugoGeneSymbol; - } - - public Integer getNumberOfAlteredCases() { - return numberOfAlteredCases; - } - - public void setNumberOfAlteredCases(Integer numberOfAlteredCases) { - this.numberOfAlteredCases = numberOfAlteredCases; - } - - @JsonProperty("qValue") - public BigDecimal getqValue() { - return qValue; - } - - public void setqValue(BigDecimal qValue) { - this.qValue = qValue; - } - - @Override - public String getUniqueEventKey() { - return hugoGeneSymbol; - } - - @Override - public String[] getHugoGeneSymbols() { - return new String[]{hugoGeneSymbol}; - } - - @Override - public Integer[] getEntrezGeneIds() { - return new Integer[]{entrezGeneId}; - } - -} diff --git a/src/main/java/org/cbioportal/model/AlterationCountByStructuralVariant.java b/src/main/java/org/cbioportal/model/AlterationCountByStructuralVariant.java deleted file mode 100644 index 88800d1f84f..00000000000 --- a/src/main/java/org/cbioportal/model/AlterationCountByStructuralVariant.java +++ /dev/null @@ -1,56 +0,0 @@ -package org.cbioportal.model; - -public class AlterationCountByStructuralVariant extends AlterationCountBase { - - private Integer gene1EntrezGeneId; - private String gene1HugoGeneSymbol; - private Integer gene2EntrezGeneId; - private String gene2HugoGeneSymbol; - - public Integer getGene1EntrezGeneId() { - return gene1EntrezGeneId; - } - - public void setGene1EntrezGeneId(Integer gene1EntrezGeneId) { - this.gene1EntrezGeneId = gene1EntrezGeneId; - } - - public String getGene1HugoGeneSymbol() { - return gene1HugoGeneSymbol; - } - - public void setGene1HugoGeneSymbol(String gene1HugoGeneSymbol) { - this.gene1HugoGeneSymbol = gene1HugoGeneSymbol; - } - - public Integer getGene2EntrezGeneId() { - return gene2EntrezGeneId; - } - - public void setGene2EntrezGeneId(Integer gene2EntrezGeneId) { - this.gene2EntrezGeneId = gene2EntrezGeneId; - } - - public String getGene2HugoGeneSymbol() { - return gene2HugoGeneSymbol; - } - - public void setGene2HugoGeneSymbol(String gene2HugoGeneSymbol) { - this.gene2HugoGeneSymbol = gene2HugoGeneSymbol; - } - - @Override - public String getUniqueEventKey() { - return gene1HugoGeneSymbol + "::" + gene2HugoGeneSymbol; - } - - @Override - public String[] getHugoGeneSymbols() { - return new String[]{gene1HugoGeneSymbol, gene2HugoGeneSymbol}; - } - - @Override - public Integer[] getEntrezGeneIds() { - return new Integer[]{gene1EntrezGeneId, gene2EntrezGeneId}; - } -} diff --git a/src/main/java/org/cbioportal/model/AlterationDriverAnnotation.java b/src/main/java/org/cbioportal/model/AlterationDriverAnnotation.java deleted file mode 100644 index 02f0f909db9..00000000000 --- a/src/main/java/org/cbioportal/model/AlterationDriverAnnotation.java +++ /dev/null @@ -1,70 +0,0 @@ -package org.cbioportal.model; - -import java.io.Serializable; - -public class AlterationDriverAnnotation implements Serializable { - - private Integer alterationEventId; - private Integer geneticProfileId; - private Integer sampleId; - private String driverFilter; - private String driverFilterAnnotation; - private String driverTiersFilter; - private String driverTiersFilterAnnotation; - - public Integer getAlterationEventId() { - return alterationEventId; - } - - public void setAlterationEventId(Integer alterationEventId) { - this.alterationEventId = alterationEventId; - } - - public Integer getGeneticProfileId() { - return geneticProfileId; - } - - public void setGeneticProfileId(Integer geneticProfileId) { - this.geneticProfileId = geneticProfileId; - } - - public Integer getSampleId() { - return sampleId; - } - - public void setSampleId(Integer sampleId) { - this.sampleId = sampleId; - } - - public String getDriverFilter() { - return driverFilter; - } - - public void setDriverFilter(String driverFilter) { - this.driverFilter = driverFilter; - } - - public String getDriverFilterAnnotation() { - return driverFilterAnnotation; - } - - public void setDriverFilterAnnotation(String driverFilterAnnotation) { - this.driverFilterAnnotation = driverFilterAnnotation; - } - - public String getDriverTiersFilter() { - return driverTiersFilter; - } - - public void setDriverTiersFilter(String driverTiersFilter) { - this.driverTiersFilter = driverTiersFilter; - } - - public String getDriverTiersFilterAnnotation() { - return driverTiersFilterAnnotation; - } - - public void setDriverTiersFilterAnnotation(String driverTiersFilterAnnotation) { - this.driverTiersFilterAnnotation = driverTiersFilterAnnotation; - } -} \ No newline at end of file diff --git a/src/main/java/org/cbioportal/model/AlterationEnrichment.java b/src/main/java/org/cbioportal/model/AlterationEnrichment.java deleted file mode 100644 index d1fdbc4ba34..00000000000 --- a/src/main/java/org/cbioportal/model/AlterationEnrichment.java +++ /dev/null @@ -1,62 +0,0 @@ -package org.cbioportal.model; - -import java.io.Serializable; -import java.math.BigDecimal; -import java.util.List; - -import com.fasterxml.jackson.annotation.JsonProperty; -import jakarta.validation.constraints.NotNull; - -public class AlterationEnrichment implements Serializable { - - @NotNull - private Integer entrezGeneId; - @NotNull - private String hugoGeneSymbol; - private String cytoband; - private BigDecimal pValue; - @NotNull - private List counts; - - public Integer getEntrezGeneId() { - return entrezGeneId; - } - - public void setEntrezGeneId(Integer entrezGeneId) { - this.entrezGeneId = entrezGeneId; - } - - public String getHugoGeneSymbol() { - return hugoGeneSymbol; - } - - public void setHugoGeneSymbol(String hugoGeneSymbol) { - this.hugoGeneSymbol = hugoGeneSymbol; - } - - public String getCytoband() { - return cytoband; - } - - public void setCytoband(String cytoband) { - this.cytoband = cytoband; - } - - @JsonProperty("pValue") - public BigDecimal getpValue() { - return pValue; - } - - public void setpValue(BigDecimal pValue) { - this.pValue = pValue; - } - - public List getCounts() { - return counts; - } - - public void setCounts(List counts) { - this.counts = counts; - } - -} diff --git a/src/main/java/org/cbioportal/model/AlterationFilter.java b/src/main/java/org/cbioportal/model/AlterationFilter.java deleted file mode 100644 index c10f8d697e7..00000000000 --- a/src/main/java/org/cbioportal/model/AlterationFilter.java +++ /dev/null @@ -1,147 +0,0 @@ -package org.cbioportal.model; - -import java.io.Serializable; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.stream.Collectors; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonInclude; -import org.cbioportal.model.util.Select; - -import com.fasterxml.jackson.annotation.JsonIgnore; - -import static com.fasterxml.jackson.annotation.JsonInclude.Include.*; - -@JsonIgnoreProperties(ignoreUnknown = true) -@JsonInclude(NON_NULL) -public class AlterationFilter extends BaseAlterationFilter implements Serializable { - - private Map mutationEventTypes = new HashMap<>(); - private Map copyNumberAlterationEventTypes = new HashMap<>(); - private Boolean structuralVariants; - - @JsonIgnore - private Select mutationTypeSelect; - @JsonIgnore - private Select cnaTypeSelect; - - public AlterationFilter() {} - - public AlterationFilter(Select mutationTypesMap, - Select cnaEventTypes, - boolean includeDriver, - boolean includeVUS, - boolean includeUnknownOncogenicity, - boolean includeGermline, - boolean includeSomatic, - boolean includeUnknownStatus, - Select tiersSelect, - boolean includeUnknownTier) { - this.mutationTypeSelect = mutationTypesMap; - this.cnaTypeSelect = cnaEventTypes; - this.includeDriver = includeDriver; - this.includeVUS = includeVUS; - this.includeUnknownOncogenicity = includeUnknownOncogenicity; - this.includeGermline = includeGermline; - this.includeSomatic = includeSomatic; - this.includeUnknownStatus = includeUnknownStatus; - this.tiersSelect = tiersSelect; - this.includeUnknownTier = includeUnknownTier; - } - - public Map getMutationEventTypes() { - return mutationEventTypes; - } - - public void setMutationEventTypes(Map mutationEventTypes) { - if (mutationEventTypes == null) { - throw new IllegalArgumentException("null value is not allowed for mutationEventTypes"); - } - this.mutationEventTypes = mutationEventTypes; - } - - public Map getCopyNumberAlterationEventTypes() { - return copyNumberAlterationEventTypes; - } - - public void setCopyNumberAlterationEventTypes(Map copyNumberAlterationEventTypes) { - if (copyNumberAlterationEventTypes == null) { - throw new IllegalArgumentException("null value is not allowed for copyNumberAlterationEventTypes"); - } - this.copyNumberAlterationEventTypes = copyNumberAlterationEventTypes; - } - - public Boolean getStructuralVariants() { - return structuralVariants; - } - - public void setStructuralVariants(Boolean structuralVariants) { - this.structuralVariants = structuralVariants; - } - - @JsonIgnore - public Select getMutationTypeSelect() { - if (mutationTypeSelect != null) - return mutationTypeSelect; - - if (mutationEventTypes == null || mutationEventTypes.getOrDefault(MutationEventType.any, false) - || allOptionsSelected(mutationEventTypes, Arrays.asList(MutationEventType.any.toString()))) { - return Select.all(); - } - - // if MutationEventType.other is true and not allOptionsSelected - if (mutationEventTypes.getOrDefault(MutationEventType.other, false)) { - List unSelected = mutationEventTypes - .entrySet() - .stream() - .filter(e -> !e.getValue()) - .map(Entry::getKey) - .collect(Collectors.toList()); - Select select = Select.byValues(unSelected); - // setting this would execute NOT IN clause in sql query - select.inverse(true); - return select; - } else { - List selected = mutationEventTypes - .entrySet() - .stream() - .filter(Entry::getValue) - .map(Entry::getKey) - .collect(Collectors.toList()); - return Select.byValues(selected); - } - } - - @JsonIgnore - public Select getCNAEventTypeSelect() { - if (cnaTypeSelect != null) - return cnaTypeSelect; - if (allOptionsSelected(copyNumberAlterationEventTypes, null)) { - return Select.all(); - } - return Select.byValues( - copyNumberAlterationEventTypes.entrySet().stream().filter(Entry::getValue).map(Entry::getKey)); - } - - @JsonIgnore - public void setMutationTypeSelect(Select mutationTypeSelect) { - this.mutationTypeSelect = mutationTypeSelect; - } - - @JsonIgnore - public void setCnaTypeSelect(Select cnaTypeSelect) { - this.cnaTypeSelect = cnaTypeSelect; - } - - @JsonIgnore - private boolean allOptionsSelected(Map options, List excludeKeys) { - return options.entrySet().stream().allMatch(e -> { - return excludeKeys == null || !excludeKeys.contains(e.getKey().toString()) ? e.getValue() : true; - }); - } - -} diff --git a/src/main/java/org/cbioportal/model/AlterationType.java b/src/main/java/org/cbioportal/model/AlterationType.java deleted file mode 100644 index b20a642669d..00000000000 --- a/src/main/java/org/cbioportal/model/AlterationType.java +++ /dev/null @@ -1,8 +0,0 @@ -package org.cbioportal.model; - -public enum AlterationType { - MUTATION_EXTENDED, - COPY_NUMBER_ALTERATION, - STRUCTURAL_VARIANT, - GENERIC_ASSAY; -} diff --git a/src/main/java/org/cbioportal/model/BaseAlterationFilter.java b/src/main/java/org/cbioportal/model/BaseAlterationFilter.java deleted file mode 100644 index df2d2f72a63..00000000000 --- a/src/main/java/org/cbioportal/model/BaseAlterationFilter.java +++ /dev/null @@ -1,138 +0,0 @@ -package org.cbioportal.model; - -import com.fasterxml.jackson.annotation.JsonIgnore; -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonInclude; -import com.fasterxml.jackson.annotation.JsonInclude.Include; -import org.cbioportal.model.util.Select; - -import java.io.Serializable; -import java.util.HashMap; -import java.util.Map; - -@JsonIgnoreProperties(ignoreUnknown = true) -@JsonInclude(Include.NON_NULL) -public class BaseAlterationFilter implements Serializable { - - protected boolean includeGermline = true; - protected boolean includeSomatic = true; - protected boolean includeUnknownStatus = true; - protected boolean includeDriver = true; - protected boolean includeVUS = true; - protected boolean includeUnknownOncogenicity = true; - protected Map tiersBooleanMap = new HashMap<>(); - protected boolean includeUnknownTier = true; - - @JsonIgnore - protected Select tiersSelect = Select.all(); - - // When default constructor is called, the filter is inactive (excludes nothing) - public BaseAlterationFilter() { - } - - public BaseAlterationFilter(boolean includeDriver, - boolean includeVUS, - boolean includeUnknownOncogenicity, - boolean includeGermline, - boolean includeSomatic, - boolean includeUnknownStatus, - Select tiersSelect, - boolean includeUnknownTier) { - this.includeGermline = includeGermline; - this.includeSomatic = includeSomatic; - this.includeUnknownStatus = includeUnknownStatus; - this.includeDriver = includeDriver; - this.includeVUS = includeVUS; - this.includeUnknownOncogenicity = includeUnknownOncogenicity; - this.tiersSelect = tiersSelect; - this.includeUnknownTier = includeUnknownTier; - } - - public boolean getIncludeGermline() { - return includeGermline; - } - - public void setIncludeGermline(boolean includeGermline) { - this.includeGermline = includeGermline; - } - - public boolean getIncludeSomatic() { - return includeSomatic; - } - - - public void setIncludeSomatic(boolean includeSomatic) { - this.includeSomatic = includeSomatic; - } - - public boolean getIncludeUnknownStatus() { - return includeUnknownStatus; - } - - public void setIncludeUnknownStatus(boolean includeUnknownStatus) { - this.includeUnknownStatus = includeUnknownStatus; - } - - public boolean getIncludeDriver() { - return includeDriver; - } - - public void setIncludeDriver(boolean includeDriver) { - this.includeDriver = includeDriver; - } - - public boolean getIncludeVUS() { - return includeVUS; - } - - public void setIncludeVUS(boolean includeVUS) { - this.includeVUS = includeVUS; - } - - public boolean getIncludeUnknownOncogenicity() { - return includeUnknownOncogenicity; - } - - public void setIncludeUnknownOncogenicity(boolean includeUnknownOncogenicity) { - this.includeUnknownOncogenicity = includeUnknownOncogenicity; - } - - public boolean getIncludeUnknownTier() { - return includeUnknownTier; - } - - public void setIncludeUnknownTier(boolean includeUnknownTier) { - this.includeUnknownTier = includeUnknownTier; - } - - public void setTiersBooleanMap(Map tiersBooleanMap) { - if (tiersBooleanMap == null) { - this.tiersSelect = Select.none(); - } else { - this.tiersSelect = Select.byValues( - tiersBooleanMap.entrySet().stream() - .filter(e -> e.getValue()) - .map(e -> e.getKey())); - // Empty map '{}' is interpreted as hasAll(). - if (tiersBooleanMap.entrySet().stream().allMatch(e -> e.getValue())) - this.tiersSelect.hasAll(true); - } - } - - public Map getTiersBooleanMap() { - return tiersBooleanMap; - } - - @JsonIgnore - public Select getSelectedTiers() { - if (tiersSelect == null) - return Select.none(); - return tiersSelect; - } - - @JsonIgnore - public void setSelectedTiers(Select tiersSelect) { - this.tiersSelect = tiersSelect; - } - -} diff --git a/src/main/java/org/cbioportal/model/Binnable.java b/src/main/java/org/cbioportal/model/Binnable.java deleted file mode 100644 index 358cafc1685..00000000000 --- a/src/main/java/org/cbioportal/model/Binnable.java +++ /dev/null @@ -1,13 +0,0 @@ -package org.cbioportal.model; - -/** - * Data that can be binned, clinical or custom - */ -public interface Binnable { - String getAttrId(); - String getAttrValue(); - String getSampleId(); - String getPatientId(); - String getStudyId(); - Boolean isPatientAttribute(); -} \ No newline at end of file diff --git a/src/main/java/org/cbioportal/model/CNA.java b/src/main/java/org/cbioportal/model/CNA.java deleted file mode 100644 index 1840eb7e6f5..00000000000 --- a/src/main/java/org/cbioportal/model/CNA.java +++ /dev/null @@ -1,39 +0,0 @@ -package org.cbioportal.model; - -import java.util.HashMap; -import java.util.Map; - -public enum CNA { - AMP ((short)2, "Amplified"), - GAIN ((short)1, "Gained"), - DIPLOID ((short)0, "Diploid"), - HETLOSS ((short)-1, "Heterozygously deleted"), - HOMDEL ((short)-2, "Homozygously deleted"); - - private short code; - private String desc; - - private CNA(short code, String desc) { - this.code = code; - this.desc = desc; - } - - private final static Map cache = new HashMap(); - static { - for (CNA cna : CNA.values()) { - cache.put(cna.code, cna); - } - } - - public static CNA getByCode(short code) { - return cache.get(code); - } - - public short getCode() { - return code; - } - - public String getDescription() { - return desc; - } -} \ No newline at end of file diff --git a/src/main/java/org/cbioportal/model/CancerStudy.java b/src/main/java/org/cbioportal/model/CancerStudy.java deleted file mode 100644 index 8504a8bd55a..00000000000 --- a/src/main/java/org/cbioportal/model/CancerStudy.java +++ /dev/null @@ -1,251 +0,0 @@ -package org.cbioportal.model; - -import java.io.Serializable; -import java.util.Date; -import jakarta.validation.constraints.NotNull; - -public class CancerStudy implements ReadPermission, Serializable { - - private Integer cancerStudyId; - @NotNull - private String cancerStudyIdentifier; - private String typeOfCancerId; - private String name; - private String description; - private Boolean publicStudy; - private String pmid; - private String citation; - private String groups; - private Integer status; - private Date importDate; - private TypeOfCancer typeOfCancer; - private Integer allSampleCount; - private Integer sequencedSampleCount; - private Integer cnaSampleCount; - private Integer mrnaRnaSeqSampleCount; - private Integer mrnaRnaSeqV2SampleCount; - private Integer mrnaMicroarraySampleCount; - private Integer miRnaSampleCount; - private Integer methylationHm27SampleCount; - private Integer rppaSampleCount; - private Integer massSpectrometrySampleCount; - private Integer completeSampleCount; - private String referenceGenome; - private Boolean readPermission = true; - private Integer treatmentCount; - private Integer structuralVariantCount; - - public Integer getCancerStudyId() { - return cancerStudyId; - } - - public void setCancerStudyId(Integer cancerStudyId) { - this.cancerStudyId = cancerStudyId; - } - - public String getCancerStudyIdentifier() { - return cancerStudyIdentifier; - } - - public void setCancerStudyIdentifier(String cancerStudyIdentifier) { - this.cancerStudyIdentifier = cancerStudyIdentifier; - } - - public String getTypeOfCancerId() { - return typeOfCancerId; - } - - public void setTypeOfCancerId(String typeOfCancerId) { - this.typeOfCancerId = typeOfCancerId; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String getDescription() { - return description; - } - - public void setDescription(String description) { - this.description = description; - } - - public Boolean getPublicStudy() { - return publicStudy; - } - - public void setPublicStudy(Boolean publicStudy) { - this.publicStudy = publicStudy; - } - - public String getPmid() { - return pmid; - } - - public void setPmid(String pmid) { - this.pmid = pmid; - } - - public String getCitation() { - return citation; - } - - public void setCitation(String citation) { - this.citation = citation; - } - - public String getGroups() { - return groups; - } - - public void setGroups(String groups) { - this.groups = groups; - } - - public Integer getStatus() { - return status; - } - - public void setStatus(Integer status) { - this.status = status; - } - - public Date getImportDate() { - return importDate; - } - - public void setImportDate(Date importDate) { - this.importDate = importDate; - } - - public TypeOfCancer getTypeOfCancer() { - return typeOfCancer; - } - - public void setTypeOfCancer(TypeOfCancer typeOfCancer) { - this.typeOfCancer = typeOfCancer; - } - - public Integer getAllSampleCount() { - return allSampleCount; - } - - public void setAllSampleCount(Integer allSampleCount) { - this.allSampleCount = allSampleCount; - } - - public Integer getSequencedSampleCount() { - return sequencedSampleCount; - } - - public void setSequencedSampleCount(Integer sequencedSampleCount) { - this.sequencedSampleCount = sequencedSampleCount; - } - - public Integer getCnaSampleCount() { - return cnaSampleCount; - } - - public void setCnaSampleCount(Integer cnaSampleCount) { - this.cnaSampleCount = cnaSampleCount; - } - - public Integer getMrnaRnaSeqSampleCount() { - return mrnaRnaSeqSampleCount; - } - - public void setMrnaRnaSeqSampleCount(Integer mrnaRnaSeqSampleCount) { - this.mrnaRnaSeqSampleCount = mrnaRnaSeqSampleCount; - } - - public Integer getMrnaRnaSeqV2SampleCount() { - return mrnaRnaSeqV2SampleCount; - } - - public void setMrnaRnaSeqV2SampleCount(Integer mrnaRnaSeqV2SampleCount) { - this.mrnaRnaSeqV2SampleCount = mrnaRnaSeqV2SampleCount; - } - - public Integer getMrnaMicroarraySampleCount() { - return mrnaMicroarraySampleCount; - } - - public void setMrnaMicroarraySampleCount(Integer mrnaMicroarraySampleCount) { - this.mrnaMicroarraySampleCount = mrnaMicroarraySampleCount; - } - - public Integer getMiRnaSampleCount() { - return miRnaSampleCount; - } - - public void setMiRnaSampleCount(Integer miRnaSampleCount) { - this.miRnaSampleCount = miRnaSampleCount; - } - - public Integer getMethylationHm27SampleCount() { - return methylationHm27SampleCount; - } - - public void setMethylationHm27SampleCount(Integer methylationHm27SampleCount) { - this.methylationHm27SampleCount = methylationHm27SampleCount; - } - - public Integer getRppaSampleCount() { - return rppaSampleCount; - } - - public void setRppaSampleCount(Integer rppaSampleCount) { - this.rppaSampleCount = rppaSampleCount; - } - - public Integer getCompleteSampleCount() { - return completeSampleCount; - } - - public void setCompleteSampleCount(Integer completeSampleCount) { - this.completeSampleCount = completeSampleCount; - } - - public Integer getMassSpectrometrySampleCount() { - return massSpectrometrySampleCount; - } - - public void setMassSpectrometrySampleCount(Integer massSpectrometrySampleCount) { - this.massSpectrometrySampleCount = massSpectrometrySampleCount; - } - - public String getReferenceGenome() { return referenceGenome; } - - public void setReferenceGenome(String referenceGenome) { this.referenceGenome = referenceGenome; } - - @Override - public void setReadPermission(Boolean permission) { - this.readPermission = permission; - } - - @Override - public Boolean getReadPermission() { - return readPermission; - } - - public Integer getTreatmentCount() { - return treatmentCount; - } - - public void setTreatmentCount(Integer treatmentCount) { - this.treatmentCount = treatmentCount; - } - - public Integer getStructuralVariantCount() { - return structuralVariantCount; - } - - public void setStructuralVariantCount(Integer structuralVariantCount) { - this.structuralVariantCount = structuralVariantCount; - } -} diff --git a/src/main/java/org/cbioportal/model/CancerStudyTags.java b/src/main/java/org/cbioportal/model/CancerStudyTags.java deleted file mode 100644 index 48f987036c0..00000000000 --- a/src/main/java/org/cbioportal/model/CancerStudyTags.java +++ /dev/null @@ -1,34 +0,0 @@ -package org.cbioportal.model; - -import java.io.Serializable; - -public class CancerStudyTags implements Serializable { - - private Integer cancerStudyId; - private String studyId; - private String tags; - - public Integer getCancerStudyId() { - return cancerStudyId; - } - - public void setCancerStudyId(Integer cancerStudyId) { - this.cancerStudyId = cancerStudyId; - } - - public String getTags() { - return tags; - } - - public void setTags(String tags) { - this.tags = tags; - } - - public String getStudyId() { - return studyId; - } - - public void setStudyId(String studyId) { - this.studyId = studyId; - } -} \ No newline at end of file diff --git a/src/main/java/org/cbioportal/model/CaseListDataCount.java b/src/main/java/org/cbioportal/model/CaseListDataCount.java deleted file mode 100644 index 218a83ffd3c..00000000000 --- a/src/main/java/org/cbioportal/model/CaseListDataCount.java +++ /dev/null @@ -1,35 +0,0 @@ -package org.cbioportal.model; - -import java.io.Serializable; - -public class CaseListDataCount implements Serializable { - - private String label; - private String value; - private Integer count; - - public String getLabel() { - return label; - } - - public void setLabel(String label) { - this.label = label; - } - - public String getValue() { - return value; - } - - public void setValue(String value) { - this.value = value; - } - - public Integer getCount() { - return count; - } - - public void setCount(Integer count) { - this.count = count; - } - -} diff --git a/src/main/java/org/cbioportal/model/ClinicalAttribute.java b/src/main/java/org/cbioportal/model/ClinicalAttribute.java deleted file mode 100644 index ef1d10e9026..00000000000 --- a/src/main/java/org/cbioportal/model/ClinicalAttribute.java +++ /dev/null @@ -1,85 +0,0 @@ -package org.cbioportal.model; - -import java.io.Serializable; -import jakarta.validation.constraints.NotNull; - -public class ClinicalAttribute implements Serializable { - - @NotNull - private String attrId; - @NotNull - private String displayName; - private String description; - private String datatype; - @NotNull - private Boolean patientAttribute; - private String priority; - private Integer cancerStudyId; - @NotNull - private String cancerStudyIdentifier; - - public String getAttrId() { - return attrId; - } - - public void setAttrId(String attrId) { - this.attrId = attrId; - } - - public String getDisplayName() { - return displayName; - } - - public void setDisplayName(String displayName) { - this.displayName = displayName; - } - - public String getDescription() { - return description; - } - - public void setDescription(String description) { - this.description = description; - } - - public String getDatatype() { - return datatype; - } - - public void setDatatype(String datatype) { - this.datatype = datatype; - } - - public Boolean getPatientAttribute() { - return patientAttribute; - } - - public void setPatientAttribute(Boolean patientAttribute) { - this.patientAttribute = patientAttribute; - } - - public String getPriority() { - return priority; - } - - public void setPriority(String priority) { - this.priority = priority; - } - - public Integer getCancerStudyId() { - return cancerStudyId; - } - - public void setCancerStudyId(Integer cancerStudyId) { - this.cancerStudyId = cancerStudyId; - } - - public String getCancerStudyIdentifier() { - return cancerStudyIdentifier; - } - - public void setCancerStudyIdentifier(String cancerStudyIdentifier) { - this.cancerStudyIdentifier = cancerStudyIdentifier; - } - -} diff --git a/src/main/java/org/cbioportal/model/ClinicalAttributeCount.java b/src/main/java/org/cbioportal/model/ClinicalAttributeCount.java deleted file mode 100644 index 440654eb68f..00000000000 --- a/src/main/java/org/cbioportal/model/ClinicalAttributeCount.java +++ /dev/null @@ -1,25 +0,0 @@ -package org.cbioportal.model; - -import java.io.Serializable; - -public class ClinicalAttributeCount implements Serializable { - - private String attrId; - private Integer count; - - public String getAttrId() { - return attrId; - } - - public void setAttrId(String attrId) { - this.attrId = attrId; - } - - public Integer getCount() { - return count; - } - - public void setCount(Integer count) { - this.count = count; - } -} diff --git a/src/main/java/org/cbioportal/model/ClinicalData.java b/src/main/java/org/cbioportal/model/ClinicalData.java deleted file mode 100644 index 3943de6044f..00000000000 --- a/src/main/java/org/cbioportal/model/ClinicalData.java +++ /dev/null @@ -1,80 +0,0 @@ -package org.cbioportal.model; - -import jakarta.validation.constraints.NotNull; - -public class ClinicalData extends UniqueKeyBase implements Binnable { - - private Integer internalId; - private String sampleId; - @NotNull - private String patientId; - @NotNull - private String studyId; - @NotNull - private String attrId; - private String attrValue; - private ClinicalAttribute clinicalAttribute; - - public Integer getInternalId() { - return internalId; - } - - public void setInternalId(Integer internalId) { - this.internalId = internalId; - } - - public String getSampleId() { - return sampleId; - } - - public void setSampleId(String sampleId) { - this.sampleId = sampleId; - } - - public String getPatientId() { - return patientId; - } - - public void setPatientId(String patientId) { - this.patientId = patientId; - } - - public String getStudyId() { - return studyId; - } - - public void setStudyId(String studyId) { - this.studyId = studyId; - } - - public String getAttrId() { - return attrId; - } - - public Boolean isPatientAttribute() { - if (clinicalAttribute == null) { - return null; - } - return this.clinicalAttribute.getPatientAttribute(); - } - - public void setAttrId(String attrId) { - this.attrId = attrId; - } - - public String getAttrValue() { - return attrValue; - } - - public void setAttrValue(String attrValue) { - this.attrValue = attrValue; - } - - public ClinicalAttribute getClinicalAttribute() { - return clinicalAttribute; - } - - public void setClinicalAttribute(ClinicalAttribute clinicalAttribute) { - this.clinicalAttribute = clinicalAttribute; - } -} diff --git a/src/main/java/org/cbioportal/model/ClinicalDataBin.java b/src/main/java/org/cbioportal/model/ClinicalDataBin.java deleted file mode 100644 index 86be0ae127c..00000000000 --- a/src/main/java/org/cbioportal/model/ClinicalDataBin.java +++ /dev/null @@ -1,16 +0,0 @@ -package org.cbioportal.model; - -import java.io.Serializable; - -public class ClinicalDataBin extends DataBin implements Serializable { - private String attributeId; - - public String getAttributeId() { - return attributeId; - } - - public void setAttributeId(String attributeId) { - this.attributeId = attributeId; - } - -} diff --git a/src/main/java/org/cbioportal/model/ClinicalDataCount.java b/src/main/java/org/cbioportal/model/ClinicalDataCount.java deleted file mode 100644 index c16e98ba08c..00000000000 --- a/src/main/java/org/cbioportal/model/ClinicalDataCount.java +++ /dev/null @@ -1,34 +0,0 @@ -package org.cbioportal.model; - -import java.io.Serializable; - -public class ClinicalDataCount implements Serializable { - - private String attributeId; - private String value; - private Integer count; - - public String getAttributeId() { - return attributeId; - } - - public void setAttributeId(String attributeId) { - this.attributeId = attributeId; - } - - public String getValue() { - return value; - } - - public void setValue(String value) { - this.value = value; - } - - public Integer getCount() { - return count; - } - - public void setCount(Integer count) { - this.count = count; - } -} diff --git a/src/main/java/org/cbioportal/model/ClinicalDataCountItem.java b/src/main/java/org/cbioportal/model/ClinicalDataCountItem.java deleted file mode 100644 index aaf56ec10ba..00000000000 --- a/src/main/java/org/cbioportal/model/ClinicalDataCountItem.java +++ /dev/null @@ -1,26 +0,0 @@ -package org.cbioportal.model; - -import java.io.Serializable; -import java.util.List; - -public class ClinicalDataCountItem implements Serializable { - - private String attributeId; - private List counts; - - public String getAttributeId() { - return attributeId; - } - - public void setAttributeId(String attributeId) { - this.attributeId = attributeId; - } - - public List getCounts() { - return counts; - } - - public void setCounts(List counts) { - this.counts = counts; - } -} diff --git a/src/main/java/org/cbioportal/model/ClinicalDataEnrichment.java b/src/main/java/org/cbioportal/model/ClinicalDataEnrichment.java deleted file mode 100644 index 10c13ac2242..00000000000 --- a/src/main/java/org/cbioportal/model/ClinicalDataEnrichment.java +++ /dev/null @@ -1,53 +0,0 @@ -package org.cbioportal.model; - -import java.io.Serializable; -import java.math.BigDecimal; - -import com.fasterxml.jackson.annotation.JsonProperty; -import jakarta.validation.constraints.NotNull; - -public class ClinicalDataEnrichment implements Serializable { - - @NotNull - private ClinicalAttribute clinicalAttribute; - @NotNull - private BigDecimal score; - @NotNull - private String method; - @NotNull - private BigDecimal pValue; - - public ClinicalAttribute getClinicalAttribute() { - return clinicalAttribute; - } - - public void setClinicalAttribute(ClinicalAttribute clinicalAttribute) { - this.clinicalAttribute = clinicalAttribute; - } - - public BigDecimal getScore() { - return score; - } - - public void setScore(BigDecimal score) { - this.score = score; - } - - public String getMethod() { - return method; - } - - public void setMethod(String method) { - this.method = method; - } - - @JsonProperty("pValue") - public BigDecimal getpValue() { - return pValue; - } - - public void setpValue(BigDecimal pValue) { - this.pValue = pValue; - } - -} diff --git a/src/main/java/org/cbioportal/model/ClinicalEvent.java b/src/main/java/org/cbioportal/model/ClinicalEvent.java deleted file mode 100644 index c98a7ea95f0..00000000000 --- a/src/main/java/org/cbioportal/model/ClinicalEvent.java +++ /dev/null @@ -1,89 +0,0 @@ -package org.cbioportal.model; - -import jakarta.validation.constraints.NotNull; - -import java.util.List; -import java.util.Objects; - -public class ClinicalEvent extends UniqueKeyBase { - - private Integer clinicalEventId; - @NotNull - private String studyId; - @NotNull - private String patientId; - @NotNull - private String eventType; - private Integer startDate; - private Integer stopDate; - private List attributes; - - public Integer getClinicalEventId() { - return clinicalEventId; - } - - public void setClinicalEventId(Integer clinicalEventId) { - this.clinicalEventId = clinicalEventId; - } - - public String getStudyId() { - return studyId; - } - - public void setStudyId(String studyId) { - this.studyId = studyId; - } - - public String getPatientId() { - return patientId; - } - - public void setPatientId(String patientId) { - this.patientId = patientId; - } - - public String getEventType() { - return eventType; - } - - public void setEventType(String eventType) { - this.eventType = eventType; - } - - public Integer getStartDate() { - return startDate; - } - - public void setStartDate(Integer startDate) { - this.startDate = startDate; - } - - public Integer getStopDate() { - return stopDate; - } - - public void setStopDate(Integer stopDate) { - this.stopDate = stopDate; - } - - public List getAttributes() { - return attributes; - } - - public void setAttributes(List attributes) { - this.attributes = attributes; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - ClinicalEvent that = (ClinicalEvent) o; - return Objects.equals(clinicalEventId, that.clinicalEventId) && Objects.equals(studyId, that.studyId) && Objects.equals(patientId, that.patientId) && Objects.equals(eventType, that.eventType) && Objects.equals(startDate, that.startDate) && Objects.equals(stopDate, that.stopDate) && Objects.equals(attributes, that.attributes); - } - - @Override - public int hashCode() { - return Objects.hash(clinicalEventId, studyId, patientId, eventType, startDate, stopDate, attributes); - } -} diff --git a/src/main/java/org/cbioportal/model/ClinicalEventData.java b/src/main/java/org/cbioportal/model/ClinicalEventData.java deleted file mode 100644 index 6430954af39..00000000000 --- a/src/main/java/org/cbioportal/model/ClinicalEventData.java +++ /dev/null @@ -1,37 +0,0 @@ -package org.cbioportal.model; - -import java.io.Serializable; -import jakarta.validation.constraints.NotNull; - -public class ClinicalEventData implements Serializable { - - private Integer clinicalEventId; - @NotNull - private String key; - @NotNull - private String value; - - public Integer getClinicalEventId() { - return clinicalEventId; - } - - public void setClinicalEventId(Integer clinicalEventId) { - this.clinicalEventId = clinicalEventId; - } - - public String getKey() { - return key; - } - - public void setKey(String key) { - this.key = key; - } - - public String getValue() { - return value; - } - - public void setValue(String value) { - this.value = value; - } -} diff --git a/src/main/java/org/cbioportal/model/ClinicalEventKeyCode.java b/src/main/java/org/cbioportal/model/ClinicalEventKeyCode.java deleted file mode 100644 index 3808f8aed10..00000000000 --- a/src/main/java/org/cbioportal/model/ClinicalEventKeyCode.java +++ /dev/null @@ -1,34 +0,0 @@ -package org.cbioportal.model; - -/** - * Clinical event data objects are key value pairs. - * Lots of different services consume specific keys. This is an attempt - * to keep those key constants in one enum. - */ -public enum ClinicalEventKeyCode { - Agent("AGENT", null), AgentClass ("AGENT_CLASS", null), AgentTarget("AGENT_TARGET", ", *"); - - private final String key; - private final String delimiter; - - ClinicalEventKeyCode(String key, String delimiter) { - this.key = key; - this.delimiter = delimiter; - } - - public String getKey() { - return key; - } - - public String getPropertyReference() { - return name().toLowerCase(); - } - - public String getDelimiter() { - return delimiter; - } - - public boolean isDelimited() { - return delimiter != null; - } -} diff --git a/src/main/java/org/cbioportal/model/ClinicalEventSample.java b/src/main/java/org/cbioportal/model/ClinicalEventSample.java deleted file mode 100644 index 75d53fc84f7..00000000000 --- a/src/main/java/org/cbioportal/model/ClinicalEventSample.java +++ /dev/null @@ -1,62 +0,0 @@ -package org.cbioportal.model; - -import java.util.Objects; -import java.io.Serializable; - -public class ClinicalEventSample implements Serializable { - private String patientId; - private String sampleId; - private String studyId; - private Integer timeTaken; - - public String getPatientId() { - return patientId; - } - - public void setPatientId(String patientId) { - this.patientId = patientId; - } - - public String getSampleId() { - return sampleId; - } - - public void setSampleId(String sampleId) { - this.sampleId = sampleId; - } - - public Integer getTimeTaken() { - return timeTaken; - } - - public void setTimeTaken(Integer timeTaken) { - this.timeTaken = timeTaken; - } - - public String getStudyId() { - return studyId; - } - - public void setStudyId(String studyId) { - this.studyId = studyId; - } - - public String key() { - return getSampleId() + getStudyId(); - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - ClinicalEventSample that = (ClinicalEventSample) o; - return getPatientId().equals(that.getPatientId()) && - getSampleId().equals(that.getSampleId()) && - getStudyId().equals(that.getStudyId()); - } - - @Override - public int hashCode() { - return Objects.hash(getPatientId(), getSampleId(), getStudyId()); - } -} diff --git a/src/main/java/org/cbioportal/model/ClinicalEventTypeCount.java b/src/main/java/org/cbioportal/model/ClinicalEventTypeCount.java deleted file mode 100644 index 95d1e129fb5..00000000000 --- a/src/main/java/org/cbioportal/model/ClinicalEventTypeCount.java +++ /dev/null @@ -1,29 +0,0 @@ -package org.cbioportal.model; - -import java.io.Serializable; - -public class ClinicalEventTypeCount implements Serializable { - private String eventType; - private Integer count; - - public ClinicalEventTypeCount(String eventType, Integer count) { - this.eventType = eventType; - this.count = count; - } - - public String getEventType() { - return eventType; - } - - public void setEventType(String eventType) { - this.eventType = eventType; - } - - public Integer getCount() { - return count; - } - - public void setCount(Integer count) { - this.count = count; - } -} diff --git a/src/main/java/org/cbioportal/model/ClinicalViolinPlotBoxData.java b/src/main/java/org/cbioportal/model/ClinicalViolinPlotBoxData.java deleted file mode 100644 index c2e24d4d4e2..00000000000 --- a/src/main/java/org/cbioportal/model/ClinicalViolinPlotBoxData.java +++ /dev/null @@ -1,68 +0,0 @@ -package org.cbioportal.model; - -import java.io.Serializable; - -public class ClinicalViolinPlotBoxData implements Serializable { - private double whiskerLower; - private double whiskerUpper; - private double median; - private double q1; - private double q3; - - @Override - public String toString() { - return "ClinicalViolinPlotBoxData{" + - "whiskerLower=" + whiskerLower + - ", whiskerUpper=" + whiskerUpper + - ", median=" + median + - ", q1=" + q1 + - ", q3=" + q3 + - '}'; - } - - public double getWhiskerLower() { - return whiskerLower; - } - - public void setWhiskerLower(double whiskerLower) { - this.whiskerLower = whiskerLower; - } - - public double getWhiskerUpper() { - return whiskerUpper; - } - - public void setWhiskerUpper(double whiskerUpper) { - this.whiskerUpper = whiskerUpper; - } - - public double getMedian() { - return median; - } - - public void setMedian(double median) { - this.median = median; - } - - public double getQ1() { - return q1; - } - - public void setQ1(double q1) { - this.q1 = q1; - } - - public double getQ3() { - return q3; - } - - public void setQ3(double q3) { - this.q3 = q3; - } - - public ClinicalViolinPlotBoxData limitWhiskers(ClinicalViolinPlotData d) { - this.setWhiskerLower(Math.max(this.getWhiskerLower(), d.getAxisStart())); - this.setWhiskerUpper(Math.min(this.getWhiskerUpper(), d.getAxisEnd())); - return this; - } -} diff --git a/src/main/java/org/cbioportal/model/ClinicalViolinPlotData.java b/src/main/java/org/cbioportal/model/ClinicalViolinPlotData.java deleted file mode 100644 index 452cabf0bcd..00000000000 --- a/src/main/java/org/cbioportal/model/ClinicalViolinPlotData.java +++ /dev/null @@ -1,44 +0,0 @@ -package org.cbioportal.model; - -import java.io.Serializable; -import java.util.List; - -public class ClinicalViolinPlotData implements Serializable { - private List rows; - private Double axisStart; - private Double axisEnd; - - @Override - public String toString() { - return "ClinicalViolinPlotData{" + - "rows=" + rows + - ", axisStart=" + axisStart + - ", axisEnd=" + axisEnd + - '}'; - } - - - public List getRows() { - return rows; - } - - public void setRows(List rows) { - this.rows = rows; - } - - public Double getAxisStart() { - return axisStart; - } - - public void setAxisStart(Double axisStart) { - this.axisStart = axisStart; - } - - public Double getAxisEnd() { - return axisEnd; - } - - public void setAxisEnd(Double axisEnd) { - this.axisEnd = axisEnd; - } -} diff --git a/src/main/java/org/cbioportal/model/ClinicalViolinPlotIndividualPoint.java b/src/main/java/org/cbioportal/model/ClinicalViolinPlotIndividualPoint.java deleted file mode 100644 index 7cff49930b0..00000000000 --- a/src/main/java/org/cbioportal/model/ClinicalViolinPlotIndividualPoint.java +++ /dev/null @@ -1,42 +0,0 @@ -package org.cbioportal.model; - -import java.io.Serializable; - -public class ClinicalViolinPlotIndividualPoint implements Serializable { - private String sampleId; - private String studyId; - private double value; - - @Override - public String toString() { - return "ClinicalViolinPlotIndividualPoint{" + - "sampleId='" + sampleId + '\'' + - ", studyId='" + studyId + '\'' + - ", value=" + value + - '}'; - } - - public String getSampleId() { - return sampleId; - } - - public void setSampleId(String sampleId) { - this.sampleId = sampleId; - } - - public String getStudyId() { - return studyId; - } - - public void setStudyId(String studyId) { - this.studyId = studyId; - } - - public double getValue() { - return value; - } - - public void setValue(double value) { - this.value = value; - } -} diff --git a/src/main/java/org/cbioportal/model/ClinicalViolinPlotRowData.java b/src/main/java/org/cbioportal/model/ClinicalViolinPlotRowData.java deleted file mode 100644 index 3a2ef647e35..00000000000 --- a/src/main/java/org/cbioportal/model/ClinicalViolinPlotRowData.java +++ /dev/null @@ -1,64 +0,0 @@ -package org.cbioportal.model; - -import java.io.Serializable; -import java.util.List; - -public class ClinicalViolinPlotRowData implements Serializable { - private String category; - private Integer numSamples; - private List curveData; - private ClinicalViolinPlotBoxData boxData; - private List individualPoints; - - @Override - public String toString() { - return "ClinicalViolinPlotRowData{" + - "category='" + category + '\'' + - ", numSamples=" + numSamples + - ", curveData=" + curveData + - ", boxData=" + boxData + - ", individualPoints=" + individualPoints + - '}'; - } - - public String getCategory() { - return category; - } - - public void setCategory(String category) { - this.category = category; - } - - public Integer getNumSamples() { - return numSamples; - } - - public void setNumSamples(Integer numSamples) { - this.numSamples = numSamples; - } - - public List getCurveData() { - return curveData; - } - - public void setCurveData(List curveData) { - this.curveData = curveData; - } - - public ClinicalViolinPlotBoxData getBoxData() { - return boxData; - } - - public void setBoxData(ClinicalViolinPlotBoxData boxData) { - this.boxData = boxData; - } - - public List getIndividualPoints() { - return individualPoints; - } - - public void setIndividualPoints(List individualPoints) { - this.individualPoints = individualPoints; - } - -} diff --git a/src/main/java/org/cbioportal/model/CoExpression.java b/src/main/java/org/cbioportal/model/CoExpression.java deleted file mode 100644 index 22fdec80784..00000000000 --- a/src/main/java/org/cbioportal/model/CoExpression.java +++ /dev/null @@ -1,52 +0,0 @@ -package org.cbioportal.model; - -import java.io.Serializable; -import java.math.BigDecimal; - -import com.fasterxml.jackson.annotation.JsonProperty; -import jakarta.validation.constraints.NotNull; - -public class CoExpression implements Serializable { - - @NotNull - private String geneticEntityId; - @NotNull - private EntityType geneticEntityType; - @NotNull - private BigDecimal spearmansCorrelation; - @NotNull - private BigDecimal pValue; - - public String getGeneticEntityId() { - return geneticEntityId; - } - - public void setGeneticEntityId(String geneticEntityId) { - this.geneticEntityId = geneticEntityId; - } - - public EntityType getGeneticEntityType() { - return geneticEntityType; - } - - public void setGeneticEntityType(EntityType geneticEntityType) { - this.geneticEntityType = geneticEntityType; - } - - public BigDecimal getSpearmansCorrelation() { - return spearmansCorrelation; - } - - public void setSpearmansCorrelation(BigDecimal spearmansCorrelation) { - this.spearmansCorrelation = spearmansCorrelation; - } - - @JsonProperty("pValue") - public BigDecimal getpValue() { - return pValue; - } - - public void setpValue(BigDecimal pValue) { - this.pValue = pValue; - } -} diff --git a/src/main/java/org/cbioportal/model/CopyNumberCount.java b/src/main/java/org/cbioportal/model/CopyNumberCount.java deleted file mode 100644 index 3748da9228c..00000000000 --- a/src/main/java/org/cbioportal/model/CopyNumberCount.java +++ /dev/null @@ -1,58 +0,0 @@ -package org.cbioportal.model; - -import java.io.Serializable; -import jakarta.validation.constraints.NotNull; - -public class CopyNumberCount implements Serializable { - - @NotNull - private String molecularProfileId; - @NotNull - private Integer entrezGeneId; - @NotNull - private Integer alteration; - @NotNull - private Integer numberOfSamples; - @NotNull - private Integer numberOfSamplesWithAlterationInGene; - - public String getMolecularProfileId() { - return molecularProfileId; - } - - public void setMolecularProfileId(String molecularProfileId) { - this.molecularProfileId = molecularProfileId; - } - - public Integer getEntrezGeneId() { - return entrezGeneId; - } - - public void setEntrezGeneId(Integer entrezGeneId) { - this.entrezGeneId = entrezGeneId; - } - - public Integer getAlteration() { - return alteration; - } - - public void setAlteration(Integer alteration) { - this.alteration = alteration; - } - - public Integer getNumberOfSamples() { - return numberOfSamples; - } - - public void setNumberOfSamples(Integer numberOfSamples) { - this.numberOfSamples = numberOfSamples; - } - - public Integer getNumberOfSamplesWithAlterationInGene() { - return numberOfSamplesWithAlterationInGene; - } - - public void setNumberOfSamplesWithAlterationInGene(Integer numberOfSamplesWithAlterationInGene) { - this.numberOfSamplesWithAlterationInGene = numberOfSamplesWithAlterationInGene; - } -} diff --git a/src/main/java/org/cbioportal/model/CopyNumberCountByGene.java b/src/main/java/org/cbioportal/model/CopyNumberCountByGene.java deleted file mode 100644 index ef1143066e7..00000000000 --- a/src/main/java/org/cbioportal/model/CopyNumberCountByGene.java +++ /dev/null @@ -1,30 +0,0 @@ -package org.cbioportal.model; - -import java.io.Serializable; - -public class CopyNumberCountByGene extends AlterationCountByGene implements Serializable { - - private Integer alteration; - private String cytoband; - - public Integer getAlteration() { - return alteration; - } - - public void setAlteration(Integer alteration) { - this.alteration = alteration; - } - - public String getCytoband() { - return cytoband; - } - - public void setCytoband(String cytoband) { - this.cytoband = cytoband; - } - - @Override - public String getUniqueEventKey() { - return getEntrezGeneId().toString() + getAlteration().toString(); - } -} diff --git a/src/main/java/org/cbioportal/model/CopyNumberSeg.java b/src/main/java/org/cbioportal/model/CopyNumberSeg.java deleted file mode 100644 index ea304052666..00000000000 --- a/src/main/java/org/cbioportal/model/CopyNumberSeg.java +++ /dev/null @@ -1,115 +0,0 @@ -package org.cbioportal.model; - -import java.math.BigDecimal; -import jakarta.validation.constraints.NotNull; - -public class CopyNumberSeg extends UniqueKeyBase { - - private Long segId; - private Integer cancerStudyId; - @NotNull - private String cancerStudyIdentifier; - private Integer sampleId; - @NotNull - private String sampleStableId; - @NotNull - private String patientId; - @NotNull - private String chr; - @NotNull - private Integer start; - @NotNull - private Integer end; - @NotNull - private Integer numProbes; - @NotNull - private BigDecimal segmentMean; - - public Long getSegId() { - return segId; - } - - public void setSegId(Long segId) { - this.segId = segId; - } - - public Integer getCancerStudyId() { - return cancerStudyId; - } - - public void setCancerStudyId(Integer cancerStudyId) { - this.cancerStudyId = cancerStudyId; - } - - public String getCancerStudyIdentifier() { - return cancerStudyIdentifier; - } - - public void setCancerStudyIdentifier(String cancerStudyIdentifier) { - this.cancerStudyIdentifier = cancerStudyIdentifier; - } - - public Integer getSampleId() { - return sampleId; - } - - public void setSampleId(Integer sampleId) { - this.sampleId = sampleId; - } - - public String getSampleStableId() { - return sampleStableId; - } - - public void setSampleStableId(String sampleStableId) { - this.sampleStableId = sampleStableId; - } - - public String getPatientId() { - return patientId; - } - - public void setPatientId(String patientId) { - this.patientId = patientId; - } - - public String getChr() { - return chr; - } - - public void setChr(String chr) { - this.chr = chr; - } - - public Integer getStart() { - return start; - } - - public void setStart(Integer start) { - this.start = start; - } - - public Integer getEnd() { - return end; - } - - public void setEnd(Integer end) { - this.end = end; - } - - public Integer getNumProbes() { - return numProbes; - } - - public void setNumProbes(Integer numProbes) { - this.numProbes = numProbes; - } - - public BigDecimal getSegmentMean() { - return segmentMean; - } - - public void setSegmentMean(BigDecimal segmentMean) { - this.segmentMean = segmentMean; - } -} diff --git a/src/main/java/org/cbioportal/model/CosmicMutation.java b/src/main/java/org/cbioportal/model/CosmicMutation.java deleted file mode 100644 index 2656205c146..00000000000 --- a/src/main/java/org/cbioportal/model/CosmicMutation.java +++ /dev/null @@ -1,47 +0,0 @@ -package org.cbioportal.model; - -import java.io.Serializable; -import jakarta.validation.constraints.NotNull; - -public class CosmicMutation implements Serializable { - - @NotNull - private String cosmicMutationId; - @NotNull - private String proteinChange; - private String keyword; - @NotNull - private Integer count; - - public String getCosmicMutationId() { - return cosmicMutationId; - } - - public void setCosmicMutationId(String cosmicMutationId) { - this.cosmicMutationId = cosmicMutationId; - } - - public String getProteinChange() { - return proteinChange; - } - - public void setProteinChange(String proteinChange) { - this.proteinChange = proteinChange; - } - - public String getKeyword() { - return keyword; - } - - public void setKeyword(String keyword) { - this.keyword = keyword; - } - - public Integer getCount() { - return count; - } - - public void setCount(Integer count) { - this.count = count; - } -} diff --git a/src/main/java/org/cbioportal/model/CountSummary.java b/src/main/java/org/cbioportal/model/CountSummary.java deleted file mode 100644 index 3466117a2ba..00000000000 --- a/src/main/java/org/cbioportal/model/CountSummary.java +++ /dev/null @@ -1,44 +0,0 @@ -package org.cbioportal.model; - -import java.io.Serializable; - -import jakarta.validation.constraints.NotNull; - -/** - * - * @author ochoaa - */ -public class CountSummary implements Serializable { - - @NotNull - private String name; - @NotNull - private Integer alteredCount; - @NotNull - private Integer profiledCount; - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public Integer getAlteredCount() { - return alteredCount; - } - - public void setAlteredCount(Integer alteredCount) { - this.alteredCount = alteredCount; - } - - public Integer getProfiledCount() { - return profiledCount; - } - - public void setProfiledCount(Integer profiledCount) { - this.profiledCount = profiledCount; - } - -} diff --git a/src/main/java/org/cbioportal/model/CustomDriverAnnotationReport.java b/src/main/java/org/cbioportal/model/CustomDriverAnnotationReport.java deleted file mode 100644 index e86668f82e3..00000000000 --- a/src/main/java/org/cbioportal/model/CustomDriverAnnotationReport.java +++ /dev/null @@ -1,24 +0,0 @@ -package org.cbioportal.model; - -import java.io.Serializable; -import java.util.Set; - -public class CustomDriverAnnotationReport implements Serializable { - private static final long serialVersionUID = 1L; - - private final boolean hasBinary; - private final Set tiers; - - public CustomDriverAnnotationReport(boolean hasBinary, Set tiers) { - this.hasBinary = hasBinary; - this.tiers = tiers; - } - - public boolean getHasBinary() { - return hasBinary; - } - - public Set getTiers() { - return tiers; - } -} \ No newline at end of file diff --git a/src/main/java/org/cbioportal/model/DataAccessToken.java b/src/main/java/org/cbioportal/model/DataAccessToken.java deleted file mode 100644 index 0895475428d..00000000000 --- a/src/main/java/org/cbioportal/model/DataAccessToken.java +++ /dev/null @@ -1,75 +0,0 @@ -package org.cbioportal.model; - -import java.io.Serializable; -import java.util.Date; - -public class DataAccessToken implements Serializable { - - private static final long serialVersionUID = 1L; - - private String token; - private String username; - private Date expiration; - private Date creation; - - public DataAccessToken() {} - - public DataAccessToken(String token) { - this.token = token; - } - - public DataAccessToken(String token, String username, Date expiration, Date creation) { - this.token = token; - this.username = username; - this.expiration = expiration; - this.creation = creation; - } - - public String getToken() { - return token; - } - - public void setToken(String token) { - this.token = token; - } - - public String getUsername() { - return username; - } - - public void setUsername(String username) { - this.username = username; - } - - public Date getExpiration() { - return expiration; - } - - public void setExpiration(Date expiration) { - this.expiration = expiration; - } - - public Date getCreation() { - return creation; - } - - public void setCreation(Date creation) { - this.creation = creation; - } - - public boolean hasEarlierExpirationThanToken(DataAccessToken dataAccessToken) { - return (this.expiration != null && this.expiration.before(dataAccessToken.getExpiration())); - } - - @Override - public String toString() { - StringBuilder b = new StringBuilder().append("token: ").append(token).append("\n"); - if (creation != null) { - b.append("creation_date: ").append(creation.toString()).append("\n"); - } - if (expiration != null) { - b.append("expiration_date: ").append(expiration.toString()).append("\n"); - } - return b.toString(); - } -} diff --git a/src/main/java/org/cbioportal/model/DataBin.java b/src/main/java/org/cbioportal/model/DataBin.java deleted file mode 100644 index f39c57704da..00000000000 --- a/src/main/java/org/cbioportal/model/DataBin.java +++ /dev/null @@ -1,44 +0,0 @@ -package org.cbioportal.model; - -import java.io.Serializable; -import java.math.BigDecimal; - -public class DataBin implements Serializable { - - private String specialValue; - private BigDecimal start; - private BigDecimal end; - private Integer count; - - public String getSpecialValue() { - return specialValue; - } - - public void setSpecialValue(String specialValue) { - this.specialValue = specialValue; - } - - public BigDecimal getStart() { - return start; - } - - public void setStart(BigDecimal start) { - this.start = start; - } - - public BigDecimal getEnd() { - return end; - } - - public void setEnd(BigDecimal end) { - this.end = end; - } - - public Integer getCount() { - return count; - } - - public void setCount(Integer count) { - this.count = count; - } -} diff --git a/src/main/java/org/cbioportal/model/DensityPlotBin.java b/src/main/java/org/cbioportal/model/DensityPlotBin.java deleted file mode 100644 index 6bff6384fbe..00000000000 --- a/src/main/java/org/cbioportal/model/DensityPlotBin.java +++ /dev/null @@ -1,71 +0,0 @@ -package org.cbioportal.model; - -import java.io.Serializable; -import java.math.BigDecimal; - -public class DensityPlotBin implements Serializable { - - private Integer count; - private BigDecimal binX; - private BigDecimal binY; - private BigDecimal minX; - private BigDecimal maxX; - private BigDecimal minY; - private BigDecimal maxY; - - public Integer getCount() { - return count; - } - - public void setCount(Integer count) { - this.count = count; - } - - public BigDecimal getBinX() { - return binX; - } - - public void setBinX(BigDecimal binX) { - this.binX = binX; - } - - public BigDecimal getBinY() { - return binY; - } - - public void setBinY(BigDecimal binY) { - this.binY = binY; - } - - public BigDecimal getMinX() { - return minX; - } - - public void setMinX(BigDecimal minX) { - this.minX = minX; - } - - public BigDecimal getMaxX() { - return maxX; - } - - public void setMaxX(BigDecimal maxX) { - this.maxX = maxX; - } - - public BigDecimal getMinY() { - return minY; - } - - public void setMinY(BigDecimal minY) { - this.minY = minY; - } - - public BigDecimal getMaxY() { - return maxY; - } - - public void setMaxY(BigDecimal maxY) { - this.maxY = maxY; - } -} diff --git a/src/main/java/org/cbioportal/model/DensityPlotData.java b/src/main/java/org/cbioportal/model/DensityPlotData.java deleted file mode 100644 index 06adc10bca5..00000000000 --- a/src/main/java/org/cbioportal/model/DensityPlotData.java +++ /dev/null @@ -1,40 +0,0 @@ -package org.cbioportal.model; - -import jakarta.validation.constraints.NotNull; -import java.io.Serializable; -import java.math.BigDecimal; -import java.util.ArrayList; -import java.util.List; - -public class DensityPlotData implements Serializable { - @NotNull - private List bins = new ArrayList<>(); - - private Double pearsonCorr; - - private Double spearmanCorr; - - public List getBins() { - return bins; - } - - public void setBins(List bins) { - this.bins = bins; - } - - public Double getPearsonCorr() { - return pearsonCorr; - } - - public void setPearsonCorr(Double pearsonCorr) { - this.pearsonCorr = pearsonCorr; - } - - public Double getSpearmanCorr() { - return spearmanCorr; - } - - public void setSpearmanCorr(Double spearmanCorr) { - this.spearmanCorr = spearmanCorr; - } -} diff --git a/src/main/java/org/cbioportal/model/DiscreteCopyNumberData.java b/src/main/java/org/cbioportal/model/DiscreteCopyNumberData.java deleted file mode 100644 index 11c20fe6068..00000000000 --- a/src/main/java/org/cbioportal/model/DiscreteCopyNumberData.java +++ /dev/null @@ -1,34 +0,0 @@ -package org.cbioportal.model; - -import com.fasterxml.jackson.annotation.JsonRawValue; - -import java.io.Serializable; - -import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.NotNull; - -public class DiscreteCopyNumberData extends Alteration implements Serializable { - @NotNull - private Integer alteration; - - @JsonRawValue - @Schema(type = "java.util.Map") - private Object annotationJson; - - public Integer getAlteration() { - return alteration; - } - - public void setAlteration(Integer alteration) { - this.alteration = alteration; - } - - public Object getAnnotationJson() { - return annotationJson; - } - - public void setAnnotationJson(String annotationJson) { - this.annotationJson = annotationJson; - } - -} diff --git a/src/main/java/org/cbioportal/model/EnrichmentType.java b/src/main/java/org/cbioportal/model/EnrichmentType.java deleted file mode 100644 index af13ab2020e..00000000000 --- a/src/main/java/org/cbioportal/model/EnrichmentType.java +++ /dev/null @@ -1,6 +0,0 @@ -package org.cbioportal.model; - -public enum EnrichmentType { - SAMPLE, - PATIENT -} diff --git a/src/main/java/org/cbioportal/model/EntityType.java b/src/main/java/org/cbioportal/model/EntityType.java deleted file mode 100644 index 507b9b6d090..00000000000 --- a/src/main/java/org/cbioportal/model/EntityType.java +++ /dev/null @@ -1,8 +0,0 @@ -package org.cbioportal.model; - -public enum EntityType { - GENE, - GENESET, - PHOSPHOPROTEIN, - GENERIC_ASSAY -} \ No newline at end of file diff --git a/src/main/java/org/cbioportal/model/ExpressionEnrichment.java b/src/main/java/org/cbioportal/model/ExpressionEnrichment.java deleted file mode 100644 index c6c562c4b64..00000000000 --- a/src/main/java/org/cbioportal/model/ExpressionEnrichment.java +++ /dev/null @@ -1,33 +0,0 @@ -package org.cbioportal.model; - -import java.io.Serializable; -import java.math.BigDecimal; -import java.util.List; - -import com.fasterxml.jackson.annotation.JsonProperty; -import jakarta.validation.constraints.NotNull; - -public class ExpressionEnrichment implements Serializable { - - @NotNull - private List groupsStatistics; - @NotNull - private BigDecimal pValue; - - public List getGroupsStatistics() { - return groupsStatistics; - } - - public void setGroupsStatistics(List groupsStatistics) { - this.groupsStatistics = groupsStatistics; - } - - @JsonProperty("pValue") - public BigDecimal getpValue() { - return pValue; - } - - public void setpValue(BigDecimal pValue) { - this.pValue = pValue; - } -} diff --git a/src/main/java/org/cbioportal/model/FractionGenomeAltered.java b/src/main/java/org/cbioportal/model/FractionGenomeAltered.java deleted file mode 100644 index f9e3d67fcdb..00000000000 --- a/src/main/java/org/cbioportal/model/FractionGenomeAltered.java +++ /dev/null @@ -1,48 +0,0 @@ -package org.cbioportal.model; - -import java.math.BigDecimal; -import jakarta.validation.constraints.NotNull; - -public class FractionGenomeAltered extends UniqueKeyBase { - - @NotNull - private String studyId; - @NotNull - private String sampleId; - @NotNull - private String patientId; - @NotNull - private BigDecimal value; - - public String getStudyId() { - return studyId; - } - - public void setStudyId(String studyId) { - this.studyId = studyId; - } - - public String getSampleId() { - return sampleId; - } - - public void setSampleId(String sampleId) { - this.sampleId = sampleId; - } - - public String getPatientId() { - return patientId; - } - - public void setPatientId(String patientId) { - this.patientId = patientId; - } - - public BigDecimal getValue() { - return value; - } - - public void setValue(BigDecimal value) { - this.value = value; - } -} diff --git a/src/main/java/org/cbioportal/model/Gene.java b/src/main/java/org/cbioportal/model/Gene.java deleted file mode 100644 index a2325da6856..00000000000 --- a/src/main/java/org/cbioportal/model/Gene.java +++ /dev/null @@ -1,43 +0,0 @@ -package org.cbioportal.model; - -import java.io.Serializable; -import jakarta.validation.constraints.NotNull; - -public class Gene implements Serializable { - - @NotNull - private Integer geneticEntityId; - @NotNull - private Integer entrezGeneId; - @NotNull - private String hugoGeneSymbol; - private String type; - - public Integer getGeneticEntityId() { return geneticEntityId; } - - public void setGeneticEntityId(Integer geneticEntityId) { this.geneticEntityId = geneticEntityId; } - - public Integer getEntrezGeneId() { - return entrezGeneId; - } - - public void setEntrezGeneId(Integer entrezGeneId) { - this.entrezGeneId = entrezGeneId; - } - - public String getHugoGeneSymbol() { - return hugoGeneSymbol; - } - - public void setHugoGeneSymbol(String hugoGeneSymbol) { - this.hugoGeneSymbol = hugoGeneSymbol; - } - - public String getType() { - return type; - } - - public void setType(String type) { - this.type = type; - } -} diff --git a/src/main/java/org/cbioportal/model/GeneAlias.java b/src/main/java/org/cbioportal/model/GeneAlias.java deleted file mode 100644 index 664a73cb831..00000000000 --- a/src/main/java/org/cbioportal/model/GeneAlias.java +++ /dev/null @@ -1,25 +0,0 @@ -package org.cbioportal.model; - -import java.io.Serializable; - -public class GeneAlias implements Serializable { - - private Integer entrezGeneId; - private String geneAlias; - - public Integer getEntrezGeneId() { - return entrezGeneId; - } - - public void setEntrezGeneId(Integer entrezGeneId) { - this.entrezGeneId = entrezGeneId; - } - - public String getGeneAlias() { - return geneAlias; - } - - public void setGeneAlias(String geneAlias) { - this.geneAlias = geneAlias; - } -} diff --git a/src/main/java/org/cbioportal/model/GeneFilter.java b/src/main/java/org/cbioportal/model/GeneFilter.java deleted file mode 100644 index ae6f62890dc..00000000000 --- a/src/main/java/org/cbioportal/model/GeneFilter.java +++ /dev/null @@ -1,28 +0,0 @@ -package org.cbioportal.model; - -import java.io.Serializable; -import java.util.List; -import java.util.Set; - -public class GeneFilter implements Serializable { - - private Set molecularProfileIds; - private List> geneQueries; - - public Set getMolecularProfileIds() { - return molecularProfileIds; - } - - public void setMolecularProfileIds(Set molecularProfileIds) { - this.molecularProfileIds = molecularProfileIds; - } - - public List> getGeneQueries() { - return geneQueries; - } - - public void setGeneQueries(List> geneQueries) { - this.geneQueries = geneQueries; - } - -} \ No newline at end of file diff --git a/src/main/java/org/cbioportal/model/GeneFilterQuery.java b/src/main/java/org/cbioportal/model/GeneFilterQuery.java deleted file mode 100644 index e8280b4ce27..00000000000 --- a/src/main/java/org/cbioportal/model/GeneFilterQuery.java +++ /dev/null @@ -1,57 +0,0 @@ -package org.cbioportal.model; - -import org.cbioportal.model.util.Select; - -import java.io.Serializable; -import java.util.List; - -public class GeneFilterQuery extends BaseAlterationFilter implements Serializable { - - private String hugoGeneSymbol; - private Integer entrezGeneId; - private List alterations; - - public GeneFilterQuery() {} - - public GeneFilterQuery(String hugoGeneSymbol, - Integer entrezGeneId, - List alterations, - boolean includeDriver, - boolean includeVUS, - boolean includeUnknownOncogenicity, - Select tiersSelect, - boolean includeUnknownTier, - boolean includeGermline, - boolean includeSomatic, - boolean includeUnknownStatus) { - super(includeDriver, includeVUS, includeUnknownOncogenicity, includeGermline, includeSomatic, includeUnknownStatus, tiersSelect, includeUnknownTier); - this.hugoGeneSymbol = hugoGeneSymbol; - this.entrezGeneId = entrezGeneId; - this.alterations = alterations; - } - - public String getHugoGeneSymbol() { - return hugoGeneSymbol; - } - - public void setHugoGeneSymbol(String hugoGeneSymbol) { - this.hugoGeneSymbol = hugoGeneSymbol; - } - - public Integer getEntrezGeneId() { - return entrezGeneId; - } - - public void setEntrezGeneId(int entrezGeneId) { - this.entrezGeneId = entrezGeneId; - } - - public List getAlterations() { - return alterations; - } - - public void setAlterations(List alterations) { - this.alterations = alterations; - } - -} diff --git a/src/main/java/org/cbioportal/model/GeneMolecularAlteration.java b/src/main/java/org/cbioportal/model/GeneMolecularAlteration.java deleted file mode 100644 index 05938ed539c..00000000000 --- a/src/main/java/org/cbioportal/model/GeneMolecularAlteration.java +++ /dev/null @@ -1,39 +0,0 @@ -package org.cbioportal.model; - -import java.io.Serializable; - -public class GeneMolecularAlteration extends MolecularAlteration implements Serializable { - - private String molecularProfileId; - private Integer entrezGeneId; - private Gene gene; - - public String getMolecularProfileId() { - return molecularProfileId; - } - - public void setMolecularProfileId(String molecularProfileId) { - this.molecularProfileId = molecularProfileId; - } - - public Integer getEntrezGeneId() { - return entrezGeneId; - } - - public void setEntrezGeneId(Integer entrezGeneId) { - this.entrezGeneId = entrezGeneId; - } - - public Gene getGene() { - return gene; - } - - public void setGene(Gene gene) { - this.gene = gene; - } - - @Override - public String getStableId() { - return entrezGeneId.toString(); - } -} diff --git a/src/main/java/org/cbioportal/model/GeneMolecularData.java b/src/main/java/org/cbioportal/model/GeneMolecularData.java deleted file mode 100644 index 6ce9e1cef68..00000000000 --- a/src/main/java/org/cbioportal/model/GeneMolecularData.java +++ /dev/null @@ -1,32 +0,0 @@ -package org.cbioportal.model; - -import java.io.Serializable; -import jakarta.validation.constraints.NotNull; - -public class GeneMolecularData extends MolecularData implements Serializable { - - @NotNull - private Integer entrezGeneId; - private Gene gene; - - public Integer getEntrezGeneId() { - return entrezGeneId; - } - - public void setEntrezGeneId(Integer entrezGeneId) { - this.entrezGeneId = entrezGeneId; - } - - public Gene getGene() { - return gene; - } - - public void setGene(Gene gene) { - this.gene = gene; - } - - @Override - public String getStableId() { - return entrezGeneId.toString(); - } -} diff --git a/src/main/java/org/cbioportal/model/GenePanel.java b/src/main/java/org/cbioportal/model/GenePanel.java deleted file mode 100644 index 6c47f89016d..00000000000 --- a/src/main/java/org/cbioportal/model/GenePanel.java +++ /dev/null @@ -1,46 +0,0 @@ -package org.cbioportal.model; - -import java.io.Serializable; -import java.util.List; -import jakarta.validation.constraints.NotNull; - -public class GenePanel implements Serializable { - - private Integer internalId; - @NotNull - private String stableId; - private String description; - private List genes; - - public Integer getInternalId() { - return internalId; - } - - public void setInternalId(Integer internalId) { - this.internalId = internalId; - } - - public String getStableId() { - return stableId; - } - - public void setStableId(String stableId) { - this.stableId = stableId; - } - - public String getDescription() { - return description; - } - - public void setDescription(String description) { - this.description = description; - } - - public List getGenes() { - return genes; - } - - public void setGenes(List genes) { - this.genes = genes; - } -} diff --git a/src/main/java/org/cbioportal/model/GenePanelData.java b/src/main/java/org/cbioportal/model/GenePanelData.java deleted file mode 100644 index ac1bfbf78b4..00000000000 --- a/src/main/java/org/cbioportal/model/GenePanelData.java +++ /dev/null @@ -1,66 +0,0 @@ -package org.cbioportal.model; - -import jakarta.validation.constraints.NotNull; - -public class GenePanelData extends UniqueKeyBase { - - @NotNull - private String molecularProfileId; - @NotNull - private String sampleId; - @NotNull - private String patientId; - @NotNull - private String studyId; - private String genePanelId; - @NotNull - private Boolean profiled; - - public String getMolecularProfileId() { - return molecularProfileId; - } - - public void setMolecularProfileId(String molecularProfileId) { - this.molecularProfileId = molecularProfileId; - } - - public String getSampleId() { - return sampleId; - } - - public void setSampleId(String sampleId) { - this.sampleId = sampleId; - } - - public String getPatientId() { - return patientId; - } - - public void setPatientId(String patientId) { - this.patientId = patientId; - } - - public String getStudyId() { - return studyId; - } - - public void setStudyId(String studyId) { - this.studyId = studyId; - } - - public String getGenePanelId() { - return genePanelId; - } - - public void setGenePanelId(String genePanelId) { - this.genePanelId = genePanelId; - } - - public Boolean getProfiled() { - return profiled; - } - - public void setProfiled(Boolean profiled) { - this.profiled = profiled; - } -} diff --git a/src/main/java/org/cbioportal/model/GenePanelToGene.java b/src/main/java/org/cbioportal/model/GenePanelToGene.java deleted file mode 100644 index b09698966f3..00000000000 --- a/src/main/java/org/cbioportal/model/GenePanelToGene.java +++ /dev/null @@ -1,37 +0,0 @@ -package org.cbioportal.model; - -import java.io.Serializable; -import jakarta.validation.constraints.NotNull; - -public class GenePanelToGene implements Serializable { - - private String genePanelId; - @NotNull - private Integer entrezGeneId; - @NotNull - private String hugoGeneSymbol; - - public String getGenePanelId() { - return genePanelId; - } - - public void setGenePanelId(String genePanelId) { - this.genePanelId = genePanelId; - } - - public Integer getEntrezGeneId() { - return entrezGeneId; - } - - public void setEntrezGeneId(Integer entrezGeneId) { - this.entrezGeneId = entrezGeneId; - } - - public String getHugoGeneSymbol() { - return hugoGeneSymbol; - } - - public void setHugoGeneSymbol(String hugoGeneSymbol) { - this.hugoGeneSymbol = hugoGeneSymbol; - } -} diff --git a/src/main/java/org/cbioportal/model/GenericAssayAdditionalProperty.java b/src/main/java/org/cbioportal/model/GenericAssayAdditionalProperty.java deleted file mode 100644 index 8fab77071aa..00000000000 --- a/src/main/java/org/cbioportal/model/GenericAssayAdditionalProperty.java +++ /dev/null @@ -1,39 +0,0 @@ -package org.cbioportal.model; - -import java.io.Serializable; - -public class GenericAssayAdditionalProperty implements Serializable { - private String name; - private String value; - private String stableId; - - public GenericAssayAdditionalProperty(String name, String value, String stableId) { - this.name = name; - this.value = value; - this.stableId = stableId; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String getValue() { - return value; - } - - public void setValue(String value) { - this.value = value; - } - - public String getStableId() { - return stableId; - } - - public void setStableId(String stableId) { - this.stableId = stableId; - } -} \ No newline at end of file diff --git a/src/main/java/org/cbioportal/model/GenericAssayBinaryEnrichment.java b/src/main/java/org/cbioportal/model/GenericAssayBinaryEnrichment.java deleted file mode 100644 index 24e84145227..00000000000 --- a/src/main/java/org/cbioportal/model/GenericAssayBinaryEnrichment.java +++ /dev/null @@ -1,19 +0,0 @@ -package org.cbioportal.model; - -import jakarta.validation.constraints.NotNull; -import java.math.BigDecimal; -import java.util.List; - -public class GenericAssayBinaryEnrichment extends GenericAssayEnrichment { - @NotNull - private List counts; - - public List getCounts() { - return counts; - } - - public void setCounts(List counts) { - this.counts = counts; - } - -} diff --git a/src/main/java/org/cbioportal/model/GenericAssayCategoricalEnrichment.java b/src/main/java/org/cbioportal/model/GenericAssayCategoricalEnrichment.java deleted file mode 100644 index afc72993136..00000000000 --- a/src/main/java/org/cbioportal/model/GenericAssayCategoricalEnrichment.java +++ /dev/null @@ -1,20 +0,0 @@ -package org.cbioportal.model; - -import com.fasterxml.jackson.annotation.JsonProperty; -import jakarta.validation.constraints.NotNull; -import java.math.BigDecimal; - -public class GenericAssayCategoricalEnrichment extends GenericAssayEnrichment { - @NotNull - private BigDecimal qValue; - - @JsonProperty("qValue") - public BigDecimal getqValue() { - return qValue; - } - - public void setqValue(BigDecimal qValue) { - this.qValue = qValue; - } - -} diff --git a/src/main/java/org/cbioportal/model/GenericAssayCountSummary.java b/src/main/java/org/cbioportal/model/GenericAssayCountSummary.java deleted file mode 100644 index 49edb224e4a..00000000000 --- a/src/main/java/org/cbioportal/model/GenericAssayCountSummary.java +++ /dev/null @@ -1,38 +0,0 @@ -package org.cbioportal.model; - -import jakarta.validation.constraints.NotNull; -import java.io.Serializable; - -public class GenericAssayCountSummary implements Serializable { - - @NotNull - private String name; - @NotNull - private Integer count; - @NotNull - private Integer totalCount; - - public Integer getCount() { - return count; - } - - public void setCount(Integer count) { - this.count = count; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public Integer getTotalCount() { - return totalCount; - } - - public void setTotalCount(Integer totalCount) { - this.totalCount = totalCount; - } -} diff --git a/src/main/java/org/cbioportal/model/GenericAssayData.java b/src/main/java/org/cbioportal/model/GenericAssayData.java deleted file mode 100644 index 3fd08f55e77..00000000000 --- a/src/main/java/org/cbioportal/model/GenericAssayData.java +++ /dev/null @@ -1,29 +0,0 @@ -package org.cbioportal.model; - -import java.io.Serializable; -import jakarta.validation.constraints.NotNull; - -public class GenericAssayData extends MolecularData implements Serializable { - - @NotNull - private String genericAssayStableId; - - /** - * @return the genericAssayStableId - */ - public String getGenericAssayStableId() { - return genericAssayStableId; - } - - /** - * @param genericAssayStableId the genericAssayStableId to set - */ - public void setGenericAssayStableId(String genericAssayStableId) { - this.genericAssayStableId = genericAssayStableId; - } - - @Override - public String getStableId() { - return genericAssayStableId; - } -} diff --git a/src/main/java/org/cbioportal/model/GenericAssayDataBin.java b/src/main/java/org/cbioportal/model/GenericAssayDataBin.java deleted file mode 100644 index 62b44070388..00000000000 --- a/src/main/java/org/cbioportal/model/GenericAssayDataBin.java +++ /dev/null @@ -1,25 +0,0 @@ -package org.cbioportal.model; - -import java.io.Serializable; - -public class GenericAssayDataBin extends DataBin implements Serializable { - private String stableId; - private String profileType; - - public String getStableId() { - return stableId; - } - - public void setStableId(String stableId) { - this.stableId = stableId; - } - - public String getProfileType() { - return profileType; - } - - public void setProfileType(String profileType) { - this.profileType = profileType; - } - -} diff --git a/src/main/java/org/cbioportal/model/GenericAssayDataCount.java b/src/main/java/org/cbioportal/model/GenericAssayDataCount.java deleted file mode 100644 index 62c14562fca..00000000000 --- a/src/main/java/org/cbioportal/model/GenericAssayDataCount.java +++ /dev/null @@ -1,33 +0,0 @@ -package org.cbioportal.model; - -import java.io.Serializable; - -public class GenericAssayDataCount implements Serializable { - - private String value; - private Integer count; - - public GenericAssayDataCount() {} - - public GenericAssayDataCount(String value, Integer count) { - this.value = value; - this.count = count; - } - - public String getValue() { - return value; - } - - public void setValue(String value) { - this.value = value; - } - - public Integer getCount() { - return count; - } - - public void setCount(Integer count) { - this.count = count; - } -} - diff --git a/src/main/java/org/cbioportal/model/GenericAssayDataCountItem.java b/src/main/java/org/cbioportal/model/GenericAssayDataCountItem.java deleted file mode 100644 index c272b617f87..00000000000 --- a/src/main/java/org/cbioportal/model/GenericAssayDataCountItem.java +++ /dev/null @@ -1,32 +0,0 @@ -package org.cbioportal.model; - -import java.io.Serializable; -import java.util.List; - -public class GenericAssayDataCountItem implements Serializable { - private String stableId; - private List counts; - - public GenericAssayDataCountItem() {} - - public GenericAssayDataCountItem(String stableId, List counts) { - this.stableId = stableId; - this.counts = counts; - } - - public String getStableId() { - return stableId; - } - - public void setStableId(String stableId) { - this.stableId = stableId; - } - - public List getCounts() { - return counts; - } - - public void setCounts(List counts) { - this.counts = counts; - } -} diff --git a/src/main/java/org/cbioportal/model/GenericAssayEnrichment.java b/src/main/java/org/cbioportal/model/GenericAssayEnrichment.java deleted file mode 100644 index 9116783494a..00000000000 --- a/src/main/java/org/cbioportal/model/GenericAssayEnrichment.java +++ /dev/null @@ -1,57 +0,0 @@ -package org.cbioportal.model; - -import java.io.Serializable; -import java.math.BigDecimal; -import java.util.HashMap; - -import com.fasterxml.jackson.annotation.JsonProperty; -import jakarta.validation.constraints.NotNull; - -public class GenericAssayEnrichment extends ExpressionEnrichment implements Serializable { - - @NotNull - private String stableId; - @NotNull - private String name; - @NotNull - private BigDecimal qValue; - @NotNull - private HashMap genericEntityMetaProperties; - - public String getStableId() { - return stableId; - } - - public void setStableId(String stableId) { - this.stableId = stableId; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public HashMap getGenericEntityMetaProperties() { - return genericEntityMetaProperties; - } - - public void setGenericEntityMetaProperties(HashMap genericEntityMetaProperties) { - this.genericEntityMetaProperties = genericEntityMetaProperties; - } - - @JsonProperty("qValue") - public BigDecimal getqValue() { - return qValue; - } - - public void setqValue(BigDecimal qValue) { - this.qValue = qValue; - } - - public static int compare(GenericAssayEnrichment c1, GenericAssayEnrichment c2) { - return c1.getpValue().compareTo(c2.getpValue()); - } -} diff --git a/src/main/java/org/cbioportal/model/GenericAssayMolecularAlteration.java b/src/main/java/org/cbioportal/model/GenericAssayMolecularAlteration.java deleted file mode 100644 index 24ddbcd09bb..00000000000 --- a/src/main/java/org/cbioportal/model/GenericAssayMolecularAlteration.java +++ /dev/null @@ -1,42 +0,0 @@ -package org.cbioportal.model; - -import java.io.Serializable; - -public class GenericAssayMolecularAlteration extends MolecularAlteration implements Serializable { - - private String molecularProfileId; - private String genericAssayStableId; - - /** - * @return the genericAssayStableId - */ - public String getGenericAssayStableId() { - return genericAssayStableId; - } - - /** - * @param genericAssayStableId the genericAssayStableId to set - */ - public void setGenericAssayStableId(String genericAssayStableId) { - this.genericAssayStableId = genericAssayStableId; - } - - /** - * @return the molecularProfileId - */ - public String getMolecularProfileId() { - return molecularProfileId; - } - - /** - * @param molecularProfileId the molecularProfileId to set - */ - public void setMolecularProfileId(String molecularProfileId) { - this.molecularProfileId = molecularProfileId; - } - - @Override - public String getStableId() { - return genericAssayStableId; - } -} diff --git a/src/main/java/org/cbioportal/model/GenericEntityProperty.java b/src/main/java/org/cbioportal/model/GenericEntityProperty.java deleted file mode 100644 index da2fbac1631..00000000000 --- a/src/main/java/org/cbioportal/model/GenericEntityProperty.java +++ /dev/null @@ -1,39 +0,0 @@ -package org.cbioportal.model; - -import java.io.Serializable; - -public class GenericEntityProperty implements Serializable { - private String name; - private String value; - private Integer entityId; - - public GenericEntityProperty(String name, String value, Integer entityId) { - this.name = name; - this.value = value; - this.entityId = entityId; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String getValue() { - return value; - } - - public void setValue(String value) { - this.value = value; - } - - public Integer getEntityId() { - return entityId; - } - - public void setEntityId(Integer entityId) { - this.entityId = entityId; - } -} diff --git a/src/main/java/org/cbioportal/model/Geneset.java b/src/main/java/org/cbioportal/model/Geneset.java deleted file mode 100644 index 5fc022ae804..00000000000 --- a/src/main/java/org/cbioportal/model/Geneset.java +++ /dev/null @@ -1,71 +0,0 @@ -package org.cbioportal.model; - -import java.io.Serializable; - -public class Geneset implements Serializable { - - private Integer internalId; - private String genesetId; - private String name; - private String description; - private String refLink; - //representative score (can be set when retrieved in study context): - private Double representativeScore; - private Double representativePvalue; - - public Integer getInternalId() { - return internalId; - } - - public void setInternalId(Integer internalId) { - this.internalId = internalId; - } - - public String getGenesetId() { - return genesetId; - } - - public void setGenesetId(String genesetId) { - this.genesetId = genesetId; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String getDescription() { - return description; - } - - public void setDescription(String description) { - this.description = description; - } - - public String getRefLink() { - return refLink; - } - - public void setRefLink(String refLink) { - this.refLink = refLink; - } - - public Double getRepresentativeScore() { - return representativeScore; - } - - public void setRepresentativeScore(Double representativeScore) { - this.representativeScore = representativeScore; - } - - public Double getRepresentativePvalue() { - return representativePvalue; - } - - public void setRepresentativePvalue(Double representativePvalue) { - this.representativePvalue = representativePvalue; - } -} \ No newline at end of file diff --git a/src/main/java/org/cbioportal/model/GenesetCorrelation.java b/src/main/java/org/cbioportal/model/GenesetCorrelation.java deleted file mode 100644 index 6bfe13ba346..00000000000 --- a/src/main/java/org/cbioportal/model/GenesetCorrelation.java +++ /dev/null @@ -1,52 +0,0 @@ -package org.cbioportal.model; - -import java.io.Serializable; - -public class GenesetCorrelation implements Serializable { - - private Integer entrezGeneId; - private String hugoGeneSymbol; - private Double correlationValue; - private String expressionMolecularProfileId; - private String zScoreMolecularProfileId; - - public Integer getEntrezGeneId() { - return entrezGeneId; - } - - public void setEntrezGeneId(Integer entrezGeneId) { - this.entrezGeneId = entrezGeneId; - } - - public String getHugoGeneSymbol() { - return hugoGeneSymbol; - } - - public void setHugoGeneSymbol(String hugoGeneSymbol) { - this.hugoGeneSymbol = hugoGeneSymbol; - } - - public Double getCorrelationValue() { - return correlationValue; - } - - public void setCorrelationValue(Double correlationValue) { - this.correlationValue = correlationValue; - } - - public String getExpressionMolecularProfileId() { - return expressionMolecularProfileId; - } - - public void setExpressionMolecularProfileId(String expressionMolecularProfileId) { - this.expressionMolecularProfileId = expressionMolecularProfileId; - } - - public String getzScoreMolecularProfileId() { - return zScoreMolecularProfileId; - } - - public void setzScoreMolecularProfileId(String zScoreMolecularProfileId) { - this.zScoreMolecularProfileId = zScoreMolecularProfileId; - } -} diff --git a/src/main/java/org/cbioportal/model/GenesetHierarchyInfo.java b/src/main/java/org/cbioportal/model/GenesetHierarchyInfo.java deleted file mode 100644 index dac02f3d454..00000000000 --- a/src/main/java/org/cbioportal/model/GenesetHierarchyInfo.java +++ /dev/null @@ -1,53 +0,0 @@ -package org.cbioportal.model; - -import java.io.Serializable; -import java.util.List; - -public class GenesetHierarchyInfo implements Serializable { - - private Integer nodeId; - private String nodeName; - private Integer parentId; - private String parentNodeName; - private List genesets; - - public Integer getNodeId() { - return nodeId; - } - - public void setNodeId(Integer nodeId) { - this.nodeId = nodeId; - } - - public Integer getParentId() { - return parentId; - } - - public void setParentId(Integer parentId) { - this.parentId = parentId; - } - - public String getNodeName() { - return nodeName; - } - - public void setNodeName(String nodeName) { - this.nodeName = nodeName; - } - - public String getParentNodeName() { - return parentNodeName; - } - - public void setParentNodeName(String parentNodeName) { - this.parentNodeName = parentNodeName; - } - - public List getGenesets() { - return genesets; - } - - public void setGenesets(List genesets) { - this.genesets = genesets; - } -} diff --git a/src/main/java/org/cbioportal/model/GenesetMolecularAlteration.java b/src/main/java/org/cbioportal/model/GenesetMolecularAlteration.java deleted file mode 100644 index e4720949596..00000000000 --- a/src/main/java/org/cbioportal/model/GenesetMolecularAlteration.java +++ /dev/null @@ -1,30 +0,0 @@ -package org.cbioportal.model; - -import java.io.Serializable; - -public class GenesetMolecularAlteration extends MolecularAlteration implements Serializable { - - private String genesetId; - private Geneset geneset; - - public String getGenesetId() { - return genesetId; - } - - public void setGenesetId(String genesetId) { - this.genesetId = genesetId; - } - - public Geneset getGeneset() { - return geneset; - } - - public void setGeneset(Geneset geneset) { - this.geneset = geneset; - } - - @Override - public String getStableId() { - return genesetId; - } -} diff --git a/src/main/java/org/cbioportal/model/GenesetMolecularData.java b/src/main/java/org/cbioportal/model/GenesetMolecularData.java deleted file mode 100644 index 16fb8b7161a..00000000000 --- a/src/main/java/org/cbioportal/model/GenesetMolecularData.java +++ /dev/null @@ -1,30 +0,0 @@ -package org.cbioportal.model; - -import java.io.Serializable; - -public class GenesetMolecularData extends MolecularData implements Serializable { - - private String genesetId; - private Geneset geneset; - - public String getGenesetId() { - return genesetId; - } - - public void setGenesetId(String genesetId) { - this.genesetId = genesetId; - } - - public Geneset getGeneset() { - return geneset; - } - - public void setGeneset(Geneset geneset) { - this.geneset = geneset; - } - - @Override - public String getStableId() { - return genesetId; - } -} diff --git a/src/main/java/org/cbioportal/model/GeneticEntity.java b/src/main/java/org/cbioportal/model/GeneticEntity.java deleted file mode 100644 index f6bf9335db7..00000000000 --- a/src/main/java/org/cbioportal/model/GeneticEntity.java +++ /dev/null @@ -1,78 +0,0 @@ -package org.cbioportal.model; - -import java.io.Serializable; - -public class GeneticEntity implements Serializable { - - private int id; - private String stableId; - private String entityType; - - /** - * Create a GeneticEntity object from fields - * @param id Internal Id - * @param entityType Type of the genetic entity - * @param stableId Stable identifier - */ - public GeneticEntity(Integer id, String entityType, String stableId) { - this.id = id; - this.entityType = entityType; - this.stableId = stableId; - } - - /** - * Create a GeneticEntity object from fields - * @param entityType Type of the genetic entity - * @param stableId Stable identifier - */ - public GeneticEntity(String entityType, String stableId) { - this.entityType = entityType; - this.stableId = stableId; - } - - public GeneticEntity(String entityType) { - this.entityType = entityType; - } - - /** - * @return the id - */ - public int getId() { - return id; - } - - /** - * @param id the id to set - */ - public void setId(Integer id) { - this.id = id; - } - - /** - * @return the stableId - */ - public String getStableId() { - return stableId; - } - - /** - * @param stableId the stableId to set - */ - public void setStableId(String stableId) { - this.stableId = stableId; - } - - /** - * @return the entity type - */ - public String getEntityType() { - return entityType; - } - - /** - * @param entityType the entityType to set - */ - public void setEntityType(String entityType) { - this.entityType = entityType; - } -} diff --git a/src/main/java/org/cbioportal/model/GenomicDataBin.java b/src/main/java/org/cbioportal/model/GenomicDataBin.java deleted file mode 100644 index f177bd8c35c..00000000000 --- a/src/main/java/org/cbioportal/model/GenomicDataBin.java +++ /dev/null @@ -1,25 +0,0 @@ -package org.cbioportal.model; - -import java.io.Serializable; - -public class GenomicDataBin extends DataBin implements Serializable { - private String hugoGeneSymbol; - private String profileType; - - public String getHugoGeneSymbol() { - return hugoGeneSymbol; - } - - public void setHugoGeneSymbol(String hugoGeneSymbol) { - this.hugoGeneSymbol = hugoGeneSymbol; - } - - public String getProfileType() { - return profileType; - } - - public void setProfileType(String profileType) { - this.profileType = profileType; - } - -} diff --git a/src/main/java/org/cbioportal/model/GenomicDataCount.java b/src/main/java/org/cbioportal/model/GenomicDataCount.java deleted file mode 100644 index f86fda5bc8f..00000000000 --- a/src/main/java/org/cbioportal/model/GenomicDataCount.java +++ /dev/null @@ -1,68 +0,0 @@ -package org.cbioportal.model; - -import java.io.Serializable; -import java.util.Objects; - -public class GenomicDataCount implements Serializable { - - private String label; - private String value; - private Integer count; - private Integer uniqueCount; - - public GenomicDataCount() {} - - public GenomicDataCount(String label, String value, Integer count) { - this.label = label; - this.value = value; - this.count = count; - } - - public GenomicDataCount(String label, String value, Integer count, Integer uniqueCount) { - this.label = label; - this.value = value; - this.count = count; - this.uniqueCount = uniqueCount; - } - - public String getLabel() { - return label; - } - - public void setLabel(String label) { - this.label = label; - } - - public String getValue() { - return value; - } - - public void setValue(String value) { - this.value = value; - } - - public Integer getCount() { - return count; - } - - public void setCount(Integer count) { - this.count = count; - } - - public Integer getUniqueCount() { return uniqueCount; } - - public void setUniqueCount(Integer uniqueCount) { this.uniqueCount = uniqueCount; } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - GenomicDataCount that = (GenomicDataCount) o; - return Objects.equals(label, that.label) && Objects.equals(value, that.value) && Objects.equals(count, that.count) && Objects.equals(uniqueCount, that.uniqueCount); - } - - @Override - public int hashCode() { - return Objects.hash(label, value, count, uniqueCount); - } -} diff --git a/src/main/java/org/cbioportal/model/GenomicDataCountItem.java b/src/main/java/org/cbioportal/model/GenomicDataCountItem.java deleted file mode 100644 index a2123a9386c..00000000000 --- a/src/main/java/org/cbioportal/model/GenomicDataCountItem.java +++ /dev/null @@ -1,43 +0,0 @@ -package org.cbioportal.model; - -import java.io.Serializable; -import java.util.List; - -public class GenomicDataCountItem implements Serializable { - - private String hugoGeneSymbol; - private String profileType; - private List counts; - - public GenomicDataCountItem() {} - - public GenomicDataCountItem(String hugoGeneSymbol, String profileType, List counts) { - this.hugoGeneSymbol = hugoGeneSymbol; - this.profileType = profileType; - this.counts = counts; - } - - public String getHugoGeneSymbol() { - return hugoGeneSymbol; - } - - public void setHugoGeneSymbol(String hugoGeneSymbol) { - this.hugoGeneSymbol = hugoGeneSymbol; - } - - public String getProfileType() { - return profileType; - } - - public void setProfileType(String profileType) { - this.profileType = profileType; - } - - public List getCounts() { - return counts; - } - - public void setCounts(List counts) { - this.counts = counts; - } -} diff --git a/src/main/java/org/cbioportal/model/GenomicEnrichment.java b/src/main/java/org/cbioportal/model/GenomicEnrichment.java deleted file mode 100644 index a4442cf1cf1..00000000000 --- a/src/main/java/org/cbioportal/model/GenomicEnrichment.java +++ /dev/null @@ -1,38 +0,0 @@ -package org.cbioportal.model; - -import java.io.Serializable; - -import jakarta.validation.constraints.NotNull; - -public class GenomicEnrichment extends ExpressionEnrichment implements Serializable { - - @NotNull - private Integer entrezGeneId; - @NotNull - private String hugoGeneSymbol; - private String cytoband; - - public Integer getEntrezGeneId() { - return entrezGeneId; - } - - public void setEntrezGeneId(Integer entrezGeneId) { - this.entrezGeneId = entrezGeneId; - } - - public String getHugoGeneSymbol() { - return hugoGeneSymbol; - } - - public void setHugoGeneSymbol(String hugoGeneSymbol) { - this.hugoGeneSymbol = hugoGeneSymbol; - } - - public String getCytoband() { - return cytoband; - } - - public void setCytoband(String cytoband) { - this.cytoband = cytoband; - } -} diff --git a/src/main/java/org/cbioportal/model/Gistic.java b/src/main/java/org/cbioportal/model/Gistic.java deleted file mode 100644 index 66a8646e2d3..00000000000 --- a/src/main/java/org/cbioportal/model/Gistic.java +++ /dev/null @@ -1,100 +0,0 @@ -package org.cbioportal.model; - -import java.io.Serializable; -import java.math.BigDecimal; -import java.util.List; - -import com.fasterxml.jackson.annotation.JsonProperty; -import jakarta.validation.constraints.NotNull; - -public class Gistic implements Serializable { - - private Long gisticRoiId; - @NotNull - private String cancerStudyId; - @NotNull - private Integer chromosome; - @NotNull - private String cytoband; - @NotNull - private Integer widePeakStart; - @NotNull - private Integer widePeakEnd; - @NotNull - private BigDecimal qValue; - @NotNull - private Boolean amp; - private List genes; - - public Long getGisticRoiId() { - return gisticRoiId; - } - - public void setGisticRoiId(Long gisticRoiId) { - this.gisticRoiId = gisticRoiId; - } - - public String getCancerStudyId() { - return cancerStudyId; - } - - public void setCancerStudyId(String cancerStudyId) { - this.cancerStudyId = cancerStudyId; - } - - public Integer getChromosome() { - return chromosome; - } - - public void setChromosome(Integer chromosome) { - this.chromosome = chromosome; - } - - public String getCytoband() { - return cytoband; - } - - public void setCytoband(String cytoband) { - this.cytoband = cytoband; - } - - public Integer getWidePeakStart() { - return widePeakStart; - } - - public void setWidePeakStart(Integer widePeakStart) { - this.widePeakStart = widePeakStart; - } - - public Integer getWidePeakEnd() { - return widePeakEnd; - } - - public void setWidePeakEnd(Integer widePeakEnd) { - this.widePeakEnd = widePeakEnd; - } - @JsonProperty("qValue") - public BigDecimal getqValue() { - return qValue; - } - - public void setqValue(BigDecimal qValue) { - this.qValue = qValue; - } - - public Boolean getAmp() { - return amp; - } - - public void setAmp(Boolean amp) { - this.amp = amp; - } - - public List getGenes() { - return genes; - } - - public void setGenes(List genes) { - this.genes = genes; - } -} \ No newline at end of file diff --git a/src/main/java/org/cbioportal/model/GisticToGene.java b/src/main/java/org/cbioportal/model/GisticToGene.java deleted file mode 100644 index 49593eedaf9..00000000000 --- a/src/main/java/org/cbioportal/model/GisticToGene.java +++ /dev/null @@ -1,37 +0,0 @@ -package org.cbioportal.model; - -import java.io.Serializable; -import jakarta.validation.constraints.NotNull; - -public class GisticToGene implements Serializable { - - private Long gisticRoiId; - @NotNull - private Integer entrezGeneId; - @NotNull - private String hugoGeneSymbol; - - public Long getGisticRoiId() { - return gisticRoiId; - } - - public void setGisticRoiId(Long gisticRoiId) { - this.gisticRoiId = gisticRoiId; - } - - public Integer getEntrezGeneId() { - return entrezGeneId; - } - - public void setEntrezGeneId(Integer entrezGeneId) { - this.entrezGeneId = entrezGeneId; - } - - public String getHugoGeneSymbol() { - return hugoGeneSymbol; - } - - public void setHugoGeneSymbol(String hugoGeneSymbol) { - this.hugoGeneSymbol = hugoGeneSymbol; - } -} \ No newline at end of file diff --git a/src/main/java/org/cbioportal/model/GroupStatistics.java b/src/main/java/org/cbioportal/model/GroupStatistics.java deleted file mode 100644 index df0950caf02..00000000000 --- a/src/main/java/org/cbioportal/model/GroupStatistics.java +++ /dev/null @@ -1,36 +0,0 @@ -package org.cbioportal.model; - -import java.io.Serializable; -import java.math.BigDecimal; - -import jakarta.validation.constraints.NotNull; - -public class GroupStatistics implements Serializable{ - - @NotNull - private String name; - @NotNull - private BigDecimal meanExpression; - @NotNull - private BigDecimal standardDeviation; - - public String getName() { - return name; - } - public void setName(String name) { - this.name = name; - } - public BigDecimal getMeanExpression() { - return meanExpression; - } - public void setMeanExpression(BigDecimal meanExpression) { - this.meanExpression = meanExpression; - } - public BigDecimal getStandardDeviation() { - return standardDeviation; - } - public void setStandardDeviation(BigDecimal standardDeviation) { - this.standardDeviation = standardDeviation; - } - -} diff --git a/src/main/java/org/cbioportal/model/Info.java b/src/main/java/org/cbioportal/model/Info.java deleted file mode 100644 index beee09b26d7..00000000000 --- a/src/main/java/org/cbioportal/model/Info.java +++ /dev/null @@ -1,129 +0,0 @@ -package org.cbioportal.model; - -import java.io.Serializable; -import jakarta.validation.constraints.NotNull; - -public class Info implements Serializable { - - @NotNull - private String portalVersion; - @NotNull - private String dbVersion; - @NotNull - private String gitBranch; - @NotNull - private String gitCommitId; - @NotNull - private String gitCommitIdAbbrev; - @NotNull - private String gitCommitIdDescribe; - @NotNull - private String gitCommitIdDescribeShort; - @NotNull - private String gitCommitMessageFull; - @NotNull - private String gitCommitMessageShort; - @NotNull - private String gitCommitMessageUserEmail; - @NotNull - private String gitCommitMessageUserName; - @NotNull - private Boolean gitDirty; - - public String getGitBranch() { - return this.gitBranch; - } - - public void setGitBranch(String gitBranch) { - this.gitBranch = gitBranch; - } - - public String getGitCommitId() { - return this.gitCommitId; - } - - public void setGitCommitId(String gitCommitId) { - this.gitCommitId = gitCommitId; - } - - public String getGitCommitIdAbbrev() { - return this.gitCommitIdAbbrev; - } - - public void setGitCommitIdAbbrev(String gitCommitIdAbbrev) { - this.gitCommitIdAbbrev = gitCommitIdAbbrev; - } - - public String getGitCommitIdDescribe() { - return this.gitCommitIdDescribe; - } - - public void setGitCommitIdDescribe(String gitCommitIdDescribe) { - this.gitCommitIdDescribe = gitCommitIdDescribe; - } - - public String getGitCommitIdDescribeShort() { - return this.gitCommitIdDescribeShort; - } - - public void setGitCommitIdDescribeShort(String gitCommitIdDescribeShort) { - this.gitCommitIdDescribeShort = gitCommitIdDescribeShort; - } - - public String getGitCommitMessageFull() { - return this.gitCommitMessageFull; - } - - public void setGitCommitMessageFull(String gitCommitMessageFull) { - this.gitCommitMessageFull = gitCommitMessageFull; - } - - public String getGitCommitMessageShort() { - return this.gitCommitMessageShort; - } - - public void setGitCommitMessageShort(String gitCommitMessageShort) { - this.gitCommitMessageShort = gitCommitMessageShort; - } - - public String getGitCommitMessageUserEmail() { - return this.gitCommitMessageUserEmail; - } - - public void setGitCommitMessageUserEmail(String gitCommitMessageUserEmail) { - this.gitCommitMessageUserEmail = gitCommitMessageUserEmail; - } - - public String getGitCommitMessageUserName() { - return this.gitCommitMessageUserName; - } - - public void setGitCommitMessageUserName(String gitCommitMessageUserName) { - this.gitCommitMessageUserName = gitCommitMessageUserName; - } - - public Boolean getGitDirty() { - return this.gitDirty; - } - - public void isGitDirty(Boolean gitDirty) { - this.gitDirty = gitDirty; - } - - - public String getPortalVersion() { - return portalVersion; - } - - public void setPortalVersion(String portalVersion) { - this.portalVersion = portalVersion; - } - - public String getDbVersion() { - return dbVersion; - } - - public void setDbVersion(String dbVersion) { - this.dbVersion = dbVersion; - } -} diff --git a/src/main/java/org/cbioportal/model/MolecularAlteration.java b/src/main/java/org/cbioportal/model/MolecularAlteration.java deleted file mode 100644 index 0728d8aebbf..00000000000 --- a/src/main/java/org/cbioportal/model/MolecularAlteration.java +++ /dev/null @@ -1,36 +0,0 @@ -package org.cbioportal.model; - -import java.io.Serializable; - -public abstract class MolecularAlteration implements Serializable { - - private String values; - private String[] splitValues = null; - - /** - * Set the values for all samples. - * - * @param values: string with list of values, comma (,) separated - */ - public void setValues(String values) { - this.values = values; - } - - /** - * Returns the values attribute split on (,). - * - * Remembers last .split to avoid repeating this costly operation. - * - * @return list of values for all samples - */ - public String[] getSplitValues() { - if (splitValues == null) { - // Use Integer.MIN_VALUE to return empty string for empty when - // trailing ,,,, - splitValues = values.split(",", Integer.MIN_VALUE); - } - return splitValues; - } - - public abstract String getStableId(); -} diff --git a/src/main/java/org/cbioportal/model/MolecularData.java b/src/main/java/org/cbioportal/model/MolecularData.java deleted file mode 100644 index 260f20d9e34..00000000000 --- a/src/main/java/org/cbioportal/model/MolecularData.java +++ /dev/null @@ -1,59 +0,0 @@ -package org.cbioportal.model; - -import jakarta.validation.constraints.NotNull; - -public abstract class MolecularData extends UniqueKeyBase { - - @NotNull - private String molecularProfileId; - @NotNull - private String sampleId; - @NotNull - private String patientId; - @NotNull - private String studyId; - @NotNull - private String value; - - public String getMolecularProfileId() { - return molecularProfileId; - } - - public void setMolecularProfileId(String molecularProfileId) { - this.molecularProfileId = molecularProfileId; - } - - public String getSampleId() { - return sampleId; - } - - public void setSampleId(String sampleId) { - this.sampleId = sampleId; - } - - public abstract String getStableId(); - - public String getPatientId() { - return patientId; - } - - public void setPatientId(String patientId) { - this.patientId = patientId; - } - - public String getStudyId() { - return studyId; - } - - public void setStudyId(String studyId) { - this.studyId = studyId; - } - - public String getValue() { - return value; - } - - public void setValue(String value) { - this.value = value; - } -} diff --git a/src/main/java/org/cbioportal/model/MolecularProfile.java b/src/main/java/org/cbioportal/model/MolecularProfile.java deleted file mode 100644 index da172984a56..00000000000 --- a/src/main/java/org/cbioportal/model/MolecularProfile.java +++ /dev/null @@ -1,168 +0,0 @@ -package org.cbioportal.model; - -import java.io.Serializable; -import jakarta.validation.constraints.NotNull; - -public class MolecularProfile implements Serializable { - - // Copied from org.mskcc.cbio.portal.model.GeneticAlterationType, if you alter this, - // don't forget to change the original one too - public enum MolecularAlterationType { - MUTATION_EXTENDED, - // uncalled mutations (mskcc internal) for showing read counts even if - // mutation wasn't called - MUTATION_UNCALLED, - STRUCTURAL_VARIANT, - COPY_NUMBER_ALTERATION, - MICRO_RNA_EXPRESSION, - MRNA_EXPRESSION, - MRNA_EXPRESSION_NORMALS, - RNA_EXPRESSION, - METHYLATION, - METHYLATION_BINARY, - PHOSPHORYLATION, - PROTEIN_LEVEL, - PROTEIN_ARRAY_PROTEIN_LEVEL, - PROTEIN_ARRAY_PHOSPHORYLATION, - GENESET_SCORE, - GENERIC_ASSAY - } - - public enum DataType { - DISCRETE; - } - - public enum ImportType { - DISCRETE_LONG; - } - - private Integer molecularProfileId; - @NotNull - private String stableId; - private Integer cancerStudyId; - @NotNull - private String cancerStudyIdentifier; - private MolecularAlterationType molecularAlterationType; - private String genericAssayType; - private String datatype; - private String name; - private String description; - private Boolean showProfileInAnalysisTab; - private CancerStudy cancerStudy; - private Float pivotThreshold; - private String sortOrder; - @NotNull - private Boolean patientLevel; - - public Integer getMolecularProfileId() { - return molecularProfileId; - } - - public void setMolecularProfileId(Integer molecularProfileId) { - this.molecularProfileId = molecularProfileId; - } - - public String getStableId() { - return stableId; - } - - public void setStableId(String stableId) { - this.stableId = stableId; - } - - public Integer getCancerStudyId() { - return cancerStudyId; - } - - public void setCancerStudyId(Integer cancerStudyId) { - this.cancerStudyId = cancerStudyId; - } - - public String getCancerStudyIdentifier() { - return cancerStudyIdentifier; - } - - public void setCancerStudyIdentifier(String cancerStudyIdentifier) { - this.cancerStudyIdentifier = cancerStudyIdentifier; - } - - public MolecularAlterationType getMolecularAlterationType() { - return molecularAlterationType; - } - - public void setMolecularAlterationType(MolecularAlterationType molecularAlterationType) { - this.molecularAlterationType = molecularAlterationType; - } - - public String getDatatype() { - return datatype; - } - - public void setDatatype(String datatype) { - this.datatype = datatype; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String getDescription() { - return description; - } - - public void setDescription(String description) { - this.description = description; - } - - public Boolean getShowProfileInAnalysisTab() { - return showProfileInAnalysisTab; - } - - public void setShowProfileInAnalysisTab(Boolean showProfileInAnalysisTab) { - this.showProfileInAnalysisTab = showProfileInAnalysisTab; - } - - public CancerStudy getCancerStudy() { - return cancerStudy; - } - - public void setCancerStudy(CancerStudy cancerStudy) { - this.cancerStudy = cancerStudy; - } - - public Float getPivotThreshold() { - return this.pivotThreshold; - } - - public void setPivotThreshold(Float pivotThreshold) { - this.pivotThreshold = pivotThreshold; - } - - public String getSortOrder() { - return this.sortOrder; - } - - public void setSortOrder(String sortOrder) { - this.sortOrder = sortOrder; - } - - public String getGenericAssayType() { - return genericAssayType; - } - - public void setGenericAssayType(String genericAssayType) { - this.genericAssayType = genericAssayType; - } - - public Boolean getPatientLevel() { - return patientLevel; - } - - public void setPatientLevel(Boolean patientLevel) { - this.patientLevel = patientLevel; - } -} diff --git a/src/main/java/org/cbioportal/model/MolecularProfileCaseIdentifier.java b/src/main/java/org/cbioportal/model/MolecularProfileCaseIdentifier.java deleted file mode 100644 index 743fee3cb0d..00000000000 --- a/src/main/java/org/cbioportal/model/MolecularProfileCaseIdentifier.java +++ /dev/null @@ -1,75 +0,0 @@ -package org.cbioportal.model; - -import jakarta.validation.constraints.NotNull; -import java.io.Serializable; - -public class MolecularProfileCaseIdentifier implements Serializable, Comparable { - - @NotNull - private String molecularProfileId; - @NotNull - private String caseId; - - public MolecularProfileCaseIdentifier() {} - - public MolecularProfileCaseIdentifier(String caseId, String molecularProfileId) { - this.molecularProfileId = molecularProfileId; - this.caseId = caseId; - } - - public String getMolecularProfileId() { - return molecularProfileId; - } - - public void setMolecularProfileId(String molecularProfileId) { - this.molecularProfileId = molecularProfileId; - } - - public String getCaseId() { - return caseId; - } - - public void setCaseId(String caseId) { - this.caseId = caseId; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((caseId == null) ? 0 : caseId.hashCode()); - result = prime * result + ((molecularProfileId == null) ? 0 : molecularProfileId.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - MolecularProfileCaseIdentifier other = (MolecularProfileCaseIdentifier) obj; - if (caseId == null) { - if (other.caseId != null) - return false; - } else if (!caseId.equals(other.caseId)) - return false; - if (molecularProfileId == null) { - if (other.molecularProfileId != null) - return false; - } else if (!molecularProfileId.equals(other.molecularProfileId)) - return false; - return true; - } - - @Override - public int compareTo(MolecularProfileCaseIdentifier o) { - if (molecularProfileId.compareTo(o.molecularProfileId) == 0) { - return caseId.compareTo(o.caseId); - } else { - return molecularProfileId.compareTo(o.molecularProfileId); - } - } -} diff --git a/src/main/java/org/cbioportal/model/MolecularProfileSamples.java b/src/main/java/org/cbioportal/model/MolecularProfileSamples.java deleted file mode 100644 index ee3b23b5c3c..00000000000 --- a/src/main/java/org/cbioportal/model/MolecularProfileSamples.java +++ /dev/null @@ -1,46 +0,0 @@ -package org.cbioportal.model; - -import java.io.Serializable; - -public class MolecularProfileSamples implements Serializable { - - private String molecularProfileId; - private String commaSeparatedSampleIds; - private String[] splitSampleIds = null; - - public String getMolecularProfileId() { - return molecularProfileId; - } - - public void setMolecularProfileId(String molecularProfileId) { - this.molecularProfileId = molecularProfileId; - } - - public String getCommaSeparatedSampleIds() { - return commaSeparatedSampleIds; - } - - /** - * Set the values for all samples. - * - * @param values: string with list of values, comma (,) separated - */ - public void setCommaSeparatedSampleIds(String commaSeparatedSampleIds) { - this.commaSeparatedSampleIds = commaSeparatedSampleIds; - } - - /** - * Returns the values attribute split on (,). - * - * Remembers last .split to avoid repeating this costly operation. - * - * @return list of values for all samples - */ - public String[] getSplitSampleIds() { - if (splitSampleIds == null) { - splitSampleIds = commaSeparatedSampleIds.split(","); - } - return splitSampleIds; - } - -} diff --git a/src/main/java/org/cbioportal/model/MrnaPercentile.java b/src/main/java/org/cbioportal/model/MrnaPercentile.java deleted file mode 100644 index 278e65eb61b..00000000000 --- a/src/main/java/org/cbioportal/model/MrnaPercentile.java +++ /dev/null @@ -1,81 +0,0 @@ -package org.cbioportal.model; - -import java.math.BigDecimal; - -import com.fasterxml.jackson.annotation.JsonProperty; -import jakarta.validation.constraints.NotNull; - -public class MrnaPercentile extends UniqueKeyBase { - - @NotNull - private String molecularProfileId; - @NotNull - private String sampleId; - @NotNull - private String patientId; - @NotNull - private String studyId; - @NotNull - private Integer entrezGeneId; - @NotNull - private BigDecimal percentile; - @NotNull - private BigDecimal zScore; - - public String getMolecularProfileId() { - return molecularProfileId; - } - - public void setMolecularProfileId(String molecularProfileId) { - this.molecularProfileId = molecularProfileId; - } - - public String getSampleId() { - return sampleId; - } - - public void setSampleId(String sampleId) { - this.sampleId = sampleId; - } - - public String getPatientId() { - return patientId; - } - - public void setPatientId(String patientId) { - this.patientId = patientId; - } - - public String getStudyId() { - return studyId; - } - - public void setStudyId(String studyId) { - this.studyId = studyId; - } - - public Integer getEntrezGeneId() { - return entrezGeneId; - } - - public void setEntrezGeneId(Integer entrezGeneId) { - this.entrezGeneId = entrezGeneId; - } - - public BigDecimal getPercentile() { - return percentile; - } - - public void setPercentile(BigDecimal percentile) { - this.percentile = percentile; - } - - @JsonProperty("zScore") - public BigDecimal getzScore() { - return zScore; - } - - public void setzScore(BigDecimal zScore) { - this.zScore = zScore; - } -} diff --git a/src/main/java/org/cbioportal/model/MutSig.java b/src/main/java/org/cbioportal/model/MutSig.java deleted file mode 100644 index 1d60c06e801..00000000000 --- a/src/main/java/org/cbioportal/model/MutSig.java +++ /dev/null @@ -1,101 +0,0 @@ -package org.cbioportal.model; - -import java.io.Serializable; -import java.math.BigDecimal; - -import com.fasterxml.jackson.annotation.JsonProperty; -import jakarta.validation.constraints.NotNull; - -public class MutSig implements Serializable { - - private Integer cancerStudyId; - @NotNull - private String cancerStudyIdentifier; - @NotNull - private Integer entrezGeneId; - @NotNull - private String hugoGeneSymbol; - @NotNull - private Integer rank; - private Integer numbasescovered; - @NotNull - private Integer nummutations; - @NotNull - private BigDecimal pValue; - @NotNull - private BigDecimal qValue; - - public Integer getCancerStudyId() { - return cancerStudyId; - } - - public void setCancerStudyId(Integer cancerStudyId) { - this.cancerStudyId = cancerStudyId; - } - - public String getCancerStudyIdentifier() { - return cancerStudyIdentifier; - } - - public void setCancerStudyIdentifier(String cancerStudyIdentifier) { - this.cancerStudyIdentifier = cancerStudyIdentifier; - } - - public Integer getEntrezGeneId() { - return entrezGeneId; - } - - public void setEntrezGeneId(Integer entrezGeneId) { - this.entrezGeneId = entrezGeneId; - } - - public String getHugoGeneSymbol() { - return hugoGeneSymbol; - } - - public void setHugoGeneSymbol(String hugoGeneSymbol) { - this.hugoGeneSymbol = hugoGeneSymbol; - } - - public Integer getRank() { - return rank; - } - - public void setRank(Integer rank) { - this.rank = rank; - } - - public Integer getNumbasescovered() { - return numbasescovered; - } - - public void setNumbasescovered(Integer numbasescovered) { - this.numbasescovered = numbasescovered; - } - - public Integer getNummutations() { - return nummutations; - } - - public void setNummutations(Integer nummutations) { - this.nummutations = nummutations; - } - - @JsonProperty("pValue") - public BigDecimal getpValue() { - return pValue; - } - - public void setpValue(BigDecimal pValue) { - this.pValue = pValue; - } - - @JsonProperty("qValue") - public BigDecimal getqValue() { - return qValue; - } - - public void setqValue(BigDecimal qValue) { - this.qValue = qValue; - } -} \ No newline at end of file diff --git a/src/main/java/org/cbioportal/model/Mutation.java b/src/main/java/org/cbioportal/model/Mutation.java deleted file mode 100644 index 3ddae915587..00000000000 --- a/src/main/java/org/cbioportal/model/Mutation.java +++ /dev/null @@ -1,216 +0,0 @@ -package org.cbioportal.model; - -import com.fasterxml.jackson.annotation.JsonRawValue; -import io.swagger.v3.oas.annotations.media.Schema; - -import java.io.Serializable; -import java.math.BigDecimal; - -public class Mutation extends Alteration implements Serializable { - - private String center; - private String mutationStatus; - private String validationStatus; - private Integer tumorAltCount; - private Integer tumorRefCount; - private Integer normalAltCount; - private Integer normalRefCount; - private String aminoAcidChange; - private String chr; - private Long startPosition; - private Long endPosition; - private String referenceAllele; - private String tumorSeqAllele; - private String proteinChange; - private String mutationType; - private String ncbiBuild; - private String variantType; - private String refseqMrnaId; - private Integer proteinPosStart; - private Integer proteinPosEnd; - private String keyword; - private AlleleSpecificCopyNumber alleleSpecificCopyNumber; - @JsonRawValue - @Schema(type = "java.util.Map") - private Object annotationJSON; - - public String getCenter() { - return center; - } - - public void setCenter(String center) { - this.center = center; - } - - public String getMutationStatus() { - return mutationStatus; - } - - public void setMutationStatus(String mutationStatus) { - this.mutationStatus = mutationStatus; - } - - public String getValidationStatus() { - return validationStatus; - } - - public void setValidationStatus(String validationStatus) { - this.validationStatus = validationStatus; - } - - public Integer getTumorAltCount() { - return tumorAltCount; - } - - public void setTumorAltCount(Integer tumorAltCount) { - this.tumorAltCount = tumorAltCount; - } - - public Integer getTumorRefCount() { - return tumorRefCount; - } - - public void setTumorRefCount(Integer tumorRefCount) { - this.tumorRefCount = tumorRefCount; - } - - public Integer getNormalAltCount() { - return normalAltCount; - } - - public void setNormalAltCount(Integer normalAltCount) { - this.normalAltCount = normalAltCount; - } - - public Integer getNormalRefCount() { - return normalRefCount; - } - - public void setNormalRefCount(Integer normalRefCount) { - this.normalRefCount = normalRefCount; - } - - public String getAminoAcidChange() { - return aminoAcidChange; - } - - public void setAminoAcidChange(String aminoAcidChange) { - this.aminoAcidChange = aminoAcidChange; - } - - public String getChr() { return chr; } - - public void setChr(String chr) { this.chr = chr; } - - public Long getStartPosition() { - return startPosition; - } - - public void setStartPosition(Long startPosition) { - this.startPosition = startPosition; - } - - public Long getEndPosition() { - return endPosition; - } - - public void setEndPosition(Long endPosition) { - this.endPosition = endPosition; - } - - public String getReferenceAllele() { - return referenceAllele; - } - - public void setReferenceAllele(String referenceAllele) { - this.referenceAllele = referenceAllele; - } - - public String getTumorSeqAllele() { - return tumorSeqAllele; - } - - public void setTumorSeqAllele(String tumorSeqAllele) { - this.tumorSeqAllele = tumorSeqAllele; - } - - public String getProteinChange() { - return proteinChange; - } - - public void setProteinChange(String proteinChange) { - this.proteinChange = proteinChange; - } - - public String getMutationType() { - return mutationType; - } - - public void setMutationType(String mutationType) { - this.mutationType = mutationType; - } - - public String getNcbiBuild() { - return ncbiBuild; - } - - public void setNcbiBuild(String ncbiBuild) { - this.ncbiBuild = ncbiBuild; - } - - public String getVariantType() { - return variantType; - } - - public void setVariantType(String variantType) { - this.variantType = variantType; - } - public String getRefseqMrnaId() { - return refseqMrnaId; - } - - public void setRefseqMrnaId(String refseqMrnaId) { - this.refseqMrnaId = refseqMrnaId; - } - - public Integer getProteinPosStart() { - return proteinPosStart; - } - - public void setProteinPosStart(Integer proteinPosStart) { - this.proteinPosStart = proteinPosStart; - } - - public Integer getProteinPosEnd() { - return proteinPosEnd; - } - - public void setProteinPosEnd(Integer proteinPosEnd) { - this.proteinPosEnd = proteinPosEnd; - } - - public String getKeyword() { - return keyword; - } - - public void setKeyword(String keyword) { - this.keyword = keyword; - } - - public AlleleSpecificCopyNumber getAlleleSpecificCopyNumber() { - return alleleSpecificCopyNumber; - } - - public void setAlleleSpecificCopyNumber(AlleleSpecificCopyNumber alleleSpecificCopyNumber) { - this.alleleSpecificCopyNumber = alleleSpecificCopyNumber; - } - - public Object getAnnotationJSON() { - return annotationJSON; - } - - public void setAnnotationJSON(String annotationJSON) { - this.annotationJSON = annotationJSON; - } - -} diff --git a/src/main/java/org/cbioportal/model/MutationCountByGene.java b/src/main/java/org/cbioportal/model/MutationCountByGene.java deleted file mode 100644 index 0f949838fc1..00000000000 --- a/src/main/java/org/cbioportal/model/MutationCountByGene.java +++ /dev/null @@ -1,7 +0,0 @@ -package org.cbioportal.model; - -import java.io.Serializable; - -public class MutationCountByGene extends AlterationCountByGene implements Serializable { - -} diff --git a/src/main/java/org/cbioportal/model/MutationCountByPosition.java b/src/main/java/org/cbioportal/model/MutationCountByPosition.java deleted file mode 100644 index f92b2fb1d17..00000000000 --- a/src/main/java/org/cbioportal/model/MutationCountByPosition.java +++ /dev/null @@ -1,48 +0,0 @@ -package org.cbioportal.model; - -import java.io.Serializable; -import jakarta.validation.constraints.NotNull; - -public class MutationCountByPosition implements Serializable { - - @NotNull - private Integer entrezGeneId; - @NotNull - private Integer proteinPosStart; - @NotNull - private Integer proteinPosEnd; - @NotNull - private Integer count; - - public Integer getEntrezGeneId() { - return entrezGeneId; - } - - public void setEntrezGeneId(Integer entrezGeneId) { - this.entrezGeneId = entrezGeneId; - } - - public Integer getProteinPosStart() { - return proteinPosStart; - } - - public void setProteinPosStart(Integer proteinPosStart) { - this.proteinPosStart = proteinPosStart; - } - - public Integer getProteinPosEnd() { - return proteinPosEnd; - } - - public void setProteinPosEnd(Integer proteinPosEnd) { - this.proteinPosEnd = proteinPosEnd; - } - - public Integer getCount() { - return count; - } - - public void setCount(Integer count) { - this.count = count; - } -} diff --git a/src/main/java/org/cbioportal/model/MutationEventType.java b/src/main/java/org/cbioportal/model/MutationEventType.java deleted file mode 100644 index e1957f20e71..00000000000 --- a/src/main/java/org/cbioportal/model/MutationEventType.java +++ /dev/null @@ -1,64 +0,0 @@ -package org.cbioportal.model; - -public enum MutationEventType { - - missense_mutation("missense_mutation"), - missense("missense"), - missense_variant("missense_variant"), - frame_shift_ins("frame_shift_ins"), - frame_shift_del("frame_shift_del"), - frameshift("frameshift"), - frameshift_deletion("frameshift_deletion"), - frameshift_insertion("frameshift_insertion"), - de_novo_start_outofframe("de_novo_start_outofframe"), - frameshift_variant("frameshift_variant"), - nonsense_mutation("nonsense_mutation"), - nonsense("nonsense"), - stopgain_snv("stopgain_snv"), - stop_gained("stop_gained"), - splice_site("splice_site"), - splice("splice"), - splicing("splicing"), - splice_site_snp("splice_site_snp"), - splice_site_del("splice_site_del"), - splice_site_indel("splice_site_indel"), - splice_region_variant("splice_region_variant"), - splice_region("splice_region"), - translation_start_site("translation_start_site"), - initiator_codon_variant("initiator_codon_variant"), - start_codon_snp("start_codon_snp"), - start_codon_del("start_codon_del"), - nonstop_mutation("nonstop_mutation"), - stop_lost("stop_lost"), - inframe_del("inframe_del"), - inframe_deletion("inframe_deletion"), - in_frame_del("in_frame_del"), - in_frame_deletion("in_frame_deletion"), - inframe_ins("inframe_ins"), - inframe_insertion("inframe_insertion"), - in_frame_ins("in_frame_ins"), - in_frame_insertion("in_frame_insertion"), - indel("indel"), - nonframeshift_deletion("nonframeshift_deletion"), - nonframeshift("nonframeshift"), - nonframeshift_insertion("nonframeshift_insertion"), - targeted_region("targeted_region"), - inframe("inframe"), - truncating("truncating"), - feature_truncation("feature_truncation"), - silent("silent"), - synonymous_variant("synonymous_variant"), - any("any"), - other("other"); - - private final String mutationType; - - MutationEventType(String mutationType) { - this.mutationType = mutationType; - } - - public String getMutationType() { - return mutationType; - } - -} diff --git a/src/main/java/org/cbioportal/model/MutationFilterOption.java b/src/main/java/org/cbioportal/model/MutationFilterOption.java deleted file mode 100644 index fd83da4f051..00000000000 --- a/src/main/java/org/cbioportal/model/MutationFilterOption.java +++ /dev/null @@ -1,18 +0,0 @@ -package org.cbioportal.model; - -public enum MutationFilterOption { - MUTATED("Mutated"), // Samples that have mutations - NOT_MUTATED("Not Mutated"), // Samples that are profiled and not mutated - NOT_PROFILED("Not Profiled"), // Samples that are not profiled - ; - - private final String selectedOption; - - MutationFilterOption(String selectedOption) { - this.selectedOption = selectedOption; - } - - public String getSelectedOption() { - return selectedOption; - } -} diff --git a/src/main/java/org/cbioportal/model/MutationSpectrum.java b/src/main/java/org/cbioportal/model/MutationSpectrum.java deleted file mode 100644 index f130728b86d..00000000000 --- a/src/main/java/org/cbioportal/model/MutationSpectrum.java +++ /dev/null @@ -1,107 +0,0 @@ -package org.cbioportal.model; - -import jakarta.validation.constraints.NotNull; - -public class MutationSpectrum extends UniqueKeyBase { - - @NotNull - private String molecularProfileId; - @NotNull - private String sampleId; - @NotNull - private String patientId; - @NotNull - private String studyId; - @NotNull - private Integer ctoA; - @NotNull - private Integer ctoG; - @NotNull - private Integer ctoT; - @NotNull - private Integer ttoA; - @NotNull - private Integer ttoC; - @NotNull - private Integer ttoG; - - public String getMolecularProfileId() { - return molecularProfileId; - } - - public void setMolecularProfileId(String molecularProfileId) { - this.molecularProfileId = molecularProfileId; - } - - public String getSampleId() { - return sampleId; - } - - public void setSampleId(String sampleId) { - this.sampleId = sampleId; - } - - public String getPatientId() { - return patientId; - } - - public void setPatientId(String patientId) { - this.patientId = patientId; - } - - public String getStudyId() { - return studyId; - } - - public void setStudyId(String studyId) { - this.studyId = studyId; - } - - public Integer getCtoA() { - return ctoA; - } - - public void setCtoA(Integer ctoA) { - this.ctoA = ctoA; - } - - public Integer getCtoG() { - return ctoG; - } - - public void setCtoG(Integer ctoG) { - this.ctoG = ctoG; - } - - public Integer getCtoT() { - return ctoT; - } - - public void setCtoT(Integer ctoT) { - this.ctoT = ctoT; - } - - public Integer getTtoA() { - return ttoA; - } - - public void setTtoA(Integer ttoA) { - this.ttoA = ttoA; - } - - public Integer getTtoC() { - return ttoC; - } - - public void setTtoC(Integer ttoC) { - this.ttoC = ttoC; - } - - public Integer getTtoG() { - return ttoG; - } - - public void setTtoG(Integer ttoG) { - this.ttoG = ttoG; - } -} diff --git a/src/main/java/org/cbioportal/model/NumericGeneMolecularData.java b/src/main/java/org/cbioportal/model/NumericGeneMolecularData.java deleted file mode 100644 index 3e519807477..00000000000 --- a/src/main/java/org/cbioportal/model/NumericGeneMolecularData.java +++ /dev/null @@ -1,78 +0,0 @@ -package org.cbioportal.model; - -import java.math.BigDecimal; - -import jakarta.validation.constraints.NotNull; - -public class NumericGeneMolecularData extends UniqueKeyBase { - - @NotNull - private Integer entrezGeneId; - private Gene gene; - @NotNull - private String molecularProfileId; - @NotNull - private String sampleId; - @NotNull - private String patientId; - @NotNull - private String studyId; - @NotNull - private BigDecimal value; - - public Integer getEntrezGeneId() { - return entrezGeneId; - } - - public void setEntrezGeneId(Integer entrezGeneId) { - this.entrezGeneId = entrezGeneId; - } - - public Gene getGene() { - return gene; - } - - public void setGene(Gene gene) { - this.gene = gene; - } - - public String getMolecularProfileId() { - return molecularProfileId; - } - - public void setMolecularProfileId(String molecularProfileId) { - this.molecularProfileId = molecularProfileId; - } - - public String getSampleId() { - return sampleId; - } - - public void setSampleId(String sampleId) { - this.sampleId = sampleId; - } - - public String getPatientId() { - return patientId; - } - - public void setPatientId(String patientId) { - this.patientId = patientId; - } - - public String getStudyId() { - return studyId; - } - - public void setStudyId(String studyId) { - this.studyId = studyId; - } - - public BigDecimal getValue() { - return value; - } - - public void setValue(BigDecimal value) { - this.value = value; - } -} diff --git a/src/main/java/org/cbioportal/model/Patient.java b/src/main/java/org/cbioportal/model/Patient.java deleted file mode 100644 index 4d2a2f1d9a6..00000000000 --- a/src/main/java/org/cbioportal/model/Patient.java +++ /dev/null @@ -1,54 +0,0 @@ -package org.cbioportal.model; - -import jakarta.validation.constraints.NotNull; - -public class Patient extends UniqueKeyBase { - - private Integer internalId; - @NotNull - private String stableId; - private Integer cancerStudyId; - @NotNull - private String cancerStudyIdentifier; - private CancerStudy cancerStudy; - - public Integer getInternalId() { - return internalId; - } - - public void setInternalId(Integer internalId) { - this.internalId = internalId; - } - - public String getStableId() { - return stableId; - } - - public void setStableId(String stableId) { - this.stableId = stableId; - } - - public Integer getCancerStudyId() { - return cancerStudyId; - } - - public void setCancerStudyId(Integer cancerStudyId) { - this.cancerStudyId = cancerStudyId; - } - - public String getCancerStudyIdentifier() { - return cancerStudyIdentifier; - } - - public void setCancerStudyIdentifier(String cancerStudyIdentifier) { - this.cancerStudyIdentifier = cancerStudyIdentifier; - } - - public CancerStudy getCancerStudy() { - return cancerStudy; - } - - public void setCancerStudy(CancerStudy cancerStudy) { - this.cancerStudy = cancerStudy; - } -} \ No newline at end of file diff --git a/src/main/java/org/cbioportal/model/PatientTreatment.java b/src/main/java/org/cbioportal/model/PatientTreatment.java deleted file mode 100644 index c838d23777e..00000000000 --- a/src/main/java/org/cbioportal/model/PatientTreatment.java +++ /dev/null @@ -1,7 +0,0 @@ -package org.cbioportal.model; - -import java.io.Serializable; - -public record PatientTreatment (String treatment, int count) implements Serializable { - -} diff --git a/src/main/java/org/cbioportal/model/PatientTreatmentReport.java b/src/main/java/org/cbioportal/model/PatientTreatmentReport.java deleted file mode 100644 index d09a2276f06..00000000000 --- a/src/main/java/org/cbioportal/model/PatientTreatmentReport.java +++ /dev/null @@ -1,11 +0,0 @@ -package org.cbioportal.model; - -import java.io.Serializable; -import java.util.Collections; -import java.util.List; - -public record PatientTreatmentReport (int totalPatients, int totalSamples, List patientTreatments) implements Serializable { - public PatientTreatmentReport(int totalPatients, int totalSamples) { - this(totalPatients, totalSamples, Collections.emptyList()); - } -} diff --git a/src/main/java/org/cbioportal/model/PatientTreatmentRow.java b/src/main/java/org/cbioportal/model/PatientTreatmentRow.java deleted file mode 100644 index 6fc5f75395e..00000000000 --- a/src/main/java/org/cbioportal/model/PatientTreatmentRow.java +++ /dev/null @@ -1,64 +0,0 @@ -package org.cbioportal.model; - -import java.io.Serializable; -import java.util.Objects; -import java.util.Set; - -public class PatientTreatmentRow implements TreatmentRow, Serializable { - private String treatment; - private int count; - private Set samples; - - public PatientTreatmentRow() {} - - public PatientTreatmentRow(String treatment, int count, Set samples) { - this.treatment = treatment; - this.count = count; - this.samples = samples; - } - - public String getTreatment() { - return treatment; - } - - public void setTreatment(String treatment) { - this.treatment = treatment; - } - - public int getCount() { - return count; - } - - public void setCount(int count) { - this.count = count; - } - - @Override - public Set getSamples() { - return samples; - } - - public void setSamples(Set samples) { - this.samples = samples; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - PatientTreatmentRow that = (PatientTreatmentRow) o; - return getCount() == that.getCount() && - getTreatment().equals(that.getTreatment()) && - Objects.equals(getSamples(), that.getSamples()); - } - - @Override - public int hashCode() { - return Objects.hash(getTreatment(), getCount(), getSamples()); - } - - public void add(SampleTreatmentRow toAdd) { - setCount(getCount() + toAdd.getCount()); - getSamples().addAll(toAdd.getSamples()); - } -} diff --git a/src/main/java/org/cbioportal/model/QueryElement.java b/src/main/java/org/cbioportal/model/QueryElement.java deleted file mode 100644 index 0112edbdc44..00000000000 --- a/src/main/java/org/cbioportal/model/QueryElement.java +++ /dev/null @@ -1,13 +0,0 @@ -package org.cbioportal.model; - -/* - QueryElement represents three types of behavior for a SQL statement in MyBatis mappers - - INACTIVE: exclude Query element from results - - ACTIVE: include Query element in results - - PASS: do not apply on Query element - Note: the specific behavior the represented by the three states - of QueryElement is determined by the mapper-xml. -*/ -public enum QueryElement { - INACTIVE, ACTIVE, PASS -} diff --git a/src/main/java/org/cbioportal/model/ReadPermission.java b/src/main/java/org/cbioportal/model/ReadPermission.java deleted file mode 100644 index c215b4aa648..00000000000 --- a/src/main/java/org/cbioportal/model/ReadPermission.java +++ /dev/null @@ -1,6 +0,0 @@ -package org.cbioportal.model; - -public interface ReadPermission { - public void setReadPermission(Boolean permission); - public Boolean getReadPermission(); -} diff --git a/src/main/java/org/cbioportal/model/ReferenceGenome.java b/src/main/java/org/cbioportal/model/ReferenceGenome.java deleted file mode 100644 index 287b17272ef..00000000000 --- a/src/main/java/org/cbioportal/model/ReferenceGenome.java +++ /dev/null @@ -1,176 +0,0 @@ -/* - * This file is part of cBioPortal. - * - * cBioPortal is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -package org.cbioportal.model; - -import java.util.Date; - - -/** - * This represents the reference genome used by molecular profiling - * - * @author Kelsey Zhu - */ -public class ReferenceGenome { - - private int referenceGenomeId; // assigned by DB, auto increment sequence number - private String genomeName; - private String species; - private String buildName; //genome assembly name - private long genomeSize; //non-N bases - private String url; - private Date releaseDate; - public static String HOMO_SAPIENS = "human"; - public static String MUS_MUSCULUS = "mouse"; - public static String HOMO_SAPIENS_DEFAULT_GENOME_BUILD = "GRCh37"; - public static String HOMO_SAPIENS_DEFAULT_GENOME_NAME = "hg19"; - public static String MUS_MUSCULUS_DEFAULT_GENOME_BUILD = "GRCm38"; - public static String HOMO_SAPIENS_DEFAULT_GENOME_BUILD_PREFIX = "GRCh"; - public static String MUS_MUSCULUS_DEFAULT_GENOME_BUILD_PREFIX = "GRCm"; - - /** - * Constructor. - * @param genomeName Name of the reference genome. - * @param species Species of the reference genome. - * @param buildName Name of genome assembly - */ - public ReferenceGenome(String genomeName, String species, String buildName) { - super(); - this.genomeName = genomeName; - this.species = species; - this.buildName = buildName; - } - - /** - * Constructor. - * @param genomeName Name of the reference genome. - * @param species Species of the reference genome. - * @param buildName Name of genome assembly - * @param genomeSize Effective genome size - * @param url URL to download reference genome - * @param releaseDate Date genome assembly released - */ - public ReferenceGenome(String genomeName, String species, String buildName, - Long genomeSize, String url, Date releaseDate) { - super(); - this.genomeName = genomeName; - this.species = species; - this.buildName = buildName; - this.genomeSize = genomeSize; - this.url = url; - this.releaseDate = releaseDate; - } - - public void setReferenceGenomeId(int referenceGenomeId) { - this.referenceGenomeId = referenceGenomeId; - } - - public int getReferenceGenomeId() { - return referenceGenomeId; - } - - public void setGenomeName(String genomeName) { - this.genomeName = genomeName; - } - - public String getGenomeName() { - return this.genomeName; - } - - public void setSpecies(String species) { - this.species = species; - } - - public String getSpecies() { - return this.species; - } - - public void setBuildName(String buildName) { - this.buildName = buildName; - } - - public String getBuildName () { - return this.buildName; - } - - public void setGenomeSize(long genomeSize) { - this.genomeSize = genomeSize; - } - - public long getGenomeSize() { - return this.genomeSize; - } - - public void setUrl(String url) { - this.url = url; - } - - public String getUrl() { - return this.url; - } - - public void setReleaseDate(Date releaseDate) { - this.releaseDate = releaseDate; - } - - public Date getReleaseDate() { - return this.releaseDate; - } - - /** - * Equals. - * @param otherReferenceGenome Other Reference Genome. - * @return true of false. - */ - @Override - public boolean equals(Object otherReferenceGenome) { - if (this == otherReferenceGenome) { - return true; - } - - if (!(otherReferenceGenome instanceof ReferenceGenome)) { - return false; - } - - ReferenceGenome that = (ReferenceGenome) otherReferenceGenome; - return - (this.genomeName).equals(that.genomeName) && - (this.species).equals(that.species) && - (this.buildName).equals(that.buildName); - } - - @Override - public int hashCode() { - int result = 3; - result = 31 * result + this.referenceGenomeId; - result = 31 * result + (this.genomeName != null ? this.genomeName.hashCode() : 0); - result = 31 * result + (this.buildName != null ? this.buildName.hashCode() : 0); - result = 31 * result + (this.species != null ? this.species.hashCode() : 0); - return result; - } - - /** - * toString() Override. - * @return string summary of reference genome - */ - @Override - public String toString() { - return "Reference Genome [referenceGenomeID=" + referenceGenomeId + ", genomeName=" + genomeName + ", species=" - + species + ", buildName=" + buildName + "]"; - } - -} \ No newline at end of file diff --git a/src/main/java/org/cbioportal/model/ReferenceGenomeGene.java b/src/main/java/org/cbioportal/model/ReferenceGenomeGene.java deleted file mode 100644 index 34ff3d82c9f..00000000000 --- a/src/main/java/org/cbioportal/model/ReferenceGenomeGene.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * This file is part of cBioPortal. - * - * cBioPortal is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -package org.cbioportal.model; - -import java.io.Serializable; -import java.net.Inet4Address; -import jakarta.validation.constraints.NotNull; - -/** - * Class to wrap Reference Genome Gene. - * @author Kelsey Zhu - */ -public class ReferenceGenomeGene implements Serializable { - @NotNull - private Integer referenceGenomeId; - @NotNull - private Integer entrezGeneId; - private String hugoGeneSymbol; - private String chromosome; - private String cytoband; - private Long start; - private Long end; - - public void setReferenceGenomeId(Integer referenceGenomeId) { this.referenceGenomeId = referenceGenomeId; } - - public Integer getReferenceGenomeId() { - return referenceGenomeId; - } - - public Integer getEntrezGeneId() { return entrezGeneId; } - - public void setEntrezGeneId(Integer entrezGeneId) { this.entrezGeneId = entrezGeneId; } - - public String getHugoGeneSymbol() { - return hugoGeneSymbol; - } - - public void setHugoGeneSymbol(String hugoGeneSymbol) { - this.hugoGeneSymbol = hugoGeneSymbol; - } - - public String getChromosome() { - return chromosome; - } - - public void setChromosome(String chromosome) { - this.chromosome = chromosome; - } - - public String getCytoband() { - return cytoband; - } - - public void setCytoband(String cytoband) { - this.cytoband = cytoband; - } - - public Long getStart() { return this.start; } - - public void setStart(Long start) { this.start = start; } - - public Long getEnd() { return this.end; } - - public void setEnd(Long end) { this.end = end; } - -} diff --git a/src/main/java/org/cbioportal/model/ResourceData.java b/src/main/java/org/cbioportal/model/ResourceData.java deleted file mode 100644 index 243b86af47c..00000000000 --- a/src/main/java/org/cbioportal/model/ResourceData.java +++ /dev/null @@ -1,67 +0,0 @@ -package org.cbioportal.model; - -import java.io.Serializable; - -import jakarta.validation.constraints.NotNull; - -public class ResourceData extends UniqueKeyBase implements Serializable { - - private String sampleId; - private String patientId; - @NotNull - private String studyId; - @NotNull - private String resourceId; - @NotNull - private String url; - private ResourceDefinition resourceDefinition; - - public String getSampleId() { - return sampleId; - } - - public void setSampleId(String sampleId) { - this.sampleId = sampleId; - } - - public String getPatientId() { - return patientId; - } - - public void setPatientId(String patientId) { - this.patientId = patientId; - } - - public String getStudyId() { - return studyId; - } - - public void setStudyId(String studyId) { - this.studyId = studyId; - } - - public String getResourceId() { - return resourceId; - } - - public void setResourceId(String resourceId) { - this.resourceId = resourceId; - } - - public String getUrl() { - return url; - } - - public void setUrl(String url) { - this.url = url; - } - - public ResourceDefinition getResourceDefinition() { - return resourceDefinition; - } - - public void setResourceDefinition(ResourceDefinition resourceDefinition) { - this.resourceDefinition = resourceDefinition; - } - -} diff --git a/src/main/java/org/cbioportal/model/ResourceDefinition.java b/src/main/java/org/cbioportal/model/ResourceDefinition.java deleted file mode 100644 index 73eacd6f287..00000000000 --- a/src/main/java/org/cbioportal/model/ResourceDefinition.java +++ /dev/null @@ -1,76 +0,0 @@ -package org.cbioportal.model; - -import java.io.Serializable; -import jakarta.validation.constraints.NotNull; - -public class ResourceDefinition implements Serializable { - - @NotNull - private String resourceId; - @NotNull - private String displayName; - private String description; - @NotNull - private ResourceType resourceType; - private String priority; - private Boolean openByDefault; - @NotNull - private String cancerStudyIdentifier; - - public String getResourceId() { - return resourceId; - } - - public void setResourceId(String resourceId) { - this.resourceId = resourceId; - } - - public String getDisplayName() { - return displayName; - } - - public void setDisplayName(String displayName) { - this.displayName = displayName; - } - - public String getDescription() { - return description; - } - - public void setDescription(String description) { - this.description = description; - } - - public ResourceType getResourceType() { - return resourceType; - } - - public void setResourceType(ResourceType resourceType) { - this.resourceType = resourceType; - } - - public String getPriority() { - return priority; - } - - public void setPriority(String priority) { - this.priority = priority; - } - - public Boolean getOpenByDefault() { - return openByDefault; - } - - public void setOpenByDefault(Boolean openByDefault) { - this.openByDefault = openByDefault; - } - - public String getCancerStudyIdentifier() { - return cancerStudyIdentifier; - } - - public void setCancerStudyIdentifier(String cancerStudyIdentifier) { - this.cancerStudyIdentifier = cancerStudyIdentifier; - } - -} diff --git a/src/main/java/org/cbioportal/model/ResourceType.java b/src/main/java/org/cbioportal/model/ResourceType.java deleted file mode 100644 index 17a9a09df40..00000000000 --- a/src/main/java/org/cbioportal/model/ResourceType.java +++ /dev/null @@ -1,7 +0,0 @@ -package org.cbioportal.model; - -public enum ResourceType { - STUDY, - SAMPLE, - PATIENT -} diff --git a/src/main/java/org/cbioportal/model/Sample.java b/src/main/java/org/cbioportal/model/Sample.java deleted file mode 100644 index a3d72e955ce..00000000000 --- a/src/main/java/org/cbioportal/model/Sample.java +++ /dev/null @@ -1,141 +0,0 @@ -package org.cbioportal.model; - -import jakarta.validation.constraints.NotNull; -import java.util.Objects; - -public class Sample extends UniqueKeyBase { - - public enum SampleType { - - PRIMARY_SOLID_TUMOR("Primary Solid Tumor"), - RECURRENT_SOLID_TUMOR("Recurrent Solid Tumor"), - PRIMARY_BLOOD_TUMOR("Primary Blood Tumor"), - RECURRENT_BLOOD_TUMOR("Recurrent Blood Tumor"), - METASTATIC("Metastatic"), - BLOOD_NORMAL("Blood Derived Normal"), - SOLID_NORMAL("Solid Tissues Normal"); - - private String value; - - SampleType(String value) { - this.value = value; - } - - public String getValue() { - return value; - } - - public static SampleType fromString(String value) { - - if (value != null) { - for (SampleType sampleType : SampleType.values()) { - if (value.equalsIgnoreCase(sampleType.value)) { - return sampleType; - } - } - } - return null; - } - - @Override - public String toString() { - return value; - } - } - - private Integer internalId; - @NotNull - private String stableId; - private SampleType sampleType; - private Integer patientId; - @NotNull - private String patientStableId; - private Patient patient; - @NotNull - private String cancerStudyIdentifier; - private Boolean sequenced; - private Boolean copyNumberSegmentPresent; - - public Integer getInternalId() { - return internalId; - } - - public void setInternalId(Integer internalId) { - this.internalId = internalId; - } - - public String getStableId() { - return stableId; - } - - public void setStableId(String stableId) { - this.stableId = stableId; - } - - public SampleType getSampleType() { - return sampleType; - } - - public void setSampleType(SampleType sampleType) { - this.sampleType = sampleType; - } - - public Integer getPatientId() { - return patientId; - } - - public void setPatientId(Integer patientId) { - this.patientId = patientId; - } - - public String getPatientStableId() { - return patientStableId; - } - - public void setPatientStableId(String patientStableId) { - this.patientStableId = patientStableId; - } - - public Patient getPatient() { - return patient; - } - - public void setPatient(Patient patient) { - this.patient = patient; - } - - public String getCancerStudyIdentifier() { - return cancerStudyIdentifier; - } - - public void setCancerStudyIdentifier(String cancerStudyIdentifier) { - this.cancerStudyIdentifier = cancerStudyIdentifier; - } - - public Boolean getSequenced() { - return sequenced; - } - - public void setSequenced(Boolean sequenced) { - this.sequenced = sequenced; - } - - public Boolean getCopyNumberSegmentPresent() { return copyNumberSegmentPresent; } - - public void setCopyNumberSegmentPresent(Boolean copyNumberSegmentPresent) { - this.copyNumberSegmentPresent = copyNumberSegmentPresent; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (!(o instanceof Sample)) return false; - Sample sample = (Sample) o; - return getStableId().equals(sample.getStableId()) && getCancerStudyIdentifier().equals(sample.getCancerStudyIdentifier()); - } - - @Override - public int hashCode() { - return Objects.hash(getStableId(), getCancerStudyIdentifier()); - } -} diff --git a/src/main/java/org/cbioportal/model/SampleClinicalDataCollection.java b/src/main/java/org/cbioportal/model/SampleClinicalDataCollection.java deleted file mode 100644 index c67d5277e8b..00000000000 --- a/src/main/java/org/cbioportal/model/SampleClinicalDataCollection.java +++ /dev/null @@ -1,36 +0,0 @@ -package org.cbioportal.model; - -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -public final class SampleClinicalDataCollection { - - private final Map> byUniqueSampleKey; - - private SampleClinicalDataCollection(Builder builder) { - this.byUniqueSampleKey = Collections.unmodifiableMap(new HashMap<>(builder.byUniqueSampleKey)); - } - - public Map> getByUniqueSampleKey() { - return byUniqueSampleKey; - } - - public static Builder builder() { - return new Builder(); - } - - public static class Builder { - private final Map> byUniqueSampleKey = new HashMap<>(); - - public Builder withByUniqueSampleKey(Map> byUniqueSampleKey) { - this.byUniqueSampleKey.putAll(byUniqueSampleKey); - return this; - } - - public SampleClinicalDataCollection build() { - return new SampleClinicalDataCollection(this); - } - } -} diff --git a/src/main/java/org/cbioportal/model/SampleList.java b/src/main/java/org/cbioportal/model/SampleList.java deleted file mode 100644 index bda4d2fc681..00000000000 --- a/src/main/java/org/cbioportal/model/SampleList.java +++ /dev/null @@ -1,101 +0,0 @@ -package org.cbioportal.model; - -import java.io.Serializable; -import java.util.List; - -import jakarta.validation.constraints.NotNull; - -public class SampleList implements Serializable { - - private Integer listId; - @NotNull - private String stableId; - private String category; - private Integer cancerStudyId; - private String cancerStudyIdentifier; - private CancerStudy cancerStudy; - private String name; - private String description; - private Integer sampleCount; - private List sampleIds; - - public Integer getListId() { - return listId; - } - - public void setListId(Integer listId) { - this.listId = listId; - } - - public String getStableId() { - return stableId; - } - - public void setStableId(String stableId) { - this.stableId = stableId; - } - - public String getCategory() { - return category; - } - - public void setCategory(String category) { - this.category = category; - } - - public Integer getCancerStudyId() { - return cancerStudyId; - } - - public void setCancerStudyId(Integer cancerStudyId) { - this.cancerStudyId = cancerStudyId; - } - - public String getCancerStudyIdentifier() { - return cancerStudyIdentifier; - } - - public void setCancerStudyIdentifier(String cancerStudyIdentifier) { - this.cancerStudyIdentifier = cancerStudyIdentifier; - } - - public CancerStudy getCancerStudy() { - return cancerStudy; - } - - public void setCancerStudy(CancerStudy cancerStudy) { - this.cancerStudy = cancerStudy; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String getDescription() { - return description; - } - - public void setDescription(String description) { - this.description = description; - } - - public Integer getSampleCount() { - return sampleCount; - } - - public void setSampleCount(Integer sampleCount) { - this.sampleCount = sampleCount; - } - - public List getSampleIds() { - return sampleIds; - } - - public void setSampleIds(List sampleIds) { - this.sampleIds = sampleIds; - } -} diff --git a/src/main/java/org/cbioportal/model/SampleListToSampleId.java b/src/main/java/org/cbioportal/model/SampleListToSampleId.java deleted file mode 100644 index bfbdb9f548b..00000000000 --- a/src/main/java/org/cbioportal/model/SampleListToSampleId.java +++ /dev/null @@ -1,27 +0,0 @@ -package org.cbioportal.model; - -import java.io.Serializable; -import jakarta.validation.constraints.NotNull; - -public class SampleListToSampleId implements Serializable { - - private Integer sampleListId; - @NotNull - private String sampleId; - - public Integer getSampleListId() { - return sampleListId; - } - - public void setSampleListId(Integer sampleListId) { - this.sampleListId = sampleListId; - } - - public String getSampleId() { - return sampleId; - } - - public void setSampleId(String sampleId) { - this.sampleId = sampleId; - } -} diff --git a/src/main/java/org/cbioportal/model/SampleTreatment.java b/src/main/java/org/cbioportal/model/SampleTreatment.java deleted file mode 100644 index edf9ef7541a..00000000000 --- a/src/main/java/org/cbioportal/model/SampleTreatment.java +++ /dev/null @@ -1,4 +0,0 @@ -package org.cbioportal.model; - -public record SampleTreatment(String treatment, int preSampleCount, int postSampleCount) { -} diff --git a/src/main/java/org/cbioportal/model/SampleTreatmentReport.java b/src/main/java/org/cbioportal/model/SampleTreatmentReport.java deleted file mode 100644 index 12cf93f4fa6..00000000000 --- a/src/main/java/org/cbioportal/model/SampleTreatmentReport.java +++ /dev/null @@ -1,6 +0,0 @@ -package org.cbioportal.model; - -import java.util.Collection; - -public record SampleTreatmentReport(int totalSamples, Collection treatments) { -} diff --git a/src/main/java/org/cbioportal/model/SampleTreatmentRow.java b/src/main/java/org/cbioportal/model/SampleTreatmentRow.java deleted file mode 100644 index ff3c56693c9..00000000000 --- a/src/main/java/org/cbioportal/model/SampleTreatmentRow.java +++ /dev/null @@ -1,79 +0,0 @@ -package org.cbioportal.model; - -import java.io.Serializable; -import java.util.Objects; -import java.util.Set; - -public class SampleTreatmentRow implements TreatmentRow, Serializable { - private TemporalRelation time; - private String treatment; - private int count; - private Set samples; - - public SampleTreatmentRow() {} - - public SampleTreatmentRow(TemporalRelation time, String treatment, int count, Set samples) { - this.time = time; - this.treatment = treatment; - this.count = count; - this.samples = samples; - } - - public TemporalRelation getTime() { - return time; - } - - public void setTime(TemporalRelation time) { - this.time = time; - } - - public String getTreatment() { - return treatment; - } - - public void setTreatment(String treatment) { - this.treatment = treatment; - } - - public int getCount() { - return count; - } - - public void setCount(int count) { - this.count = count; - } - - @Override - public Set getSamples() { - return samples; - } - - public void setSamples(Set samples) { - this.samples = samples; - } - - public String key() { - return getTreatment() + getTime().name(); - } - - public void add(SampleTreatmentRow toAdd) { - getSamples().addAll(toAdd.getSamples()); - setCount(getSamples().size()); - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - SampleTreatmentRow that = (SampleTreatmentRow) o; - return getCount() == that.getCount() && - getTime() == that.getTime() && - getTreatment().equals(that.getTreatment()) && - Objects.equals(getSamples(), that.getSamples()); - } - - @Override - public int hashCode() { - return Objects.hash(getTime(), getTreatment(), getCount(), getSamples()); - } -} diff --git a/src/main/java/org/cbioportal/model/StructuralVariant.java b/src/main/java/org/cbioportal/model/StructuralVariant.java deleted file mode 100644 index 3c803a1b337..00000000000 --- a/src/main/java/org/cbioportal/model/StructuralVariant.java +++ /dev/null @@ -1,460 +0,0 @@ -/* - * Copyright (c) 2018 - 2022 The Hyve B.V. - * This code is licensed under the GNU Affero General Public License (AGPL), - * version 3, or (at your option) any later version. - */ - -/* - * This file is part of cBioPortal. - * - * cBioPortal is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -package org.cbioportal.model; - -import com.fasterxml.jackson.annotation.*; -import io.swagger.v3.oas.annotations.media.Schema; -import org.cbioportal.model.UniqueKeyBase; - -import java.io.Serializable; - -public class StructuralVariant extends UniqueKeyBase implements Serializable { - - private String molecularProfileId; - private String sampleId; - private String patientId; - private String studyId; - private Integer site1EntrezGeneId; - private String site1HugoSymbol; - private String site1EnsemblTranscriptId; - private String site1Chromosome; - private Integer site1Position; - private String site1Contig; - private String site1Region; - private Integer site1RegionNumber; - private String site1Description; - private Integer site2EntrezGeneId; - private String site2HugoSymbol; - private String site2EnsemblTranscriptId; - private String site2Chromosome; - private Integer site2Position; - private String site2Contig; - private String site2Region; - private Integer site2RegionNumber; - private String site2Description; - private String site2EffectOnFrame; - private String ncbiBuild; - private String dnaSupport; - private String rnaSupport; - private Integer normalReadCount; - private Integer tumorReadCount; - private Integer normalVariantCount; - private Integer tumorVariantCount; - private Integer normalPairedEndReadCount; - private Integer tumorPairedEndReadCount; - private Integer normalSplitReadCount; - private Integer tumorSplitReadCount; - private String annotation; - private String breakpointType; - private String connectionType; - private String eventInfo; - private String variantClass; - private Integer length; - private String comments; - private String driverFilter; - private String driverFilterAnn; - private String driverTiersFilter; - private String driverTiersFilterAnn; - private String svStatus; - - @JsonRawValue - @Schema(type = "java.util.Map") - private Object annotationJson; - - public String getMolecularProfileId() { - return molecularProfileId; - } - - public void setMolecularProfileId(String molecularProfileId) { - this.molecularProfileId = molecularProfileId; - } - - public String getSampleId() { - return sampleId; - } - - public void setSampleId(String tumorSampleBarcode) { - this.sampleId = tumorSampleBarcode; - } - - public String getPatientId() { - return patientId; - } - - public void setPatientId(String patientId) { - this.patientId = patientId; - } - - public String getStudyId() { - return studyId; - } - - public void setStudyId(String studyId) { - this.studyId = studyId; - } - - public Integer getSite1EntrezGeneId() { - return site1EntrezGeneId; - } - - public void setSite1EntrezGeneId(Integer site1EntrezGeneId) { - this.site1EntrezGeneId = site1EntrezGeneId; - } - - public String getSite1HugoSymbol() { - return site1HugoSymbol; - } - - public void setSite1HugoSymbol(String site1HugoSymbol) { - this.site1HugoSymbol = site1HugoSymbol; - } - - public String getSite1EnsemblTranscriptId() { - return site1EnsemblTranscriptId; - } - - public void setSite1EnsemblTranscriptId(String site1TranscriptId) { - this.site1EnsemblTranscriptId = site1TranscriptId; - } - - public String getSite1Chromosome() { - return site1Chromosome; - } - - public void setSite1Chromosome(String site1Chrom) { - this.site1Chromosome = site1Chrom; - } - - public Integer getSite1Position() { - return site1Position; - } - - public void setSite1Position(Integer site1Pos) { - this.site1Position = site1Pos; - } - - public String getSite1Description() { - return site1Description; - } - - public void setSite1Description(String site1Desc) { - this.site1Description = site1Desc; - } - - public Integer getSite2EntrezGeneId() { - return site2EntrezGeneId; - } - - public void setSite2EntrezGeneId(Integer site2EntrezGeneId) { - this.site2EntrezGeneId = site2EntrezGeneId; - } - - public String getSite2HugoSymbol() { - return site2HugoSymbol; - } - - public void setSite2HugoSymbol(String site2HugoSymbol) { - this.site2HugoSymbol = site2HugoSymbol; - } - - public String getSite2EnsemblTranscriptId() { - return site2EnsemblTranscriptId; - } - - public void setSite2EnsemblTranscriptId(String site2TranscriptId) { - this.site2EnsemblTranscriptId = site2TranscriptId; - } - - public String getSite2Chromosome() { - return site2Chromosome; - } - - public void setSite2Chromosome(String site2Chrom) { - this.site2Chromosome = site2Chrom; - } - - public Integer getSite2Position() { - return site2Position; - } - - public void setSite2Position(Integer site2Pos) { - this.site2Position = site2Pos; - } - - public String getSite2Description() { - return site2Description; - } - - public void setSite2Description(String site2Desc) { - this.site2Description = site2Desc; - } - - public String getSite2EffectOnFrame() { - return site2EffectOnFrame; - } - - public void setSite2EffectOnFrame(String site2EffectOnFrame) { - this.site2EffectOnFrame = site2EffectOnFrame; - } - - public String getNcbiBuild() { - return ncbiBuild; - } - - public void setNcbiBuild(String ncbiBuild) { - this.ncbiBuild = ncbiBuild; - } - - public String getDnaSupport() { - return dnaSupport; - } - - public void setDnaSupport(String dnaSupport) { - this.dnaSupport = dnaSupport; - } - - public String getRnaSupport() { - return rnaSupport; - } - - public void setRnaSupport(String rnaSupport) { - this.rnaSupport = rnaSupport; - } - - public Integer getNormalReadCount() { - return normalReadCount; - } - - public void setNormalReadCount(Integer normalReadCount) { - this.normalReadCount = normalReadCount; - } - - public Integer getTumorReadCount() { - return tumorReadCount; - } - - public void setTumorReadCount(Integer tumorReadCount) { - this.tumorReadCount = tumorReadCount; - } - - public Integer getNormalVariantCount() { - return normalVariantCount; - } - - public void setNormalVariantCount(Integer normalVariantCount) { - this.normalVariantCount = normalVariantCount; - } - - public Integer getTumorVariantCount() { - return tumorVariantCount; - } - - public void setTumorVariantCount(Integer tumorVariantCount) { - this.tumorVariantCount = tumorVariantCount; - } - - public Integer getNormalPairedEndReadCount() { - return normalPairedEndReadCount; - } - - public void setNormalPairedEndReadCount(Integer normalPairedEndReadCount) { - this.normalPairedEndReadCount = normalPairedEndReadCount; - } - - public Integer getTumorPairedEndReadCount() { - return tumorPairedEndReadCount; - } - - public void setTumorPairedEndReadCount(Integer tumorPairedEndReadCount) { - this.tumorPairedEndReadCount = tumorPairedEndReadCount; - } - - public Integer getNormalSplitReadCount() { - return normalSplitReadCount; - } - - public void setNormalSplitReadCount(Integer normalSplitReadCount) { - this.normalSplitReadCount = normalSplitReadCount; - } - - public Integer getTumorSplitReadCount() { - return tumorSplitReadCount; - } - - public void setTumorSplitReadCount(Integer tumorSplitReadCount) { - this.tumorSplitReadCount = tumorSplitReadCount; - } - - public String getAnnotation() { - return annotation; - } - - public void setAnnotation(String annotation) { - this.annotation = annotation; - } - - public String getBreakpointType() { - return breakpointType; - } - - public void setBreakpointType(String breakpointType) { - this.breakpointType = breakpointType; - } - - public String getConnectionType() { - return connectionType; - } - - public void setConnectionType(String connectionType) { - this.connectionType = connectionType; - } - - public String getEventInfo() { - return eventInfo; - } - - public void setEventInfo(String eventInfo) { - this.eventInfo = eventInfo; - } - - public String getVariantClass() { - return variantClass; - } - - public void setVariantClass(String variantClass) { - this.variantClass = variantClass; - } - - public Integer getLength() { - return length; - } - - public void setLength(Integer length) { - this.length = length; - } - - public String getComments() { - return comments; - } - - public void setComments(String comments) { - this.comments = comments; - } - - public String getDriverFilter() { - return driverFilter; - } - - public void setDriverFilter(String driverFilter) { - this.driverFilter = driverFilter; - } - - public String getDriverFilterAnn() { - return driverFilterAnn; - } - - public void setDriverFilterAnn(String driverFilterAnn) { - this.driverFilterAnn = driverFilterAnn; - } - - public String getDriverTiersFilter() { - return driverTiersFilter; - } - - public void setDriverTiersFilter(String driverTiersFilter) { - this.driverTiersFilter = driverTiersFilter; - } - - public String getDriverTiersFilterAnn() { - return driverTiersFilterAnn; - } - - public void setDriverTiersFilterAnn(String driverTiersFilterAnn) { - this.driverTiersFilterAnn = driverTiersFilterAnn; - } - - public String getSvStatus() { - return svStatus; - } - - public void setSvStatus(String svStatus) { - this.svStatus = svStatus; - } - - public String getSite1Contig() { - return site1Contig; - } - - public void setSite1Contig(String site1Contig) { - this.site1Contig = site1Contig; - } - - public String getSite1Region() { - return site1Region; - } - - public void setSite1Region(String site1Region) { - this.site1Region = site1Region; - } - - public Integer getSite1RegionNumber() { - return site1RegionNumber; - } - - public void setSite1RegionNumber(Integer site1RegionNumber) { - this.site1RegionNumber = site1RegionNumber; - } - - public String getSite2Contig() { - return site2Contig; - } - - public void setSite2Contig(String site2Contig) { - this.site2Contig = site2Contig; - } - - public String getSite2Region() { - return site2Region; - } - - public void setSite2Region(String site2Region) { - this.site2Region = site2Region; - } - - public Integer getSite2RegionNumber() { - return site2RegionNumber; - } - - public void setSite2RegionNumber(Integer site2RegionNumber) { - this.site2RegionNumber = site2RegionNumber; - } - - public Object getAnnotationJson() { - return annotationJson; - } - - public void setAnnotationJson(String annotationJson) { - this.annotationJson = annotationJson; - } -} diff --git a/src/main/java/org/cbioportal/model/StructuralVariantFilterQuery.java b/src/main/java/org/cbioportal/model/StructuralVariantFilterQuery.java deleted file mode 100644 index 0b857f2367a..00000000000 --- a/src/main/java/org/cbioportal/model/StructuralVariantFilterQuery.java +++ /dev/null @@ -1,48 +0,0 @@ -package org.cbioportal.model; - -import org.cbioportal.model.util.Select; -import org.springframework.lang.Nullable; - -import java.io.Serializable; - -public class StructuralVariantFilterQuery extends BaseAlterationFilter implements Serializable { - - private StructuralVariantGeneSubQuery gene1Query; - private StructuralVariantGeneSubQuery gene2Query; - - public StructuralVariantFilterQuery() {} - - public StructuralVariantFilterQuery(String gene1HugoSymbol, - @Nullable Integer gene1EntrezId, - String gene2HugoSymbol, - @Nullable Integer gene2EntrezId, - boolean includeDriver, - boolean includeVUS, - boolean includeUnknownOncogenicity, - Select tiersSelect, - boolean includeUnknownTier, - boolean includeGermline, - boolean includeSomatic, - boolean includeUnknownStatus) { - super(includeDriver, includeVUS, includeUnknownOncogenicity, includeGermline, includeSomatic, includeUnknownStatus, tiersSelect, includeUnknownTier); - this.gene1Query = new StructuralVariantGeneSubQuery(gene1HugoSymbol, gene1EntrezId); - this.gene2Query = new StructuralVariantGeneSubQuery(gene2HugoSymbol, gene2EntrezId); - } - - public StructuralVariantGeneSubQuery getGene1Query() { - return gene1Query; - } - - public void setGene1Query(StructuralVariantGeneSubQuery gene1Query) { - this.gene1Query = gene1Query; - } - - public StructuralVariantGeneSubQuery getGene2Query() { - return gene2Query; - } - - public void setGene2Query(StructuralVariantGeneSubQuery gene2Query) { - this.gene2Query = gene2Query; - } - -} diff --git a/src/main/java/org/cbioportal/model/StructuralVariantGeneSubQuery.java b/src/main/java/org/cbioportal/model/StructuralVariantGeneSubQuery.java deleted file mode 100644 index 224ba6bec2a..00000000000 --- a/src/main/java/org/cbioportal/model/StructuralVariantGeneSubQuery.java +++ /dev/null @@ -1,85 +0,0 @@ -package org.cbioportal.model; - -import com.fasterxml.jackson.annotation.JsonIgnore; -import org.springframework.lang.Nullable; - -import jakarta.validation.constraints.AssertTrue; -import java.io.Serializable; - -public class StructuralVariantGeneSubQuery implements Serializable { - - @Nullable - protected String hugoSymbol; - - @Nullable - protected Integer entrezId; - - @Nullable - protected StructuralVariantSpecialValue specialValue; - - @JsonIgnore - @AssertTrue(message = "Should contain only one EntrezId, hugoSymbol or specialValue.") - public boolean isContainingOnlyOneIdentifierOrSpecialValue() { - int fieldCount = 0; - if (entrezId != null) { - fieldCount++; - } - if (hugoSymbol != null) { - fieldCount++; - } - if (specialValue != null) { - fieldCount++; - } - return fieldCount == 1; - } - - public StructuralVariantGeneSubQuery() {} - - public StructuralVariantGeneSubQuery(String hugoSymbol) { - this.hugoSymbol = hugoSymbol; - } - - public StructuralVariantGeneSubQuery(Integer entrezId) { - this.entrezId = entrezId; - } - - public StructuralVariantGeneSubQuery(StructuralVariantSpecialValue specialValue) { - this.specialValue = specialValue; - } - - public StructuralVariantGeneSubQuery(String hugoSymbol, Integer entrezId) { - this.entrezId = entrezId; - this.hugoSymbol = hugoSymbol; - if (hugoSymbol == null && entrezId == null) { - this.specialValue = StructuralVariantSpecialValue.NO_GENE; - } - } - - @Nullable - public String getHugoSymbol() { - return hugoSymbol; - } - - public void setHugoSymbol(@Nullable String hugoSymbol) { - this.hugoSymbol = hugoSymbol; - } - - @Nullable - public StructuralVariantSpecialValue getSpecialValue() { - return specialValue; - } - - public void setSpecialValue(@Nullable StructuralVariantSpecialValue specialValue) { - this.specialValue = specialValue; - } - - @Nullable - public Integer getEntrezId() { - return entrezId; - } - - public void setEntrezId(@Nullable Integer entrezId) { - this.entrezId = entrezId; - } -} - diff --git a/src/main/java/org/cbioportal/model/StructuralVariantQuery.java b/src/main/java/org/cbioportal/model/StructuralVariantQuery.java deleted file mode 100644 index 6dc8856869e..00000000000 --- a/src/main/java/org/cbioportal/model/StructuralVariantQuery.java +++ /dev/null @@ -1,42 +0,0 @@ -package org.cbioportal.model; - -import jakarta.validation.Valid; -import java.io.Serializable; - -public class StructuralVariantQuery implements Serializable { - - @Valid - private StructuralVariantGeneSubQuery gene1; - - @Valid - private StructuralVariantGeneSubQuery gene2; - - public StructuralVariantQuery( - StructuralVariantGeneSubQuery gene1, - StructuralVariantGeneSubQuery gene2 - ) { - this.gene1 = gene1; - this.gene2 = gene2; - } - - public StructuralVariantQuery() { - // Needed by jackson - } - - public StructuralVariantGeneSubQuery getGene1() { - return gene1; - } - - public void setGene1(StructuralVariantGeneSubQuery gene1) { - this.gene1 = gene1; - } - - public StructuralVariantGeneSubQuery getGene2() { - return gene2; - } - - public void setGene2(StructuralVariantGeneSubQuery gene2) { - this.gene2 = gene2; - } - -} diff --git a/src/main/java/org/cbioportal/model/StructuralVariantSpecialValue.java b/src/main/java/org/cbioportal/model/StructuralVariantSpecialValue.java deleted file mode 100644 index 8af29b9fd75..00000000000 --- a/src/main/java/org/cbioportal/model/StructuralVariantSpecialValue.java +++ /dev/null @@ -1,15 +0,0 @@ -package org.cbioportal.model; - -public enum StructuralVariantSpecialValue { - - /** - * Match any gene - */ - ANY_GENE, - - /** - * Match gene IS NULL - */ - NO_GENE; - -} diff --git a/src/main/java/org/cbioportal/model/StudyViewFilterContext.java b/src/main/java/org/cbioportal/model/StudyViewFilterContext.java deleted file mode 100644 index e23e5f7d9d4..00000000000 --- a/src/main/java/org/cbioportal/model/StudyViewFilterContext.java +++ /dev/null @@ -1,14 +0,0 @@ -package org.cbioportal.model; - -import org.cbioportal.web.parameter.CustomSampleIdentifier; -import org.cbioportal.web.parameter.StudyViewFilter; - -import java.util.List; - -public record StudyViewFilterContext( - StudyViewFilter studyViewFilter, - List customDataFilterSamples, - List involvedCancerStudies -) { - -} diff --git a/src/main/java/org/cbioportal/model/StudyViewStructuralVariantFilter.java b/src/main/java/org/cbioportal/model/StudyViewStructuralVariantFilter.java deleted file mode 100644 index d4ae0879873..00000000000 --- a/src/main/java/org/cbioportal/model/StudyViewStructuralVariantFilter.java +++ /dev/null @@ -1,63 +0,0 @@ -package org.cbioportal.model; - -import jakarta.validation.constraints.AssertTrue; -import java.io.Serializable; -import java.util.List; -import java.util.Set; - -public class StudyViewStructuralVariantFilter implements Serializable { - - private Set molecularProfileIds; - private List> structVarQueries; - - @AssertTrue(message = "'specialValue' field of gene1/gene2 StructVarGeneSubQueries cannot be both ANY_GENE or NO_GENE.") - private boolean isGeneQueriesSpecialValueCorrect() { - return structVarQueries.stream() - .flatMap(queryList -> queryList.stream()) - .filter(structVarFilterQuery -> structVarFilterQuery.getGene1Query().getSpecialValue() != null - && structVarFilterQuery.getGene2Query().getSpecialValue() != null - ) - .noneMatch(structVarFilterQuery -> - structVarFilterQuery.getGene1Query().getSpecialValue() == - structVarFilterQuery.getGene2Query().getSpecialValue() - ); - } - - @AssertTrue(message = "'geneId' field of gene1/gene2 StructVarGeneSubQueries cannot be both null.") - private boolean isGeneQueriesGeneIdCorrect() { - return structVarQueries.stream() - .flatMap(queryList -> queryList.stream()) - .noneMatch(structVarFilterQuery -> - structVarFilterQuery.getGene1Query().getHugoSymbol() == null && - structVarFilterQuery.getGene2Query().getHugoSymbol() == null - ); - } - - @AssertTrue(message = "'geneId' field of gene1/gene2 StructVarGeneSubQueries cannot be null when no specialValue set.") - private boolean isGeneQueriesHasGeneIdWhenSpecialValueNull() { - return structVarQueries.stream() - .flatMap(queryList -> queryList.stream()) - .noneMatch(structVarFilterQuery -> - (structVarFilterQuery.getGene1Query().getHugoSymbol() == null && - structVarFilterQuery.getGene1Query().getSpecialValue() == null) - || (structVarFilterQuery.getGene2Query().getHugoSymbol() == null && - structVarFilterQuery.getGene2Query().getSpecialValue() == null) - ); - } - - public Set getMolecularProfileIds() { - return molecularProfileIds; - } - - public void setMolecularProfileIds(Set molecularProfileIds) { - this.molecularProfileIds = molecularProfileIds; - } - - public List> getStructVarQueries() { - return structVarQueries; - } - - public void setStructVarQueries(List> structVarQueries) { - this.structVarQueries = structVarQueries; - } -} \ No newline at end of file diff --git a/src/main/java/org/cbioportal/model/TableTimestampPair.java b/src/main/java/org/cbioportal/model/TableTimestampPair.java deleted file mode 100644 index 1587bfc8e85..00000000000 --- a/src/main/java/org/cbioportal/model/TableTimestampPair.java +++ /dev/null @@ -1,26 +0,0 @@ -package org.cbioportal.model; - -import jakarta.validation.constraints.NotNull; -import java.io.Serializable; - -public class TableTimestampPair implements Serializable { - @NotNull - private String tableName; - private String updateTime; - - public String getUpdateTime() { - return updateTime; - } - - public void setUpdateTime(String updateTime) { - this.updateTime = updateTime; - } - - public String getTableName() { - return tableName; - } - - public void setTableName(String tableName) { - this.tableName = tableName; - } -} diff --git a/src/main/java/org/cbioportal/model/TemporalRelation.java b/src/main/java/org/cbioportal/model/TemporalRelation.java deleted file mode 100644 index 8c204c46208..00000000000 --- a/src/main/java/org/cbioportal/model/TemporalRelation.java +++ /dev/null @@ -1,6 +0,0 @@ -package org.cbioportal.model; - -public enum TemporalRelation { - Pre, - Post -} diff --git a/src/main/java/org/cbioportal/model/Treatment.java b/src/main/java/org/cbioportal/model/Treatment.java deleted file mode 100644 index 746d88dcebe..00000000000 --- a/src/main/java/org/cbioportal/model/Treatment.java +++ /dev/null @@ -1,69 +0,0 @@ -package org.cbioportal.model; - -import java.io.Serializable; -import java.util.Objects; - -public class Treatment implements Serializable { - private String treatment; - private String studyId; - private String patientId; - private Integer start; - private Integer stop; - - public String getTreatment() { - return treatment; - } - - public void setTreatment(String treatment) { - this.treatment = treatment; - } - - public String getStudyId() { - return studyId; - } - - public void setStudyId(String studyId) { - this.studyId = studyId; - } - - public String getPatientId() { - return patientId; - } - - public void setPatientId(String patientId) { - this.patientId = patientId; - } - - public Integer getStart() { - return start; - } - - public void setStart(Integer start) { - this.start = start; - } - - public Integer getStop() { - return stop; - } - - public void setStop(Integer stop) { - this.stop = stop; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (!(o instanceof Treatment)) return false; - Treatment treatment1 = (Treatment) o; - return getTreatment().equals(treatment1.getTreatment()) && - getStudyId().equals(treatment1.getStudyId()) && - getPatientId().equals(treatment1.getPatientId()) && - Objects.equals(getStart(), treatment1.getStart()) && - Objects.equals(getStop(), treatment1.getStop()); - } - - @Override - public int hashCode() { - return Objects.hash(getTreatment(), getStudyId(), getPatientId(), getStart(), getStop()); - } -} diff --git a/src/main/java/org/cbioportal/model/TreatmentRow.java b/src/main/java/org/cbioportal/model/TreatmentRow.java deleted file mode 100644 index 32662b7222c..00000000000 --- a/src/main/java/org/cbioportal/model/TreatmentRow.java +++ /dev/null @@ -1,7 +0,0 @@ -package org.cbioportal.model; - -import java.util.Set; - -public interface TreatmentRow { - public Set getSamples(); -} diff --git a/src/main/java/org/cbioportal/model/TypeOfCancer.java b/src/main/java/org/cbioportal/model/TypeOfCancer.java deleted file mode 100644 index 6c564c3e37a..00000000000 --- a/src/main/java/org/cbioportal/model/TypeOfCancer.java +++ /dev/null @@ -1,54 +0,0 @@ -package org.cbioportal.model; - -import java.io.Serializable; -import jakarta.validation.constraints.NotNull; - -public class TypeOfCancer implements Serializable { - - @NotNull - private String typeOfCancerId; - private String name; - private String dedicatedColor; - private String shortName; - private String parent; - - public String getTypeOfCancerId() { - return typeOfCancerId; - } - - public void setTypeOfCancerId(String typeOfCancerId) { - this.typeOfCancerId = typeOfCancerId; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String getDedicatedColor() { - return dedicatedColor; - } - - public void setDedicatedColor(String dedicatedColor) { - this.dedicatedColor = dedicatedColor; - } - - public String getShortName() { - return shortName; - } - - public void setShortName(String shortName) { - this.shortName = shortName; - } - - public String getParent() { - return parent; - } - - public void setParent(String parent) { - this.parent = parent; - } -} \ No newline at end of file diff --git a/src/main/java/org/cbioportal/model/UniqueKeyBase.java b/src/main/java/org/cbioportal/model/UniqueKeyBase.java deleted file mode 100644 index 33198b81f3b..00000000000 --- a/src/main/java/org/cbioportal/model/UniqueKeyBase.java +++ /dev/null @@ -1,25 +0,0 @@ -package org.cbioportal.model; - -import java.io.Serializable; - -public abstract class UniqueKeyBase implements Serializable { - - private String uniqueSampleKey; - private String uniquePatientKey; - - public String getUniqueSampleKey() { - return uniqueSampleKey; - } - - public void setUniqueSampleKey(String uniqueSampleKey) { - this.uniqueSampleKey = uniqueSampleKey; - } - - public String getUniquePatientKey() { - return uniquePatientKey; - } - - public void setUniquePatientKey(String uniquePatientKey) { - this.uniquePatientKey = uniquePatientKey; - } -} diff --git a/src/main/java/org/cbioportal/model/User.java b/src/main/java/org/cbioportal/model/User.java deleted file mode 100644 index 646e8cac647..00000000000 --- a/src/main/java/org/cbioportal/model/User.java +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright (c) 2015 Memorial Sloan-Kettering Cancer Center. - * - * This library is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS - * FOR A PARTICULAR PURPOSE. The software and documentation provided hereunder - * is on an "as is" basis, and Memorial Sloan-Kettering Cancer Center has no - * obligations to provide maintenance, support, updates, enhancements or - * modifications. In no event shall Memorial Sloan-Kettering Cancer Center be - * liable to any party for direct, indirect, special, incidental or - * consequential damages, including lost profits, arising out of the use of this - * software and its documentation, even if Memorial Sloan-Kettering Cancer - * Center has been advised of the possibility of such damage. - */ - -/* - * This file is part of cBioPortal. - * - * cBioPortal is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . -*/ - -package org.cbioportal.model; - -import java.io.Serializable; - -/** - * This represents a user, identified by an email address. - * - * @author Arthur Goldberg goldberg@cbio.mskcc.org - * @author Benjamin Gross - */ -public class User implements Serializable { - private String email; - private String name; - private boolean enabled; - - public User(String email, String name, boolean enabled) { - if (null == email) { - throw new IllegalArgumentException ("email is null."); - } - this.email = email; - if (null == name) { - throw new IllegalArgumentException ("name is null."); - } - this.name = name; - this.enabled = enabled; - } - - public User(String email, String name, Boolean enabled) { - this(email, name, enabled != null ? enabled.booleanValue() : false); - } - - public String getEmail() { - return email; - } - - public void setEmail(String email) { - this.email = email.toLowerCase(); - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public boolean isEnabled() { - return enabled; - } - - public void setEnabled(boolean enabled) { - this.enabled = enabled; - } - - @Override - public boolean equals(Object otherUser) { - if (this == otherUser) { - return true; - } - - if (!(otherUser instanceof User)) { - return false; - } - - User that = (User) otherUser; - return this.email == that.email - && this.name == that.name; - } - - @Override - public int hashCode() { - int hash = 7; - hash = 67 * hash + (this.email != null ? this.email.hashCode() : 0); - hash = 67 * hash + (this.name != null ? this.name.hashCode() : 0); - return hash; - } -} diff --git a/src/main/java/org/cbioportal/model/UserAuthorities.java b/src/main/java/org/cbioportal/model/UserAuthorities.java deleted file mode 100644 index d8d4e641f6c..00000000000 --- a/src/main/java/org/cbioportal/model/UserAuthorities.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (c) 2015 Memorial Sloan-Kettering Cancer Center. - * - * This library is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS - * FOR A PARTICULAR PURPOSE. The software and documentation provided hereunder - * is on an "as is" basis, and Memorial Sloan-Kettering Cancer Center has no - * obligations to provide maintenance, support, updates, enhancements or - * modifications. In no event shall Memorial Sloan-Kettering Cancer Center be - * liable to any party for direct, indirect, special, incidental or - * consequential damages, including lost profits, arising out of the use of this - * software and its documentation, even if Memorial Sloan-Kettering Cancer - * Center has been advised of the possibility of such damage. - */ - -/* - * This file is part of cBioPortal. - * - * cBioPortal is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . -*/ - -package org.cbioportal.model; - -// imports -import java.io.Serializable; -import java.util.List; - -/** - * User authorites bean. - * - * @author Benjamin Gross - */ -public class UserAuthorities implements Serializable { - - private String email; - private List authorities; - - public UserAuthorities() {} - - /** - * Constructor. - */ - public UserAuthorities(String email, List authorities) { - this.email = email; - this.authorities = authorities; - } - - // accessors - public String getEmail() { return email; } - public void setEmail(String email) { this.email = email.toLowerCase(); } - public List getAuthorities() { return authorities; } - public void setAuthorities(List authorities) { this.authorities = authorities; } -} diff --git a/src/main/java/org/cbioportal/model/VariantCount.java b/src/main/java/org/cbioportal/model/VariantCount.java deleted file mode 100644 index fdc43b721cb..00000000000 --- a/src/main/java/org/cbioportal/model/VariantCount.java +++ /dev/null @@ -1,67 +0,0 @@ -package org.cbioportal.model; - -import java.io.Serializable; -import jakarta.validation.constraints.NotNull; - -public class VariantCount implements Serializable { - - @NotNull - private String molecularProfileId; - @NotNull - private Integer entrezGeneId; - private String keyword; - @NotNull - private Integer numberOfSamples; - @NotNull - private Integer numberOfSamplesWithMutationInGene; - @NotNull - private Integer numberOfSamplesWithKeyword; - - public String getMolecularProfileId() { - return molecularProfileId; - } - - public void setMolecularProfileId(String molecularProfileId) { - this.molecularProfileId = molecularProfileId; - } - - public Integer getEntrezGeneId() { - return entrezGeneId; - } - - public void setEntrezGeneId(Integer entrezGeneId) { - this.entrezGeneId = entrezGeneId; - } - - public String getKeyword() { - return keyword; - } - - public void setKeyword(String keyword) { - this.keyword = keyword; - } - - public Integer getNumberOfSamples() { - return numberOfSamples; - } - - public void setNumberOfSamples(Integer numberOfSamples) { - this.numberOfSamples = numberOfSamples; - } - - public Integer getNumberOfSamplesWithMutationInGene() { - return numberOfSamplesWithMutationInGene; - } - - public void setNumberOfSamplesWithMutationInGene(Integer numberOfSamplesWithMutationInGene) { - this.numberOfSamplesWithMutationInGene = numberOfSamplesWithMutationInGene; - } - - public Integer getNumberOfSamplesWithKeyword() { - return numberOfSamplesWithKeyword; - } - - public void setNumberOfSamplesWithKeyword(Integer numberOfSamplesWithKeyword) { - this.numberOfSamplesWithKeyword = numberOfSamplesWithKeyword; - } -} diff --git a/src/main/java/org/cbioportal/model/meta/BaseMeta.java b/src/main/java/org/cbioportal/model/meta/BaseMeta.java deleted file mode 100644 index dac0a7caba4..00000000000 --- a/src/main/java/org/cbioportal/model/meta/BaseMeta.java +++ /dev/null @@ -1,16 +0,0 @@ -package org.cbioportal.model.meta; - -import java.io.Serializable; - -public class BaseMeta implements Serializable { - - private Integer totalCount; - - public Integer getTotalCount() { - return totalCount; - } - - public void setTotalCount(Integer totalCount) { - this.totalCount = totalCount; - } -} diff --git a/src/main/java/org/cbioportal/model/meta/GenericAssayMeta.java b/src/main/java/org/cbioportal/model/meta/GenericAssayMeta.java deleted file mode 100644 index 2f22fd9b5e0..00000000000 --- a/src/main/java/org/cbioportal/model/meta/GenericAssayMeta.java +++ /dev/null @@ -1,80 +0,0 @@ -package org.cbioportal.model.meta; - -import java.io.Serializable; -import java.util.HashMap; - -public class GenericAssayMeta implements Serializable { - - private String stableId; - private String entityType; - private HashMap genericEntityMetaProperties; - - /** - * Create a generic assay meta object from fields - * - * @param entityType Type of the generic assay meta - * @param stableId Stable identifier of the generic assay - * meta used in the cBioPortal instance - * @param genericEntityMetaProperties generic entity meta properties are the - * additional properties, may differ between - * different generic assay data - */ - - public GenericAssayMeta(String stableId) { - this.stableId = stableId; - } - - public GenericAssayMeta(String entityType, String stableId) { - this.entityType = entityType; - this.stableId = stableId; - this.genericEntityMetaProperties = new HashMap<>(); - } - - public GenericAssayMeta(String entityType, String stableId, HashMap genericEntityMetaProperties) { - this.entityType = entityType; - this.stableId = stableId; - this.genericEntityMetaProperties = genericEntityMetaProperties; - } - - /** - * @return the stableId - */ - public String getStableId() { - return stableId; - } - - /** - * @param stableId the stableId to set - */ - public void setStableId(String stableId) { - this.stableId = stableId; - } - - /** - * @return the entity type - */ - public String getEntityType() { - return entityType; - } - - /** - * @param entityType the entityType to set - */ - public void setEntityType(String entityType) { - this.entityType = entityType; - } - - /** - * @return the generic entity meta properties - */ - public HashMap getGenericEntityMetaProperties() { - return genericEntityMetaProperties; - } - - /** - * @param genericEntityMetaProperties the genericEntityMetaProperties to set - */ - public void setGenericEntityMetaProperties(HashMap genericEntityMetaProperties) { - this.genericEntityMetaProperties = genericEntityMetaProperties; - } -} diff --git a/src/main/java/org/cbioportal/model/meta/MutationMeta.java b/src/main/java/org/cbioportal/model/meta/MutationMeta.java deleted file mode 100644 index bb9f82a83a0..00000000000 --- a/src/main/java/org/cbioportal/model/meta/MutationMeta.java +++ /dev/null @@ -1,14 +0,0 @@ -package org.cbioportal.model.meta; - -public class MutationMeta extends BaseMeta { - - private Integer sampleCount; - - public Integer getSampleCount() { - return sampleCount; - } - - public void setSampleCount(Integer sampleCount) { - this.sampleCount = sampleCount; - } -} diff --git a/src/main/java/org/cbioportal/model/util/QueryElement.java b/src/main/java/org/cbioportal/model/util/QueryElement.java deleted file mode 100644 index d7b78a96de2..00000000000 --- a/src/main/java/org/cbioportal/model/util/QueryElement.java +++ /dev/null @@ -1,5 +0,0 @@ -package org.cbioportal.model.util; - -public enum QueryElement { - INACTIVE, ACTIVE, PASS -} diff --git a/src/main/java/org/cbioportal/model/util/Select.java b/src/main/java/org/cbioportal/model/util/Select.java deleted file mode 100644 index e10f2c0ebda..00000000000 --- a/src/main/java/org/cbioportal/model/util/Select.java +++ /dev/null @@ -1,84 +0,0 @@ -package org.cbioportal.model.util; - -import java.util.*; -import java.util.function.Function; -import java.util.stream.Collectors; -import java.util.stream.Stream; -import java.util.stream.StreamSupport; - -/** - * Used to distinguish selecting all items (no filtering) from select none (filter all). - * Basically it is Iterable that implements the Null Object pattern. - * @param - */ -public class Select implements Iterable { - - private final Iterable iterable; - private boolean hasAllExternal = false; - private boolean inverse = false; - - private static final Select ALL = new Select<>(null); - @SuppressWarnings("unchecked") - public static Select all() { - return (Select) ALL; - } - private static final Select NONE = new Select<>(Collections.emptyList()); - @SuppressWarnings("unchecked") - public static Select none() { - return (Select) NONE; - } - - public static Select byValues(Iterable iterable) { - return new Select<>(iterable); - } - - public static Select byValues(Stream stream) { - return stream == null ? all() : new Select<>(stream.collect(Collectors.toList())); - } - - public Select map(Function function) { - if (hasAll()) { - return all(); - } - if (hasNone()) { - return none(); - } - return Select.byValues(StreamSupport.stream(this.spliterator(), false).map(function)); - } - - private Select(Iterable iterable) { - this.iterable = iterable; - } - - public final boolean hasAll() { - return null == iterable || hasAllExternal; - } - - public final boolean hasNone() { - return !hasAllExternal && !hasAll() && !hasValues(); - } - - public final boolean hasValues() { - return null != iterable && iterable.iterator().hasNext(); - } - - public void hasAll(boolean value) { - this.hasAllExternal = value; - } - - public void inverse(boolean inverse) { - this.inverse = inverse; - } - - public boolean inverse() { - return this.inverse; - } - - @Override - public Iterator iterator() { - if (null == iterable) { - throw new UnsupportedOperationException("Iteration over Select.ALL is not defined."); - } - return iterable.iterator(); - } -} diff --git a/src/main/java/org/cbioportal/persistence/AlterationDriverAnnotationRepository.java b/src/main/java/org/cbioportal/persistence/AlterationDriverAnnotationRepository.java deleted file mode 100644 index d89b33ed9b6..00000000000 --- a/src/main/java/org/cbioportal/persistence/AlterationDriverAnnotationRepository.java +++ /dev/null @@ -1,13 +0,0 @@ -package org.cbioportal.persistence; - -import org.cbioportal.model.AlterationDriverAnnotation; -import org.springframework.cache.annotation.Cacheable; - -import java.util.List; - -public interface AlterationDriverAnnotationRepository { - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - List getAlterationDriverAnnotations(List molecularProfileCaseIdentifiers); - -} \ No newline at end of file diff --git a/src/main/java/org/cbioportal/persistence/AlterationRepository.java b/src/main/java/org/cbioportal/persistence/AlterationRepository.java deleted file mode 100644 index b8f436eea09..00000000000 --- a/src/main/java/org/cbioportal/persistence/AlterationRepository.java +++ /dev/null @@ -1,40 +0,0 @@ -package org.cbioportal.persistence; - -import org.cbioportal.model.*; -import org.cbioportal.model.util.Select; -import org.springframework.cache.annotation.Cacheable; - -import java.util.List; -import java.util.Set; - -public interface AlterationRepository { - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - List getSampleAlterationGeneCounts(Set molecularProfileCaseIdentifiers, - Select entrezGeneIds, - AlterationFilter alterationFilter); - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - List getPatientAlterationGeneCounts(Set molecularProfileCaseIdentifiers, - Select entrezGeneIds, - AlterationFilter alterationFilter); - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - List getSampleCnaGeneCounts(Set molecularProfileCaseIdentifiers, - Select entrezGeneIds, - AlterationFilter alterationFilter); - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - List getPatientCnaGeneCounts(Set molecularProfileCaseIdentifiers, - Select entrezGeneIds, - AlterationFilter alterationFilter); - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - List getSampleStructuralVariantCounts(Set molecularProfileCaseIdentifiers, - AlterationFilter alterationFilter); - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - List getPatientStructuralVariantCounts(Set molecularProfileCaseIdentifiers, - AlterationFilter alterationFilter); - -} diff --git a/src/main/java/org/cbioportal/persistence/CacheEnabledConfig.java b/src/main/java/org/cbioportal/persistence/CacheEnabledConfig.java deleted file mode 100644 index 45b22f5bbf4..00000000000 --- a/src/main/java/org/cbioportal/persistence/CacheEnabledConfig.java +++ /dev/null @@ -1,73 +0,0 @@ -package org.cbioportal.persistence; - -import jakarta.annotation.PostConstruct; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.stereotype.Component; - -import java.util.ArrayList; -import java.util.Arrays; - -@Component -public class CacheEnabledConfig { - - private static final Logger LOG = LoggerFactory.getLogger(CacheEnabledConfig.class); - - @Value("${persistence.cache_type:no-cache}") - private String cacheType; - @Value("${persistence.cache_type_clickhouse:no-cache}") - private String cacheTypeClickhouse; - - private boolean enabled; - private boolean enabledClickhouse; - - public static final String EHCACHE_DISK = "ehcache-disk"; - public static final String EHCACHE_HEAP = "ehcache-heap"; - public static final String EHCACHE_HYBRID = "ehcache-hybrid"; - public static final String REDIS = "redis"; - - public static ArrayList validCacheTypes = new ArrayList(Arrays.asList(EHCACHE_DISK, EHCACHE_HEAP, EHCACHE_HYBRID, REDIS)); - - @PostConstruct - public void init() { - this.enabled = enableCache(cacheType); - LOG.info("Cache is enabled: " + this.enabled); - this.enabledClickhouse = enableCache(cacheTypeClickhouse); - LOG.info("Cache is enabled for clickhouse: " + this.enabledClickhouse); - } - - public static boolean enableCache(String cacheType) { - for (String validCacheType : validCacheTypes) { - if (validCacheType.equalsIgnoreCase(cacheType)) { - return true; - } - } - return false; - } - - public String getEnabled() { - if (enabled) { - return "true"; - } else { - return "false"; - } - } - - public boolean isEnabled() { - return enabled; - } - - public String getEnabledClickhouse() { - if (enabledClickhouse) { - return "true"; - } else { - return "false"; - } - } - - public boolean isEnabledClickhouse() { - return enabledClickhouse; - } - -} diff --git a/src/main/java/org/cbioportal/persistence/CancerTypeRepository.java b/src/main/java/org/cbioportal/persistence/CancerTypeRepository.java deleted file mode 100644 index a670d074007..00000000000 --- a/src/main/java/org/cbioportal/persistence/CancerTypeRepository.java +++ /dev/null @@ -1,20 +0,0 @@ -package org.cbioportal.persistence; - -import org.cbioportal.model.TypeOfCancer; -import org.cbioportal.model.meta.BaseMeta; - -import org.springframework.cache.annotation.Cacheable; - -import java.util.List; - -public interface CancerTypeRepository { - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - List getAllCancerTypes(String projection, Integer pageSize, Integer pageNumber, String sortBy, - String direction); - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - BaseMeta getMetaCancerTypes(); - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - TypeOfCancer getCancerType(String cancerTypeId); -} diff --git a/src/main/java/org/cbioportal/persistence/ClinicalAttributeRepository.java b/src/main/java/org/cbioportal/persistence/ClinicalAttributeRepository.java deleted file mode 100644 index aa7c8ede12f..00000000000 --- a/src/main/java/org/cbioportal/persistence/ClinicalAttributeRepository.java +++ /dev/null @@ -1,44 +0,0 @@ -package org.cbioportal.persistence; - -import org.cbioportal.model.ClinicalAttribute; -import org.cbioportal.model.ClinicalAttributeCount; -import org.cbioportal.model.meta.BaseMeta; - -import org.springframework.cache.annotation.Cacheable; - -import java.util.List; - -public interface ClinicalAttributeRepository { - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - List getAllClinicalAttributes(String projection, Integer pageSize, Integer pageNumber, - String sortBy, String direction); - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - BaseMeta getMetaClinicalAttributes(); - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - ClinicalAttribute getClinicalAttribute(String studyId, String clinicalAttributeId); - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - List getAllClinicalAttributesInStudy(String studyId, String projection, Integer pageSize, - Integer pageNumber, String sortBy, String direction); - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - BaseMeta getMetaClinicalAttributesInStudy(String studyId); - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - List fetchClinicalAttributes(List studyIds, String projection); - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - BaseMeta fetchMetaClinicalAttributes(List studyIds); - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - List getClinicalAttributeCountsBySampleIds(List studyIds, List sampleIds); - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - List getClinicalAttributeCountsBySampleListId(String sampleListId); - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - List getClinicalAttributesByStudyIdsAndAttributeIds(List studyIds, List attributeIds); -} diff --git a/src/main/java/org/cbioportal/persistence/ClinicalDataRepository.java b/src/main/java/org/cbioportal/persistence/ClinicalDataRepository.java deleted file mode 100644 index ed320908d2e..00000000000 --- a/src/main/java/org/cbioportal/persistence/ClinicalDataRepository.java +++ /dev/null @@ -1,69 +0,0 @@ -package org.cbioportal.persistence; - -import org.cbioportal.model.ClinicalData; -import org.cbioportal.model.ClinicalDataCount; -import org.cbioportal.model.meta.BaseMeta; - -import org.springframework.cache.annotation.Cacheable; - -import java.util.List; - -public interface ClinicalDataRepository { - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - List getAllClinicalDataOfSampleInStudy(String studyId, String sampleId, String attributeId, - String projection, Integer pageSize, Integer pageNumber, - String sortBy, String direction); - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - BaseMeta getMetaSampleClinicalData(String studyId, String sampleId, String attributeId); - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - List getAllClinicalDataOfPatientInStudy(String studyId, String patientId, String attributeId, - String projection, Integer pageSize, - Integer pageNumber, String sortBy, String direction); - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - BaseMeta getMetaPatientClinicalData(String studyId, String patientId, String attributeId); - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - List getAllClinicalDataInStudy(String studyId, String attributeId, - String clinicalDataType, String projection, - Integer pageSize, Integer pageNumber, String sortBy, - String direction); - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - BaseMeta getMetaAllClinicalData(String studyId, String attributeId, String clinicalDataType); - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - List fetchAllClinicalDataInStudy(String studyId, List ids, List attributeIds, - String clinicalDataType, String projection); - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - BaseMeta fetchMetaClinicalDataInStudy(String studyId, List ids, List attributeIds, - String clinicalDataType); - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - List fetchClinicalData(List studyIds, List ids, List attributeIds, - String clinicalDataType, String projection); - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - BaseMeta fetchMetaClinicalData(List studyIds, List ids, List attributeIds, - String clinicalDataType); - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - List fetchClinicalDataCounts(List studyIds, List sampleIds, List attributeIds, - String clinicalDataType, String projection); - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - List getPatientClinicalDataDetailedToSample(List studyIds, List patientIds, - List attributeIds); - - List getVisibleSampleInternalIdsForClinicalTable(List studyIds, List sampleIds, - Integer pageSize, Integer pageNumber, String searchTerm, - String sortBy, String direction); - - List getSampleClinicalDataBySampleInternalIds(List visibleSampleInternalIds); - - List getPatientClinicalDataBySampleInternalIds(List visibleSampleInternalIds); -} diff --git a/src/main/java/org/cbioportal/persistence/ClinicalEventRepository.java b/src/main/java/org/cbioportal/persistence/ClinicalEventRepository.java deleted file mode 100644 index bf6d31470c9..00000000000 --- a/src/main/java/org/cbioportal/persistence/ClinicalEventRepository.java +++ /dev/null @@ -1,45 +0,0 @@ -package org.cbioportal.persistence; - -import org.cbioportal.model.ClinicalEvent; -import org.cbioportal.model.ClinicalEventData; -import org.cbioportal.model.meta.BaseMeta; - -import org.springframework.cache.annotation.Cacheable; - -import java.util.List; -import java.util.Map; -import java.util.Set; - -public interface ClinicalEventRepository { - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - List getAllClinicalEventsOfPatientInStudy(String studyId, String patientId, String projection, - Integer pageSize, Integer pageNumber, String sortBy, - String direction); - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - BaseMeta getMetaPatientClinicalEvents(String studyId, String patientId); - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - List getDataOfClinicalEvents(List clinicalEventIds); - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - List getAllClinicalEventsInStudy(String studyId, String projection, Integer pageSize, - Integer pageNumber, String sortBy, String direction); - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - BaseMeta getMetaClinicalEvents(String studyId); - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - Map> getSamplesOfPatientsPerEventTypeInStudy(List studyIds, List sampleIds); - - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - List getPatientsDistinctClinicalEventInStudies(List studyIds, List patientIds); - - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - List getTimelineEvents(List studyIds, List patientIds, List clinicalEvents); - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - List getClinicalEventsMeta(List studyIds, List patientIds, List clinicalEvents); -} diff --git a/src/main/java/org/cbioportal/persistence/CopyNumberSegmentRepository.java b/src/main/java/org/cbioportal/persistence/CopyNumberSegmentRepository.java deleted file mode 100644 index 3618de022df..00000000000 --- a/src/main/java/org/cbioportal/persistence/CopyNumberSegmentRepository.java +++ /dev/null @@ -1,31 +0,0 @@ -package org.cbioportal.persistence; - -import org.cbioportal.model.CopyNumberSeg; -import org.cbioportal.model.meta.BaseMeta; - -import org.springframework.cache.annotation.Cacheable; - -import java.util.List; - -public interface CopyNumberSegmentRepository { - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - List getCopyNumberSegmentsInSampleInStudy(String studyId, String sampleId, String chromosome, String projection, - Integer pageSize, Integer pageNumber, String sortBy, - String direction); - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - BaseMeta getMetaCopyNumberSegmentsInSampleInStudy(String studyId, String sampleId, String chromosome); - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - List fetchSamplesWithCopyNumberSegments(List studyIds, List sampleIds, String chromosome); - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - List fetchCopyNumberSegments(List studyIds, List sampleIds, String chromosome, String projection); - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - BaseMeta fetchMetaCopyNumberSegments(List studyIds, List sampleIds, String chromosome); - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - List getCopyNumberSegmentsBySampleListId(String studyId, String sampleListId, String chromosome, String projection); -} diff --git a/src/main/java/org/cbioportal/persistence/CosmicCountRepository.java b/src/main/java/org/cbioportal/persistence/CosmicCountRepository.java deleted file mode 100644 index c45133c25e8..00000000000 --- a/src/main/java/org/cbioportal/persistence/CosmicCountRepository.java +++ /dev/null @@ -1,11 +0,0 @@ -package org.cbioportal.persistence; - -import java.util.List; -import org.cbioportal.model.CosmicMutation; -import org.springframework.cache.annotation.Cacheable; - -public interface CosmicCountRepository { - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - List fetchCosmicCountsByKeywords(List keywords); -} diff --git a/src/main/java/org/cbioportal/persistence/DataAccessTokenRepository.java b/src/main/java/org/cbioportal/persistence/DataAccessTokenRepository.java deleted file mode 100644 index ddd46236a9e..00000000000 --- a/src/main/java/org/cbioportal/persistence/DataAccessTokenRepository.java +++ /dev/null @@ -1,17 +0,0 @@ -package org.cbioportal.persistence; - -import org.cbioportal.model.DataAccessToken; -import java.util.List; - -public interface DataAccessTokenRepository { - - List getAllDataAccessTokensForUsername(String username); - - DataAccessToken getDataAccessToken(String token); - - void addDataAccessToken(DataAccessToken token); - - void removeDataAccessToken(String token); - - void removeAllDataAccessTokensForUsername(String username); -} diff --git a/src/main/java/org/cbioportal/persistence/DiscreteCopyNumberRepository.java b/src/main/java/org/cbioportal/persistence/DiscreteCopyNumberRepository.java deleted file mode 100644 index ae07f0e3f2f..00000000000 --- a/src/main/java/org/cbioportal/persistence/DiscreteCopyNumberRepository.java +++ /dev/null @@ -1,58 +0,0 @@ -package org.cbioportal.persistence; - -import org.cbioportal.model.CopyNumberCountByGene; -import org.cbioportal.model.DiscreteCopyNumberData; -import org.cbioportal.model.GeneFilterQuery; -import org.cbioportal.model.meta.BaseMeta; -import org.springframework.cache.annotation.Cacheable; - -import java.util.List; - -public interface DiscreteCopyNumberRepository { - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - List getDiscreteCopyNumbersInMolecularProfileBySampleListId(String molecularProfileId, - String sampleListId, - List entrezGeneIds, - List alterationTypes, - String projection); - - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - BaseMeta getMetaDiscreteCopyNumbersInMolecularProfileBySampleListId(String molecularProfileId, - String sampleListId, - List entrezGeneIds, - List alterationTypes); - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - List fetchDiscreteCopyNumbersInMolecularProfile(String molecularProfileId, - List sampleIds, - List entrezGeneIds, - List alterationTypes, - String projection); - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - List getDiscreteCopyNumbersInMultipleMolecularProfiles(List molecularProfileIds, - List sampleIds, - List entrezGeneIds, - List alterationTypes, - String projection); - - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - List getDiscreteCopyNumbersInMultipleMolecularProfilesByGeneQueries(List molecularProfileIds, - List sampleIds, - List geneFilterQuery, - String projection); - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - BaseMeta fetchMetaDiscreteCopyNumbersInMolecularProfile(String molecularProfileId, - List sampleIds, - List entrezGeneIds, - List alterationTypes); - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - List getSampleCountByGeneAndAlterationAndSampleIds(String molecularProfileId, - List sampleIds, - List entrezGeneIds, - List alterations); -} diff --git a/src/main/java/org/cbioportal/persistence/GenePanelRepository.java b/src/main/java/org/cbioportal/persistence/GenePanelRepository.java deleted file mode 100644 index 49817ff86be..00000000000 --- a/src/main/java/org/cbioportal/persistence/GenePanelRepository.java +++ /dev/null @@ -1,46 +0,0 @@ -package org.cbioportal.persistence; - -import org.cbioportal.model.GenePanel; -import org.cbioportal.model.GenePanelData; -import org.cbioportal.model.GenePanelToGene; -import org.cbioportal.model.MolecularProfileCaseIdentifier; -import org.cbioportal.model.meta.BaseMeta; - -import org.springframework.cache.annotation.Cacheable; - -import java.util.List; -import java.util.Set; - -public interface GenePanelRepository { - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - List getAllGenePanels(String projection, Integer pageSize, Integer pageNumber, String sortBy, - String direction); - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - BaseMeta getMetaGenePanels(); - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - GenePanel getGenePanel(String genePanelId); - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - List fetchGenePanels(List genePanelIds, String projection); - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - List getGenePanelDataBySampleListId(String molecularProfileId, String sampleListId); - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - List fetchGenePanelData(String molecularProfileId, List sampleIds); - - List fetchGenePanelDataByMolecularProfileIds(Set molecularProfileIds); - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - List fetchGenePanelDataByMolecularProfileId(String molecularProfileId); - - List fetchGenePanelDataInMultipleMolecularProfiles(List molecularProfileSampleIdentifiers); - - List fetchGenePanelDataInMultipleMolecularProfilesByPatientIds(List molecularProfileSampleIdentifiers); - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - List getGenesOfPanels(List genePanelIds); -} diff --git a/src/main/java/org/cbioportal/persistence/GeneRepository.java b/src/main/java/org/cbioportal/persistence/GeneRepository.java deleted file mode 100644 index a0bdd4b5715..00000000000 --- a/src/main/java/org/cbioportal/persistence/GeneRepository.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright (c) 2016 - 2019 Memorial Sloan Kettering Cancer Center. - * - * This library is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS - * FOR A PARTICULAR PURPOSE. The software and documentation provided hereunder - * is on an "as is" basis, and Memorial Sloan-Kettering Cancer Center has no - * obligations to provide maintenance, support, updates, enhancements or - * modifications. In no event shall Memorial Sloan-Kettering Cancer Center be - * liable to any party for direct, indirect, special, incidental or - * consequential damages, including lost profits, arising out of the use of this - * software and its documentation, even if Memorial Sloan-Kettering Cancer - * Center has been advised of the possibility of such damage. - */ - -/* - * This file is part of cBioPortal. - * - * cBioPortal is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . -*/ -package org.cbioportal.persistence; - -import org.cbioportal.model.Gene; -import org.cbioportal.model.GeneAlias; -import org.cbioportal.model.meta.BaseMeta; - -import org.springframework.cache.annotation.Cacheable; - -import java.util.List; - -public interface GeneRepository { - - @Cacheable(cacheResolver = "staticRepositoryCacheOneResolver", condition = "@cacheEnabledConfig.getEnabled()") - List getAllGenes(String keyword, String alias, String projection, Integer pageSize, Integer pageNumber, String sortBy, - String direction); - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - BaseMeta getMetaGenes(String keyword, String alias); - - Gene getGeneByGeneticEntityId(Integer geneticEntityId); - - @Cacheable(cacheResolver = "staticRepositoryCacheOneResolver", condition = "@cacheEnabledConfig.getEnabled()") - Gene getGeneByEntrezGeneId(Integer entrezGeneId); - - @Cacheable(cacheResolver = "staticRepositoryCacheOneResolver", condition = "@cacheEnabledConfig.getEnabled()") - Gene getGeneByHugoGeneSymbol(String hugoGeneSymbol); - - @Cacheable(cacheResolver = "staticRepositoryCacheOneResolver", condition = "@cacheEnabledConfig.getEnabled()") - List getAliasesOfGeneByEntrezGeneId(Integer entrezGeneId); - - @Cacheable(cacheResolver = "staticRepositoryCacheOneResolver", condition = "@cacheEnabledConfig.getEnabled()") - List getAliasesOfGeneByHugoGeneSymbol(String hugoGeneSymbol); - - // not cached because this is called only a single time, during @PostConstruct method of GeneServiceImpl - List getAllAliases(); - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - List fetchGenesByEntrezGeneIds(List entrezGeneIds, String projection); - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - List fetchGenesByHugoGeneSymbols(List hugoGeneSymbols, String projection); - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - BaseMeta fetchMetaGenesByEntrezGeneIds(List entrezGeneIds); - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - BaseMeta fetchMetaGenesByHugoGeneSymbols(List hugoGeneSymbols); -} diff --git a/src/main/java/org/cbioportal/persistence/GenericAssayRepository.java b/src/main/java/org/cbioportal/persistence/GenericAssayRepository.java deleted file mode 100644 index 27f8f1f8964..00000000000 --- a/src/main/java/org/cbioportal/persistence/GenericAssayRepository.java +++ /dev/null @@ -1,19 +0,0 @@ -package org.cbioportal.persistence; - -import java.util.List; - -import org.cbioportal.model.meta.GenericAssayMeta; -import org.cbioportal.model.GenericAssayAdditionalProperty; -import org.springframework.cache.annotation.Cacheable; - -public interface GenericAssayRepository { - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - List getGenericAssayMeta(List stableIds); - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - List getGenericAssayAdditionalproperties(List stableIds); - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - List getGenericAssayStableIdsByMolecularIds(List molecularProfileIds); -} diff --git a/src/main/java/org/cbioportal/persistence/GenesetHierarchyRepository.java b/src/main/java/org/cbioportal/persistence/GenesetHierarchyRepository.java deleted file mode 100644 index 5db19320acf..00000000000 --- a/src/main/java/org/cbioportal/persistence/GenesetHierarchyRepository.java +++ /dev/null @@ -1,20 +0,0 @@ -package org.cbioportal.persistence; - -import java.util.List; - -import org.cbioportal.model.Geneset; -import org.cbioportal.model.GenesetHierarchyInfo; - -import org.springframework.cache.annotation.Cacheable; - -public interface GenesetHierarchyRepository { - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - List getGenesetHierarchyParents(List genesetIds); - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - List getGenesetHierarchyGenesets(Integer nodeId); - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - List getGenesetHierarchySuperNodes(List genesetIds); -} diff --git a/src/main/java/org/cbioportal/persistence/GenesetRepository.java b/src/main/java/org/cbioportal/persistence/GenesetRepository.java deleted file mode 100644 index dcd73779403..00000000000 --- a/src/main/java/org/cbioportal/persistence/GenesetRepository.java +++ /dev/null @@ -1,30 +0,0 @@ -package org.cbioportal.persistence; - -import java.util.List; - -import org.cbioportal.model.Gene; -import org.cbioportal.model.Geneset; -import org.cbioportal.model.meta.BaseMeta; - -import org.springframework.cache.annotation.Cacheable; - -public interface GenesetRepository { - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - List getAllGenesets(String projection, Integer pageSize, Integer pageNumber); - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - BaseMeta getMetaGenesets(); - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - Geneset getGeneset(String genesetId); - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - List fetchGenesets(List genesetIds); - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - List getGenesByGenesetId(String genesetId); - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - String getGenesetVersion(); -} diff --git a/src/main/java/org/cbioportal/persistence/MolecularDataRepository.java b/src/main/java/org/cbioportal/persistence/MolecularDataRepository.java deleted file mode 100644 index 5c2f8a9600a..00000000000 --- a/src/main/java/org/cbioportal/persistence/MolecularDataRepository.java +++ /dev/null @@ -1,50 +0,0 @@ -package org.cbioportal.persistence; - -import java.util.List; -import java.util.Map; -import java.util.Set; - -import org.cbioportal.model.GeneMolecularAlteration; -import org.cbioportal.model.GenericAssayMolecularAlteration; -import org.cbioportal.model.GenesetMolecularAlteration; -import org.springframework.cache.annotation.Cacheable; -import org.cbioportal.model.MolecularProfileSamples; - -public interface MolecularDataRepository { - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - MolecularProfileSamples getCommaSeparatedSampleIdsOfMolecularProfile(String molecularProfileId); - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - Map commaSeparatedSampleIdsOfMolecularProfilesMap(Set molecularProfileIds); - - // Not caching when entrezGeneIds is null or empty because the large response size sometimes crashes the cache - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", - condition = "@cacheEnabledConfig.getEnabled() && #entrezGeneIds != null && #entrezGeneIds.size() != 0") - List getGeneMolecularAlterations(String molecularProfileId, List entrezGeneIds, - String projection); - - Iterable getGeneMolecularAlterationsIterable(String molecularProfileId, List entrezGeneIds, - String projection); - - // Same as getGeneMolecularAlterationsIterable above, except assumes that - // entrezGeneIds is null or empty AND projection is "SUMMARY" - Iterable getGeneMolecularAlterationsIterableFast(String molecularProfileId); - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - List getGeneMolecularAlterationsInMultipleMolecularProfiles(Set molecularProfileIds, - List entrezGeneIds, - String projection); - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - List getGenesetMolecularAlterations(String molecularProfileId, List genesetIds, - String projection); - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - List getGenericAssayMolecularAlterations(String molecularProfileId, List stableIds, - String projection); - - Iterable getGenericAssayMolecularAlterationsIterable(String molecularProfileId, - List stableIds, String projection); - -} diff --git a/src/main/java/org/cbioportal/persistence/MolecularProfileRepository.java b/src/main/java/org/cbioportal/persistence/MolecularProfileRepository.java deleted file mode 100644 index 41cb01bc8ec..00000000000 --- a/src/main/java/org/cbioportal/persistence/MolecularProfileRepository.java +++ /dev/null @@ -1,47 +0,0 @@ -package org.cbioportal.persistence; - -import org.cbioportal.model.MolecularProfile; -import org.cbioportal.model.meta.BaseMeta; - -import org.springframework.cache.annotation.Cacheable; - -import java.util.List; -import java.util.Set; - -public interface MolecularProfileRepository { - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - List getAllMolecularProfiles(String projection, Integer pageSize, Integer pageNumber, - String sortBy, String direction); - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - BaseMeta getMetaMolecularProfiles(); - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - MolecularProfile getMolecularProfile(String molecularProfileId); - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - List getMolecularProfiles(Set molecularProfileIds, String projection); - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - BaseMeta getMetaMolecularProfiles(Set molecularProfileIds); - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - List getAllMolecularProfilesInStudy(String studyId, String projection, Integer pageSize, - Integer pageNumber, String sortBy, String direction); - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - BaseMeta getMetaMolecularProfilesInStudy(String studyId); - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - List getMolecularProfilesInStudies(List studyIds, String projection); - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - BaseMeta getMetaMolecularProfilesInStudies(List studyIds); - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - List getMolecularProfilesReferredBy(String referringMolecularProfileId); - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - List getMolecularProfilesReferringTo(String referredMolecularProfileId); -} diff --git a/src/main/java/org/cbioportal/persistence/MutationRepository.java b/src/main/java/org/cbioportal/persistence/MutationRepository.java deleted file mode 100644 index ffcef1b6f0c..00000000000 --- a/src/main/java/org/cbioportal/persistence/MutationRepository.java +++ /dev/null @@ -1,62 +0,0 @@ -package org.cbioportal.persistence; - -import org.cbioportal.model.GeneFilterQuery; -import org.cbioportal.model.GenomicDataCountItem; -import org.cbioportal.model.Mutation; -import org.cbioportal.model.MutationCountByPosition; -import org.cbioportal.model.meta.MutationMeta; -import org.springframework.cache.annotation.Cacheable; - -import java.util.List; - -public interface MutationRepository { - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - List getMutationsInMolecularProfileBySampleListId(String molecularProfileId, String sampleListId, - List entrezGeneIds, boolean snpOnly, - String projection, Integer pageSize, Integer pageNumber, - String sortBy, String direction); - - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - MutationMeta getMetaMutationsInMolecularProfileBySampleListId(String molecularProfileId, String sampleListId, - List entrezGeneIds); - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - List getMutationsInMultipleMolecularProfiles(List molecularProfileIds, List sampleIds, - List entrezGeneIds, String projection, - Integer pageSize, Integer pageNumber, - String sortBy, String direction); - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - List getMutationsInMultipleMolecularProfilesByGeneQueries(List molecularProfileIds, - List sampleIds, - List geneQueries, - String projection, - Integer pageSize, - Integer pageNumber, - String sortBy, - String direction); - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - MutationMeta getMetaMutationsInMultipleMolecularProfiles(List molecularProfileIds, List sampleIds, - List entrezGeneIds); - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - List fetchMutationsInMolecularProfile(String molecularProfileId, List sampleIds, - List entrezGeneIds, boolean snpOnly, String projection, - Integer pageSize, Integer pageNumber, String sortBy, - String direction); - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - MutationMeta fetchMetaMutationsInMolecularProfile(String molecularProfileId, List sampleIds, - List entrezGeneIds); - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - MutationCountByPosition getMutationCountByPosition(Integer entrezGeneId, Integer proteinPosStart, - Integer proteinPosEnd); - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - GenomicDataCountItem getMutationCountsByType(List molecularProfileIds, List sampleIds, - List entrezGeneIds, String profileType); -} diff --git a/src/main/java/org/cbioportal/persistence/PatientRepository.java b/src/main/java/org/cbioportal/persistence/PatientRepository.java deleted file mode 100644 index 54c92024b79..00000000000 --- a/src/main/java/org/cbioportal/persistence/PatientRepository.java +++ /dev/null @@ -1,37 +0,0 @@ -package org.cbioportal.persistence; - -import org.cbioportal.model.Patient; -import org.cbioportal.model.meta.BaseMeta; - -import org.springframework.cache.annotation.Cacheable; - -import java.util.List; - -public interface PatientRepository { - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - List getAllPatients(String keyword, String projection, Integer pageSize, Integer pageNumber, String sortBy, - String direction); - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - BaseMeta getMetaPatients(String keyword); - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - List getAllPatientsInStudy(String studyId, String projection, Integer pageSize, Integer pageNumber, - String sortBy, String direction); - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - BaseMeta getMetaPatientsInStudy(String studyId); - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - Patient getPatientInStudy(String studyId, String patientId); - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - List fetchPatients(List studyIds, List patientIds, String projection); - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - BaseMeta fetchMetaPatients(List studyIds, List patientIds); - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - List getPatientsOfSamples(List studyIds, List sampleIds); -} diff --git a/src/main/java/org/cbioportal/persistence/PersistenceConstants.java b/src/main/java/org/cbioportal/persistence/PersistenceConstants.java deleted file mode 100644 index c5b3124a7ef..00000000000 --- a/src/main/java/org/cbioportal/persistence/PersistenceConstants.java +++ /dev/null @@ -1,9 +0,0 @@ -package org.cbioportal.persistence; - -public class PersistenceConstants { - - public static final String DETAILED_PROJECTION = "DETAILED"; - public static final String SUMMARY_PROJECTION = "SUMMARY"; - public static final String ID_PROJECTION = "ID"; - public static final String SAMPLE_CLINICAL_DATA_TYPE = "SAMPLE"; -} diff --git a/src/main/java/org/cbioportal/persistence/ReferenceGenomeGeneRepository.java b/src/main/java/org/cbioportal/persistence/ReferenceGenomeGeneRepository.java deleted file mode 100644 index 7b906fed60a..00000000000 --- a/src/main/java/org/cbioportal/persistence/ReferenceGenomeGeneRepository.java +++ /dev/null @@ -1,19 +0,0 @@ -package org.cbioportal.persistence; - -import org.cbioportal.model.ReferenceGenomeGene; -import java.util.List; -import org.springframework.cache.annotation.Cacheable; - -public interface ReferenceGenomeGeneRepository { - @Cacheable(cacheResolver = "staticRepositoryCacheOneResolver", condition = "@cacheEnabledConfig.getEnabled()") - List getAllGenesByGenomeName(String genomeName); - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - List getGenesByHugoGeneSymbolsAndGenomeName(List geneIds, String genomeName); - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - List getGenesByGenomeName(List geneIds, String genomeName); - @Cacheable(cacheResolver = "staticRepositoryCacheOneResolver", condition = "@cacheEnabledConfig.getEnabled()") - ReferenceGenomeGene getReferenceGenomeGene(Integer geneId, String genomeName); - @Cacheable(cacheResolver = "staticRepositoryCacheOneResolver", condition = "@cacheEnabledConfig.getEnabled()") - ReferenceGenomeGene getReferenceGenomeGeneByEntityId(Integer geneticEntityId, String genomeName); -} - diff --git a/src/main/java/org/cbioportal/persistence/ResourceDataRepository.java b/src/main/java/org/cbioportal/persistence/ResourceDataRepository.java deleted file mode 100644 index c93898dd2ce..00000000000 --- a/src/main/java/org/cbioportal/persistence/ResourceDataRepository.java +++ /dev/null @@ -1,29 +0,0 @@ -package org.cbioportal.persistence; - -import java.util.List; - -import org.cbioportal.model.ResourceData; -import org.springframework.cache.annotation.Cacheable; - -public interface ResourceDataRepository { - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - List getAllResourceDataOfSampleInStudy(String studyId, String sampleId, String resourceId, - String projection, Integer pageSize, Integer pageNumber, String sortBy, String direction); - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - List getAllResourceDataOfPatientInStudy(String studyId, String patientId, String resourceId, - String projection, Integer pageSize, Integer pageNumber, String sortBy, String direction); - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - List getAllResourceDataForStudy(String studyId, String resourceId, String projection, - Integer pageSize, Integer pageNumber, String sortBy, String direction); - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - List getResourceDataForAllPatientsInStudy(String studyId, String resourceId, String projection, - Integer pageSize, Integer pageNumber, String sortBy, String direction); - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - List getResourceDataForAllSamplesInStudy(String studyId, String resourceId, String projection, - Integer pageSize, Integer pageNumber, String sortBy, String direction); -} diff --git a/src/main/java/org/cbioportal/persistence/ResourceDefinitionRepository.java b/src/main/java/org/cbioportal/persistence/ResourceDefinitionRepository.java deleted file mode 100644 index 1f248d5775c..00000000000 --- a/src/main/java/org/cbioportal/persistence/ResourceDefinitionRepository.java +++ /dev/null @@ -1,15 +0,0 @@ -package org.cbioportal.persistence; - -import java.util.List; - -import org.cbioportal.model.ResourceDefinition; -import org.springframework.cache.annotation.Cacheable; - -public interface ResourceDefinitionRepository { - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - ResourceDefinition getResourceDefinition(String studyId, String resourceId); - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - List fetchResourceDefinitions(List studyIds, String projection, Integer pageSize, - Integer pageNumber, String sortBy, String direction); -} diff --git a/src/main/java/org/cbioportal/persistence/SampleListRepository.java b/src/main/java/org/cbioportal/persistence/SampleListRepository.java deleted file mode 100644 index 0c0e7745d8a..00000000000 --- a/src/main/java/org/cbioportal/persistence/SampleListRepository.java +++ /dev/null @@ -1,38 +0,0 @@ -package org.cbioportal.persistence; - -import org.cbioportal.model.SampleList; -import org.cbioportal.model.SampleListToSampleId; -import org.cbioportal.model.meta.BaseMeta; - -import org.springframework.cache.annotation.Cacheable; - -import java.util.List; - -public interface SampleListRepository { - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - List getAllSampleLists(String projection, Integer pageSize, Integer pageNumber, String sortBy, - String direction); - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - BaseMeta getMetaSampleLists(); - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - SampleList getSampleList(String sampleListId); - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - List getSampleLists(List sampleListIds, String projection); - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - List getAllSampleListsInStudies(List studyIds, String projection, Integer pageSize, Integer pageNumber, - String sortBy, String direction); - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - BaseMeta getMetaSampleListsInStudy(String studyId); - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - List getAllSampleIdsInSampleList(String sampleListId); - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - List getSampleListSampleIds(List sampleListIds); -} diff --git a/src/main/java/org/cbioportal/persistence/SampleRepository.java b/src/main/java/org/cbioportal/persistence/SampleRepository.java deleted file mode 100644 index 8ce831fe951..00000000000 --- a/src/main/java/org/cbioportal/persistence/SampleRepository.java +++ /dev/null @@ -1,60 +0,0 @@ -package org.cbioportal.persistence; - -import org.cbioportal.model.Sample; -import org.cbioportal.model.meta.BaseMeta; - -import org.springframework.cache.annotation.Cacheable; - -import java.util.List; - -public interface SampleRepository { - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - List getAllSamples(String keyword, List studyIds, String projection, Integer pageSize, - Integer pageNumber, String sort, String direction); - - BaseMeta getMetaSamples(String keyword, List studyIds); - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - List getAllSamplesInStudy(String studyId, String projection, Integer pageSize, Integer pageNumber, - String sortBy, String direction); - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - BaseMeta getMetaSamplesInStudy(String studyId); - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - List getAllSamplesInStudies(List studyIds, String projection, Integer pageSize, Integer pageNumber, - String sortBy, String direction); - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - Sample getSampleInStudy(String studyId, String sampleId); - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - List getAllSamplesOfPatientInStudy(String studyId, String patientId, String projection, Integer pageSize, - Integer pageNumber, String sortBy, String direction); - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - BaseMeta getMetaSamplesOfPatientInStudy(String studyId, String patientId); - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - List getAllSamplesOfPatientsInStudy(String studyId, List patientIds, String projection); - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - List getSamplesOfPatientsInMultipleStudies(List studyIds, List patientIds, String projection); - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - List fetchSamples(List studyIds, List sampleIds, String projection); - - List fetchSamplesBySampleListIds(List sampleListIds, String projection); - - @Cacheable(cacheResolver = "staticRepositoryCacheOneResolver", condition = "@cacheEnabledConfig.getEnabled()") - List fetchSampleBySampleListId(String sampleListIds, String projection); - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - BaseMeta fetchMetaSamples(List studyIds, List sampleIds); - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - BaseMeta fetchMetaSamples(List sampleListIds); - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - List getSamplesByInternalIds(List internalIds); -} diff --git a/src/main/java/org/cbioportal/persistence/SecurityRepository.java b/src/main/java/org/cbioportal/persistence/SecurityRepository.java deleted file mode 100644 index 68ff9f1a3a5..00000000000 --- a/src/main/java/org/cbioportal/persistence/SecurityRepository.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (c) 2015 Memorial Sloan-Kettering Cancer Center. - * - * This library is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS - * FOR A PARTICULAR PURPOSE. The software and documentation provided hereunder - * is on an "as is" basis, and Memorial Sloan-Kettering Cancer Center has no - * obligations to provide maintenance, support, updates, enhancements or - * modifications. In no event shall Memorial Sloan-Kettering Cancer Center be - * liable to any party for direct, indirect, special, incidental or - * consequential damages, including lost profits, arising out of the use of this - * software and its documentation, even if Memorial Sloan-Kettering Cancer - * Center has been advised of the possibility of such damage. - */ - -/* - * This file is part of cBioPortal. - * - * cBioPortal is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . -*/ - -package org.cbioportal.persistence; - -// imports -import java.util.Set; - -import org.cbioportal.model.User; -import org.cbioportal.model.UserAuthorities; - -/** - * Interface to use to retrieve - * portal user information. - */ -public interface SecurityRepository { - - /** - * Given a user id, returns a user instance. - * If username does not exist in db, returns null. - * - * @param username String - * @return User - */ - User getPortalUser(String username); - - /** - * Given a user id, returns a UserAuthorities instance. - * If username does not exist in db, returns null. - * - * @param username String - * @return UserAuthorities - */ - UserAuthorities getPortalUserAuthorities(String username); - - void addPortalUser(User user); - void addPortalUserAuthorities(UserAuthorities userAuthorities); - - /** - * Given an internal cancer study id, returns a set of upper case cancer study group strings. - * Returns empty set if cancer study does not exist or there are no groups. - * - * @param internalCancerStudyId Integer - * @return Set cancer study group strings in upper case - */ - Set getCancerStudyGroups(Integer internalCancerStudyId); -} diff --git a/src/main/java/org/cbioportal/persistence/SignificantCopyNumberRegionRepository.java b/src/main/java/org/cbioportal/persistence/SignificantCopyNumberRegionRepository.java deleted file mode 100644 index 4e5fa225ce0..00000000000 --- a/src/main/java/org/cbioportal/persistence/SignificantCopyNumberRegionRepository.java +++ /dev/null @@ -1,22 +0,0 @@ -package org.cbioportal.persistence; - -import org.cbioportal.model.Gistic; -import org.cbioportal.model.GisticToGene; -import org.cbioportal.model.meta.BaseMeta; - -import org.springframework.cache.annotation.Cacheable; - -import java.util.List; - -public interface SignificantCopyNumberRegionRepository { - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - List getSignificantCopyNumberRegions(String studyId, String projection, Integer pageSize, - Integer pageNumber, String sortBy, String direction); - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - BaseMeta getMetaSignificantCopyNumberRegions(String studyId); - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - List getGenesOfRegions(List gisticRoiIds); -} diff --git a/src/main/java/org/cbioportal/persistence/SignificantlyMutatedGeneRepository.java b/src/main/java/org/cbioportal/persistence/SignificantlyMutatedGeneRepository.java deleted file mode 100644 index 4c20a80e31d..00000000000 --- a/src/main/java/org/cbioportal/persistence/SignificantlyMutatedGeneRepository.java +++ /dev/null @@ -1,18 +0,0 @@ -package org.cbioportal.persistence; - -import org.cbioportal.model.MutSig; -import org.cbioportal.model.meta.BaseMeta; - -import org.springframework.cache.annotation.Cacheable; - -import java.util.List; - -public interface SignificantlyMutatedGeneRepository { - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - List getSignificantlyMutatedGenes(String studyId, String projection, Integer pageSize, Integer pageNumber, - String sortBy, String direction); - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - BaseMeta getMetaSignificantlyMutatedGenes(String studyId); -} diff --git a/src/main/java/org/cbioportal/persistence/StaticDataTimeStampRepository.java b/src/main/java/org/cbioportal/persistence/StaticDataTimeStampRepository.java deleted file mode 100644 index 616d5e158d5..00000000000 --- a/src/main/java/org/cbioportal/persistence/StaticDataTimeStampRepository.java +++ /dev/null @@ -1,10 +0,0 @@ -package org.cbioportal.persistence; - -import org.cbioportal.model.TableTimestampPair; - -import java.util.Date; -import java.util.List; - -public interface StaticDataTimeStampRepository { - List getTimestamps(List tables); -} diff --git a/src/main/java/org/cbioportal/persistence/StructuralVariantRepository.java b/src/main/java/org/cbioportal/persistence/StructuralVariantRepository.java deleted file mode 100644 index 8818779e193..00000000000 --- a/src/main/java/org/cbioportal/persistence/StructuralVariantRepository.java +++ /dev/null @@ -1,29 +0,0 @@ -package org.cbioportal.persistence; - -import java.util.List; - -import org.cbioportal.model.GeneFilterQuery; -import org.cbioportal.model.StructuralVariantFilterQuery; -import org.cbioportal.model.StructuralVariant; -import org.cbioportal.model.StructuralVariantQuery; -import org.springframework.cache.annotation.Cacheable; - -public interface StructuralVariantRepository { - - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - List fetchStructuralVariants(List molecularProfileIds, - List sampleIds, - List entrezGeneIds, - List structuralVariantQueries); - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - List fetchStructuralVariantsByGeneQueries(List molecularProfileIds, - List sampleIds, - List geneQueries); - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - List fetchStructuralVariantsByStructVarQueries(List molecularProfileIds, - List sampleIds, - List structVarQueries); -} diff --git a/src/main/java/org/cbioportal/persistence/StudyRepository.java b/src/main/java/org/cbioportal/persistence/StudyRepository.java deleted file mode 100644 index 875250b5b23..00000000000 --- a/src/main/java/org/cbioportal/persistence/StudyRepository.java +++ /dev/null @@ -1,34 +0,0 @@ -package org.cbioportal.persistence; - -import org.cbioportal.model.CancerStudy; -import org.cbioportal.model.CancerStudyTags; -import org.cbioportal.model.meta.BaseMeta; - -import org.springframework.cache.annotation.Cacheable; - -import java.util.List; - -public interface StudyRepository { - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - List getAllStudies(String keyword, String projection, Integer pageSize, Integer pageNumber, - String sortBy, String direction); - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - BaseMeta getMetaStudies(String keyword); - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - CancerStudy getStudy(String studyId, String projection); - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - List fetchStudies(List studyIds, String projection); - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - BaseMeta fetchMetaStudies(List studyIds); - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - CancerStudyTags getTags(String studyId); - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - List getTagsForMultipleStudies(List studyIds); -} diff --git a/src/main/java/org/cbioportal/persistence/StudyViewRepository.java b/src/main/java/org/cbioportal/persistence/StudyViewRepository.java deleted file mode 100644 index c39158ad433..00000000000 --- a/src/main/java/org/cbioportal/persistence/StudyViewRepository.java +++ /dev/null @@ -1,92 +0,0 @@ -package org.cbioportal.persistence; - -import org.cbioportal.model.AlterationCountByGene; -import org.cbioportal.model.ClinicalAttribute; -import org.cbioportal.model.CaseListDataCount; -import org.cbioportal.model.ClinicalData; -import org.cbioportal.model.ClinicalDataCount; -import org.cbioportal.model.ClinicalDataCountItem; -import org.cbioportal.model.ClinicalEventTypeCount; -import org.cbioportal.model.CopyNumberCountByGene; -import org.cbioportal.model.GenericAssayDataCountItem; -import org.cbioportal.model.GenomicDataCountItem; -import org.cbioportal.model.GenomicDataCount; -import org.cbioportal.model.MolecularProfile; -import org.cbioportal.model.PatientTreatment; -import org.cbioportal.model.Sample; -import org.cbioportal.model.SampleTreatment; -import org.cbioportal.model.StudyViewFilterContext; -import org.cbioportal.web.parameter.ClinicalDataType; -import org.cbioportal.web.parameter.GenericAssayDataBinFilter; -import org.cbioportal.web.parameter.GenericAssayDataFilter; -import org.cbioportal.web.parameter.GenomicDataBinFilter; -import org.cbioportal.web.parameter.GenomicDataFilter; - -import java.util.List; -import java.util.Map; -import java.util.Set; - -public interface StudyViewRepository { - List getFilteredSamples(StudyViewFilterContext studyViewFilterContext); - - List getFilteredStudyIds(StudyViewFilterContext studyViewFilterContext); - - List getSampleClinicalData(StudyViewFilterContext studyViewFilterContext, List attributeIds); - - List getPatientClinicalData(StudyViewFilterContext studyViewFilterContext, List attributeIds); - - List getMutatedGenes(StudyViewFilterContext studyViewFilterContext); - - List getStructuralVariantGenes(StudyViewFilterContext studyViewFilterContext); - List getCnaGenes(StudyViewFilterContext studyViewFilterContext); - - List getClinicalDataCounts(StudyViewFilterContext studyViewFilterContext, List filteredAttributes); - - List getMolecularProfileSampleCounts(StudyViewFilterContext studyViewFilterContext); - - Map getClinicalAttributeDatatypeMap(); - - List getCaseListDataCountsPerStudy(StudyViewFilterContext studyViewFilterContext); - - Map getTotalProfiledCounts(StudyViewFilterContext studyViewFilterContext, String alterationType, List molecularProfiles); - - List getClinicalAttributes(); - - List getClinicalAttributesForStudies(List studyIds); - - int getFilteredSamplesCount(StudyViewFilterContext studyViewFilterContext); - - int getFilteredPatientCount(StudyViewFilterContext studyViewFilterContext); - - Map> getMatchingGenePanelIds(StudyViewFilterContext studyViewFilterContext, String alterationType); - - int getTotalProfiledCountsByAlterationType(StudyViewFilterContext studyViewFilterContext, String alterationType); - - int getSampleProfileCountWithoutPanelData(StudyViewFilterContext studyViewFilterContext, String alterationType); - - List getClinicalEventTypeCounts(StudyViewFilterContext studyViewFilterContext); - - List getPatientTreatments(StudyViewFilterContext studyViewFilterContext); - - int getTotalPatientTreatmentCount(StudyViewFilterContext studyViewFilterContext); - - List getSampleTreatments(StudyViewFilterContext studyViewFilterContext); - - int getTotalSampleTreatmentCount(StudyViewFilterContext studyViewFilterContext); - - List getCNACounts(StudyViewFilterContext studyViewFilterContext, List genomicDataFilters); - - List getGenericAssayDataCounts(StudyViewFilterContext studyViewFilterContext, List genericAssayDataFilters); - - Map getMutationCounts(StudyViewFilterContext studyViewFilterContext, GenomicDataFilter genomicDataFilter); - - List getMutationCountsByType(StudyViewFilterContext studyViewFilterContext, List genomicDataFilters); - - List getGenomicDataBinCounts(StudyViewFilterContext studyViewFilterContext, List genomicDataBinFilters); - - List getGenericAssayDataBinCounts(StudyViewFilterContext studyViewFilterContext, List genericAssayDataBinFilters); - - List getGenericAssayProfiles(); - - List getFilteredMolecularProfilesByAlterationType(StudyViewFilterContext studyViewFilterContext, String alterationType); -} diff --git a/src/main/java/org/cbioportal/persistence/TreatmentRepository.java b/src/main/java/org/cbioportal/persistence/TreatmentRepository.java deleted file mode 100644 index bc2e0705b16..00000000000 --- a/src/main/java/org/cbioportal/persistence/TreatmentRepository.java +++ /dev/null @@ -1,31 +0,0 @@ -package org.cbioportal.persistence; - -import org.cbioportal.model.ClinicalEventKeyCode; -import org.cbioportal.model.ClinicalEventSample; -import org.cbioportal.model.Treatment; -import org.springframework.cache.annotation.Cacheable; - -import java.util.List; -import java.util.Map; -import java.util.Set; - -public interface TreatmentRepository { - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - public Map> getTreatmentsByPatientId(List sampleIds, List studyIds, ClinicalEventKeyCode key); - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - public List getTreatments(List sampleIds, List studyIds, ClinicalEventKeyCode key); - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - public Map> getSamplesByPatientId(List sampleIds, List studyIds); - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - public Map> getShallowSamplesByPatientId(List sampleIds, List studyIds); - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - public Boolean hasTreatmentData(List studies, ClinicalEventKeyCode key); - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - public Boolean hasSampleTimelineData(List studies); - -} diff --git a/src/main/java/org/cbioportal/persistence/VariantCountRepository.java b/src/main/java/org/cbioportal/persistence/VariantCountRepository.java deleted file mode 100644 index b3f6e078cbd..00000000000 --- a/src/main/java/org/cbioportal/persistence/VariantCountRepository.java +++ /dev/null @@ -1,14 +0,0 @@ -package org.cbioportal.persistence; - -import org.cbioportal.model.VariantCount; - -import org.springframework.cache.annotation.Cacheable; - -import java.util.List; - -public interface VariantCountRepository { - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - List fetchVariantCounts(String molecularProfileId, List entrezGeneIds, - List keywords); -} diff --git a/src/main/java/org/cbioportal/persistence/cachemaputil/CacheMapBuilder.java b/src/main/java/org/cbioportal/persistence/cachemaputil/CacheMapBuilder.java deleted file mode 100644 index ed189f01c7d..00000000000 --- a/src/main/java/org/cbioportal/persistence/cachemaputil/CacheMapBuilder.java +++ /dev/null @@ -1,79 +0,0 @@ -package org.cbioportal.persistence.cachemaputil; - -import java.util.function.Function; -import java.util.stream.Collectors; -import org.cbioportal.model.CancerStudy; -import org.cbioportal.model.EntityType; -import org.cbioportal.model.MolecularProfile; -import org.cbioportal.model.SampleList; -import org.cbioportal.persistence.GenericAssayRepository; -import org.cbioportal.persistence.MolecularProfileRepository; -import org.cbioportal.persistence.SampleListRepository; -import org.cbioportal.persistence.StudyRepository; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -@Component -public class CacheMapBuilder { - - private static final Logger LOG = LoggerFactory.getLogger(CacheMapBuilder.class); - - @Autowired - private StudyRepository studyRepository; - - @Autowired - private MolecularProfileRepository molecularProfileRepository; - - @Autowired - private SampleListRepository sampleListRepository; - - @Autowired - private GenericAssayRepository genericAssayRepository; - - private static final int REPOSITORY_RESULT_LIMIT = Integer.MAX_VALUE; // retrieve all entries (no limit to return size) - private static final int REPOSITORY_RESULT_OFFSET = 0; // retrieve all entries (do not skip any) - - public Map buildMolecularProfileMap() { - Map molecularProfileMap = molecularProfileRepository.getAllMolecularProfiles( - "SUMMARY", - REPOSITORY_RESULT_LIMIT, - REPOSITORY_RESULT_OFFSET, - null, - "ASC").stream() - .collect(Collectors.toMap(MolecularProfile::getStableId, Function.identity())); - LOG.debug(" molecular profile map size: " + molecularProfileMap.size()); - return molecularProfileMap; - } - - public Map buildSampleListMap() { - Map sampleListMap = sampleListRepository.getAllSampleLists( - "SUMMARY", - REPOSITORY_RESULT_LIMIT, - REPOSITORY_RESULT_OFFSET, - null, - "ASC").stream() - .collect(Collectors.toMap(SampleList::getStableId, Function.identity())); - LOG.debug(" sample list map size: " + sampleListMap.size()); - return sampleListMap; - } - - public Map buildCancerStudyMap() { - Map cancerStudyMap = studyRepository.getAllStudies( - null, - "SUMMARY", - REPOSITORY_RESULT_LIMIT, - REPOSITORY_RESULT_OFFSET, - null, - "ASC").stream() - .collect(Collectors.toMap(CancerStudy::getCancerStudyIdentifier, Function.identity())); - LOG.debug(" cancer study map size: " + cancerStudyMap.size()); - return cancerStudyMap; - } -} diff --git a/src/main/java/org/cbioportal/persistence/cachemaputil/CacheMapUtil.java b/src/main/java/org/cbioportal/persistence/cachemaputil/CacheMapUtil.java deleted file mode 100644 index f476c301186..00000000000 --- a/src/main/java/org/cbioportal/persistence/cachemaputil/CacheMapUtil.java +++ /dev/null @@ -1,18 +0,0 @@ -package org.cbioportal.persistence.cachemaputil; - -import org.cbioportal.model.CancerStudy; -import org.cbioportal.model.MolecularProfile; -import org.cbioportal.model.SampleList; - -import java.util.Map; - -public interface CacheMapUtil { - Map getMolecularProfileMap(); - - Map getSampleListMap(); - - Map getCancerStudyMap(); - - boolean hasCacheEnabled(); - -} diff --git a/src/main/java/org/cbioportal/persistence/cachemaputil/InactiveCacheMapUtil.java b/src/main/java/org/cbioportal/persistence/cachemaputil/InactiveCacheMapUtil.java deleted file mode 100644 index 8213ede2aaf..00000000000 --- a/src/main/java/org/cbioportal/persistence/cachemaputil/InactiveCacheMapUtil.java +++ /dev/null @@ -1,39 +0,0 @@ -package org.cbioportal.persistence.cachemaputil; - -import org.cbioportal.model.CancerStudy; -import org.cbioportal.model.MolecularProfile; -import org.cbioportal.model.SampleList; -import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; -import org.springframework.stereotype.Component; - -import java.util.Map; - -@Component -// This implementation of the CacheMapUtils is instantiated on portals where all uses can access any study. -@ConditionalOnExpression("'false' eq '${authenticate}' or ('optional_oauth2' eq '${authenticate}' and 'true' ne '${security.method_authorization_enabled}')") -public class InactiveCacheMapUtil implements CacheMapUtil { - - // Since user-permission evaluation is not needed when this bean is present, throw an error when it is accessed. - - @Override - public Map getMolecularProfileMap() { - throw new RuntimeException("A CacheMapUtils method was called on a portal where studies are accessible to all users."); - } - - @Override - public Map getSampleListMap() { - throw new RuntimeException("A CacheMapUtils method was called on a portal where studies are accessible to all users."); - } - - @Override - public Map getCancerStudyMap() { - throw new RuntimeException("A CacheMapUtils method was called on a portal where studies are accessible to all users."); - } - - // bean is only instantiated when there is no user authorization - @Override - public boolean hasCacheEnabled() { - return false; - } - -} \ No newline at end of file diff --git a/src/main/java/org/cbioportal/persistence/cachemaputil/SpringManagedCacheMapUtil.java b/src/main/java/org/cbioportal/persistence/cachemaputil/SpringManagedCacheMapUtil.java deleted file mode 100644 index c492b2400b0..00000000000 --- a/src/main/java/org/cbioportal/persistence/cachemaputil/SpringManagedCacheMapUtil.java +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright (c) 2018 - 2019 Memorial Sloan-Kettering Cancer Center. - * - * This library is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS - * FOR A PARTICULAR PURPOSE. The software and documentation provided hereunder - * is on an "as is" basis, and Memorial Sloan-Kettering Cancer Center has no - * obligations to provide maintenance, support, updates, enhancements or - * modifications. In no event shall Memorial Sloan-Kettering Cancer Center be - * liable to any party for direct, indirect, special, incidental or - * consequential damages, including lost profits, arising out of the use of this - * software and its documentation, even if Memorial Sloan-Kettering Cancer - * Center has been advised of the possibility of such damage. - */ - -/* - * This file is part of cBioPortal. - * - * cBioPortal is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -package org.cbioportal.persistence.cachemaputil; - -import jakarta.annotation.PostConstruct; -import org.cbioportal.model.CancerStudy; -import org.cbioportal.model.MolecularProfile; -import org.cbioportal.model.SampleList; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.cache.annotation.Cacheable; -import org.springframework.stereotype.Component; - -import java.util.Map; - -@Component -// Instantiate when user authorization is active and spring-managed implementation is needed -@ConditionalOnExpression("{'oauth2','saml','saml_plus_basic'}.contains('${authenticate}') or ('optional_oauth2' eq '${authenticate}' and 'true' eq '${security.method_authorization_enabled}')") -@ConditionalOnProperty(value = "cache.cache-map-utils.spring-managed", havingValue = "true") -public class SpringManagedCacheMapUtil implements CacheMapUtil { - - private static final Logger LOG = LoggerFactory.getLogger(SpringManagedCacheMapUtil.class); - - @Value("${persistence.cache_type:no-cache}") - private String cacheType; - @Value("${persistence.cache_type_clickhouse:no-cache}") - private String cacheTypeClickhouse; - - @Value("${cache.cache-map-utils.spring-managed}") - private boolean springManagedCacheMapUtils; - - @Autowired - private CacheMapBuilder cacheMapBuilder; - - @PostConstruct - public void init() { - // Make sure the user does not have a conflicting configuration. Explode if there is. - if (cacheType.equals("no-cache") && cacheTypeClickhouse.equals("no-cache") && springManagedCacheMapUtils) { - throw new RuntimeException("cache.cache-map-utils.spring-managed property is set to 'true' but the portal is not " + - "configured with a cache-implementation (persistence.cache_type property is 'no-cache'). Please set to 'false'" + - " or configure the cache."); - } - } - - // This implementation of the CacheMapUtils does not keep a locally cached/referenced HashMap - // but retrieves the HashMaps from the active Spring caching solution. - - @Override - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - public Map getMolecularProfileMap() { - LOG.debug("Building molecularProfileMap (cache miss)"); - return cacheMapBuilder.buildMolecularProfileMap(); - } - - @Override - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - public Map getSampleListMap() { - LOG.debug("Building sampleListMap (cache miss)"); - return cacheMapBuilder.buildSampleListMap(); - } - - @Override - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - public Map getCancerStudyMap() { - LOG.debug("Building cancerStudyMap (cache miss)"); - return cacheMapBuilder.buildCancerStudyMap(); - } - - // bean is only instantiated when there is user authorization - @Override - public boolean hasCacheEnabled() { - return true; - } - -} diff --git a/src/main/java/org/cbioportal/persistence/cachemaputil/StaticRefCacheMapUtil.java b/src/main/java/org/cbioportal/persistence/cachemaputil/StaticRefCacheMapUtil.java deleted file mode 100644 index 48d07e0bff1..00000000000 --- a/src/main/java/org/cbioportal/persistence/cachemaputil/StaticRefCacheMapUtil.java +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright (c) 2018 - 2019 Memorial Sloan-Kettering Cancer Center. - * - * This library is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS - * FOR A PARTICULAR PURPOSE. The software and documentation provided hereunder - * is on an "as is" basis, and Memorial Sloan-Kettering Cancer Center has no - * obligations to provide maintenance, support, updates, enhancements or - * modifications. In no event shall Memorial Sloan-Kettering Cancer Center be - * liable to any party for direct, indirect, special, incidental or - * consequential damages, including lost profits, arising out of the use of this - * software and its documentation, even if Memorial Sloan-Kettering Cancer - * Center has been advised of the possibility of such damage. - */ - -/* - * This file is part of cBioPortal. - * - * cBioPortal is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -package org.cbioportal.persistence.cachemaputil; - -import jakarta.annotation.PostConstruct; -import org.cbioportal.model.CancerStudy; -import org.cbioportal.model.MolecularProfile; -import org.cbioportal.model.SampleList; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.stereotype.Component; - -import java.util.Map; - -@Component -// Instantiate when user authorization is active and spring-managed implementation is not needed -@ConditionalOnExpression("{'oauth2','saml','saml_plus_basic'}.contains('${authenticate}') or ('optional_oauth2' eq '${authenticate}' and 'true' eq '${security.method_authorization_enabled}')") -@ConditionalOnProperty(value = "cache.cache-map-utils.spring-managed", havingValue = "false", matchIfMissing = true) -public class StaticRefCacheMapUtil implements CacheMapUtil { - - private static final Logger LOG = LoggerFactory.getLogger(StaticRefCacheMapUtil.class); - - @Autowired - private CacheMapBuilder cacheMapBuilder; - - // This implementation of the CacheMapUtils keeps a locally cached/referenced HashMap and does - // not defer to any Spring managed caching solution. - - // maps used to cache required relationships - in all maps stable ids are key - // Fields are static because the proxying mechanism of the CancerStudyPermissionEvaluator - // appears to perturb the Singleton scope of the CacheMapUtils bean. When debugging - // two version appeared to exist in context. A mechanism with bean injection did not work here. - static Map molecularProfileCache; - static Map sampleListCache; - static Map cancerStudyCache; - - @PostConstruct - private void init() { - initializeCacheMemory(); - } - - public synchronized void initializeCacheMemory() { - LOG.debug("creating cache maps for authorization"); - molecularProfileCache = cacheMapBuilder.buildMolecularProfileMap(); - sampleListCache = cacheMapBuilder.buildSampleListMap(); - cancerStudyCache = cacheMapBuilder.buildCancerStudyMap(); - } - - @Override - public Map getMolecularProfileMap() { - return molecularProfileCache; - } - - @Override - public Map getSampleListMap() { - return sampleListCache; - } - - @Override - public Map getCancerStudyMap() { - return cancerStudyCache; - } - - @Override - public boolean hasCacheEnabled() { - return true; - } - -} diff --git a/src/main/java/org/cbioportal/persistence/config/EhCacheConfig.java b/src/main/java/org/cbioportal/persistence/config/EhCacheConfig.java deleted file mode 100644 index 15c7d10f76b..00000000000 --- a/src/main/java/org/cbioportal/persistence/config/EhCacheConfig.java +++ /dev/null @@ -1,49 +0,0 @@ -package org.cbioportal.persistence.config; - -import org.cbioportal.persistence.util.CustomEhcachingProvider; -import org.cbioportal.persistence.util.CustomKeyGenerator; -import org.cbioportal.utils.config.annotation.ConditionalOnProperty; -import org.springframework.cache.CacheManager; -import org.springframework.cache.annotation.CachingConfigurerSupport; -import org.springframework.cache.annotation.EnableCaching; -import org.springframework.cache.interceptor.KeyGenerator; -import org.springframework.cache.interceptor.NamedCacheResolver; -import org.springframework.cache.jcache.JCacheCacheManager; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; - -@Configuration -@EnableCaching -@ConditionalOnProperty(name = "persistence.cache_type", havingValue = {"ehcache-heap", "ehcache-disk", "ehcache-hybrid"}) -public class EhCacheConfig extends CachingConfigurerSupport { - - @Bean - @Override - public CacheManager cacheManager() { - return new JCacheCacheManager( - customEhcachingProvider().getCacheManager() - ); - } - - @Bean - @Override - public KeyGenerator keyGenerator() { - return new CustomKeyGenerator(); - } - - @Bean - public CustomEhcachingProvider customEhcachingProvider() { - return new CustomEhcachingProvider(); - } - - @Bean - public NamedCacheResolver generalRepositoryCacheResolver() { - return new NamedCacheResolver(cacheManager(), "GeneralRepositoryCache"); - } - - @Bean - public NamedCacheResolver staticRepositoryCacheOneResolver() { - return new NamedCacheResolver(cacheManager(), "StaticRepositoryCacheOne"); - } - -} diff --git a/src/main/java/org/cbioportal/persistence/config/RedisConfig.java b/src/main/java/org/cbioportal/persistence/config/RedisConfig.java deleted file mode 100644 index 99c225a33bd..00000000000 --- a/src/main/java/org/cbioportal/persistence/config/RedisConfig.java +++ /dev/null @@ -1,63 +0,0 @@ -package org.cbioportal.persistence.config; - -import org.cbioportal.persistence.util.CustomKeyGenerator; -import org.cbioportal.persistence.util.CustomRedisCachingProvider; -import org.cbioportal.persistence.util.LoggingCacheErrorHandler; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; -import org.springframework.cache.CacheManager; -import org.springframework.cache.annotation.CachingConfigurerSupport; -import org.springframework.cache.annotation.EnableCaching; -import org.springframework.cache.interceptor.CacheErrorHandler; -import org.springframework.cache.interceptor.CacheResolver; -import org.springframework.cache.interceptor.KeyGenerator; -import org.springframework.cache.interceptor.NamedCacheResolver; - -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; - -@Configuration -@EnableCaching -@ConditionalOnExpression( - "#{environment['persistence.cache_type'] == 'redis' or environment['persistence.cache_type_clickhouse'] == 'redis'}" -) -public class RedisConfig extends CachingConfigurerSupport { - - @Value("${redis.name:cbioportal}") - private String redisName; - - @Bean - @Override - public CacheManager cacheManager() { - return customRedisCachingProvider().getCacheManager( - customRedisCachingProvider().getRedissonClient() - ); - } - - @Override - public CacheErrorHandler errorHandler() { - return new LoggingCacheErrorHandler(); - } - - @Bean - @Override - public KeyGenerator keyGenerator() { - return new CustomKeyGenerator(); - } - - @Bean - public CustomRedisCachingProvider customRedisCachingProvider() { - return new CustomRedisCachingProvider(); - } - - @Bean - public CacheResolver generalRepositoryCacheResolver() { - return new NamedCacheResolver(cacheManager(), redisName + "GeneralRepositoryCache"); - } - - @Bean - public CacheResolver staticRepositoryCacheOneResolver() { - return new NamedCacheResolver(cacheManager(), redisName + "StaticRepositoryCacheOne"); - } - -} diff --git a/src/main/java/org/cbioportal/persistence/enums/ClinicalAttributeDataType.java b/src/main/java/org/cbioportal/persistence/enums/ClinicalAttributeDataType.java deleted file mode 100644 index 591f67e117d..00000000000 --- a/src/main/java/org/cbioportal/persistence/enums/ClinicalAttributeDataType.java +++ /dev/null @@ -1,16 +0,0 @@ -package org.cbioportal.persistence.enums; - -public enum ClinicalAttributeDataType { - CATEGORICAL("CATEGORICAL"), - NUMERIC("NUMERIC"); - - private final String value; - - ClinicalAttributeDataType(String value) { - this.value = value; - } - - public String getValue() { - return this.value; - } -} diff --git a/src/main/java/org/cbioportal/persistence/enums/DataSource.java b/src/main/java/org/cbioportal/persistence/enums/DataSource.java deleted file mode 100644 index 09b81b79edb..00000000000 --- a/src/main/java/org/cbioportal/persistence/enums/DataSource.java +++ /dev/null @@ -1,15 +0,0 @@ -package org.cbioportal.persistence.enums; - -public enum DataSource { - PATIENT("PATIENT"),SAMPLE("SAMPLE"); - - private final String value; - - DataSource(String value) { - this.value = value; - } - - public String getValue() { - return this.value; - } -} diff --git a/src/main/java/org/cbioportal/persistence/helper/AlterationFilterHelper.java b/src/main/java/org/cbioportal/persistence/helper/AlterationFilterHelper.java deleted file mode 100644 index 1d8f63a55f2..00000000000 --- a/src/main/java/org/cbioportal/persistence/helper/AlterationFilterHelper.java +++ /dev/null @@ -1,151 +0,0 @@ -package org.cbioportal.persistence.helper; - -import org.cbioportal.model.AlterationFilter; -import org.cbioportal.model.CNA; -import org.cbioportal.model.MutationEventType; -import org.cbioportal.model.util.Select; -import org.springframework.lang.NonNull; -import org.springframework.lang.Nullable; - -import java.util.Objects; - -public final class AlterationFilterHelper { - - public static AlterationFilterHelper build(@Nullable AlterationFilter alterationFilter) { - if (Objects.isNull(alterationFilter)) { - alterationFilter = new AlterationFilter(); - } - return new AlterationFilterHelper(alterationFilter); - } - - private final AlterationFilter alterationFilter; - private final Select mappedMutationTypes; - - private final Select mappedCnaTypes; - - private AlterationFilterHelper(@NonNull AlterationFilter alterationFilter){ - this.alterationFilter = alterationFilter; - this.mappedMutationTypes = buildMutationTypeList(); - this.mappedCnaTypes = buildCnaTypeList(); - } - - private Select buildMutationTypeList() { - if (alterationFilter.getMutationTypeSelect().hasNone()) { - return Select.none(); - } - if (alterationFilter.getMutationTypeSelect().hasAll()) { - return Select.all(); - } - Select typeSelects = alterationFilter.getMutationTypeSelect().map(MutationEventType::getMutationType); - typeSelects.inverse(alterationFilter.getMutationTypeSelect().inverse()); - - return typeSelects; - } - - public Select getMutationTypeList() { - return mappedMutationTypes; - } - - public Select getCnaTypeList() { - return mappedCnaTypes; - } - - public Select buildCnaTypeList() { - if (alterationFilter.getCNAEventTypeSelect().hasNone()) { - return Select.none(); - } - if (alterationFilter.getCNAEventTypeSelect().hasAll()) { - return Select.all(); - } - return alterationFilter.getCNAEventTypeSelect().map(CNA::getCode); - } - - public boolean hasDriver() { - return alterationFilter.getIncludeDriver(); - } - - public boolean hasVUSDriver() { - return alterationFilter.getIncludeVUS(); - } - - public boolean hasUnknownOncogenicity() { - return alterationFilter.getIncludeUnknownOncogenicity(); - } - - public boolean hasGermline() { - return alterationFilter.getIncludeGermline(); - } - - public boolean hasSomatic() { - return alterationFilter.getIncludeSomatic(); - } - - public boolean hasUnknownMutationStatus() { - return alterationFilter.getIncludeUnknownStatus(); - } - - public Select getSelectedTiers() { - return alterationFilter.getSelectedTiers(); - } - - public boolean hasUnknownTier() { - return alterationFilter.getIncludeUnknownTier(); - } - - public boolean isAllDriverAnnotationSelected() { - return alterationFilter.getIncludeDriver() && alterationFilter.getIncludeVUS() && alterationFilter.getIncludeUnknownOncogenicity(); - } - - public boolean isNoDriverAnnotationSelected() { - return !alterationFilter.getIncludeDriver() && !alterationFilter.getIncludeVUS() && !alterationFilter.getIncludeUnknownOncogenicity(); - } - - public boolean isSomeDriverAnnotationsSelected() { - return !isAllDriverAnnotationSelected() && !isNoDriverAnnotationSelected(); - } - - public boolean isAllMutationStatusSelected() { - return alterationFilter.getIncludeGermline() - && alterationFilter.getIncludeSomatic() - && alterationFilter.getIncludeUnknownStatus(); - } - - public boolean isNoMutationStatusSelected() { - return !alterationFilter.getIncludeGermline() - && !alterationFilter.getIncludeSomatic() - && !alterationFilter.getIncludeUnknownStatus(); - } - - public boolean isSomeMutationStatusSelected() { - return !isAllMutationStatusSelected() && !isNoMutationStatusSelected(); - } - - public boolean isAllTierOptionsSelected() { - return !Objects.isNull(alterationFilter.getSelectedTiers()) - && alterationFilter.getSelectedTiers().hasAll() - && alterationFilter.getIncludeUnknownTier(); - } - - public boolean isNoTierOptionsSelected() { - return (Objects.isNull(alterationFilter.getSelectedTiers()) || alterationFilter.getSelectedTiers().hasNone()) - && !alterationFilter.getIncludeUnknownTier(); - } - - public boolean isSomeTierOptionsSelected() { - return !isAllTierOptionsSelected() && !isNoTierOptionsSelected(); - } - - public boolean shouldApplyMutationAlterationFilter() { - return isSomeDriverAnnotationsSelected() - || isSomeMutationStatusSelected() - || isSomeTierOptionsSelected() - || mappedMutationTypes.hasNone() - || (!mappedMutationTypes.hasNone() && !mappedMutationTypes.hasAll()); - } - - public boolean shouldApplyCnaAlterationFilter() { - return isSomeDriverAnnotationsSelected() - || mappedCnaTypes.hasNone() - || (!mappedCnaTypes.hasNone() && !mappedCnaTypes.hasAll()); - } -} diff --git a/src/main/java/org/cbioportal/persistence/helper/StudyViewFilterHelper.java b/src/main/java/org/cbioportal/persistence/helper/StudyViewFilterHelper.java deleted file mode 100644 index d0c87d2eabb..00000000000 --- a/src/main/java/org/cbioportal/persistence/helper/StudyViewFilterHelper.java +++ /dev/null @@ -1,253 +0,0 @@ -package org.cbioportal.persistence.helper; - -import org.cbioportal.model.MolecularProfile; -import org.cbioportal.persistence.enums.DataSource; -import org.cbioportal.web.parameter.ClinicalDataFilter; -import org.cbioportal.web.parameter.CategorizedGenericAssayDataCountFilter; -import org.cbioportal.web.parameter.CustomSampleIdentifier; -import org.cbioportal.web.parameter.DataFilter; -import org.cbioportal.web.parameter.DataFilterValue; -import org.cbioportal.web.parameter.GenericAssayDataFilter; -import org.cbioportal.web.parameter.GenomicDataFilter; -import org.cbioportal.web.parameter.StudyViewFilter; -import org.springframework.lang.NonNull; -import org.springframework.lang.Nullable; - -import java.math.BigDecimal; -import java.util.ArrayList; -import java.util.EnumMap; -import java.util.List; -import java.util.Map; -import java.util.Objects; - -public final class StudyViewFilterHelper { - public static StudyViewFilterHelper build(@Nullable StudyViewFilter studyViewFilter, - @Nullable Map> genericAssayProfilesMap, - @Nullable List customDataSamples, - @Nullable List involvedCancerStudies) { - if (Objects.isNull(studyViewFilter)) { - studyViewFilter = new StudyViewFilter(); - } - if (Objects.isNull(genericAssayProfilesMap)) { - genericAssayProfilesMap = new EnumMap<>(DataSource.class); - } - if (Objects.isNull(customDataSamples)) { - customDataSamples = new ArrayList<>(); - } - if (Objects.isNull(involvedCancerStudies)) { - involvedCancerStudies = new ArrayList<>(); - } - if (studyViewFilter.getGenomicDataFilters() != null && !studyViewFilter.getGenomicDataFilters().isEmpty()) { - List mergedGenomicDataFilters = mergeDataFilters(studyViewFilter.getGenomicDataFilters()); - studyViewFilter.setGenomicDataFilters(mergedGenomicDataFilters); - } - if (studyViewFilter.getClinicalDataFilters() != null && !studyViewFilter.getClinicalDataFilters().isEmpty()) { - List mergedClinicalDataFilters = mergeDataFilters(studyViewFilter.getClinicalDataFilters()); - studyViewFilter.setClinicalDataFilters(mergedClinicalDataFilters); - } - if (studyViewFilter.getGenericAssayDataFilters() != null && !studyViewFilter.getGenericAssayDataFilters().isEmpty()) { - List mergedGenericAssayDataFilters = mergeDataFilters(studyViewFilter.getGenericAssayDataFilters()); - studyViewFilter.setGenericAssayDataFilters(mergedGenericAssayDataFilters); - } - return new StudyViewFilterHelper(studyViewFilter, genericAssayProfilesMap, customDataSamples, involvedCancerStudies); - } - - private final StudyViewFilter studyViewFilter; - private final CategorizedGenericAssayDataCountFilter categorizedGenericAssayDataCountFilter; - private final List customDataSamples; - private final List involvedCancerStudies; - - private StudyViewFilterHelper(@NonNull StudyViewFilter studyViewFilter, - @NonNull Map> genericAssayProfilesMap, - @NonNull List customDataSamples, - @NonNull List involvedCancerStudies) { - this.studyViewFilter = studyViewFilter; - this.categorizedGenericAssayDataCountFilter = extractGenericAssayDataCountFilters(studyViewFilter, genericAssayProfilesMap); - this.customDataSamples = customDataSamples; - this.involvedCancerStudies = involvedCancerStudies; - } - - public StudyViewFilter studyViewFilter() { - return studyViewFilter; - } - - public CategorizedGenericAssayDataCountFilter categorizedGenericAssayDataCountFilter() { - return categorizedGenericAssayDataCountFilter; - } - - public List customDataSamples() { - return this.customDataSamples; - } - - public String[] filteredSampleIdentifiers() { - if (studyViewFilter != null && studyViewFilter.getSampleIdentifiers() != null) { - return studyViewFilter.getSampleIdentifiers().stream() - .map(sampleIdentifier -> sampleIdentifier.getStudyId() + "_" + sampleIdentifier.getSampleId()) - .toArray(String[]::new); - } else { - return new String[0]; - } - } - - public List involvedCancerStudies() { - return involvedCancerStudies; - } - - private CategorizedGenericAssayDataCountFilter extractGenericAssayDataCountFilters(final StudyViewFilter studyViewFilter, Map> genericAssayProfilesMap) { - if ((studyViewFilter.getGenericAssayDataFilters() == null || genericAssayProfilesMap.isEmpty())) - { - return CategorizedGenericAssayDataCountFilter.getBuilder().build(); - } - - CategorizedGenericAssayDataCountFilter.Builder builder = CategorizedGenericAssayDataCountFilter.getBuilder(); - - // No BINARY in the database yet - List sampleNumericalProfileTypes = genericAssayProfilesMap.get(DataSource.SAMPLE) - .stream().filter(profile -> profile.getDatatype().equals("LIMIT-VALUE")) - .map(profile -> profile.getStableId().replace(profile.getCancerStudyIdentifier() + "_", "")) - .toList(); - builder.setSampleNumericalGenericAssayDataFilters(studyViewFilter.getGenericAssayDataFilters().stream() - .filter(genericAssayDataFilter -> sampleNumericalProfileTypes.contains(genericAssayDataFilter.getProfileType())) - .toList()); - List sampleCategoricalProfileTypes = genericAssayProfilesMap.get(DataSource.SAMPLE) - .stream().filter(profile -> profile.getDatatype().equals("CATEGORICAL") || profile.getDatatype().equals("BINARY")) - .map(profile -> profile.getStableId().replace(profile.getCancerStudyIdentifier() + "_", "")) - .toList(); - builder.setSampleCategoricalGenericAssayDataFilters(studyViewFilter.getGenericAssayDataFilters().stream() - .filter(genericAssayDataFilter -> sampleCategoricalProfileTypes.contains(genericAssayDataFilter.getProfileType())) - .toList()); - List patientCategoricalProfileTypes = genericAssayProfilesMap.get(DataSource.PATIENT) - .stream().filter(profile -> profile.getDatatype().equals("CATEGORICAL") || profile.getDatatype().equals("BINARY")) - .map(profile -> profile.getStableId().replace(profile.getCancerStudyIdentifier() + "_", "")) - .toList(); - builder.setPatientCategoricalGenericAssayDataFilters(studyViewFilter.getGenericAssayDataFilters().stream() - .filter(genericAssayDataFilter -> patientCategoricalProfileTypes.contains(genericAssayDataFilter.getProfileType())) - .toList()); - return builder.build(); - } - - public boolean isCategoricalClinicalDataFilter(ClinicalDataFilter clinicalDataFilter) { - var filterValue = clinicalDataFilter.getValues().getFirst(); - return filterValue.getValue() != null; - } - - /** - * Merge the range of numerical bins in DataFilters to reduce the number of scans that runs on the database when filtering. - */ - public static List mergeDataFilters(List filters) { - // this should throw error or move to all binning endpoints in the future for input validation - if (!areValidFilters(filters)) { - return filters; - } - - boolean hasNumericalValue = false; - List mergedDataFilters = new ArrayList<>(); - - for (T filter : filters) { - List mergedValues = new ArrayList<>(); - List nonNumericalValues = new ArrayList<>(); - - // record the start and end of current merging range - BigDecimal mergedStart = null; - BigDecimal mergedEnd = null; - // for each value - for (DataFilterValue dataFilterValue : filter.getValues()) { - // if it is non-numerical, leave it as is - if (dataFilterValue.getValue() != null) { - nonNumericalValues.add(dataFilterValue); - continue; - } - // else it is numerical so start merging process - hasNumericalValue = true; - BigDecimal start = dataFilterValue.getStart(); - BigDecimal end = dataFilterValue.getEnd(); - - // if current merging range is null, we take current bin's range - if (mergedStart == null && mergedEnd == null) { - mergedStart = start; - mergedEnd = end; - } - // else we already has a merging range, we check if this one is consecutive of our range - else if (mergedEnd.equals(start)) { - // if true, we expand our range - mergedEnd = end; - } - else { - // otherwise it's a gap, so we save our current range first, and then use current bin to start the next range - mergedValues.add(new DataFilterValue(mergedStart, mergedEnd)); - mergedStart = start; - mergedEnd = end; - } - } - - // in the end we need to save the final range, but if everything is non-numerical then no need to - if (hasNumericalValue) { - mergedValues.add(new DataFilterValue(mergedStart, mergedEnd)); - } - mergedValues.addAll(nonNumericalValues); - filter.setValues(mergedValues); - mergedDataFilters.add(filter); - } - - return mergedDataFilters; - } - - public static boolean areValidFilters(List filters) { - if (filters == null || filters.isEmpty()) { - return false; - } - - for (T filter : filters) { - if (!isValidFilter(filter)) { - return false; - } - } - return true; - } - - private static boolean isValidFilter(T filter) { - if (filter == null || filter.getValues() == null || filter.getValues().isEmpty()) { - return false; - } - - BigDecimal start = null; - BigDecimal end = null; - for (DataFilterValue value : filter.getValues()) { - if (!validateDataFilterValue(value, start, end)) { - return false; - } - // update start and end values to check next bin range - if (value.getStart() != null) { - start = value.getStart(); - } - if (value.getEnd() != null) { - end = value.getEnd(); - } - } - return true; - } - - private static boolean validateDataFilterValue(DataFilterValue value, BigDecimal lastStart, BigDecimal lastEnd) { - // non-numerical value should not have numerical value - if (value.getValue() != null) { - return value.getStart() == null && value.getEnd() == null; - } - - // check if start < end - if (value.getStart() != null && value.getEnd() != null - && value.getStart().compareTo(value.getEnd()) >= 0) { - return false; - } - - // check if start stays increasing and no overlapping - if (value.getStart() != null - && ((lastStart != null && lastStart.compareTo(value.getStart()) >= 0) - || (lastEnd != null && value.getStart().compareTo(lastEnd) < 0))) { - return false; - } - - // check if end stays increasing - return value.getEnd() == null || lastEnd == null - || lastEnd.compareTo(value.getEnd()) < 0; - } -} diff --git a/src/main/java/org/cbioportal/persistence/model/SampleAcquisitionEventRecord.java b/src/main/java/org/cbioportal/persistence/model/SampleAcquisitionEventRecord.java deleted file mode 100644 index b02c24c7100..00000000000 --- a/src/main/java/org/cbioportal/persistence/model/SampleAcquisitionEventRecord.java +++ /dev/null @@ -1,4 +0,0 @@ -package org.cbioportal.persistence.model; - -public record SampleAcquisitionEventRecord(String sampleId, String patientUniqueId, String cancerStudyId, int timeTaken) { -} diff --git a/src/main/java/org/cbioportal/persistence/model/TreatmentRecord.java b/src/main/java/org/cbioportal/persistence/model/TreatmentRecord.java deleted file mode 100644 index aeeac35723b..00000000000 --- a/src/main/java/org/cbioportal/persistence/model/TreatmentRecord.java +++ /dev/null @@ -1,4 +0,0 @@ -package org.cbioportal.persistence.model; - -public record TreatmentRecord(String patientUniqueId, String treatment, int startTime, int stopTime) { -} diff --git a/src/main/java/org/cbioportal/persistence/mybatis/AlterationCountsMapper.java b/src/main/java/org/cbioportal/persistence/mybatis/AlterationCountsMapper.java deleted file mode 100644 index 4b1461cdbb8..00000000000 --- a/src/main/java/org/cbioportal/persistence/mybatis/AlterationCountsMapper.java +++ /dev/null @@ -1,134 +0,0 @@ -package org.cbioportal.persistence.mybatis; - -import org.cbioportal.model.AlterationCountByGene; -import org.cbioportal.model.AlterationCountByStructuralVariant; -import org.cbioportal.model.CopyNumberCountByGene; -import org.cbioportal.model.MolecularProfileCaseIdentifier; -import org.cbioportal.model.util.Select; - -import java.util.List; - -public interface AlterationCountsMapper { - - /** - * Calculate sample-level counts of mutation and discrete CNA alteration events in genes. - * @param entrezGeneIds Gene ids to get counts for. - * @param mutationTypes Types of mutations to include in alteration counts. - * @param cnaTypes Types of discrete copy number alteration types to include in alteration counts. - * @param includeDriver Include Variants of Unknown significance. Uses annotations loaded as 'custom driver annotations'. - * @param includeVUS Include Variants of Unknown significance. Uses annotations loaded as 'custom driver annotations'. - * @param includeUnknownOncogenicity Include variants that are not annotated as driver or VUS. Uses annotations loaded as 'custom driver annotations'. - * @param selectedTiers Force alterations assigned to a tier to be interpreted as driver events. Uses tier annotations loaded as 'custom driver annotation tiers'. - * @param includeUnknownTier Include mutations that have unspecified tier, or tiers with '', 'NA' or 'unknown' in alteration counts - * @param includeGermline Include germline mutations in alteration counts - * @param includeSomatic Include somatic mutations in alteration counts - * @return Gene-level counts of (1) the total number of alterations and (2) the number of altered samples. - */ - List getSampleAlterationGeneCounts(List mutationMolecularProfileCaseIdentifiers, - List cnaMolecularProfileCaseIdentifiers, - List structuralVariantMolecularProfileCaseIdentifiers, - Select entrezGeneIds, - Select mutationTypes, - Select cnaTypes, - boolean includeDriver, - boolean includeVUS, - boolean includeUnknownOncogenicity, - Select selectedTiers, - boolean includeUnknownTier, boolean includeGermline, - boolean includeSomatic, - boolean includeUnknownStatus); - - /** - * Calculate patient-level counts of mutation and discrete CNA alteration events in genes. - * @param entrezGeneIds Gene ids to get counts for. - * @param mutationTypes Types of mutations to include in alteration counts. - * @param cnaTypes Types of discrete copy number alteration types to include in alteration counts. - * @param includeDriver Include Variants of Unknown significance. Uses annotations loaded as 'custom driver annotations'. - * @param includeVUS Include Variants of Unknown significance. Uses annotations loaded as 'custom driver annotations'. - * @param includeUnknownOncogenicity Include variants that are not annotated as driver or VUS. Uses annotations loaded as 'custom driver annotations'. - * @param selectedTiers Force alterations assigned to a tier to be interpreted as driver events. Uses tier annotations loaded as 'custom driver annotation tiers'. - * @param includeUnknownTier Include mutations that have unspecified tier, or tiers with '', 'NA' or 'unknown' in alteration counts - * @param includeGermline Include germline mutations in alteration counts - * @param includeSomatic Include somatic mutations in alteration counts - * @param includeUnknownStatus Include mutations that have mutation status 'unknown' in alteration counts - * @return Gene-level counts of (1) the total number of alterations and (2) the number of altered patients. - */ - List getPatientAlterationGeneCounts(List mutationMolecularProfileCaseIdentifiers, - List cnaMolecularProfileCaseIdentifiers, - List structuralVariantMolecularProfileCaseIdentifiers, - Select entrezGeneIds, - Select mutationTypes, - Select cnaTypes, - boolean includeDriver, - boolean includeVUS, - boolean includeUnknownOncogenicity, - Select selectedTiers, - boolean includeUnknownTier, - boolean includeGermline, - boolean includeSomatic, - boolean includeUnknownStatus); - - // legacy method that returns CopyNumberCountByGene - List getSampleCnaGeneCounts(List cnaMolecularProfileCaseIdentifiers, - Select entrezGeneIds, - Select cnaTypes, - boolean includeDriver, - boolean includeVUS, - boolean includeUnknownOncogenicity, - Select selectedTiers, - boolean includeUnknownTier); - - // legacy method that returns CopyNumberCountByGene - List getPatientCnaGeneCounts(List cnaMolecularProfileCaseIdentifiers, - Select entrezGeneIds, - Select cnaTypes, - boolean includeDriver, - boolean includeVUS, - boolean includeUnknownOncogenicity, - Select selectedTiers, - boolean includeUnknownTier); - - List getMolecularProfileCaseInternalIdentifier(List molecularProfileSampleIdentifiers, String caseType); - - /** - * Calculate sample-level counts of structural variant events. - * @param includeDriver Include Variants of Unknown significance. Uses annotations loaded as 'custom driver annotations'. - * @param includeVUS Include Variants of Unknown significance. Uses annotations loaded as 'custom driver annotations'. - * @param includeUnknownOncogenicity Include variants that are not annotated as driver or VUS. Uses annotations loaded as 'custom driver annotations'. - * @param selectedTiers Force alterations assigned to a tier to be interpreted as driver events. Uses tier annotations loaded as 'custom driver annotation tiers'. - * @param includeUnknownTier Include mutations that have unspecified tier, or tiers with '', 'NA' or 'unknown' in alteration counts - * @param includeGermline Include germline mutations in alteration counts - * @param includeSomatic Include somatic mutations in alteration counts - * @return StructVar-level counts (GeneA::GeneB) of (1) the total number of alterations and (2) the number of altered samples. - */ - List getSampleStructuralVariantCounts(List structuralVariantMolecularProfileCaseIdentifiers, - boolean includeDriver, - boolean includeVUS, - boolean includeUnknownOncogenicity, - Select selectedTiers, - boolean includeUnknownTier, - boolean includeGermline, - boolean includeSomatic, - boolean includeUnknownStatus); - /** - * Calculate patient-level counts of structural variant events. - * @param includeDriver Include Variants of Unknown significance. Uses annotations loaded as 'custom driver annotations'. - * @param includeVUS Include Variants of Unknown significance. Uses annotations loaded as 'custom driver annotations'. - * @param includeUnknownOncogenicity Include variants that are not annotated as driver or VUS. Uses annotations loaded as 'custom driver annotations'. - * @param selectedTiers Force alterations assigned to a tier to be interpreted as driver events. Uses tier annotations loaded as 'custom driver annotation tiers'. - * @param includeUnknownTier Include mutations that have unspecified tier, or tiers with '', 'NA' or 'unknown' in alteration counts - * @param includeGermline Include germline mutations in alteration counts - * @param includeSomatic Include somatic mutations in alteration counts - * @return StructVar-level counts (GeneA::GeneB) of (1) the total number of alterations and (2) the number of altered patients. - */ - List getPatientStructuralVariantCounts(List structuralVariantMolecularProfileCaseIdentifiers, - boolean includeDriver, - boolean includeVUS, - boolean includeUnknownOncogenicity, - Select selectedTiers, - boolean includeUnknownTier, - boolean includeGermline, - boolean includeSomatic, - boolean includeUnknownStatus); - -} diff --git a/src/main/java/org/cbioportal/persistence/mybatis/AlterationDriverAnnotationMapper.java b/src/main/java/org/cbioportal/persistence/mybatis/AlterationDriverAnnotationMapper.java deleted file mode 100644 index 34b5a02eb05..00000000000 --- a/src/main/java/org/cbioportal/persistence/mybatis/AlterationDriverAnnotationMapper.java +++ /dev/null @@ -1,12 +0,0 @@ -package org.cbioportal.persistence.mybatis; - -import org.apache.ibatis.annotations.Param; -import org.cbioportal.model.AlterationDriverAnnotation; - -import java.util.List; - -public interface AlterationDriverAnnotationMapper { - - List getAlterationDriverAnnotations(@Param("molecularProfileIds") List molecularProfileIds); - -} \ No newline at end of file diff --git a/src/main/java/org/cbioportal/persistence/mybatis/AlterationDriverAnnotationMyBatisRepository.java b/src/main/java/org/cbioportal/persistence/mybatis/AlterationDriverAnnotationMyBatisRepository.java deleted file mode 100644 index 222336aac14..00000000000 --- a/src/main/java/org/cbioportal/persistence/mybatis/AlterationDriverAnnotationMyBatisRepository.java +++ /dev/null @@ -1,28 +0,0 @@ -package org.cbioportal.persistence.mybatis; - -import org.cbioportal.model.*; -import org.cbioportal.persistence.AlterationDriverAnnotationRepository; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Repository; - -import java.util.Collections; -import java.util.List; - -@Repository -public class AlterationDriverAnnotationMyBatisRepository implements AlterationDriverAnnotationRepository { - - @Autowired - private AlterationDriverAnnotationMapper alterationDriverAnnotationMapper; - - @Override - public List getAlterationDriverAnnotations( - List molecularProfileIds) { - - if (molecularProfileIds == null || molecularProfileIds.isEmpty()) { - return Collections.emptyList(); - } - - return alterationDriverAnnotationMapper.getAlterationDriverAnnotations(molecularProfileIds); - } - -} \ No newline at end of file diff --git a/src/main/java/org/cbioportal/persistence/mybatis/AlterationMyBatisRepository.java b/src/main/java/org/cbioportal/persistence/mybatis/AlterationMyBatisRepository.java deleted file mode 100644 index a48b6476b59..00000000000 --- a/src/main/java/org/cbioportal/persistence/mybatis/AlterationMyBatisRepository.java +++ /dev/null @@ -1,246 +0,0 @@ -package org.cbioportal.persistence.mybatis; - -import org.cbioportal.model.AlterationCountByGene; -import org.cbioportal.model.AlterationCountByStructuralVariant; -import org.cbioportal.model.AlterationFilter; -import org.cbioportal.model.CNA; -import org.cbioportal.model.CopyNumberCountByGene; -import org.cbioportal.model.MolecularProfile; -import org.cbioportal.model.MolecularProfileCaseIdentifier; -import org.cbioportal.model.MutationEventType; -import org.cbioportal.model.MolecularProfile.MolecularAlterationType; -import org.cbioportal.model.util.Select; -import org.cbioportal.persistence.AlterationRepository; -import org.cbioportal.persistence.MolecularProfileRepository; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Repository; - -import java.util.*; -import java.util.stream.Collectors; - -@Repository -public class AlterationMyBatisRepository implements AlterationRepository { - - @Autowired - private AlterationCountsMapper alterationCountsMapper; - @Autowired - private MolecularProfileRepository molecularProfileRepository; - - @Override - public List getSampleAlterationGeneCounts(Set molecularProfileCaseIdentifiers, - Select entrezGeneIds, - AlterationFilter alterationFilter) { - - if ((alterationFilter.getMutationTypeSelect().hasNone() && alterationFilter.getCNAEventTypeSelect().hasNone() - && !alterationFilter.getStructuralVariants()) - || (molecularProfileCaseIdentifiers == null || molecularProfileCaseIdentifiers.isEmpty()) - || allAlterationsExcludedDriverAnnotation(alterationFilter) - || allAlterationsExcludedMutationStatus(alterationFilter) - || allAlterationsExcludedDriverTierAnnotation(alterationFilter) - ) { - // We want a mutable empty list: - return new ArrayList<>(); - } - - Set molecularProfileIds = molecularProfileCaseIdentifiers.stream() - .map(MolecularProfileCaseIdentifier::getMolecularProfileId) - .collect(Collectors.toSet()); - Map profileTypeByProfileId = molecularProfileRepository - .getMolecularProfiles(molecularProfileIds, "SUMMARY") - .stream() - .collect(Collectors.toMap(datum -> datum.getMolecularProfileId().toString(), MolecularProfile::getMolecularAlterationType)); - Map> groupedIdentifiersByProfileType = - alterationCountsMapper.getMolecularProfileCaseInternalIdentifier(new ArrayList<>(molecularProfileCaseIdentifiers), "SAMPLE_ID") - .stream() - .collect(Collectors.groupingBy(e -> profileTypeByProfileId.getOrDefault(e.getMolecularProfileId(), null))); - return alterationCountsMapper.getSampleAlterationGeneCounts( - groupedIdentifiersByProfileType.get(MolecularAlterationType.MUTATION_EXTENDED), - groupedIdentifiersByProfileType.get(MolecularAlterationType.COPY_NUMBER_ALTERATION), - groupedIdentifiersByProfileType.get(MolecularAlterationType.STRUCTURAL_VARIANT), - entrezGeneIds, - createMutationTypeList(alterationFilter), - createCnaTypeList(alterationFilter), - alterationFilter.getIncludeDriver(), - alterationFilter.getIncludeVUS(), - alterationFilter.getIncludeUnknownOncogenicity(), - alterationFilter.getSelectedTiers(), - alterationFilter.getIncludeUnknownTier(), - alterationFilter.getIncludeGermline(), - alterationFilter.getIncludeSomatic(), - alterationFilter.getIncludeUnknownStatus()); - } - - @Override - public List getPatientAlterationGeneCounts(Set molecularProfileCaseIdentifiers, - Select entrezGeneIds, - AlterationFilter alterationFilter) { - - if ((alterationFilter.getMutationTypeSelect().hasNone() && alterationFilter.getCNAEventTypeSelect().hasNone() - && !alterationFilter.getStructuralVariants()) - || (molecularProfileCaseIdentifiers == null || molecularProfileCaseIdentifiers.isEmpty()) - || allAlterationsExcludedDriverAnnotation(alterationFilter) - || allAlterationsExcludedMutationStatus(alterationFilter) - || allAlterationsExcludedDriverTierAnnotation(alterationFilter)) { - return Collections.emptyList(); - } - - Set molecularProfileIds = molecularProfileCaseIdentifiers.stream() - .map(MolecularProfileCaseIdentifier::getMolecularProfileId) - .collect(Collectors.toSet()); - - Map profileTypeByProfileId = molecularProfileRepository - .getMolecularProfiles(molecularProfileIds, "SUMMARY") - .stream() - .collect(Collectors.toMap(datum -> datum.getMolecularProfileId().toString(), MolecularProfile::getMolecularAlterationType)); - - Map> groupedIdentifiersByProfileType = - alterationCountsMapper.getMolecularProfileCaseInternalIdentifier(new ArrayList<>(molecularProfileCaseIdentifiers), "PATIENT_ID") - .stream() - .collect(Collectors.groupingBy(e -> profileTypeByProfileId.getOrDefault(e.getMolecularProfileId(), null))); - - - return alterationCountsMapper.getPatientAlterationGeneCounts( - groupedIdentifiersByProfileType.get(MolecularAlterationType.MUTATION_EXTENDED), - groupedIdentifiersByProfileType.get(MolecularAlterationType.COPY_NUMBER_ALTERATION), - groupedIdentifiersByProfileType.get(MolecularAlterationType.STRUCTURAL_VARIANT), - entrezGeneIds, - createMutationTypeList(alterationFilter), - createCnaTypeList(alterationFilter), - alterationFilter.getIncludeDriver(), - alterationFilter.getIncludeVUS(), - alterationFilter.getIncludeUnknownOncogenicity(), - alterationFilter.getSelectedTiers(), - alterationFilter.getIncludeUnknownTier(), - alterationFilter.getIncludeGermline(), - alterationFilter.getIncludeSomatic(), - alterationFilter.getIncludeUnknownStatus() - ); - } - - @Override - public List getSampleCnaGeneCounts(Set molecularProfileCaseIdentifiers, - Select entrezGeneIds, - AlterationFilter alterationFilter) { - - if (alterationFilter.getCNAEventTypeSelect().hasNone() || molecularProfileCaseIdentifiers == null - || allAlterationsExcludedDriverAnnotation(alterationFilter) - || allAlterationsExcludedDriverTierAnnotation(alterationFilter)) { - return Collections.emptyList(); - } - - List molecularProfileCaseInternalIdentifiers = - alterationCountsMapper.getMolecularProfileCaseInternalIdentifier(new ArrayList<>(molecularProfileCaseIdentifiers), "SAMPLE_ID"); - - return alterationCountsMapper.getSampleCnaGeneCounts( - molecularProfileCaseInternalIdentifiers, - entrezGeneIds, - createCnaTypeList(alterationFilter), - alterationFilter.getIncludeDriver(), - alterationFilter.getIncludeVUS(), - alterationFilter.getIncludeUnknownOncogenicity(), - alterationFilter.getSelectedTiers(), - alterationFilter.getIncludeUnknownTier()); - } - - @Override - public List getPatientCnaGeneCounts(Set molecularProfileCaseIdentifiers, - Select entrezGeneIds, - AlterationFilter alterationFilter) { - - if (alterationFilter.getCNAEventTypeSelect().hasNone() || molecularProfileCaseIdentifiers == null - || allAlterationsExcludedDriverAnnotation(alterationFilter) - || allAlterationsExcludedDriverTierAnnotation(alterationFilter)) { - return Collections.emptyList(); - } - List molecularProfileCaseInternalIdentifiers = - alterationCountsMapper.getMolecularProfileCaseInternalIdentifier(new ArrayList<>(molecularProfileCaseIdentifiers), "PATIENT_ID"); - - return alterationCountsMapper.getPatientCnaGeneCounts( - molecularProfileCaseInternalIdentifiers, - entrezGeneIds, - createCnaTypeList(alterationFilter), - alterationFilter.getIncludeDriver(), - alterationFilter.getIncludeVUS(), - alterationFilter.getIncludeUnknownOncogenicity(), - alterationFilter.getSelectedTiers(), - alterationFilter.getIncludeUnknownTier()); - } - - @Override - public List getSampleStructuralVariantCounts(Set molecularProfileCaseIdentifiers, - AlterationFilter alterationFilter) { - - if (molecularProfileCaseIdentifiers == null - || molecularProfileCaseIdentifiers.isEmpty() - || allAlterationsExcludedMutationStatus(alterationFilter)) { - return Collections.emptyList(); - } - - return alterationCountsMapper.getSampleStructuralVariantCounts( - new ArrayList<>(molecularProfileCaseIdentifiers), - alterationFilter.getIncludeDriver(), - alterationFilter.getIncludeVUS(), - alterationFilter.getIncludeUnknownOncogenicity(), - alterationFilter.getSelectedTiers(), - alterationFilter.getIncludeUnknownTier(), - alterationFilter.getIncludeGermline(), - alterationFilter.getIncludeSomatic(), - alterationFilter.getIncludeUnknownStatus()); - } - - @Override - public List getPatientStructuralVariantCounts(Set molecularProfileCaseIdentifiers, - AlterationFilter alterationFilter) { - - if (molecularProfileCaseIdentifiers == null - || molecularProfileCaseIdentifiers.isEmpty() - || allAlterationsExcludedMutationStatus(alterationFilter)) { - return Collections.emptyList(); - } - - return alterationCountsMapper.getPatientStructuralVariantCounts( - new ArrayList<>(molecularProfileCaseIdentifiers), - alterationFilter.getIncludeDriver(), - alterationFilter.getIncludeVUS(), - alterationFilter.getIncludeUnknownOncogenicity(), - alterationFilter.getSelectedTiers(), - alterationFilter.getIncludeUnknownTier(), - alterationFilter.getIncludeGermline(), - alterationFilter.getIncludeSomatic(), - alterationFilter.getIncludeUnknownStatus()); - } - - private Select createCnaTypeList(final AlterationFilter alterationFilter) { - if (alterationFilter.getCNAEventTypeSelect().hasNone()) - return Select.none(); - if (alterationFilter.getCNAEventTypeSelect().hasAll()) - return Select.all(); - return alterationFilter.getCNAEventTypeSelect().map(CNA::getCode); - } - - private Select createMutationTypeList(final AlterationFilter alterationFilter) { - if (alterationFilter.getMutationTypeSelect().hasNone()) - return Select.none(); - if (alterationFilter.getMutationTypeSelect().hasAll()) - return Select.all(); - Select mappedMutationTypes = alterationFilter.getMutationTypeSelect().map(MutationEventType::getMutationType); - mappedMutationTypes.inverse(alterationFilter.getMutationTypeSelect().inverse()); - - return mappedMutationTypes; - } - - private boolean allAlterationsExcludedMutationStatus(AlterationFilter alterationFilter) { - return !alterationFilter.getIncludeGermline() && !alterationFilter.getIncludeSomatic() && !alterationFilter.getIncludeUnknownStatus(); - } - - private boolean allAlterationsExcludedDriverAnnotation(AlterationFilter alterationFilter) { - return !alterationFilter.getIncludeDriver() && !alterationFilter.getIncludeVUS() - && !alterationFilter.getIncludeUnknownOncogenicity(); - } - - private boolean allAlterationsExcludedDriverTierAnnotation(AlterationFilter alterationFilter) { - return alterationFilter.getSelectedTiers().hasNone() - && !alterationFilter.getIncludeUnknownTier(); - } - -} diff --git a/src/main/java/org/cbioportal/persistence/mybatis/CancerTypeMapper.java b/src/main/java/org/cbioportal/persistence/mybatis/CancerTypeMapper.java deleted file mode 100644 index 4fbe328f514..00000000000 --- a/src/main/java/org/cbioportal/persistence/mybatis/CancerTypeMapper.java +++ /dev/null @@ -1,16 +0,0 @@ -package org.cbioportal.persistence.mybatis; - -import org.cbioportal.model.TypeOfCancer; -import org.cbioportal.model.meta.BaseMeta; - -import java.util.List; - -public interface CancerTypeMapper { - - List getAllCancerTypes(String projection, Integer limit, Integer offset, String sortBy, - String direction); - - BaseMeta getMetaCancerTypes(); - - TypeOfCancer getCancerType(String cancerTypeId, String projection); -} diff --git a/src/main/java/org/cbioportal/persistence/mybatis/CancerTypeMyBatisRepository.java b/src/main/java/org/cbioportal/persistence/mybatis/CancerTypeMyBatisRepository.java deleted file mode 100644 index 64cc83d3af3..00000000000 --- a/src/main/java/org/cbioportal/persistence/mybatis/CancerTypeMyBatisRepository.java +++ /dev/null @@ -1,36 +0,0 @@ -package org.cbioportal.persistence.mybatis; - -import org.cbioportal.model.TypeOfCancer; -import org.cbioportal.model.meta.BaseMeta; -import org.cbioportal.persistence.CancerTypeRepository; -import org.cbioportal.persistence.PersistenceConstants; -import org.cbioportal.persistence.mybatis.util.PaginationCalculator; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Repository; - -import java.util.List; - -@Repository -public class CancerTypeMyBatisRepository implements CancerTypeRepository { - - @Autowired - private CancerTypeMapper cancerTypeMapper; - - @Override - public List getAllCancerTypes(String projection, Integer pageSize, Integer pageNumber, String sortBy, - String direction) { - - return cancerTypeMapper.getAllCancerTypes(projection, pageSize, - PaginationCalculator.offset(pageSize, pageNumber), sortBy, direction); - } - - @Override - public BaseMeta getMetaCancerTypes() { - return cancerTypeMapper.getMetaCancerTypes(); - } - - @Override - public TypeOfCancer getCancerType(String cancerTypeId) { - return cancerTypeMapper.getCancerType(cancerTypeId, PersistenceConstants.DETAILED_PROJECTION); - } -} diff --git a/src/main/java/org/cbioportal/persistence/mybatis/ClinicalAttributeMapper.java b/src/main/java/org/cbioportal/persistence/mybatis/ClinicalAttributeMapper.java deleted file mode 100644 index cfee6ac5933..00000000000 --- a/src/main/java/org/cbioportal/persistence/mybatis/ClinicalAttributeMapper.java +++ /dev/null @@ -1,23 +0,0 @@ -package org.cbioportal.persistence.mybatis; - -import org.cbioportal.model.ClinicalAttribute; -import org.cbioportal.model.ClinicalAttributeCount; -import org.cbioportal.model.meta.BaseMeta; - -import java.util.List; - -public interface ClinicalAttributeMapper { - - List getClinicalAttributes(List studyIds, String projection, Integer limit, Integer offset, - String sortBy, String direction); - - BaseMeta getMetaClinicalAttributes(List studyIds); - - ClinicalAttribute getClinicalAttribute(String studyId, String clinicalAttributeId, String projection); - - List getClinicalAttributeCountsBySampleIds(List studyIds, List sampleIds); - - List getClinicalAttributeCountsBySampleListId(String sampleListId); - - List getClinicalAttributesByStudyIdsAndAttributeIds(List studyIds, List attributeIds); -} diff --git a/src/main/java/org/cbioportal/persistence/mybatis/ClinicalAttributeMyBatisRepository.java b/src/main/java/org/cbioportal/persistence/mybatis/ClinicalAttributeMyBatisRepository.java deleted file mode 100644 index 58fbbba59a2..00000000000 --- a/src/main/java/org/cbioportal/persistence/mybatis/ClinicalAttributeMyBatisRepository.java +++ /dev/null @@ -1,86 +0,0 @@ -package org.cbioportal.persistence.mybatis; - -import org.cbioportal.model.ClinicalAttribute; -import org.cbioportal.model.ClinicalAttributeCount; -import org.cbioportal.model.meta.BaseMeta; -import org.cbioportal.persistence.ClinicalAttributeRepository; -import org.cbioportal.persistence.PersistenceConstants; -import org.cbioportal.persistence.mybatis.util.PaginationCalculator; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Repository; - -import java.util.Arrays; -import java.util.List; - -@Repository -public class ClinicalAttributeMyBatisRepository implements ClinicalAttributeRepository { - - @Autowired - private ClinicalAttributeMapper clinicalAttributeMapper; - - @Override - public List getAllClinicalAttributes(String projection, Integer pageSize, Integer pageNumber, - String sortBy, String direction) { - - return clinicalAttributeMapper.getClinicalAttributes(null, projection, pageSize, - PaginationCalculator.offset(pageSize, pageNumber), sortBy, direction); - } - - @Override - public BaseMeta getMetaClinicalAttributes() { - - return clinicalAttributeMapper.getMetaClinicalAttributes(null); - } - - @Override - public ClinicalAttribute getClinicalAttribute(String studyId, String clinicalAttributeId) { - - return clinicalAttributeMapper.getClinicalAttribute(studyId, clinicalAttributeId, - PersistenceConstants.DETAILED_PROJECTION); - } - - @Override - public List getAllClinicalAttributesInStudy(String studyId, String projection, Integer pageSize, - Integer pageNumber, String sortBy, - String direction) { - - return clinicalAttributeMapper.getClinicalAttributes(Arrays.asList(studyId), projection, pageSize, - PaginationCalculator.offset(pageSize, pageNumber), sortBy, direction); - } - - @Override - public BaseMeta getMetaClinicalAttributesInStudy(String studyId) { - - return clinicalAttributeMapper.getMetaClinicalAttributes(Arrays.asList(studyId)); - } - - @Override - public List fetchClinicalAttributes(List studyIds, String projection) { - - return clinicalAttributeMapper.getClinicalAttributes(studyIds, projection, 0, 0, null, null); - } - - @Override - public BaseMeta fetchMetaClinicalAttributes(List studyIds) { - - return clinicalAttributeMapper.getMetaClinicalAttributes(studyIds); - } - - @Override - public List getClinicalAttributeCountsBySampleIds(List studyIds, List sampleIds) { - - return clinicalAttributeMapper.getClinicalAttributeCountsBySampleIds(studyIds, sampleIds); - } - - @Override - public List getClinicalAttributeCountsBySampleListId(String sampleListId) { - - return clinicalAttributeMapper.getClinicalAttributeCountsBySampleListId(sampleListId); - } - - @Override - public List getClinicalAttributesByStudyIdsAndAttributeIds(List studyIds, - List attributeIds) { - return clinicalAttributeMapper.getClinicalAttributesByStudyIdsAndAttributeIds(studyIds, attributeIds); - } -} diff --git a/src/main/java/org/cbioportal/persistence/mybatis/ClinicalDataMapper.java b/src/main/java/org/cbioportal/persistence/mybatis/ClinicalDataMapper.java deleted file mode 100644 index 50bb0c4e197..00000000000 --- a/src/main/java/org/cbioportal/persistence/mybatis/ClinicalDataMapper.java +++ /dev/null @@ -1,49 +0,0 @@ -package org.cbioportal.persistence.mybatis; - -import org.cbioportal.model.ClinicalData; -import org.cbioportal.model.ClinicalDataCount; -import org.cbioportal.model.meta.BaseMeta; - -import java.util.List; - -public interface ClinicalDataMapper { - - List getSampleClinicalData(List studyIds, List sampleIds, List attributeIds, - String projection, Integer limit, Integer offset, String sortBy, - String direction); - - BaseMeta getMetaSampleClinicalData(List studyIds, List sampleIds, List attributeIds); - - List getPatientClinicalData(List studyIds, List patientIds, List attributeIds, - String projection, Integer limit, Integer offset, String sortBy, - String direction); - - List getSampleClinicalTable(List studyIds, List sampleIds, String projection, - Integer limit, Integer offset, String searchTerm, - String sortByAttrId, Boolean sortAttrIsNumber, Boolean sortIsPatientAttr, - String direction); - - Integer getSampleClinicalTableCount(List studyIds, List sampleIds, String projection, - String searchTerm, String sortBy, String direction); - - BaseMeta getMetaPatientClinicalData(List studyIds, List patientIds, List attributeIds); - - List fetchSampleClinicalDataCounts(List studyIds, List sampleIds, - List attributeIds); - - List fetchPatientClinicalDataCounts(List studyIds, List patientIds, - List attributeIds, String projection); - - List getPatientClinicalDataDetailedToSample(List studyIds, List patientIds, - List attributeIds, String projection, Integer limit, - Integer offset, String sortBy, String direction); - - List getVisibleSampleInternalIdsForClinicalTable(List studyIds, List sampleIds, - String projection, Integer limit, Integer offset, - String searchTerm, String sortAttrId, Boolean sortAttrIsNumber, - Boolean sortIsPatientAttr, String direction); - - List getSampleClinicalDataBySampleInternalIds(List sampleInternalIds); - - List getPatientClinicalDataBySampleInternalIds(List sampleInternalIds); -} diff --git a/src/main/java/org/cbioportal/persistence/mybatis/ClinicalDataMyBatisRepository.java b/src/main/java/org/cbioportal/persistence/mybatis/ClinicalDataMyBatisRepository.java deleted file mode 100644 index 19cdde259fa..00000000000 --- a/src/main/java/org/cbioportal/persistence/mybatis/ClinicalDataMyBatisRepository.java +++ /dev/null @@ -1,235 +0,0 @@ -package org.cbioportal.persistence.mybatis; - -import org.cbioportal.model.ClinicalAttribute; -import org.cbioportal.model.ClinicalData; -import org.cbioportal.model.ClinicalDataCount; -import org.cbioportal.model.Patient; -import org.cbioportal.model.meta.BaseMeta; -import org.cbioportal.persistence.ClinicalDataRepository; -import org.cbioportal.persistence.ClinicalAttributeRepository; -import org.cbioportal.persistence.PatientRepository; -import org.cbioportal.persistence.PersistenceConstants; -import org.cbioportal.persistence.mybatis.util.PaginationCalculator; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Repository; -import org.springframework.util.Assert; - -import java.util.*; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -@Repository -public class ClinicalDataMyBatisRepository implements ClinicalDataRepository { - - @Autowired - private ClinicalDataMapper clinicalDataMapper; - @Autowired - private PatientRepository patientRepository; - @Autowired - private ClinicalAttributeRepository clinicalAttributeRepository; - - @Override - public List getAllClinicalDataOfSampleInStudy(String studyId, String sampleId, - String attributeId, String projection, - Integer pageSize, Integer pageNumber, - String sortBy, String direction) { - - return clinicalDataMapper.getSampleClinicalData(Arrays.asList(studyId), Arrays.asList(sampleId), - attributeId != null ? Arrays.asList(attributeId) : null, projection, pageSize, - PaginationCalculator.offset(pageSize, pageNumber), sortBy, direction); - } - - @Override - public BaseMeta getMetaSampleClinicalData(String studyId, String sampleId, String attributeId) { - return clinicalDataMapper.getMetaSampleClinicalData(Arrays.asList(studyId), Arrays.asList(sampleId), - attributeId != null ? Arrays.asList(attributeId) : null); - } - - @Override - public List getAllClinicalDataOfPatientInStudy(String studyId, String patientId, - String attributeId, String projection, - Integer pageSize, Integer pageNumber, - String sortBy, String direction) { - - return clinicalDataMapper.getPatientClinicalData(Arrays.asList(studyId), Arrays.asList(patientId), - attributeId != null ? Arrays.asList(attributeId) : null, projection, pageSize, - PaginationCalculator.offset(pageSize, pageNumber), sortBy, direction); - } - - @Override - public BaseMeta getMetaPatientClinicalData(String studyId, String patientId, String attributeId) { - return clinicalDataMapper.getMetaPatientClinicalData(Arrays.asList(studyId), Arrays.asList(patientId), - attributeId != null ? Arrays.asList(attributeId) : null); - } - - @Override - public List getAllClinicalDataInStudy(String studyId, String attributeId, - String clinicalDataType, String projection, - Integer pageSize, Integer pageNumber, - String sortBy, String direction) { - - if (clinicalDataType.equals(PersistenceConstants.SAMPLE_CLINICAL_DATA_TYPE)) { - return clinicalDataMapper.getSampleClinicalData(Arrays.asList(studyId), null, - attributeId != null ? Arrays.asList(attributeId) : null, projection, pageSize, - PaginationCalculator.offset(pageSize, pageNumber), sortBy, direction); - } else { - return clinicalDataMapper.getPatientClinicalData(Arrays.asList(studyId), null, - attributeId != null ? Arrays.asList(attributeId) : null, projection, pageSize, - PaginationCalculator.offset(pageSize, pageNumber), sortBy, direction); - } - } - - @Override - public BaseMeta getMetaAllClinicalData(String studyId, String attributeId, String clinicalDataType) { - - BaseMeta baseMeta = new BaseMeta(); - - if (clinicalDataType.equals(PersistenceConstants.SAMPLE_CLINICAL_DATA_TYPE)) { - baseMeta.setTotalCount(clinicalDataMapper.getMetaSampleClinicalData(Arrays.asList(studyId), null, - attributeId != null ? Arrays.asList(attributeId) : null).getTotalCount()); - } else { - baseMeta.setTotalCount(clinicalDataMapper.getMetaPatientClinicalData(Arrays.asList(studyId), null, - attributeId != null ? Arrays.asList(attributeId) : null).getTotalCount()); - } - - return baseMeta; - } - - @Override - public List fetchAllClinicalDataInStudy(String studyId, List ids, List attributeIds, - String clinicalDataType, String projection) { - - if (clinicalDataType.equals(PersistenceConstants.SAMPLE_CLINICAL_DATA_TYPE)) { - return clinicalDataMapper.getSampleClinicalData(Arrays.asList(studyId), ids, attributeIds, - projection, 0, 0, null, null); - } else { - return clinicalDataMapper.getPatientClinicalData(Arrays.asList(studyId), ids, attributeIds, - projection, 0, 0, null, null); - } - } - - @Override - public BaseMeta fetchMetaClinicalDataInStudy(String studyId, List ids, List attributeIds, - String clinicalDataType) { - - BaseMeta baseMeta = new BaseMeta(); - - if (clinicalDataType.equals(PersistenceConstants.SAMPLE_CLINICAL_DATA_TYPE)) { - baseMeta.setTotalCount(clinicalDataMapper.getMetaSampleClinicalData(Arrays.asList(studyId), ids, - attributeIds).getTotalCount()); - } else { - baseMeta.setTotalCount(clinicalDataMapper.getMetaPatientClinicalData(Arrays.asList(studyId), ids, - attributeIds).getTotalCount()); - } - - return baseMeta; - } - - @Override - public List fetchClinicalData(List studyIds, List ids, - List attributeIds, String clinicalDataType, - String projection) { - if (ids.isEmpty()) { - return new ArrayList<>(); - } - if (clinicalDataType.equals(PersistenceConstants.SAMPLE_CLINICAL_DATA_TYPE)) { - return clinicalDataMapper.getSampleClinicalData(studyIds, ids, attributeIds, projection, 0, 0, null, null); - } else { - return clinicalDataMapper.getPatientClinicalData(studyIds, ids, attributeIds, projection, 0, 0, null, null); - } - } - - public List getVisibleSampleInternalIdsForClinicalTable(List studyIds, List sampleIds, - Integer pageSize, Integer pageNumber, String searchTerm, - String sortAttrId, String direction) { - if (sampleIds.isEmpty()) { - return new ArrayList<>(); - } - Integer offset = PaginationCalculator.offset(pageSize, pageNumber); - Boolean sortAttrIsNumber = null; - Boolean sortIsPatientAttr = null; - - if (sortAttrId != null) { - if (sortAttrId.equals("patientId") || sortAttrId.equals("sampleId")) { - //these are both false because patientId and sampleId are actually not - //clinical attributes and are never numbers - sortAttrIsNumber = false; - sortIsPatientAttr = false; - } else { - ClinicalAttribute clinicalAttributeMeta = getClinicalAttributeMeta(studyIds, sortAttrId); - sortAttrIsNumber = clinicalAttributeMeta.getDatatype().equals("NUMBER"); - sortIsPatientAttr = clinicalAttributeMeta.getPatientAttribute(); - } - } - - - - return clinicalDataMapper.getVisibleSampleInternalIdsForClinicalTable(studyIds, sampleIds,"SUMMARY", pageSize, - offset, searchTerm, sortAttrId, sortAttrIsNumber, sortIsPatientAttr, direction); - } - - private ClinicalAttribute getClinicalAttributeMeta(List studyIds, String attrId) { - Assert.notNull(studyIds, "Arguments may not be null"); - Assert.notNull(attrId, "Arguments may not be null"); - Stream uniqueStudyIds = studyIds.stream().distinct(); - Optional clinicalAttributeMeta = uniqueStudyIds - .map(studyId -> clinicalAttributeRepository.getClinicalAttribute(studyId, attrId)) - .filter(Objects::nonNull) - .findFirst(); - Assert.isTrue(clinicalAttributeMeta.isPresent(), "Clinical Attribute " + attrId + - " was not found in studies " + studyIds.stream().collect(Collectors.joining(", ")) ); - return clinicalAttributeMeta.get(); - } - - @Override - public BaseMeta fetchMetaClinicalData(List studyIds, List ids, List attributeIds, - String clinicalDataType) { - - BaseMeta baseMeta = new BaseMeta(); - - if (clinicalDataType.equals(PersistenceConstants.SAMPLE_CLINICAL_DATA_TYPE)) { - baseMeta.setTotalCount(clinicalDataMapper.getMetaSampleClinicalData(studyIds, ids, attributeIds) - .getTotalCount()); - } else { - baseMeta.setTotalCount(clinicalDataMapper.getMetaPatientClinicalData(studyIds, ids, attributeIds) - .getTotalCount()); - } - - return baseMeta; - } - - @Override - public List fetchClinicalDataCounts(List studyIds, List sampleIds, - List attributeIds, String clinicalDataType, String projection) { - - if (clinicalDataType.equals(PersistenceConstants.SAMPLE_CLINICAL_DATA_TYPE)) { - return clinicalDataMapper.fetchSampleClinicalDataCounts(studyIds, sampleIds, attributeIds); - } else { - List patients = patientRepository.getPatientsOfSamples(studyIds, sampleIds); - List patientStudyIds = new ArrayList<>(); - patients.forEach(p -> patientStudyIds.add(p.getCancerStudyIdentifier())); - return clinicalDataMapper.fetchPatientClinicalDataCounts(patientStudyIds, - patients.stream().map(Patient::getStableId).collect(Collectors.toList()), attributeIds, projection); - } - } - - @Override - public List getPatientClinicalDataDetailedToSample(List studyIds, List patientIds, - List attributeIds) { - - return clinicalDataMapper.getPatientClinicalDataDetailedToSample(studyIds, patientIds, attributeIds, "SUMMARY", - 0, 0, null, null); - } - - @Override - public List getSampleClinicalDataBySampleInternalIds(List sampleInternalIds) { - return sampleInternalIds == null || sampleInternalIds.isEmpty() ? - new ArrayList<>() : clinicalDataMapper.getSampleClinicalDataBySampleInternalIds(sampleInternalIds); - } - - @Override - public List getPatientClinicalDataBySampleInternalIds(List sampleInternalIds) { - return sampleInternalIds == null || sampleInternalIds.isEmpty() ? - new ArrayList<>() : clinicalDataMapper.getPatientClinicalDataBySampleInternalIds(sampleInternalIds); - } -} diff --git a/src/main/java/org/cbioportal/persistence/mybatis/ClinicalEventMapper.java b/src/main/java/org/cbioportal/persistence/mybatis/ClinicalEventMapper.java deleted file mode 100644 index d87b0e8467d..00000000000 --- a/src/main/java/org/cbioportal/persistence/mybatis/ClinicalEventMapper.java +++ /dev/null @@ -1,30 +0,0 @@ -package org.cbioportal.persistence.mybatis; - -import org.cbioportal.model.ClinicalEvent; -import org.cbioportal.model.ClinicalEventData; -import org.cbioportal.model.meta.BaseMeta; - -import java.util.List; - -public interface ClinicalEventMapper { - - List getPatientClinicalEvent(String studyId, String patientId, String projection, Integer limit, - Integer offset, String sortBy, String direction); - - BaseMeta getMetaPatientClinicalEvent(String studyId, String patientId); - - List getDataOfClinicalEvents(List clinicalEventIds); - - List getStudyClinicalEvent(String studyId, String projection, Integer limit, - Integer offset, String sortBy, String direction); - - BaseMeta getMetaClinicalEvent(String studyId); - - List getSamplesOfPatientsPerEventType(List studyIds, List sampleIds); - - List getPatientsDistinctClinicalEventInStudies(List studyIds, List patientIds); - - List getTimelineEvents(List studyIds, List patientIds, List clinicalEvents); - - List getClinicalEventsMeta(List studyIds, List patientIds, List clinicalEvents); -} diff --git a/src/main/java/org/cbioportal/persistence/mybatis/ClinicalEventMyBatisRepository.java b/src/main/java/org/cbioportal/persistence/mybatis/ClinicalEventMyBatisRepository.java deleted file mode 100644 index ef65f4fa879..00000000000 --- a/src/main/java/org/cbioportal/persistence/mybatis/ClinicalEventMyBatisRepository.java +++ /dev/null @@ -1,81 +0,0 @@ -package org.cbioportal.persistence.mybatis; - -import org.cbioportal.model.ClinicalEvent; -import org.cbioportal.model.ClinicalEventData; -import org.cbioportal.model.meta.BaseMeta; -import org.cbioportal.persistence.ClinicalEventRepository; -import org.cbioportal.persistence.mybatis.util.PaginationCalculator; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Repository; - -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.stream.Collectors; - -import static java.util.stream.Collectors.groupingBy; - -@Repository -public class ClinicalEventMyBatisRepository implements ClinicalEventRepository { - - @Autowired - private ClinicalEventMapper clinicalEventMapper; - - @Override - public List getAllClinicalEventsOfPatientInStudy(String studyId, String patientId, String projection, - Integer pageSize, Integer pageNumber, String sortBy, - String direction) { - return clinicalEventMapper.getPatientClinicalEvent(studyId, patientId, projection, pageSize, - PaginationCalculator.offset(pageSize, pageNumber), sortBy, direction); - } - - @Override - public BaseMeta getMetaPatientClinicalEvents(String studyId, String patientId) { - - return clinicalEventMapper.getMetaPatientClinicalEvent(studyId, patientId); - } - - @Override - public List getDataOfClinicalEvents(List clinicalEventIds) { - - return clinicalEventMapper.getDataOfClinicalEvents(clinicalEventIds); - } - - @Override - public List getAllClinicalEventsInStudy(String studyId, String projection, Integer pageSize, - Integer pageNumber, String sortBy, String direction) { - return clinicalEventMapper.getStudyClinicalEvent(studyId, projection, pageSize, - PaginationCalculator.offset(pageSize, pageNumber), sortBy, direction); - } - - @Override - public BaseMeta getMetaClinicalEvents(String studyId) { - - return clinicalEventMapper.getMetaClinicalEvent(studyId); - } - - @Override - public Map> getSamplesOfPatientsPerEventTypeInStudy(List studyIds, List sampleIds) { - return clinicalEventMapper.getSamplesOfPatientsPerEventType(studyIds, sampleIds) - .stream() - .collect(groupingBy(ClinicalEvent::getEventType, - Collectors.mapping(ClinicalEvent::getUniqueSampleKey, Collectors.toSet()))); - } - - @Override - public List getPatientsDistinctClinicalEventInStudies(List studyIds, List patientIds) { - return clinicalEventMapper.getPatientsDistinctClinicalEventInStudies(studyIds, patientIds); - } - - @Override - public List getTimelineEvents(List studyIds, - List patientIds, - List clinicalEvents) { - return clinicalEventMapper.getTimelineEvents(studyIds, patientIds, clinicalEvents); - } - - @Override - public List getClinicalEventsMeta(List studyIds, List patientIds, List clinicalEvents) { - return clinicalEventMapper.getClinicalEventsMeta(studyIds, patientIds, clinicalEvents); - } -} diff --git a/src/main/java/org/cbioportal/persistence/mybatis/CopyNumberSegmentMapper.java b/src/main/java/org/cbioportal/persistence/mybatis/CopyNumberSegmentMapper.java deleted file mode 100644 index 1a0878bd654..00000000000 --- a/src/main/java/org/cbioportal/persistence/mybatis/CopyNumberSegmentMapper.java +++ /dev/null @@ -1,18 +0,0 @@ -package org.cbioportal.persistence.mybatis; - -import org.cbioportal.model.CopyNumberSeg; -import org.cbioportal.model.meta.BaseMeta; - -import java.util.List; - -public interface CopyNumberSegmentMapper { - - List getCopyNumberSegments(List studyIds, List sampleIds, String chromosome, String projection, - Integer limit, Integer offset, String sortBy, String direction); - - List getSamplesWithCopyNumberSegments(List studyIds, List sampleIds, String chromosome); - - BaseMeta getMetaCopyNumberSegments(List studyIds, List sampleIds, String chromosome); - - List getCopyNumberSegmentsBySampleListId(String studyId, String sampleListId, String chromosome, String projection); -} diff --git a/src/main/java/org/cbioportal/persistence/mybatis/CopyNumberSegmentMyBatisRepository.java b/src/main/java/org/cbioportal/persistence/mybatis/CopyNumberSegmentMyBatisRepository.java deleted file mode 100644 index 4e586ddb8c6..00000000000 --- a/src/main/java/org/cbioportal/persistence/mybatis/CopyNumberSegmentMyBatisRepository.java +++ /dev/null @@ -1,64 +0,0 @@ -package org.cbioportal.persistence.mybatis; - -import org.cbioportal.model.CopyNumberSeg; -import org.cbioportal.model.meta.BaseMeta; -import org.cbioportal.persistence.CopyNumberSegmentRepository; -import org.cbioportal.persistence.mybatis.util.PaginationCalculator; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Repository; - -import java.util.Arrays; -import java.util.List; - -@Repository -public class CopyNumberSegmentMyBatisRepository implements CopyNumberSegmentRepository { - - @Autowired - private CopyNumberSegmentMapper copyNumberSegmentMapper; - - - @Override - public List getCopyNumberSegmentsInSampleInStudy(String studyId, String sampleId, String chromosome, - String projection, Integer pageSize, - Integer pageNumber, String sortBy, - String direction) { - - return copyNumberSegmentMapper.getCopyNumberSegments(Arrays.asList(studyId), Arrays.asList(sampleId), chromosome, - projection, pageSize, PaginationCalculator.offset(pageSize, pageNumber), sortBy, direction); - } - - @Override - public BaseMeta getMetaCopyNumberSegmentsInSampleInStudy(String studyId, String sampleId, String chromosome) { - - return copyNumberSegmentMapper.getMetaCopyNumberSegments(Arrays.asList(studyId), Arrays.asList(sampleId), chromosome); - } - - @Override - public List fetchSamplesWithCopyNumberSegments(List studyIds, List sampleIds, String chromosome) { - return copyNumberSegmentMapper.getSamplesWithCopyNumberSegments(studyIds, sampleIds, chromosome); - } - - @Override - public List fetchCopyNumberSegments(List studyIds, - List sampleIds, - String chromosome, - String projection) { - - return copyNumberSegmentMapper.getCopyNumberSegments(studyIds, sampleIds, chromosome, projection, 0, 0, null, null); - } - - @Override - public BaseMeta fetchMetaCopyNumberSegments(List studyIds, List sampleIds, String chromosome) { - - return copyNumberSegmentMapper.getMetaCopyNumberSegments(studyIds, sampleIds, chromosome); - } - - @Override - public List getCopyNumberSegmentsBySampleListId(String studyId, - String sampleListId, - String chromosome, - String projection) { - - return copyNumberSegmentMapper.getCopyNumberSegmentsBySampleListId(studyId, sampleListId, chromosome, projection); - } -} diff --git a/src/main/java/org/cbioportal/persistence/mybatis/CosmicCountMapper.java b/src/main/java/org/cbioportal/persistence/mybatis/CosmicCountMapper.java deleted file mode 100644 index bfa7dec8af9..00000000000 --- a/src/main/java/org/cbioportal/persistence/mybatis/CosmicCountMapper.java +++ /dev/null @@ -1,10 +0,0 @@ -package org.cbioportal.persistence.mybatis; - -import org.cbioportal.model.CosmicMutation; - -import java.util.List; - -public interface CosmicCountMapper { - - List getCosmicCountsByKeywords(List keywords); -} diff --git a/src/main/java/org/cbioportal/persistence/mybatis/CosmicCountMyBatisRepository.java b/src/main/java/org/cbioportal/persistence/mybatis/CosmicCountMyBatisRepository.java deleted file mode 100644 index 9c2612f6576..00000000000 --- a/src/main/java/org/cbioportal/persistence/mybatis/CosmicCountMyBatisRepository.java +++ /dev/null @@ -1,20 +0,0 @@ -package org.cbioportal.persistence.mybatis; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Repository; - -import java.util.List; -import org.cbioportal.model.CosmicMutation; -import org.cbioportal.persistence.CosmicCountRepository; - -@Repository -public class CosmicCountMyBatisRepository implements CosmicCountRepository { - - @Autowired - private CosmicCountMapper cosmicCountMapper; - - public List fetchCosmicCountsByKeywords(List keywords) { - - return cosmicCountMapper.getCosmicCountsByKeywords(keywords); - } -} diff --git a/src/main/java/org/cbioportal/persistence/mybatis/DataAccessTokenMapper.java b/src/main/java/org/cbioportal/persistence/mybatis/DataAccessTokenMapper.java deleted file mode 100644 index bdadadf7e83..00000000000 --- a/src/main/java/org/cbioportal/persistence/mybatis/DataAccessTokenMapper.java +++ /dev/null @@ -1,18 +0,0 @@ -package org.cbioportal.persistence.mybatis; - -import org.cbioportal.model.DataAccessToken; -import java.util.List; - -public interface DataAccessTokenMapper { - - List getAllDataAccessTokensForUsername(String username); - - DataAccessToken getDataAccessToken(String token); - - void addDataAccessToken(DataAccessToken token); - - void removeDataAccessToken(String token); - - void removeAllDataAccessTokensForUsername(String username); -} - diff --git a/src/main/java/org/cbioportal/persistence/mybatis/DataAccessTokenMyBatisRepository.java b/src/main/java/org/cbioportal/persistence/mybatis/DataAccessTokenMyBatisRepository.java deleted file mode 100644 index e0e15bcd751..00000000000 --- a/src/main/java/org/cbioportal/persistence/mybatis/DataAccessTokenMyBatisRepository.java +++ /dev/null @@ -1,39 +0,0 @@ -package org.cbioportal.persistence.mybatis; - -import java.util.List; -import org.cbioportal.model.DataAccessToken; -import org.cbioportal.persistence.DataAccessTokenRepository; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Repository; - -@Repository -public class DataAccessTokenMyBatisRepository implements DataAccessTokenRepository { - - @Autowired - private DataAccessTokenMapper dataAccessTokenMapper; - - @Override - public List getAllDataAccessTokensForUsername(String username) { - return dataAccessTokenMapper.getAllDataAccessTokensForUsername(username); - } - - @Override - public DataAccessToken getDataAccessToken(String token) { - return dataAccessTokenMapper.getDataAccessToken(token); - } - - @Override - public void addDataAccessToken(DataAccessToken token) { - dataAccessTokenMapper.addDataAccessToken(token); - } - - @Override - public void removeDataAccessToken(String token) { - dataAccessTokenMapper.removeDataAccessToken(token); - } - - @Override - public void removeAllDataAccessTokensForUsername(String username) { - dataAccessTokenMapper.removeAllDataAccessTokensForUsername(username); - } -} diff --git a/src/main/java/org/cbioportal/persistence/mybatis/DiscreteCopyNumberMapper.java b/src/main/java/org/cbioportal/persistence/mybatis/DiscreteCopyNumberMapper.java deleted file mode 100644 index ab2934e6496..00000000000 --- a/src/main/java/org/cbioportal/persistence/mybatis/DiscreteCopyNumberMapper.java +++ /dev/null @@ -1,42 +0,0 @@ -package org.cbioportal.persistence.mybatis; - -import org.cbioportal.model.CopyNumberCountByGene; -import org.cbioportal.model.DiscreteCopyNumberData; -import org.cbioportal.model.GeneFilterQuery; -import org.cbioportal.model.meta.BaseMeta; - -import java.util.List; - -public interface DiscreteCopyNumberMapper { - - List getDiscreteCopyNumbersBySampleListId(String molecularProfileId, String sampleListId, - List entrezGeneIds, - List alterationTypes, String projection); - - BaseMeta getMetaDiscreteCopyNumbersBySampleListId(String molecularProfileId, String sampleListId, - List entrezGeneIds, List alterationTypes); - - List getDiscreteCopyNumbersBySampleIds(String molecularProfileId, List sampleIds, - List entrezGeneIds, - List alterationTypes, String projection); - - List getDiscreteCopyNumbersInMultipleMolecularProfiles(List molecularProfileIds, - List sampleIds, - List entrezGeneIds, - List alterationTypes, - String projection); - - List getDiscreteCopyNumbersInMultipleMolecularProfilesByGeneQueries(List molecularProfileIds, - List sampleIds, - String projection, - List geneQueries); - - BaseMeta getMetaDiscreteCopyNumbersBySampleIds(String molecularProfileId, List sampleIds, - List entrezGeneIds, List alterationTypes); - - List getSampleCountByGeneAndAlterationAndSampleIds(String molecularProfileId, - List sampleIds, - List entrezGeneIds, - List alterations); - -} diff --git a/src/main/java/org/cbioportal/persistence/mybatis/DiscreteCopyNumberMyBatisRepository.java b/src/main/java/org/cbioportal/persistence/mybatis/DiscreteCopyNumberMyBatisRepository.java deleted file mode 100644 index fdde1d8d0c6..00000000000 --- a/src/main/java/org/cbioportal/persistence/mybatis/DiscreteCopyNumberMyBatisRepository.java +++ /dev/null @@ -1,91 +0,0 @@ -package org.cbioportal.persistence.mybatis; - -import org.cbioportal.model.CopyNumberCountByGene; -import org.cbioportal.model.DiscreteCopyNumberData; -import org.cbioportal.model.GeneFilterQuery; -import org.cbioportal.model.meta.BaseMeta; -import org.cbioportal.persistence.DiscreteCopyNumberRepository; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Repository; - -import java.util.List; - -@Repository -public class DiscreteCopyNumberMyBatisRepository implements DiscreteCopyNumberRepository { - - @Autowired - private DiscreteCopyNumberMapper discreteCopyNumberMapper; - - @Override - public List getDiscreteCopyNumbersInMolecularProfileBySampleListId( - String molecularProfileId, - String sampleListId, - List entrezGeneIds, - List alterationTypes, - String projection) { - - return discreteCopyNumberMapper.getDiscreteCopyNumbersBySampleListId(molecularProfileId, sampleListId, - entrezGeneIds, alterationTypes, projection); - } - - @Override - public BaseMeta getMetaDiscreteCopyNumbersInMolecularProfileBySampleListId(String molecularProfileId, - String sampleListId, - List entrezGeneIds, - List alterationTypes) { - - return discreteCopyNumberMapper.getMetaDiscreteCopyNumbersBySampleListId(molecularProfileId, sampleListId, - entrezGeneIds, alterationTypes); - } - - @Override - public List fetchDiscreteCopyNumbersInMolecularProfile(String molecularProfileId, - List sampleIds, - List entrezGeneIds, - List alterationTypes, - String projection) { - - return discreteCopyNumberMapper.getDiscreteCopyNumbersBySampleIds(molecularProfileId, sampleIds, entrezGeneIds, - alterationTypes, projection); - } - - @Override - public List getDiscreteCopyNumbersInMultipleMolecularProfiles(List molecularProfileIds, - List sampleIds, - List entrezGeneIds, - List alterationTypes, - String projection) { - return discreteCopyNumberMapper.getDiscreteCopyNumbersInMultipleMolecularProfiles(molecularProfileIds, - sampleIds, entrezGeneIds, alterationTypes, projection); - } - - @Override - public List getDiscreteCopyNumbersInMultipleMolecularProfilesByGeneQueries(List molecularProfileIds, - List sampleIds, - List geneQueries, - String projection) { - - return discreteCopyNumberMapper.getDiscreteCopyNumbersInMultipleMolecularProfilesByGeneQueries(molecularProfileIds, - sampleIds, projection, geneQueries); - } - - @Override - public BaseMeta fetchMetaDiscreteCopyNumbersInMolecularProfile(String molecularProfileId, List sampleIds, - List entrezGeneIds, - List alterationTypes) { - - return discreteCopyNumberMapper.getMetaDiscreteCopyNumbersBySampleIds(molecularProfileId, sampleIds, - entrezGeneIds, alterationTypes); - } - - @Override - public List getSampleCountByGeneAndAlterationAndSampleIds(String molecularProfileId, - List sampleIds, - List entrezGeneIds, - List alterations) { - - return discreteCopyNumberMapper.getSampleCountByGeneAndAlterationAndSampleIds(molecularProfileId, sampleIds, - entrezGeneIds, alterations); - } - -} diff --git a/src/main/java/org/cbioportal/persistence/mybatis/GeneMapper.java b/src/main/java/org/cbioportal/persistence/mybatis/GeneMapper.java deleted file mode 100644 index 79cc63318df..00000000000 --- a/src/main/java/org/cbioportal/persistence/mybatis/GeneMapper.java +++ /dev/null @@ -1,35 +0,0 @@ -package org.cbioportal.persistence.mybatis; - -import org.cbioportal.model.Gene; -import org.cbioportal.model.GeneAlias; -import org.cbioportal.model.meta.BaseMeta; - -import java.util.List; - -public interface GeneMapper { - - List getGenes(String keyword, String alias, String projection, Integer limit, Integer offset, String sortBy, - String direction); - - BaseMeta getMetaGenes(String keyword, String alias); - - Gene getGeneByGeneticEntityId(Integer geneticEntityId, String projection); - - Gene getGeneByEntrezGeneId(Integer entrezGeneId, String projection); - - Gene getGeneByHugoGeneSymbol(String hugoGeneSymbol, String projection); - - List getAliasesOfGeneByEntrezGeneId(Integer entrezGeneId); - - List getAliasesOfGeneByHugoGeneSymbol(String hugoGeneSymbol); - - List getAllAliases(); - - List getGenesByEntrezGeneIds(List entrezGeneIds, String projection); - - List getGenesByHugoGeneSymbols(List hugoGeneSymbols, String projection); - - BaseMeta getMetaGenesByEntrezGeneIds(List entrezGeneIds); - - BaseMeta getMetaGenesByHugoGeneSymbols(List hugoGeneSymbols); -} diff --git a/src/main/java/org/cbioportal/persistence/mybatis/GeneMyBatisRepository.java b/src/main/java/org/cbioportal/persistence/mybatis/GeneMyBatisRepository.java deleted file mode 100644 index abf41874294..00000000000 --- a/src/main/java/org/cbioportal/persistence/mybatis/GeneMyBatisRepository.java +++ /dev/null @@ -1,91 +0,0 @@ -package org.cbioportal.persistence.mybatis; - -import org.cbioportal.model.Gene; -import org.cbioportal.model.GeneAlias; -import org.cbioportal.model.meta.BaseMeta; -import org.cbioportal.persistence.GeneRepository; -import org.cbioportal.persistence.PersistenceConstants; -import org.cbioportal.persistence.mybatis.util.PaginationCalculator; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Repository; - -import java.util.List; - -@Repository -public class GeneMyBatisRepository implements GeneRepository { - - @Autowired - private GeneMapper geneMapper; - - @Override - public List getAllGenes(String keyword, String alias, String projection, Integer pageSize, Integer pageNumber, String sortBy, - String direction) { - - return geneMapper.getGenes(keyword, alias, projection, pageSize, PaginationCalculator.offset(pageSize, pageNumber), - sortBy, direction); - } - - @Override - public BaseMeta getMetaGenes(String keyword, String alias) { - - return geneMapper.getMetaGenes(keyword, alias); - } - - @Override - public Gene getGeneByGeneticEntityId(Integer geneticEntityId) { - return geneMapper.getGeneByGeneticEntityId(geneticEntityId, PersistenceConstants.DETAILED_PROJECTION); - } - - @Override - public Gene getGeneByEntrezGeneId(Integer entrezGeneId) { - - return geneMapper.getGeneByEntrezGeneId(entrezGeneId, PersistenceConstants.DETAILED_PROJECTION); - } - - @Override - public Gene getGeneByHugoGeneSymbol(String hugoGeneSymbol) { - - return geneMapper.getGeneByHugoGeneSymbol(hugoGeneSymbol, PersistenceConstants.DETAILED_PROJECTION); - } - - @Override - public List getAliasesOfGeneByEntrezGeneId(Integer entrezGeneId) { - - return geneMapper.getAliasesOfGeneByEntrezGeneId(entrezGeneId); - } - - @Override - public List getAliasesOfGeneByHugoGeneSymbol(String hugoGeneSymbol) { - - return geneMapper.getAliasesOfGeneByHugoGeneSymbol(hugoGeneSymbol); - } - - @Override - public List getAllAliases() { - return geneMapper.getAllAliases(); - } - - @Override - public List fetchGenesByEntrezGeneIds(List entrezGeneIds, String projection) { - - return geneMapper.getGenesByEntrezGeneIds(entrezGeneIds, projection); - } - - @Override - public List fetchGenesByHugoGeneSymbols(List hugoGeneSymbols, String projection) { - - return geneMapper.getGenesByHugoGeneSymbols(hugoGeneSymbols, projection); - } - - @Override - public BaseMeta fetchMetaGenesByEntrezGeneIds(List entrezGeneIds) { - - return geneMapper.getMetaGenesByEntrezGeneIds(entrezGeneIds); - } - - @Override - public BaseMeta fetchMetaGenesByHugoGeneSymbols(List hugoGeneSymbols) { - - return geneMapper.getMetaGenesByHugoGeneSymbols(hugoGeneSymbols); - } -} diff --git a/src/main/java/org/cbioportal/persistence/mybatis/GenePanelMapper.java b/src/main/java/org/cbioportal/persistence/mybatis/GenePanelMapper.java deleted file mode 100644 index 5d5d8371754..00000000000 --- a/src/main/java/org/cbioportal/persistence/mybatis/GenePanelMapper.java +++ /dev/null @@ -1,34 +0,0 @@ -package org.cbioportal.persistence.mybatis; - -import org.cbioportal.model.GenePanel; -import org.cbioportal.model.GenePanelData; -import org.cbioportal.model.GenePanelToGene; -import org.cbioportal.model.MolecularProfileCaseIdentifier; -import org.cbioportal.model.meta.BaseMeta; - -import java.util.List; -import java.util.Set; - -public interface GenePanelMapper { - - List getAllGenePanels(String projection, Integer limit, Integer offset, String sortBy, - String direction); - - BaseMeta getMetaGenePanels(); - - GenePanel getGenePanel(String genePanelId, String projection); - - List fetchGenePanels(List genePanelIds, String projection); - - List getGenePanelDataBySampleListId(String molecularProfileId, String sampleListId); - - List getGenePanelDataBySampleIds(String molecularProfileId, List sampleIds); - - List fetchGenePanelDataByMolecularProfileIds(Set molecularProfileIds); - - List fetchGenePanelDataInMultipleMolecularProfiles(List molecularProfileSampleIdentifiers); - - List fetchGenePanelDataInMultipleMolecularProfilesByPatientIds(List molecularProfileSampleIdentifiers); - - List getGenesOfPanels(List genePanelIds); -} diff --git a/src/main/java/org/cbioportal/persistence/mybatis/GenePanelMyBatisRepository.java b/src/main/java/org/cbioportal/persistence/mybatis/GenePanelMyBatisRepository.java deleted file mode 100644 index cd984b312f1..00000000000 --- a/src/main/java/org/cbioportal/persistence/mybatis/GenePanelMyBatisRepository.java +++ /dev/null @@ -1,80 +0,0 @@ -package org.cbioportal.persistence.mybatis; - -import org.cbioportal.model.GenePanel; -import org.cbioportal.model.GenePanelData; -import org.cbioportal.model.GenePanelToGene; -import org.cbioportal.model.MolecularProfileCaseIdentifier; -import org.cbioportal.model.meta.BaseMeta; -import org.cbioportal.persistence.GenePanelRepository; -import org.cbioportal.persistence.PersistenceConstants; -import org.cbioportal.persistence.mybatis.util.PaginationCalculator; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Repository; - -import java.util.Collections; -import java.util.List; -import java.util.Set; - -@Repository -public class GenePanelMyBatisRepository implements GenePanelRepository { - - @Autowired - private GenePanelMapper genePanelMapper; - - @Override - public List getAllGenePanels(String projection, Integer pageSize, Integer pageNumber, String sortBy, - String direction) { - return genePanelMapper.getAllGenePanels(projection, pageSize, PaginationCalculator.offset(pageSize, pageNumber), - sortBy, direction); - } - - @Override - public BaseMeta getMetaGenePanels() { - return genePanelMapper.getMetaGenePanels(); - } - - @Override - public GenePanel getGenePanel(String genePanelId) { - return genePanelMapper.getGenePanel(genePanelId, PersistenceConstants.DETAILED_PROJECTION); - } - - @Override - public List fetchGenePanels(List genePanelIds, String projection) { - return genePanelMapper.fetchGenePanels(genePanelIds, projection); - } - - @Override - public List getGenePanelDataBySampleListId(String molecularProfileId, String sampleListId) { - return genePanelMapper.getGenePanelDataBySampleListId(molecularProfileId, sampleListId); - } - - @Override - public List fetchGenePanelData(String molecularProfileId, List sampleIds) { - return genePanelMapper.getGenePanelDataBySampleIds(molecularProfileId, sampleIds); - } - - @Override - public List fetchGenePanelDataByMolecularProfileIds(Set molecularProfileIds) { - return genePanelMapper.fetchGenePanelDataByMolecularProfileIds(molecularProfileIds); - } - - @Override - public List fetchGenePanelDataByMolecularProfileId(String molecularProfileId) { - return genePanelMapper.fetchGenePanelDataByMolecularProfileIds(Collections.singleton(molecularProfileId)); - } - - @Override - public List fetchGenePanelDataInMultipleMolecularProfiles(List molecularProfileSampleIdentifiers) { - return genePanelMapper.fetchGenePanelDataInMultipleMolecularProfiles(molecularProfileSampleIdentifiers); - } - - @Override - public List fetchGenePanelDataInMultipleMolecularProfilesByPatientIds(List molecularProfileSampleIdentifiers) { - return genePanelMapper.fetchGenePanelDataInMultipleMolecularProfilesByPatientIds(molecularProfileSampleIdentifiers); - } - - @Override - public List getGenesOfPanels(List genePanelIds) { - return genePanelMapper.getGenesOfPanels(genePanelIds); - } -} diff --git a/src/main/java/org/cbioportal/persistence/mybatis/GenericAssayMapper.java b/src/main/java/org/cbioportal/persistence/mybatis/GenericAssayMapper.java deleted file mode 100644 index 08a2f175fdd..00000000000 --- a/src/main/java/org/cbioportal/persistence/mybatis/GenericAssayMapper.java +++ /dev/null @@ -1,21 +0,0 @@ -package org.cbioportal.persistence.mybatis; - -import java.util.HashMap; -import java.util.List; - -import org.cbioportal.model.meta.GenericAssayMeta; -import org.cbioportal.model.GenericAssayAdditionalProperty; - -public interface GenericAssayMapper { - - List getGenericAssayMeta(List stableIds); - - List getGenericAssayAdditionalproperties(List stableIds); - - List getMolecularProfileInternalIdsByMolecularProfileIds(List molecularProfileIds); - - List getGeneticEntityIdsByMolecularProfileInternalIds(List molecularProfileInternalIds); - - List getGenericAssayStableIdsByGeneticEntityIds(List geneticEntityIds); - -} \ No newline at end of file diff --git a/src/main/java/org/cbioportal/persistence/mybatis/GenericAssayMyBatisRepository.java b/src/main/java/org/cbioportal/persistence/mybatis/GenericAssayMyBatisRepository.java deleted file mode 100644 index 4ee5a68de22..00000000000 --- a/src/main/java/org/cbioportal/persistence/mybatis/GenericAssayMyBatisRepository.java +++ /dev/null @@ -1,54 +0,0 @@ -package org.cbioportal.persistence.mybatis; - -import org.cbioportal.model.meta.GenericAssayMeta; -import org.cbioportal.model.GenericAssayAdditionalProperty; -import org.cbioportal.persistence.GenericAssayRepository; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Repository; -import org.springframework.cache.annotation.Cacheable; -import java.util.ArrayList; -import java.util.List; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -@Repository -public class GenericAssayMyBatisRepository implements GenericAssayRepository { - - @Autowired - private GenericAssayMapper genericAssayMapper; - - private static final Logger LOG = LoggerFactory.getLogger(GenericAssayMyBatisRepository.class); - - @Override - @Cacheable(cacheResolver = "staticRepositoryCacheOneResolver", condition = "@cacheEnabledConfig.getEnabled()") - public List getGenericAssayMeta(List stableIds) { - - return genericAssayMapper.getGenericAssayMeta(stableIds); - } - - @Override - @Cacheable(cacheResolver = "staticRepositoryCacheOneResolver", condition = "@cacheEnabledConfig.getEnabled()") - public List getGenericAssayAdditionalproperties(List stableIds) { - return genericAssayMapper.getGenericAssayAdditionalproperties(stableIds); - } - - @Override - @Cacheable(cacheResolver = "staticRepositoryCacheOneResolver", condition = "@cacheEnabledConfig.getEnabled()") - public List getGenericAssayStableIdsByMolecularIds(List molecularProfileIds) { - - List molecularProfileInternalIds = genericAssayMapper.getMolecularProfileInternalIdsByMolecularProfileIds(molecularProfileIds); - if (molecularProfileInternalIds.size() > 0) { - List geneticEntityIds = genericAssayMapper.getGeneticEntityIdsByMolecularProfileInternalIds(molecularProfileInternalIds); - if (geneticEntityIds.size() > 0) { - // return result - return genericAssayMapper.getGenericAssayStableIdsByGeneticEntityIds(geneticEntityIds); - } else { - LOG.error("Returned an Empty list. Cannot find accociate entity ids for molecular profiles: " + molecularProfileIds.toString()); - } - } else { - LOG.error("Returned an Empty list. Cannot find internal ids for molecular profiles: " + molecularProfileIds.toString()); - } - // log error and return empty list if something went wrong - return new ArrayList(); - } -} \ No newline at end of file diff --git a/src/main/java/org/cbioportal/persistence/mybatis/GenesetHierarchyMapper.java b/src/main/java/org/cbioportal/persistence/mybatis/GenesetHierarchyMapper.java deleted file mode 100644 index aa612490fe0..00000000000 --- a/src/main/java/org/cbioportal/persistence/mybatis/GenesetHierarchyMapper.java +++ /dev/null @@ -1,16 +0,0 @@ -package org.cbioportal.persistence.mybatis; - -import java.util.List; - -import org.apache.ibatis.annotations.Param; -import org.cbioportal.model.Geneset; -import org.cbioportal.model.GenesetHierarchyInfo; - -public interface GenesetHierarchyMapper { - - List getGenesetHierarchyParents(@Param("genesetIds") List genesetIds); - - List getGenesetHierarchyGenesets(Integer nodeId); - - List getGenesetHierarchySuperNodes(@Param("genesetIds") List genesetIds); -} diff --git a/src/main/java/org/cbioportal/persistence/mybatis/GenesetHierarchyMyBatisRepository.java b/src/main/java/org/cbioportal/persistence/mybatis/GenesetHierarchyMyBatisRepository.java deleted file mode 100644 index a5ab47711a7..00000000000 --- a/src/main/java/org/cbioportal/persistence/mybatis/GenesetHierarchyMyBatisRepository.java +++ /dev/null @@ -1,32 +0,0 @@ -package org.cbioportal.persistence.mybatis; - -import java.util.List; - -import org.cbioportal.model.Geneset; -import org.cbioportal.model.GenesetHierarchyInfo; -import org.cbioportal.persistence.GenesetHierarchyRepository; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Repository; - -@Repository -public class GenesetHierarchyMyBatisRepository implements GenesetHierarchyRepository { - - @Autowired - private GenesetHierarchyMapper genesetHierarchyMapper; - - @Override - public List getGenesetHierarchyParents(List genesetIds) { - - return genesetHierarchyMapper.getGenesetHierarchyParents(genesetIds); - } - @Override - public List getGenesetHierarchyGenesets(Integer nodeId) { - - return genesetHierarchyMapper.getGenesetHierarchyGenesets(nodeId); - } - @Override - public List getGenesetHierarchySuperNodes(List genesetIds) { - - return genesetHierarchyMapper.getGenesetHierarchySuperNodes(genesetIds); - } -} diff --git a/src/main/java/org/cbioportal/persistence/mybatis/GenesetMapper.java b/src/main/java/org/cbioportal/persistence/mybatis/GenesetMapper.java deleted file mode 100644 index b6484cb55ff..00000000000 --- a/src/main/java/org/cbioportal/persistence/mybatis/GenesetMapper.java +++ /dev/null @@ -1,33 +0,0 @@ -package org.cbioportal.persistence.mybatis; - -import java.util.List; - -import org.cbioportal.model.Gene; -import org.cbioportal.model.Geneset; -import org.cbioportal.model.meta.BaseMeta; - -public interface GenesetMapper { - - List getGenesets(String projection, - Integer limit, - Integer offset, - String sortBy, - String direction); - - BaseMeta getMetaGenesets(); - - Geneset getGenesetByInternalId(Integer internalId, - String projection); - - Geneset getGenesetByGenesetId(String genesetId, - String projection); - - Geneset getGenesetByGeneticEntityId(Integer geneticEntityId, - String projection); - - List fetchGenesets(List genesetIds); - - List getGenesByGenesetId(String genesetId, String projection); - - String getGenesetVersion(); -} diff --git a/src/main/java/org/cbioportal/persistence/mybatis/GenesetMyBatisRepository.java b/src/main/java/org/cbioportal/persistence/mybatis/GenesetMyBatisRepository.java deleted file mode 100644 index 0cba9bef284..00000000000 --- a/src/main/java/org/cbioportal/persistence/mybatis/GenesetMyBatisRepository.java +++ /dev/null @@ -1,55 +0,0 @@ -package org.cbioportal.persistence.mybatis; - -import java.util.List; - -import org.cbioportal.model.Gene; -import org.cbioportal.model.Geneset; -import org.cbioportal.model.meta.BaseMeta; -import org.cbioportal.persistence.GenesetRepository; -import org.cbioportal.persistence.PersistenceConstants; -import org.cbioportal.persistence.mybatis.util.PaginationCalculator; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Repository; - -@Repository -public class GenesetMyBatisRepository implements GenesetRepository { - - @Autowired - GenesetMapper genesetMapper; - - @Override - public List getAllGenesets(String projection, Integer pageSize, Integer pageNumber) { - - return genesetMapper.getGenesets(projection, pageSize, PaginationCalculator.offset(pageSize, pageNumber), "EXTERNAL_ID", "ASC"); - } - - @Override - public BaseMeta getMetaGenesets() { - - return genesetMapper.getMetaGenesets(); - } - - @Override - public Geneset getGeneset(String genesetId) { - - return genesetMapper.getGenesetByGenesetId(genesetId, PersistenceConstants.DETAILED_PROJECTION); - } - - @Override - public List fetchGenesets(List genesetIds) { - - return genesetMapper.fetchGenesets(genesetIds); - } - - @Override - public List getGenesByGenesetId(String genesetId) { - - return genesetMapper.getGenesByGenesetId(genesetId, PersistenceConstants.SUMMARY_PROJECTION); - } - - @Override - public String getGenesetVersion() { - - return genesetMapper.getGenesetVersion(); - } -} diff --git a/src/main/java/org/cbioportal/persistence/mybatis/MolecularDataMapper.java b/src/main/java/org/cbioportal/persistence/mybatis/MolecularDataMapper.java deleted file mode 100644 index 9191f75494c..00000000000 --- a/src/main/java/org/cbioportal/persistence/mybatis/MolecularDataMapper.java +++ /dev/null @@ -1,39 +0,0 @@ -package org.cbioportal.persistence.mybatis; - - -import org.cbioportal.model.GeneMolecularAlteration; -import org.cbioportal.model.GenericAssayMolecularAlteration; -import org.cbioportal.model.GenesetMolecularAlteration; -import org.cbioportal.model.MolecularProfileSamples; - -import java.util.List; -import java.util.Set; - -import org.apache.ibatis.cursor.Cursor; - -public interface MolecularDataMapper { - - List getCommaSeparatedSampleIdsOfMolecularProfiles(Set molecularProfileIds); - - List getGeneMolecularAlterations(String molecularProfileId, List entrezGeneIds, - String projection); - - Cursor getGeneMolecularAlterationsIter(String molecularProfileId, List entrezGeneIds, - String projection); - - // Same as getGeneMolecularAlterationsIter above, except assumes that - // entrezGeneIds is null or empty AND projection is "SUMMARY" - Cursor getGeneMolecularAlterationsIterFast(String molecularProfileId); - - List getGeneMolecularAlterationsInMultipleMolecularProfiles(Set molecularProfileIds, - List entrezGeneIds, String projection); - - List getGenesetMolecularAlterations(String molecularProfileId, List genesetIds, - String projection); - - List getGenericAssayMolecularAlterations(String molecularProfileId, List stableIds, - String projection); - - Cursor getGenericAssayMolecularAlterationsIter(String molecularProfileId, - List stableIds, String projection); -} diff --git a/src/main/java/org/cbioportal/persistence/mybatis/MolecularDataMyBatisRepository.java b/src/main/java/org/cbioportal/persistence/mybatis/MolecularDataMyBatisRepository.java deleted file mode 100644 index b724350c86f..00000000000 --- a/src/main/java/org/cbioportal/persistence/mybatis/MolecularDataMyBatisRepository.java +++ /dev/null @@ -1,85 +0,0 @@ -package org.cbioportal.persistence.mybatis; - -import org.cbioportal.model.*; -import org.cbioportal.persistence.MolecularDataRepository; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Repository; - -import java.util.*; -import java.util.function.Function; -import java.util.stream.Collectors; - -@Repository -public class MolecularDataMyBatisRepository implements MolecularDataRepository { - - @Autowired - private MolecularDataMapper molecularDataMapper; - - @Override - public MolecularProfileSamples getCommaSeparatedSampleIdsOfMolecularProfile(String molecularProfileId) { - try { - return molecularDataMapper.getCommaSeparatedSampleIdsOfMolecularProfiles( - Collections.singleton(molecularProfileId)).get(0); - } catch (IndexOutOfBoundsException e) { - return null; - } - } - - @Override - public Map commaSeparatedSampleIdsOfMolecularProfilesMap(Set molecularProfileIds) { - - return molecularDataMapper.getCommaSeparatedSampleIdsOfMolecularProfiles(molecularProfileIds) - .stream() - .collect(Collectors.toMap(MolecularProfileSamples::getMolecularProfileId, Function.identity())); - } - - @Override - public List getGeneMolecularAlterations(String molecularProfileId, - List entrezGeneIds, String projection) { - - return molecularDataMapper.getGeneMolecularAlterations(molecularProfileId, entrezGeneIds, projection); - } - - @Override - // In order to return a cursor/iterator to the service layer, we need a transaction setup in the service - // layer. Currently, the bottom stackframe is CoExpressionService:getCoExpressions. It is there where - // you will find the transaction created. - public Iterable getGeneMolecularAlterationsIterable(String molecularProfileId, - List entrezGeneIds, String projection) { - - return molecularDataMapper.getGeneMolecularAlterationsIter(molecularProfileId, entrezGeneIds, projection); - } - - @Override - public Iterable getGeneMolecularAlterationsIterableFast(String molecularProfileId) { - - return molecularDataMapper.getGeneMolecularAlterationsIterFast(molecularProfileId); - } - - @Override - public List getGeneMolecularAlterationsInMultipleMolecularProfiles(Set molecularProfileIds, - List entrezGeneIds, - String projection) { - - return molecularDataMapper.getGeneMolecularAlterationsInMultipleMolecularProfiles(molecularProfileIds, entrezGeneIds, - projection); - } - - @Override - public List getGenesetMolecularAlterations(String molecularProfileId, - List genesetIds, String projection) { - - return molecularDataMapper.getGenesetMolecularAlterations(molecularProfileId, genesetIds, projection); - } - - @Override - public List getGenericAssayMolecularAlterations(String molecularProfileId, List stableIds, String projection) { - return molecularDataMapper.getGenericAssayMolecularAlterations(molecularProfileId, stableIds, projection); - } - - @Override - public Iterable getGenericAssayMolecularAlterationsIterable( - String molecularProfileId, List stableIds, String projection) { - return molecularDataMapper.getGenericAssayMolecularAlterationsIter(molecularProfileId, stableIds, projection); - } -} diff --git a/src/main/java/org/cbioportal/persistence/mybatis/MolecularProfileMapper.java b/src/main/java/org/cbioportal/persistence/mybatis/MolecularProfileMapper.java deleted file mode 100644 index 64bf0a5936d..00000000000 --- a/src/main/java/org/cbioportal/persistence/mybatis/MolecularProfileMapper.java +++ /dev/null @@ -1,25 +0,0 @@ -package org.cbioportal.persistence.mybatis; - -import org.cbioportal.model.MolecularProfile; -import org.cbioportal.model.meta.BaseMeta; - -import java.util.List; -import java.util.Set; - -public interface MolecularProfileMapper { - - List getAllMolecularProfilesInStudies(List studyIds, String projection, Integer limit, Integer offset, - String sortBy, String direction); - - BaseMeta getMetaMolecularProfilesInStudies(List studyIds); - - MolecularProfile getMolecularProfile(String molecularProfileId, String projection); - - List getMolecularProfiles(Set molecularProfileIds, String projection); - - BaseMeta getMetaMolecularProfiles(Set molecularProfileIds); - - List getMolecularProfilesReferredBy(String referringMolecularProfileId, String projection); - - List getMolecularProfilesReferringTo(String referredMolecularProfileId, String projection); -} diff --git a/src/main/java/org/cbioportal/persistence/mybatis/MolecularProfileMyBatisRepository.java b/src/main/java/org/cbioportal/persistence/mybatis/MolecularProfileMyBatisRepository.java deleted file mode 100644 index bf0e656f401..00000000000 --- a/src/main/java/org/cbioportal/persistence/mybatis/MolecularProfileMyBatisRepository.java +++ /dev/null @@ -1,90 +0,0 @@ -package org.cbioportal.persistence.mybatis; - -import org.cbioportal.model.MolecularProfile; -import org.cbioportal.model.meta.BaseMeta; -import org.cbioportal.persistence.MolecularProfileRepository; -import org.cbioportal.persistence.PersistenceConstants; -import org.cbioportal.persistence.mybatis.util.PaginationCalculator; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Repository; -import java.util.Arrays; -import java.util.List; -import java.util.Set; - -@Repository -public class MolecularProfileMyBatisRepository implements MolecularProfileRepository { - - @Autowired - private MolecularProfileMapper molecularProfileMapper; - - @Override - public List getAllMolecularProfiles(String projection, Integer pageSize, Integer pageNumber, - String sortBy, String direction) { - - return molecularProfileMapper.getAllMolecularProfilesInStudies(null, projection, pageSize, - PaginationCalculator.offset(pageSize, pageNumber), sortBy, direction); - } - - @Override - public BaseMeta getMetaMolecularProfiles() { - - return molecularProfileMapper.getMetaMolecularProfilesInStudies(null); - } - - @Override - public MolecularProfile getMolecularProfile(String molecularProfileId) { - return molecularProfileMapper.getMolecularProfile(molecularProfileId, PersistenceConstants.DETAILED_PROJECTION); - } - - @Override - public List getMolecularProfiles(Set molecularProfileIds, String projection) { - - return molecularProfileMapper.getMolecularProfiles(molecularProfileIds, projection); - } - - @Override - public BaseMeta getMetaMolecularProfiles(Set molecularProfileIds) { - - return molecularProfileMapper.getMetaMolecularProfiles(molecularProfileIds); - } - - @Override - public List getAllMolecularProfilesInStudy(String studyId, String projection, Integer pageSize, - Integer pageNumber, String sortBy, String direction) { - - return molecularProfileMapper.getAllMolecularProfilesInStudies(Arrays.asList(studyId), projection, pageSize, - PaginationCalculator.offset(pageSize, pageNumber), sortBy, direction); - } - - @Override - public BaseMeta getMetaMolecularProfilesInStudy(String studyId) { - - return molecularProfileMapper.getMetaMolecularProfilesInStudies(Arrays.asList(studyId)); - } - - @Override - public List getMolecularProfilesInStudies(List studyIds, String projection) { - - return molecularProfileMapper.getAllMolecularProfilesInStudies(studyIds, projection, 0, 0, null, null); - } - - @Override - public BaseMeta getMetaMolecularProfilesInStudies(List studyIds) { - - return molecularProfileMapper.getMetaMolecularProfilesInStudies(studyIds); - } - - @Override - public List getMolecularProfilesReferredBy(String referringMolecularProfileId) { - - return molecularProfileMapper.getMolecularProfilesReferredBy(referringMolecularProfileId, - PersistenceConstants.DETAILED_PROJECTION); - } - - @Override - public List getMolecularProfilesReferringTo(String referredMolecularProfileId) { - - return molecularProfileMapper.getMolecularProfilesReferringTo(referredMolecularProfileId, - PersistenceConstants.DETAILED_PROJECTION); - } -} diff --git a/src/main/java/org/cbioportal/persistence/mybatis/MutationMapper.java b/src/main/java/org/cbioportal/persistence/mybatis/MutationMapper.java deleted file mode 100644 index 26a26ddfad9..00000000000 --- a/src/main/java/org/cbioportal/persistence/mybatis/MutationMapper.java +++ /dev/null @@ -1,47 +0,0 @@ -package org.cbioportal.persistence.mybatis; - -import org.cbioportal.model.GeneFilterQuery; -import org.cbioportal.model.GenomicDataCountItem; -import org.cbioportal.model.Mutation; -import org.cbioportal.model.MutationCountByPosition; -import org.cbioportal.model.meta.MutationMeta; - -import java.util.List; - -public interface MutationMapper { - - List getMutationsBySampleListId(String molecularProfileId, String sampleListId, List entrezGeneIds, - boolean snpOnly, String projection, Integer limit, Integer offset, - String sortBy, String direction); - - MutationMeta getMetaMutationsBySampleListId(String molecularProfileId, String sampleListId, - List entrezGeneIds, boolean snpOnly); - - - List getMutationsInMultipleMolecularProfiles(List molecularProfileIds, List sampleIds, - List entrezGeneIds, boolean snpOnly, - String projection, Integer limit, - Integer offset, String sortBy, String direction); - - List getMutationsInMultipleMolecularProfilesByGeneQueries(List molecularProfileIds, - List sampleIds, - boolean snpOnly, - String projection, - Integer limit, - Integer offset, - String sortBy, - String direction, - List geneQueries); - - MutationMeta getMetaMutationsInMultipleMolecularProfiles(List molecularProfileIds, List sampleIds, - List entrezGeneIds, boolean snpOnly); - - MutationMeta getMetaMutationsBySampleIds(String molecularProfileId, List sampleIds, - List entrezGeneIds, boolean snpOnly); - - MutationCountByPosition getMutationCountByPosition(Integer entrezGeneId, Integer proteinPosStart, - Integer proteinPosEnd); - - GenomicDataCountItem getMutationCountsByType(List molecularProfileIds, List sampleIds, - List entrezGeneIds, boolean snpOnly, String profileType); -} diff --git a/src/main/java/org/cbioportal/persistence/mybatis/MutationMyBatisRepository.java b/src/main/java/org/cbioportal/persistence/mybatis/MutationMyBatisRepository.java deleted file mode 100644 index d5e5ae0d3f6..00000000000 --- a/src/main/java/org/cbioportal/persistence/mybatis/MutationMyBatisRepository.java +++ /dev/null @@ -1,142 +0,0 @@ -package org.cbioportal.persistence.mybatis; - -import org.cbioportal.model.GeneFilterQuery; -import org.cbioportal.model.GenomicDataCountItem; -import org.cbioportal.model.Mutation; -import org.cbioportal.model.MutationCountByPosition; -import org.cbioportal.model.meta.MutationMeta; -import org.cbioportal.persistence.MutationRepository; -import org.cbioportal.persistence.mybatis.util.MolecularProfileCaseIdentifierUtil; -import org.cbioportal.persistence.mybatis.util.PaginationCalculator; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Repository; - -import java.util.*; -import java.util.stream.Collectors; - -@Repository -public class MutationMyBatisRepository implements MutationRepository { - - @Autowired - private MutationMapper mutationMapper; - @Autowired - private MolecularProfileCaseIdentifierUtil molecularProfileCaseIdentifierUtil; - - @Override - public List getMutationsInMolecularProfileBySampleListId(String molecularProfileId, String sampleListId, - List entrezGeneIds, boolean snpOnly, - String projection, Integer pageSize, - Integer pageNumber, String sortBy, - String direction) { - - return mutationMapper.getMutationsBySampleListId(molecularProfileId, sampleListId, entrezGeneIds, snpOnly, - projection, pageSize, PaginationCalculator.offset(pageSize, pageNumber), sortBy, direction); - } - - @Override - public MutationMeta getMetaMutationsInMolecularProfileBySampleListId(String molecularProfileId, String sampleListId, - List entrezGeneIds) { - - return mutationMapper.getMetaMutationsBySampleListId(molecularProfileId, sampleListId, entrezGeneIds, false); - } - - @Override - public List getMutationsInMultipleMolecularProfiles(List molecularProfileIds, - List sampleIds, List entrezGeneIds, - String projection, Integer pageSize, - Integer pageNumber, String sortBy, String direction) { - - return molecularProfileCaseIdentifierUtil - .getGroupedCasesByMolecularProfileId(molecularProfileIds, sampleIds) - .entrySet() - .stream() - .flatMap(entry -> mutationMapper.getMutationsInMultipleMolecularProfiles( - Arrays.asList(entry.getKey()), - new ArrayList<>(entry.getValue()), - entrezGeneIds, - false, - projection, - pageSize, - PaginationCalculator.offset(pageSize, pageNumber), - sortBy, - direction).stream()) - .collect(Collectors.toList()); - } - - @Override - public List getMutationsInMultipleMolecularProfilesByGeneQueries(List molecularProfileIds, - List sampleIds, - List geneQueries, - String projection, - Integer pageSize, - Integer pageNumber, - String sortBy, - String direction) { - if (geneQueries.isEmpty()) - return Collections.emptyList(); - - return molecularProfileCaseIdentifierUtil - .getGroupedCasesByMolecularProfileId(molecularProfileIds, sampleIds) - .entrySet() - .stream() - .flatMap(entry -> mutationMapper.getMutationsInMultipleMolecularProfilesByGeneQueries( - Arrays.asList(entry.getKey()), - new ArrayList<>(entry.getValue()), - false, - projection, - pageSize, - PaginationCalculator.offset(pageSize, pageNumber), - sortBy, - direction, - geneQueries).stream()) - .collect(Collectors.toList()); - } - - @Override - public MutationMeta getMetaMutationsInMultipleMolecularProfiles(List molecularProfileIds, - List sampleIds, - List entrezGeneIds) { - - return mutationMapper.getMetaMutationsInMultipleMolecularProfiles(molecularProfileIds, sampleIds, entrezGeneIds, - false); - } - - @Override - public List fetchMutationsInMolecularProfile(String molecularProfileId, List sampleIds, - List entrezGeneIds, boolean snpOnly, - String projection, Integer pageSize, Integer pageNumber, - String sortBy, String direction) { - - return mutationMapper.getMutationsInMultipleMolecularProfiles( - Arrays.asList(molecularProfileId), - new ArrayList<>(sampleIds), - entrezGeneIds, - snpOnly, - projection, - pageSize, - PaginationCalculator.offset(pageSize, pageNumber), - sortBy, - direction); - } - - @Override - public MutationMeta fetchMetaMutationsInMolecularProfile(String molecularProfileId, List sampleIds, - List entrezGeneIds) { - - return mutationMapper.getMetaMutationsBySampleIds(molecularProfileId, sampleIds, entrezGeneIds, false); - } - - @Override - public MutationCountByPosition getMutationCountByPosition(Integer entrezGeneId, Integer proteinPosStart, - Integer proteinPosEnd) { - - return mutationMapper.getMutationCountByPosition(entrezGeneId, proteinPosStart, proteinPosEnd); - } - - @Override - public GenomicDataCountItem getMutationCountsByType(List molecularProfileIds, List sampleIds, - List entrezGeneIds, String profileType) { - return mutationMapper.getMutationCountsByType(molecularProfileIds, sampleIds, entrezGeneIds, - false, profileType); - } -} diff --git a/src/main/java/org/cbioportal/persistence/mybatis/PatientMapper.java b/src/main/java/org/cbioportal/persistence/mybatis/PatientMapper.java deleted file mode 100644 index 70864aa54ec..00000000000 --- a/src/main/java/org/cbioportal/persistence/mybatis/PatientMapper.java +++ /dev/null @@ -1,18 +0,0 @@ -package org.cbioportal.persistence.mybatis; - -import org.cbioportal.model.Patient; -import org.cbioportal.model.meta.BaseMeta; - -import java.util.List; - -public interface PatientMapper { - - List getPatients(List studyIds, List patientIds, String keyword, String projection, - Integer limit, Integer offset, String sortBy, String direction); - - BaseMeta getMetaPatients(List studyIds, List patientIds, String keyword); - - Patient getPatient(String studyId, String patientId, String projection); - - List getPatientsOfSamples(List studyIds, List sampleIds); -} diff --git a/src/main/java/org/cbioportal/persistence/mybatis/PatientMyBatisRepository.java b/src/main/java/org/cbioportal/persistence/mybatis/PatientMyBatisRepository.java deleted file mode 100644 index af4f1593030..00000000000 --- a/src/main/java/org/cbioportal/persistence/mybatis/PatientMyBatisRepository.java +++ /dev/null @@ -1,70 +0,0 @@ -package org.cbioportal.persistence.mybatis; - -import org.cbioportal.model.Patient; -import org.cbioportal.model.meta.BaseMeta; -import org.cbioportal.persistence.PatientRepository; -import org.cbioportal.persistence.PersistenceConstants; -import org.cbioportal.persistence.mybatis.util.PaginationCalculator; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Repository; - -import java.util.Arrays; -import java.util.List; - -@Repository -public class PatientMyBatisRepository implements PatientRepository { - - @Autowired - private PatientMapper patientMapper; - - @Override - public List getAllPatients(String keyword, String projection, Integer pageSize, Integer pageNumber, - String sortBy, String direction) { - return patientMapper.getPatients(null, null, keyword, projection, pageSize, - PaginationCalculator.offset(pageSize, pageNumber), sortBy, direction); - } - - @Override - public BaseMeta getMetaPatients(String keyword) { - - return patientMapper.getMetaPatients(null, null, keyword); - } - - @Override - public List getAllPatientsInStudy(String studyId, String projection, Integer pageSize, Integer pageNumber, - String sortBy, String direction) { - - return patientMapper.getPatients(Arrays.asList(studyId), null, null, projection, pageSize, - PaginationCalculator.offset(pageSize, pageNumber), sortBy, direction); - } - - @Override - public BaseMeta getMetaPatientsInStudy(String studyId) { - - return patientMapper.getMetaPatients(Arrays.asList(studyId), null, null); - } - - @Override - public Patient getPatientInStudy(String studyId, String patientId) { - - return patientMapper.getPatient(studyId, patientId, PersistenceConstants.DETAILED_PROJECTION); - } - - @Override - public List fetchPatients(List studyIds, List patientIds, String projection) { - - return patientMapper.getPatients(studyIds, patientIds, null, projection, 0, 0, null, null); - } - - @Override - public BaseMeta fetchMetaPatients(List studyIds, List patientIds) { - - return patientMapper.getMetaPatients(studyIds, patientIds, null); - } - - @Override - public List getPatientsOfSamples(List studyIds, List sampleIds) { - - return patientMapper.getPatientsOfSamples(studyIds, sampleIds); - } -} diff --git a/src/main/java/org/cbioportal/persistence/mybatis/ReferenceGenomeGeneMapper.java b/src/main/java/org/cbioportal/persistence/mybatis/ReferenceGenomeGeneMapper.java deleted file mode 100644 index 39e7bdb5d50..00000000000 --- a/src/main/java/org/cbioportal/persistence/mybatis/ReferenceGenomeGeneMapper.java +++ /dev/null @@ -1,13 +0,0 @@ -package org.cbioportal.persistence.mybatis; - -import org.cbioportal.model.ReferenceGenomeGene; -import java.util.List; - -public interface ReferenceGenomeGeneMapper { - List getAllGenesByGenomeName(String genomeName, String projection); - List getGenesByHugoGeneSymbolsAndGenomeName(List geneIds, String genomeName, String projection); - List getGenesByGenomeName(List geneIds, String genomeName, String projection); - ReferenceGenomeGene getReferenceGenomeGene(Integer geneId, String genomeName, String projection); - ReferenceGenomeGene getReferenceGenomeGeneByEntityId(Integer geneticEntityId, String genomeName, String projection); -} - diff --git a/src/main/java/org/cbioportal/persistence/mybatis/ReferenceGenomeGeneMyBatisRepository.java b/src/main/java/org/cbioportal/persistence/mybatis/ReferenceGenomeGeneMyBatisRepository.java deleted file mode 100644 index dc4091a2ec7..00000000000 --- a/src/main/java/org/cbioportal/persistence/mybatis/ReferenceGenomeGeneMyBatisRepository.java +++ /dev/null @@ -1,46 +0,0 @@ -package org.cbioportal.persistence.mybatis; - -import java.util.List; - -import org.cbioportal.model.ReferenceGenomeGene; -import org.cbioportal.persistence.ReferenceGenomeGeneRepository; -import org.cbioportal.persistence.PersistenceConstants; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Repository; - -@Repository -public class ReferenceGenomeGeneMyBatisRepository implements ReferenceGenomeGeneRepository { - - @Autowired - private ReferenceGenomeGeneMapper referenceGenomeGeneMapper; - - @Override - public List getAllGenesByGenomeName(String genomeName) { - - return referenceGenomeGeneMapper.getAllGenesByGenomeName(genomeName, PersistenceConstants.SUMMARY_PROJECTION); - } - - @Override - public List getGenesByHugoGeneSymbolsAndGenomeName(List geneIds, String genomeName) { - - return referenceGenomeGeneMapper.getGenesByHugoGeneSymbolsAndGenomeName(geneIds, genomeName, PersistenceConstants.SUMMARY_PROJECTION); - } - - @Override - public List getGenesByGenomeName(List geneIds, String genomeName) { - - return referenceGenomeGeneMapper.getGenesByGenomeName(geneIds, genomeName, PersistenceConstants.SUMMARY_PROJECTION); - } - - @Override - public ReferenceGenomeGene getReferenceGenomeGene(Integer geneId, String genomeName) { - - return referenceGenomeGeneMapper.getReferenceGenomeGene(geneId, genomeName, PersistenceConstants.SUMMARY_PROJECTION); - } - - @Override - public ReferenceGenomeGene getReferenceGenomeGeneByEntityId(Integer geneticEntityId, String genomeName) { - return referenceGenomeGeneMapper.getReferenceGenomeGeneByEntityId(geneticEntityId, genomeName, - PersistenceConstants.SUMMARY_PROJECTION); - } -} diff --git a/src/main/java/org/cbioportal/persistence/mybatis/ResourceDataMapper.java b/src/main/java/org/cbioportal/persistence/mybatis/ResourceDataMapper.java deleted file mode 100644 index ec3ea25ab9d..00000000000 --- a/src/main/java/org/cbioportal/persistence/mybatis/ResourceDataMapper.java +++ /dev/null @@ -1,24 +0,0 @@ -package org.cbioportal.persistence.mybatis; - -import java.util.List; - -import org.cbioportal.model.ResourceData; - -public interface ResourceDataMapper { - - List getResourceDataOfSampleInStudy(String studyId, String sampleId, String resourceId, - String projection, Integer limit, Integer offset, String sortBy, String direction); - - List getResourceDataOfPatientInStudy(String studyId, String patientId, String resourceId, - String projection, Integer limit, Integer offset, String sortBy, String direction); - - List getResourceDataForStudy(String studyId, String resourceId, String projection, Integer limit, - Integer offset, String sortBy, String direction); - - List getResourceDataForAllPatientsInStudy(String studyId, String resourceId, String projection, Integer limit, - Integer offset, String sortBy, String direction); - - List getResourceDataForAllSamplesInStudy(String studyId, String resourceId, String projection, Integer limit, - Integer offset, String sortBy, String direction); - -} diff --git a/src/main/java/org/cbioportal/persistence/mybatis/ResourceDataMyBatisRepository.java b/src/main/java/org/cbioportal/persistence/mybatis/ResourceDataMyBatisRepository.java deleted file mode 100644 index 79a66956f5c..00000000000 --- a/src/main/java/org/cbioportal/persistence/mybatis/ResourceDataMyBatisRepository.java +++ /dev/null @@ -1,57 +0,0 @@ -package org.cbioportal.persistence.mybatis; - -import java.util.List; - -import org.cbioportal.model.ResourceData; -import org.cbioportal.persistence.ResourceDataRepository; -import org.cbioportal.persistence.mybatis.util.PaginationCalculator; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Repository; - -@Repository -public class ResourceDataMyBatisRepository implements ResourceDataRepository { - - @Autowired - private ResourceDataMapper resourceDataMapper; - - @Override - public List getAllResourceDataOfSampleInStudy(String studyId, String sampleId, String resourceId, - String projection, Integer pageSize, Integer pageNumber, String sortBy, String direction) { - - return resourceDataMapper.getResourceDataOfSampleInStudy(studyId, sampleId, resourceId, projection, pageSize, - PaginationCalculator.offset(pageSize, pageNumber), sortBy, direction); - } - - @Override - public List getAllResourceDataOfPatientInStudy(String studyId, String patientId, String resourceId, - String projection, Integer pageSize, Integer pageNumber, String sortBy, String direction) { - - return resourceDataMapper.getResourceDataOfPatientInStudy(studyId, patientId, resourceId, projection, pageSize, - PaginationCalculator.offset(pageSize, pageNumber), sortBy, direction); - } - - @Override - public List getAllResourceDataForStudy(String studyId, String resourceId, String projection, - Integer pageSize, Integer pageNumber, String sortBy, String direction) { - - return resourceDataMapper.getResourceDataForStudy(studyId, resourceId, projection, pageSize, - PaginationCalculator.offset(pageSize, pageNumber), sortBy, direction); - } - - @Override - public List getResourceDataForAllPatientsInStudy(String studyId, String resourceId, String projection, - Integer pageSize, Integer pageNumber, String sortBy, String direction) { - - return resourceDataMapper.getResourceDataForAllPatientsInStudy(studyId, resourceId, projection, pageSize, - PaginationCalculator.offset(pageSize, pageNumber), sortBy, direction); - } - - @Override - public List getResourceDataForAllSamplesInStudy(String studyId, String resourceId, String projection, - Integer pageSize, Integer pageNumber, String sortBy, String direction) { - - return resourceDataMapper.getResourceDataForAllSamplesInStudy(studyId, resourceId, projection, pageSize, - PaginationCalculator.offset(pageSize, pageNumber), sortBy, direction); - } - -} diff --git a/src/main/java/org/cbioportal/persistence/mybatis/ResourceDefinitionMapper.java b/src/main/java/org/cbioportal/persistence/mybatis/ResourceDefinitionMapper.java deleted file mode 100644 index e15c5218bb0..00000000000 --- a/src/main/java/org/cbioportal/persistence/mybatis/ResourceDefinitionMapper.java +++ /dev/null @@ -1,14 +0,0 @@ -package org.cbioportal.persistence.mybatis; - -import java.util.List; - -import org.cbioportal.model.ResourceDefinition; - -public interface ResourceDefinitionMapper { - - ResourceDefinition getResourceDefinition(String studyId, String resourceId, String projection); - - List getResourceDefinitions(List studyIds, String projection, Integer limit, Integer offset, - String sortBy, String direction); - -} diff --git a/src/main/java/org/cbioportal/persistence/mybatis/ResourceDefinitionMyBatisRepository.java b/src/main/java/org/cbioportal/persistence/mybatis/ResourceDefinitionMyBatisRepository.java deleted file mode 100644 index 4a07420fb73..00000000000 --- a/src/main/java/org/cbioportal/persistence/mybatis/ResourceDefinitionMyBatisRepository.java +++ /dev/null @@ -1,29 +0,0 @@ -package org.cbioportal.persistence.mybatis; - -import java.util.List; - -import org.cbioportal.model.ResourceDefinition; -import org.cbioportal.persistence.PersistenceConstants; -import org.cbioportal.persistence.ResourceDefinitionRepository; -import org.cbioportal.persistence.mybatis.util.PaginationCalculator; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Repository; - -@Repository -public class ResourceDefinitionMyBatisRepository implements ResourceDefinitionRepository { - - @Autowired - private ResourceDefinitionMapper resourceDefinitionMapper; - - @Override - public ResourceDefinition getResourceDefinition(String studyId, String resourceId) { - return resourceDefinitionMapper.getResourceDefinition(studyId, resourceId, - PersistenceConstants.DETAILED_PROJECTION); - } - - @Override - public List fetchResourceDefinitions(List studyIds, String projection, Integer pageSize, Integer pageNumber, String sortBy, String direction) { - return resourceDefinitionMapper.getResourceDefinitions(studyIds, projection, pageSize, - PaginationCalculator.offset(pageSize, pageNumber), sortBy, direction); - } -} diff --git a/src/main/java/org/cbioportal/persistence/mybatis/SampleListMapper.java b/src/main/java/org/cbioportal/persistence/mybatis/SampleListMapper.java deleted file mode 100644 index af777db0597..00000000000 --- a/src/main/java/org/cbioportal/persistence/mybatis/SampleListMapper.java +++ /dev/null @@ -1,23 +0,0 @@ -package org.cbioportal.persistence.mybatis; - -import org.cbioportal.model.SampleList; -import org.cbioportal.model.SampleListToSampleId; -import org.cbioportal.model.meta.BaseMeta; - -import java.util.List; - -public interface SampleListMapper { - - List getAllSampleLists(List studyIds, String projection, Integer limit, Integer offset, String sortBy, - String direction); - - BaseMeta getMetaSampleLists(String studyId); - - SampleList getSampleList(String sampleListId, String projection); - - List getSampleLists(List sampleListIds, String projection); - - List getAllSampleIdsInSampleList(String sampleListId); - - List getSampleListSampleIds(List sampleListIds); -} diff --git a/src/main/java/org/cbioportal/persistence/mybatis/SampleListMyBatisRepository.java b/src/main/java/org/cbioportal/persistence/mybatis/SampleListMyBatisRepository.java deleted file mode 100644 index f7141eef555..00000000000 --- a/src/main/java/org/cbioportal/persistence/mybatis/SampleListMyBatisRepository.java +++ /dev/null @@ -1,74 +0,0 @@ -package org.cbioportal.persistence.mybatis; - -import org.cbioportal.model.SampleList; -import org.cbioportal.model.SampleListToSampleId; -import org.cbioportal.model.meta.BaseMeta; -import org.springframework.cache.annotation.Cacheable; - -import org.cbioportal.persistence.PersistenceConstants; -import org.cbioportal.persistence.SampleListRepository; -import org.cbioportal.persistence.mybatis.util.PaginationCalculator; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Repository; - -import java.util.List; - -@Repository -public class SampleListMyBatisRepository implements SampleListRepository { - - @Autowired - private SampleListMapper sampleListMapper; - - @Override - public List getAllSampleLists(String projection, Integer pageSize, Integer pageNumber, String sortBy, - String direction) { - - return sampleListMapper.getAllSampleLists(null, projection, pageSize, - PaginationCalculator.offset(pageSize, pageNumber), sortBy, direction); - } - - @Override - public BaseMeta getMetaSampleLists() { - - return sampleListMapper.getMetaSampleLists(null); - } - - @Override - public SampleList getSampleList(String sampleListId) { - - return sampleListMapper.getSampleList(sampleListId, PersistenceConstants.DETAILED_PROJECTION); - } - - @Override - public List getSampleLists(List sampleListIds, String projection) { - - return sampleListMapper.getSampleLists(sampleListIds, projection); - } - - @Override - public List getAllSampleListsInStudies(List studyIds, String projection, Integer pageSize, - Integer pageNumber, String sortBy, String direction) { - - return sampleListMapper.getAllSampleLists(studyIds, projection, pageSize, - PaginationCalculator.offset(pageSize, pageNumber), sortBy, direction); - } - - @Override - public BaseMeta getMetaSampleListsInStudy(String studyId) { - - return sampleListMapper.getMetaSampleLists(studyId); - } - - @Override - public List getAllSampleIdsInSampleList(String sampleListId) { - - return sampleListMapper.getAllSampleIdsInSampleList(sampleListId); - } - - @Override - @Cacheable(cacheResolver = "staticRepositoryCacheOneResolver", condition = "@cacheEnabledConfig.getEnabled()") - public List getSampleListSampleIds(List sampleListIds) { - - return sampleListMapper.getSampleListSampleIds(sampleListIds); - } -} diff --git a/src/main/java/org/cbioportal/persistence/mybatis/SampleMapper.java b/src/main/java/org/cbioportal/persistence/mybatis/SampleMapper.java deleted file mode 100644 index 8d77020b1fc..00000000000 --- a/src/main/java/org/cbioportal/persistence/mybatis/SampleMapper.java +++ /dev/null @@ -1,26 +0,0 @@ -package org.cbioportal.persistence.mybatis; - -import org.cbioportal.model.Sample; -import org.cbioportal.model.meta.BaseMeta; - -import java.util.List; - -public interface SampleMapper { - - List getSamples(List studyIds, String patientId, List sampleIds, String keyword, - String projection, Integer limit, Integer offset, String sortBy, String direction); - - List getSamplesBySampleListIds(List sampleListIds, String projection); - - BaseMeta getMetaSamples(List studyIds, String patientId, List sampleIds, String keyword); - - BaseMeta getMetaSamplesBySampleListIds(List sampleListIds); - - Sample getSample(String studyId, String sampleId, String projection); - - List getSamplesByInternalIds(List internalIds, String projection); - - List getSamplesOfPatients(String studyId, List patientIds, String projection); - - List getSamplesOfPatientsInMultipleStudies(List studyIds, List patientIds, String projection); -} diff --git a/src/main/java/org/cbioportal/persistence/mybatis/SampleMyBatisRepository.java b/src/main/java/org/cbioportal/persistence/mybatis/SampleMyBatisRepository.java deleted file mode 100644 index 0fc72b39234..00000000000 --- a/src/main/java/org/cbioportal/persistence/mybatis/SampleMyBatisRepository.java +++ /dev/null @@ -1,133 +0,0 @@ -package org.cbioportal.persistence.mybatis; - -import org.cbioportal.model.Sample; -import org.cbioportal.model.meta.BaseMeta; -import org.cbioportal.persistence.SampleRepository; -import org.cbioportal.persistence.PersistenceConstants; -import org.cbioportal.persistence.mybatis.util.PaginationCalculator; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Repository; - -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.stream.Collectors; - -@Repository -public class SampleMyBatisRepository implements SampleRepository { - - @Autowired - private SampleMapper sampleMapper; - - @Override - public List getAllSamples( - String keyword, List studyIds, String projection, - Integer pageSize, Integer pageNumber, String sort, String direction - ) { - return sampleMapper.getSamples( - studyIds, null, null, keyword, projection, pageSize, - PaginationCalculator.offset(pageSize, pageNumber), sort, direction); - } - - @Override - public BaseMeta getMetaSamples(String keyword, List studyIds) { - return sampleMapper.getMetaSamples(studyIds, null, null, keyword); - } - - @Override - public List getAllSamplesInStudy(String studyId, String projection, Integer pageSize, Integer pageNumber, - String sortBy, String direction) { - - return sampleMapper.getSamples(Arrays.asList(studyId), null, null, null, projection, pageSize, - PaginationCalculator.offset(pageSize, pageNumber), sortBy, direction); - } - - @Override - public BaseMeta getMetaSamplesInStudy(String studyId) { - - return sampleMapper.getMetaSamples(Arrays.asList(studyId), null, null, null); - } - - @Override - public List getAllSamplesInStudies(List studyIds, String projection, Integer pageSize, - Integer pageNumber, String sortBy, String direction) { - return sampleMapper.getSamples(studyIds, null, null, null, projection, pageSize, - PaginationCalculator.offset(pageSize, pageNumber), sortBy, direction); - } - - @Override - public Sample getSampleInStudy(String studyId, String sampleId) { - - return sampleMapper.getSample(studyId, sampleId, PersistenceConstants.DETAILED_PROJECTION); - } - - @Override - public List getAllSamplesOfPatientInStudy(String studyId, String patientId, String projection, - Integer pageSize, Integer pageNumber, String sortBy, - String direction) { - - return sampleMapper.getSamples(Arrays.asList(studyId), patientId, null, null, projection, - pageSize, PaginationCalculator.offset(pageSize, pageNumber), sortBy, direction); - } - - @Override - public BaseMeta getMetaSamplesOfPatientInStudy(String studyId, String patientId) { - - return sampleMapper.getMetaSamples(Arrays.asList(studyId), patientId, null, null); - } - - @Override - public List getAllSamplesOfPatientsInStudy(String studyId, List patientIds, String projection) { - - return sampleMapper.getSamplesOfPatients(studyId, patientIds, projection); - } - - @Override - public List getSamplesOfPatientsInMultipleStudies(List studyIds, List patientIds, - String projection) { - - return sampleMapper.getSamplesOfPatientsInMultipleStudies(studyIds, patientIds, projection); - } - - @Override - public List fetchSamples(List studyIds, List sampleIds, String projection) { - - return sampleMapper.getSamples(studyIds, null, sampleIds, null, - projection, 0, 0, null, null); - } - - @Override - public List fetchSamplesBySampleListIds(List sampleListIds, String projection) { - // Rather than get all the samples for all the sample list IDs all at once, - // we get them 1 sample list ID at a time. This allows for more efficient caching, since - // the samples associated with each sample list are only cached once. - // We also need to remove duplicates samples because samples from multiple sample list IDs can have overlapping - return sampleListIds.stream() - .flatMap(id -> fetchSampleBySampleListId(id, projection).stream()) - .distinct() - .collect(Collectors.toList()); - } - - @Override - public List fetchSampleBySampleListId(String sampleListId, String projection) { - return sampleMapper.getSamplesBySampleListIds(Collections.singletonList(sampleListId), projection); - } - - @Override - public BaseMeta fetchMetaSamples(List studyIds, List sampleIds) { - - return sampleMapper.getMetaSamples(studyIds, null, sampleIds, null); - } - - @Override - public BaseMeta fetchMetaSamples(List sampleListIds) { - - return sampleMapper.getMetaSamplesBySampleListIds(sampleListIds); - } - - @Override - public List getSamplesByInternalIds(List internalIds) { - - return sampleMapper.getSamplesByInternalIds(internalIds, PersistenceConstants.ID_PROJECTION); - } -} diff --git a/src/main/java/org/cbioportal/persistence/mybatis/SecurityMapper.java b/src/main/java/org/cbioportal/persistence/mybatis/SecurityMapper.java deleted file mode 100644 index 3f47af78354..00000000000 --- a/src/main/java/org/cbioportal/persistence/mybatis/SecurityMapper.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (c) 2015 Memorial Sloan-Kettering Cancer Center. - * - * This library is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS - * FOR A PARTICULAR PURPOSE. The software and documentation provided hereunder - * is on an "as is" basis, and Memorial Sloan-Kettering Cancer Center has no - * obligations to provide maintenance, support, updates, enhancements or - * modifications. In no event shall Memorial Sloan-Kettering Cancer Center be - * liable to any party for direct, indirect, special, incidental or - * consequential damages, including lost profits, arising out of the use of this - * software and its documentation, even if Memorial Sloan-Kettering Cancer - * Center has been advised of the possibility of such damage. - */ - -/* - * This file is part of cBioPortal. - * - * cBioPortal is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . -*/ - -package org.cbioportal.persistence.mybatis; - -// imports -import org.apache.ibatis.annotations.Param; - -import org.cbioportal.model.User; -import org.cbioportal.model.UserAuthorities; - -/** - * Interface to use to retrieve - * portal user information. - */ -public interface SecurityMapper { - - /** - * Given a user id, returns a user instance. - * If username does not exist in db, returns null. - * - * @param username String - * @return User - */ - User getPortalUser(@Param("username") String username); - - /** - * Given a user id, returns a UserAuthorities instance. - * If username does not exist in db, returns null. - * - * @param username String - * @return User - */ - UserAuthorities getPortalUserAuthorities(@Param("username") String username); - - void addPortalUser(User user); - void addPortalUserAuthority(@Param("email") String email, @Param("authority") String authority); - - /** - * Given an internal cancer study id, returns groups string. - * Returns null if cancer study does not exist. - * - * @param internalCancerStudyId Integer - * @return String groups - */ - String getCancerStudyGroups(Integer internalCancerStudyId); -} diff --git a/src/main/java/org/cbioportal/persistence/mybatis/SecurityMyBatisRepository.java b/src/main/java/org/cbioportal/persistence/mybatis/SecurityMyBatisRepository.java deleted file mode 100644 index 3172948d2a5..00000000000 --- a/src/main/java/org/cbioportal/persistence/mybatis/SecurityMyBatisRepository.java +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Copyright (c) 2015 Memorial Sloan-Kettering Cancer Center. - * - * This library is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS - * FOR A PARTICULAR PURPOSE. The software and documentation provided hereunder - * is on an "as is" basis, and Memorial Sloan-Kettering Cancer Center has no - * obligations to provide maintenance, support, updates, enhancements or - * modifications. In no event shall Memorial Sloan-Kettering Cancer Center be - * liable to any party for direct, indirect, special, incidental or - * consequential damages, including lost profits, arising out of the use of this - * software and its documentation, even if Memorial Sloan-Kettering Cancer - * Center has been advised of the possibility of such damage. - */ - -/* - * This file is part of cBioPortal. - * - * cBioPortal is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . -*/ - -package org.cbioportal.persistence.mybatis; - -// imports -import java.util.Arrays; -import java.util.Collections; -import java.util.HashSet; -import java.util.Set; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import org.cbioportal.model.User; -import org.cbioportal.model.UserAuthorities; -import org.cbioportal.persistence.SecurityRepository; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Repository; - -@Repository -public class SecurityMyBatisRepository implements SecurityRepository { - - private static final Logger log = LoggerFactory.getLogger(SecurityMyBatisRepository.class); - - @Autowired - private SecurityMapper securityMapper; - - /** - * Given a user id, returns a user instance. - * If username does not exist in db, returns null. - * - * @param username String - * @return User - */ - @Override - public User getPortalUser(String username) { - User user = securityMapper.getPortalUser(username); - if (user != null) { - log.debug("User " + username + " was found in the users table, email is " + user.getEmail()); - } else { - log.debug("User " + username + " is null"); - } - return user; - } - - /** - * Given a user id, returns a UserAuthorities instance. - * If username does not exist in db, returns null. - * - * @param username String - * @return UserAuthorities - */ - @Override - public UserAuthorities getPortalUserAuthorities(String username) { - return securityMapper.getPortalUserAuthorities(username); - } - - @Override - public void addPortalUser(User user) { - securityMapper.addPortalUser(user); - } - - @Override - public void addPortalUserAuthorities(UserAuthorities userAuthorities) { - for (String authority : userAuthorities.getAuthorities()) { - securityMapper.addPortalUserAuthority(userAuthorities.getEmail(), authority); - } - } - - /** - * Given an internal cancer study id, returns a set of upper case cancer study group strings. - * Returns empty set if cancer study does not exist or there are no groups. - * - * @param internalCancerStudyId Integer - * @return Set cancer study group strings in upper case - */ - @Override - public Set getCancerStudyGroups(Integer internalCancerStudyId) { - String groups = securityMapper.getCancerStudyGroups(internalCancerStudyId); - if (groups == null) { - return Collections.emptySet(); - } - return new HashSet(Arrays.asList(groups.toUpperCase().split(";"))); - } -} diff --git a/src/main/java/org/cbioportal/persistence/mybatis/SignificantCopyNumberRegionMapper.java b/src/main/java/org/cbioportal/persistence/mybatis/SignificantCopyNumberRegionMapper.java deleted file mode 100644 index dbcc1f2b852..00000000000 --- a/src/main/java/org/cbioportal/persistence/mybatis/SignificantCopyNumberRegionMapper.java +++ /dev/null @@ -1,17 +0,0 @@ -package org.cbioportal.persistence.mybatis; - -import org.cbioportal.model.Gistic; -import org.cbioportal.model.GisticToGene; -import org.cbioportal.model.meta.BaseMeta; - -import java.util.List; - -public interface SignificantCopyNumberRegionMapper { - - List getSignificantCopyNumberRegions(String studyId, String projection, Integer limit, Integer offset, - String sortBy, String direction); - - BaseMeta getMetaSignificantCopyNumberRegions(String studyId); - - List getGenesOfRegions(List gisticRoiIds); -} diff --git a/src/main/java/org/cbioportal/persistence/mybatis/SignificantCopyNumberRegionMyBatisRepository.java b/src/main/java/org/cbioportal/persistence/mybatis/SignificantCopyNumberRegionMyBatisRepository.java deleted file mode 100644 index 7cadd7e8cd1..00000000000 --- a/src/main/java/org/cbioportal/persistence/mybatis/SignificantCopyNumberRegionMyBatisRepository.java +++ /dev/null @@ -1,38 +0,0 @@ -package org.cbioportal.persistence.mybatis; - -import org.cbioportal.model.Gistic; -import org.cbioportal.model.GisticToGene; -import org.cbioportal.model.meta.BaseMeta; -import org.cbioportal.persistence.SignificantCopyNumberRegionRepository; -import org.cbioportal.persistence.mybatis.util.PaginationCalculator; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Repository; - -import java.util.List; - -@Repository -public class SignificantCopyNumberRegionMyBatisRepository implements SignificantCopyNumberRegionRepository { - - @Autowired - private SignificantCopyNumberRegionMapper significantCopyNumberRegionMapper; - - @Override - public List getSignificantCopyNumberRegions(String studyId, String projection, Integer pageSize, - Integer pageNumber, String sortBy, String direction) { - - return significantCopyNumberRegionMapper.getSignificantCopyNumberRegions(studyId, projection, pageSize, - PaginationCalculator.offset(pageSize, pageNumber), sortBy, direction); - } - - @Override - public BaseMeta getMetaSignificantCopyNumberRegions(String studyId) { - - return significantCopyNumberRegionMapper.getMetaSignificantCopyNumberRegions(studyId); - } - - @Override - public List getGenesOfRegions(List gisticRoiIds) { - - return significantCopyNumberRegionMapper.getGenesOfRegions(gisticRoiIds); - } -} diff --git a/src/main/java/org/cbioportal/persistence/mybatis/SignificantlyMutatedGeneMapper.java b/src/main/java/org/cbioportal/persistence/mybatis/SignificantlyMutatedGeneMapper.java deleted file mode 100644 index 0cb1eccefe6..00000000000 --- a/src/main/java/org/cbioportal/persistence/mybatis/SignificantlyMutatedGeneMapper.java +++ /dev/null @@ -1,14 +0,0 @@ -package org.cbioportal.persistence.mybatis; - -import org.cbioportal.model.MutSig; -import org.cbioportal.model.meta.BaseMeta; - -import java.util.List; - -public interface SignificantlyMutatedGeneMapper { - - List getSignificantlyMutatedGenes(String studyId, String projection, Integer limit, Integer offset, - String sortBy, String direction); - - BaseMeta getMetaSignificantlyMutatedGenes(String studyId); -} diff --git a/src/main/java/org/cbioportal/persistence/mybatis/SignificantlyMutatedGeneMyBatisRepository.java b/src/main/java/org/cbioportal/persistence/mybatis/SignificantlyMutatedGeneMyBatisRepository.java deleted file mode 100644 index 69225317885..00000000000 --- a/src/main/java/org/cbioportal/persistence/mybatis/SignificantlyMutatedGeneMyBatisRepository.java +++ /dev/null @@ -1,31 +0,0 @@ -package org.cbioportal.persistence.mybatis; - -import org.cbioportal.model.MutSig; -import org.cbioportal.model.meta.BaseMeta; -import org.cbioportal.persistence.SignificantlyMutatedGeneRepository; -import org.cbioportal.persistence.mybatis.util.PaginationCalculator; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Repository; - -import java.util.List; - -@Repository -public class SignificantlyMutatedGeneMyBatisRepository implements SignificantlyMutatedGeneRepository { - - @Autowired - private SignificantlyMutatedGeneMapper significantlyMutatedGeneMapper; - - @Override - public List getSignificantlyMutatedGenes(String studyId, String projection, Integer pageSize, - Integer pageNumber, String sortBy, String direction) { - - return significantlyMutatedGeneMapper.getSignificantlyMutatedGenes(studyId, projection, pageSize, - PaginationCalculator.offset(pageSize, pageNumber), sortBy, direction); - } - - @Override - public BaseMeta getMetaSignificantlyMutatedGenes(String studyId) { - - return significantlyMutatedGeneMapper.getMetaSignificantlyMutatedGenes(studyId); - } -} diff --git a/src/main/java/org/cbioportal/persistence/mybatis/StaticDataTimeStampMyBatisRepository.java b/src/main/java/org/cbioportal/persistence/mybatis/StaticDataTimeStampMyBatisRepository.java deleted file mode 100644 index bdcf5eb308a..00000000000 --- a/src/main/java/org/cbioportal/persistence/mybatis/StaticDataTimeStampMyBatisRepository.java +++ /dev/null @@ -1,23 +0,0 @@ -package org.cbioportal.persistence.mybatis; - -import org.cbioportal.model.TableTimestampPair; -import org.cbioportal.persistence.StaticDataTimeStampRepository; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.stereotype.Repository; - -import java.util.List; - -@Repository -public class StaticDataTimeStampMyBatisRepository implements StaticDataTimeStampRepository { - @Value("${db.portal_db_name:}") - private String dbName; - - @Autowired - private StaticDataTimestampMapper staticDataTimestampMapper; - - @Override - public List getTimestamps(List tableNames) { - return staticDataTimestampMapper.getTimestamps(tableNames, dbName); - } -} diff --git a/src/main/java/org/cbioportal/persistence/mybatis/StaticDataTimestampMapper.java b/src/main/java/org/cbioportal/persistence/mybatis/StaticDataTimestampMapper.java deleted file mode 100644 index 573d0d8be6c..00000000000 --- a/src/main/java/org/cbioportal/persistence/mybatis/StaticDataTimestampMapper.java +++ /dev/null @@ -1,9 +0,0 @@ -package org.cbioportal.persistence.mybatis; - -import org.cbioportal.model.TableTimestampPair; - -import java.util.List; - -public interface StaticDataTimestampMapper { - List getTimestamps(List tables, String dbName); -} diff --git a/src/main/java/org/cbioportal/persistence/mybatis/StructuralVariantMapper.java b/src/main/java/org/cbioportal/persistence/mybatis/StructuralVariantMapper.java deleted file mode 100644 index 2a24f753b0d..00000000000 --- a/src/main/java/org/cbioportal/persistence/mybatis/StructuralVariantMapper.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (c) 2018 The Hyve B.V. - * This code is licensed under the GNU Affero General Public License (AGPL), - * version 3, or (at your option) any later version. - */ - -/* - * This file is part of cBioPortal. - * - * cBioPortal is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -package org.cbioportal.persistence.mybatis; - -import java.util.List; - -import org.cbioportal.model.GeneFilterQuery; -import org.cbioportal.model.StructuralVariantFilterQuery; -import org.cbioportal.model.StructuralVariant; -import org.cbioportal.model.StructuralVariantQuery; - -public interface StructuralVariantMapper { - - List fetchStructuralVariants(List molecularProfileIds, - List sampleIds, - List entrezGeneIds, - List structuralVariantQueries); - - List fetchStructuralVariantsByGeneQueries(List molecularProfileIds, - List sampleIds, - List geneQueries); - - List fetchStructuralVariantsByStructVarQueries(List molecularProfileIds, - List sampleIds, - List structVarQueries); -} diff --git a/src/main/java/org/cbioportal/persistence/mybatis/StructuralVariantMyBatisRepository.java b/src/main/java/org/cbioportal/persistence/mybatis/StructuralVariantMyBatisRepository.java deleted file mode 100644 index f03d42130da..00000000000 --- a/src/main/java/org/cbioportal/persistence/mybatis/StructuralVariantMyBatisRepository.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright (c) 2018 The Hyve B.V. - * This code is licensed under the GNU Affero General Public License (AGPL), - * version 3, or (at your option) any later version. - */ - -/* - * This file is part of cBioPortal. - * - * cBioPortal is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -package org.cbioportal.persistence.mybatis; - -import org.cbioportal.model.GeneFilterQuery; -import org.cbioportal.model.StructuralVariantFilterQuery; -import org.cbioportal.model.StructuralVariant; -import org.cbioportal.model.StructuralVariantQuery; -import org.cbioportal.persistence.StructuralVariantRepository; -import org.cbioportal.persistence.mybatis.util.MolecularProfileCaseIdentifierUtil; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Repository; - -import java.util.ArrayList; -import java.util.List; -import java.util.stream.Collectors; - -import static java.util.Arrays.asList; - -@Repository -public class StructuralVariantMyBatisRepository implements StructuralVariantRepository { - - @Autowired - private StructuralVariantMapper structuralVariantMapper; - @Autowired - private MolecularProfileCaseIdentifierUtil molecularProfileCaseIdentifierUtil; - - @Override - public List fetchStructuralVariants(List molecularProfileIds, - List sampleIds, - List entrezGeneIds, - List structuralVariantQueries) { - if (molecularProfileIds == null || molecularProfileIds.isEmpty()) { - return new ArrayList<>(); - } - return molecularProfileCaseIdentifierUtil.getGroupedCasesByMolecularProfileId(molecularProfileIds, sampleIds) - .entrySet() - .stream() - .flatMap(entry -> - structuralVariantMapper - .fetchStructuralVariants( - asList(entry.getKey()), - new ArrayList<>(entry.getValue()), - entrezGeneIds, - structuralVariantQueries - ) - .stream() - ) - .collect(Collectors.toList()); - } - - @Override - public List fetchStructuralVariantsByGeneQueries(List molecularProfileIds, - List sampleIds, - List geneQueries) { - if (geneQueries == null || geneQueries.isEmpty() - || molecularProfileIds == null || molecularProfileIds.isEmpty()) { - return new ArrayList<>(); - } - return structuralVariantMapper.fetchStructuralVariantsByGeneQueries(molecularProfileIds, sampleIds, geneQueries); - } - - @Override - public List fetchStructuralVariantsByStructVarQueries(List molecularProfileIds, - List sampleIds, - List structVarQueries) { - if (structVarQueries == null || structVarQueries.isEmpty() - || molecularProfileIds == null || molecularProfileIds.isEmpty()) { - return new ArrayList<>(); - } - return structuralVariantMapper.fetchStructuralVariantsByStructVarQueries(molecularProfileIds, sampleIds, structVarQueries); - } -} diff --git a/src/main/java/org/cbioportal/persistence/mybatis/StudyMapper.java b/src/main/java/org/cbioportal/persistence/mybatis/StudyMapper.java deleted file mode 100644 index 04290b77c80..00000000000 --- a/src/main/java/org/cbioportal/persistence/mybatis/StudyMapper.java +++ /dev/null @@ -1,21 +0,0 @@ -package org.cbioportal.persistence.mybatis; - -import org.cbioportal.model.CancerStudy; -import org.cbioportal.model.CancerStudyTags; -import org.cbioportal.model.meta.BaseMeta; - -import java.util.List; - -public interface StudyMapper { - - List getStudies(List studyIds, String keyword, String projection, Integer limit, Integer offset, String sortBy, - String direction); - - BaseMeta getMetaStudies(List studyIds, String keyword); - - CancerStudy getStudy(String studyId, String projection); - - CancerStudyTags getTags(String studyId); - - List getTagsForMultipleStudies(List studyIds); -} diff --git a/src/main/java/org/cbioportal/persistence/mybatis/StudyMyBatisRepository.java b/src/main/java/org/cbioportal/persistence/mybatis/StudyMyBatisRepository.java deleted file mode 100644 index 813c6ff5ab6..00000000000 --- a/src/main/java/org/cbioportal/persistence/mybatis/StudyMyBatisRepository.java +++ /dev/null @@ -1,62 +0,0 @@ -package org.cbioportal.persistence.mybatis; - -import org.cbioportal.model.CancerStudy; -import org.cbioportal.model.CancerStudyTags; -import org.cbioportal.model.meta.BaseMeta; -import org.cbioportal.persistence.StudyRepository; -import org.cbioportal.persistence.mybatis.util.PaginationCalculator; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Repository; - -import java.util.ArrayList; -import java.util.List; - -@Repository -public class StudyMyBatisRepository implements StudyRepository { - - @Autowired - private StudyMapper studyMapper; - - @Override - public List getAllStudies(String keyword, String projection, Integer pageSize, Integer pageNumber, - String sortBy, String direction) { - - return studyMapper.getStudies(null, keyword, projection, pageSize, PaginationCalculator.offset(pageSize, pageNumber), - sortBy, direction); - } - - @Override - public BaseMeta getMetaStudies(String keyword) { - return studyMapper.getMetaStudies(null, keyword); - } - - @Override - public CancerStudy getStudy(String studyId, String projection) { - return studyMapper.getStudy(studyId, projection); - } - - @Override - public List fetchStudies(List studyIds, String projection) { - - return studyMapper.getStudies(studyIds, null, projection, 0, 0, null, null); - } - - @Override - public BaseMeta fetchMetaStudies(List studyIds) { - - return studyMapper.getMetaStudies(studyIds, null); - } - - @Override - public CancerStudyTags getTags(String studyId) { - return studyMapper.getTags(studyId); - } - - @Override - public List getTagsForMultipleStudies(List studyIds) { - if (studyIds == null || studyIds.isEmpty()) { - return new ArrayList<>(); - } - return studyMapper.getTagsForMultipleStudies(studyIds); - } -} diff --git a/src/main/java/org/cbioportal/persistence/mybatis/TreatmentMapper.java b/src/main/java/org/cbioportal/persistence/mybatis/TreatmentMapper.java deleted file mode 100644 index 44e4f856079..00000000000 --- a/src/main/java/org/cbioportal/persistence/mybatis/TreatmentMapper.java +++ /dev/null @@ -1,19 +0,0 @@ -package org.cbioportal.persistence.mybatis; - -import org.cbioportal.model.ClinicalEventSample; -import org.cbioportal.model.Treatment; - -import java.util.List; -import java.util.Set; - -public interface TreatmentMapper { - List getAllTreatments(List sampleIds, List studyIds, String key); - - List getAllSamples(List sampleIds, List studyIds); - - List getAllShallowSamples(List sampleIds, List studyIds); - - Boolean hasTreatmentData(List sampleIds, List studyIds, String key); - - Boolean hasSampleTimelineData(List sampleIds, List studyIds); -} diff --git a/src/main/java/org/cbioportal/persistence/mybatis/TreatmentMyBatisRepository.java b/src/main/java/org/cbioportal/persistence/mybatis/TreatmentMyBatisRepository.java deleted file mode 100644 index d44bdfc808a..00000000000 --- a/src/main/java/org/cbioportal/persistence/mybatis/TreatmentMyBatisRepository.java +++ /dev/null @@ -1,77 +0,0 @@ -package org.cbioportal.persistence.mybatis; - -import org.cbioportal.model.*; -import org.cbioportal.persistence.TreatmentRepository; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Repository; - -import java.util.*; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -import static java.util.stream.Collectors.groupingBy; - -@Repository -public class TreatmentMyBatisRepository implements TreatmentRepository { - @Autowired - private TreatmentMapper treatmentMapper; - - @Override - public Map> getTreatmentsByPatientId(List sampleIds, List studyIds, ClinicalEventKeyCode key) { - return getTreatments(sampleIds, studyIds, key) - .stream() - .collect(groupingBy(Treatment::getPatientId)); - } - - @Override - public List getTreatments(List sampleIds, List studyIds, ClinicalEventKeyCode key) { - return treatmentMapper.getAllTreatments(sampleIds, studyIds, key.getKey()) - .stream() - .flatMap(treatment -> splitIfDelimited(treatment, key)) - .collect(Collectors.toList()); - } - - private Stream splitIfDelimited(Treatment unsplitTreatment, ClinicalEventKeyCode key) { - if (key.isDelimited()) { - return Arrays.stream(unsplitTreatment.getTreatment().split(key.getDelimiter())) - .map(treatmentName -> { - Treatment treatment = new Treatment(); - treatment.setTreatment(treatmentName); - treatment.setStudyId(unsplitTreatment.getStudyId()); - treatment.setPatientId(unsplitTreatment.getPatientId()); - treatment.setStart(unsplitTreatment.getStart()); - treatment.setStop(unsplitTreatment.getStop()); - treatment.setPatientId(unsplitTreatment.getPatientId()); - return treatment; - }); - } - return Stream.of(unsplitTreatment); - } - - @Override - public Map> getSamplesByPatientId(List sampleIds, List studyIds) { - return treatmentMapper.getAllSamples(sampleIds, studyIds) - .stream() - .sorted(Comparator.comparing(ClinicalEventSample::getTimeTaken)) // put earliest events first - .distinct() // uniqueness determined by sample id, patient id, and study id - // combined, the sort and distinct produce the earliest clinical event row for each unique sample - .collect(groupingBy(ClinicalEventSample::getPatientId)); - } - - public Map> getShallowSamplesByPatientId(List sampleIds, List studyIds) { - return treatmentMapper.getAllShallowSamples(sampleIds, studyIds) - .stream() - .distinct() - .collect(groupingBy(ClinicalEventSample::getPatientId)); - } - - @Override - public Boolean hasTreatmentData(List studies, ClinicalEventKeyCode key) { - return treatmentMapper.hasTreatmentData(null, studies, key.getKey()); - } - - @Override - public Boolean hasSampleTimelineData(List studies) { - return treatmentMapper.hasSampleTimelineData(null, studies); - } -} diff --git a/src/main/java/org/cbioportal/persistence/mybatis/VariantCountMapper.java b/src/main/java/org/cbioportal/persistence/mybatis/VariantCountMapper.java deleted file mode 100644 index 2d67d112897..00000000000 --- a/src/main/java/org/cbioportal/persistence/mybatis/VariantCountMapper.java +++ /dev/null @@ -1,11 +0,0 @@ -package org.cbioportal.persistence.mybatis; - -import org.cbioportal.model.VariantCount; - -import java.util.List; - -public interface VariantCountMapper { - - List fetchVariantCounts(String molecularProfileId, List entrezGeneIds, - List keywords); -} diff --git a/src/main/java/org/cbioportal/persistence/mybatis/VariantCountMyBatisRepository.java b/src/main/java/org/cbioportal/persistence/mybatis/VariantCountMyBatisRepository.java deleted file mode 100644 index 723c2bafa30..00000000000 --- a/src/main/java/org/cbioportal/persistence/mybatis/VariantCountMyBatisRepository.java +++ /dev/null @@ -1,22 +0,0 @@ -package org.cbioportal.persistence.mybatis; - -import org.cbioportal.model.VariantCount; -import org.cbioportal.persistence.VariantCountRepository; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Repository; - -import java.util.List; - -@Repository -public class VariantCountMyBatisRepository implements VariantCountRepository { - - @Autowired - private VariantCountMapper variantCountMapper; - - @Override - public List fetchVariantCounts(String molecularProfileId, List entrezGeneIds, - List keywords) { - - return variantCountMapper.fetchVariantCounts(molecularProfileId, entrezGeneIds, keywords); - } -} diff --git a/src/main/java/org/cbioportal/persistence/mybatis/config/PersistenceConfig.java b/src/main/java/org/cbioportal/persistence/mybatis/config/PersistenceConfig.java deleted file mode 100644 index b8dba141ae4..00000000000 --- a/src/main/java/org/cbioportal/persistence/mybatis/config/PersistenceConfig.java +++ /dev/null @@ -1,64 +0,0 @@ -package org.cbioportal.persistence.mybatis.config; - -import org.cbioportal.model.Sample; -import org.cbioportal.persistence.mybatis.typehandler.SampleTypeTypeHandler; -import org.cbioportal.utils.config.annotation.ConditionalOnProperty; -import org.mybatis.spring.SqlSessionFactoryBean; -import org.mybatis.spring.annotation.MapperScan; -import org.mybatis.spring.boot.autoconfigure.ConfigurationCustomizer; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.context.ApplicationContext; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.jdbc.datasource.DataSourceTransactionManager; - -import javax.sql.DataSource; -import java.io.IOException; - - -@Configuration -@MapperScan(value="org.cbioportal.persistence.mybatis", sqlSessionFactoryRef="sqlSessionFactory") -public class PersistenceConfig { - - // This is the only way I was able to register the SampleType TypeHandler to MyBatis. - // The bean-based approach described in the MyBatis docs for mybatis-spring-boot-autoconfigure - // did not work in my hands (See: https://mybatis.org/spring-boot-starter/mybatis-spring-boot-autoconfigure#Detecting_MyBatis_components). - @Bean - ConfigurationCustomizer mybatisConfigurationCustomizer() { - return new ConfigurationCustomizer() { - @Override - public void customize(org.apache.ibatis.session.Configuration configuration) { - configuration.getTypeHandlerRegistry().register(Sample.SampleType.class, new SampleTypeTypeHandler()); - } - }; - } - - @Bean("sqlSessionFactory") - @ConditionalOnProperty(name = "clickhouse_mode", havingValue = "true") - public SqlSessionFactoryBean sqlSessionFactorySpecifyDataSource(@Qualifier("mysqlDataSource") DataSource dataSource, ApplicationContext applicationContext) throws IOException { - return sqlSessionFactory(dataSource, applicationContext); - } - - @Bean("sqlSessionFactory") - @ConditionalOnProperty(name = "clickhouse_mode", havingValue = "false", matchIfMissing = true) - public SqlSessionFactoryBean sqlSessionFactoryDefault(DataSource dataSource, ApplicationContext applicationContext) throws IOException { - return sqlSessionFactory(dataSource, applicationContext); - } - - - private SqlSessionFactoryBean sqlSessionFactory(DataSource dataSource, ApplicationContext applicationContext) throws IOException { - SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean(); - sessionFactory.setDataSource(dataSource); - sessionFactory.setMapperLocations( - applicationContext.getResources("classpath:org/cbioportal/persistence/mybatis/*.xml") - ); - sessionFactory.setTypeHandlers(new SampleTypeTypeHandler()); - return sessionFactory; - } - - @Bean - @ConditionalOnProperty(name = "clickhouse_mode", havingValue = "true") - public DataSourceTransactionManager transactionManager(@Qualifier("mysqlDataSource") DataSource dataSource) { - return new DataSourceTransactionManager(dataSource); - } -} diff --git a/src/main/java/org/cbioportal/persistence/mybatis/typehandler/SampleTypeTypeHandler.java b/src/main/java/org/cbioportal/persistence/mybatis/typehandler/SampleTypeTypeHandler.java deleted file mode 100644 index 1b3d7b9986b..00000000000 --- a/src/main/java/org/cbioportal/persistence/mybatis/typehandler/SampleTypeTypeHandler.java +++ /dev/null @@ -1,35 +0,0 @@ -package org.cbioportal.persistence.mybatis.typehandler; - -import org.apache.ibatis.type.JdbcType; -import org.apache.ibatis.type.MappedTypes; -import org.apache.ibatis.type.TypeHandler; -import org.cbioportal.model.Sample; - -import java.sql.CallableStatement; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; - -@MappedTypes(Sample.SampleType.class) -public class SampleTypeTypeHandler implements TypeHandler { - - @Override - public void setParameter(PreparedStatement preparedStatement, int i, Sample.SampleType sampleType, JdbcType jdbcType) throws SQLException { - preparedStatement.setString(i, sampleType.getValue()); - } - - @Override - public Sample.SampleType getResult(ResultSet resultSet, String s) throws SQLException { - return Sample.SampleType.fromString(resultSet.getString(s)); - } - - @Override - public Sample.SampleType getResult(ResultSet resultSet, int i) throws SQLException { - return Sample.SampleType.fromString(resultSet.getString(i)); - } - - @Override - public Sample.SampleType getResult(CallableStatement callableStatement, int i) throws SQLException { - return Sample.SampleType.fromString(callableStatement.getString(i)); - } -} diff --git a/src/main/java/org/cbioportal/persistence/mybatis/util/CustomMyBatisObjectFactory.java b/src/main/java/org/cbioportal/persistence/mybatis/util/CustomMyBatisObjectFactory.java deleted file mode 100644 index 4899efbed12..00000000000 --- a/src/main/java/org/cbioportal/persistence/mybatis/util/CustomMyBatisObjectFactory.java +++ /dev/null @@ -1,19 +0,0 @@ -package org.cbioportal.persistence.mybatis.util; - -import org.apache.ibatis.reflection.factory.DefaultObjectFactory; - -import java.util.*; - -public class CustomMyBatisObjectFactory extends DefaultObjectFactory { - - public T create(Class type) { - String typeName = type.getName(); - T toReturn = (T) super.create(type); - return (toReturn instanceof List) ? (T) new LimitedPermissionArrayList() : toReturn; - } - public T create(Class type, List> constructorArgTypes, List constructorArgs) { - String typeName = type.getName(); - T toReturn = (T) super.create(type, constructorArgTypes, constructorArgs); - return (toReturn instanceof List) ? (T) new LimitedPermissionArrayList() : toReturn; - } -} diff --git a/src/main/java/org/cbioportal/persistence/mybatis/util/LimitedPermissionArrayList.java b/src/main/java/org/cbioportal/persistence/mybatis/util/LimitedPermissionArrayList.java deleted file mode 100644 index 3c864c42d72..00000000000 --- a/src/main/java/org/cbioportal/persistence/mybatis/util/LimitedPermissionArrayList.java +++ /dev/null @@ -1,62 +0,0 @@ -package org.cbioportal.persistence.mybatis.util; - -import java.util.*; -import java.util.function.*; - -public class LimitedPermissionArrayList extends ArrayList { - - public boolean addAll(Collection c) { - System.out.println("addAll called"); - throw new UnsupportedOperationException(); - } - - public boolean addAll(int index, Collection c) { - System.out.println("addAll called"); - throw new UnsupportedOperationException(); - } - - public void clear() { - System.out.println("clear called"); - throw new UnsupportedOperationException(); - } - - public T remove(int index) { - System.out.println("remove called"); - throw new UnsupportedOperationException(); - } - - public boolean remove(Object o) { - System.out.println("LimitedPermissionArrayList:remove() called, throwing UnsupportedOperationException()"); - throw new UnsupportedOperationException(); - } - - public boolean removeAll(Collection c) { - System.out.println("LimitedPermissionArrayList:removeAll() called, throwing UnsupportedOperationException()"); - throw new UnsupportedOperationException(); - } - - public boolean removeIf(Predicate filter) { - System.out.println("LimitedPermissionArrayList:removeIF() called, throwing UnsupportedOperationException()"); - throw new UnsupportedOperationException(); - } - - protected void removeRange(int fromIndex, int toIndex) { - System.out.println("LimitedPermissionArrayList:removeRange() called, throwing UnsupportedOperationException()"); - throw new UnsupportedOperationException(); - } - - public void replaceAll(UnaryOperator operator) { - System.out.println("LimitedPermissionArrayList:replaceAll() called, throwing UnsupportedOperationException()"); - throw new UnsupportedOperationException(); - } - - public boolean retainAll(Collection c) { - System.out.println("LimitedPermissionArrayList:retainAlll() called, throwing UnsupportedOperationException()"); - throw new UnsupportedOperationException(); - } - - public T set(int index, T element) { - System.out.println("LimitedPermissionArrayList:set() called, throwing UnsupportedOperationException()"); - throw new UnsupportedOperationException(); - } -} diff --git a/src/main/java/org/cbioportal/persistence/mybatis/util/MolecularProfileCaseIdentifierUtil.java b/src/main/java/org/cbioportal/persistence/mybatis/util/MolecularProfileCaseIdentifierUtil.java deleted file mode 100644 index 699f3f239b5..00000000000 --- a/src/main/java/org/cbioportal/persistence/mybatis/util/MolecularProfileCaseIdentifierUtil.java +++ /dev/null @@ -1,33 +0,0 @@ -package org.cbioportal.persistence.mybatis.util; - -import org.apache.commons.math3.util.Pair; -import org.springframework.stereotype.Component; -import org.springframework.util.CollectionUtils; - -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.function.Function; -import java.util.stream.Collectors; -import java.util.stream.IntStream; - -import static java.util.stream.Collectors.*; - -@Component -public class MolecularProfileCaseIdentifierUtil { - - public Map> getGroupedCasesByMolecularProfileId(List molecularProfileIds, List caseIds) { - - if (CollectionUtils.isEmpty(caseIds)) { - return molecularProfileIds.stream().collect(Collectors.toMap(Function.identity(), e -> new HashSet<>())); - } - - return IntStream.range(0, molecularProfileIds.size()) - .mapToObj(i -> new Pair<>(molecularProfileIds.get(i), caseIds.get(i))) - .collect(groupingBy( - Pair::getFirst, - mapping(Pair::getSecond, toSet())) - ); - } -} diff --git a/src/main/java/org/cbioportal/persistence/mybatis/util/PaginationCalculator.java b/src/main/java/org/cbioportal/persistence/mybatis/util/PaginationCalculator.java deleted file mode 100644 index ab2b4588052..00000000000 --- a/src/main/java/org/cbioportal/persistence/mybatis/util/PaginationCalculator.java +++ /dev/null @@ -1,26 +0,0 @@ -package org.cbioportal.persistence.mybatis.util; - -public class PaginationCalculator { - - private PaginationCalculator() {} - - /** - * PageNumber '0' represents the first page (no offset). - */ - public static Integer offset(Integer pageSize, Integer pageNumber) { - return pageSize == null || pageNumber == null ? - null : pageSize * pageNumber; - } - - /** - * Returns 'lastIndex' as used by the subList command; position of the last element (exclusive). - */ - public static Integer lastIndex(Integer offset, Integer pageSize, Integer listLength) { - if (offset == null || pageSize == null || listLength == null) { - return null; - } - return (offset + pageSize) <= listLength ? - (offset + pageSize) : listLength; - } - -} diff --git a/src/main/java/org/cbioportal/persistence/mybatisclickhouse/StudyViewMapper.java b/src/main/java/org/cbioportal/persistence/mybatisclickhouse/StudyViewMapper.java deleted file mode 100644 index dca5ad64125..00000000000 --- a/src/main/java/org/cbioportal/persistence/mybatisclickhouse/StudyViewMapper.java +++ /dev/null @@ -1,90 +0,0 @@ -package org.cbioportal.persistence.mybatisclickhouse; - -import org.apache.ibatis.annotations.Param; -import org.cbioportal.model.AlterationCountByGene; -import org.cbioportal.model.CaseListDataCount; -import org.cbioportal.model.ClinicalAttribute; -import org.cbioportal.model.ClinicalData; -import org.cbioportal.model.ClinicalDataCount; -import org.cbioportal.model.ClinicalDataCountItem; -import org.cbioportal.model.ClinicalEventTypeCount; -import org.cbioportal.model.CopyNumberCountByGene; -import org.cbioportal.model.GenePanelToGene; -import org.cbioportal.model.GenericAssayDataCountItem; -import org.cbioportal.model.GenomicDataCount; -import org.cbioportal.model.GenomicDataCountItem; -import org.cbioportal.model.PatientTreatment; -import org.cbioportal.model.MolecularProfile; -import org.cbioportal.model.Sample; -import org.cbioportal.model.SampleTreatment; -import org.cbioportal.persistence.helper.AlterationFilterHelper; -import org.cbioportal.persistence.helper.StudyViewFilterHelper; -import org.cbioportal.web.parameter.GenericAssayDataBinFilter; -import org.cbioportal.web.parameter.GenericAssayDataFilter; -import org.cbioportal.web.parameter.GenomicDataBinFilter; -import org.cbioportal.web.parameter.GenomicDataFilter; - -import java.util.List; -import java.util.Map; - - -public interface StudyViewMapper { - List getFilteredSamples(@Param("studyViewFilterHelper") StudyViewFilterHelper studyViewFilterHelper); - - List getFilteredStudyIds(@Param("studyViewFilterHelper") StudyViewFilterHelper studyViewFilterHelper); - - List getMolecularProfileSampleCounts(@Param("studyViewFilterHelper") StudyViewFilterHelper studyViewFilterHelper); - - List getMutatedGenes(StudyViewFilterHelper studyViewFilterHelper, AlterationFilterHelper alterationFilterHelper); - - List getCnaGenes(StudyViewFilterHelper studyViewFilterHelper, AlterationFilterHelper alterationFilterHelper); - - List getStructuralVariantGenes(StudyViewFilterHelper studyViewFilterHelper, AlterationFilterHelper alterationFilterHelper); - - List getClinicalDataCounts(StudyViewFilterHelper studyViewFilterHelper, List attributeIds, List filteredAttributeValues); - - List getCaseListDataCountsPerStudy(@Param("studyViewFilterHelper") StudyViewFilterHelper studyViewFilterHelper); - - List getClinicalAttributes(); - - List getClinicalAttributesForStudies(List studyIds); - - List getSampleClinicalDataFromStudyViewFilter(StudyViewFilterHelper studyViewFilterHelper, List attributeIds); - - List getPatientClinicalDataFromStudyViewFilter(StudyViewFilterHelper studyViewFilterHelper, List attributeIds); - - List getTotalProfiledCounts(StudyViewFilterHelper studyViewFilterHelper, String alterationType, List molecularProfiles); - - int getFilteredSamplesCount(@Param("studyViewFilterHelper") StudyViewFilterHelper studyViewFilterHelper); - - int getFilteredPatientsCount(@Param("studyViewFilterHelper") StudyViewFilterHelper studyViewFilterHelper); - - List getMatchingGenePanelIds(StudyViewFilterHelper studyViewFilterHelper, String alterationType); - - int getTotalProfiledCountByAlterationType(StudyViewFilterHelper studyViewFilterHelper, String alterationType); - - int getSampleProfileCountWithoutPanelData(StudyViewFilterHelper studyViewFilterHelper, String alterationType); - - List getClinicalEventTypeCounts(@Param("studyViewFilterHelper") StudyViewFilterHelper studyViewFilterHelper); - - List getPatientTreatments(@Param("studyViewFilterHelper") StudyViewFilterHelper studyViewFilterHelper); - int getPatientTreatmentCounts(@Param("studyViewFilterHelper") StudyViewFilterHelper studyViewFilterHelper); - List getSampleTreatmentCounts(@Param("studyViewFilterHelper") StudyViewFilterHelper studyViewFilterHelper); - int getTotalSampleTreatmentCounts(@Param("studyViewFilterHelper") StudyViewFilterHelper studyViewFilterHelper); - - List getCNACounts(StudyViewFilterHelper studyViewFilterHelper, List genomicDataFilters); - - List getGenericAssayDataCounts(StudyViewFilterHelper studyViewFilterHelper, List genericAssayDataFilters); - - Map getMutationCounts(StudyViewFilterHelper studyViewFilterHelper, GenomicDataFilter genomicDataFilter); - - List getMutationCountsByType(StudyViewFilterHelper studyViewFilterHelper, List genomicDataFilters); - - List getGenomicDataBinCounts(StudyViewFilterHelper studyViewFilterHelper, List genomicDataBinFilters); - - List getGenericAssayDataBinCounts(StudyViewFilterHelper studyViewFilterHelper, List genericAssayDataBinFilters); - - List getGenericAssayProfiles(); - - List getFilteredMolecularProfilesByAlterationType(StudyViewFilterHelper studyViewFilterHelper, String alterationType); -} diff --git a/src/main/java/org/cbioportal/persistence/mybatisclickhouse/StudyViewMyBatisRepository.java b/src/main/java/org/cbioportal/persistence/mybatisclickhouse/StudyViewMyBatisRepository.java deleted file mode 100644 index d3f594d61be..00000000000 --- a/src/main/java/org/cbioportal/persistence/mybatisclickhouse/StudyViewMyBatisRepository.java +++ /dev/null @@ -1,271 +0,0 @@ -package org.cbioportal.persistence.mybatisclickhouse; -import org.cbioportal.model.AlterationCountByGene; -import org.cbioportal.model.ClinicalAttribute; -import org.cbioportal.model.CaseListDataCount; -import org.cbioportal.model.ClinicalData; -import org.cbioportal.model.ClinicalDataCount; -import org.cbioportal.model.ClinicalDataCountItem; -import org.cbioportal.model.ClinicalEventTypeCount; -import org.cbioportal.model.GenePanelToGene; -import org.cbioportal.model.GenericAssayDataCountItem; -import org.cbioportal.model.GenomicDataCountItem; -import org.cbioportal.model.GenomicDataCount; -import org.cbioportal.model.CopyNumberCountByGene; -import org.cbioportal.model.MolecularProfile; -import org.cbioportal.model.PatientTreatment; -import org.cbioportal.model.Sample; -import org.cbioportal.model.SampleTreatment; -import org.cbioportal.model.StudyViewFilterContext; -import org.cbioportal.persistence.StudyViewRepository; -import org.cbioportal.persistence.enums.DataSource; -import org.cbioportal.persistence.helper.AlterationFilterHelper; -import org.cbioportal.persistence.helper.StudyViewFilterHelper; -import org.cbioportal.service.util.StudyViewColumnarServiceUtil; -import org.cbioportal.utils.config.annotation.ConditionalOnProperty; -import org.cbioportal.web.parameter.ClinicalDataType; -import org.cbioportal.web.parameter.GenericAssayDataBinFilter; -import org.cbioportal.web.parameter.GenericAssayDataFilter; -import org.cbioportal.web.parameter.GenomicDataBinFilter; -import org.cbioportal.web.parameter.GenomicDataFilter; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Repository; - -import java.util.Collections; -import java.util.EnumMap; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.stream.Collectors; - -@Repository -@ConditionalOnProperty(name = "clickhouse_mode", havingValue = "true") -public class StudyViewMyBatisRepository implements StudyViewRepository { - - private final StudyViewMapper studyViewMapper; - private Map> clinicalAttributesMap = new EnumMap<>(DataSource.class); - private Map> genericAssayProfilesMap = new EnumMap<>(DataSource.class); - - private static final List FILTERED_CLINICAL_ATTR_VALUES = Collections.emptyList(); - private final StudyViewMapper mapper; - - @Autowired - public StudyViewMyBatisRepository(StudyViewMapper mapper, StudyViewMapper studyViewMapper) { - this.mapper = mapper; - this.studyViewMapper = studyViewMapper; - } - - @Override - public List getFilteredSamples(StudyViewFilterContext studyViewFilterContext) { - return mapper.getFilteredSamples(createStudyViewFilterHelper(studyViewFilterContext)); - } - - @Override - public List getFilteredStudyIds(StudyViewFilterContext studyViewFilterContext) { - return mapper.getFilteredStudyIds(createStudyViewFilterHelper(studyViewFilterContext)); - } - - @Override - public List getMutatedGenes(StudyViewFilterContext studyViewFilterContext) { - return mapper.getMutatedGenes(createStudyViewFilterHelper(studyViewFilterContext), - AlterationFilterHelper.build(studyViewFilterContext.studyViewFilter().getAlterationFilter())); - } - - @Override - public List getCnaGenes(StudyViewFilterContext studyViewFilterContext) { - return mapper.getCnaGenes(createStudyViewFilterHelper(studyViewFilterContext), - AlterationFilterHelper.build(studyViewFilterContext.studyViewFilter().getAlterationFilter())); - } - - @Override - public List getStructuralVariantGenes(StudyViewFilterContext studyViewFilterContext) { - return mapper.getStructuralVariantGenes(createStudyViewFilterHelper(studyViewFilterContext), - AlterationFilterHelper.build(studyViewFilterContext.studyViewFilter().getAlterationFilter())); - } - - @Override - public List getClinicalDataCounts(StudyViewFilterContext studyViewFilterContext, List filteredAttributes) { - return mapper.getClinicalDataCounts(createStudyViewFilterHelper(studyViewFilterContext), - filteredAttributes, FILTERED_CLINICAL_ATTR_VALUES); - } - - @Override - public List getMolecularProfileSampleCounts(StudyViewFilterContext studyViewFilterContext) { - var sampleCounts = mapper.getMolecularProfileSampleCounts(createStudyViewFilterHelper(studyViewFilterContext)); - return StudyViewColumnarServiceUtil.mergeGenomicDataCounts(sampleCounts); - - } - - public StudyViewFilterHelper createStudyViewFilterHelper(StudyViewFilterContext studyViewFilterContext) { - return StudyViewFilterHelper.build( - studyViewFilterContext.studyViewFilter(), - getGenericAssayProfilesMap(), - studyViewFilterContext.customDataFilterSamples(), - studyViewFilterContext.involvedCancerStudies() - ); - } - - @Override - public List getClinicalAttributes() { - return mapper.getClinicalAttributes(); - } - - @Override - public List getGenericAssayProfiles() { - return mapper.getGenericAssayProfiles(); - } - - @Override - public List getFilteredMolecularProfilesByAlterationType(StudyViewFilterContext studyViewFilterContext, String alterationType) { - return studyViewMapper.getFilteredMolecularProfilesByAlterationType(createStudyViewFilterHelper(studyViewFilterContext), alterationType); - } - - @Override - public Map getClinicalAttributeDatatypeMap() { - if (clinicalAttributesMap.isEmpty()) { - buildClinicalAttributeNameMap(); - } - - Map attributeDatatypeMap = new HashMap<>(); - - clinicalAttributesMap - .get(DataSource.SAMPLE) - .forEach(attribute -> attributeDatatypeMap.put(attribute.getAttrId(), ClinicalDataType.SAMPLE)); - - clinicalAttributesMap - .get(DataSource.PATIENT) - .forEach(attribute -> attributeDatatypeMap.put(attribute.getAttrId(), ClinicalDataType.PATIENT)); - - return attributeDatatypeMap; - } - - @Override - public List getClinicalAttributesForStudies(List studyIds) { - return mapper.getClinicalAttributesForStudies(studyIds); - } - - @Override - public List getCaseListDataCountsPerStudy(StudyViewFilterContext studyViewFilterContext) { - return mapper.getCaseListDataCountsPerStudy(createStudyViewFilterHelper(studyViewFilterContext)); - } - - @Override - public List getSampleClinicalData(StudyViewFilterContext studyViewFilterContext, List attributeIds) { - return mapper.getSampleClinicalDataFromStudyViewFilter(createStudyViewFilterHelper(studyViewFilterContext), attributeIds); - } - - @Override - public List getPatientClinicalData(StudyViewFilterContext studyViewFilterContext, List attributeIds) { - return mapper.getPatientClinicalDataFromStudyViewFilter(createStudyViewFilterHelper(studyViewFilterContext), attributeIds); - } - - @Override - public Map getTotalProfiledCounts(StudyViewFilterContext studyViewFilterContext, String alterationType, List molecularProfiles) { - return mapper.getTotalProfiledCounts(createStudyViewFilterHelper(studyViewFilterContext), alterationType, molecularProfiles) - .stream() - .collect(Collectors.groupingBy(AlterationCountByGene::getHugoGeneSymbol, - Collectors.mapping(AlterationCountByGene::getNumberOfProfiledCases, Collectors.summingInt(Integer::intValue)))); - } - - @Override - public int getFilteredSamplesCount(StudyViewFilterContext studyViewFilterContext) { - return mapper.getFilteredSamplesCount(createStudyViewFilterHelper(studyViewFilterContext)); - } - - @Override - public int getFilteredPatientCount(StudyViewFilterContext studyViewFilterContext) { - return mapper.getFilteredPatientsCount(createStudyViewFilterHelper(studyViewFilterContext)); - } - - @Override - public Map> getMatchingGenePanelIds(StudyViewFilterContext studyViewFilterContext, String alterationType) { - return mapper.getMatchingGenePanelIds(createStudyViewFilterHelper(studyViewFilterContext), alterationType) - .stream() - .collect(Collectors.groupingBy(GenePanelToGene::getHugoGeneSymbol, - Collectors.mapping(GenePanelToGene::getGenePanelId, Collectors.toSet()))); - } - - @Override - public int getTotalProfiledCountsByAlterationType(StudyViewFilterContext studyViewFilterContext, String alterationType) { - return mapper.getTotalProfiledCountByAlterationType(createStudyViewFilterHelper(studyViewFilterContext), alterationType); - } - - @Override - public int getSampleProfileCountWithoutPanelData(StudyViewFilterContext studyViewFilterContext, String alterationType) { - return mapper.getSampleProfileCountWithoutPanelData(createStudyViewFilterHelper(studyViewFilterContext), alterationType); - } - - - @Override - public List getClinicalEventTypeCounts(StudyViewFilterContext studyViewFilterContext) { - return mapper.getClinicalEventTypeCounts(createStudyViewFilterHelper(studyViewFilterContext)); - } - - @Override - public List getPatientTreatments(StudyViewFilterContext studyViewFilterContext) { - return mapper.getPatientTreatments(createStudyViewFilterHelper(studyViewFilterContext)); - } - - @Override - public int getTotalPatientTreatmentCount(StudyViewFilterContext studyViewFilterContext) { - return mapper.getPatientTreatmentCounts(createStudyViewFilterHelper(studyViewFilterContext)); - } - - @Override - public List getSampleTreatments(StudyViewFilterContext studyViewFilterContext) { - return mapper.getSampleTreatmentCounts(createStudyViewFilterHelper(studyViewFilterContext)); - } - - @Override - public int getTotalSampleTreatmentCount(StudyViewFilterContext studyViewFilterContext) { - return mapper.getTotalSampleTreatmentCounts(createStudyViewFilterHelper(studyViewFilterContext)); - } - - @Override - public List getGenomicDataBinCounts(StudyViewFilterContext studyViewFilterContext, List genomicDataBinFilters) { - return mapper.getGenomicDataBinCounts(createStudyViewFilterHelper(studyViewFilterContext), genomicDataBinFilters); - } - - @Override - public List getGenericAssayDataBinCounts(StudyViewFilterContext studyViewFilterContext, List genericAssayDataBinFilters) { - return mapper.getGenericAssayDataBinCounts(createStudyViewFilterHelper(studyViewFilterContext), genericAssayDataBinFilters); - } - - private void buildClinicalAttributeNameMap() { - clinicalAttributesMap = this.getClinicalAttributes() - .stream() - .collect(Collectors.groupingBy(ca -> ca.getPatientAttribute().booleanValue() ? DataSource.PATIENT : DataSource.SAMPLE)); - } - - private void buildGenericAssayProfilesMap() { - genericAssayProfilesMap = this.getGenericAssayProfiles() - .stream() - .collect(Collectors.groupingBy(ca -> ca.getPatientLevel().booleanValue() ? DataSource.PATIENT : DataSource.SAMPLE)); - } - - private Map> getGenericAssayProfilesMap() { - if (genericAssayProfilesMap.isEmpty()) { - buildGenericAssayProfilesMap(); - } - return genericAssayProfilesMap; - } - - @Override - public List getCNACounts(StudyViewFilterContext studyViewFilterContext, List genomicDataFilters) { - return mapper.getCNACounts(createStudyViewFilterHelper(studyViewFilterContext), genomicDataFilters); - } - - @Override - public List getGenericAssayDataCounts(StudyViewFilterContext studyViewFilterContext, List genericAssayDataFilters) { - return mapper.getGenericAssayDataCounts(createStudyViewFilterHelper(studyViewFilterContext), genericAssayDataFilters); - } - - public Map getMutationCounts(StudyViewFilterContext studyViewFilterContext, GenomicDataFilter genomicDataFilter) { - return mapper.getMutationCounts(createStudyViewFilterHelper(studyViewFilterContext), genomicDataFilter); - } - - public List getMutationCountsByType(StudyViewFilterContext studyViewFilterContext, List genomicDataFilters) { - return mapper.getMutationCountsByType(createStudyViewFilterHelper(studyViewFilterContext), genomicDataFilters); - } - -} \ No newline at end of file diff --git a/src/main/java/org/cbioportal/persistence/mybatisclickhouse/config/PersistenceColumnarConfig.java b/src/main/java/org/cbioportal/persistence/mybatisclickhouse/config/PersistenceColumnarConfig.java deleted file mode 100644 index 7acea62ecec..00000000000 --- a/src/main/java/org/cbioportal/persistence/mybatisclickhouse/config/PersistenceColumnarConfig.java +++ /dev/null @@ -1,32 +0,0 @@ -package org.cbioportal.persistence.mybatisclickhouse.config; - -import org.cbioportal.persistence.mybatis.typehandler.SampleTypeTypeHandler; -import org.cbioportal.utils.config.annotation.ConditionalOnProperty; -import org.mybatis.spring.SqlSessionFactoryBean; -import org.mybatis.spring.annotation.MapperScan; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.context.ApplicationContext; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; - -import javax.sql.DataSource; -import java.io.IOException; - - -@Configuration -@ConditionalOnProperty(name = "clickhouse_mode", havingValue = "true") -@MapperScan(value= "org.cbioportal.persistence.mybatisclickhouse", sqlSessionFactoryRef ="sqlColumnarSessionFactory") -public class PersistenceColumnarConfig { - - @Bean("sqlColumnarSessionFactory") - public SqlSessionFactoryBean sqlColumnarSessionFactory(@Qualifier("clickhouseDataSource") DataSource dataSource, ApplicationContext applicationContext) throws IOException { - SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean(); - sessionFactory.setDataSource(dataSource); - sessionFactory.setMapperLocations( - applicationContext.getResources("classpath:org/cbioportal/persistence/mybatisclickhouse/*.xml") - ); - sessionFactory.setTypeHandlers(new SampleTypeTypeHandler()); - return sessionFactory; - } - -} diff --git a/src/main/java/org/cbioportal/persistence/util/CacheEventLogger.java b/src/main/java/org/cbioportal/persistence/util/CacheEventLogger.java deleted file mode 100644 index d7dd14d1374..00000000000 --- a/src/main/java/org/cbioportal/persistence/util/CacheEventLogger.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (c) 2019 Memorial Sloan-Kettering Cancer Center. - * - * This library is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS - * FOR A PARTICULAR PURPOSE. The software and documentation provided hereunder - * is on an "as is" basis, and Memorial Sloan-Kettering Cancer Center has no - * obligations to provide maintenance, support, updates, enhancements or - * modifications. In no event shall Memorial Sloan-Kettering Cancer Center be - * liable to any party for direct, indirect, special, incidental or - * consequential damages, including lost profits, arising out of the use of this - * software and its documentation, even if Memorial Sloan-Kettering Cancer - * Center has been advised of the possibility of such damage. - */ - -/* - * This file is part of cBioPortal. - * - * cBioPortal is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -package org.cbioportal.persistence.util; - -import org.ehcache.event.*; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class CacheEventLogger implements CacheEventListener { - - private static final Logger log = LoggerFactory.getLogger(CacheEventLogger.class); - - // this is to allow spring to inject EhcacheStatistics via MethodInvokingFactoryBean - private static EhcacheStatistics ehcacheStatistics; - public static void setCacheStatistics(EhcacheStatistics ecs) - { - ehcacheStatistics = ecs; - } - - @Override - public void onEvent(CacheEvent cacheEvent) { - if (log.isDebugEnabled()) { - log.debug("CACHE_EVENT:\n" + - "\tTYPE: " + cacheEvent.getType() + "\n" + - "\tKEY: " + cacheEvent.getKey() + "\n" + - "\tVALUE: " + cacheEvent.getNewValue() + "\n" + - "CACHE_EVENT<>\n"); - log.debug(ehcacheStatistics.getCacheStatistics()); - } - } -} diff --git a/src/main/java/org/cbioportal/persistence/util/CacheUtils.java b/src/main/java/org/cbioportal/persistence/util/CacheUtils.java deleted file mode 100644 index 46b33334ab7..00000000000 --- a/src/main/java/org/cbioportal/persistence/util/CacheUtils.java +++ /dev/null @@ -1,8 +0,0 @@ -package org.cbioportal.persistence.util; - -import java.util.List; - -public interface CacheUtils { - List getKeys(String cacheName); - void evictByPattern(String cacheName, String pattern); -} diff --git a/src/main/java/org/cbioportal/persistence/util/CustomEhcachingProvider.java b/src/main/java/org/cbioportal/persistence/util/CustomEhcachingProvider.java deleted file mode 100644 index b4591cc3600..00000000000 --- a/src/main/java/org/cbioportal/persistence/util/CustomEhcachingProvider.java +++ /dev/null @@ -1,298 +0,0 @@ -/* - * Copyright (c) 2019 Memorial Sloan-Kettering Cancer Center. - * - * This library is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS - * FOR A PARTICULAR PURPOSE. The software and documentation provided hereunder - * is on an "as is" basis, and Memorial Sloan-Kettering Cancer Center has no - * obligations to provide maintenance, support, updates, enhancements or - * modifications. In no event shall Memorial Sloan-Kettering Cancer Center be - * liable to any party for direct, indirect, special, incidental or - * consequential damages, including lost profits, arising out of the use of this - * software and its documentation, even if Memorial Sloan-Kettering Cancer - * Center has been advised of the possibility of such damage. - */ - -/* - * This file is part of cBioPortal. - * - * cBioPortal is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -package org.cbioportal.persistence.util; - -import java.io.*; -import java.net.URL; -import java.util.*; -import javax.cache.CacheManager; -import org.ehcache.config.CacheConfiguration; -import org.ehcache.config.builders.CacheConfigurationBuilder; -import org.ehcache.config.builders.ResourcePoolsBuilder; -import org.ehcache.config.Configuration; -import org.ehcache.config.units.MemoryUnit; -import org.ehcache.xml.XmlConfiguration; -import org.ehcache.core.config.DefaultConfiguration; -import org.ehcache.jsr107.EhcacheCachingProvider; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; -import org.ehcache.impl.config.persistence.DefaultPersistenceConfiguration; -import org.cbioportal.persistence.CacheEnabledConfig; - -public class CustomEhcachingProvider extends EhcacheCachingProvider { - - private static final Logger LOG = LoggerFactory.getLogger(CustomEhcachingProvider.class); - - @Value("${ehcache.xml_configuration:/ehcache.xml}") - private String xmlConfigurationFile; - - @Value("${persistence.cache_type:no-cache}") - private String cacheType; - - @Value("${ehcache.general_repository_cache.max_mega_bytes_heap:1024}") - private Integer generalRepositoryCacheMaxMegaBytes; - - @Value("${ehcache.static_repository_cache_one.max_mega_bytes_heap:30}") - private Integer staticRepositoryCacheOneMaxMegaBytes; - - @Value("${ehcache.persistence_path:/tmp/}") - private String persistencePath; - - @Value("${ehcache.general_repository_cache.max_mega_bytes_local_disk:4096}") - private Integer generalRepositoryCacheMaxMegaBytesLocalDisk; - - @Value("${ehcache.static_repository_cache_one.max_mega_bytes_local_disk:32}") - private Integer staticRepositoryCacheOneMaxMegaBytesLocalDisk; - - @Autowired - private CacheEnabledConfig cacheEnabledConfig; - - @Override - public CacheManager getCacheManager() { - - CacheManager toReturn = null; - try { - if (cacheEnabledConfig.enableCache(cacheType)) { - detectCacheConfigurationErrorsAndLog(); - LOG.info("Caching is enabled, using '" + xmlConfigurationFile + "' for configuration"); - XmlConfiguration xmlConfiguration = new XmlConfiguration(getClass().getResource(xmlConfigurationFile)); - - // initilize configurations specific to each individual cache (by template) - // to add new cache - create cache configuration with its own resource pool + template - ResourcePoolsBuilder generalRepositoryCacheResourcePoolsBuilder = ResourcePoolsBuilder.newResourcePoolsBuilder(); - ResourcePoolsBuilder staticRepositoryCacheOneResourcePoolsBuilder = ResourcePoolsBuilder.newResourcePoolsBuilder(); - - // Set up heap resources as long as not disk-only - if (!cacheType.equalsIgnoreCase(CacheEnabledConfig.EHCACHE_DISK)) { - generalRepositoryCacheResourcePoolsBuilder = generalRepositoryCacheResourcePoolsBuilder.heap(generalRepositoryCacheMaxMegaBytes, MemoryUnit.MB); - staticRepositoryCacheOneResourcePoolsBuilder = staticRepositoryCacheOneResourcePoolsBuilder.heap(staticRepositoryCacheOneMaxMegaBytes, MemoryUnit.MB); - } - // Set up disk resources as long as not heap-only - // will default to using /tmp -- let Ehcache throw exception if persistence path is invalid (locked or otherwise) - if (!cacheType.equalsIgnoreCase(CacheEnabledConfig.EHCACHE_HEAP)) { - generalRepositoryCacheResourcePoolsBuilder = generalRepositoryCacheResourcePoolsBuilder.disk(generalRepositoryCacheMaxMegaBytesLocalDisk, MemoryUnit.MB); - staticRepositoryCacheOneResourcePoolsBuilder = staticRepositoryCacheOneResourcePoolsBuilder.disk(staticRepositoryCacheOneMaxMegaBytesLocalDisk, MemoryUnit.MB); - } - - CacheConfiguration generalRepositoryCacheConfiguration = xmlConfiguration.newCacheConfigurationBuilderFromTemplate("RepositoryCacheTemplate", - Object.class, Object.class, generalRepositoryCacheResourcePoolsBuilder) - .withSizeOfMaxObjectGraph(Long.MAX_VALUE) - .withSizeOfMaxObjectSize(Long.MAX_VALUE, MemoryUnit.B) - .build(); - CacheConfiguration staticRepositoryCacheOneConfiguration = xmlConfiguration.newCacheConfigurationBuilderFromTemplate("RepositoryCacheTemplate", - Object.class, Object.class, staticRepositoryCacheOneResourcePoolsBuilder) - .withSizeOfMaxObjectGraph(Long.MAX_VALUE) - .withSizeOfMaxObjectSize(Long.MAX_VALUE, MemoryUnit.B) - .build(); - - // places caches in a map which will be used to create cache manager - Map> caches = new HashMap<>(); - caches.put("GeneralRepositoryCache", generalRepositoryCacheConfiguration); - caches.put("StaticRepositoryCacheOne", staticRepositoryCacheOneConfiguration); - - Configuration configuration = null; - if (cacheType.equalsIgnoreCase(CacheEnabledConfig.EHCACHE_HEAP)) { - configuration = new DefaultConfiguration(caches, this.getDefaultClassLoader()); - } else { // add persistence configuration if cacheType is either disk-only or hybrid - File persistenceFile = new File(persistencePath); - configuration = new DefaultConfiguration(caches, this.getDefaultClassLoader(), new DefaultPersistenceConfiguration(persistenceFile)); - } - - toReturn = this.getCacheManager(this.getDefaultURI(), configuration); - } else { - LOG.info("Caching is disabled"); - // we can not really disable caching, - // we can not make a cache of 0 objects, - // and we can not make a heap of memory size 0, so make a tiny heap - CacheConfiguration generalRepositoryCacheConfiguration = CacheConfigurationBuilder.newCacheConfigurationBuilder(Object.class, - Object.class, - ResourcePoolsBuilder.newResourcePoolsBuilder().heap(1, MemoryUnit.B)).build(); - CacheConfiguration staticRepositoryCacheOneConfiguration = CacheConfigurationBuilder.newCacheConfigurationBuilder(Object.class, - Object.class, - ResourcePoolsBuilder.newResourcePoolsBuilder().heap(1, MemoryUnit.B)).build(); - - Map> caches = new HashMap<>(); - caches.put("GeneralRepositoryCache", generalRepositoryCacheConfiguration); - caches.put("StaticRepositoryCacheOne", staticRepositoryCacheOneConfiguration); - - Configuration configuration = new DefaultConfiguration(caches, this.getDefaultClassLoader()); - - toReturn = this.getCacheManager(this.getDefaultURI(), configuration); - } - } - catch (Exception e) { - LOG.error(e.getClass().getName() + ": " + e.getMessage()); - StringWriter stackTrace = new StringWriter(); - e.printStackTrace(new PrintWriter(stackTrace)); - LOG.error(stackTrace.toString()); - } - return toReturn; - } - - public void detectCacheConfigurationErrorsAndLog() { - String MESSAGE_PREFIX = "Errors detected during configuration of Ehcache:"; - StringBuffer messages = new StringBuffer(MESSAGE_PREFIX); - boolean usesHeap = false; - boolean usesDisk = false; - switch (this.cacheType.trim().toLowerCase()) { - case "no-cache": - break; - case "ehcache-heap": - usesHeap = true; - break; - case "ehcache-disk": - usesDisk = true; - break; - case "ehcache-hybrid": - usesHeap = true; - usesDisk = true; - break; - case "redis": - break; // we should not be in here in this case - default: - messages.append("\n property persistence.cache_type has value (") - .append(cacheType) - .append(") which is not a recognized value"); - } - if (usesDisk || usesHeap) { - if (xmlConfigurationFile == null || xmlConfigurationFile.trim().length() == 0) { - messages.append("\n property ehcache.xml_configuration is required but is unset"); - } else { - URL configFileURL = getClass().getResource(xmlConfigurationFile); - if (configFileURL == null) { - messages.append("\n property ehcache.xml_configuration has value (") - .append(xmlConfigurationFile) - .append(") but this resource is not available to the classloader"); - } else { - boolean readable = false; - InputStream configFileInputStream = null; - try { - configFileInputStream = configFileURL.openStream(); - configFileInputStream.read(); - configFileInputStream.close(); - readable = true; - } catch (IOException e) { - } finally { - try { - configFileInputStream.close(); - } catch (IOException e) { - LOG.error("UNABLE TO CLOSE configFileURLInputStream"); - } - } - - if (!readable) { - messages.append("\n property ehcache.xml_configuration has value (") - .append(xmlConfigurationFile) - .append(") but an attempt to read from this resource failed"); - } - } - } - } - if (usesDisk) { - if (generalRepositoryCacheMaxMegaBytesLocalDisk == null) { - messages.append("\n property ehcache.general_repository_cache.max_mega_bytes_local_disk is required to be set, but has no value"); - } else { - if (generalRepositoryCacheMaxMegaBytesLocalDisk <= 0) { - messages.append("\n property ehcache.general_repository_cache.max_mega_bytes_local_disk must be greater than zero but is not"); - } - } - if (staticRepositoryCacheOneMaxMegaBytesLocalDisk == null) { - messages.append("\n property ehcache.static_repository_cache_one.max_mega_bytes_local_disk is required to be set, but has no value"); - } else { - if (staticRepositoryCacheOneMaxMegaBytesLocalDisk <= 0) { - messages.append("\n property ehcache.static_repository_cache_one.max_mega_bytes_local_disk must be greater than zero but is not"); - } - } - if (persistencePath == null || persistencePath.trim().length() == 0) { - messages.append("\n property ehcache.persistence_path is required when using a disk resource but is unset"); - } else { - File persistenceDirectory = new File(persistencePath); - boolean accessible = false; - try { - if (persistenceDirectory.isDirectory() && persistenceDirectory.canWrite()) { - accessible = true; - } - } catch (SecurityException e) { - } - if (!accessible) { - messages.append("\n property ehcache.persistence_path has value (") - .append(persistencePath) - .append(") but this path does not exist or is not an accessible directory"); - } - } - } - if (usesHeap) { - if (generalRepositoryCacheMaxMegaBytes == null) { - messages.append("\n property ehcache.general_repository_cache.max_mega_bytes_heap is required to be set, but has no value"); - } else { - if (generalRepositoryCacheMaxMegaBytes <= 0) { - messages.append("\n property ehcache.general_repository_cache.max_mega_bytes_heap must be greater than zero but is not"); - } - } - if (staticRepositoryCacheOneMaxMegaBytes == null) { - messages.append("\n property ehcache.static_repository_cache_one.max_mega_bytes_heap is required to be set, but has no value"); - } else { - if (staticRepositoryCacheOneMaxMegaBytes <= 0) { - messages.append("\n property ehcache.static_repository_cache_one.max_mega_bytes_heap must be greater than zero but is not"); - } - } - } - if (usesHeap && usesDisk) { - if (generalRepositoryCacheMaxMegaBytesLocalDisk != null - && generalRepositoryCacheMaxMegaBytes != null - && generalRepositoryCacheMaxMegaBytesLocalDisk <= generalRepositoryCacheMaxMegaBytes) { - messages.append("\n property ehcache.general_repository_cache.max_mega_bytes_heap must be set to a value less than the value of "); - messages.append("property ehcache.general_repository_cache.max_mega_bytes_local_disk, however "); - messages.append(generalRepositoryCacheMaxMegaBytes); - messages.append(" is not less than "); - messages.append(generalRepositoryCacheMaxMegaBytesLocalDisk); - } - if (staticRepositoryCacheOneMaxMegaBytesLocalDisk != null - && staticRepositoryCacheOneMaxMegaBytes != null - && staticRepositoryCacheOneMaxMegaBytesLocalDisk <= staticRepositoryCacheOneMaxMegaBytes) { - messages.append("\n property ehcache.static_repository_cache_one.max_mega_bytes_heap must be set to a value less than the value of "); - messages.append("property ehcache.static_repository_cache_one.max_mega_bytes_local_disk, however "); - messages.append(staticRepositoryCacheOneMaxMegaBytes); - messages.append(" is not less than "); - messages.append(staticRepositoryCacheOneMaxMegaBytesLocalDisk); - } - } - if (messages.length() > MESSAGE_PREFIX.length()) { - LOG.error(messages.toString()); - LOG.error("because of Ehcache configuration errors, it is likely that an exception will be thrown during startup. Recent observed exceptions contain the string" - + " \"Provider org.redisson.jcache.JCachingProvider not a subtype\" even though the problem is in the Ehcache configuration settings."); - } - } -} diff --git a/src/main/java/org/cbioportal/persistence/util/CustomKeyGenerator.java b/src/main/java/org/cbioportal/persistence/util/CustomKeyGenerator.java deleted file mode 100644 index 948d5d344c5..00000000000 --- a/src/main/java/org/cbioportal/persistence/util/CustomKeyGenerator.java +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright (c) 2019 Memorial Sloan-Kettering Cancer Center. - * - * This library is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS - * FOR A PARTICULAR PURPOSE. The software and documentation provided hereunder - * is on an "as is" basis, and Memorial Sloan-Kettering Cancer Center has no - * obligations to provide maintenance, support, updates, enhancements or - * modifications. In no event shall Memorial Sloan-Kettering Cancer Center be - * liable to any party for direct, indirect, special, incidental or - * consequential damages, including lost profits, arising out of the use of this - * software and its documentation, even if Memorial Sloan-Kettering Cancer - * Center has been advised of the possibility of such damage. - */ - -/* - * This file is part of cBioPortal. - * - * cBioPortal is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -package org.cbioportal.persistence.util; - -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; -import org.cbioportal.model.CancerStudy; -import org.cbioportal.model.util.Select; -import org.cbioportal.persistence.CacheEnabledConfig; -import org.cbioportal.persistence.StudyRepository; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.cache.interceptor.KeyGenerator; -import org.springframework.util.DigestUtils; - -import java.lang.reflect.Method; -import java.util.Arrays; -import java.util.stream.Collectors; - - -public class CustomKeyGenerator implements KeyGenerator { - public static final String CACHE_KEY_PARAM_DELIMITER = "_"; - public static final int PARAM_LENGTH_HASH_LIMIT = 1024; - - @Autowired - private CacheEnabledConfig cacheEnabledConfig; - - @Autowired - private StudyRepository studyRepository; - - private static final ObjectMapper mapper = new ObjectMapper(); - - private static final Logger LOG = LoggerFactory.getLogger(CustomKeyGenerator.class); - - public Object generate(Object target, Method method, Object... params) { - if (!cacheEnabledConfig.isEnabled() && !cacheEnabledConfig.isEnabledClickhouse()) { - return ""; - } - String key = target.getClass().getSimpleName() + CACHE_KEY_PARAM_DELIMITER - + method.getName() + CACHE_KEY_PARAM_DELIMITER - + Arrays.stream(params) - .map(this::exceptionlessWrite) - .collect(Collectors.joining(CACHE_KEY_PARAM_DELIMITER)); - LOG.debug("Created key: " + key); - return key; - } - - private String exceptionlessWrite(Object toSerialize) { - if (toSerialize instanceof Select && ((Select) toSerialize).hasAll()) { - // Select implements Iterable, but Select.All throws an exception - // when you call iterator(), which breaks Jackson, so we need some custom logic - return "Select.ALL"; - } - try { - String json = mapper.writeValueAsString(toSerialize); - if (json.length() > PARAM_LENGTH_HASH_LIMIT) { - // To allow study-specific cache eviction, extract relevant - // study identifiers and add these to the cache keys. - String matchedStudyIds = studyRepository.getAllStudies(null, "SUMMARY", null, null, null, null) - .stream() - .map(CancerStudy::getCancerStudyIdentifier) - .distinct() - .filter(json::contains) - .collect(Collectors.joining(CACHE_KEY_PARAM_DELIMITER)); - return matchedStudyIds + CACHE_KEY_PARAM_DELIMITER + DigestUtils.md5DigestAsHex(json.getBytes()); - } else { - // leave short keys intact, but remove semicolons to make things look cleaner in redis - return json.replaceAll(":", CACHE_KEY_PARAM_DELIMITER); - } - } catch (JsonProcessingException e) { - LOG.error("Could not serialize param to string: ", e); - return ""; - } - } -} diff --git a/src/main/java/org/cbioportal/persistence/util/CustomRedisCache.java b/src/main/java/org/cbioportal/persistence/util/CustomRedisCache.java deleted file mode 100644 index 5036bdd6e9a..00000000000 --- a/src/main/java/org/cbioportal/persistence/util/CustomRedisCache.java +++ /dev/null @@ -1,197 +0,0 @@ -package org.cbioportal.persistence.util; - -import org.redisson.api.RedissonClient; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.cache.Cache; -import org.springframework.cache.support.AbstractValueAdaptingCache; -import org.springframework.cache.support.SimpleValueWrapper; -import org.springframework.lang.Nullable; - -import java.io.*; -import java.util.concurrent.Callable; -import java.util.concurrent.TimeUnit; -import java.util.zip.GZIPInputStream; -import java.util.zip.GZIPOutputStream; - -public class CustomRedisCache extends AbstractValueAdaptingCache { - private static final Logger LOG = LoggerFactory.getLogger(CustomRedisCache.class); - public static final String DELIMITER = ":"; - public static final int INFINITE_TTL = -1; - - private final String name; - private final long ttlMinutes; - private final RedissonClient redissonClient; - - /** - * Create a new ConcurrentMapCache with the specified name. - * @param name the name of the cache - */ - public CustomRedisCache(String name, RedissonClient client, long ttlMinutes) { - super(true); - this.name = name; - this.redissonClient = client; - this.ttlMinutes = ttlMinutes; - } - - @Override - public final String getName() { - return name; - } - - public final RedissonClient getNativeCache() { - return this.redissonClient; - } - - @Override - @Nullable - protected Object lookup(Object key) { - Object value = this.redissonClient.getBucket(name + DELIMITER + key).get(); - if (value != null){ - value = fromStoreValue(value); - asyncRefresh(key); - } - return value; - } - - private void asyncRefresh(Object key) { - if (ttlMinutes != INFINITE_TTL) { - this.redissonClient.getBucket(name + DELIMITER + key).expireAsync(ttlMinutes, TimeUnit.MINUTES); - } - } - - @Override - @Nullable - public T get(Object key, Callable valueLoader) { - Object zippedValue = this.redissonClient.getBucket(name + DELIMITER + key).get(); - T value = null; - if (zippedValue != null) { - value = (T) fromStoreValue(zippedValue); - asyncRefresh(key); - } - try { - return value == null ? valueLoader.call() : value; - } catch (Exception ex) { - throw new ValueRetrievalException(key, valueLoader, ex); - } - } - - @Override - public void put(Object key, @Nullable Object value) { - if (value == null) { - LOG.warn("Storing null value for key {} in cache. That's probably not great.", key); - } - if (ttlMinutes == INFINITE_TTL) { - this.redissonClient.getBucket(name + DELIMITER + key).setAsync(toStoreValue(value)); - } else { - this.redissonClient.getBucket(name + DELIMITER + key).setAsync(toStoreValue(value), ttlMinutes, TimeUnit.MINUTES); - } - } - - @Override - @Nullable - public ValueWrapper putIfAbsent(Object key, @Nullable Object value) { - Object cached = lookup(key); - if (cached != null) { - return toValueWrapper(cached); - } else { - put(key, value); - } - return toValueWrapper(value); - } - - @Override - public void evict(Object pattern) { - evictIfPresent(pattern); - } - - @Override - public boolean evictIfPresent(Object pattern) { - // Pattern is expected to be a regular expression - if (pattern instanceof String) { - String[] keys = redissonClient.getKeys().getKeysStream() - .filter(key -> key.startsWith(name)) - .filter(key -> key.matches((String) pattern)) - .toArray(String[]::new); - // Calling delete() with empty array causes an error in the Redisson client. - if (keys.length > 0) - return redissonClient.getKeys().delete(keys) > 0; - } else { - LOG.warn("Pattern passed for cache key eviction is not of String type. Cache eviction could not be performed."); - } - return false; - } - - @Override - public void clear() { - this.redissonClient.getKeys().deleteByPattern(name + DELIMITER + "*"); - } - - @Override - public boolean invalidate() { - return this.redissonClient.getKeys().deleteByPattern(name + DELIMITER + "*") > 0; - } - - @Override - protected Object toStoreValue(@Nullable Object userValue) { - if (userValue == null) { - return null; - } - - ByteArrayOutputStream byteOut = new ByteArrayOutputStream(); - ObjectOutputStream objectOut; - try { - // serialize to byte array - objectOut = new ObjectOutputStream(byteOut); - objectOut.writeObject(userValue); - objectOut.flush(); - byte[] uncompressedByteArray = byteOut.toByteArray(); - - // compress byte array - byteOut = new ByteArrayOutputStream(uncompressedByteArray.length); - GZIPOutputStream g = new GZIPOutputStream(byteOut); - g.write(uncompressedByteArray); - g.close(); - return byteOut.toByteArray(); - } catch (IOException e) { - LOG.warn("Error compressing object for cache: ", e); - return null; - } - } - - @Override - protected Object fromStoreValue(@Nullable Object storeValue) { - if (storeValue == null) { - return null; - } - - byte[] bytes = (byte[]) storeValue; - ByteArrayInputStream byteIn = new ByteArrayInputStream(bytes); - ByteArrayOutputStream byteOut = new ByteArrayOutputStream(); - GZIPInputStream gzipIn; - try { - // inflate to byte array - gzipIn = new GZIPInputStream(byteIn); - byte[] buffer = new byte[1024]; - int len; - while ((len = gzipIn.read(buffer)) != -1) { - byteOut.write(buffer, 0, len); - } - byte[] unzippedBytes = byteOut.toByteArray(); - - // deserialize byte array to object - byteIn = new ByteArrayInputStream(unzippedBytes); - ObjectInputStream oi = new ObjectInputStream(byteIn); - return oi.readObject(); - } catch (IOException | ClassNotFoundException e) { - LOG.warn("Error inflating object from cache: ", e); - return null; - } - } - - @Nullable - @Override - protected Cache.ValueWrapper toValueWrapper(@Nullable Object storeValue) { - return (storeValue != null ? new SimpleValueWrapper(storeValue) : null); - } -} diff --git a/src/main/java/org/cbioportal/persistence/util/CustomRedisCacheManager.java b/src/main/java/org/cbioportal/persistence/util/CustomRedisCacheManager.java deleted file mode 100644 index 0c5cdb93dcd..00000000000 --- a/src/main/java/org/cbioportal/persistence/util/CustomRedisCacheManager.java +++ /dev/null @@ -1,57 +0,0 @@ -package org.cbioportal.persistence.util; - -import jakarta.validation.constraints.NotNull; -import org.redisson.api.RedissonClient; -import org.springframework.cache.Cache; -import org.springframework.cache.CacheManager; - -import java.util.Collection; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; - - -public class CustomRedisCacheManager implements CacheManager { - private final ConcurrentMap caches = new ConcurrentHashMap<>(); - private final RedissonClient client; - private final long ttlInMins; - - public CustomRedisCacheManager(RedissonClient client, long ttlInMins) { - this.client = client; - this.ttlInMins = ttlInMins; - } - - /** - * Get the cache associated with the given name. - *

Note that the cache may be lazily created at runtime if the - * native provider supports it. - * - * @param name the cache identifier (must not be {@code null}) - * @return the associated cache, or {@code null} if such a cache - * does not exist or could be not created - */ - @Override - public Cache getCache(String name) { - // !name.toLowerCase().contains("static") is a hack. Sometimes spring calls this getCache method from - // a place I can't control, so I needed a way in this method to determine whether or not the cache - // it's getting should have a ttl. - // In practice, any cache we have that is static should not expire. - // (I mean, we have two caches, so this isn't rocket science) - return getCache(name, !name.toLowerCase().contains("static")); - } - - @NotNull - public Cache getCache(String name, boolean expires) { - long clientTTLInMinutes = expires ? ttlInMins : CustomRedisCache.INFINITE_TTL; - return caches.computeIfAbsent(name, k -> new CustomRedisCache(name, client, clientTTLInMinutes)); - } - - /** - * Get a collection of the cache names known by this manager. - * - * @return the names of all caches known by the cache manager - */ - @Override - public Collection getCacheNames() { - return caches.keySet(); - } -} diff --git a/src/main/java/org/cbioportal/persistence/util/CustomRedisCachingProvider.java b/src/main/java/org/cbioportal/persistence/util/CustomRedisCachingProvider.java deleted file mode 100644 index 88b6aaa79c3..00000000000 --- a/src/main/java/org/cbioportal/persistence/util/CustomRedisCachingProvider.java +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright (c) 2020 Memorial Sloan-Kettering Cancer Center. - * - * This library is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS - * FOR A PARTICULAR PURPOSE. The software and documentation provided hereunder - * is on an "as is" basis, and Memorial Sloan-Kettering Cancer Center has no - * obligations to provide maintenance, support, updates, enhancements or - * modifications. In no event shall Memorial Sloan-Kettering Cancer Center be - * liable to any party for direct, indirect, special, incidental or - * consequential damages, including lost profits, arising out of the use of this - * software and its documentation, even if Memorial Sloan-Kettering Cancer - * Center has been advised of the possibility of such damage. - */ - -/* - * This file is part of cBioPortal. - * - * cBioPortal is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -package org.cbioportal.persistence.util; - -import org.redisson.Redisson; -import org.redisson.api.RedissonClient; -import org.redisson.config.Config; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.cache.Cache; -import org.springframework.cache.CacheManager; - -public class CustomRedisCachingProvider { - - private static final Logger LOG = LoggerFactory.getLogger(CustomRedisCachingProvider.class); - - @Value("${redis.name:cbioportal}") - private String redisName; - - @Value("${redis.leader_address}") - private String leaderAddress; - - @Value("${redis.follower_address}") - private String followerAddress; - - @Value("${redis.database}") - private Integer database; - - @Value("${redis.password}") - private String password; - - @Value("${redis.ttl_mins:10000}") - private Long expiryMins; - - @Value("${redis.clear_on_startup:true}") - private boolean clearOnStartup; - - public RedissonClient getRedissonClient() { - if (leaderAddress == null || "".equals(leaderAddress)) { - return null; - } - - Config config = new Config(); - LOG.debug("leaderAddress: " + leaderAddress); - LOG.debug("followerAddress: " + followerAddress); - config.useMasterSlaveServers() - .setMasterAddress(leaderAddress) - .addSlaveAddress(followerAddress) - .setDatabase(database) - .setPassword(password); - - RedissonClient redissonClient = Redisson.create(config); - LOG.debug("Created Redisson Client: " + redissonClient); - return redissonClient; - } - - public CacheManager getCacheManager(RedissonClient redissonClient) { - CustomRedisCacheManager manager = new CustomRedisCacheManager(redissonClient, expiryMins); - - if (clearOnStartup) { - Cache generalCache = manager.getCache(redisName + "GeneralRepositoryCache"); - if(generalCache != null) { - generalCache.clear(); - } - - Cache staticRepositoryCache = manager.getCache(redisName + "StaticRepositoryCacheOne"); - if(staticRepositoryCache != null) { - staticRepositoryCache.clear(); - } - } - return manager; - } -} diff --git a/src/main/java/org/cbioportal/persistence/util/EhCacheUtils.java b/src/main/java/org/cbioportal/persistence/util/EhCacheUtils.java deleted file mode 100644 index b8226ec0f80..00000000000 --- a/src/main/java/org/cbioportal/persistence/util/EhCacheUtils.java +++ /dev/null @@ -1,46 +0,0 @@ -package org.cbioportal.persistence.util; - - -import jakarta.annotation.PostConstruct; -import org.cbioportal.utils.config.annotation.ConditionalOnProperty; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -import javax.cache.CacheManager; -import java.util.ArrayList; -import java.util.List; - -@Component -@ConditionalOnProperty(name = "persistence.cache_type", havingValue = {"ehcache-heap", "ehcache-disk", "ehcache-hybrid"}) -public class EhCacheUtils implements CacheUtils { - - @Autowired - private CustomEhcachingProvider customEhcachingProvider; - private CacheManager cacheManager; - - @PostConstruct - public void init() { - this.cacheManager = customEhcachingProvider.getCacheManager(); - } - - @Override - public List getKeys(String cacheName) throws IllegalArgumentException { - javax.cache.Cache cache = cacheManager.getCache(cacheName); - if (cache == null) { - throw new IllegalArgumentException("Cannot find cache with name '" + cacheName + "'"); - } - List keysInCache = new ArrayList<>(); - cache.iterator().forEachRemaining(entry -> keysInCache.add(entry.getKey())); - return keysInCache; - } - - @Override - public void evictByPattern(String cacheName, String pattern) { - javax.cache.Cache cache = cacheManager.getCache(cacheName); - this.getKeys(cacheName).stream() - .filter(key -> key.matches(pattern)) - .forEach(key -> { - cache.remove(key); - }); - } -} diff --git a/src/main/java/org/cbioportal/persistence/util/EhcacheStatistics.java b/src/main/java/org/cbioportal/persistence/util/EhcacheStatistics.java deleted file mode 100644 index bbf5d273ed9..00000000000 --- a/src/main/java/org/cbioportal/persistence/util/EhcacheStatistics.java +++ /dev/null @@ -1,147 +0,0 @@ -/* - * Copyright (c) 2019 Memorial Sloan-Kettering Cancer Center. - * - * This library is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS - * FOR A PARTICULAR PURPOSE. The software and documentation provided hereunder - * is on an "as is" basis, and Memorial Sloan-Kettering Cancer Center has no - * obligations to provide maintenance, support, updates, enhancements or - * modifications. In no event shall Memorial Sloan-Kettering Cancer Center be - * liable to any party for direct, indirect, special, incidental or - * consequential damages, including lost profits, arising out of the use of this - * software and its documentation, even if Memorial Sloan-Kettering Cancer - * Center has been advised of the possibility of such damage. - */ - -/* - * This file is part of cBioPortal. - * - * cBioPortal is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -package org.cbioportal.persistence.util; - -import jakarta.annotation.PostConstruct; -import org.cbioportal.utils.config.annotation.ConditionalOnProperty; -import org.ehcache.core.statistics.*; -import org.ehcache.config.ResourceType; -import org.ehcache.impl.internal.statistics.DefaultStatisticsService; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -import java.util.Map; - -@Component -@ConditionalOnProperty(name = "persistence.cache_type", havingValue = {"ehcache-heap", "ehcache-disk", "ehcache-hybrid"}) -public class EhcacheStatistics { - - private static String TIER_NOT_IN_USE = "Tier not in use"; - - private static double BYTES_IN_MB = 1048576.0; - private static double BYTES_IN_GB = 1073741824.0; - - @Autowired - private CustomEhcachingProvider customEhcachingProvider; - - private javax.cache.CacheManager cacheManager; - private DefaultStatisticsService statisticsService; - - @PostConstruct - public void initializeStatisticsService () { - try { - cacheManager = customEhcachingProvider.getCacheManager(); - statisticsService = new DefaultStatisticsService(); - for (String cacheName : cacheManager.getCacheNames()) { - javax.cache.Cache cache = cacheManager.getCache(cacheName); - org.ehcache.Cache ehcache = (org.ehcache.Cache)cache.unwrap(org.ehcache.Cache.class); - statisticsService.cacheAdded(cacheName, ehcache); - } - } - catch (Exception e) { - e.printStackTrace(); - } - } - - public String getCacheStatistics() { - StringBuilder builder = new StringBuilder(); - builder.append("\n\nCACHE_STATISTICS START\n\n"); - for (String cacheName : cacheManager.getCacheNames()) { - builder.append("Cache: " + cacheName + "\n"); - builder.append("Allocated (heap): " + getAllocatedBytes(cacheName, ResourceType.Core.HEAP) + "\n"); - builder.append("Occupied (heap): " + getOccupiedBytes(cacheName, "OnHeap", ResourceType.Core.HEAP) + "\n"); - builder.append("Allocated (disk): " + getAllocatedBytes(cacheName, ResourceType.Core.DISK) + "\n"); - builder.append("Occupied (disk): " + getOccupiedBytes(cacheName, "Disk", ResourceType.Core.DISK) + "\n"); - builder.append("\n"); - } - builder.append("CACHE_STATISTICS END\n"); - return builder.toString(); - } - - private String getAllocatedBytes(String cacheName, ResourceType.Core resourceType) - { - try { - org.ehcache.Cache ehcache = getEhcache(cacheName); - return (getAllocatedBytes(ehcache, resourceType) + getAllocatedUnit(ehcache, resourceType)); - } - catch (NullPointerException e) { - return TIER_NOT_IN_USE; - } - } - - private String getOccupiedBytes(String cacheName, String tier, ResourceType.Core resourceType) - { - try { - CacheStatistics cacheStatistics = statisticsService.getCacheStatistics(cacheName); - Map tierStatistics = cacheStatistics.getTierStatistics(); - long occupiedBytes = tierStatistics.get(tier).getOccupiedByteSize(); - return scaleOccupiedBytes(cacheName, occupiedBytes, resourceType); - } - catch (NullPointerException e) { - return TIER_NOT_IN_USE; - } - } - - private org.ehcache.Cache getEhcache(String cacheName) - { - javax.cache.Cache cache = cacheManager.getCache(cacheName); - return (org.ehcache.Cache)cache.unwrap(org.ehcache.Cache.class); - } - - private String getAllocatedBytes(org.ehcache.Cache ehcache, ResourceType.Core resourceType) throws NullPointerException - { - return String.valueOf(ehcache.getRuntimeConfiguration().getResourcePools().getPoolForResource(resourceType).getSize()); - } - - private String getAllocatedUnit(org.ehcache.Cache ehcache, ResourceType.Core resourceType) throws NullPointerException - { - return ehcache.getRuntimeConfiguration().getResourcePools().getPoolForResource(resourceType).getUnit().toString(); - } - - private String scaleOccupiedBytes(String cacheName, long occupiedBytes, ResourceType.Core resourceType) throws NullPointerException - { - org.ehcache.Cache ehcache = getEhcache(cacheName); - String allocatedUnit = getAllocatedUnit(ehcache, resourceType); - if (allocatedUnit.equals("MB")) { - return String.valueOf(String.format("%.01f", occupiedBytes / BYTES_IN_MB) + "MB (" + occupiedBytes + " bytes)"); - } - else if (allocatedUnit.equals("GB")) { - return String.valueOf(String.format("%.01f", occupiedBytes / BYTES_IN_GB) + "GB (" + occupiedBytes + " bytes)"); - } - else { - return (String.valueOf(occupiedBytes) + " bytes"); - } - - } -} diff --git a/src/main/java/org/cbioportal/persistence/util/LoggingCacheErrorHandler.java b/src/main/java/org/cbioportal/persistence/util/LoggingCacheErrorHandler.java deleted file mode 100644 index a682c568dca..00000000000 --- a/src/main/java/org/cbioportal/persistence/util/LoggingCacheErrorHandler.java +++ /dev/null @@ -1,43 +0,0 @@ -package org.cbioportal.persistence.util; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.cache.Cache; -import org.springframework.cache.interceptor.CacheErrorHandler; - -/** - * Implementation of org.springframework.cache.interceptor.CacheErrorHandler - * that logs the error messages when performing Redis operations. - * Redis will throw a RuntimeException causing our APIs to return HTTP 500 responses, so we defined - * this class to just log the errors and allow our app fallback to the non-cached version. - */ - -public class LoggingCacheErrorHandler implements CacheErrorHandler { - - private static final Logger LOG = LoggerFactory.getLogger(LoggingCacheErrorHandler.class); - - @Override - public void handleCacheGetError(RuntimeException exception, Cache cache, Object key) { - LOG.error(String.format("Cache '%s' failed to get entry with key '%s'", cache.getName(), key), exception); - LOG.error(String.format("Cache error message: '%s'", exception.getMessage())); - } - - @Override - public void handleCachePutError(RuntimeException exception, Cache cache, Object key, Object value) { - LOG.error(String.format("Cache '%s' failed to put entry with key '%s'", cache.getName(), key), exception); - LOG.error(String.format("Cache error message: '%s'", exception.getMessage())); - } - - @Override - public void handleCacheEvictError(RuntimeException exception, Cache cache, Object key) { - LOG.error(String.format("Cache '%s' failed to evict entry with key '%s'", cache.getName(), key), exception); - LOG.error(String.format("Cache error message: '%s'", exception.getMessage())); - } - - @Override - public void handleCacheClearError(RuntimeException exception, Cache cache) { - LOG.error(String.format("Cache '%s' failed to clear entries", cache.getName()), exception); - LOG.error(String.format("Cache error message: '%s'", exception.getMessage())); - } - -} diff --git a/src/main/java/org/cbioportal/persistence/util/RedisCacheUtils.java b/src/main/java/org/cbioportal/persistence/util/RedisCacheUtils.java deleted file mode 100644 index ec5579c544d..00000000000 --- a/src/main/java/org/cbioportal/persistence/util/RedisCacheUtils.java +++ /dev/null @@ -1,51 +0,0 @@ -package org.cbioportal.persistence.util; - -import static org.cbioportal.persistence.util.CustomRedisCache.DELIMITER; - - -import org.redisson.api.RedissonClient; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; -import org.springframework.cache.Cache; -import org.springframework.cache.CacheManager; -import org.springframework.stereotype.Component; - -import java.util.List; -import java.util.stream.Collectors; - -@Component -@ConditionalOnExpression( - "#{environment['persistence.cache_type'] == 'redis' or environment['persistence.cache_type_clickhouse'] == 'redis'}" -) -public class RedisCacheUtils implements CacheUtils { - - @Autowired - private CacheManager cacheManager; - - @Override - public List getKeys(String cacheName) { - Cache cache = cacheManager.getCache(cacheName); - - if(cache == null) { - throw new RuntimeException("Native cache not of class RedissonCache!!!"); - } - - if (cache.getNativeCache() instanceof RedissonClient) { - return ((RedissonClient)cache.getNativeCache()) - .getKeys() - .getKeysStream() - .filter(k -> k.startsWith(cache.getName() + DELIMITER)) - .collect(Collectors.toList()); - } else { - throw new RuntimeException("Native cache not of class RedissonCache!!!"); - } - } - - @Override - public void evictByPattern(String cacheName, String pattern) { - Cache cache = cacheManager.getCache(cacheName); - if(cache != null) { - cache.evict(pattern); - } - } -} diff --git a/src/main/java/org/cbioportal/properties/CustomDataSourceConfiguration.java b/src/main/java/org/cbioportal/properties/CustomDataSourceConfiguration.java deleted file mode 100644 index f71d07b1393..00000000000 --- a/src/main/java/org/cbioportal/properties/CustomDataSourceConfiguration.java +++ /dev/null @@ -1,39 +0,0 @@ -package org.cbioportal.properties; - -import org.cbioportal.utils.config.annotation.ConditionalOnProperty; -import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties; -import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; - -import javax.sql.DataSource; - -@Configuration -@ConditionalOnProperty(name = "clickhouse_mode", havingValue = "true") -public class CustomDataSourceConfiguration { - @Bean - @ConfigurationProperties("spring.datasource.mysql") - public DataSourceProperties mysqlDataSourceProperties() { - return new DataSourceProperties(); - } - - @Bean - @ConfigurationProperties("spring.datasource.clickhouse") - public DataSourceProperties clickhouseDatSourceProperties() { - return new DataSourceProperties(); - } - - @Bean("mysqlDataSource") - public DataSource mysqlDataSource() { - return mysqlDataSourceProperties() - .initializeDataSourceBuilder() - .build(); - } - - @Bean("clickhouseDataSource") - public DataSource clickhouseDataSource() { - return clickhouseDatSourceProperties() - .initializeDataSourceBuilder() - .build(); - } -} diff --git a/src/main/java/org/cbioportal/properties/PortalProperties.java b/src/main/java/org/cbioportal/properties/PortalProperties.java deleted file mode 100644 index 298c343a7be..00000000000 --- a/src/main/java/org/cbioportal/properties/PortalProperties.java +++ /dev/null @@ -1,24 +0,0 @@ -package org.cbioportal.properties; - -import org.cbioportal.utils.validation.AllowedValues; -import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.context.annotation.Configuration; -import org.springframework.validation.annotation.Validated; - -@Validated -@Configuration -@ConfigurationProperties -public class PortalProperties { - - @AllowedValues(values = {"false", "saml", "oauth2", - "optional_oauth2", "saml_plus_basic"}) - private String authenticate; - - public void setAuthenticate(String authenticate) { - this.authenticate = authenticate; - } - - public String getAuthenticate() { - return authenticate; - } -} diff --git a/src/main/java/org/cbioportal/proxy/LegacyProxyController.java b/src/main/java/org/cbioportal/proxy/LegacyProxyController.java deleted file mode 100644 index a2403f22f86..00000000000 --- a/src/main/java/org/cbioportal/proxy/LegacyProxyController.java +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Copyright (c) 2015 Memorial Sloan-Kettering Cancer Center. - * - * This library is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS - * FOR A PARTICULAR PURPOSE. The software and documentation provided hereunder - * is on an "as is" basis, and Memorial Sloan-Kettering Cancer Center has no - * obligations to provide maintenance, support, updates, enhancements or - * modifications. In no event shall Memorial Sloan-Kettering Cancer Center be - * liable to any party for direct, indirect, special, incidental or - * consequential damages, including lost profits, arising out of the use of this - * software and its documentation, even if Memorial Sloan-Kettering Cancer - * Center has been advised of the possibility of such damage. - */ - -/* - * This file is part of cBioPortal. - * - * cBioPortal is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . -*/ - -package org.cbioportal.proxy; - -import java.io.IOException; -import java.net.URI; -import java.net.URISyntaxException; -import java.util.HashMap; -import java.util.Map; - - -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.http.HttpEntity; -import org.springframework.http.HttpMethod; -import org.springframework.http.ResponseEntity; -import org.springframework.stereotype.Controller; -import org.springframework.util.StringUtils; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestMethod; -import org.springframework.web.bind.annotation.ResponseBody; -import org.springframework.web.client.RestTemplate; - -@Controller -@RequestMapping("/api/proxy") -public class LegacyProxyController { - - private String bitlyURL; - private String sessionServiceURL; - private Boolean enableOncokb; - - @Value("${bitly.url:''}") - public void setBitlyURL(String property) { - this.bitlyURL = property; - } - - @Value("${session.service.url:''}") // default is empty string - public void setSessionServiceURL(String property) { - this.sessionServiceURL = property; - } - - @Value("${show.oncokb:true}") - public void setEnableOncokb(Boolean property) { - if(property == null) { - property = true; - } - this.enableOncokb = property; - } - - // This is a general proxy for future use. - // Please modify and improve it as needed with your best expertise. The author does not have fully understanding - // of JAVA proxy when creating this proxy. - // Created by Hongxin - @RequestMapping(value="/{path}") - public @ResponseBody String getProxyURL(@PathVariable String path, - @RequestBody(required = false) String body, HttpMethod method, - HttpServletRequest request, HttpServletResponse response) throws URISyntaxException, IOException { - Map pathToUrl = new HashMap<>(); - - pathToUrl.put("bitly", bitlyURL); - pathToUrl.put("3dHotspots", "https://www.3dhotspots.org/api/hotspots/3d/"); - - String URL = pathToUrl.get(path) == null ? "" : pathToUrl.get(path); - - if (path != null && StringUtils.startsWithIgnoreCase(path, "oncokb") && !enableOncokb) { - response.sendError(403, "OncoKB service is disabled."); - return ""; - } - - //If request method is GET, include query string - if (method.equals(HttpMethod.GET) && request.getQueryString() != null){ - URL += "?" + request.getQueryString(); - } - return respProxy(URL, method, body, response); - } - - private String respProxy(String url, HttpMethod method, Object body, HttpServletResponse response) throws IOException { - try { - RestTemplate restTemplate = new RestTemplate(); - URI uri = new URI(url); - ResponseEntity responseEntity = restTemplate.exchange(uri, method, new HttpEntity<>(body), String.class); - return responseEntity.getBody(); - } catch (Exception exception) { - String errorMessage = "Unexpected error: " + exception.getLocalizedMessage(); - response.sendError(503, errorMessage); - return errorMessage; - } - } - - @RequestMapping(value="/bitly", method = RequestMethod.GET) - public @ResponseBody String getBitlyURL(HttpMethod method, HttpServletRequest request, HttpServletResponse response) throws URISyntaxException, IOException { - return respProxy(bitlyURL + request.getQueryString(), method, null, response); - } - -} diff --git a/src/main/java/org/cbioportal/proxy/Monkifier.java b/src/main/java/org/cbioportal/proxy/Monkifier.java deleted file mode 100644 index b50d6da4dfb..00000000000 --- a/src/main/java/org/cbioportal/proxy/Monkifier.java +++ /dev/null @@ -1,54 +0,0 @@ -package org.cbioportal.proxy; - -import jakarta.servlet.http.HttpServletRequest; -import org.apache.commons.codec.binary.Base64; -import org.springframework.stereotype.Component; -import org.springframework.util.CollectionUtils; -import org.springframework.web.util.UriComponentsBuilder; - -import java.util.Arrays; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - -@Component -public class Monkifier { - public String decodeBase64(String value) { - return new String(Base64.decodeBase64(value.getBytes())); - } - - public String encodeBase64(String value) { - return value == null ? "": new String(Base64.encodeBase64(value.getBytes())); - } - - public String decodeQueryString(HttpServletRequest request) { - if (request.getQueryString() == null) { - return null; - } - - return this.decodeQueryString(request.getParameterMap()); - } - - public String decodeQueryString(Map encodedQueryParams) { - Map> decodedQueryParams = encodedQueryParams - .entrySet() - .stream() - .collect( - Collectors.toMap( - e -> this.decodeBase64(e.getKey()), - e -> Arrays.stream(e.getValue()).map(this::decodeBase64).collect(Collectors.toList()) - ) - ); - - return UriComponentsBuilder - .newInstance() - .queryParams(CollectionUtils.toMultiValueMap(decodedQueryParams)) - .build() - // encode to avoid potentially invalid query strings - .encode() - .toString() - // remove ? from the beginning of the query string, - // we only want the parameters (e.g: param1=value1¶m2=value2) - .replaceFirst("\\?", ""); - } -} diff --git a/src/main/java/org/cbioportal/proxy/ProxyController.java b/src/main/java/org/cbioportal/proxy/ProxyController.java deleted file mode 100644 index 0296aec3390..00000000000 --- a/src/main/java/org/cbioportal/proxy/ProxyController.java +++ /dev/null @@ -1,193 +0,0 @@ -package org.cbioportal.proxy; - -import jakarta.servlet.http.HttpServletRequest; -import org.apache.commons.lang3.StringUtils; -import org.cbioportal.proxy.util.CheckDarwinAccessUtil; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.http.HttpEntity; -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpMethod; -import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; -import org.springframework.http.converter.StringHttpMessageConverter; -import org.springframework.security.core.Authentication; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.ResponseStatus; -import org.springframework.web.bind.annotation.RestController; -import org.springframework.web.client.RestTemplate; - -import java.io.UnsupportedEncodingException; -import java.net.URI; -import java.net.URISyntaxException; -import java.nio.charset.StandardCharsets; -import java.util.regex.Pattern; - -// TODO Consider creating separate DispatcherServlets as in the original web.xml -// See: https://stackoverflow.com/a/30686733/11651683 - -@RestController -@RequestMapping("/proxy") -public class ProxyController { - private static final String DEFAULT_ONCOKB_URL = "https://public.api.oncokb.org/api/v1"; - - @Autowired - private Monkifier monkifier; - - @Value("${oncokb.token:}") - private String oncokbToken; - - @Value("${oncokb.public_api.url:https://public.api.oncokb.org/api/v1}") - private String oncokbApiUrl; - - @Value("${show.oncokb:false}") - private Boolean showOncokb; - - @Value("${darwin.auth_url:}") - private String darwinAuthUrl; - - @Value("${ddp.response_url:}") - private String ddpResponseUrl; - - @Value("${cis.user:}") - private String cisUser; - - @Value("${darwin.regex:Test}") - private String darwinRegex; - - /** - * This dev endpoint can be used (with a personal access token) instead of the production endpoint. - * This is useful when debugging the frontend proxy API calls. - */ - @RequestMapping("/dev/oncokb/**") - public String devProxyOncokb( - @RequestBody(required = false) String body, - HttpMethod method, - HttpServletRequest request - ) throws URISyntaxException { - String token = request.getHeader("X-Proxy-User-Agreement"); - token = (token == null || token.isEmpty()) ? "NA": token; - - return exchangeOncokbData( - body, - request.getPathInfo().replaceFirst("/dev/oncokb", ""), - request.getQueryString(), - method, - getOncokbHeaders(request, token) - ); - } - - @RequestMapping("/A8F74CD7851BDEE8DCD2E86AB4E2A711/**") - public String proxyEncodedOncokb( - @RequestBody(required = false) String body, - HttpMethod method, - HttpServletRequest request - ) throws URISyntaxException, UnsupportedEncodingException { - // make sure that the custom Proxy User Agreement header exists - String proxyUserAgreement = request.getHeader("X-Proxy-User-Agreement"); - if (proxyUserAgreement == null || !proxyUserAgreement.equals( - "I/We do NOT use this obfuscated proxy to programmatically obtain private OncoKB data. " + - "I/We know that I/we should get a valid data access token by registering at https://www.oncokb.org/account/register." - )) { - throw new OncoKBProxyUserAgreementException(); - } - - String decodedBody = body == null ? null: this.monkifier.decodeBase64(body); - String encodedPath = request.getRequestURI().replaceFirst("/proxy/A8F74CD7851BDEE8DCD2E86AB4E2A711/", ""); - String decodedPath = this.monkifier.decodeBase64(encodedPath); - String decodedQueryString = this.monkifier.decodeQueryString(request); - - String response = exchangeOncokbData( - decodedBody, - decodedPath, - decodedQueryString, - method, - getOncokbHeaders(request) - ); - - return "\"" + this.monkifier.encodeBase64(response) + "\""; - } - - private String exchangeOncokbData( - String body, - String pathInfo, - String queryString, - HttpMethod method, - HttpHeaders httpHeaders - ) throws URISyntaxException { - return exchangeData( - body, - buildUri(this.oncokbApiUrl + pathInfo, queryString), - method, - httpHeaders, - String.class - ).getBody(); - } - - private HttpHeaders getOncokbHeaders(HttpServletRequest request) { - return this.getOncokbHeaders(request, null); - } - - private HttpHeaders getOncokbHeaders(HttpServletRequest request, String token) { - String oncokbToken = token == null ? this.oncokbToken : token; - - if (!this.showOncokb) { - throw new OncoKBServiceIsDisabledException(); - } - - HttpHeaders httpHeaders = initHeaders(request); - - if (!StringUtils.isEmpty(oncokbToken)) { - httpHeaders.add("Authorization", "Bearer " + oncokbToken); - } - - return httpHeaders; - } - - @GetMapping("/checkDarwinAccess") - public ResponseEntity checkDarwinAccess(HttpServletRequest request, Authentication authentication) { - String user = authentication != null ? authentication.getName(): "anonymousUser"; - String darwinResponse = CheckDarwinAccessUtil.checkAccess(request, darwinAuthUrl, ddpResponseUrl, cisUser, Pattern.compile(darwinRegex), user); - return new ResponseEntity<>(darwinResponse, HttpStatus.OK); - } - - private HttpHeaders initHeaders(HttpServletRequest request) { - HttpHeaders httpHeaders = new HttpHeaders(); - - String contentType = request.getHeader("Content-Type"); - if (contentType != null) { - httpHeaders.setContentType(MediaType.valueOf(contentType)); - } - - return httpHeaders; - } - - private URI buildUri(String path, String queryString, boolean useSecureProtocol) throws URISyntaxException { - return buildUri((useSecureProtocol ? "https" : "http") + ":/" + path, queryString); - } - - private URI buildUri(String path, String queryString) throws URISyntaxException { - return new URI(path + (queryString == null ? "" : "?" + queryString)); - } - - private ResponseEntity exchangeData(String body, URI uri, HttpMethod method, HttpHeaders httpHeaders, Class responseType) { - RestTemplate restTemplate = new RestTemplate(); - restTemplate.getMessageConverters().add(0, new StringHttpMessageConverter(StandardCharsets.UTF_8)); - return restTemplate.exchange(uri, method, new HttpEntity<>(body, httpHeaders), responseType); - } - - @ResponseStatus(code = HttpStatus.NOT_FOUND, reason = "OncoKB service is disabled") - public class OncoKBServiceIsDisabledException extends RuntimeException { - } - - @ResponseStatus(code = HttpStatus.BAD_REQUEST, reason = "Fair Usage Agreement is missing") - public class OncoKBProxyUserAgreementException extends RuntimeException { - } - - @ResponseStatus(code = HttpStatus.BAD_REQUEST, reason = "Unknown/Invalid hostname") - public class UnknownHostException extends RuntimeException { - } -} \ No newline at end of file diff --git a/src/main/java/org/cbioportal/proxy/util/CheckDarwinAccessUtil.java b/src/main/java/org/cbioportal/proxy/util/CheckDarwinAccessUtil.java deleted file mode 100644 index be9dc2b1152..00000000000 --- a/src/main/java/org/cbioportal/proxy/util/CheckDarwinAccessUtil.java +++ /dev/null @@ -1,243 +0,0 @@ -package org.cbioportal.proxy.util; - -import com.fasterxml.jackson.annotation.JsonAnyGetter; -import com.fasterxml.jackson.annotation.JsonAnySetter; -import com.fasterxml.jackson.annotation.JsonIgnore; -import com.fasterxml.jackson.annotation.JsonProperty; -import jakarta.servlet.http.HttpServletRequest; -import org.apache.commons.lang3.builder.ToStringBuilder; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.http.HttpEntity; -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpMethod; -import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; -import org.springframework.util.LinkedMultiValueMap; -import org.springframework.web.client.RestTemplate; - -import java.util.HashMap; -import java.util.Map; -import java.util.Objects; -import java.util.regex.Pattern; - -public final class CheckDarwinAccessUtil { - private static final Logger logger = LoggerFactory.getLogger(CheckDarwinAccessUtil.class); - - private static final String DDP_INFO_ENDPOINT = "/info"; - public static final String SAMPLE_ID = "sample_id"; - public static final String PATIENT_ID = "case_id"; - - private CheckDarwinAccessUtil() { - throw new IllegalStateException("Utility class"); - } - - public static String checkAccess(HttpServletRequest request, String darwinAuthUrl, String ddpResponseUrl, String cisUser, Pattern sampleIdRegex, String user) { - logger.debug("checkDarwinAccess Requested"); - if (!existsDarwinProperties(darwinAuthUrl, ddpResponseUrl, cisUser, sampleIdRegex)) { - logger.debug("Darwin Properties do not exists"); - return ""; - } - // if sample id does not match regex or username matches cis username then return empty string - String userName = user.split("@")[0]; - String darwinResponse = ""; - try { - String[] sampleIds = request.getParameter(SAMPLE_ID).split(","); - if (sampleIdRegex.matcher(sampleIds[0]).find() && !cisUser.equals(userName)) { - String patientId = request.getParameter(PATIENT_ID); - darwinResponse = getResponse(userName, patientId, darwinAuthUrl, ddpResponseUrl); - } - } catch (NullPointerException ignored) { - logger.debug("Error Sending CheckDarwinAccess API"); - } - - return darwinResponse; - } - - public static String getResponse(String userName, String patientId, String darwinAuthUrl, String ddpResponseUrl) { - RestTemplate restTemplate = new RestTemplate(); - HttpEntity> requestEntity = getRequestEntity(userName, patientId); - ResponseEntity responseEntity = restTemplate.exchange(darwinAuthUrl, HttpMethod.POST, requestEntity, DarwinAccess.class); - String darwinResponse = Objects.requireNonNull(responseEntity.getBody()).getDarwinAuthResponse(); - String deidentificationId = Objects.requireNonNull(responseEntity.getBody()).getDeidentificationId(); - if (!darwinResponse.equals("valid")) { - return ""; - } - if (deidentificationId.isEmpty()) { - return ""; - } - // construct URL - return ddpResponseUrl + deidentificationId + DDP_INFO_ENDPOINT; - } - - private static HttpEntity> getRequestEntity(String userName, String patientId) { - LinkedMultiValueMap map = new LinkedMultiValueMap<>(); - map.add("p_userName", userName); - map.add("p_dmp_pid", patientId); - HttpHeaders headers = new HttpHeaders(); - headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); - return new HttpEntity<>(map, headers); - } - - public static boolean existsDarwinProperties(String darwinAuthUrl, String ddpResponseUrl, String cisUser, Pattern sampleIdRegex) { - return (!darwinAuthUrl.isEmpty() && !ddpResponseUrl.isEmpty() && !cisUser.isEmpty() && !sampleIdRegex.toString().isEmpty()); - } - - - public static class DarwinAccess { - /** - * (Required) - **/ - @JsonProperty("darwinAuthResponse") - private String darwinAuthResponse; - /** - * (Required) - **/ - @JsonProperty("p_userName") - private String pUserName; - /** - * (Required) - **/ - @JsonProperty("p_dmp_pid") - private String pDmpPid; - /** - * (Required) - **/ - @JsonProperty("deidentification_id") - private String deidentificationId; - - @JsonIgnore - private Map additionalProperties = new HashMap<>(); - - /** - * No args constructor for use in serialization - **/ - public DarwinAccess() { - } - - /** - * - **/ - public DarwinAccess(String darwinAuthResponse, String pUserName, String pDmpPid, String deidentificationId) { - this.darwinAuthResponse = darwinAuthResponse; - this.pUserName = pUserName; - this.pDmpPid = pDmpPid; - this.deidentificationId = deidentificationId; - } - - /** - * (Required) - * - * @return The darwinAuthResponse - **/ - @JsonProperty("darwinAuthResponse") - public String getDarwinAuthResponse() { - return darwinAuthResponse; - } - - /** - * (Required) - * - * @param darwinAuthResponse The Darwin authorization response - **/ - @JsonProperty("darwinAuthResponse") - public void setDarwinAuthResponse(String darwinAuthResponse) { - this.darwinAuthResponse = darwinAuthResponse; - } - - public DarwinAccess withDarwinAuthResponse(String darwinAuthResponse) { - this.darwinAuthResponse = darwinAuthResponse; - return this; - } - - /** - * (Required) - * - * @return The p_userName - **/ - @JsonProperty("p_userName") - public String getPUserName() { - return pUserName; - } - - /** - * (Required) - * - * @param pUserName The p_userName - **/ - @JsonProperty("p_userName") - public void setPUserName(String pUserName) { - this.pUserName = pUserName; - } - - public DarwinAccess withPUserName(String pUserName) { - this.pUserName = pUserName; - return this; - } - - /** - * (Required) - * - * @return The p_dmp_pid - **/ - @JsonProperty("p_dmp_pid") - public String getPDmpPid() { - return pDmpPid; - } - - /** - * (Required) - * - * @param pDmpPid The p_dmp_pid - **/ - @JsonProperty("p_dmp_pid") - public void setPDmpPid(String pDmpPid) { - this.pDmpPid = pDmpPid; - } - - /** - * (Required) - * - * @return The deidentification_id - **/ - @JsonProperty("deidentification_id") - public String getDeidentificationId() { - return deidentificationId; - } - - /** - * (Required) - * - * @param deidentificationId The deidentification_id - **/ - @JsonProperty("deidentification_id") - public void setDeidentificationId(String deidentificationId) { - this.deidentificationId = deidentificationId; - } - - public DarwinAccess withPDmpPid(String pDmpPid) { - this.pDmpPid = pDmpPid; - return this; - } - - @Override - public String toString() { - return ToStringBuilder.reflectionToString(this); - } - - @JsonAnyGetter - public Map getAdditionalProperties() { - return this.additionalProperties; - } - - @JsonAnySetter - public void setAdditionalProperty(String name, Object value) { - this.additionalProperties.put(name, value); - } - - public DarwinAccess withAdditionalProperty(String name, Object value) { - this.additionalProperties.put(name, value); - return this; - } - } -} \ No newline at end of file diff --git a/src/main/java/org/cbioportal/security/CancerStudyPermissionEvaluator.java b/src/main/java/org/cbioportal/security/CancerStudyPermissionEvaluator.java deleted file mode 100644 index 3cd7c732b7c..00000000000 --- a/src/main/java/org/cbioportal/security/CancerStudyPermissionEvaluator.java +++ /dev/null @@ -1,409 +0,0 @@ -/* - * Copyright (c) 2015 - 2019 Memorial Sloan-Kettering Cancer Center. - * - * This library is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS - * FOR A PARTICULAR PURPOSE. The software and documentation provided hereunder - * is on an "as is" basis, and Memorial Sloan-Kettering Cancer Center has no - * obligations to provide maintenance, support, updates, enhancements or - * modifications. In no event shall Memorial Sloan-Kettering Cancer Center be - * liable to any party for direct, indirect, special, incidental or - * consequential damages, including lost profits, arising out of the use of this - * software and its documentation, even if Memorial Sloan-Kettering Cancer - * Center has been advised of the possibility of such damage. - */ - -/* - * This file is part of cBioPortal. - * - * cBioPortal is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -package org.cbioportal.security; - -import java.io.Serializable; -import java.util.*; -import java.util.stream.Collectors; - -import org.cbioportal.model.CancerStudy; -import org.cbioportal.model.MolecularProfile; -import org.cbioportal.model.Patient; -import org.cbioportal.model.SampleList; -import org.cbioportal.persistence.cachemaputil.CacheMapUtil; -import org.cbioportal.utils.security.AccessLevel; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.security.access.PermissionEvaluator; -import org.springframework.security.core.Authentication; -import org.springframework.security.core.authority.AuthorityUtils; - -/** - * A custom PermissionEvaluator implementation that checks whether a - * particular user has access to a particular cancer study. - * - * Anonymous users will only get access to public studies. - * - * @author Benjamin Gross - */ -public class CancerStudyPermissionEvaluator implements PermissionEvaluator { - - private final CacheMapUtil cacheMapUtil; - - private static final String ALL_CANCER_STUDIES_ID = "all"; - private static final String ALL_TCGA_CANCER_STUDIES_ID = "all_tcga"; - private static final String ALL_TARGET_CANCER_STUDIES_ID = "all_nci_target"; - private static final String TARGET_TYPE_CANCER_STUDY_ID = "CancerStudyId"; - private static final String TARGET_TYPE_MOLECULAR_PROFILE_ID = "MolecularProfileId"; - private static final String TARGET_TYPE_GENETIC_PROFILE_ID = "GeneticProfileId"; - private static final String TARGET_TYPE_SAMPLE_LIST_ID = "SampleListId"; - private static final String TARGET_TYPE_COLLECTION_OF_SAMPLE_LIST_IDS = "Collection"; - private static final String TARGET_TYPE_COLLECTION_OF_CANCER_STUDY_IDS = "Collection"; - private static final String TARGET_TYPE_COLLECTION_OF_MOLECULAR_PROFILE_IDS = "Collection"; - private static final String TARGET_TYPE_COLLECTION_OF_GENETIC_PROFILE_IDS = "Collection"; - private static final Logger log = LoggerFactory.getLogger(CancerStudyPermissionEvaluator.class); - - private final String APP_NAME; - private String DEFAULT_APP_NAME = "public_portal"; - - private final String FILTER_GROUPS_BY_APP_NAME; - - private final String PUBLIC_CANCER_STUDIES_GROUP; -// @Value("${always_show_study_group:}") -// private void setPublicCancerStudiesGroup(String property) { -// PUBLIC_CANCER_STUDIES_GROUP = property; -// if (log.isDebugEnabled()) { -// log.debug("setPublicCancerStudiesGroup(), always_show_study_group = " + ((property == null) ? "null" : property)); -// } -// if (property != null && property.trim().isEmpty()) { -// PUBLIC_CANCER_STUDIES_GROUP = null; -// } -// } - - public CancerStudyPermissionEvaluator(final String appName, final String doFilterGroupsByAppName, final String alwaysShowCancerStudyGroup, final CacheMapUtil cacheMapUtil ) { - this.APP_NAME = appName; - this.FILTER_GROUPS_BY_APP_NAME = doFilterGroupsByAppName; - this.PUBLIC_CANCER_STUDIES_GROUP = alwaysShowCancerStudyGroup; - this.cacheMapUtil = cacheMapUtil; - } - /** - * Implementation of {@code PermissionEvaluator}. - * this method handles the direct evaluation of user access to individual instances from the data model. - * - * @param authentication - * @param targetDomainObject CancerStudy, MolecularProfile, SampleList, or Patient - * @param permission - */ - @Override - public boolean hasPermission(Authentication authentication, Object targetDomainObject, Object permission) { - if (log.isDebugEnabled()) { - log.debug("hasPermission(), checking permissions on targetDomainObject"); - } - if (targetDomainObject == null) { - if (log.isDebugEnabled()) { - log.debug("hasPermission(), targetDomainObject is null, returning false"); - } - return false; - } - CancerStudy cancerStudy = getRelevantCancerStudyFromTarget(targetDomainObject); - if (log.isDebugEnabled()) { - if (cancerStudy == null) { - log.debug("hasPermission(), stable cancer study is null."); - } - if (authentication == null) { - log.debug("hasPermission(), authentication is null."); - } - } - // nothing to do if stable cancer study is null or authentication is null - // return false as spring-security document specifies - if (cancerStudy == null || authentication == null) { - return false; - } - - // Actually, it's not entirely clear why we do this null test, since the - // authentication will always have authorities. - Object user = authentication.getPrincipal(); - if (user != null) { - return hasAccessToCancerStudy(authentication, cancerStudy, (AccessLevel) permission); - } else { - return false; - } - } - - /** - * Implementation of {@code PermissionEvaluator}. - * - * @param authentication - * @param targetId Serialized String cancer study id, - * String molecular profile id, - * String genetic profile id, - * String sample list id, - * Collection of cancer study ids, - * Collection of molecular profile ids, - * Collection of genetic profile ids, - * or Collection of sample list ids - * @param targetType String 'CancerStudyId', - * 'MolecularProfileId', - * 'GeneticProfileId', - * 'SampleListId', - * 'Collection', - * 'Collection', - * 'Collection', - * or 'Collection' - * @param permission - */ - @Override - public boolean hasPermission(Authentication authentication, Serializable targetId, String targetType, Object permission) { - if (log.isDebugEnabled()) { - log.debug("hasPermission(), checking permissions on targetId"); - } - if (targetId == null) { - if (log.isDebugEnabled()) { - log.debug("hasPermission(), targetId is null, returning false"); - } - return false; - } - if (TARGET_TYPE_CANCER_STUDY_ID.equals(targetType)) { - return hasAccessToCancerStudy(authentication, (String)targetId, permission); - } else if (TARGET_TYPE_MOLECULAR_PROFILE_ID.equals(targetType) || TARGET_TYPE_GENETIC_PROFILE_ID.equals(targetType)) { - return hasAccessToMolecularProfile(authentication, (String)targetId, permission); - } else if (TARGET_TYPE_SAMPLE_LIST_ID.equals(targetType)) { - return hasAccessToSampleList(authentication, (String)targetId, permission); - } else if (TARGET_TYPE_COLLECTION_OF_CANCER_STUDY_IDS.equals(targetType)) { - return hasAccessToCancerStudies(authentication, (Collection)targetId, permission); - } else if (TARGET_TYPE_COLLECTION_OF_MOLECULAR_PROFILE_IDS.equals(targetType) || TARGET_TYPE_COLLECTION_OF_GENETIC_PROFILE_IDS.equals(targetType)) { - return hasAccessToMolecularProfiles(authentication, (Collection)targetId, permission); - } else if (TARGET_TYPE_COLLECTION_OF_SAMPLE_LIST_IDS.equals(targetType)) { - return hasAccessToSampleLists(authentication, (Collection) targetId, permission); - } else { - if (log.isDebugEnabled()) { - log.debug("hasPermission(), unknown targetType '" + targetType + "'"); - } - } - return false; - } - - private CancerStudy getRelevantCancerStudyFromTarget(Object targetDomainObject) { - if (targetDomainObject instanceof CancerStudy) { - return (CancerStudy) targetDomainObject; - } else if (targetDomainObject instanceof MolecularProfile) { - MolecularProfile molecularProfile = (MolecularProfile) targetDomainObject; - if (molecularProfile.getCancerStudy() != null) { - return molecularProfile.getCancerStudy(); - } - // cancer study was not included so get it from cache - return cacheMapUtil.getCancerStudyMap().get(molecularProfile.getCancerStudyIdentifier()); - } else if (targetDomainObject instanceof SampleList) { - SampleList sampleList = (SampleList) targetDomainObject; - if (sampleList.getCancerStudy() != null) { - return sampleList.getCancerStudy(); - } - // cancer study was not included so get it from cache - return cacheMapUtil.getCancerStudyMap().get(sampleList.getCancerStudyIdentifier()); - } else if (targetDomainObject instanceof Patient) { - Patient patient = (Patient) targetDomainObject; - if (patient.getCancerStudy() != null) { - return patient.getCancerStudy(); - } - // cancer study was not included so get it from cache - return cacheMapUtil.getCancerStudyMap().get(patient.getCancerStudyIdentifier()); - } - // unable to handle targetDomainObject type - if (log.isDebugEnabled()) { - log.debug("hasPermission(), targetDomainObject class is '" + targetDomainObject.getClass().getName() + "'"); - } - return null; - } - - /** - * Helper function to determine if given user has access to given cancer study. - * - * @param cancerStudy cancer study to check for - * @param authentication Spring Authentication of the logged-in user. - * @return boolean - */ - private boolean hasAccessToCancerStudy(Authentication authentication, CancerStudy cancerStudy, AccessLevel permission) { - - // The 'list' permission is only requested by the /api/studies endpoint of StudyController. This permission is - // requested by the Study Overview page when the portal instance is configured to show all studies (with non- - // authorized study options greyed out), instead of only showing authorized studies. - // When the 'list' permission is requested, CancerPermissionEvaluator returns true always. - if (AccessLevel.LIST == permission) { - return true; - } - - Set grantedAuthorities = getGrantedAuthorities(authentication); - String stableStudyID = cancerStudy.getCancerStudyIdentifier(); - if (log.isDebugEnabled()) { - log.debug("hasAccessToCancerStudy(), cancer study stable id: " + stableStudyID); - log.debug("hasAccessToCancerStudy(), user: " + authentication.getPrincipal().toString()); - for (String authority : grantedAuthorities) { - log.debug("hasAccessToCancerStudy(), authority: " + authority); - } - } - // everybody has access the 'all' cancer study - if (stableStudyID.equalsIgnoreCase(ALL_CANCER_STUDIES_ID)) { - return true; - } - // if a user has access to 'all', simply return true - if (grantedAuthorities.contains(ALL_CANCER_STUDIES_ID.toUpperCase())) { - if (log.isDebugEnabled()) { - log.debug("hasAccessToCancerStudy(), user has access to ALL cancer studies, return true"); - } - return true; - } - // if a user has access to 'all_tcga', simply return true for tcga studies - if (grantedAuthorities.contains(ALL_TCGA_CANCER_STUDIES_ID.toUpperCase()) && - stableStudyID.toUpperCase().endsWith("_TCGA")) { - if (log.isDebugEnabled()) { - log.debug("hasAccessToCancerStudy(), user has access to ALL_TCGA cancer studies return true"); - } - return true; - } - // if a user has access to 'all_target', simply return true for target studies - if (grantedAuthorities.contains(ALL_TARGET_CANCER_STUDIES_ID.toUpperCase()) && - (stableStudyID.toUpperCase().endsWith("_TARGET") - || stableStudyID.equalsIgnoreCase("ALL_TARGET_PHASE1") - || stableStudyID.equalsIgnoreCase("ALL_TARGET_PHASE2"))) { - if (log.isDebugEnabled()) { - log.debug("hasAccessToCancerStudy(), user has access to ALL_NCI_TARGET cancer studies return true"); - } - return true; - } - // check if user is in study groups - // performance now takes precedence over group accuracy (minimal risk to caching cancer study groups) - // need to filter out empty groups, this can cause issue if grantedAuthorities and groups both contain empty string - Set groups = Arrays.stream(cancerStudy.getGroups().split(";")) - .filter(g -> !g.isEmpty()) - .collect(Collectors.toSet()); - if (!Collections.disjoint(groups, grantedAuthorities)) { - if (log.isDebugEnabled()) { - log.debug("hasAccessToCancerStudy(), user has access by groups return true"); - } - return true; - } - // finally, check if the user has this study specifically listed in his 'groups' (a 'group' of this study only) - boolean toReturn = grantedAuthorities.contains(stableStudyID.toUpperCase()); - if (log.isDebugEnabled()) { - if (toReturn == true) { - log.debug("hasAccessToCancerStudy(), user has access to this cancer study: '" + stableStudyID.toUpperCase() + "', returning true."); - } else { - log.debug("hasAccessToCancerStudy(), user does not have access to the cancer study: '" + stableStudyID.toUpperCase() + "', returning false."); - } - } - return toReturn; - } - - private boolean hasAccessToCancerStudy(Authentication authentication, String cancerStudyId, Object permission) { - // everybody has access the 'all' cancer study - // we have to check this right here (instead of checking later) - // because the 'all' cancer study does not exist in the database - if (cancerStudyId.equalsIgnoreCase(ALL_CANCER_STUDIES_ID)) { - return true; - } - CancerStudy cancerStudy = cacheMapUtil.getCancerStudyMap().get(cancerStudyId); - if (cancerStudy == null) { - return false; - } - return hasPermission(authentication, cancerStudy, permission); - } - - private boolean hasAccessToMolecularProfile(Authentication authentication, String molecularProfileId, Object permission) { - MolecularProfile molecularProfile = cacheMapUtil.getMolecularProfileMap().get(molecularProfileId); - if (molecularProfile == null) { - return false; - } - return hasPermission(authentication, molecularProfile, permission); - } - - private boolean hasAccessToSampleList(Authentication authentication, String sampleListId, Object permission) { - SampleList sampleList = cacheMapUtil.getSampleListMap().get(sampleListId); - if (sampleList == null) { - return false; - } - return hasPermission(authentication, sampleList, permission); - } - - private boolean hasAccessToCancerStudies(Authentication authentication, Collection cancerStudyIds, Object permission) { - for (String cancerStudyId : cancerStudyIds) { - if (!hasPermission(authentication, cancerStudyId, TARGET_TYPE_CANCER_STUDY_ID, permission)) { - return false; - } - } - return true; - } - - private boolean hasAccessToMolecularProfiles(Authentication authentication, Collection molecularProfileIds, Object permission) { - for (String molecularProfileId : molecularProfileIds) { - MolecularProfile molecularProfile = cacheMapUtil.getMolecularProfileMap().get(molecularProfileId); - if (molecularProfile == null || !hasPermission(authentication, molecularProfile, permission)) { - return false; - } - } - return true; - } - - private boolean hasAccessToSampleLists(Authentication authentication, Collection sampleListIds, Object permission) { - for (String sampleListId : sampleListIds) { - SampleList sampleList = cacheMapUtil.getSampleListMap().get(sampleListId); - if (sampleList == null || !hasPermission(authentication, sampleList, permission)) { - return false; - } - } - return true; - } - - private Set getGrantedAuthorities(Authentication authentication) { - String appName = getAppName().toUpperCase(); - // need to filter out empty authorities, this can cause issue if grantedAuthorities and groups both contain empty string - Set allAuthorities = AuthorityUtils.authorityListToSet(authentication.getAuthorities()) - .stream() - .map(authority -> authority.replaceAll("^ROLE_", "")) - .filter(a -> !a.isEmpty()) - .collect(Collectors.toSet()); - Set grantedAuthorities = new HashSet<>(); - if (filterGroupsByAppName()) { - for (String au : allAuthorities) { - if (au.toUpperCase().startsWith(appName + ":")) { - grantedAuthorities.add(au.substring(appName.length() + 1).toUpperCase()); - } - } - } else { - for (String au : allAuthorities) { - grantedAuthorities.add(au.toUpperCase()); - } - } - // all users are allowed access to PUBLIC studies - if (log.isDebugEnabled()) { - log.debug("PUBLIC_CANCER_STUDIES_GROUP= " + ((PUBLIC_CANCER_STUDIES_GROUP == null) ? "null" : PUBLIC_CANCER_STUDIES_GROUP)); - } - if (PUBLIC_CANCER_STUDIES_GROUP != null) { - grantedAuthorities.add(PUBLIC_CANCER_STUDIES_GROUP.toUpperCase()); - } - return grantedAuthorities; - } - - private String getAppName() { - if (log.isDebugEnabled()) { - log.debug("getAppName(), APP_NAME = " + ((APP_NAME == null) ? "null" : APP_NAME)); - } - return (APP_NAME == null || APP_NAME.trim().isEmpty()) ? DEFAULT_APP_NAME : APP_NAME; - } - - private boolean filterGroupsByAppName() { - if (log.isDebugEnabled()) { - log.debug("filterGroupsByAppName(), FILTER_GROUPS_BY_APP_NAME = " + ((FILTER_GROUPS_BY_APP_NAME == null) ? "null" : FILTER_GROUPS_BY_APP_NAME)); - } - return FILTER_GROUPS_BY_APP_NAME == null || Boolean.parseBoolean(FILTER_GROUPS_BY_APP_NAME); - } -} \ No newline at end of file diff --git a/src/main/java/org/cbioportal/security/basic/BasicRestfulAuthenticationSuccessHandler.java b/src/main/java/org/cbioportal/security/basic/BasicRestfulAuthenticationSuccessHandler.java deleted file mode 100644 index 9291f27abcd..00000000000 --- a/src/main/java/org/cbioportal/security/basic/BasicRestfulAuthenticationSuccessHandler.java +++ /dev/null @@ -1,36 +0,0 @@ -package org.cbioportal.security.basic; - -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; -import jakarta.servlet.http.HttpSession; -import org.springframework.security.core.Authentication; -import org.springframework.security.core.context.SecurityContext; -import org.springframework.security.core.context.SecurityContextHolder; -import org.springframework.security.core.context.SecurityContextHolderStrategy; -import org.springframework.security.web.DefaultRedirectStrategy; -import org.springframework.security.web.RedirectStrategy; -import org.springframework.security.web.authentication.AuthenticationSuccessHandler; -import org.springframework.security.web.context.HttpSessionSecurityContextRepository; -import org.springframework.security.web.context.SecurityContextRepository; - -import java.io.IOException; - -public class BasicRestfulAuthenticationSuccessHandler implements AuthenticationSuccessHandler { - - private final SecurityContextHolderStrategy securityContextHolderStrategy = SecurityContextHolder.getContextHolderStrategy(); - private final SecurityContextRepository securityContextRepository = new HttpSessionSecurityContextRepository(); - private final RedirectStrategy redirectStrategy = new DefaultRedirectStrategy(); - @Override - public void onAuthenticationSuccess(HttpServletRequest request, - HttpServletResponse response, Authentication authentication) throws IOException { - HttpSession session = request.getSession(true); - session.setAttribute("user_id", request.getParameter("user_id")); - SecurityContext context = this.securityContextHolderStrategy.createEmptyContext(); - context.setAuthentication(authentication); - this.securityContextHolderStrategy.setContext(context); - this.securityContextRepository.saveContext(context, request, response); - redirectStrategy.sendRedirect(request, response, "/restful_login"); - } - - -} \ No newline at end of file diff --git a/src/main/java/org/cbioportal/security/config/ApiSecurityConfig.java b/src/main/java/org/cbioportal/security/config/ApiSecurityConfig.java deleted file mode 100644 index b83524d0869..00000000000 --- a/src/main/java/org/cbioportal/security/config/ApiSecurityConfig.java +++ /dev/null @@ -1,102 +0,0 @@ -package org.cbioportal.security.config; - -import org.cbioportal.security.token.RestAuthenticationEntryPoint; -import org.cbioportal.security.token.TokenAuthenticationFilter; -import org.cbioportal.security.token.TokenAuthenticationSuccessHandler; -import org.cbioportal.service.DataAccessTokenService; -import org.cbioportal.utils.config.annotation.ConditionalOnProperty; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.core.Ordered; -import org.springframework.core.annotation.Order; -import org.springframework.http.HttpStatus; -import org.springframework.lang.Nullable; -import org.springframework.security.authentication.AuthenticationManager; -import org.springframework.security.authentication.AuthenticationProvider; -import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; -import org.springframework.security.config.annotation.web.builders.HttpSecurity; -import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer; -import org.springframework.security.web.SecurityFilterChain; -import org.springframework.security.web.authentication.HttpStatusEntryPoint; -import org.springframework.security.web.context.SecurityContextHolderFilter; -import org.springframework.security.web.util.matcher.AntPathRequestMatcher; - -@Configuration -@ConditionalOnProperty(name = "authenticate", havingValue = {"false", "optional_oauth2"}, isNot = true) -public class ApiSecurityConfig { - - // Add security filter chains that handle calls to the API endpoints. - // Different chains are added for the '/api' and legacy '/webservice.do' paths. - // Both are able to handle API tokens provided in the request. - // see: "Creating and Customizing Filter Chains" @ https://spring.io/guides/topicals/spring-security-architecture - - @Bean - @Order(Ordered.HIGHEST_PRECEDENCE) - public SecurityFilterChain securityFilterChain(HttpSecurity http, @Nullable DataAccessTokenService tokenService) throws Exception { - http.csrf(AbstractHttpConfigurer::disable) - // This filter chain only grabs requests to the '/api' path. - .securityMatcher("/api/**", "/webservice.do") - .authorizeHttpRequests(authorize -> authorize - .requestMatchers( - "/api/swagger-resources/**", - "/api/swagger-ui.html", - "/api/health", - "/api/public_virtual_studies/**", - "/api/cache/**").permitAll() - .anyRequest().authenticated() - ) - .sessionManagement(sessionManagement -> sessionManagement.sessionFixation().migrateSession()) - .exceptionHandling(eh -> - eh.defaultAuthenticationEntryPointFor( - new HttpStatusEntryPoint(HttpStatus.UNAUTHORIZED), AntPathRequestMatcher.antMatcher("/api/**") - ) - ); - // When dat.method is not 'none' and a tokenService bean is present, - // the apiTokenAuthenticationFilter is added to the filter chain. - if (tokenService != null) { - http.apply(ApiTokenFilterDsl.tokenFilterDsl(tokenService)); - } - return http.build(); - } - - @Autowired - public void buildAuthenticationManager(AuthenticationManagerBuilder authenticationManagerBuilder, - @Nullable AuthenticationProvider... authenticationProviders) { - if (authenticationProviders != null) { - for (AuthenticationProvider authenticationProvider : authenticationProviders) { - authenticationManagerBuilder.authenticationProvider(authenticationProvider); - } - } - } - - @Bean - public RestAuthenticationEntryPoint restAuthenticationEntryPoint() { - return new RestAuthenticationEntryPoint(); - } - -} - - -class ApiTokenFilterDsl extends AbstractHttpConfigurer { - - private final DataAccessTokenService tokenService; - - public ApiTokenFilterDsl(DataAccessTokenService tokenService) { - this.tokenService = tokenService; - } - - @Override - public void configure(HttpSecurity http) { - AuthenticationManager authenticationManager = http.getSharedObject(AuthenticationManager.class); - TokenAuthenticationSuccessHandler tokenAuthenticationSuccessHandler = new TokenAuthenticationSuccessHandler(); - TokenAuthenticationFilter filter = new TokenAuthenticationFilter("/**", authenticationManager, tokenService); - filter.setAuthenticationSuccessHandler(tokenAuthenticationSuccessHandler); - http.addFilterAfter(filter, SecurityContextHolderFilter.class); - } - - public static ApiTokenFilterDsl tokenFilterDsl(DataAccessTokenService tokenService) { - return new ApiTokenFilterDsl(tokenService); - } - -} diff --git a/src/main/java/org/cbioportal/security/config/AutoconfigureExcludeConfig.java b/src/main/java/org/cbioportal/security/config/AutoconfigureExcludeConfig.java deleted file mode 100644 index 5c14beb51e6..00000000000 --- a/src/main/java/org/cbioportal/security/config/AutoconfigureExcludeConfig.java +++ /dev/null @@ -1,38 +0,0 @@ -package org.cbioportal.security.config; - -import org.cbioportal.utils.config.annotation.ConditionalOnProperty; -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; -import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration; -import org.springframework.boot.autoconfigure.security.oauth2.client.servlet.OAuth2ClientAutoConfiguration; -import org.springframework.boot.autoconfigure.security.saml2.Saml2RelyingPartyAutoConfiguration; -import org.springframework.context.annotation.Configuration; - -// Conditionally disable autoconfguration for Spring Boot components. -public class AutoconfigureExcludeConfig { - - private AutoconfigureExcludeConfig() {} - - @Configuration - @ConditionalOnProperty(name = "authenticate", havingValue = {"saml", "oauth2", "optional_oauth2","saml_plus_basic"}, isNot = true) - @EnableAutoConfiguration(exclude={OAuth2ClientAutoConfiguration.class, Saml2RelyingPartyAutoConfiguration.class}) - public static class ExcludeAll {} - - @Configuration - @ConditionalOnExpression("{'saml','saml_plus_basic'}.contains('${authenticate}')") - @EnableAutoConfiguration(exclude=OAuth2ClientAutoConfiguration.class) - public static class Saml {} - - @Configuration - @ConditionalOnProperty(name = "authenticate", havingValue = "oauth2") - @EnableAutoConfiguration(exclude=Saml2RelyingPartyAutoConfiguration.class) - public static class OAuth2 {} - - @Configuration - @ConditionalOnExpression( - "T(org.apache.commons.lang3.StringUtils).isEmpty('${spring.session.store-type:}')" - ) - @EnableAutoConfiguration(exclude=RedisAutoConfiguration.class) - public static class Redis {} - -} diff --git a/src/main/java/org/cbioportal/security/config/CorsConfig.java b/src/main/java/org/cbioportal/security/config/CorsConfig.java deleted file mode 100644 index d96050013cc..00000000000 --- a/src/main/java/org/cbioportal/security/config/CorsConfig.java +++ /dev/null @@ -1,37 +0,0 @@ -package org.cbioportal.security.config; - -import org.springframework.beans.factory.annotation.Value; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; -import org.springframework.web.cors.CorsConfiguration; -import org.springframework.web.cors.CorsConfigurationSource; -import org.springframework.web.cors.UrlBasedCorsConfigurationSource; - -import java.util.List; - -@Configuration -@EnableWebSecurity -public class CorsConfig { - @Value("${security.cors.allowed-origins:}") - private String allowedOrigins; - - @Bean - CorsConfigurationSource corsConfigurationSource() { - List parsedAllowedOrigins = List.of(allowedOrigins.split(",")); - UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); - if ( parsedAllowedOrigins.isEmpty()) { - return source; - } - - CorsConfiguration configuration = new CorsConfiguration(); - configuration.setAllowedOrigins(parsedAllowedOrigins); - configuration.setAllowedMethods(List.of("GET","POST", "HEAD","OPTIONS")); - configuration.setAllowedHeaders(List.of("user-agent", "Origin", "Accept", "X-Requested-With","Content-Type", - "Access-Control-Request-Method","Access-Control-Request-Headers","Content-Encoding", - "X-Proxy-User-Agreement", "x-current-url")); - configuration.setExposedHeaders(List.of("total-count", "sample-count", "elapsed-time")); - source.registerCorsConfiguration("/**", configuration); - return source; - } -} diff --git a/src/main/java/org/cbioportal/security/config/CustomOAuth2AuthorizationConfig.java b/src/main/java/org/cbioportal/security/config/CustomOAuth2AuthorizationConfig.java deleted file mode 100644 index 7929fdce39f..00000000000 --- a/src/main/java/org/cbioportal/security/config/CustomOAuth2AuthorizationConfig.java +++ /dev/null @@ -1,78 +0,0 @@ -package org.cbioportal.security.config; - -import org.cbioportal.model.User; -import org.cbioportal.model.UserAuthorities; -import org.cbioportal.persistence.SecurityRepository; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; -import org.springframework.security.core.GrantedAuthority; -import org.springframework.security.core.authority.AuthorityUtils; -import org.springframework.security.oauth2.client.oidc.userinfo.OidcUserRequest; -import org.springframework.security.oauth2.client.oidc.userinfo.OidcUserService; -import org.springframework.security.oauth2.client.userinfo.OAuth2UserService; -import org.springframework.security.oauth2.core.OAuth2AuthenticationException; -import org.springframework.security.oauth2.core.oidc.user.DefaultOidcUser; -import org.springframework.security.oauth2.core.oidc.user.OidcUser; - -import java.util.HashSet; -import java.util.Objects; -import java.util.Set; - -@Configuration -@EnableWebSecurity -@ConditionalOnProperty(value = "authorization", havingValue = "true") -public class CustomOAuth2AuthorizationConfig { - Logger log = LoggerFactory.getLogger(CustomOAuth2AuthorizationConfig.class); - - private final SecurityRepository securityRepository; - - private static final String NAME_ATTRIBUTE_KEY = "email"; - - @Autowired - public CustomOAuth2AuthorizationConfig(SecurityRepository securityRepository) { - this.securityRepository = securityRepository; - } - - @Bean - public OAuth2UserService oidcUserService() { - final OidcUserService delegate = new OidcUserService(); - - return userRequest -> { - log.debug("Custom OAuth2 Authorization Enabled"); - - // Delegate to the default implementation for loading a user - OidcUser oidcUser = delegate.loadUser(userRequest); - - var authenticatedPortalUser = loadPortalUser(oidcUser.getEmail()); - if (Objects.isNull(authenticatedPortalUser.cbioUser) || !authenticatedPortalUser.cbioUser.isEnabled()) { - log.debug("User: {} either not in db or not authorized", oidcUser.getEmail()); - throw new OAuth2AuthenticationException("user not authorized"); - } - Set mappedAuthorities = authenticatedPortalUser.authorities; - oidcUser = new DefaultOidcUser(mappedAuthorities, oidcUser.getIdToken(), oidcUser.getUserInfo(), NAME_ATTRIBUTE_KEY); - return oidcUser; - }; - } - - private AuthenticatedPortalUser loadPortalUser(String email) { - Set mappedAuthorities = new HashSet<>(); - User cbioUser = securityRepository.getPortalUser(email); - if (!Objects.isNull(cbioUser)) { - UserAuthorities authorities = securityRepository.getPortalUserAuthorities(email); - if (!Objects.isNull(authorities)) { - mappedAuthorities.addAll(AuthorityUtils.createAuthorityList(authorities.getAuthorities())); - } - } - return new AuthenticatedPortalUser(cbioUser, mappedAuthorities); - } - - record AuthenticatedPortalUser(User cbioUser, Set authorities) { - - } - -} \ No newline at end of file diff --git a/src/main/java/org/cbioportal/security/config/MethodSecurityConfig.java b/src/main/java/org/cbioportal/security/config/MethodSecurityConfig.java deleted file mode 100644 index c6bd8d04645..00000000000 --- a/src/main/java/org/cbioportal/security/config/MethodSecurityConfig.java +++ /dev/null @@ -1,36 +0,0 @@ -package org.cbioportal.security.config; - -import org.cbioportal.persistence.cachemaputil.CacheMapUtil; -import org.cbioportal.security.CancerStudyPermissionEvaluator; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler; -import org.springframework.security.access.expression.method.MethodSecurityExpressionHandler; -import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity; - -@Configuration -@EnableMethodSecurity(prePostEnabled = true) -// We are allowing users to enable method_authorization if optional_oauth2 is selected -@ConditionalOnExpression("{'oauth2','saml', 'saml_plus_basic'}.contains('${authenticate}') or ('optional_oauth2' eq '${authenticate}' and 'true' eq '${security.method_authorization_enabled}')") -public class MethodSecurityConfig { - - @Bean - public CancerStudyPermissionEvaluator cancerStudyPermissionEvaluator( - @Value("${app.name:}") String appName, - @Value("${filter_groups_by_appname:true}") String doFilterGroupsByAppName, - @Value("${always_show_study_group:}") String alwaysShowCancerStudyGroup, - CacheMapUtil cacheMapUtil - ) { - return new CancerStudyPermissionEvaluator(appName, doFilterGroupsByAppName, alwaysShowCancerStudyGroup, cacheMapUtil); - } - - @Bean - public MethodSecurityExpressionHandler createExpressionHandler(CancerStudyPermissionEvaluator cancerStudyPermissionEvaluator) { - DefaultMethodSecurityExpressionHandler expressionHandler = - new DefaultMethodSecurityExpressionHandler(); - expressionHandler.setPermissionEvaluator(cancerStudyPermissionEvaluator); - return expressionHandler; - } -} \ No newline at end of file diff --git a/src/main/java/org/cbioportal/security/config/NoSecurityConfig.java b/src/main/java/org/cbioportal/security/config/NoSecurityConfig.java deleted file mode 100644 index 42f49c96cd3..00000000000 --- a/src/main/java/org/cbioportal/security/config/NoSecurityConfig.java +++ /dev/null @@ -1,27 +0,0 @@ -package org.cbioportal.security.config; - -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.security.config.Customizer; -import org.springframework.security.config.annotation.web.builders.HttpSecurity; -import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; -import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer; -import org.springframework.security.web.SecurityFilterChain; - -@Configuration -@EnableWebSecurity -@ConditionalOnProperty(value = "authenticate", havingValue = "false", matchIfMissing = true) -public class NoSecurityConfig { - @Bean - public SecurityFilterChain filterChain(HttpSecurity http) throws Exception{ - return http - .cors(Customizer.withDefaults()) - .csrf(AbstractHttpConfigurer::disable) - .authorizeHttpRequests(auth -> auth - .requestMatchers("/").permitAll() - .anyRequest().permitAll() - ) - .build(); - } -} \ No newline at end of file diff --git a/src/main/java/org/cbioportal/security/config/OAuth2SecurityConfig.java b/src/main/java/org/cbioportal/security/config/OAuth2SecurityConfig.java deleted file mode 100644 index fd3b8b48b3f..00000000000 --- a/src/main/java/org/cbioportal/security/config/OAuth2SecurityConfig.java +++ /dev/null @@ -1,114 +0,0 @@ -package org.cbioportal.security.config; - -import org.cbioportal.security.util.ClaimRoleExtractorUtil; -import org.cbioportal.security.util.GrantedAuthorityUtil; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.boot.autoconfigure.security.SecurityProperties; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.core.annotation.Order; -import org.springframework.security.config.Customizer; -import org.springframework.security.config.annotation.web.builders.HttpSecurity; -import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer; -import org.springframework.security.core.GrantedAuthority; -import org.springframework.security.core.authority.SimpleGrantedAuthority; -import org.springframework.security.core.authority.mapping.GrantedAuthoritiesMapper; -import org.springframework.security.oauth2.client.oidc.web.logout.OidcClientInitiatedLogoutSuccessHandler; -import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository; -import org.springframework.security.oauth2.core.oidc.user.OidcUserAuthority; -import org.springframework.security.oauth2.core.user.OAuth2UserAuthority; -import org.springframework.security.web.SecurityFilterChain; -import org.springframework.security.web.authentication.logout.LogoutSuccessHandler; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Set; -import java.util.stream.Collectors; - - -@Configuration -// add new chain after api-filter chain (at position -2), but before the default fallback chain -@Order(SecurityProperties.BASIC_AUTH_ORDER - 1) -@ConditionalOnProperty(value = "authenticate", havingValue = "oauth2") -public class OAuth2SecurityConfig { - - private static final Logger log = LoggerFactory.getLogger(OAuth2SecurityConfig.class); - - - @Value("${spring.security.oauth2.client.jwt-roles-path:resource_access::cbioportal::roles}") - private String jwtRolesPath; - - private static final String LOGIN_URL = "/login"; - - @Bean - @Order(1) - public SecurityFilterChain filterChain(HttpSecurity http, ClientRegistrationRepository clientRegistrationRepository) throws Exception { - http.csrf(AbstractHttpConfigurer::disable) - .cors(Customizer.withDefaults()) - .authorizeHttpRequests(authorize -> - authorize - .requestMatchers("/api/health", LOGIN_URL, "/images/**").permitAll() - .anyRequest().authenticated() - ) - .oauth2Login(login -> - login - .loginPage(LOGIN_URL) - .userInfoEndpoint(userInfo -> - userInfo.userAuthoritiesMapper(userAuthoritiesMapper()) - ) - .failureUrl(LOGIN_URL + "?logout_failure") - ) - .logout(logout -> logout - .logoutSuccessHandler(oidcLogoutSuccessHandler(clientRegistrationRepository)) - ); - return http.build(); - } - - - private GrantedAuthoritiesMapper userAuthoritiesMapper() { - return (authorities) -> { - Set mappedAuthorities = new HashSet<>(); - - authorities.forEach(authority -> { - List> claims = new ArrayList<>(); - switch (authority) { - case OidcUserAuthority oidcUserAuthority -> { - if(!Objects.isNull(oidcUserAuthority.getUserInfo())) { - claims.add(oidcUserAuthority.getUserInfo().getClaims()); - } - claims.add(oidcUserAuthority.getIdToken().getClaims()); - } - case OAuth2UserAuthority oAuth2UserAuthority -> claims.add(oAuth2UserAuthority.getAttributes()); - case SimpleGrantedAuthority simpleGrantedAuthority -> mappedAuthorities.add(simpleGrantedAuthority); - default -> log.debug("Unsupported UserAuthority Type {}", authority); - } - if(!claims.isEmpty()) { - var roles = claims.stream() - .filter(claim -> !Objects.isNull(claim)) - .map(claim -> ClaimRoleExtractorUtil.extractClientRoles(claim, jwtRolesPath)) - .flatMap(Collection::stream) - .collect(Collectors.toSet()); - - mappedAuthorities.addAll(GrantedAuthorityUtil.generateGrantedAuthoritiesFromRoles(roles)); - } - }); - return mappedAuthorities; - }; - } - - // See: https://docs.spring.io/spring-security/reference/5.7-SNAPSHOT/servlet/oauth2/login/advanced.html#oauth2login-advanced-oidc-logout - private LogoutSuccessHandler oidcLogoutSuccessHandler(ClientRegistrationRepository clientRegistrationRepository) { - OidcClientInitiatedLogoutSuccessHandler oidcLogoutSuccessHandler = - new OidcClientInitiatedLogoutSuccessHandler(clientRegistrationRepository); - oidcLogoutSuccessHandler.setPostLogoutRedirectUri("{baseUrl}"); - return oidcLogoutSuccessHandler; - } - -} diff --git a/src/main/java/org/cbioportal/security/config/OptionalOAuth2SecurityConfig.java b/src/main/java/org/cbioportal/security/config/OptionalOAuth2SecurityConfig.java deleted file mode 100644 index 248921b2235..00000000000 --- a/src/main/java/org/cbioportal/security/config/OptionalOAuth2SecurityConfig.java +++ /dev/null @@ -1,35 +0,0 @@ -package org.cbioportal.security.config; - -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.boot.autoconfigure.security.SecurityProperties; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.core.annotation.Order; -import org.springframework.security.config.Customizer; -import org.springframework.security.config.annotation.web.builders.HttpSecurity; -import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; -import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer; -import org.springframework.security.web.SecurityFilterChain; - - -@Configuration -@EnableWebSecurity -// add new chain after api-filter chain (at position -2), but before the default fallback chain -@Order(SecurityProperties.BASIC_AUTH_ORDER - 1) -@ConditionalOnProperty(value = "authenticate", havingValue = "optional_oauth2") -public class OptionalOAuth2SecurityConfig { - - @Bean - public SecurityFilterChain optionalOAuth2filterChain(HttpSecurity http) throws Exception { - return http - .oauth2Login(oauth -> oauth.loginPage("/login")) - .authorizeHttpRequests(auth -> auth - .requestMatchers("/").permitAll() - .anyRequest().permitAll()) - .cors(Customizer.withDefaults()) - .csrf(AbstractHttpConfigurer::disable) - .logout(logout -> logout.logoutSuccessUrl("/")) - .build(); - } - -} diff --git a/src/main/java/org/cbioportal/security/config/Saml2AndBasicConfig.java b/src/main/java/org/cbioportal/security/config/Saml2AndBasicConfig.java deleted file mode 100644 index 691979c0072..00000000000 --- a/src/main/java/org/cbioportal/security/config/Saml2AndBasicConfig.java +++ /dev/null @@ -1,130 +0,0 @@ -package org.cbioportal.security.config; - -import org.cbioportal.security.basic.BasicRestfulAuthenticationSuccessHandler; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.http.HttpStatus; -import org.springframework.security.authentication.AuthenticationManager; -import org.springframework.security.authentication.dao.DaoAuthenticationProvider; -import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; -import org.springframework.security.config.annotation.web.builders.HttpSecurity; -import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; -import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer; -import org.springframework.security.core.userdetails.User; -import org.springframework.security.core.userdetails.UserDetails; -import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; -import org.springframework.security.provisioning.InMemoryUserDetailsManager; -import org.springframework.security.web.SecurityFilterChain; -import org.springframework.security.web.authentication.HttpStatusEntryPoint; -import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; -import org.springframework.security.web.authentication.logout.LogoutSuccessHandler; -import org.springframework.security.web.context.HttpSessionSecurityContextRepository; -import org.springframework.security.web.context.SecurityContextHolderFilter; -import org.springframework.security.web.util.matcher.AntPathRequestMatcher; - -import java.util.Objects; - -import static org.springframework.security.config.Customizer.withDefaults; - - -@Configuration -@EnableWebSecurity -@ConditionalOnProperty(value = "authenticate", havingValue = "saml_plus_basic") -public class Saml2AndBasicConfig { - private static final String LOGOUT_URL = "/logout"; - private static final String BASIC_LOGOUT_URL = "/j_spring_security_logout"; - - @Value("${basic.username:MOCK_USER}") - private String basicUsername; - - @Value("${basic.password:MOCK_PASSWORD}") - private String basicPassword; - - @Value("${basic.authorities:}") - private String basicAuthorities; - - - @Bean - public SecurityFilterChain samlFilterChain(HttpSecurity http, AuthenticationManagerBuilder authenticationManagerBuilder, - LogoutSuccessHandler logoutSuccessHandler) throws Exception { - buildAuthenticationManager(authenticationManagerBuilder, userDetailsService()); - http.csrf(AbstractHttpConfigurer::disable) - .cors(withDefaults()) - .authorizeHttpRequests(auth -> - auth.requestMatchers("/api/health", "/images/**", "/js/**", "/login").permitAll() - .anyRequest().authenticated()) - .exceptionHandling(eh -> - eh.defaultAuthenticationEntryPointFor( - new HttpStatusEntryPoint(HttpStatus.UNAUTHORIZED), AntPathRequestMatcher.antMatcher("/api/**") - ) - ) - .securityContext(securityContext -> securityContext. - securityContextRepository(new HttpSessionSecurityContextRepository()) - ) - .saml2Login(withDefaults()) - .sessionManagement(sessionManagement -> sessionManagement.sessionFixation().migrateSession()) - // NOTE: I did not get the official .saml2Logout() DSL to work as - // described at https://docs.spring.io/spring-security/reference/6.1/servlet/saml2/logout.html - // Logout Service POST Binding URL: http://localhost:8080/logout/saml2/slo - .logout(logout -> logout - .logoutUrl(LOGOUT_URL) - .clearAuthentication(true) - .invalidateHttpSession(true) - .logoutSuccessHandler(logoutSuccessHandler) - ) - .logout(logout -> logout - .logoutUrl(BASIC_LOGOUT_URL) - .clearAuthentication(true) - .invalidateHttpSession(true) - ); - - http.apply(new BasicFilterDsl()); - return http.build(); - } - - private class BasicFilterDsl extends AbstractHttpConfigurer { - @Override - public void configure(HttpSecurity http) { - AuthenticationManager authenticationManager = http.getSharedObject(AuthenticationManager.class); - UsernamePasswordAuthenticationFilter filter = - new UsernamePasswordAuthenticationFilter(); - filter.setPostOnly(false); - filter.setFilterProcessesUrl("/j_spring_security_check"); - filter.setUsernameParameter("j_username"); - filter.setPasswordParameter("j_password"); - filter.setAuthenticationManager(authenticationManager); - filter.setAuthenticationSuccessHandler(new BasicRestfulAuthenticationSuccessHandler()); - http.addFilterAfter(filter, SecurityContextHolderFilter.class); - } - } - - public void buildAuthenticationManager(AuthenticationManagerBuilder authenticationManagerBuilder, InMemoryUserDetailsManager userDetailsManager ) { - DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider(); - authenticationProvider.setUserDetailsService(userDetailsManager); - authenticationProvider.setPasswordEncoder(bCryptPasswordEncoder()); - authenticationManagerBuilder.authenticationProvider(authenticationProvider); - } - - - @Bean - public InMemoryUserDetailsManager userDetailsService() { - if(Objects.isNull(basicAuthorities)) { - basicAuthorities = "NOOP"; - } - - UserDetails user = User - .withUsername(this.basicUsername) - .password(this.basicPassword) - .roles(basicAuthorities.split(",")) - .build(); - return new InMemoryUserDetailsManager(user); - } - - @Bean - public BCryptPasswordEncoder bCryptPasswordEncoder() { - return new BCryptPasswordEncoder(10); - } - -} diff --git a/src/main/java/org/cbioportal/security/config/Saml2SecurityConfig.java b/src/main/java/org/cbioportal/security/config/Saml2SecurityConfig.java deleted file mode 100644 index 527df01140b..00000000000 --- a/src/main/java/org/cbioportal/security/config/Saml2SecurityConfig.java +++ /dev/null @@ -1,106 +0,0 @@ -package org.cbioportal.security.config; - -import org.cbioportal.security.util.GrantedAuthorityUtil; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.core.convert.converter.Converter; -import org.springframework.http.HttpStatus; -import org.springframework.security.config.Customizer; -import org.springframework.security.config.annotation.web.builders.HttpSecurity; -import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; -import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer; -import org.springframework.security.core.GrantedAuthority; -import org.springframework.security.saml2.provider.service.authentication.OpenSaml4AuthenticationProvider; -import org.springframework.security.saml2.provider.service.authentication.Saml2AuthenticatedPrincipal; -import org.springframework.security.saml2.provider.service.authentication.Saml2Authentication; -import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistrationRepository; -import org.springframework.security.saml2.provider.service.web.DefaultRelyingPartyRegistrationResolver; -import org.springframework.security.saml2.provider.service.web.authentication.logout.OpenSaml4LogoutRequestResolver; -import org.springframework.security.saml2.provider.service.web.authentication.logout.Saml2RelyingPartyInitiatedLogoutSuccessHandler; -import org.springframework.security.web.SecurityFilterChain; -import org.springframework.security.web.authentication.HttpStatusEntryPoint; -import org.springframework.security.web.authentication.logout.LogoutSuccessHandler; -import org.springframework.security.web.util.matcher.AntPathRequestMatcher; - -import java.util.Collection; -import java.util.HashSet; -import java.util.Objects; -import java.util.Set; - -import static org.springframework.security.config.Customizer.withDefaults; - -@Configuration -@EnableWebSecurity -@ConditionalOnExpression("{'saml','saml_plus_basic'}.contains('${authenticate}')") -public class Saml2SecurityConfig { - - private static final String LOGOUT_URL = "/logout"; - - @Value("${saml.idp.metadata.attribute.role:Role}") - private String roleAttributeName; - - @Bean - @ConditionalOnProperty(value = "authenticate", havingValue = "saml") - public SecurityFilterChain samlFilterChain(HttpSecurity http, RelyingPartyRegistrationRepository relyingPartyRegistrationRepository) throws Exception { - return http.csrf(AbstractHttpConfigurer::disable) - .cors(Customizer.withDefaults()) - .authorizeHttpRequests(auth -> - auth.requestMatchers("/api/health", "/images/**", "/js/**", "/login").permitAll() - .anyRequest().authenticated()) - .exceptionHandling(eh -> - eh.defaultAuthenticationEntryPointFor( - new HttpStatusEntryPoint(HttpStatus.UNAUTHORIZED), AntPathRequestMatcher.antMatcher("/api/**") - ) - ) - .saml2Login(withDefaults()) - // NOTE: I did not get the official .saml2Logout() DSL to work as - // described at https://docs.spring.io/spring-security/reference/6.1/servlet/saml2/logout.html - // Logout Service POST Binding URL: http://localhost:8080/logout/saml2/slo - .logout(logout -> logout - .logoutUrl(LOGOUT_URL) - .logoutSuccessHandler(logoutSuccessHandler(relyingPartyRegistrationRepository)) - ) - .build(); - } - - @Bean - public OpenSaml4AuthenticationProvider openSaml4AuthenticationProvider() { - OpenSaml4AuthenticationProvider authenticationProvider = new OpenSaml4AuthenticationProvider(); - authenticationProvider.setResponseAuthenticationConverter(rolesConverter()); - return authenticationProvider; - } - - private Converter rolesConverter() { - - Converter delegate = - OpenSaml4AuthenticationProvider.createDefaultResponseAuthenticationConverter(); - - return (responseToken) -> { - Saml2Authentication authentication = delegate.convert(responseToken); - var principal = (Saml2AuthenticatedPrincipal) Objects.requireNonNull(authentication).getPrincipal(); - Collection roles = principal.getAttribute(this.roleAttributeName); - Set mappedAuthorities = new HashSet<>(); - if (!Objects.isNull(roles)) { - mappedAuthorities.addAll(GrantedAuthorityUtil.generateGrantedAuthoritiesFromRoles(roles)); - } else { - mappedAuthorities.addAll(authentication.getAuthorities()); - } - return new Saml2Authentication(principal, authentication.getSaml2Response(), mappedAuthorities); - }; - } - - @Bean - public LogoutSuccessHandler logoutSuccessHandler(RelyingPartyRegistrationRepository relyingPartyRegistrationRepository) { - // Perform logout at the SAML2 IDP - DefaultRelyingPartyRegistrationResolver relyingPartyRegistrationResolver = - new DefaultRelyingPartyRegistrationResolver(relyingPartyRegistrationRepository); - OpenSaml4LogoutRequestResolver logoutRequestResolver = - new OpenSaml4LogoutRequestResolver(relyingPartyRegistrationResolver); - - return new Saml2RelyingPartyInitiatedLogoutSuccessHandler(logoutRequestResolver); - } - -} diff --git a/src/main/java/org/cbioportal/security/token/RestAuthenticationEntryPoint.java b/src/main/java/org/cbioportal/security/token/RestAuthenticationEntryPoint.java deleted file mode 100644 index 8b5136520b2..00000000000 --- a/src/main/java/org/cbioportal/security/token/RestAuthenticationEntryPoint.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (c) 2015 Memorial Sloan-Kettering Cancer Center. - * - * This library is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS - * FOR A PARTICULAR PURPOSE. The software and documentation provided hereunder - * is on an "as is" basis, and Memorial Sloan-Kettering Cancer Center has no - * obligations to provide maintenance, support, updates, enhancements or - * modifications. In no event shall Memorial Sloan-Kettering Cancer Center be - * liable to any party for direct, indirect, special, incidental or - * consequential damages, including lost profits, arising out of the use of this - * software and its documentation, even if Memorial Sloan-Kettering Cancer - * Center has been advised of the possibility of such damage. - */ - -/* - * This file is part of cBioPortal. - * - * cBioPortal is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -package org.cbioportal.security.token; - -import java.io.IOException; - -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; -import org.springframework.security.core.AuthenticationException; -import org.springframework.security.web.AuthenticationEntryPoint; - -public class RestAuthenticationEntryPoint implements AuthenticationEntryPoint { - - @Override - public void commence(HttpServletRequest request, HttpServletResponse response, - AuthenticationException authException) throws IOException { - response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized"); - } - -} diff --git a/src/main/java/org/cbioportal/security/token/TokenAuthenticationFilter.java b/src/main/java/org/cbioportal/security/token/TokenAuthenticationFilter.java deleted file mode 100644 index 42988160137..00000000000 --- a/src/main/java/org/cbioportal/security/token/TokenAuthenticationFilter.java +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Copyright (c) 2018 Memorial Sloan-Kettering Cancer Center. - * - * This library is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS - * FOR A PARTICULAR PURPOSE. The software and documentation provided hereunder - * is on an "as is" basis, and Memorial Sloan-Kettering Cancer Center has no - * obligations to provide maintenance, support, updates, enhancements or - * modifications. In no event shall Memorial Sloan-Kettering Cancer Center be - * liable to any party for direct, indirect, special, incidental or - * consequential damages, including lost profits, arising out of the use of this - * software and its documentation, even if Memorial Sloan-Kettering Cancer - * Center has been advised of the possibility of such damage. - */ - -/* - * This file is part of cBioPortal. - * - * cBioPortal is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . -*/ - -package org.cbioportal.security.token; - -import jakarta.servlet.ServletException; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; -import org.cbioportal.service.DataAccessTokenService; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.security.authentication.AuthenticationManager; -import org.springframework.security.authentication.BadCredentialsException; -import org.springframework.security.core.Authentication; -import org.springframework.security.core.AuthenticationException; -import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter; - -import java.io.IOException; - -import static com.google.common.net.HttpHeaders.AUTHORIZATION; - -/** - * - * @author Manda Wilson - */ -public class TokenAuthenticationFilter extends AbstractAuthenticationProcessingFilter { - - private DataAccessTokenService tokenService; - - private static final String BEARER = "Bearer"; - - private static final Logger LOG = LoggerFactory.getLogger(TokenAuthenticationFilter.class); - - public TokenAuthenticationFilter() { - // allow any request to contain an authorization header - super("/**"); - } - - public TokenAuthenticationFilter(String s, AuthenticationManager authenticationManagerBean) { - super(s, authenticationManagerBean); - } - - public TokenAuthenticationFilter(String s, AuthenticationManager authenticationManager, DataAccessTokenService tokenService) { - super(s, authenticationManager); - this.tokenService = tokenService; - } - - @Override - protected boolean requiresAuthentication(HttpServletRequest request, HttpServletResponse response) { - // only required if we do see an authorization header - String param = request.getHeader(AUTHORIZATION); - if (param == null) { - LOG.debug("attemptAuthentication(), authorization header is null, continue on to other security filters"); - return false; - } - return true; - } - - @Override - public Authentication attemptAuthentication (HttpServletRequest request, HttpServletResponse response) throws AuthenticationException, IOException, jakarta.servlet.ServletException{ - - String token = extractHeaderToken(request); - - if (token == null) { - LOG.error("No token was found in request header."); - throw new BadCredentialsException("No token was found in request header."); - } - - Authentication auth = tokenService.createAuthenticationRequest(token); - - return getAuthenticationManager().authenticate(auth); - } - - @Override - protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, jakarta.servlet.FilterChain chain, Authentication authResult) throws IOException, ServletException { - super.successfulAuthentication(request, response, chain, authResult); - chain.doFilter(request, response); - } - - /** - * Extract the bearer token from a header. - * - * @param request - * @return The token, or null if no authorization header was supplied - */ - protected String extractHeaderToken(HttpServletRequest request) { - String authorizationHeader = request.getHeader(AUTHORIZATION); - if (authorizationHeader != null && !authorizationHeader.isEmpty() && authorizationHeader.toLowerCase().startsWith(BEARER.toLowerCase())) { - return authorizationHeader.substring(BEARER.length()).trim(); - } - return null; - } - -} diff --git a/src/main/java/org/cbioportal/security/token/TokenAuthenticationSuccessHandler.java b/src/main/java/org/cbioportal/security/token/TokenAuthenticationSuccessHandler.java deleted file mode 100644 index b2db8dddabf..00000000000 --- a/src/main/java/org/cbioportal/security/token/TokenAuthenticationSuccessHandler.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (c) 2018 Memorial Sloan-Kettering Cancer Center. - * - * This library is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS - * FOR A PARTICULAR PURPOSE. The software and documentation provided hereunder - * is on an "as is" basis, and Memorial Sloan-Kettering Cancer Center has no - * obligations to provide maintenance, support, updates, enhancements or - * modifications. In no event shall Memorial Sloan-Kettering Cancer Center be - * liable to any party for direct, indirect, special, incidental or - * consequential damages, including lost profits, arising out of the use of this - * software and its documentation, even if Memorial Sloan-Kettering Cancer - * Center has been advised of the possibility of such damage. - */ - -/* - * This file is part of cBioPortal. - * - * cBioPortal is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . -*/ - -package org.cbioportal.security.token; - -import jakarta.servlet.ServletException; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; -import org.springframework.security.core.Authentication; -import org.springframework.security.web.authentication.AuthenticationSuccessHandler; -import org.springframework.stereotype.Component; - -import java.io.IOException; - -@Component -public class TokenAuthenticationSuccessHandler implements AuthenticationSuccessHandler { - - @Override - public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException { - // We do not need to do anything extra on REST authentication success, because there is no page to redirect to - } - -} diff --git a/src/main/java/org/cbioportal/security/token/config/DataAccessTokenConfig.java b/src/main/java/org/cbioportal/security/token/config/DataAccessTokenConfig.java deleted file mode 100644 index a800772cfa7..00000000000 --- a/src/main/java/org/cbioportal/security/token/config/DataAccessTokenConfig.java +++ /dev/null @@ -1,47 +0,0 @@ -package org.cbioportal.security.token.config; - -import org.cbioportal.persistence.SecurityRepository; -import org.cbioportal.security.token.oauth2.JwtTokenVerifierBuilder; -import org.cbioportal.security.token.oauth2.OAuth2DataAccessTokenServiceImpl; -import org.cbioportal.security.token.oauth2.OAuth2TokenAuthenticationProvider; -import org.cbioportal.security.token.oauth2.OAuth2TokenRefreshRestTemplate; -import org.cbioportal.security.token.uuid.UuidTokenAuthenticationProvider; -import org.cbioportal.service.impl.UnauthDataAccessTokenServiceImpl; -import org.cbioportal.utils.config.annotation.ConditionalOnProperty; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.web.client.RestTemplate; - -@Configuration -@ConditionalOnProperty(name = "dat.method", havingValue = {"", "none"}, isNot = true) -public class DataAccessTokenConfig { - - - // provider - @Bean("tokenAuthenticationProvider") - @ConditionalOnProperty(name = "dat.method", havingValue = "oauth2") - public OAuth2TokenAuthenticationProvider oauth2TokenAuthenticationProvider(OAuth2TokenRefreshRestTemplate refreshRestTemplate) { - return new OAuth2TokenAuthenticationProvider(refreshRestTemplate); - } - - // TODO - implement jwt providers - @Bean("tokenAuthenticationProvider") - @ConditionalOnProperty(name = "dat.method", havingValue = "uuid") - public UuidTokenAuthenticationProvider uuidTokenAuthenticationProvider(SecurityRepository repository) { - return new UuidTokenAuthenticationProvider(repository); - } - - // service - @Bean("dataAccessTokenService") - @ConditionalOnProperty(name = "dat.method", havingValue = "oauth2") - public OAuth2DataAccessTokenServiceImpl oauth2DataAccessTokenService(RestTemplate template, JwtTokenVerifierBuilder jwtTokenVerifierBuilder) { - return new OAuth2DataAccessTokenServiceImpl(template, jwtTokenVerifierBuilder); - } - - @Bean("dataAccessTokenService") - @ConditionalOnProperty(name = "dat.method", havingValue = "none") - public UnauthDataAccessTokenServiceImpl unauthDataAccessTokenService() { - return new UnauthDataAccessTokenServiceImpl(); - } - -} \ No newline at end of file diff --git a/src/main/java/org/cbioportal/security/token/oauth2/OAuth2BearerAuthenticationToken.java b/src/main/java/org/cbioportal/security/token/oauth2/OAuth2BearerAuthenticationToken.java deleted file mode 100644 index 1e60681df90..00000000000 --- a/src/main/java/org/cbioportal/security/token/oauth2/OAuth2BearerAuthenticationToken.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (c) 2020 The Hyve B.V. - * - * This library is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS - * FOR A PARTICULAR PURPOSE. The software and documentation provided hereunder - * is on an "as is" basis, and Memorial Sloan-Kettering Cancer Center has no - * obligations to provide maintenance, support, updates, enhancements or - * modifications. In no event shall Memorial Sloan-Kettering Cancer Center be - * liable to any party for direct, indirect, special, incidental or - * consequential damages, including lost profits, arising out of the use of this - * software and its documentation, even if Memorial Sloan-Kettering Cancer - * Center has been advised of the possibility of such damage. - */ - -/* - * This file is part of cBioPortal. - * - * cBioPortal is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . -*/ - -package org.cbioportal.security.token.oauth2; - -import java.util.Collection; -import java.util.HashSet; - -import org.springframework.security.authentication.AbstractAuthenticationToken; -import org.springframework.security.core.GrantedAuthority; - -/** - * OAuth2BearerAuthenticationToken - */ -public class OAuth2BearerAuthenticationToken extends AbstractAuthenticationToken { - - private static final long serialVersionUID = 1L; - private final String accessToken; - private final Object principal; - - public OAuth2BearerAuthenticationToken(String accessToken) { - super(new HashSet<>()); - this.principal = null; - this.accessToken = accessToken; - } - - public OAuth2BearerAuthenticationToken(Object principal, String accessToken) { - super(new HashSet<>()); - this.accessToken = accessToken; - this.principal = principal; - } - - public OAuth2BearerAuthenticationToken(Object principal, Collection authorities) { - super(authorities); - accessToken = null; - this.principal = principal; - setAuthenticated(true); - } - - @Override - public Object getCredentials() { - return accessToken; - } - - @Override - public Object getPrincipal() { - return principal; - } - - -} \ No newline at end of file diff --git a/src/main/java/org/cbioportal/security/token/oauth2/OAuth2DataAccessTokenServiceImpl.java b/src/main/java/org/cbioportal/security/token/oauth2/OAuth2DataAccessTokenServiceImpl.java deleted file mode 100644 index 9e546ce10bf..00000000000 --- a/src/main/java/org/cbioportal/security/token/oauth2/OAuth2DataAccessTokenServiceImpl.java +++ /dev/null @@ -1,202 +0,0 @@ -/* - * Copyright (c) 2020 The Hyve B.V. - * - * This library is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS - * FOR A PARTICULAR PURPOSE. The software and documentation provided hereunder - * is on an "as is" basis, and Memorial Sloan-Kettering Cancer Center has no - * obligations to provide maintenance, support, updates, enhancements or - * modifications. In no event shall Memorial Sloan-Kettering Cancer Center be - * liable to any party for direct, indirect, special, incidental or - * consequential damages, including lost profits, arising out of the use of this - * software and its documentation, even if Memorial Sloan-Kettering Cancer - * Center has been advised of the possibility of such damage. - */ - -/* - * This file is part of cBioPortal. - * - * cBioPortal is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . -*/ - -package org.cbioportal.security.token.oauth2; - -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import org.cbioportal.model.DataAccessToken; -import org.cbioportal.service.DataAccessTokenService; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.http.HttpEntity; -import org.springframework.http.HttpHeaders; -import org.springframework.http.ResponseEntity; -import org.springframework.security.authentication.BadCredentialsException; -import org.springframework.security.core.Authentication; -import org.springframework.security.jwt.Jwt; -import org.springframework.security.jwt.JwtHelper; -import org.springframework.util.LinkedMultiValueMap; -import org.springframework.util.MultiValueMap; -import org.springframework.web.client.RestTemplate; - -import java.io.IOException; -import java.util.Date; -import java.util.List; - -public class OAuth2DataAccessTokenServiceImpl implements DataAccessTokenService { - @Value("${dat.oauth2.issuer}") - private String issuer; - - @Value("${dat.oauth2.clientId}") - private String clientId; - - @Value("${dat.oauth2.clientSecret}") - private String clientSecret; - - @Value("${dat.oauth2.accessTokenUri}") - private String accessTokenUri; - - @Value("${dat.oauth2.redirectUri}") - private String redirectUri; - - private final RestTemplate template; - - private final JwtTokenVerifierBuilder jwtTokenVerifierBuilder; - - @Autowired - public OAuth2DataAccessTokenServiceImpl(RestTemplate template, JwtTokenVerifierBuilder jwtTokenVerifierBuilder) { - this.template = template; - this.jwtTokenVerifierBuilder = jwtTokenVerifierBuilder; - } - - @Override - // request offline token from authentication server via back channel - public DataAccessToken createDataAccessToken(final String accessCode) { - - HttpHeaders headers = new HttpHeaders(); - - MultiValueMap map = new LinkedMultiValueMap<>(); - map.add("grant_type", "authorization_code"); - map.add("code", accessCode); - map.add("client_id", clientId); - map.add("client_secret", clientSecret); - map.add("redirect_uri", redirectUri); - map.add("scope", "openid offline_access"); // `openid must be included according to OIDC standards - - HttpEntity> offlineRequest = new HttpEntity<>(map, headers); - - ResponseEntity response = template.postForEntity(accessTokenUri, offlineRequest, String.class); - - String offlineToken = ""; - try { - JsonNode json = new ObjectMapper().readTree(response.getBody()); - offlineToken = json.get("refresh_token").asText(); - } catch (Exception e) { - throw new BadCredentialsException("Offline token could not be retrieved using access_code: "+ accessCode ); - } - - return new DataAccessToken(offlineToken); - } - - @Override - public List getAllDataAccessTokens(final String username) { - throw new UnsupportedOperationException( - "this implementation of (pure) JWT Data Access Tokens does not allow retrieval of stored tokens"); - } - - @Override - public DataAccessToken getDataAccessToken(final String username) { - throw new UnsupportedOperationException( - "this implementation of (pure) JWT Data Access Tokens does not allow retrieval of stored tokens"); - } - - @Override - public DataAccessToken getDataAccessTokenInfo(final String token) { - throw new UnsupportedOperationException( - "this implementation of (pure) JWT Data Access Tokens does not allow this operation"); - } - - @Override - public void revokeAllDataAccessTokens(final String username) { - throw new UnsupportedOperationException( - "this implementation of (pure) JWT Data Access Tokens does not allow revocation of tokens"); - } - - @Override - public void revokeDataAccessToken(final String token) { - throw new UnsupportedOperationException( - "this implementation of (pure) JWT Data Access Tokens does not allow revocation of tokens"); - } - - @Override - public Boolean isValid(final String token) { - final String kid = JwtHelper.headers(token).get("kid"); - try { - - final Jwt tokenDecoded = JwtHelper.decodeAndVerify(token, jwtTokenVerifierBuilder.build(kid)); - final String claims = tokenDecoded.getClaims(); - final JsonNode claimsMap = new ObjectMapper().readTree(claims); - - hasValidIssuer(claimsMap); - hasValidClientId(claimsMap); - - } catch (Exception e) { - throw new BadCredentialsException("Token is not valid (wrong key, issuer, or audience)."); - } - return true; - } - - @Override - public String getUsername(final String token) { - - final Jwt tokenDecoded = JwtHelper.decode(token); - - final String claims = tokenDecoded.getClaims(); - JsonNode claimsMap; - try { - claimsMap = new ObjectMapper().readTree(claims); - } catch (IOException e) { - throw new BadCredentialsException("User name could not be found in offline token."); - } - - if (! claimsMap.has("sub")) { - throw new BadCredentialsException("User name could not be found in offline token."); - } - - return claimsMap.get("sub").asText(); - } - - @Override - public Date getExpiration(final String token) { - return null; - } - - private void hasValidIssuer(final JsonNode claimsMap) throws BadCredentialsException { - if (!claimsMap.get("iss").asText().equals(issuer)) { - throw new BadCredentialsException("Wrong Issuer found in token"); - } - } - - private void hasValidClientId(final JsonNode claimsMap) throws BadCredentialsException { - if (!claimsMap.get("aud").asText().equals(clientId)) { - throw new BadCredentialsException("Wrong clientId found in token"); - } - } - - @Override - public Authentication createAuthenticationRequest(String offlineToken) { - // validity of the offline token is checked by the OAuth2 authentication server - return new OAuth2BearerAuthenticationToken(offlineToken); - } - -} diff --git a/src/main/java/org/cbioportal/security/token/oauth2/OAuth2TokenAuthenticationProvider.java b/src/main/java/org/cbioportal/security/token/oauth2/OAuth2TokenAuthenticationProvider.java deleted file mode 100644 index d8dfafa7b66..00000000000 --- a/src/main/java/org/cbioportal/security/token/oauth2/OAuth2TokenAuthenticationProvider.java +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Copyright (c) 2020 The Hyve B.V. - * - * This library is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS - * FOR A PARTICULAR PURPOSE. The software and documentation provided hereunder - * is on an "as is" basis, and Memorial Sloan-Kettering Cancer Center has no - * obligations to provide maintenance, support, updates, enhancements or - * modifications. In no event shall Memorial Sloan-Kettering Cancer Center be - * liable to any party for direct, indirect, special, incidental or - * consequential damages, including lost profits, arising out of the use of this - * software and its documentation, even if Memorial Sloan-Kettering Cancer - * Center has been advised of the possibility of such damage. - */ - -/* - * This file is part of cBioPortal. - * - * cBioPortal is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . -*/ - -package org.cbioportal.security.token.oauth2; - -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import org.cbioportal.security.util.ClaimRoleExtractorUtil; -import org.cbioportal.security.util.GrantedAuthorityUtil; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.security.authentication.AuthenticationProvider; -import org.springframework.security.authentication.BadCredentialsException; -import org.springframework.security.core.Authentication; -import org.springframework.security.core.AuthenticationException; -import org.springframework.security.core.GrantedAuthority; -import org.springframework.security.jwt.Jwt; -import org.springframework.security.jwt.JwtHelper; - -import java.io.IOException; -import java.util.Collection; - -public class OAuth2TokenAuthenticationProvider implements AuthenticationProvider { - - @Value("${dat.oauth2.jwtRolesPath:resource_access::cbioportal::roles}") - private String jwtRolesPath; - - private final OAuth2TokenRefreshRestTemplate tokenRefreshRestTemplate; - - public OAuth2TokenAuthenticationProvider(OAuth2TokenRefreshRestTemplate tokenRefreshRestTemplate) { - this.tokenRefreshRestTemplate = tokenRefreshRestTemplate; - } - @Override - public boolean supports(Class authentication) { - return authentication.isAssignableFrom(OAuth2BearerAuthenticationToken.class); - } - - @Override - public Authentication authenticate(Authentication authentication) throws AuthenticationException { - - String offlineToken = (String) authentication.getCredentials(); - - // Note: validity of the offline token is not checked in cBioPortal - // backend, is handeled by the OAuth2 authentication server. - - // request an access token from the OAuth2 identity provider - final String accessToken = tokenRefreshRestTemplate.getAccessToken(offlineToken); - - Collection authorities = extractAuthorities(accessToken); - String username = getUsername(accessToken); - - return new OAuth2BearerAuthenticationToken(username, authorities); - } - - // Read roles/authorities from JWT token. - private Collection extractAuthorities(final String token) throws BadCredentialsException { - try { - final Jwt tokenDecoded = JwtHelper.decode(token); - final String claims = tokenDecoded.getClaims(); - return GrantedAuthorityUtil.generateGrantedAuthoritiesFromRoles(ClaimRoleExtractorUtil.extractClientRoles(claims, jwtRolesPath)); - - } catch (Exception e) { - throw new BadCredentialsException("Authorities could not be extracted from access token."); - } - } - - private String getUsername(final String token) { - - final Jwt tokenDecoded = JwtHelper.decode(token); - - final String claims = tokenDecoded.getClaims(); - JsonNode claimsMap; - try { - claimsMap = new ObjectMapper().readTree(claims); - } catch (IOException e) { - throw new BadCredentialsException("User name could not be found in access token."); - } - - if (! claimsMap.has("sub")) { - throw new BadCredentialsException("User name could not be found in access token."); - } - - return claimsMap.get("sub").asText(); - } - -} diff --git a/src/main/java/org/cbioportal/security/token/oauth2/OAuth2TokenRefreshRestTemplate.java b/src/main/java/org/cbioportal/security/token/oauth2/OAuth2TokenRefreshRestTemplate.java deleted file mode 100644 index fefe7ccb2d8..00000000000 --- a/src/main/java/org/cbioportal/security/token/oauth2/OAuth2TokenRefreshRestTemplate.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright (c) 2020 The Hyve B.V. - * - * This library is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS - * FOR A PARTICULAR PURPOSE. The software and documentation provided hereunder - * is on an "as is" basis, and Memorial Sloan-Kettering Cancer Center has no - * obligations to provide maintenance, support, updates, enhancements or - * modifications. In no event shall Memorial Sloan-Kettering Cancer Center be - * liable to any party for direct, indirect, special, incidental or - * consequential damages, including lost profits, arising out of the use of this - * software and its documentation, even if Memorial Sloan-Kettering Cancer - * Center has been advised of the possibility of such damage. - */ - -/* - * This file is part of cBioPortal. - * - * cBioPortal is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . -*/ - -package org.cbioportal.security.token.oauth2; - -import com.fasterxml.jackson.databind.ObjectMapper; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.http.HttpEntity; -import org.springframework.http.HttpHeaders; -import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; -import org.springframework.security.authentication.BadCredentialsException; -import org.springframework.stereotype.Component; -import org.springframework.util.LinkedMultiValueMap; -import org.springframework.util.MultiValueMap; -import org.springframework.web.client.RestTemplate; - -@Component -public class OAuth2TokenRefreshRestTemplate { - - private final Logger logger = LoggerFactory.getLogger(getClass()); - - @Value("${dat.oauth2.clientId:}") - private String clientId; - - @Value("${dat.oauth2.clientSecret:}") - private String clientSecret; - - @Value("${dat.oauth2.accessTokenUri:}") - private String accessTokenUri; - - private final RestTemplate template; - - @Autowired - public OAuth2TokenRefreshRestTemplate(RestTemplate template) { - this.template = template; - } - - public String getAccessToken(String offlineToken) throws BadCredentialsException { - HttpHeaders headers = new HttpHeaders(); - headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); - - MultiValueMap map = new LinkedMultiValueMap<>(); - map.add("grant_type", "refresh_token"); - map.add("client_id", clientId); - map.add("client_secret", clientSecret); - map.add("refresh_token", offlineToken); - - HttpEntity> request = new HttpEntity<>(map, headers); - - ResponseEntity response = null; - try { - response = template.postForEntity(accessTokenUri, request, String.class); - String accessToken = new ObjectMapper().readTree(response.getBody()).get("access_token").asText(); - logger.debug("Received access token from authentication server:\n{}",accessToken); - return accessToken; - } catch (Exception e) { - logger.error("Authentication server did not return an access token. Server response:\n{}",response); - throw new BadCredentialsException("Authentication server did not return an access token."); - } - - } - -} diff --git a/src/main/java/org/cbioportal/security/token/uuid/UuidTokenAuthenticationProvider.java b/src/main/java/org/cbioportal/security/token/uuid/UuidTokenAuthenticationProvider.java deleted file mode 100644 index 85268a3df22..00000000000 --- a/src/main/java/org/cbioportal/security/token/uuid/UuidTokenAuthenticationProvider.java +++ /dev/null @@ -1,43 +0,0 @@ -package org.cbioportal.security.token.uuid; - -import org.cbioportal.model.UserAuthorities; -import org.cbioportal.persistence.SecurityRepository; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.security.authentication.AuthenticationProvider; -import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; -import org.springframework.security.core.Authentication; -import org.springframework.security.core.AuthenticationException; -import org.springframework.security.core.GrantedAuthority; -import org.springframework.security.core.authority.AuthorityUtils; - -import java.util.HashSet; -import java.util.Objects; -import java.util.Set; - -public class UuidTokenAuthenticationProvider implements AuthenticationProvider { - private static final Logger log = LoggerFactory.getLogger(UuidTokenAuthenticationProvider.class); - - private final SecurityRepository securityRepository; - - public UuidTokenAuthenticationProvider(final SecurityRepository securityRepository) { - this.securityRepository = securityRepository; - } - - @Override - public Authentication authenticate(Authentication authentication) throws AuthenticationException { - String user = (String) authentication.getPrincipal(); - log.debug("Attempt to grab user Authorities for user: {}", user); - UserAuthorities authorities = securityRepository.getPortalUserAuthorities(user); - Set mappedAuthorities = new HashSet<>(); - if (!Objects.isNull(authorities)) { - mappedAuthorities.addAll(AuthorityUtils.createAuthorityList(authorities.getAuthorities())); - } - return new UsernamePasswordAuthenticationToken(user, "does not match unused", mappedAuthorities); - } - - @Override - public boolean supports(Class authentication) { - return authentication.isAssignableFrom(UsernamePasswordAuthenticationToken.class); - } -} diff --git a/src/main/java/org/cbioportal/security/util/ClaimRoleExtractorUtil.java b/src/main/java/org/cbioportal/security/util/ClaimRoleExtractorUtil.java deleted file mode 100644 index 1f3e094529a..00000000000 --- a/src/main/java/org/cbioportal/security/util/ClaimRoleExtractorUtil.java +++ /dev/null @@ -1,64 +0,0 @@ -package org.cbioportal.security.util; - -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.security.authentication.BadCredentialsException; - -import java.util.Collection; -import java.util.Collections; -import java.util.Map; -import java.util.stream.Collectors; -import java.util.stream.StreamSupport; - -public class ClaimRoleExtractorUtil { - private static final Logger log = LoggerFactory.getLogger(ClaimRoleExtractorUtil.class); - - public static Collection extractClientRoles(final Map claims, final String jwtRolesPath) { - try { - // Convert the map to a JSON string - ObjectMapper objectMapper = new ObjectMapper(); - String jsonString = objectMapper.writeValueAsString(claims); - - JsonNode rolesCursor = new ObjectMapper().readTree(jsonString); - return extractClientRoles(rolesCursor, jwtRolesPath); - } catch (Exception e) { - log.error("Error extracting claims as a json string"); - } - return Collections.emptyList(); - } - - public static Collection extractClientRoles(final String claims, final String jwtRolesPath) { - try { - JsonNode rolesCursor = new ObjectMapper().readTree(claims); - return extractClientRoles(rolesCursor, jwtRolesPath); - } catch (Exception e) { - log.error("Error converting Json String to JsonNode Object"); - } - return Collections.emptyList(); - } - - public static Collection extractClientRoles(final JsonNode claims, final String jwtRolesPath) { - try { - - JsonNode rolesCursor = claims; - for (var keyName : jwtRolesPath.split("::")) { - if (rolesCursor.has(keyName)) { - rolesCursor = rolesCursor.get(keyName); - } else { - throw new BadCredentialsException("Cannot Find user Roles in JWT Access Token "); - } - - } - return StreamSupport.stream(rolesCursor.spliterator(), false) - .map(JsonNode::asText) - .collect(Collectors.toSet()); - } catch (Exception e) { - log.error("Error Grabbing Client Roles from OIDC User Info: Realm roles must follow the convention {}", jwtRolesPath); - } - return Collections.emptyList(); - } - - -} diff --git a/src/main/java/org/cbioportal/security/util/GrantedAuthorityUtil.java b/src/main/java/org/cbioportal/security/util/GrantedAuthorityUtil.java deleted file mode 100644 index 68645faf456..00000000000 --- a/src/main/java/org/cbioportal/security/util/GrantedAuthorityUtil.java +++ /dev/null @@ -1,14 +0,0 @@ -package org.cbioportal.security.util; - -import org.springframework.security.core.GrantedAuthority; -import org.springframework.security.core.authority.SimpleGrantedAuthority; - -import java.util.Collection; -import java.util.stream.Collectors; - -public class GrantedAuthorityUtil { - private static final String PREFIX_RESOURCE_ROLE = "ROLE_"; - public static Collection generateGrantedAuthoritiesFromRoles(Collection roles) { - return roles.stream().map(role -> new SimpleGrantedAuthority(PREFIX_RESOURCE_ROLE + role)).collect(Collectors.toSet()); - } -} diff --git a/src/main/java/org/cbioportal/service/AlterationCountService.java b/src/main/java/org/cbioportal/service/AlterationCountService.java deleted file mode 100644 index 639c1daab7d..00000000000 --- a/src/main/java/org/cbioportal/service/AlterationCountService.java +++ /dev/null @@ -1,82 +0,0 @@ -package org.cbioportal.service; - -import org.apache.commons.math3.util.Pair; -import org.cbioportal.model.*; -import org.cbioportal.model.util.Select; -import org.cbioportal.service.exception.StudyNotFoundException; -import org.cbioportal.web.parameter.CategorizedClinicalDataCountFilter; -import org.cbioportal.web.parameter.CustomSampleIdentifier; -import org.cbioportal.web.parameter.SampleIdentifier; -import org.cbioportal.web.parameter.StudyViewFilter; - -import java.util.List; - -public interface AlterationCountService { - - Pair, Long> getSampleAlterationGeneCounts(List molecularProfileCaseIdentifiers, - Select entrezGeneIds, - boolean includeFrequency, - boolean includeMissingAlterationsFromGenePanel, - AlterationFilter alterationFilter); - - Pair, Long> getPatientAlterationGeneCounts(List molecularProfileCaseIdentifiers, - Select entrezGeneIds, - boolean includeFrequency, - boolean includeMissingAlterationsFromGenePanel, - AlterationFilter alterationFilter); - - Pair, Long> getSampleMutationGeneCounts(List molecularProfileCaseIdentifiers, - Select entrezGeneIds, - boolean includeFrequency, - boolean includeMissingAlterationsFromGenePanel, - AlterationFilter alterationFilter); - - Pair, Long> getPatientMutationGeneCounts(List molecularProfileCaseIdentifiers, - Select entrezGeneIds, - boolean includeFrequency, - boolean includeMissingAlterationsFromGenePanel, - AlterationFilter alterationFilter); - - Pair, Long> getSampleStructuralVariantGeneCounts(List molecularProfileCaseIdentifiers, - Select entrezGeneIds, - boolean includeFrequency, - boolean includeMissingAlterationsFromGenePanel, - AlterationFilter alterationFilter); - - Pair, Long> getPatientStructuralVariantGeneCounts(List molecularProfileCaseIdentifiers, - Select entrezGeneIds, - boolean includeFrequency, - boolean includeMissingAlterationsFromGenePanel, - AlterationFilter alterationFilter); - - Pair, Long> getSampleStructuralVariantCounts(List molecularProfileCaseIdentifiers, - boolean includeFrequency, - boolean includeMissingAlterationsFromGenePanel, - AlterationFilter alterationFilter); - -// Should be restored when old CNA count endpoint is retired -// Pair, Long> getSampleCnaCounts(List molecularProfileCaseIdentifiers, -// Select entrezGeneIds, -// boolean includeFrequency, -// boolean includeMissingAlterationsFromGenePanel, -// AlterationEventTypeFilter alterationFilter); -// -// Pair, Long> getPatientCnaCounts(List molecularProfileCaseIdentifiers, -// Select entrezGeneIds, -// boolean includeFrequency, -// boolean includeMissingAlterationsFromGenePanel, -// AlterationEventTypeFilter alterationFilter); - - // Should be removed when old CNA count endpoint is retired - Pair, Long> getSampleCnaGeneCounts(List molecularProfileCaseIdentifiers, - Select entrezGeneIds, - boolean includeFrequency, - boolean includeMissingAlterationsFromGenePanel, - AlterationFilter alterationFilter); - - Pair, Long> getPatientCnaGeneCounts(List molecularProfileCaseIdentifiers, - Select entrezGeneIds, - boolean includeFrequency, - boolean includeMissingAlterationsFromGenePanel, - AlterationFilter alterationFilter); -} diff --git a/src/main/java/org/cbioportal/service/AlterationDriverAnnotationService.java b/src/main/java/org/cbioportal/service/AlterationDriverAnnotationService.java deleted file mode 100644 index 6f13a93f0f0..00000000000 --- a/src/main/java/org/cbioportal/service/AlterationDriverAnnotationService.java +++ /dev/null @@ -1,9 +0,0 @@ -package org.cbioportal.service; - -import org.cbioportal.model.CustomDriverAnnotationReport; - -import java.util.List; - -public interface AlterationDriverAnnotationService { - CustomDriverAnnotationReport getCustomDriverAnnotationProps(List molecularProfileIds); -} \ No newline at end of file diff --git a/src/main/java/org/cbioportal/service/AlterationEnrichmentService.java b/src/main/java/org/cbioportal/service/AlterationEnrichmentService.java deleted file mode 100644 index 98d01347e38..00000000000 --- a/src/main/java/org/cbioportal/service/AlterationEnrichmentService.java +++ /dev/null @@ -1,19 +0,0 @@ -package org.cbioportal.service; - -import org.cbioportal.model.AlterationEnrichment; -import org.cbioportal.model.AlterationFilter; -import org.cbioportal.model.EnrichmentType; -import org.cbioportal.model.MolecularProfileCaseIdentifier; -import org.cbioportal.service.exception.MolecularProfileNotFoundException; - -import java.util.List; -import java.util.Map; - -public interface AlterationEnrichmentService { - - List getAlterationEnrichments( - Map> molecularProfileCaseSets, - EnrichmentType enrichmentType, - AlterationFilter alterationFilter) - throws MolecularProfileNotFoundException; -} diff --git a/src/main/java/org/cbioportal/service/AttributeByStudyService.java b/src/main/java/org/cbioportal/service/AttributeByStudyService.java deleted file mode 100644 index a1f198d1e15..00000000000 --- a/src/main/java/org/cbioportal/service/AttributeByStudyService.java +++ /dev/null @@ -1,9 +0,0 @@ -package org.cbioportal.service; - -import org.cbioportal.model.ClinicalAttribute; - -import java.util.List; - -public interface AttributeByStudyService { - List getClinicalAttributesByStudyIdsAndAttributeIds(List studyIds, List attributeIds); -} diff --git a/src/main/java/org/cbioportal/service/CacheService.java b/src/main/java/org/cbioportal/service/CacheService.java deleted file mode 100644 index ca0831f361e..00000000000 --- a/src/main/java/org/cbioportal/service/CacheService.java +++ /dev/null @@ -1,10 +0,0 @@ -package org.cbioportal.service; - -import org.cbioportal.service.exception.CacheOperationException; - -import java.util.List; - -public interface CacheService { - void clearCaches(boolean springManagedCache) throws CacheOperationException; - void clearCachesForStudy(String studyId, boolean springManagedCache) throws CacheOperationException; -} diff --git a/src/main/java/org/cbioportal/service/CacheStatisticsService.java b/src/main/java/org/cbioportal/service/CacheStatisticsService.java deleted file mode 100644 index 94453f84c6f..00000000000 --- a/src/main/java/org/cbioportal/service/CacheStatisticsService.java +++ /dev/null @@ -1,13 +0,0 @@ -package org.cbioportal.service; - -import java.util.*; -import org.cbioportal.service.exception.CacheNotFoundException; - -public interface CacheStatisticsService { - - List getKeyCountsPerClass(String cacheName) throws CacheNotFoundException; - - List getKeysInCache(String cacheName) throws CacheNotFoundException; - - String getCacheStatistics(); -} diff --git a/src/main/java/org/cbioportal/service/CancerTypeService.java b/src/main/java/org/cbioportal/service/CancerTypeService.java deleted file mode 100644 index fad6e41b1d3..00000000000 --- a/src/main/java/org/cbioportal/service/CancerTypeService.java +++ /dev/null @@ -1,20 +0,0 @@ -package org.cbioportal.service; - -import org.cbioportal.model.TypeOfCancer; -import org.cbioportal.model.meta.BaseMeta; -import org.cbioportal.service.exception.CancerTypeNotFoundException; - -import java.util.List; -import java.util.Map; - -public interface CancerTypeService { - - List getAllCancerTypes(String projection, Integer pageSize, Integer pageNumber, String sortBy, - String direction); - - BaseMeta getMetaCancerTypes(); - - TypeOfCancer getCancerType(String cancerTypeId) throws CancerTypeNotFoundException; - - Map getPrimarySiteMap(); -} diff --git a/src/main/java/org/cbioportal/service/ClinicalAttributeService.java b/src/main/java/org/cbioportal/service/ClinicalAttributeService.java deleted file mode 100644 index 3b648824419..00000000000 --- a/src/main/java/org/cbioportal/service/ClinicalAttributeService.java +++ /dev/null @@ -1,34 +0,0 @@ -package org.cbioportal.service; - -import org.cbioportal.model.ClinicalAttribute; -import org.cbioportal.model.ClinicalAttributeCount; -import org.cbioportal.model.meta.BaseMeta; -import org.cbioportal.service.exception.ClinicalAttributeNotFoundException; -import org.cbioportal.service.exception.StudyNotFoundException; - -import java.util.List; - -public interface ClinicalAttributeService extends AttributeByStudyService { - - List getAllClinicalAttributes(String projection, Integer pageSize, Integer pageNumber, - String sortBy, String direction); - - BaseMeta getMetaClinicalAttributes(); - - ClinicalAttribute getClinicalAttribute(String studyId, String clinicalAttributeId) - throws ClinicalAttributeNotFoundException, StudyNotFoundException; - - List getAllClinicalAttributesInStudy(String studyId, String projection, Integer pageSize, - Integer pageNumber, String sortBy, String direction) throws StudyNotFoundException; - - BaseMeta getMetaClinicalAttributesInStudy(String studyId) throws StudyNotFoundException; - - List fetchClinicalAttributes(List studyIds, String projection); - - BaseMeta fetchMetaClinicalAttributes(List studyIds); - - List getClinicalAttributeCountsBySampleIds(List studyIds, List sampleIds); - - List getClinicalAttributeCountsBySampleListId(String sampleListId); - -} diff --git a/src/main/java/org/cbioportal/service/ClinicalDataDensityPlotService.java b/src/main/java/org/cbioportal/service/ClinicalDataDensityPlotService.java deleted file mode 100644 index 211963e11b8..00000000000 --- a/src/main/java/org/cbioportal/service/ClinicalDataDensityPlotService.java +++ /dev/null @@ -1,13 +0,0 @@ -package org.cbioportal.service; - -import org.cbioportal.model.ClinicalData; -import org.cbioportal.model.DensityPlotData; -import org.cbioportal.web.parameter.StudyViewFilter; -import org.cbioportal.web.util.DensityPlotParameters; - -import java.math.BigDecimal; -import java.util.List; - -public interface ClinicalDataDensityPlotService { - DensityPlotData getDensityPlotData(List filteredClinicalData, DensityPlotParameters densityPlotParameters, StudyViewFilter studyViewFilter); -} diff --git a/src/main/java/org/cbioportal/service/ClinicalDataService.java b/src/main/java/org/cbioportal/service/ClinicalDataService.java deleted file mode 100644 index b57474d1c4f..00000000000 --- a/src/main/java/org/cbioportal/service/ClinicalDataService.java +++ /dev/null @@ -1,60 +0,0 @@ -package org.cbioportal.service; - -import org.apache.commons.lang3.tuple.ImmutablePair; -import org.cbioportal.model.ClinicalData; -import org.cbioportal.model.ClinicalDataCountItem; -import org.cbioportal.model.SampleClinicalDataCollection; -import org.cbioportal.model.meta.BaseMeta; -import org.cbioportal.service.exception.PatientNotFoundException; -import org.cbioportal.service.exception.SampleNotFoundException; -import org.cbioportal.service.exception.StudyNotFoundException; -import java.util.List; - -public interface ClinicalDataService { - - List getAllClinicalDataOfSampleInStudy(String studyId, String sampleId, String attributeId, - String projection, Integer pageSize, Integer pageNumber, - String sortBy, String direction) - throws SampleNotFoundException, StudyNotFoundException; - - BaseMeta getMetaSampleClinicalData(String studyId, String sampleId, String attributeId) - throws SampleNotFoundException, StudyNotFoundException; - - List getAllClinicalDataOfPatientInStudy(String studyId, String patientId, String attributeId, - String projection, Integer pageSize, - Integer pageNumber, String sortBy, String direction) - throws PatientNotFoundException, StudyNotFoundException; - - BaseMeta getMetaPatientClinicalData(String studyId, String patientId, String attributeId) - throws PatientNotFoundException, StudyNotFoundException; - - List getAllClinicalDataInStudy(String studyId, String attributeId, - String clinicalDataType, String projection, - Integer pageSize, Integer pageNumber, String sortBy, - String direction) throws StudyNotFoundException; - - BaseMeta getMetaAllClinicalData(String studyId, String attributeId, String clinicalDataType) - throws StudyNotFoundException; - - List fetchAllClinicalDataInStudy(String studyId, List ids, List attributeIds, - String clinicalDataType, String projection) - throws StudyNotFoundException; - - BaseMeta fetchMetaClinicalDataInStudy(String studyId, List ids, List attributeIds, - String clinicalDataType) throws StudyNotFoundException; - - List fetchClinicalData(List studyIds, List ids, List attributeIds, - String clinicalDataType, String projection); - - BaseMeta fetchMetaClinicalData(List studyIds, List ids, List attributeIds, - String clinicalDataType); - - List fetchClinicalDataCounts(List studyIds, List sampleIds, List attributeIds); - - List getPatientClinicalDataDetailedToSample(List studyIds, List patientIds, - List attributeIds); - - ImmutablePair fetchSampleClinicalTable(List studyIds, List sampleIds, Integer pageSize, - Integer pageNumber, String searchTerm, String sortBy, String direction); - -} diff --git a/src/main/java/org/cbioportal/service/ClinicalEventService.java b/src/main/java/org/cbioportal/service/ClinicalEventService.java deleted file mode 100644 index ad0009ac0b6..00000000000 --- a/src/main/java/org/cbioportal/service/ClinicalEventService.java +++ /dev/null @@ -1,41 +0,0 @@ -package org.cbioportal.service; - -import org.cbioportal.model.ClinicalData; -import org.cbioportal.model.ClinicalEvent; -import org.cbioportal.model.ClinicalEventTypeCount; -import org.cbioportal.model.meta.BaseMeta; -import org.cbioportal.service.exception.PatientNotFoundException; -import org.cbioportal.service.exception.StudyNotFoundException; -import org.cbioportal.web.parameter.SurvivalRequest; - -import java.util.List; -import java.util.Map; -import java.util.Set; - -public interface ClinicalEventService { - - List getAllClinicalEventsOfPatientInStudy(String studyId, String patientId, String projection, - Integer pageSize, Integer pageNumber, String sortBy, - String direction) - throws PatientNotFoundException, StudyNotFoundException; - - BaseMeta getMetaPatientClinicalEvents(String studyId, String patientId) - throws PatientNotFoundException, StudyNotFoundException; - - List getAllClinicalEventsInStudy(String studyId, String projection, Integer pageSize, - Integer pageNumber, String sortBy, String direction); - - BaseMeta getMetaClinicalEvents(String studyId) - throws StudyNotFoundException; - - Map> getPatientsSamplesPerClinicalEventType(List studyIds, List sampleIds); - - List getClinicalEventTypeCounts(List studyIds, List sampleIds); - - List getSurvivalData(List studyIds, List patientIds, - String attributeIdPrefix, - SurvivalRequest survivalRequest); - - List getClinicalEventsMeta(List studyIds, List patientIds, - List clinicalEvents); -} diff --git a/src/main/java/org/cbioportal/service/CoExpressionService.java b/src/main/java/org/cbioportal/service/CoExpressionService.java deleted file mode 100644 index fe9137f806f..00000000000 --- a/src/main/java/org/cbioportal/service/CoExpressionService.java +++ /dev/null @@ -1,32 +0,0 @@ -package org.cbioportal.service; - -import org.cbioportal.model.CoExpression; -import org.cbioportal.model.EntityType; -import org.cbioportal.service.exception.GeneNotFoundException; -import org.cbioportal.service.exception.GenesetNotFoundException; -import org.cbioportal.service.exception.MolecularProfileNotFoundException; -import org.cbioportal.service.exception.SampleListNotFoundException; - -import java.util.List; - -public interface CoExpressionService { - - List getCoExpressions(String molecularProfileId, String sampleListId, String geneticEntityId, - EntityType geneticEntityType, Double threshold) - throws MolecularProfileNotFoundException, GenesetNotFoundException, GeneNotFoundException; - - List getCoExpressions(String geneticEntityId, EntityType geneticEntityType, - String sampleListId, String molecularProfileIdA, String molecularProfileIdB, - Double threshold) - throws MolecularProfileNotFoundException, SampleListNotFoundException, GenesetNotFoundException, GeneNotFoundException; - - - List fetchCoExpressions(String geneticEntityId, EntityType geneticEntityType, - List sampleIds, String molecularProfileIdA, String molecularProfileIdB, - Double threshold) - throws MolecularProfileNotFoundException, GenesetNotFoundException, GeneNotFoundException; - - List fetchCoExpressions(String molecularProfileId, List sampleIds, String geneticEntityId, - EntityType geneticEntityType, Double threshold) - throws MolecularProfileNotFoundException ,GenesetNotFoundException, GeneNotFoundException; -} diff --git a/src/main/java/org/cbioportal/service/CopyNumberSegmentService.java b/src/main/java/org/cbioportal/service/CopyNumberSegmentService.java deleted file mode 100644 index f251e710474..00000000000 --- a/src/main/java/org/cbioportal/service/CopyNumberSegmentService.java +++ /dev/null @@ -1,25 +0,0 @@ -package org.cbioportal.service; - -import org.cbioportal.model.CopyNumberSeg; -import org.cbioportal.model.meta.BaseMeta; -import org.cbioportal.service.exception.SampleNotFoundException; -import org.cbioportal.service.exception.StudyNotFoundException; - -import java.util.List; - -public interface CopyNumberSegmentService { - - List getCopyNumberSegmentsInSampleInStudy(String studyId, String sampleId, String chromosome, String projection, - Integer pageSize, Integer pageNumber, String sortBy, - String direction) - throws SampleNotFoundException, StudyNotFoundException; - - BaseMeta getMetaCopyNumberSegmentsInSampleInStudy(String studyId, String sampleId, String chromosome) - throws SampleNotFoundException, StudyNotFoundException; - - List fetchCopyNumberSegments(List studyIds, List sampleIds, String chromosome, String projection); - - BaseMeta fetchMetaCopyNumberSegments(List studyIds, List sampleIds, String chromosome); - - List getCopyNumberSegmentsBySampleListId(String studyId, String sampleListId, String chromosome, String projection); -} diff --git a/src/main/java/org/cbioportal/service/CosmicCountService.java b/src/main/java/org/cbioportal/service/CosmicCountService.java deleted file mode 100644 index 4ba451f6008..00000000000 --- a/src/main/java/org/cbioportal/service/CosmicCountService.java +++ /dev/null @@ -1,10 +0,0 @@ -package org.cbioportal.service; - - -import java.util.List; -import org.cbioportal.model.CosmicMutation; - -public interface CosmicCountService { - - List fetchCosmicCountsByKeywords(List keywords); -} diff --git a/src/main/java/org/cbioportal/service/CustomDataService.java b/src/main/java/org/cbioportal/service/CustomDataService.java deleted file mode 100644 index 6f1b96f8c65..00000000000 --- a/src/main/java/org/cbioportal/service/CustomDataService.java +++ /dev/null @@ -1,10 +0,0 @@ -package org.cbioportal.service; - -import org.cbioportal.service.util.CustomDataSession; - -import java.util.List; -import java.util.Map; - -public interface CustomDataService { - Map getCustomDataSessions(List attributes); -} diff --git a/src/main/java/org/cbioportal/service/DataAccessTokenService.java b/src/main/java/org/cbioportal/service/DataAccessTokenService.java deleted file mode 100644 index 77447dab63e..00000000000 --- a/src/main/java/org/cbioportal/service/DataAccessTokenService.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (c) 2018 Memorial Sloan-Kettering Cancer Center. - * - * This library is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS - * FOR A PARTICULAR PURPOSE. The software and documentation provided hereunder - * is on an "as is" basis, and Memorial Sloan-Kettering Cancer Center has no - * obligations to provide maintenance, support, updates, enhancements or - * modifications. In no event shall Memorial Sloan-Kettering Cancer Center be - * liable to any party for direct, indirect, special, incidental or - * consequential damages, including lost profits, arising out of the use of this - * software and its documentation, even if Memorial Sloan-Kettering Cancer - * Center has been advised of the possibility of such damage. - */ - -/* - * This file is part of cBioPortal. - * - * cBioPortal is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . -*/ - -package org.cbioportal.service; - -import java.util.Date; -import java.util.List; - -import org.cbioportal.model.DataAccessToken; -import org.springframework.security.core.Authentication; - -public interface DataAccessTokenService { - - public DataAccessToken createDataAccessToken(String username); - public List getAllDataAccessTokens(String username); - public DataAccessToken getDataAccessToken(String username); - public DataAccessToken getDataAccessTokenInfo(String token); - public void revokeAllDataAccessTokens(String username); - public void revokeDataAccessToken(String token); - public String getUsername(String token); - public Date getExpiration(String token); - public Authentication createAuthenticationRequest(String token); - - /** - * Tests token validity. - * Token is valid if: - * - not yet expired and - * - not revoked and - * - can be verified as issued through this service (maybe via signature) - * @param token - * @return - */ - public Boolean isValid(String token); - -} diff --git a/src/main/java/org/cbioportal/service/DiscreteCopyNumberService.java b/src/main/java/org/cbioportal/service/DiscreteCopyNumberService.java deleted file mode 100644 index 7dbd1e8a5a9..00000000000 --- a/src/main/java/org/cbioportal/service/DiscreteCopyNumberService.java +++ /dev/null @@ -1,53 +0,0 @@ -package org.cbioportal.service; - -import org.cbioportal.model.*; -import org.cbioportal.model.meta.BaseMeta; -import org.cbioportal.service.exception.MolecularProfileNotFoundException; - -import java.util.List; - -public interface DiscreteCopyNumberService { - - List getDiscreteCopyNumbersInMolecularProfileBySampleListId(String molecularProfileId, - String sampleListId, - List entrezGeneIds, - List alterationTypes, - String projection) - throws MolecularProfileNotFoundException; - - BaseMeta getMetaDiscreteCopyNumbersInMolecularProfileBySampleListId(String molecularProfileId, String sampleListId, - List entrezGeneIds, - List alterationTypes) - throws MolecularProfileNotFoundException; - - List fetchDiscreteCopyNumbersInMolecularProfile(String molecularProfileId, - List sampleIds, - List entrezGeneIds, - List alterationTypes, - String projection) - throws MolecularProfileNotFoundException; - - List getDiscreteCopyNumbersInMultipleMolecularProfiles(List molecularProfileIds, - List sampleIds, - List entrezGeneIds, - List alterationTypes, - String projection); - - List getDiscreteCopyNumbersInMultipleMolecularProfilesByGeneQueries(List molecularProfileIds, - List sampleIds, - List geneQueries, - String projection); - - BaseMeta fetchMetaDiscreteCopyNumbersInMolecularProfile(String molecularProfileId, List sampleIds, - List entrezGeneIds, List alterationTypes) - throws MolecularProfileNotFoundException; - - List getSampleCountByGeneAndAlterationAndSampleIds(String molecularProfileId, - List sampleIds, - List entrezGeneIds, - List alterations) - throws MolecularProfileNotFoundException; - - List fetchCopyNumberCounts(String molecularProfileId, List entrezGeneIds, - List alterations) throws MolecularProfileNotFoundException; -} diff --git a/src/main/java/org/cbioportal/service/ExpressionEnrichmentService.java b/src/main/java/org/cbioportal/service/ExpressionEnrichmentService.java deleted file mode 100644 index d3c2a444bd8..00000000000 --- a/src/main/java/org/cbioportal/service/ExpressionEnrichmentService.java +++ /dev/null @@ -1,34 +0,0 @@ -package org.cbioportal.service; - -import java.util.List; -import java.util.Map; - -import org.cbioportal.model.EnrichmentType; -import org.cbioportal.model.GenericAssayEnrichment; -import org.cbioportal.model.GenomicEnrichment; -import org.cbioportal.model.MolecularProfileCaseIdentifier; -import org.cbioportal.model.GenericAssayBinaryEnrichment; -import org.cbioportal.model.GenericAssayCategoricalEnrichment; -import org.cbioportal.service.exception.MolecularProfileNotFoundException; - -public interface ExpressionEnrichmentService { - - List getGenomicEnrichments(String molecularProfileId, - Map> molecularProfileCaseSets, EnrichmentType enrichmentType) - throws MolecularProfileNotFoundException; - - List getGenericAssayNumericalEnrichments(String molecularProfileId, - Map> molecularProfileCaseSets, EnrichmentType enrichmentType) - throws MolecularProfileNotFoundException; - List getGenericAssayBinaryEnrichments( - String molecularProfileId, - Map> molecularProfileCaseSets, - EnrichmentType enrichmentType) - throws MolecularProfileNotFoundException; - - List getGenericAssayCategoricalEnrichments(String molecularProfileId, - Map> molecularProfileCaseSets, - EnrichmentType enrichmentType) - throws MolecularProfileNotFoundException; - -} diff --git a/src/main/java/org/cbioportal/service/FrontendPropertiesService.java b/src/main/java/org/cbioportal/service/FrontendPropertiesService.java deleted file mode 100644 index a965eaf40d1..00000000000 --- a/src/main/java/org/cbioportal/service/FrontendPropertiesService.java +++ /dev/null @@ -1,10 +0,0 @@ -package org.cbioportal.service; - -import java.util.Map; - -public interface FrontendPropertiesService { - - String getFrontendProperty(FrontendPropertiesServiceImpl.FrontendProperty property); - Map getFrontendProperties(); - -} diff --git a/src/main/java/org/cbioportal/service/FrontendPropertiesServiceImpl.java b/src/main/java/org/cbioportal/service/FrontendPropertiesServiceImpl.java deleted file mode 100644 index abe7f299226..00000000000 --- a/src/main/java/org/cbioportal/service/FrontendPropertiesServiceImpl.java +++ /dev/null @@ -1,410 +0,0 @@ -package org.cbioportal.service; - -import jakarta.annotation.PostConstruct; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.core.env.Environment; -import org.springframework.stereotype.Service; - -import java.io.BufferedReader; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Paths; -import java.util.Arrays; -import java.util.HashMap; -import java.util.Map; -import java.util.stream.Collectors; - - -// Class adapted from legacy config_service.jsp and GlobalProperties.java -@Service -public class FrontendPropertiesServiceImpl implements FrontendPropertiesService { - - private final Logger log = LoggerFactory.getLogger(FrontendPropertiesServiceImpl.class); - - // This enum holds properties exposed to the frontend reactapp. - // Format: ("", "") - // There are some properties that require processing before being exposed to the frontend. - public enum FrontendProperty { - dat_method("dat.method", null), - oncoprint_custom_driver_annotation_binary_menu_label( - "oncoprint.custom_driver_annotation.binary.menu_label", null), - oncoprint_custom_driver_annotation_binary_menu_description( - "oncoprint.custom_driver_annotation.binary.menu_description", null), - disabled_tabs("disabled_tabs", null), - civic_url("civic.url", null), - oncoprint_custom_driver_annotation_binary_default( - "oncoprint.custom_driver_annotation.binary.default", null), - oncoprint_oncokb_default("oncoprint.oncokb.default", null), - oncoprint_hotspots_default("oncoprint.hotspots.default", null), - oncoprint_clustered_default("oncoprint.clustered.default", null), - oncokb_merge_icons_by_default("oncokb.merge_icons_by_default", null), - oncoprint_clinical_tracks_config_json("oncoprint.clinical_tracks.config_json", null), - genomenexus_url("genomenexus.url", null), - genomenexus_url_grch38("genomenexus.url.grch38", null), - genomenexus_isoform_override_source("genomenexus.isoform_override_source", null), - google_analytics_profile_id("google_analytics_profile_id", null), - analytics_report_url("analytics_report_url", null), - oncoprint_hide_vus_default("oncoprint.hide_vus.default", null), - mycancergenome_show("mycancergenome.show", null), - oncokb_public_api_url("oncokb.public_api.url", null), - digitalslidearchive_iframe_url("digitalslidearchive.iframe.url", null), - digitalslidearchive_meta_url("digitalslidearchive.meta.url", null), - mdacc_heatmap_meta_url("mdacc.heatmap.meta.url", null), - mdacc_heatmap_patient_url("mdacc.heatmap.patient.url", null), - mdacc_heatmap_study_meta_url("mdacc.heatmap.study.meta.url", null), - mdacc_heatmap_study_url("mdacc.heatmap.study.url", null), - show_mdacc_heatmap("show.mdacc.heatmap", null), - oncoprint_custom_driver_annotation_tiers_menu_label( - "oncoprint.custom_driver_annotation.tiers.menu_label", null), - oncoprint_custom_driver_annotation_tiers_menu_description( - "oncoprint.custom_driver_annotation.tiers.menu_description", null), - patient_view_use_legacy_timeline("patient_view.use_legacy_timeline", null), - installation_map_url("installation_map_url", null), - priority_studies("priority_studies", null), - show_hotspot("show.hotspot", null), - show_oncokb("show.oncokb", null), - show_civic("show.civic", null), - show_genomenexus("show.genomenexus", null), - show_genomenexus_annotation_sources("show.genomenexus.annotation_sources", null), - show_mutation_mappert_tool_grch38("show.mutation_mappert_tool.grch38", null), - show_transcript_dropdown("show.transcript_dropdown", null), - show_signal("show.signal", null), - show_cbioportal("show.cbioportal", null), - show_cosmic("show.cosmic", null), - show_ndex("show.ndex", null), - survival_show_p_q_values_in_survival_type_table( - "survival.show_p_q_values_in_survival_type_table", null), - survival_min_group_threshold("survival.min_group_threshold", null), - survival_initial_x_axis_limit("survival.initial_x_axis_limit", null), - skin_documentation_about("skin.documentation.about", null), - skin_documentation_baseurl("skin.documentation.baseurl", null), - skin_example_study_queries("skin.example_study_queries", null), - skin_blurb("skin.blurb", null), - skin_custom_header_tabs("skin.custom_header_tabs", null), - skin_data_sets_footer("skin.data_sets_footer", null), - skin_data_sets_header("skin.data_sets_header", null), - skin_documentation_markdown("skin.documentation.markdown", null), - skin_email_contact("skin.email_contact", null), - skin_examples_right_column_html("skin.examples_right_column_html", null), - skin_documentation_faq("skin.documentation.faq", null), - skin_footer("skin.footer", null), - skin_footer_show_dev("skin.footer_show_dev", null), - skin_login_contact_html("skin.login.contact_html", null), - skin_login_saml_registration_html("skin.login.saml.registration_html", null), - skin_documentation_news("skin.documentation.news", null), - skin_documentation_oql("skin.documentation.oql", null), - skin_query_max_tree_depth("skin.query.max_tree_depth", null), - skin_quick_select_buttons("skin.quick_select_buttons", null), - skin_right_logo("skin.right_logo", null), - skin_left_logo("skin.left_logo", null), - skin_right_nav_show_data_sets("skin.right_nav.show_data_sets", null), - skin_right_nav_show_examples("skin.right_nav.show_examples", null), - skin_right_nav_show_testimonials("skin.right_nav.show_testimonials", null), - skin_right_nav_show_whats_new("skin.right_nav.show_whats_new", null), - skin_right_nav_show_twitter("skin.right_nav.show_twitter", null), - skin_right_nav_whats_new_blurb("skin.right_nav.whats_new_blurb", null), - skin_show_about_tab("skin.show_about_tab", null), - skin_show_data_tab("skin.show_data_tab", null), - skin_show_faqs_tab("skin.show_faqs_tab", null), - skin_show_news_tab("skin.show_news_tab", null), - skin_show_r_matlab_tab("skin.show_r_matlab_tab", null), - skin_show_tools_tab("skin.show_tools_tab", null), - skin_show_tutorials_tab("skin.show_tutorials_tab", null), - skin_show_web_api_tab("skin.show_web_api_tab", null), - skin_show_tweet_button("skin.show_tweet_button", null), - skin_show_study_help_button("skin.show_study_help_button", null), - skin_patientview_filter_genes_profiled_all_samples( - "skin.patientview.filter_genes_profiled_all_samples", null), - skin_patientview_show_mskcc_slide_viewer("skin.patientview.show_mskcc_slide_viewer", null), - skin_show_settings_menu("skin.show_settings_menu", null), - skin_hide_logout_button("skin.hide_logout_button", null), - quick_search_enabled("quick_search.enabled", null), - default_cross_cancer_study_session_id("default_cross_cancer_study_session_id", null), - default_cross_cancer_study_list("default_cross_cancer_study_list", null), - default_cross_cancer_study_list_name("default_cross_cancer_study_list_name", null), - skin_description("skin.description", null), - skin_title("skin.title", null), - app_name("app.name", null), - skin_authorization_message("skin.authorization_message", null), - session_url_length_threshold("session.url_length_threshold", null), - bitly_api_key("bitly.api_key", null), - bitly_user("bitly.user", null), - bitly_access_token("bitly.access.token", null), - oncoprint_custom_driver_annotation_tiers_default( - "oncoprint.custom_driver_annotation.tiers.default", null), - ensembl_transcript_url("ensembl.transcript_url", null), - enable_persistent_cache("enable_persistent_cache", null), - enable_request_body_gzip_compression("enable_request_body_gzip_compression", null), - query_product_limit("query_product_limit", null), - skin_show_gsva("skin.show_gsva", null), - saml_idp_metadata_entityid("saml.idp.metadata.entityid", null), - saml_logout_local("saml.logout.local", null), - skin_citation_rule_text("skin.citation_rule_text", null), - skin_geneset_hierarchy_default_p_value("skin.geneset_hierarchy.default_p_value", null), - skin_geneset_hierarchy_default_gsva_score("skin.geneset_hierarchy.default_gsva_score", null), - app_version("app.version", null), - frontendSentryEndpoint("sentryjs.frontend_project_endpoint", null), - - // These properties require additional processing. - // Names refer to the property that requires processing. - frontendConfigOverride("frontend.config", null), - query_sets_of_genes("querypage.setsofgenes.location", null), - authenticationMethod("authenticate", "false"), - mskWholeSlideViewerToken("msk.whole.slide.viewer.secret.key", null), - oncoprintOncoKbHotspotsDefault("oncoprint.oncokb_hotspots.default", "true"), - oncoKbTokenDefined("oncokb.token", ""), - sessionServiceEnabled("session.service.url", ""), - frontendUrl("frontend.url", null), - skin_hide_download_controls("skin.hide_download_controls", "show"), - study_download_url("study_download_url", "https://cbioportal-datahub.s3.amazonaws.com/"), - enable_cross_study_expression("enable_cross_study_expression", ""), - studyview_max_samples_selected("studyview.max_samples_selected", null), - skin_home_page_show_reference_genome("skin.home_page.show_reference_genome", null), - vaf_sequential_mode_default("vaf.sequential_mode.default", null), - vaf_log_scale_default("vaf.log_scale.default", null), - skin_patient_view_custom_sample_type_colors_json("skin.patient_view.custom_sample_type_colors_json", null), - skin_study_view_show_sv_table("skin.study_view.show_sv_table", null), - skin_home_page_show_unauthorized_studies("skin.home_page.show_unauthorized_studies", null), - skin_home_page_unauthorized_studies_global_message("skin.home_page.unauthorized_studies_global_message", null), - skin_mutation_table_namespace_column_show_by_default("skin.mutation_table.namespace_column.show_by_default", null), - skin_geneset_hierarchy_collapse_by_default("skin.geneset_hierarchy.collapse_by_default", null), - skin_patient_view_mutation_table_columns_show_on_init("skin.patient_view.mutation_table.columns.show_on_init", null), - skin_results_view_mutation_table_columns_show_on_init("skin.results_view.mutation_table.columns.show_on_init", null), - skin_patient_view_copy_number_table_columns_show_on_init("skin.patient_view.copy_number_table.columns.show_on_init", null), - skin_patient_view_structural_variant_table_columns_show_on_init("skin.patient_view.structural_variant_table.columns.show_on_init", null), - skin_results_view_tables_default_sort_column("skin.results_view.tables.default_sort_column", null), - skin_survival_plot_clinical_event_types_show_on_init("skin.survival_plot.clinical_event_types.show_on_init", null), - skin_show_donate_button("skin.show_donate_button", "false"), - - skin_patient_view_tables_default_sort_column("skin.patient_view.tables.default_sort_column", null), - enable_treatment_groups("enable_treatment_groups", null), - comparison_categorical_na_values("comparison.categorical_na_values", null), - clinical_attribute_product_limit("clinical_attribute_product_limit", null), - skin_right_nav_show_web_tours("skin.right_nav.show_web_tours", "false"), - - download_custom_buttons_json("download_custom_buttons_json", null), - - enable_study_tags("enable_study_tags", null), - enable_darwin("enable_darwin", null), - - clickhouse_mode("clickhouse_mode", "false"); - - - - private final String propertyName; - private final String defaultValue; - - FrontendProperty(String name, String defaultValue) { - this.propertyName = name; - this.defaultValue = defaultValue; - } - - public String getPropertyName() { - return propertyName; - } - - public String getFrontendName() { - return this.name(); - } - - public String getDefaultValue() { - return defaultValue; - } - } - - @Autowired - private Environment env; - - private static Map serverConfigProperties; - - @PostConstruct - public void init() { - serverConfigProperties = Arrays.stream(FrontendProperty.values()) - // do not use toMap here because null values are problematic - .collect( - HashMap::new, - (out, property) -> out.put(property.getFrontendName(), getPropertyValue(property)), - HashMap::putAll - ); - } - - private String getPropertyValue(FrontendProperty property) { - String propertyValue = env.getProperty(property.getPropertyName(), property.getDefaultValue()); - if (propertyValue != null) - propertyValue = propertyValue.trim(); - switch (property.getFrontendName()) { - // First, add properties that require pre-processing. - case "frontendConfigOverride": - case "query_sets_of_genes": - case "skin.patient_view.custom_sample_type_colors_json": - case "oncoprint.clinical_tracks.config_json": - case "download_custom_buttons_json": - return readFile(propertyValue); - case "oncoprintOncoKbHotspotsDefault": - return enableOncoKBandHotspotsParamValue(propertyValue); - case "oncoKbTokenDefined": - case "sessionServiceEnabled": - return String.valueOf(!propertyValue.isEmpty()); - case "frontendUrl": - return getFrontendUrl(propertyValue); - case "enable_darwin": - return enableDarwin(); - // For others, just return the value in the properties file. - default: - return propertyValue; - } - } - - private String enableOncoKBandHotspots(String enableOncoKBandHotspots) { - if (enableOncoKBandHotspots.equalsIgnoreCase("custom")) { - return "custom"; - } else if (enableOncoKBandHotspots.equalsIgnoreCase("false")) { - return "false"; - } - return "true"; - } - - private String enableOncoKBandHotspotsParamValue(String enableOncoKBandHotspots) { - switch (enableOncoKBandHotspots(enableOncoKBandHotspots)) { - case "true": - return "undefined"; - case "false": - return "\"disable\""; - case "custom": - return "\"custom\""; - } - return null; - } - - public String getFrontendProperty(FrontendProperty property) { - return serverConfigProperties.get(property.getFrontendName()); - } - - public Map getFrontendProperties() { - // Make sure that requests work on individual instances of this data. - return cloneProperties(); - } - - private Map cloneProperties() { - return serverConfigProperties.entrySet().stream() - .collect( - HashMap::new, - (out, entry) -> out.put(entry.getKey(), entry.getValue()), - HashMap::putAll - ); - } - - /** - * Find the file, either on the file system or in a .jar, and return as an InputStream. - * @propertiesFileName: the file path - * @return: a valid InputStream (not null), otherwise throws FileNotFoundException - * TECH: file system locations have precedence over classpath - * REF: based on getResourceStream() in WebServletContextListener.java - */ - private InputStream locateFile(String filePath) throws FileNotFoundException { - // try absolute or relative to working directory - File file = new File(filePath); - if (file.exists()) { - // throws if is a directory or cannot be opened - log.info("Found frontend config file: {}", file.getAbsolutePath()); - return new FileInputStream(file); - } - - // try relative to PORTAL_HOME - String home = System.getenv("PORTAL_HOME"); - if (home != null) { - file = new File(Paths.get(home, filePath).toString()); - if (file.exists()) { - log.info("Found frontend config file: {}", file.getAbsolutePath()); - return new FileInputStream(file); - } - } - - // try resource (e.g. app.jar) - InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream(filePath); - if (inputStream != null) { - log.info("Found frontend config resource: {}", filePath); - return inputStream; - } else { - throw new FileNotFoundException("File not found in system or classpath: " + filePath); - } - } - - /** - * Read the file, either on the file system or in a .jar, and return the content as a single-line string. - * @propertiesFileName: the file path - */ - private String readFile(String propertiesFileName) { - if (propertiesFileName == null || propertiesFileName.isEmpty()) { - return null; - } - - // strip off classpath prefix and always check all locations (ClassLoader and file system) - String filePath = propertiesFileName.startsWith("classpath:") - ? propertiesFileName.substring("classpath:".length()) - : propertiesFileName; - - try { - InputStream inputStream = locateFile(filePath); - BufferedReader br = new BufferedReader(new InputStreamReader(inputStream)); - return br.lines().map(String::trim).collect(Collectors.joining("")); - } catch (Exception e) { - log.error("Error reading frontend config file: {}", e.getMessage()); - return null; - } - } - - public String getFrontendUrl(String propertyValue) { - String frontendUrlRuntime = env.getProperty("frontend.url.runtime", ""); - if (frontendUrlRuntime.length() > 0) { - try { - String url = parseUrl(Files.readString(Paths.get(frontendUrlRuntime)).replaceAll("[\\r\\n]+", "")); - if (log.isInfoEnabled()) { - log.info("Using frontend from {}: {}", frontendUrlRuntime, url); - } - return url; - } catch (IOException e) { - // error reading file, use existing frontendUrl - if (log.isErrorEnabled()) { - log.error("Can't read frontend.url.runtime: {}", frontendUrlRuntime); - } - } - } - return propertyValue; - } - - public String enableDarwin() { - String darwinAuthUrl = env.getProperty("darwin.auth_url", ""); - String ddpResponseUrl = env.getProperty("ddp.response_url", ""); - String cisUser = env.getProperty("cis.user", ""); - String darwinRegex = env.getProperty("darwin.regex", ""); - if (!darwinAuthUrl.isBlank() && !ddpResponseUrl.isBlank() && !cisUser.isBlank() && !darwinRegex.isBlank()) { - return "true"; - } else { - return "false"; - } - } - - /* - * Trim whitespace of url and append / if it does not exist. Return empty - * string otherwise. - */ - public static String parseUrl(String url) { - String rv = ""; - if (url != null && !url.isEmpty()) { - rv = url.trim(); - if (!rv.endsWith("/")) { - rv += "/"; - } - } - return rv; - } - -} diff --git a/src/main/java/org/cbioportal/service/GeneMemoizerService.java b/src/main/java/org/cbioportal/service/GeneMemoizerService.java deleted file mode 100644 index 995afc60a27..00000000000 --- a/src/main/java/org/cbioportal/service/GeneMemoizerService.java +++ /dev/null @@ -1,11 +0,0 @@ -package org.cbioportal.service; - -import org.cbioportal.model.ReferenceGenomeGene; - -import java.util.List; - -public interface GeneMemoizerService { - List fetchGenes(String genomeName); - - void cacheGenes(List genes, String genomeName); -} diff --git a/src/main/java/org/cbioportal/service/GenePanelService.java b/src/main/java/org/cbioportal/service/GenePanelService.java deleted file mode 100644 index 9c0b2c6c8e6..00000000000 --- a/src/main/java/org/cbioportal/service/GenePanelService.java +++ /dev/null @@ -1,39 +0,0 @@ -package org.cbioportal.service; - -import org.cbioportal.model.GenePanel; -import org.cbioportal.model.GenePanelData; -import org.cbioportal.model.MolecularProfileCaseIdentifier; -import org.cbioportal.model.meta.BaseMeta; -import org.cbioportal.service.exception.GenePanelNotFoundException; -import org.cbioportal.service.exception.MolecularProfileNotFoundException; -import org.springframework.cache.annotation.Cacheable; - -import java.util.List; -import java.util.Set; - -public interface GenePanelService { - - List getAllGenePanels(String projection, Integer pageSize, Integer pageNumber, String sortBy, - String direction); - - BaseMeta getMetaGenePanels(); - - GenePanel getGenePanel(String genePanelId) throws GenePanelNotFoundException; - - List getGenePanelData(String molecularProfileId, String sampleListId) - throws MolecularProfileNotFoundException; - - List fetchGenePanelData(String molecularProfileId, List sampleIds) - throws MolecularProfileNotFoundException; - - @Cacheable(cacheResolver = "staticRepositoryCacheOneResolver", condition = "@cacheEnabledConfig.getEnabled()") - List fetchGenePanelDataByMolecularProfileIds(Set molecularProfileIds); - - @Cacheable(cacheResolver = "staticRepositoryCacheOneResolver", condition = "@cacheEnabledConfig.getEnabled()") - List fetchGenePanelDataInMultipleMolecularProfiles(List molecularProfileSampleIdentifiers); - - @Cacheable(cacheResolver = "staticRepositoryCacheOneResolver", condition = "@cacheEnabledConfig.getEnabled()") - List fetchGenePanelDataInMultipleMolecularProfilesByPatientIds(List molecularProfileSampleIdentifiers); - - List fetchGenePanels(List genePanelIds, String projection); -} diff --git a/src/main/java/org/cbioportal/service/GeneService.java b/src/main/java/org/cbioportal/service/GeneService.java deleted file mode 100644 index ce60d3a4c79..00000000000 --- a/src/main/java/org/cbioportal/service/GeneService.java +++ /dev/null @@ -1,26 +0,0 @@ -package org.cbioportal.service; - -import org.cbioportal.model.Gene; -import org.cbioportal.model.meta.BaseMeta; -import org.cbioportal.service.exception.GeneNotFoundException; -import org.cbioportal.service.exception.GeneWithMultipleEntrezIdsException; - -import java.util.List; - -public interface GeneService { - - List getAllGenes(String keyword, String alias, String projection, Integer pageSize, Integer pageNumber, String sortBy, - String direction); - - BaseMeta getMetaGenes(String keyword, String alias); - - Gene getGene(String geneId) throws GeneNotFoundException, GeneWithMultipleEntrezIdsException; - - Gene getGeneByGeneticEntityId(Integer geneticEntityId) throws GeneNotFoundException; - - List getAliasesOfGene(String geneId) throws GeneNotFoundException, GeneWithMultipleEntrezIdsException; - - List fetchGenes(List geneIds, String geneIdType, String projection); - - BaseMeta fetchMetaGenes(List geneIds, String geneIdType); -} diff --git a/src/main/java/org/cbioportal/service/GenericAssayService.java b/src/main/java/org/cbioportal/service/GenericAssayService.java deleted file mode 100644 index 8f85a4fd179..00000000000 --- a/src/main/java/org/cbioportal/service/GenericAssayService.java +++ /dev/null @@ -1,24 +0,0 @@ -package org.cbioportal.service; - -import java.util.List; - -import org.cbioportal.model.GenericAssayData; -import org.cbioportal.model.meta.GenericAssayMeta; -import org.cbioportal.service.exception.MolecularProfileNotFoundException; - -public interface GenericAssayService { - - List getGenericAssayMetaByStableIdsAndMolecularIds(List stableIds, List molecularProfileIds, String projection); - - List getGenericAssayData(String molecularProfileId, String sampleListId, - List genericAssayStableIds, String projection) - throws MolecularProfileNotFoundException; - - List fetchGenericAssayData(String molecularProfileId, List sampleIds, - List genericAssayStableIds, String projection) - throws MolecularProfileNotFoundException; - - List fetchGenericAssayData(List molecularProfileIds, List sampleIds, - List genericAssayStableIds, String projection) - throws MolecularProfileNotFoundException; -} diff --git a/src/main/java/org/cbioportal/service/GenesetCorrelationService.java b/src/main/java/org/cbioportal/service/GenesetCorrelationService.java deleted file mode 100644 index 8136290b344..00000000000 --- a/src/main/java/org/cbioportal/service/GenesetCorrelationService.java +++ /dev/null @@ -1,20 +0,0 @@ -package org.cbioportal.service; - -import java.util.List; - -import org.cbioportal.model.GenesetCorrelation; -import org.cbioportal.service.exception.GenesetNotFoundException; -import org.cbioportal.service.exception.MolecularProfileNotFoundException; -import org.cbioportal.service.exception.SampleListNotFoundException; - -public interface GenesetCorrelationService { - - List fetchCorrelatedGenes(String genesetId, String geneticProfileId, - double correlationThreshold) throws MolecularProfileNotFoundException, GenesetNotFoundException; - - List fetchCorrelatedGenes(String genesetId, String geneticProfileId, - List sampleIds, double correlationThreshold) throws MolecularProfileNotFoundException, GenesetNotFoundException; - - List fetchCorrelatedGenes(String genesetId, String geneticProfileId, String sampleListId, - double correlationThreshold) throws MolecularProfileNotFoundException, SampleListNotFoundException, GenesetNotFoundException; -} diff --git a/src/main/java/org/cbioportal/service/GenesetDataService.java b/src/main/java/org/cbioportal/service/GenesetDataService.java deleted file mode 100644 index 9ad80bf9f08..00000000000 --- a/src/main/java/org/cbioportal/service/GenesetDataService.java +++ /dev/null @@ -1,17 +0,0 @@ -package org.cbioportal.service; - -import java.util.List; - -import org.cbioportal.model.GenesetMolecularAlteration; -import org.cbioportal.model.GenesetMolecularData; -import org.cbioportal.service.exception.MolecularProfileNotFoundException; -import org.cbioportal.service.exception.SampleListNotFoundException; - -public interface GenesetDataService { - - List fetchGenesetData(String geneticProfileId, List sampleIds, List genesetIds) throws MolecularProfileNotFoundException; - - List fetchGenesetData(String geneticProfileId, String sampleListId, List genesetIds) throws MolecularProfileNotFoundException, SampleListNotFoundException; - - List getGenesetAlterations(String molecularProfileId, List genesetIds) throws MolecularProfileNotFoundException; -} diff --git a/src/main/java/org/cbioportal/service/GenesetHierarchyService.java b/src/main/java/org/cbioportal/service/GenesetHierarchyService.java deleted file mode 100644 index 4aea20dab8e..00000000000 --- a/src/main/java/org/cbioportal/service/GenesetHierarchyService.java +++ /dev/null @@ -1,19 +0,0 @@ -package org.cbioportal.service; - -import java.util.List; - -import org.cbioportal.model.GenesetHierarchyInfo; -import org.cbioportal.service.exception.MolecularProfileNotFoundException; -import org.cbioportal.service.exception.SampleListNotFoundException; - -public interface GenesetHierarchyService { - - List fetchGenesetHierarchyInfo(String geneticProfileId, Integer percentile, Double scoreThreshold, Double pvalueThreshold) throws MolecularProfileNotFoundException; - - List fetchGenesetHierarchyInfo(String geneticProfileId, Integer percentile, Double scoreThreshold, - Double pvalueThreshold, List sampleIds) throws MolecularProfileNotFoundException; - - List fetchGenesetHierarchyInfo(String geneticProfileId, Integer percentile, Double scoreThreshold, - Double pvalueThreshold, String sampleListId) throws MolecularProfileNotFoundException, SampleListNotFoundException; - -} diff --git a/src/main/java/org/cbioportal/service/GenesetService.java b/src/main/java/org/cbioportal/service/GenesetService.java deleted file mode 100644 index 29a3630f5c3..00000000000 --- a/src/main/java/org/cbioportal/service/GenesetService.java +++ /dev/null @@ -1,25 +0,0 @@ -package org.cbioportal.service; - -import java.util.List; - -import org.cbioportal.model.Gene; -import org.cbioportal.model.Geneset; -import org.cbioportal.model.meta.BaseMeta; -import org.cbioportal.service.exception.GenesetNotFoundException; - -public interface GenesetService { - - List getAllGenesets(String projection, Integer pageSize, Integer pageNumber); - - BaseMeta getMetaGenesets(); - - Geneset getGeneset(String genesetId) throws GenesetNotFoundException; - - List getGenesByGenesetId(String genesetId) throws GenesetNotFoundException; - - List fetchGenesets(List genesetIds); - - String getGenesetVersion(); - -} - diff --git a/src/main/java/org/cbioportal/service/MolecularDataService.java b/src/main/java/org/cbioportal/service/MolecularDataService.java deleted file mode 100644 index b1ac3fa3eaa..00000000000 --- a/src/main/java/org/cbioportal/service/MolecularDataService.java +++ /dev/null @@ -1,45 +0,0 @@ -package org.cbioportal.service; - -import org.cbioportal.model.GeneFilterQuery; -import org.cbioportal.model.GeneMolecularAlteration; -import org.cbioportal.model.GeneMolecularData; -import org.cbioportal.model.meta.BaseMeta; -import org.cbioportal.service.exception.MolecularProfileNotFoundException; - -import java.util.List; - -public interface MolecularDataService { - - List getMolecularData(String molecularProfileId, String sampleListId, - List entrezGeneIds, String projection) - throws MolecularProfileNotFoundException; - - BaseMeta getMetaMolecularData(String molecularProfileId, String sampleListId, List entrezGeneIds) - throws MolecularProfileNotFoundException; - - List fetchMolecularData(String molecularProfileId, List sampleIds, - List entrezGeneIds, String projection) - throws MolecularProfileNotFoundException; - - BaseMeta fetchMetaMolecularData(String molecularProfileId, List sampleIds, List entrezGeneIds) - throws MolecularProfileNotFoundException; - - Iterable getMolecularAlterations(String molecularProfileId, List entrezGeneIds, - String projection) throws MolecularProfileNotFoundException; - - Integer getNumberOfSamplesInMolecularProfile(String molecularProfileId); - - List getMolecularDataInMultipleMolecularProfiles(List molecularProfileIds, - List sampleIds, - List entrezGeneIds, - String projection); - - List getMolecularDataInMultipleMolecularProfilesByGeneQueries(List molecularProfileIds, - List sampleIds, - List geneQueries, - String projection); - - BaseMeta getMetaMolecularDataInMultipleMolecularProfiles(List molecularProfileIds, List sampleIds, - List entrezGeneIds); - -} diff --git a/src/main/java/org/cbioportal/service/MolecularProfileService.java b/src/main/java/org/cbioportal/service/MolecularProfileService.java deleted file mode 100644 index e3724261798..00000000000 --- a/src/main/java/org/cbioportal/service/MolecularProfileService.java +++ /dev/null @@ -1,46 +0,0 @@ -package org.cbioportal.service; - -import org.cbioportal.model.MolecularProfile; -import org.cbioportal.model.MolecularProfileCaseIdentifier; -import org.cbioportal.model.meta.BaseMeta; -import org.cbioportal.service.exception.MolecularProfileNotFoundException; -import org.cbioportal.service.exception.StudyNotFoundException; - -import java.util.List; -import java.util.Set; - -public interface MolecularProfileService { - - List getAllMolecularProfiles(String projection, Integer pageSize, Integer pageNumber, - String sortBy, String direction); - - BaseMeta getMetaMolecularProfiles(); - - MolecularProfile getMolecularProfile(String molecularProfileId) throws MolecularProfileNotFoundException; - - List getMolecularProfiles(Set molecularProfileIds, String projection); - - BaseMeta getMetaMolecularProfiles(Set molecularProfileIds); - - List getAllMolecularProfilesInStudy(String studyId, String projection, Integer pageSize, - Integer pageNumber, String sortBy, String direction) - throws StudyNotFoundException; - - BaseMeta getMetaMolecularProfilesInStudy(String studyId) throws StudyNotFoundException; - - List getMolecularProfilesInStudies(List studyIds, String projection); - - BaseMeta getMetaMolecularProfilesInStudies(List studyIds); - - List getMolecularProfilesReferredBy(String referringMolecularProfileId) - throws MolecularProfileNotFoundException; - - List getMolecularProfilesReferringTo(String referredMolecularProfileId) - throws MolecularProfileNotFoundException; - - List getMolecularProfileCaseIdentifiers(List studyIds, List sampleIds); - List getFirstMutationProfileCaseIdentifiers(List studyIds, List sampleIds); - List getMutationProfileCaseIdentifiers(List studyIds, List sampleIds); - List getFirstDiscreteCNAProfileCaseIdentifiers(List studyIds, List sampleIds); - List getFirstStructuralVariantProfileCaseIdentifiers(List studyIds, List sampleIds); -} diff --git a/src/main/java/org/cbioportal/service/MrnaPercentileService.java b/src/main/java/org/cbioportal/service/MrnaPercentileService.java deleted file mode 100644 index 98e0ed5a0f5..00000000000 --- a/src/main/java/org/cbioportal/service/MrnaPercentileService.java +++ /dev/null @@ -1,12 +0,0 @@ -package org.cbioportal.service; - -import org.cbioportal.model.MrnaPercentile; -import org.cbioportal.service.exception.MolecularProfileNotFoundException; - -import java.util.List; - -public interface MrnaPercentileService { - - List fetchMrnaPercentile(String molecularProfileId, String sampleId, List entrezGeneIds) - throws MolecularProfileNotFoundException; -} diff --git a/src/main/java/org/cbioportal/service/MutationService.java b/src/main/java/org/cbioportal/service/MutationService.java deleted file mode 100644 index c51153d1111..00000000000 --- a/src/main/java/org/cbioportal/service/MutationService.java +++ /dev/null @@ -1,53 +0,0 @@ -package org.cbioportal.service; - -import org.cbioportal.model.GeneFilterQuery; -import org.cbioportal.model.GenomicDataCountItem; -import org.cbioportal.model.Mutation; -import org.cbioportal.model.MutationCountByPosition; -import org.cbioportal.model.meta.MutationMeta; -import org.cbioportal.service.exception.MolecularProfileNotFoundException; - -import java.util.List; - -public interface MutationService { - - List getMutationsInMolecularProfileBySampleListId(String molecularProfileId, String sampleListId, - List entrezGeneIds, boolean snpOnly, - String projection, Integer pageSize, Integer pageNumber, - String sortBy, String direction) - throws MolecularProfileNotFoundException; - - MutationMeta getMetaMutationsInMolecularProfileBySampleListId(String molecularProfileId, String sampleListId, - List entrezGeneIds) - throws MolecularProfileNotFoundException; - - List getMutationsInMultipleMolecularProfiles(List molecularProfileIds, List sampleIds, - List entrezGeneIds, String projection, - Integer pageSize, Integer pageNumber, - String sortBy, String direction); - - List getMutationsInMultipleMolecularProfilesByGeneQueries(List molecularProfileIds, List sampleIds, - List geneQueries, - String projection, Integer pageSize, Integer pageNumber, - String sortBy, String direction); - - MutationMeta getMetaMutationsInMultipleMolecularProfiles(List molecularProfileIds, List sampleIds, - List entrezGeneIds); - - List fetchMutationsInMolecularProfile(String molecularProfileId, List sampleIds, - List entrezGeneIds, boolean snpOnly, String projection, - Integer pageSize, Integer pageNumber, String sortBy, - String direction) - throws MolecularProfileNotFoundException; - - MutationMeta fetchMetaMutationsInMolecularProfile(String molecularProfileId, List sampleIds, - List entrezGeneIds) - throws MolecularProfileNotFoundException; - - List fetchMutationCountsByPosition(List entrezGeneIds, - List proteinPosStarts, - List proteinPosEnds); - - GenomicDataCountItem getMutationCountsByType(List molecularProfileIds, List sampleIds, - List entrezGeneIds, String profileType); -} diff --git a/src/main/java/org/cbioportal/service/MutationSpectrumService.java b/src/main/java/org/cbioportal/service/MutationSpectrumService.java deleted file mode 100644 index 63c0a050991..00000000000 --- a/src/main/java/org/cbioportal/service/MutationSpectrumService.java +++ /dev/null @@ -1,15 +0,0 @@ -package org.cbioportal.service; - -import org.cbioportal.model.MutationSpectrum; -import org.cbioportal.service.exception.MolecularProfileNotFoundException; - -import java.util.List; - -public interface MutationSpectrumService { - - List getMutationSpectrums(String molecularProfileId, String sampleListId) - throws MolecularProfileNotFoundException; - - List fetchMutationSpectrums(String molecularProfileId, List sampleIds) - throws MolecularProfileNotFoundException; -} diff --git a/src/main/java/org/cbioportal/service/PatientService.java b/src/main/java/org/cbioportal/service/PatientService.java deleted file mode 100644 index 7ee3b93db76..00000000000 --- a/src/main/java/org/cbioportal/service/PatientService.java +++ /dev/null @@ -1,29 +0,0 @@ -package org.cbioportal.service; - -import org.cbioportal.model.Patient; -import org.cbioportal.model.meta.BaseMeta; -import org.cbioportal.service.exception.PatientNotFoundException; -import org.cbioportal.service.exception.StudyNotFoundException; - -import java.util.List; - -public interface PatientService { - - List getAllPatients(String keyword, String projection, Integer pageSize, Integer pageNumber, - String sortBy, String direction); - - BaseMeta getMetaPatients(String keyword); - - List getAllPatientsInStudy(String studyId, String projection, Integer pageSize, Integer pageNumber, - String sortBy, String direction) throws StudyNotFoundException; - - BaseMeta getMetaPatientsInStudy(String studyId) throws StudyNotFoundException; - - Patient getPatientInStudy(String studyId, String patientId) throws PatientNotFoundException, StudyNotFoundException; - - List fetchPatients(List studyIds, List patientIds, String projection); - - BaseMeta fetchMetaPatients(List studyIds, List patientIds); - - List getPatientsOfSamples(List studyIds, List sampleIds); -} diff --git a/src/main/java/org/cbioportal/service/ReadPermissionService.java b/src/main/java/org/cbioportal/service/ReadPermissionService.java deleted file mode 100644 index 7c3bc23c8d4..00000000000 --- a/src/main/java/org/cbioportal/service/ReadPermissionService.java +++ /dev/null @@ -1,10 +0,0 @@ -package org.cbioportal.service; - -import org.cbioportal.model.ReadPermission; -import org.springframework.security.core.Authentication; - -import java.util.Collection; - -public interface ReadPermissionService { - public void setReadPermission(Collection entities, Authentication authentication); -} diff --git a/src/main/java/org/cbioportal/service/ReferenceGenomeGeneService.java b/src/main/java/org/cbioportal/service/ReferenceGenomeGeneService.java deleted file mode 100644 index 1fb09b586c9..00000000000 --- a/src/main/java/org/cbioportal/service/ReferenceGenomeGeneService.java +++ /dev/null @@ -1,12 +0,0 @@ -package org.cbioportal.service; - -import org.cbioportal.model.ReferenceGenomeGene; -import java.util.List; - -public interface ReferenceGenomeGeneService { - List fetchAllReferenceGenomeGenes(String genomeName); - List fetchGenesByGenomeName(List geneIds, String genomeName); - List fetchGenesByHugoGeneSymbolsAndGenomeName(List geneIds, String genomeName); - ReferenceGenomeGene getReferenceGenomeGene(Integer geneID, String genomeName); - ReferenceGenomeGene getReferenceGenomeGeneByEntityId(Integer entityId, String genomeName); -} diff --git a/src/main/java/org/cbioportal/service/ResourceDataService.java b/src/main/java/org/cbioportal/service/ResourceDataService.java deleted file mode 100644 index 5727906394c..00000000000 --- a/src/main/java/org/cbioportal/service/ResourceDataService.java +++ /dev/null @@ -1,26 +0,0 @@ -package org.cbioportal.service; - -import java.util.List; - -import org.cbioportal.model.ResourceData; -import org.cbioportal.service.exception.PatientNotFoundException; -import org.cbioportal.service.exception.SampleNotFoundException; -import org.cbioportal.service.exception.StudyNotFoundException; - -public interface ResourceDataService { - - List getAllResourceDataOfSampleInStudy(String studyId, String sampleId, String resourceId, - String projection, Integer pageSize, Integer pageNumber, String sortBy, String direction) - throws SampleNotFoundException, StudyNotFoundException; - - List getAllResourceDataOfPatientInStudy(String studyId, String patientId, String resourceId, - String projection, Integer pageSize, Integer pageNumber, String sortBy, String direction) - throws PatientNotFoundException, StudyNotFoundException; - - List getAllResourceDataForStudy(String studyId, String resourceId, String projection, - Integer pageSize, Integer pageNumber, String sortBy, String direction) throws StudyNotFoundException; - - List getAllResourceDataForStudyPatientSample(String studyId, String resourceId, String projection, - Integer pageSize, Integer pageNumber, String sortBy, String direction) throws StudyNotFoundException; - -} diff --git a/src/main/java/org/cbioportal/service/ResourceDefinitionService.java b/src/main/java/org/cbioportal/service/ResourceDefinitionService.java deleted file mode 100644 index 9c413cf64b5..00000000000 --- a/src/main/java/org/cbioportal/service/ResourceDefinitionService.java +++ /dev/null @@ -1,18 +0,0 @@ -package org.cbioportal.service; - -import java.util.List; - -import org.cbioportal.model.ResourceDefinition; -import org.cbioportal.service.exception.ResourceDefinitionNotFoundException; -import org.cbioportal.service.exception.StudyNotFoundException; - -public interface ResourceDefinitionService { - - ResourceDefinition getResourceDefinition(String studyId, String resourceId) - throws ResourceDefinitionNotFoundException, StudyNotFoundException; - - List getAllResourceDefinitionsInStudy(String studyId, String projection, Integer pageSize, - Integer pageNumber, String sortBy, String direction) throws StudyNotFoundException; - - List fetchResourceDefinitions(List studyIds, String projection) throws StudyNotFoundException; -} diff --git a/src/main/java/org/cbioportal/service/SampleListService.java b/src/main/java/org/cbioportal/service/SampleListService.java deleted file mode 100644 index bae2e8205e5..00000000000 --- a/src/main/java/org/cbioportal/service/SampleListService.java +++ /dev/null @@ -1,29 +0,0 @@ -package org.cbioportal.service; - -import org.cbioportal.model.SampleList; -import org.cbioportal.model.meta.BaseMeta; -import org.cbioportal.service.exception.SampleListNotFoundException; -import org.cbioportal.service.exception.StudyNotFoundException; - -import java.util.List; - -public interface SampleListService { - - List getAllSampleLists(String projection, Integer pageSize, Integer pageNumber, String sortBy, - String direction); - - BaseMeta getMetaSampleLists(); - - SampleList getSampleList(String sampleListId) throws SampleListNotFoundException; - - List getAllSampleListsInStudy(String studyId, String projection, Integer pageSize, Integer pageNumber, - String sortBy, String direction) throws StudyNotFoundException; - - BaseMeta getMetaSampleListsInStudy(String studyId) throws StudyNotFoundException; - - List getAllSampleIdsInSampleList(String sampleListId) throws SampleListNotFoundException; - - List fetchSampleLists(List sampleListIds, String projection); - - List getAllSampleListsInStudies(List studyIds, String projection); -} diff --git a/src/main/java/org/cbioportal/service/SampleService.java b/src/main/java/org/cbioportal/service/SampleService.java deleted file mode 100644 index 4d1c6d9c9e1..00000000000 --- a/src/main/java/org/cbioportal/service/SampleService.java +++ /dev/null @@ -1,48 +0,0 @@ -package org.cbioportal.service; - -import org.cbioportal.model.Sample; -import org.cbioportal.model.meta.BaseMeta; -import org.cbioportal.service.exception.PatientNotFoundException; -import org.cbioportal.service.exception.SampleNotFoundException; -import org.cbioportal.service.exception.StudyNotFoundException; - -import java.util.List; - -public interface SampleService { - - List getAllSamplesInStudy(String studyId, String projection, Integer pageSize, Integer pageNumber, - String sortBy, String direction) throws StudyNotFoundException; - - BaseMeta getMetaSamplesInStudy(String studyId) throws StudyNotFoundException; - - List getAllSamplesInStudies(List studyIds, String projection, Integer pageSize, Integer pageNumber, - String sortBy, String direction); - - Sample getSampleInStudy(String studyId, String sampleId) throws SampleNotFoundException, StudyNotFoundException; - - List getAllSamplesOfPatientInStudy(String studyId, String patientId, String projection, Integer pageSize, - Integer pageNumber, String sortBy, String direction) - throws StudyNotFoundException, PatientNotFoundException; - - BaseMeta getMetaSamplesOfPatientInStudy(String studyId, String patientId) - throws StudyNotFoundException, PatientNotFoundException; - - List getAllSamplesOfPatientsInStudy(String studyId, List patientIds, String projection); - - List getSamplesOfPatientsInMultipleStudies(List studyIds, List patientIds, String projection); - - List fetchSamples(List studyIds, List sampleIds, String projection); - - List fetchSamples(List sampleListIds, String projection); - - BaseMeta fetchMetaSamples(List studyIds, List sampleIds); - - BaseMeta fetchMetaSamples(List sampleListIds); - - List getSamplesByInternalIds(List internalIds); - - List getAllSamples(String keyword, List studyIds, String projection, - Integer pageSize, Integer pageNumber, String sort, String direction); - - BaseMeta getMetaSamples(String keyword, List studyIds); -} diff --git a/src/main/java/org/cbioportal/service/ServerStatusService.java b/src/main/java/org/cbioportal/service/ServerStatusService.java deleted file mode 100644 index ac77b693c08..00000000000 --- a/src/main/java/org/cbioportal/service/ServerStatusService.java +++ /dev/null @@ -1,7 +0,0 @@ -package org.cbioportal.service; - -import org.cbioportal.service.impl.ServerStatusServiceImpl.ServerStatusMessage; - -public interface ServerStatusService { - ServerStatusMessage getServerStatus(); -} diff --git a/src/main/java/org/cbioportal/service/SignificantCopyNumberRegionService.java b/src/main/java/org/cbioportal/service/SignificantCopyNumberRegionService.java deleted file mode 100644 index 712e980a99b..00000000000 --- a/src/main/java/org/cbioportal/service/SignificantCopyNumberRegionService.java +++ /dev/null @@ -1,15 +0,0 @@ -package org.cbioportal.service; - -import org.cbioportal.model.Gistic; -import org.cbioportal.model.meta.BaseMeta; -import org.cbioportal.service.exception.StudyNotFoundException; - -import java.util.List; - -public interface SignificantCopyNumberRegionService { - - List getSignificantCopyNumberRegions(String studyId, String projection, Integer pageSize, - Integer pageNumber, String sortBy, String direction) throws StudyNotFoundException; - - BaseMeta getMetaSignificantCopyNumberRegions(String studyId) throws StudyNotFoundException; -} diff --git a/src/main/java/org/cbioportal/service/SignificantlyMutatedGeneService.java b/src/main/java/org/cbioportal/service/SignificantlyMutatedGeneService.java deleted file mode 100644 index dc60a5b485b..00000000000 --- a/src/main/java/org/cbioportal/service/SignificantlyMutatedGeneService.java +++ /dev/null @@ -1,15 +0,0 @@ -package org.cbioportal.service; - -import org.cbioportal.model.MutSig; -import org.cbioportal.model.meta.BaseMeta; -import org.cbioportal.service.exception.StudyNotFoundException; - -import java.util.List; - -public interface SignificantlyMutatedGeneService { - - List getSignificantlyMutatedGenes(String studyId, String projection, Integer pageSize, Integer pageNumber, - String sortBy, String direction) throws StudyNotFoundException; - - BaseMeta getMetaSignificantlyMutatedGenes(String studyId) throws StudyNotFoundException; -} diff --git a/src/main/java/org/cbioportal/service/StaticDataTimestampService.java b/src/main/java/org/cbioportal/service/StaticDataTimestampService.java deleted file mode 100644 index 07c6abb0221..00000000000 --- a/src/main/java/org/cbioportal/service/StaticDataTimestampService.java +++ /dev/null @@ -1,13 +0,0 @@ -package org.cbioportal.service; - -import org.cbioportal.model.TableTimestampPair; - -import java.util.Date; -import java.util.List; -import java.util.Map; - -public interface StaticDataTimestampService { - Map getTimestamps(List tables); - - Map getTimestampsAsDates(List tables); -} diff --git a/src/main/java/org/cbioportal/service/StructuralVariantService.java b/src/main/java/org/cbioportal/service/StructuralVariantService.java deleted file mode 100644 index 6fe7dc5d34d..00000000000 --- a/src/main/java/org/cbioportal/service/StructuralVariantService.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (c) 2018 The Hyve B.V. - * This code is licensed under the GNU Affero General Public License (AGPL), - * version 3, or (at your option) any later version. - */ - -/* - * This file is part of cBioPortal. - * - * cBioPortal is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -package org.cbioportal.service; - -import java.util.List; - -import org.cbioportal.model.GeneFilterQuery; -import org.cbioportal.model.StructuralVariantFilterQuery; -import org.cbioportal.model.StructuralVariant; -import org.cbioportal.model.StructuralVariantQuery; - -public interface StructuralVariantService { - - List fetchStructuralVariants( - List molecularProfileIds, - List sampleIds, - List entrezGeneIds, - List structuralVariantQueries - ); - - List fetchStructuralVariantsByGeneQueries(List molecularProfileIds, - List sampleIds, - List geneQueries); - - List fetchStructuralVariantsByStructVarQueries(List molecularProfileIds, - List sampleIds, - List structVarQueries); -} \ No newline at end of file diff --git a/src/main/java/org/cbioportal/service/StudyService.java b/src/main/java/org/cbioportal/service/StudyService.java deleted file mode 100644 index 4d80c394d65..00000000000 --- a/src/main/java/org/cbioportal/service/StudyService.java +++ /dev/null @@ -1,28 +0,0 @@ -package org.cbioportal.service; - -import org.cbioportal.model.CancerStudy; -import org.cbioportal.model.CancerStudyTags; -import org.cbioportal.model.meta.BaseMeta; -import org.cbioportal.service.exception.StudyNotFoundException; -import org.cbioportal.utils.security.AccessLevel; -import org.springframework.security.core.Authentication; - -import java.util.List; - -public interface StudyService { - - List getAllStudies(String keyword, String projection, Integer pageSize, Integer pageNumber, - String sortBy, String direction, Authentication authentication, AccessLevel accessLevel); - - BaseMeta getMetaStudies(String keyword); - - CancerStudy getStudy(String studyId) throws StudyNotFoundException; - - List fetchStudies(List studyIds, String projection); - - BaseMeta fetchMetaStudies(List studyIds); - - CancerStudyTags getTags(String studyId, AccessLevel accessLevel); - - List getTagsForMultipleStudies(List studyIds); -} diff --git a/src/main/java/org/cbioportal/service/StudyViewColumnarService.java b/src/main/java/org/cbioportal/service/StudyViewColumnarService.java deleted file mode 100644 index 67ee1f9efe4..00000000000 --- a/src/main/java/org/cbioportal/service/StudyViewColumnarService.java +++ /dev/null @@ -1,63 +0,0 @@ -package org.cbioportal.service; - -import org.cbioportal.model.AlterationCountByGene; -import org.cbioportal.model.CaseListDataCount; -import org.cbioportal.model.ClinicalData; -import org.cbioportal.model.ClinicalDataCountItem; -import org.cbioportal.model.ClinicalEventTypeCount; -import org.cbioportal.model.GenericAssayDataCountItem; -import org.cbioportal.model.GenomicDataCountItem; -import org.cbioportal.model.GenomicDataCount; -import org.cbioportal.model.CopyNumberCountByGene; -import org.cbioportal.model.PatientTreatmentReport; -import org.cbioportal.model.Sample; -import org.cbioportal.model.SampleTreatmentReport; -import org.cbioportal.service.exception.StudyNotFoundException; -import org.cbioportal.web.parameter.ClinicalDataType; -import org.cbioportal.web.parameter.GenericAssayDataBinFilter; -import org.cbioportal.web.parameter.GenericAssayDataFilter; -import org.cbioportal.web.parameter.GenomicDataBinFilter; -import org.cbioportal.web.parameter.GenomicDataFilter; -import org.cbioportal.web.parameter.StudyViewFilter; - -import java.util.List; -import java.util.Map; - -public interface StudyViewColumnarService { - - List getFilteredSamples(StudyViewFilter studyViewFilter); - - List getMutatedGenes(StudyViewFilter interceptedStudyViewFilter) throws StudyNotFoundException; - List getCnaGenes(StudyViewFilter interceptedStudyViewFilter) throws StudyNotFoundException; - List getStructuralVariantGenes(StudyViewFilter studyViewFilter) throws StudyNotFoundException; - - Map getClinicalAttributeDatatypeMap(StudyViewFilter studyViewFilter); - - List getClinicalDataCounts(StudyViewFilter studyViewFilter, List filteredAttributes); - - List getCaseListDataCounts(StudyViewFilter studyViewFilter); - - List getPatientClinicalData(StudyViewFilter studyViewFilter, List attributeIds); - - List getSampleClinicalData(StudyViewFilter studyViewFilter, List attributeIds); - - List getMolecularProfileSampleCounts(StudyViewFilter studyViewFilter); - - List getClinicalEventTypeCounts(StudyViewFilter studyViewFilter); - PatientTreatmentReport getPatientTreatmentReport(StudyViewFilter studyViewFilter); - SampleTreatmentReport getSampleTreatmentReport(StudyViewFilter studyViewFilter); - - List getCNACountsByGeneSpecific(StudyViewFilter studyViewFilter, List genomicDataFilters); - - List getGenericAssayDataCounts(StudyViewFilter studyViewFilter, List genericAssayDataFilters); - - List getMutationCountsByGeneSpecific(StudyViewFilter studyViewFilter, List genomicDataFilters); - - List getGenomicDataBinCounts(StudyViewFilter studyViewFilter, List genomicDataBinFilters); - - List getGenericAssayDataBinCounts(StudyViewFilter studyViewFilter, List genericAssayDataBinFilters); - - List getMutationTypeCountsByGeneSpecific(StudyViewFilter studyViewFilter, List genomicDataFilters); - - List fetchClinicalDataForXyPlot(StudyViewFilter studyViewFilter, List attributeIds, boolean shouldFilterNonEmptyClinicalData); -} diff --git a/src/main/java/org/cbioportal/service/StudyViewService.java b/src/main/java/org/cbioportal/service/StudyViewService.java deleted file mode 100644 index c4cb00151e5..00000000000 --- a/src/main/java/org/cbioportal/service/StudyViewService.java +++ /dev/null @@ -1,37 +0,0 @@ -package org.cbioportal.service; - -import org.apache.commons.math3.util.Pair; -import org.cbioportal.model.AlterationCountByGene; -import org.cbioportal.model.AlterationCountByStructuralVariant; -import org.cbioportal.model.AlterationFilter; -import org.cbioportal.model.CopyNumberCountByGene; -import org.cbioportal.model.GenericAssayDataCountItem; -import org.cbioportal.model.GenomicDataCount; -import org.cbioportal.model.GenomicDataCountItem; -import org.cbioportal.service.exception.StudyNotFoundException; - -import java.util.List; - -public interface StudyViewService { - List getGenomicDataCounts(List studyIds, List sampleIds); - - List getMutationAlterationCountByGenes(List studyIds, List sampleIds, AlterationFilter annotationFilter) - throws StudyNotFoundException; - - List getMutationCountsByGeneSpecific(List studyIds, List sampleIds, List> genomicDataFilters, AlterationFilter annotationFilter); - - List getMutationTypeCountsByGeneSpecific(List studyIds, List sampleIds, List> genomicDataFilters); - - List getStructuralVariantAlterationCountByGenes(List studyIds, List sampleIds, AlterationFilter annotationFilter) - throws StudyNotFoundException; - - List getStructuralVariantAlterationCounts(List studyIds, List sampleIds, AlterationFilter annotationFilters); - - List getCNAAlterationCountByGenes(List studyIds, List sampleIds, AlterationFilter annotationFilter) - throws StudyNotFoundException; - - List getCNAAlterationCountsByGeneSpecific(List studyIds, List sampleIds, List> genomicDataFilters); - - List fetchGenericAssayDataCounts(List sampleIds, List studyIds, List stableIds, List profileTypes); - -} diff --git a/src/main/java/org/cbioportal/service/TreatmentService.java b/src/main/java/org/cbioportal/service/TreatmentService.java deleted file mode 100644 index 0c7ff536b49..00000000000 --- a/src/main/java/org/cbioportal/service/TreatmentService.java +++ /dev/null @@ -1,14 +0,0 @@ -package org.cbioportal.service; - -import java.util.List; - -import org.cbioportal.model.PatientTreatmentRow; -import org.cbioportal.model.SampleTreatmentRow; -import org.cbioportal.model.ClinicalEventKeyCode; - -public interface TreatmentService { - public List getAllSampleTreatmentRows(List samples, List studies, ClinicalEventKeyCode key); - public List getAllPatientTreatmentRows(List samples, List studies, ClinicalEventKeyCode key); - public Boolean containsTreatmentData(List studies, ClinicalEventKeyCode tier); - public Boolean containsSampleTreatmentData(List studyIds, ClinicalEventKeyCode tier); -} diff --git a/src/main/java/org/cbioportal/service/VariantCountService.java b/src/main/java/org/cbioportal/service/VariantCountService.java deleted file mode 100644 index 74dc9758461..00000000000 --- a/src/main/java/org/cbioportal/service/VariantCountService.java +++ /dev/null @@ -1,12 +0,0 @@ -package org.cbioportal.service; - -import org.cbioportal.model.VariantCount; -import org.cbioportal.service.exception.MolecularProfileNotFoundException; - -import java.util.List; - -public interface VariantCountService { - - List fetchVariantCounts(String molecularProfileId, List entrezGeneIds, List keywords) - throws MolecularProfileNotFoundException; -} diff --git a/src/main/java/org/cbioportal/service/ViolinPlotService.java b/src/main/java/org/cbioportal/service/ViolinPlotService.java deleted file mode 100644 index 37eade2f739..00000000000 --- a/src/main/java/org/cbioportal/service/ViolinPlotService.java +++ /dev/null @@ -1,22 +0,0 @@ -package org.cbioportal.service; - -import org.cbioportal.model.ClinicalData; -import org.cbioportal.model.ClinicalViolinPlotData; -import org.cbioportal.model.Sample; -import org.cbioportal.web.parameter.StudyViewFilter; - -import java.math.BigDecimal; -import java.util.List; - -public interface ViolinPlotService { - ClinicalViolinPlotData getClinicalViolinPlotData( - List sampleClinicalDataForViolinPlot, - List samplesForSampleCounts, - BigDecimal axisStart, - BigDecimal axisEnd, - BigDecimal numCurvePoints, - Boolean useLogScale, - BigDecimal sigmaMultiplier, - StudyViewFilter studyViewFilter - ); -} diff --git a/src/main/java/org/cbioportal/service/alteration/AlterationCountByGeneService.java b/src/main/java/org/cbioportal/service/alteration/AlterationCountByGeneService.java deleted file mode 100644 index 79d29dc8ff3..00000000000 --- a/src/main/java/org/cbioportal/service/alteration/AlterationCountByGeneService.java +++ /dev/null @@ -1,14 +0,0 @@ -package org.cbioportal.service.alteration; - -import org.cbioportal.model.AlterationCountByGene; -import org.cbioportal.model.CopyNumberCountByGene; -import org.cbioportal.model.StudyViewFilterContext; -import org.cbioportal.service.exception.StudyNotFoundException; - -import java.util.List; - -public interface AlterationCountByGeneService { - List getMutatedGenes(StudyViewFilterContext studyViewFilterContext) throws StudyNotFoundException; - List getCnaGenes(StudyViewFilterContext studyViewFilterContext) throws StudyNotFoundException; - List getStructuralVariantGenes(StudyViewFilterContext studyViewFilterContext) throws StudyNotFoundException; -} diff --git a/src/main/java/org/cbioportal/service/alteration/AlterationCountByGeneServiceImpl.java b/src/main/java/org/cbioportal/service/alteration/AlterationCountByGeneServiceImpl.java deleted file mode 100644 index 9aea4ade562..00000000000 --- a/src/main/java/org/cbioportal/service/alteration/AlterationCountByGeneServiceImpl.java +++ /dev/null @@ -1,218 +0,0 @@ -package org.cbioportal.service.alteration; - -import org.apache.commons.math3.util.Pair; -import org.cbioportal.model.AlterationCountByGene; -import org.cbioportal.model.AlterationType; -import org.cbioportal.model.CopyNumberCountByGene; -import org.cbioportal.model.Gistic; -import org.cbioportal.model.MolecularProfile; -import org.cbioportal.model.MutSig; -import org.cbioportal.model.StudyViewFilterContext; -import org.cbioportal.persistence.StudyViewRepository; -import org.cbioportal.service.SignificantCopyNumberRegionService; -import org.cbioportal.service.SignificantlyMutatedGeneService; -import org.cbioportal.service.exception.StudyNotFoundException; -import org.cbioportal.service.util.AlterationCountServiceUtil; -import org.cbioportal.utils.config.annotation.ConditionalOnProperty; -import org.cbioportal.web.parameter.Projection; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.lang.NonNull; -import org.springframework.stereotype.Service; - -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.function.Function; -import java.util.stream.Collectors; - -/** - * Implementation of the AlterationCountService interface, providing methods for retrieving and processing - * alteration counts for samples and patients based on various criteria. - */ -@Service -@ConditionalOnProperty(name = "clickhouse_mode", havingValue = "true") -public class AlterationCountByGeneServiceImpl implements AlterationCountByGeneService { - private final StudyViewRepository studyViewRepository; - private final SignificantlyMutatedGeneService significantlyMutatedGeneService; - private final SignificantCopyNumberRegionService significantCopyNumberRegionService; - - /** - * Constructor for AlterationCountByGeneServiceImpl. - * - * @param studyViewRepository Repository for study-related queries. - * @param significantlyMutatedGeneService Service for retrieving significantly mutated genes. - * @param significantCopyNumberRegionService Service for retrieving significant copy number regions. - */ - @Autowired - public AlterationCountByGeneServiceImpl(StudyViewRepository studyViewRepository, SignificantlyMutatedGeneService significantlyMutatedGeneService, SignificantCopyNumberRegionService significantCopyNumberRegionService) { - this.studyViewRepository = studyViewRepository; - this.significantlyMutatedGeneService = significantlyMutatedGeneService; - this.significantCopyNumberRegionService = significantCopyNumberRegionService; - } - - /** - * Retrieves a list of mutated genes and their alteration counts for a given filter context. - * - * @param studyViewFilterContext Context containing filter criteria. - * @return List of AlterationCountByGene objects representing mutated genes. - * @throws StudyNotFoundException if the specified study is not found. - */ - @Override - public List getMutatedGenes(StudyViewFilterContext studyViewFilterContext) throws StudyNotFoundException { - var alterationCountByGenes = populateAlterationCounts(AlterationCountServiceUtil.combineAlterationCountsWithConflictingHugoSymbols(studyViewRepository.getMutatedGenes(studyViewFilterContext)), - studyViewFilterContext, AlterationType.MUTATION_EXTENDED); - return populateAlterationCountsWithMutSigQValue(alterationCountByGenes, studyViewFilterContext); - } - - /** - * Retrieves a list of genes with copy number alterations (CNA) and their alteration counts for a given filter context. - * - * @param studyViewFilterContext Context containing filter criteria. - * @return List of CopyNumberCountByGene objects representing genes with CNAs. - * @throws StudyNotFoundException if the specified study is not found. - */ - public List getCnaGenes(StudyViewFilterContext studyViewFilterContext) throws StudyNotFoundException { - var copyNumberAlterationCounts = populateAlterationCounts(AlterationCountServiceUtil.combineCopyNumberCountsWithConflictingHugoSymbols(studyViewRepository.getCnaGenes(studyViewFilterContext)), studyViewFilterContext, AlterationType.COPY_NUMBER_ALTERATION); - return populateAlterationCountsWithCNASigQValue(copyNumberAlterationCounts, studyViewFilterContext); - } - - /** - * Retrieves a list of structural variant genes and their alteration counts for a given filter context. - * - * @param studyViewFilterContext Context containing filter criteria. - * @return List of AlterationCountByGene objects representing structural variant genes. - * @throws StudyNotFoundException if the specified study is not found. - */ - @Override - public List getStructuralVariantGenes(StudyViewFilterContext studyViewFilterContext) throws StudyNotFoundException { - var alterationCountByGenes = populateAlterationCounts(AlterationCountServiceUtil.combineAlterationCountsWithConflictingHugoSymbols(studyViewRepository.getStructuralVariantGenes(studyViewFilterContext)), - studyViewFilterContext, AlterationType.STRUCTURAL_VARIANT); - return populateAlterationCountsWithMutSigQValue(alterationCountByGenes, studyViewFilterContext); - } - - /** - * Populates alteration counts with profile data, including the total profiled count and matching gene panel IDs. - * - * @param alterationCounts List of alteration counts to enrich. - * @param studyViewFilterContext Context containing filter criteria. - * @param alterationType Type of alteration (e.g., mutation, CNA, structural variant). - * @param The type of alteration count. - * @return List of enriched alteration counts. - */ - private List populateAlterationCounts(@NonNull List alterationCounts, - @NonNull StudyViewFilterContext studyViewFilterContext, - @NonNull AlterationType alterationType) { - final var firstMolecularProfileForEachStudy = getFirstMolecularProfileGroupedByStudy(studyViewFilterContext, alterationType); - final int totalProfiledCount = studyViewRepository.getTotalProfiledCountsByAlterationType(studyViewFilterContext, alterationType.toString()); - var profiledCountsMap = studyViewRepository.getTotalProfiledCounts(studyViewFilterContext, alterationType.toString(), firstMolecularProfileForEachStudy); - final var matchingGenePanelIdsMap = studyViewRepository.getMatchingGenePanelIds(studyViewFilterContext, alterationType.toString()); - final int sampleProfileCountWithoutGenePanelData = studyViewRepository.getSampleProfileCountWithoutPanelData(studyViewFilterContext, alterationType.toString()); - - alterationCounts.parallelStream() - .forEach(alterationCountByGene -> { - String hugoGeneSymbol = alterationCountByGene.getHugoGeneSymbol(); - Set matchingGenePanelIds = matchingGenePanelIdsMap.get(hugoGeneSymbol) != null ? - matchingGenePanelIdsMap.get(hugoGeneSymbol) : Collections.emptySet(); - - int alterationTotalProfiledCount = AlterationCountServiceUtil.computeTotalProfiledCount(AlterationCountServiceUtil.hasGenePanelData(matchingGenePanelIds), - profiledCountsMap.getOrDefault(hugoGeneSymbol, 0), - sampleProfileCountWithoutGenePanelData, totalProfiledCount); - - alterationCountByGene.setNumberOfProfiledCases(alterationTotalProfiledCount); - - alterationCountByGene.setMatchingGenePanelIds(matchingGenePanelIds); - - }); - return alterationCounts; - } - - /** - * Updates alteration counts with MutSig Q-value data for significance. - * - * @param alterationCountByGenes List of alteration counts to update. - * @param studyViewFilterContext Context containing filter criteria. - * @return List of alteration counts updated with MutSig Q-value. - * @throws StudyNotFoundException if the specified study is not found. - */ - private List populateAlterationCountsWithMutSigQValue(List alterationCountByGenes, StudyViewFilterContext studyViewFilterContext) throws StudyNotFoundException { - final var mutSigs = getMutSigs(studyViewFilterContext); - // If MutSig is not empty update Mutated Genes - return AlterationCountServiceUtil.updateAlterationCountsWithMutSigQValue(alterationCountByGenes, mutSigs); - } - - /** - * Updates copy number alteration counts with GISTIC significance data. - * - * @param alterationCountByGenes List of alteration counts to update. - * @param studyViewFilterContext Context containing filter criteria. - * @return List of alteration counts updated with GISTIC significance data. - * @throws StudyNotFoundException if the specified study is not found. - */ - private List populateAlterationCountsWithCNASigQValue(List alterationCountByGenes, StudyViewFilterContext studyViewFilterContext) throws StudyNotFoundException { - final var gisticMap = getGisticMap(studyViewFilterContext); - return AlterationCountServiceUtil.updateAlterationCountsWithCNASigQValue(alterationCountByGenes, gisticMap); - } - - /** - * Retrieves the first molecular profile for each study based on the alteration type. - * - * @param studyViewFilterContext Context containing filter criteria. - * @param alterationType Type of alteration (e.g., mutation, CNA, structural variant). - * @return List of MolecularProfile objects representing the first profile for each study. - */ - private List getFirstMolecularProfileGroupedByStudy(StudyViewFilterContext studyViewFilterContext, AlterationType alterationType) { - final var molecularProfiles = studyViewRepository.getFilteredMolecularProfilesByAlterationType(studyViewFilterContext, alterationType.toString()); - return AlterationCountServiceUtil.getFirstMolecularProfileGroupedByStudy(molecularProfiles); - } - - /** - * Retrieves MutSig data for significantly mutated genes in the specified studies. - * - * @param studyViewFilterContext Context containing filter criteria. - * @return Map of MutSig objects keyed by Hugo gene symbol. - * @throws StudyNotFoundException if the specified study is not found. - */ - private Map getMutSigs(StudyViewFilterContext studyViewFilterContext) throws StudyNotFoundException { - var distinctStudyIds = studyViewRepository.getFilteredStudyIds(studyViewFilterContext); - Map mutSigs = new HashMap<>(); - if (distinctStudyIds.size() == 1) { - var studyId = distinctStudyIds.getFirst(); - mutSigs = significantlyMutatedGeneService.getSignificantlyMutatedGenes( - studyId, - Projection.SUMMARY.name(), - null, - null, - null, - null) - .stream() - .collect(Collectors.toMap(MutSig::getHugoGeneSymbol, Function.identity())); - } - return mutSigs; - } - - /** - * Retrieves GISTIC data for significant copy number alterations in the specified studies. - * - * @param studyViewFilterContext Context containing filter criteria. - * @return Map of GISTIC objects keyed by gene and G-score rank. - * @throws StudyNotFoundException if the specified study is not found. - */ - private Map, Gistic> getGisticMap(StudyViewFilterContext studyViewFilterContext) throws StudyNotFoundException { - var distinctStudyIds = studyViewRepository.getFilteredStudyIds(studyViewFilterContext); - Map, Gistic> gisticMap = new HashMap<>(); - if (distinctStudyIds.size() == 1) { - var studyId = distinctStudyIds.getFirst(); - List gisticList = significantCopyNumberRegionService.getSignificantCopyNumberRegions( - studyId, - Projection.SUMMARY.name(), - null, - null, - null, - null); - AlterationCountServiceUtil.setupGisticMap(gisticList, gisticMap); - } - return gisticMap; - } -} diff --git a/src/main/java/org/cbioportal/service/exception/AccessForbiddenException.java b/src/main/java/org/cbioportal/service/exception/AccessForbiddenException.java deleted file mode 100644 index d9dd8b64bd5..00000000000 --- a/src/main/java/org/cbioportal/service/exception/AccessForbiddenException.java +++ /dev/null @@ -1,7 +0,0 @@ -package org.cbioportal.service.exception; - -public class AccessForbiddenException extends RuntimeException { - public AccessForbiddenException(String message) { - super(message); - } -} diff --git a/src/main/java/org/cbioportal/service/exception/CacheNotFoundException.java b/src/main/java/org/cbioportal/service/exception/CacheNotFoundException.java deleted file mode 100644 index 457db60daa2..00000000000 --- a/src/main/java/org/cbioportal/service/exception/CacheNotFoundException.java +++ /dev/null @@ -1,20 +0,0 @@ -package org.cbioportal.service.exception; - -public class CacheNotFoundException extends Exception { - - private String cacheName; - - public CacheNotFoundException(String cacheName) { - super("No cache found with name " + cacheName); - this.cacheName = cacheName; - } - - public String getCacheName() { - return cacheName; - } - - public void setCacheName(String cacheName) { - this.cacheName = cacheName; - } - -} diff --git a/src/main/java/org/cbioportal/service/exception/CacheOperationException.java b/src/main/java/org/cbioportal/service/exception/CacheOperationException.java deleted file mode 100644 index 1580a77c476..00000000000 --- a/src/main/java/org/cbioportal/service/exception/CacheOperationException.java +++ /dev/null @@ -1,7 +0,0 @@ -package org.cbioportal.service.exception; - -public class CacheOperationException extends Exception { - public CacheOperationException(String message, Throwable cause) { - super(message, cause); - } -} diff --git a/src/main/java/org/cbioportal/service/exception/CancerTypeNotFoundException.java b/src/main/java/org/cbioportal/service/exception/CancerTypeNotFoundException.java deleted file mode 100644 index e8f0ef923d6..00000000000 --- a/src/main/java/org/cbioportal/service/exception/CancerTypeNotFoundException.java +++ /dev/null @@ -1,19 +0,0 @@ -package org.cbioportal.service.exception; - -public class CancerTypeNotFoundException extends Exception { - - private String cancerTypeId; - - public CancerTypeNotFoundException(String cancerTypeId) { - super(); - this.cancerTypeId = cancerTypeId; - } - - public String getCancerTypeId() { - return cancerTypeId; - } - - public void setCancerTypeId(String cancerTypeId) { - this.cancerTypeId = cancerTypeId; - } -} diff --git a/src/main/java/org/cbioportal/service/exception/ClinicalAttributeNotFoundException.java b/src/main/java/org/cbioportal/service/exception/ClinicalAttributeNotFoundException.java deleted file mode 100644 index beca71b82e9..00000000000 --- a/src/main/java/org/cbioportal/service/exception/ClinicalAttributeNotFoundException.java +++ /dev/null @@ -1,29 +0,0 @@ -package org.cbioportal.service.exception; - -public class ClinicalAttributeNotFoundException extends Exception { - - private String studyId; - private String clinicalAttributeId; - - public ClinicalAttributeNotFoundException(String studyId, String clinicalAttributeId) { - super(); - this.studyId = studyId; - this.clinicalAttributeId = clinicalAttributeId; - } - - public String getStudyId() { - return studyId; - } - - public void setStudyId(String studyId) { - this.studyId = studyId; - } - - public String getClinicalAttributeId() { - return clinicalAttributeId; - } - - public void setClinicalAttributeId(String clinicalAttributeId) { - this.clinicalAttributeId = clinicalAttributeId; - } -} diff --git a/src/main/java/org/cbioportal/service/exception/GeneNotFoundException.java b/src/main/java/org/cbioportal/service/exception/GeneNotFoundException.java deleted file mode 100644 index 4f69921765e..00000000000 --- a/src/main/java/org/cbioportal/service/exception/GeneNotFoundException.java +++ /dev/null @@ -1,19 +0,0 @@ -package org.cbioportal.service.exception; - -public class GeneNotFoundException extends Exception { - - private String geneId; - - public GeneNotFoundException(String geneId) { - super(); - this.geneId = geneId; - } - - public String getGeneId() { - return geneId; - } - - public void setGeneId(String geneId) { - this.geneId = geneId; - } -} diff --git a/src/main/java/org/cbioportal/service/exception/GenePanelNotFoundException.java b/src/main/java/org/cbioportal/service/exception/GenePanelNotFoundException.java deleted file mode 100644 index 0511561f851..00000000000 --- a/src/main/java/org/cbioportal/service/exception/GenePanelNotFoundException.java +++ /dev/null @@ -1,19 +0,0 @@ -package org.cbioportal.service.exception; - -public class GenePanelNotFoundException extends Exception { - - private String genePanelId; - - public GenePanelNotFoundException(String genePanelId) { - super(); - this.genePanelId = genePanelId; - } - - public String getGenePanelId() { - return genePanelId; - } - - public void setGenePanelId(String genePanelId) { - this.genePanelId = genePanelId; - } -} diff --git a/src/main/java/org/cbioportal/service/exception/GeneWithMultipleEntrezIdsException.java b/src/main/java/org/cbioportal/service/exception/GeneWithMultipleEntrezIdsException.java deleted file mode 100644 index e475eb07546..00000000000 --- a/src/main/java/org/cbioportal/service/exception/GeneWithMultipleEntrezIdsException.java +++ /dev/null @@ -1,20 +0,0 @@ -package org.cbioportal.service.exception; - -//TODO: this class should be removed once the issue is resolved database -public class GeneWithMultipleEntrezIdsException extends Exception { - - private String geneId; - - public GeneWithMultipleEntrezIdsException(String geneId) { - super(); - this.geneId = geneId; - } - - public String getGeneId() { - return geneId; - } - - public void setGeneId(String geneId) { - this.geneId = geneId; - } -} diff --git a/src/main/java/org/cbioportal/service/exception/GenericAssayNotFoundException.java b/src/main/java/org/cbioportal/service/exception/GenericAssayNotFoundException.java deleted file mode 100644 index ec19640c509..00000000000 --- a/src/main/java/org/cbioportal/service/exception/GenericAssayNotFoundException.java +++ /dev/null @@ -1,25 +0,0 @@ -package org.cbioportal.service.exception; - -public class GenericAssayNotFoundException extends Exception { - - private String stableId; - - public GenericAssayNotFoundException(String stableId) { - super(); - this.setStableId(stableId); - } - - /** - * @return the stableId - */ - public String getStableId() { - return stableId; - } - - /** - * @param stableId the stableId to set - */ - public void setStableId(String stableId) { - this.stableId = stableId; - } -} diff --git a/src/main/java/org/cbioportal/service/exception/GenesetNotFoundException.java b/src/main/java/org/cbioportal/service/exception/GenesetNotFoundException.java deleted file mode 100644 index 6019759bf58..00000000000 --- a/src/main/java/org/cbioportal/service/exception/GenesetNotFoundException.java +++ /dev/null @@ -1,19 +0,0 @@ -package org.cbioportal.service.exception; - -public class GenesetNotFoundException extends Exception { - - private String genesetId; - - public GenesetNotFoundException(String genesetId) { - super(); - this.genesetId = genesetId; - } - - public String getGenesetId() { - return genesetId; - } - - public void setGenesetId(String genesetId) { - this.genesetId = genesetId; - } -} diff --git a/src/main/java/org/cbioportal/service/exception/MolecularProfileNotFoundException.java b/src/main/java/org/cbioportal/service/exception/MolecularProfileNotFoundException.java deleted file mode 100644 index 574356a8e18..00000000000 --- a/src/main/java/org/cbioportal/service/exception/MolecularProfileNotFoundException.java +++ /dev/null @@ -1,19 +0,0 @@ -package org.cbioportal.service.exception; - -public class MolecularProfileNotFoundException extends Exception { - - private String molecularProfileId; - - public MolecularProfileNotFoundException(String molecularProfileId) { - super(); - this.molecularProfileId = molecularProfileId; - } - - public String getMolecularProfileId() { - return molecularProfileId; - } - - public void setMolecularProfileId(String molecularProfileId) { - this.molecularProfileId = molecularProfileId; - } -} diff --git a/src/main/java/org/cbioportal/service/exception/PatientNotFoundException.java b/src/main/java/org/cbioportal/service/exception/PatientNotFoundException.java deleted file mode 100644 index 7f19e4d9e0c..00000000000 --- a/src/main/java/org/cbioportal/service/exception/PatientNotFoundException.java +++ /dev/null @@ -1,29 +0,0 @@ -package org.cbioportal.service.exception; - -public class PatientNotFoundException extends Exception { - - private String studyId; - private String patientId; - - public PatientNotFoundException(String studyId, String patientId) { - super(); - this.studyId = studyId; - this.patientId = patientId; - } - - public String getStudyId() { - return studyId; - } - - public void setStudyId(String studyId) { - this.studyId = studyId; - } - - public String getPatientId() { - return patientId; - } - - public void setPatientId(String patientId) { - this.patientId = patientId; - } -} diff --git a/src/main/java/org/cbioportal/service/exception/ResourceDefinitionNotFoundException.java b/src/main/java/org/cbioportal/service/exception/ResourceDefinitionNotFoundException.java deleted file mode 100644 index 45451464f5e..00000000000 --- a/src/main/java/org/cbioportal/service/exception/ResourceDefinitionNotFoundException.java +++ /dev/null @@ -1,30 +0,0 @@ -package org.cbioportal.service.exception; - -public class ResourceDefinitionNotFoundException extends Exception { - - private String studyId; - private String resourceId; - - public ResourceDefinitionNotFoundException(String studyId, String resourceId) { - super(); - this.studyId = studyId; - this.resourceId = resourceId; - } - - public String getStudyId() { - return studyId; - } - - public void setStudyId(String studyId) { - this.studyId = studyId; - } - - public String getResourceId() { - return resourceId; - } - - public void setResourceId(String resourceId) { - this.resourceId = resourceId; - } - -} \ No newline at end of file diff --git a/src/main/java/org/cbioportal/service/exception/SampleListNotFoundException.java b/src/main/java/org/cbioportal/service/exception/SampleListNotFoundException.java deleted file mode 100644 index fcda0ca5ba0..00000000000 --- a/src/main/java/org/cbioportal/service/exception/SampleListNotFoundException.java +++ /dev/null @@ -1,19 +0,0 @@ -package org.cbioportal.service.exception; - -public class SampleListNotFoundException extends Exception { - - private String sampleListId; - - public SampleListNotFoundException(String sampleListId) { - super(); - this.sampleListId = sampleListId; - } - - public String getSampleListId() { - return sampleListId; - } - - public void setSampleListId(String sampleListId) { - this.sampleListId = sampleListId; - } -} diff --git a/src/main/java/org/cbioportal/service/exception/SampleNotFoundException.java b/src/main/java/org/cbioportal/service/exception/SampleNotFoundException.java deleted file mode 100644 index d95f89d0712..00000000000 --- a/src/main/java/org/cbioportal/service/exception/SampleNotFoundException.java +++ /dev/null @@ -1,29 +0,0 @@ -package org.cbioportal.service.exception; - -public class SampleNotFoundException extends Exception { - - private String studyId; - private String sampleId; - - public SampleNotFoundException(String studyId, String sampleId) { - super(); - this.studyId = studyId; - this.sampleId = sampleId; - } - - public String getStudyId() { - return studyId; - } - - public void setStudyId(String studyId) { - this.studyId = studyId; - } - - public String getSampleId() { - return sampleId; - } - - public void setSampleId(String sampleId) { - this.sampleId = sampleId; - } -} diff --git a/src/main/java/org/cbioportal/service/exception/StudyNotFoundException.java b/src/main/java/org/cbioportal/service/exception/StudyNotFoundException.java deleted file mode 100644 index 119acd4a898..00000000000 --- a/src/main/java/org/cbioportal/service/exception/StudyNotFoundException.java +++ /dev/null @@ -1,19 +0,0 @@ -package org.cbioportal.service.exception; - -public class StudyNotFoundException extends Exception { - - private String studyId; - - public StudyNotFoundException(String studyId) { - super(); - this.studyId = studyId; - } - - public String getStudyId() { - return studyId; - } - - public void setStudyId(String studyId) { - this.studyId = studyId; - } -} diff --git a/src/main/java/org/cbioportal/service/impl/AlterationCountServiceImpl.java b/src/main/java/org/cbioportal/service/impl/AlterationCountServiceImpl.java deleted file mode 100644 index 8c5ebc5c1fa..00000000000 --- a/src/main/java/org/cbioportal/service/impl/AlterationCountServiceImpl.java +++ /dev/null @@ -1,288 +0,0 @@ -package org.cbioportal.service.impl; - -import org.apache.commons.math3.util.Pair; -import org.cbioportal.model.AlterationCountBase; -import org.cbioportal.model.AlterationCountByGene; -import org.cbioportal.model.AlterationCountByStructuralVariant; -import org.cbioportal.model.AlterationFilter; -import org.cbioportal.model.CopyNumberCountByGene; -import org.cbioportal.model.MolecularProfile; -import org.cbioportal.model.MolecularProfileCaseIdentifier; -import org.cbioportal.model.util.Select; -import org.cbioportal.persistence.AlterationRepository; -import org.cbioportal.persistence.MolecularProfileRepository; -import org.cbioportal.persistence.StudyViewRepository; -import org.cbioportal.service.AlterationCountService; -import org.cbioportal.service.SignificantCopyNumberRegionService; -import org.cbioportal.service.SignificantlyMutatedGeneService; -import org.cbioportal.service.util.AlterationCountServiceUtil; -import org.cbioportal.service.util.AlterationEnrichmentUtil; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.TreeSet; -import java.util.concurrent.atomic.AtomicReference; -import java.util.function.BiFunction; -import java.util.function.Function; -import java.util.stream.Collectors; - -@Service -public class AlterationCountServiceImpl implements AlterationCountService { - - private final AlterationRepository alterationRepository; - private final AlterationEnrichmentUtil alterationEnrichmentUtil; - private final AlterationEnrichmentUtil alterationEnrichmentUtilCna; - private final AlterationEnrichmentUtil alterationEnrichmentUtilStructVar; - private final MolecularProfileRepository molecularProfileRepository; - - - @Autowired - public AlterationCountServiceImpl(AlterationRepository alterationRepository, AlterationEnrichmentUtil alterationEnrichmentUtil, - AlterationEnrichmentUtil alterationEnrichmentUtilCna, - AlterationEnrichmentUtil alterationEnrichmentUtilStructVar, - MolecularProfileRepository molecularProfileRepository) { - this.alterationRepository = alterationRepository; - this.alterationEnrichmentUtil = alterationEnrichmentUtil; - this.alterationEnrichmentUtilCna = alterationEnrichmentUtilCna; - this.alterationEnrichmentUtilStructVar = alterationEnrichmentUtilStructVar; - this.molecularProfileRepository = molecularProfileRepository; - } - @Override - public Pair, Long> getSampleAlterationGeneCounts(List molecularProfileCaseIdentifiers, - Select entrezGeneIds, - boolean includeFrequency, - boolean includeMissingAlterationsFromGenePanel, - AlterationFilter alterationFilter) { - - Function, List> dataFetcher = profileCaseIdentifiers -> - alterationRepository.getSampleAlterationGeneCounts(new TreeSet<>(profileCaseIdentifiers), entrezGeneIds, alterationFilter); - - BiFunction, List, Long> includeFrequencyFunction = - (a, b) -> alterationEnrichmentUtil.includeFrequencyForSamples(a, b, includeMissingAlterationsFromGenePanel); - - return getAlterationGeneCounts( - molecularProfileCaseIdentifiers, - includeFrequency, - dataFetcher, - includeFrequencyFunction - ); - } - - @Override - public Pair, Long> getPatientAlterationGeneCounts(List molecularProfileCaseIdentifiers, - Select entrezGeneIds, - boolean includeFrequency, - boolean includeMissingAlterationsFromGenePanel, - AlterationFilter alterationFilter) { - - Function, List> dataFetcher = profileCaseIdentifiers -> - alterationRepository.getPatientAlterationGeneCounts(new TreeSet<>(profileCaseIdentifiers), entrezGeneIds, alterationFilter); - - BiFunction, List, Long> includeFrequencyFunction = - (a, b) -> alterationEnrichmentUtil.includeFrequencyForPatients(a, b, includeMissingAlterationsFromGenePanel); - - return getAlterationGeneCounts( - molecularProfileCaseIdentifiers, - includeFrequency, - dataFetcher, - includeFrequencyFunction - ); - } - - @Override - public Pair, Long> getSampleMutationGeneCounts(List molecularProfileCaseIdentifiers, - Select entrezGeneIds, - boolean includeFrequency, - boolean includeMissingAlterationsFromGenePanel, - AlterationFilter alterationFilter) { - return getSampleAlterationGeneCounts(molecularProfileCaseIdentifiers, - entrezGeneIds, - includeFrequency, - includeMissingAlterationsFromGenePanel, - alterationFilter - ); - } - - @Override - public Pair, Long> getPatientMutationGeneCounts(List molecularProfileCaseIdentifiers, - Select entrezGeneIds, - boolean includeFrequency, - boolean includeMissingAlterationsFromGenePanel, - AlterationFilter alterationFilter) { - return getPatientAlterationGeneCounts(molecularProfileCaseIdentifiers, - entrezGeneIds, - includeFrequency, - includeMissingAlterationsFromGenePanel, - alterationFilter); - } - - @Override - public Pair, Long> getSampleStructuralVariantGeneCounts(List molecularProfileCaseIdentifiers, - Select entrezGeneIds, - boolean includeFrequency, - boolean includeMissingAlterationsFromGenePanel, - AlterationFilter alterationFilter) { - return getSampleAlterationGeneCounts(molecularProfileCaseIdentifiers, - entrezGeneIds, - includeFrequency, - includeMissingAlterationsFromGenePanel, - alterationFilter - ); - } - - @Override - public Pair, Long> getPatientStructuralVariantGeneCounts(List molecularProfileCaseIdentifiers, - Select entrezGeneIds, - boolean includeFrequency, - boolean includeMissingAlterationsFromGenePanel, - AlterationFilter alterationFilter) { - return getPatientAlterationGeneCounts(molecularProfileCaseIdentifiers, - entrezGeneIds, - includeFrequency, - includeMissingAlterationsFromGenePanel, - alterationFilter - ); - } - - @Override - public Pair, Long> getSampleStructuralVariantCounts(List molecularProfileCaseIdentifiers, - boolean includeFrequency, - boolean includeMissingAlterationsFromGenePanel, - AlterationFilter alterationFilter) { - - Function, List> dataFetcher = profileCaseIdentifiers -> - alterationRepository.getSampleStructuralVariantCounts(new TreeSet<>(profileCaseIdentifiers), alterationFilter); - - BiFunction, List, Long> includeFrequencyFunction = - (a, b) -> alterationEnrichmentUtilStructVar.includeFrequencyForSamples(a, b, includeMissingAlterationsFromGenePanel); - - return getAlterationGeneCounts( - molecularProfileCaseIdentifiers, - includeFrequency, - dataFetcher, - includeFrequencyFunction - ); - } - -// -- Should be reinstated when the legacy CNA count endpoint retires -// @Override -// public List getSampleCnaCounts(List molecularProfileCaseIdentifiers, -// Select entrezGeneIds, -// boolean includeFrequency, -// boolean includeMissingAlterationsFromGenePanel, -// AlterationEventTypeFilter alterationFilter) { -// return getSampleAlterationCounts(molecularProfileCaseIdentifiers, -// entrezGeneIds, -// includeFrequency, -// includeMissingAlterationsFromGenePanel, -// new ArrayList<>(), -// alterationFilter); -// } -// -// @Override -// public List getPatientCnaCounts(List molecularProfileCaseIdentifiers, -// List entrezGeneIds, -// boolean includeFrequency, -// boolean includeMissingAlterationsFromGenePanel, -// AlterationEventTypeFilter alterationFilter) { -// return getPatientAlterationCounts(molecularProfileCaseIdentifiers, -// entrezGeneIds, -// includeFrequency, -// includeMissingAlterationsFromGenePanel, -// new ArrayList<>(), -// alterationFilter); -// } - - @Override - public Pair, Long> getSampleCnaGeneCounts(List molecularProfileCaseIdentifiers, - Select entrezGeneIds, - boolean includeFrequency, - boolean includeMissingAlterationsFromGenePanel, - AlterationFilter alterationFilter) { - - Function, List> dataFetcher = profileCaseIdentifiers -> - alterationRepository.getSampleCnaGeneCounts(new TreeSet<>(profileCaseIdentifiers), entrezGeneIds, alterationFilter); - - BiFunction, List, Long> includeFrequencyFunction = - (a, b) -> alterationEnrichmentUtilCna.includeFrequencyForSamples(a, b, includeMissingAlterationsFromGenePanel); - - Function keyGenerator = d -> d.getEntrezGeneId().toString() + d.getAlteration().toString(); - - return getAlterationGeneCounts( - molecularProfileCaseIdentifiers, - includeFrequency, - dataFetcher, - includeFrequencyFunction - ); - } - - @Override - public Pair, Long> getPatientCnaGeneCounts(List molecularProfileCaseIdentifiers, - Select entrezGeneIds, - boolean includeFrequency, - boolean includeMissingAlterationsFromGenePanel, - AlterationFilter alterationFilter) { - - Function, List> dataFetcher = profileCaseIdentifiers -> - alterationRepository.getPatientCnaGeneCounts(new TreeSet<>(profileCaseIdentifiers), entrezGeneIds, alterationFilter); - - BiFunction, List, Long> includeFrequencyFunction = - (a, b) -> alterationEnrichmentUtilCna.includeFrequencyForPatients(a, b, includeMissingAlterationsFromGenePanel); - - Function keyGenerator = d -> d.getEntrezGeneId().toString() + d.getAlteration().toString(); - - return getAlterationGeneCounts( - molecularProfileCaseIdentifiers, - includeFrequency, - dataFetcher, - includeFrequencyFunction - ); - } - - private Pair, Long> getAlterationGeneCounts( - List molecularProfileCaseIdentifiers, - boolean includeFrequency, - Function, List> dataFetcher, - BiFunction, List, Long> includeFrequencyFunction) { - - List alterationCountByGenes; - AtomicReference profiledCasesCount = new AtomicReference<>(0L); - if (molecularProfileCaseIdentifiers.isEmpty()) { - alterationCountByGenes = Collections.emptyList(); - } else { - Set molecularProfileIds = molecularProfileCaseIdentifiers - .stream() - .map(MolecularProfileCaseIdentifier::getMolecularProfileId) - .collect(Collectors.toSet()); - Map molecularProfileIdStudyIdMap = molecularProfileRepository - .getMolecularProfiles(molecularProfileIds, "SUMMARY") - .stream() - .collect(Collectors.toMap(MolecularProfile::getStableId, MolecularProfile::getCancerStudyIdentifier)); - - Map totalResult = new HashMap<>(); - - molecularProfileCaseIdentifiers - .stream() - .collect(Collectors - .groupingBy(identifier -> molecularProfileIdStudyIdMap.get(identifier.getMolecularProfileId()))) - .values() - .forEach(studyMolecularProfileCaseIdentifiers -> { - List studyAlterationCountByGenes = dataFetcher.apply(studyMolecularProfileCaseIdentifiers); - if (includeFrequency) { - Long studyProfiledCasesCount = includeFrequencyFunction.apply(studyMolecularProfileCaseIdentifiers, studyAlterationCountByGenes); - profiledCasesCount.updateAndGet(v -> v + studyProfiledCasesCount); - } - AlterationCountServiceUtil.setupAlterationGeneCountsMap(studyAlterationCountByGenes, totalResult); - }); - alterationCountByGenes = new ArrayList<>(totalResult.values()); - } - return new Pair<>(alterationCountByGenes, profiledCasesCount.get()); - } - -} diff --git a/src/main/java/org/cbioportal/service/impl/AlterationDriverAnnotationServiceImpl.java b/src/main/java/org/cbioportal/service/impl/AlterationDriverAnnotationServiceImpl.java deleted file mode 100644 index d5846ca02c1..00000000000 --- a/src/main/java/org/cbioportal/service/impl/AlterationDriverAnnotationServiceImpl.java +++ /dev/null @@ -1,35 +0,0 @@ -package org.cbioportal.service.impl; - -import org.cbioportal.model.AlterationDriverAnnotation; -import org.cbioportal.model.CustomDriverAnnotationReport; -import org.cbioportal.persistence.AlterationDriverAnnotationRepository; -import org.cbioportal.service.AlterationDriverAnnotationService; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -import java.util.*; -import java.util.stream.Collectors; - -@Service -public class AlterationDriverAnnotationServiceImpl implements AlterationDriverAnnotationService { - - @Autowired - private AlterationDriverAnnotationRepository alterationDriverAnnotationRepository; - private final Set NO_DATA_TIERS = new HashSet<>(Arrays.asList(null, "", "NA")); - - public CustomDriverAnnotationReport getCustomDriverAnnotationProps(List molecularProfileIds) { - - List rows = alterationDriverAnnotationRepository - .getAlterationDriverAnnotations(molecularProfileIds); - - Set tiers = rows.stream() - .map(AlterationDriverAnnotation::getDriverTiersFilter) - .filter(driverTiersFilter -> !NO_DATA_TIERS.contains(driverTiersFilter)) - .collect(Collectors.toCollection(TreeSet::new)); - boolean hasBinary = rows.stream().anyMatch(d -> - "Putative_Driver".equals(d.getDriverFilter()) || - "Putative_Passenger".equals(d.getDriverFilter())); - - return new CustomDriverAnnotationReport(hasBinary, tiers); - } -} \ No newline at end of file diff --git a/src/main/java/org/cbioportal/service/impl/AlterationEnrichmentServiceImpl.java b/src/main/java/org/cbioportal/service/impl/AlterationEnrichmentServiceImpl.java deleted file mode 100644 index cbe49e76429..00000000000 --- a/src/main/java/org/cbioportal/service/impl/AlterationEnrichmentServiceImpl.java +++ /dev/null @@ -1,66 +0,0 @@ -package org.cbioportal.service.impl; - -import org.apache.commons.math3.util.Pair; -import org.cbioportal.model.*; -import org.cbioportal.model.util.Select; -import org.cbioportal.service.AlterationEnrichmentService; -import org.cbioportal.service.AlterationCountService; -import org.cbioportal.service.util.AlterationEnrichmentUtil; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - -@Service -public class AlterationEnrichmentServiceImpl implements AlterationEnrichmentService { - - @Autowired - private AlterationCountService alterationCountService; - @Autowired - private AlterationEnrichmentUtil alterationEnrichmentUtil; - - @Override - public List getAlterationEnrichments( - Map> molecularProfileCaseSets, - EnrichmentType enrichmentType, - AlterationFilter alterationFilter) { - - Map, Long>> alterationCountsbyEntrezGeneIdAndGroup = getAlterationCountsbyEntrezGeneIdAndGroup( - molecularProfileCaseSets, enrichmentType, alterationFilter); - - return alterationEnrichmentUtil.createAlterationEnrichments(alterationCountsbyEntrezGeneIdAndGroup); - } - - public Map, Long>> getAlterationCountsbyEntrezGeneIdAndGroup( - Map> molecularProfileCaseSets, - EnrichmentType enrichmentType, - AlterationFilter alterationFilter) { - return molecularProfileCaseSets - .entrySet() - .stream() - .collect(Collectors.toMap( - entry -> entry.getKey(), // group name - entry -> { // group counts - - if (enrichmentType.equals(EnrichmentType.SAMPLE)) { - return alterationCountService - .getSampleAlterationGeneCounts( - entry.getValue(), - Select.all(), - true, - true, - alterationFilter); - } else { - return alterationCountService - .getPatientAlterationGeneCounts( - entry.getValue(), - Select.all(), - true, - true, - alterationFilter); - } - })); - } -} diff --git a/src/main/java/org/cbioportal/service/impl/CacheServiceImpl.java b/src/main/java/org/cbioportal/service/impl/CacheServiceImpl.java deleted file mode 100644 index 41896b98d9b..00000000000 --- a/src/main/java/org/cbioportal/service/impl/CacheServiceImpl.java +++ /dev/null @@ -1,111 +0,0 @@ -package org.cbioportal.service.impl; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.cbioportal.persistence.StudyRepository; -import org.cbioportal.persistence.cachemaputil.CacheMapUtil; -import org.cbioportal.persistence.cachemaputil.StaticRefCacheMapUtil; -import org.cbioportal.persistence.util.CacheUtils; -import org.cbioportal.service.CacheService; -import org.cbioportal.service.exception.CacheOperationException; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.cache.CacheManager; -import org.springframework.stereotype.Component; - -import java.util.ArrayList; -import java.util.List; -import java.util.stream.Collectors; - -@Component -public class CacheServiceImpl implements CacheService { - - private static final Log LOG = LogFactory.getLog(CacheServiceImpl.class); - - @Autowired(required = false) - private CacheManager cacheManager; - - @Autowired - private CacheMapUtil cacheMapUtil; - - // When caching is disabled there is no CacheUtils bean. - @Autowired(required = false) - private CacheUtils cacheUtils; - - @Autowired - private StudyRepository studyRepository; - - @Override - public void clearCaches(boolean clearSpringManagedCache) throws CacheOperationException { - - // Flush Spring-managed caches (only when cache strategy has been defined). - if (clearSpringManagedCache) { - attemptEvictSpringManagedCache(".*"); - } - - // Flush cache used for user permission evaluation. - // Only needed when using cache not managed by the Spring caches. - if (cacheMapUtil instanceof StaticRefCacheMapUtil) { - ((StaticRefCacheMapUtil) cacheMapUtil).initializeCacheMemory(); - } - - // Note: DAO classes in package org.mskcc.cbio.portal.dao do have their own - // caching strategy. Since these classes are only used by the deprecated old - // version of the r-library and may result in problems in the running instance - // when flushing the cashes, we do not handle these caches in this service. - } - - // This evicts keys from the general and static caches when updating/adding/deleting a study. - public void clearCachesForStudy(String studyId, boolean clearSpringManagedCache) throws CacheOperationException { - - List allStudyIds = studyRepository.getAllStudies(null, "SUMMARY", null, null, null, null) - .stream() - .map(study -> study.getCancerStudyIdentifier()) - .collect(Collectors.toList()); - - // Flush Spring-managed caches (only when cache strategy has been defined). - if (clearSpringManagedCache) { - attemptEvictSpringManagedCache(buildEvictionRegex(studyId, allStudyIds)); - } - - // Flush cache used for user permission evaluation. - // Only needed when using cache not managed by the Spring caches. - if (cacheMapUtil instanceof StaticRefCacheMapUtil) { - ((StaticRefCacheMapUtil) cacheMapUtil).initializeCacheMemory(); - } - - } - - private void attemptEvictSpringManagedCache(String pattern) throws CacheOperationException { - try { - if (cacheManager != null) { - cacheManager.getCacheNames().stream() - .forEach(cacheName -> { - cacheUtils.evictByPattern(cacheName, pattern); - }); - } - } catch (RuntimeException e) { - e.printStackTrace(); - LOG.error("Error while evicting cache." + e.getMessage()); - throw new CacheOperationException("Error while evicting cache.", e); - } - } - - // Regex that selects keys that match id of deleted study - // or lacking any study id completely. For example: - // ^(?=.*study_id_1).*|^(?!.*study_id_1)(?!.*study_id_2)(?!.*study_id_3).* - // https://stackoverflow.com/a/8240998/11651683 - private String buildEvictionRegex(String studyId, List allStudyIds) { - - // make sure imported studyId is in all studies. - List all = new ArrayList<>(); - all.add(studyId); - all.addAll(allStudyIds); - - String allIdsRegex = all.stream() - .map(id -> "(?!.*" + id + ")") - .collect(Collectors.joining("")); - - return "^(?=.*" + studyId + ").*|^" + allIdsRegex + ".*"; - } - -} diff --git a/src/main/java/org/cbioportal/service/impl/CacheStatisticsServiceImpl.java b/src/main/java/org/cbioportal/service/impl/CacheStatisticsServiceImpl.java deleted file mode 100644 index f5f74f15e23..00000000000 --- a/src/main/java/org/cbioportal/service/impl/CacheStatisticsServiceImpl.java +++ /dev/null @@ -1,89 +0,0 @@ -package org.cbioportal.service.impl; - -import jakarta.annotation.PostConstruct; -import org.cbioportal.persistence.util.CustomEhcachingProvider; -import org.cbioportal.service.CacheStatisticsService; -import org.cbioportal.service.exception.CacheNotFoundException; -import org.cbioportal.utils.config.annotation.ConditionalOnProperty; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.stereotype.Service; - -import javax.cache.Cache; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; - -@Service -@ConditionalOnProperty(name = "persistence.cache_type", havingValue = {"ehcache-heap", "ehcache-disk", "ehcache-hybrid"}) -public class CacheStatisticsServiceImpl implements CacheStatisticsService { - - @Autowired - private CustomEhcachingProvider customEhcachingProvider; - - private javax.cache.CacheManager cacheManager; - - @Value("${cache.statistics_endpoint_enabled:false}") - public boolean cacheStatisticsEndpointEnabled; - - @PostConstruct - public void initializeStatisticsService () { - cacheManager = customEhcachingProvider.getCacheManager(); - } - - protected void checkIfCacheStatisticsEndpointEnabled() { - if (!cacheStatisticsEndpointEnabled) { - // TODO re-implement Service module level Exception? - throw new RuntimeException("Cache statistics is not enabled for this instance of the portal."); - } - } - - @Override - public List getKeyCountsPerClass(String cacheName) throws CacheNotFoundException { - checkIfCacheStatisticsEndpointEnabled(); - Cache cache = cacheManager.getCache(cacheName); - if (cache == null) { - throw new CacheNotFoundException(cacheName); - } - Map classToKeyCount = new HashMap(); - Iterator> iterator = cache.iterator(); - while (iterator.hasNext()) { - Cache.Entry entry = iterator.next(); - String cacheKey = entry.getKey(); - String className = cacheKey.split("_")[0]; - int keyCount = classToKeyCount.containsKey(className) ? classToKeyCount.get(className) : 0; - classToKeyCount.put(className, keyCount + 1); - } - List keyCountsPerClass = new ArrayList(); - for (Map.Entry entry : classToKeyCount.entrySet()) { - keyCountsPerClass.add(entry.getKey().toString() + ": " + entry.getValue().toString() + " keys"); - } - return keyCountsPerClass; - } - - @Override - public List getKeysInCache(String cacheName) throws CacheNotFoundException { - checkIfCacheStatisticsEndpointEnabled(); - Cache cache = cacheManager.getCache(cacheName); - if (cache == null) { - throw new CacheNotFoundException(cacheName); - } - Integer numberOfKeys = 0; - List keysInCache = new ArrayList(); - Iterator> iterator = cache.iterator(); - while (iterator.hasNext()) { - Cache.Entry entry = iterator.next(); - keysInCache.add(entry.getKey()); - numberOfKeys += 1; - } - keysInCache.add("Total Number of Keys: " + numberOfKeys.toString()); - return keysInCache; - } - - @Override - public String getCacheStatistics() { - throw new UnsupportedOperationException("Requested API is not implemented yet"); - } -} diff --git a/src/main/java/org/cbioportal/service/impl/CancerTypeServiceImpl.java b/src/main/java/org/cbioportal/service/impl/CancerTypeServiceImpl.java deleted file mode 100644 index e039b58eaab..00000000000 --- a/src/main/java/org/cbioportal/service/impl/CancerTypeServiceImpl.java +++ /dev/null @@ -1,78 +0,0 @@ -package org.cbioportal.service.impl; - -import jakarta.annotation.PostConstruct; -import org.cbioportal.model.TypeOfCancer; -import org.cbioportal.model.meta.BaseMeta; -import org.cbioportal.persistence.CancerTypeRepository; -import org.cbioportal.service.CancerTypeService; -import org.cbioportal.service.exception.CancerTypeNotFoundException; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; - - -@Service -public class CancerTypeServiceImpl implements CancerTypeService { - - private static final String TISSUE = "tissue"; - - @Autowired - private CancerTypeRepository cancerTypeRepository; - - private Map primarySiteMap = new HashMap<>(); - - @PostConstruct - public void initPrimarySiteMap() { - - List allCancerTypes = getAllCancerTypes("SUMMARY", null, null, null, null); - - for (TypeOfCancer typeOfCancer : allCancerTypes) { - - if (!typeOfCancer.getTypeOfCancerId().equals(TISSUE)) { - TypeOfCancer primarySite = getParent(allCancerTypes, typeOfCancer); - primarySiteMap.put(typeOfCancer.getTypeOfCancerId(), primarySite); - } - } - } - - @Override - public List getAllCancerTypes(String projection, Integer pageSize, Integer pageNumber, String sortBy, - String direction) { - - return cancerTypeRepository.getAllCancerTypes(projection, pageSize, pageNumber, sortBy, direction); - } - - @Override - public BaseMeta getMetaCancerTypes() { - return cancerTypeRepository.getMetaCancerTypes(); - } - - @Override - public TypeOfCancer getCancerType(String cancerTypeId) throws CancerTypeNotFoundException { - - TypeOfCancer typeOfCancer = cancerTypeRepository.getCancerType(cancerTypeId); - if (typeOfCancer == null) { - throw new CancerTypeNotFoundException(cancerTypeId); - } - - return typeOfCancer; - } - - @Override - public Map getPrimarySiteMap() { - return primarySiteMap; - } - - private TypeOfCancer getParent(List allCancerTypes, TypeOfCancer typeOfCancer) { - - if (typeOfCancer.getParent().equals(TISSUE)) { - return typeOfCancer; - } - - return getParent(allCancerTypes, allCancerTypes.stream().filter(c -> - c.getTypeOfCancerId().equals(typeOfCancer.getParent())).findFirst().get()); - } -} diff --git a/src/main/java/org/cbioportal/service/impl/ClinicalAttributeServiceImpl.java b/src/main/java/org/cbioportal/service/impl/ClinicalAttributeServiceImpl.java deleted file mode 100644 index bb245846cc9..00000000000 --- a/src/main/java/org/cbioportal/service/impl/ClinicalAttributeServiceImpl.java +++ /dev/null @@ -1,112 +0,0 @@ -package org.cbioportal.service.impl; - -import org.cbioportal.model.ClinicalAttribute; -import org.cbioportal.model.ClinicalAttributeCount; -import org.cbioportal.model.meta.BaseMeta; -import org.cbioportal.persistence.ClinicalAttributeRepository; -import org.cbioportal.service.ClinicalAttributeService; -import org.cbioportal.service.StudyService; -import org.cbioportal.service.exception.ClinicalAttributeNotFoundException; -import org.cbioportal.service.exception.StudyNotFoundException; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.security.access.prepost.PostFilter; -import org.springframework.stereotype.Service; - -import java.util.List; -import java.util.ArrayList; - -@Service -public class ClinicalAttributeServiceImpl implements ClinicalAttributeService { - - @Autowired - private ClinicalAttributeRepository clinicalAttributeRepository; - @Autowired - private StudyService studyService; - @Value("${authenticate:false}") - private String AUTHENTICATE; - - @Override - @PostFilter("hasPermission(filterObject.cancerStudyIdentifier, 'CancerStudyId', T(org.cbioportal.utils.security.AccessLevel).READ)") - public List getAllClinicalAttributes(String projection, Integer pageSize, Integer pageNumber, - String sortBy, String direction) { - - List clinicalAttributes = clinicalAttributeRepository.getAllClinicalAttributes(projection, pageSize, pageNumber, sortBy, - direction); - // copy the list before returning so @PostFilter doesn't taint the list stored in the persistence layer cache - return (AUTHENTICATE.equals("false")) ? clinicalAttributes : new ArrayList(clinicalAttributes); - } - - @Override - public BaseMeta getMetaClinicalAttributes() { - - return clinicalAttributeRepository.getMetaClinicalAttributes(); - } - - @Override - public ClinicalAttribute getClinicalAttribute(String studyId, String clinicalAttributeId) - throws ClinicalAttributeNotFoundException, StudyNotFoundException { - - studyService.getStudy(studyId); - - ClinicalAttribute clinicalAttribute = clinicalAttributeRepository.getClinicalAttribute(studyId, - clinicalAttributeId); - - if (clinicalAttribute == null) { - throw new ClinicalAttributeNotFoundException(studyId, clinicalAttributeId); - } - - return clinicalAttribute; - } - - @Override - public List getAllClinicalAttributesInStudy(String studyId, String projection, Integer pageSize, - Integer pageNumber, String sortBy, - String direction) throws StudyNotFoundException { - - studyService.getStudy(studyId); - - return clinicalAttributeRepository.getAllClinicalAttributesInStudy(studyId, projection, pageSize, pageNumber, - sortBy, direction); - } - - @Override - public BaseMeta getMetaClinicalAttributesInStudy(String studyId) throws StudyNotFoundException { - - studyService.getStudy(studyId); - - return clinicalAttributeRepository.getMetaClinicalAttributesInStudy(studyId); - } - - @Override - public List fetchClinicalAttributes(List studyIds, String projection) { - - return clinicalAttributeRepository.fetchClinicalAttributes(studyIds, projection); - } - - @Override - public BaseMeta fetchMetaClinicalAttributes(List studyIds) { - - return clinicalAttributeRepository.fetchMetaClinicalAttributes(studyIds); - } - - @Override - public List getClinicalAttributeCountsBySampleIds(List studyIds, List sampleIds) { - - return clinicalAttributeRepository.getClinicalAttributeCountsBySampleIds(studyIds, sampleIds); - } - - @Override - public List getClinicalAttributeCountsBySampleListId(String sampleListId) { - - return clinicalAttributeRepository.getClinicalAttributeCountsBySampleListId(sampleListId); - } - - @Override - public List getClinicalAttributesByStudyIdsAndAttributeIds(List studyIds, - List attributeIds) { - - return clinicalAttributeRepository - .getClinicalAttributesByStudyIdsAndAttributeIds(studyIds, attributeIds); - } -} diff --git a/src/main/java/org/cbioportal/service/impl/ClinicalDataDensityPlotServiceImpl.java b/src/main/java/org/cbioportal/service/impl/ClinicalDataDensityPlotServiceImpl.java deleted file mode 100644 index cb4d8d780e9..00000000000 --- a/src/main/java/org/cbioportal/service/impl/ClinicalDataDensityPlotServiceImpl.java +++ /dev/null @@ -1,146 +0,0 @@ -package org.cbioportal.service.impl; - -import org.apache.commons.lang3.math.NumberUtils; -import org.apache.commons.math3.stat.correlation.PearsonsCorrelation; -import org.apache.commons.math3.stat.correlation.SpearmansCorrelation; -import org.cbioportal.model.ClinicalData; -import org.cbioportal.model.DensityPlotBin; -import org.cbioportal.model.DensityPlotData; -import org.cbioportal.service.ClinicalDataDensityPlotService; -import org.cbioportal.web.columnar.StudyViewColumnStoreController; -import org.cbioportal.web.parameter.StudyViewFilter; -import org.cbioportal.web.util.DensityPlotParameters; -import org.springframework.cache.annotation.Cacheable; -import org.springframework.stereotype.Service; - -import java.math.BigDecimal; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - - -@Service -public class ClinicalDataDensityPlotServiceImpl implements ClinicalDataDensityPlotService { - - @Cacheable( - cacheResolver = "staticRepositoryCacheOneResolver", - condition = "@cacheEnabledConfig.getEnabledClickhouse() && @studyViewFilterUtil.isUnfilteredQuery(#studyViewFilter)" - ) - @Override - public DensityPlotData getDensityPlotData(List sampleClinicalData, DensityPlotParameters densityPlotParameters, StudyViewFilter studyViewFilter) { - DensityPlotData result = new DensityPlotData(); - result.setBins(new ArrayList<>()); - - Map> clinicalDataGroupedBySampleId = sampleClinicalData.stream(). - collect(Collectors.groupingBy(c -> c.getStudyId() + "_" + c.getSampleId())); - - List extractedXYClinicalData = clinicalDataGroupedBySampleId.entrySet().stream() - .filter(entry -> entry.getValue().size() == 2 && - NumberUtils.isCreatable(entry.getValue().get(0).getAttrValue()) && - NumberUtils.isCreatable(entry.getValue().get(1).getAttrValue()) - ).flatMap(entry -> entry.getValue().stream()) - .toList(); - - if (extractedXYClinicalData.isEmpty()) { - return result; - } - - Map> partition = extractedXYClinicalData.stream().collect( - Collectors.partitioningBy(c -> c.getAttrId().equals(densityPlotParameters.getXAxisAttributeId()))); - - boolean useXLogScale = densityPlotParameters.getXAxisLogScale() && ClinicalDataDensityPlotServiceImpl.isLogScalePossibleForAttribute(densityPlotParameters.getXAxisAttributeId()); - boolean useYLogScale = densityPlotParameters.getYAxisLogScale() && ClinicalDataDensityPlotServiceImpl.isLogScalePossibleForAttribute(densityPlotParameters.getYAxisAttributeId()); - - double[] xValues = partition.get(true).stream().mapToDouble( - useXLogScale ? ClinicalDataDensityPlotServiceImpl::parseValueLog : ClinicalDataDensityPlotServiceImpl::parseValueLinear - ).toArray(); - double[] yValues = partition.get(false).stream().mapToDouble( - useYLogScale ? ClinicalDataDensityPlotServiceImpl::parseValueLog : ClinicalDataDensityPlotServiceImpl::parseValueLinear - ).toArray(); - double[] xValuesCopy = Arrays.copyOf(xValues, xValues.length); - double[] yValuesCopy = Arrays.copyOf(yValues, yValues.length); // Why copy these? - Arrays.sort(xValuesCopy); - Arrays.sort(yValuesCopy); - - double xAxisStartValue = densityPlotParameters.getXAxisStart() == null ? xValuesCopy[0] : - (useXLogScale ? ClinicalDataDensityPlotServiceImpl.logScale(densityPlotParameters.getXAxisStart().doubleValue()) : densityPlotParameters.getXAxisStart().doubleValue()); - double xAxisEndValue = densityPlotParameters.getXAxisEnd() == null ? xValuesCopy[xValuesCopy.length - 1] : - (useXLogScale ? ClinicalDataDensityPlotServiceImpl.logScale(densityPlotParameters.getXAxisEnd().doubleValue()) : densityPlotParameters.getXAxisEnd().doubleValue()); - double yAxisStartValue = densityPlotParameters.getYAxisStart() == null ? yValuesCopy[0] : - (useYLogScale ? ClinicalDataDensityPlotServiceImpl.logScale(densityPlotParameters.getYAxisStart().doubleValue()) : densityPlotParameters.getYAxisStart().doubleValue()); - double yAxisEndValue = densityPlotParameters.getYAxisEnd() == null ? yValuesCopy[yValuesCopy.length - 1] : - (useYLogScale ? ClinicalDataDensityPlotServiceImpl.logScale(densityPlotParameters.getYAxisEnd().doubleValue()) : densityPlotParameters.getYAxisEnd().doubleValue()); - double xAxisBinInterval = (xAxisEndValue - xAxisStartValue) / densityPlotParameters.getXAxisBinCount(); - double yAxisBinInterval = (yAxisEndValue - yAxisStartValue) / densityPlotParameters.getYAxisBinCount(); - List bins = result.getBins(); - for (int i = 0; i < densityPlotParameters.getXAxisBinCount(); i++) { - for (int j = 0; j < densityPlotParameters.getYAxisBinCount(); j++) { - DensityPlotBin densityPlotBin = new DensityPlotBin(); - densityPlotBin.setBinX(BigDecimal.valueOf(xAxisStartValue + (i * xAxisBinInterval))); - densityPlotBin.setBinY(BigDecimal.valueOf(yAxisStartValue + (j * yAxisBinInterval))); - densityPlotBin.setCount(0); - bins.add(densityPlotBin); - } - } - - for (int i = 0; i < xValues.length; i++) { - double xValue = xValues[i]; - double yValue = yValues[i]; - int xBinIndex = (int) ((xValue - xAxisStartValue) / xAxisBinInterval); - int yBinIndex = (int) ((yValue - yAxisStartValue) / yAxisBinInterval); - int index = (int) (((xBinIndex - (xBinIndex == densityPlotParameters.getXAxisBinCount() ? 1 : 0)) * densityPlotParameters.getYAxisBinCount()) + - (yBinIndex - (yBinIndex == densityPlotParameters.getYAxisBinCount() ? 1 : 0))); - DensityPlotBin densityPlotBin = bins.get(index); - densityPlotBin.setCount(densityPlotBin.getCount() + 1); - BigDecimal xValueBigDecimal = BigDecimal.valueOf(xValue); - BigDecimal yValueBigDecimal = BigDecimal.valueOf(yValue); - - // Set new min and max as needed - if (densityPlotBin.getMinX() == null || densityPlotBin.getMinX().compareTo(xValueBigDecimal) > 0){ - densityPlotBin.setMinX(xValueBigDecimal); - } - if (densityPlotBin.getMaxX() == null || densityPlotBin.getMaxX().compareTo(xValueBigDecimal) < 0){ - densityPlotBin.setMaxX(xValueBigDecimal); - } - if (densityPlotBin.getMinY() == null || densityPlotBin.getMinY().compareTo(yValueBigDecimal) > 0){ - densityPlotBin.setMinY(yValueBigDecimal); - } - if (densityPlotBin.getMaxY() == null || densityPlotBin.getMaxY().compareTo(yValueBigDecimal) < 0){ - densityPlotBin.setMaxY(yValueBigDecimal); - } - } - - if (xValues.length > 1) { - // need at least 2 entries in each to compute correlation - result.setPearsonCorr(new PearsonsCorrelation().correlation(xValues, yValues)); - result.setSpearmanCorr(new SpearmansCorrelation().correlation(xValues, yValues)); - } else { - // if less than 1 entry, just set 0 correlation - result.setSpearmanCorr(0.0); - result.setPearsonCorr(0.0); - } - - // filter out empty bins - result.setBins(result.getBins().stream().filter((bin)->(bin.getCount() > 0)).collect(Collectors.toList())); - return result; - } - - - private static boolean isLogScalePossibleForAttribute(String clinicalAttributeId) { - return clinicalAttributeId.equals("MUTATION_COUNT"); - } - - private static double logScale(double val) { - return Math.log(1+val); - } - - private static double parseValueLog(ClinicalData c) { - return ClinicalDataDensityPlotServiceImpl.logScale(Double.parseDouble(c.getAttrValue())); - } - - private static double parseValueLinear(ClinicalData c) { - return Double.parseDouble(c.getAttrValue()); - } -} diff --git a/src/main/java/org/cbioportal/service/impl/ClinicalDataServiceImpl.java b/src/main/java/org/cbioportal/service/impl/ClinicalDataServiceImpl.java deleted file mode 100644 index 7258f8e313e..00000000000 --- a/src/main/java/org/cbioportal/service/impl/ClinicalDataServiceImpl.java +++ /dev/null @@ -1,272 +0,0 @@ -package org.cbioportal.service.impl; - -import org.apache.commons.lang3.tuple.ImmutablePair; -import org.cbioportal.model.*; -import org.cbioportal.model.meta.BaseMeta; -import org.cbioportal.persistence.ClinicalDataRepository; -import org.cbioportal.persistence.mybatis.util.PaginationCalculator; -import org.cbioportal.service.*; -import org.cbioportal.service.exception.*; -import org.cbioportal.service.util.ClinicalAttributeUtil; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -import java.util.*; -import java.util.function.Function; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -import static org.cbioportal.utils.Encoder.calculateBase64; - -@Service -public class ClinicalDataServiceImpl implements ClinicalDataService { - - @Autowired - private ClinicalDataRepository clinicalDataRepository; - @Autowired - private StudyService studyService; - @Autowired - private PatientService patientService; - @Autowired - private SampleService sampleService; - @Autowired - private ClinicalAttributeService clinicalAttributeService; - @Autowired - private ClinicalAttributeUtil clinicalAttributeUtil; - - @Override - public List getAllClinicalDataOfSampleInStudy(String studyId, String sampleId, String attributeId, - String projection, Integer pageSize, Integer pageNumber, - String sortBy, String direction) - throws SampleNotFoundException, StudyNotFoundException { - - sampleService.getSampleInStudy(studyId, sampleId); - - return clinicalDataRepository.getAllClinicalDataOfSampleInStudy(studyId, sampleId, attributeId, projection, - pageSize, pageNumber, sortBy, direction); - } - - @Override - public BaseMeta getMetaSampleClinicalData(String studyId, String sampleId, String attributeId) - throws SampleNotFoundException, StudyNotFoundException { - - sampleService.getSampleInStudy(studyId, sampleId); - - return clinicalDataRepository.getMetaSampleClinicalData(studyId, sampleId, attributeId); - } - - @Override - public List getAllClinicalDataOfPatientInStudy(String studyId, String patientId, String attributeId, - String projection, Integer pageSize, - Integer pageNumber, String sortBy, String direction) - throws PatientNotFoundException, StudyNotFoundException { - - patientService.getPatientInStudy(studyId, patientId); - - return clinicalDataRepository.getAllClinicalDataOfPatientInStudy(studyId, patientId, attributeId, projection, - pageSize, pageNumber, sortBy, direction); - } - - @Override - public BaseMeta getMetaPatientClinicalData(String studyId, String patientId, String attributeId) - throws PatientNotFoundException, StudyNotFoundException { - - patientService.getPatientInStudy(studyId, patientId); - - return clinicalDataRepository.getMetaPatientClinicalData(studyId, patientId, attributeId); - } - - @Override - public List getAllClinicalDataInStudy(String studyId, String attributeId, String clinicalDataType, - String projection, Integer pageSize, Integer pageNumber, - String sortBy, String direction) throws StudyNotFoundException { - - studyService.getStudy(studyId); - - return clinicalDataRepository.getAllClinicalDataInStudy(studyId, attributeId, clinicalDataType, projection, - pageSize, pageNumber, sortBy, direction); - } - - @Override - public BaseMeta getMetaAllClinicalData(String studyId, String attributeId, String clinicalDataType) - throws StudyNotFoundException { - - studyService.getStudy(studyId); - - return clinicalDataRepository.getMetaAllClinicalData(studyId, attributeId, clinicalDataType); - } - - @Override - public List fetchAllClinicalDataInStudy(String studyId, List ids, List attributeIds, - String clinicalDataType, String projection) - throws StudyNotFoundException { - - studyService.getStudy(studyId); - - return clinicalDataRepository.fetchAllClinicalDataInStudy(studyId, ids, attributeIds, clinicalDataType, - projection); - } - - @Override - public BaseMeta fetchMetaClinicalDataInStudy(String studyId, List ids, List attributeIds, - String clinicalDataType) throws StudyNotFoundException { - - studyService.getStudy(studyId); - - return clinicalDataRepository.fetchMetaClinicalDataInStudy(studyId, ids, attributeIds, clinicalDataType); - } - - @Override - public List fetchClinicalData(List studyIds, List ids, List attributeIds, - String clinicalDataType, String projection) { - if (ids.isEmpty()) { - return new ArrayList<>(); - } - return clinicalDataRepository.fetchClinicalData(studyIds, ids, attributeIds, clinicalDataType, projection); - } - - @Override - public BaseMeta fetchMetaClinicalData(List studyIds, List ids, List attributeIds, - String clinicalDataType) { - - return clinicalDataRepository.fetchMetaClinicalData(studyIds, ids, attributeIds, clinicalDataType); - } - - @Override - public List fetchClinicalDataCounts(List studyIds, List sampleIds, - List attributeIds) { - - if (attributeIds.isEmpty()) { - return new ArrayList<>(); - } - - List clinicalAttributes = clinicalAttributeService - .getClinicalAttributesByStudyIdsAndAttributeIds(studyIds, attributeIds); - - List sampleAttributeIds = new ArrayList<>(); - List patientAttributeIds = new ArrayList<>(); - // patient attributes which are also sample attributes in other studies - List conflictingPatientAttributeIds = new ArrayList<>(); - - clinicalAttributeUtil.extractCategorizedClinicalAttributes(clinicalAttributes, sampleAttributeIds, - patientAttributeIds, conflictingPatientAttributeIds); - - List clinicalDataCounts = new ArrayList(); - if (!sampleAttributeIds.isEmpty()) { - clinicalDataCounts.addAll(clinicalDataRepository.fetchClinicalDataCounts(studyIds, sampleIds, - sampleAttributeIds, "SAMPLE", "SUMMARY")); - } - - if (!patientAttributeIds.isEmpty()) { - clinicalDataCounts.addAll(clinicalDataRepository.fetchClinicalDataCounts(studyIds, sampleIds, - patientAttributeIds, "PATIENT", "SUMMARY")); - } - - if (!conflictingPatientAttributeIds.isEmpty()) { - clinicalDataCounts.addAll(clinicalDataRepository.fetchClinicalDataCounts(studyIds, sampleIds, - conflictingPatientAttributeIds, "PATIENT", "DETAILED")); - } - - sampleAttributeIds.addAll(conflictingPatientAttributeIds); - - clinicalDataCounts = clinicalDataCounts - .stream().filter(c -> !c.getValue().toUpperCase().equals("NA") - && !c.getValue().toUpperCase().equals("NAN") && !c.getValue().toUpperCase().equals("N/A")) - .collect(Collectors.toList()); - - Map> clinicalDataCountMap = clinicalDataCounts.stream() - .collect(Collectors.groupingBy(ClinicalDataCount::getAttributeId)); - - List patients = new ArrayList(); - if (!patientAttributeIds.isEmpty()) { - patients.addAll(patientService.getPatientsOfSamples(studyIds, sampleIds)); - } - - HashSet uniqueAttributeIds = new HashSet<>(attributeIds); - - return uniqueAttributeIds.stream().map(attributeId -> { - - int naCount = 0; - int totalCount = 0; - List counts = clinicalDataCountMap.getOrDefault(attributeId, new ArrayList<>()); - - if (conflictingPatientAttributeIds.contains(attributeId)) { - // if its a conflicting attribute then sum all counts - counts = counts.stream().collect(Collectors.toMap(ClinicalDataCount::getValue, Function.identity(), - (clinicalDataCount1, clinicalDataCount2) -> { - clinicalDataCount1.setCount(clinicalDataCount1.getCount() + clinicalDataCount2.getCount()); - return clinicalDataCount1; - })).values().stream().collect(Collectors.toList()); - } - - if (!counts.isEmpty()) { - totalCount = counts.stream().mapToInt(ClinicalDataCount::getCount).sum(); - } - - if (sampleAttributeIds.contains(attributeId)) { - naCount = sampleIds.size() - totalCount; - } else { - naCount = patients.size() - totalCount; - } - - if (naCount > 0) { - ClinicalDataCount clinicalDataCount = new ClinicalDataCount(); - clinicalDataCount.setAttributeId(attributeId); - clinicalDataCount.setValue("NA"); - clinicalDataCount.setCount(naCount); - counts.add(clinicalDataCount); - } - - ClinicalDataCountItem clinicalDataCountItem = new ClinicalDataCountItem(); - clinicalDataCountItem.setAttributeId(attributeId); - clinicalDataCountItem.setCounts(counts); - return clinicalDataCountItem; - - }).collect(Collectors.toList()); - } - - @Override - public List getPatientClinicalDataDetailedToSample(List studyIds, List patientIds, - List attributeIds) { - return clinicalDataRepository.getPatientClinicalDataDetailedToSample(studyIds, patientIds, attributeIds); - } - - @Override - public ImmutablePair fetchSampleClinicalTable(List studyIds, List sampleIds, Integer pageSize, Integer pageNumber, String searchTerm, String sortBy, String direction) { - if (studyIds == null || studyIds.isEmpty() || sampleIds == null || sampleIds.isEmpty()) { - return new ImmutablePair<>(SampleClinicalDataCollection.builder().build(), 0); - } - - // Request un-paginated data. - List allSampleInternalIds = clinicalDataRepository.getVisibleSampleInternalIdsForClinicalTable( - studyIds, sampleIds, - null, null, - searchTerm, sortBy, direction - ); - Integer offset = PaginationCalculator.offset(pageSize, pageNumber); - - if (allSampleInternalIds.isEmpty() || offset >= allSampleInternalIds.size()) { - return new ImmutablePair<>(SampleClinicalDataCollection.builder().build(), 0); - } - - return buildSampleClinicalDataCollection(allSampleInternalIds, offset, pageSize); - } - - private ImmutablePair buildSampleClinicalDataCollection(List allSampleInternalIds, Integer offset, Integer pageSize) { - - // Apply pagination to the sampleId list. - Integer toIndex = PaginationCalculator.lastIndex(offset, pageSize, allSampleInternalIds.size()); - List visibleSampleInternalIds = allSampleInternalIds.subList(offset, toIndex); - - List sampleClinicalData = clinicalDataRepository.getSampleClinicalDataBySampleInternalIds(visibleSampleInternalIds); - List patientClinicalData = clinicalDataRepository.getPatientClinicalDataBySampleInternalIds(visibleSampleInternalIds); - - // Merge sample and patient level clinical data and key by unique sample-key. - SampleClinicalDataCollection sampleClinicalDataCollection = SampleClinicalDataCollection.builder().withByUniqueSampleKey( - Stream.concat(sampleClinicalData.stream(), patientClinicalData.stream()) - .collect(Collectors.groupingBy(clinicalDatum -> calculateBase64(clinicalDatum.getSampleId(), clinicalDatum.getStudyId()))) - ).build(); - - return new ImmutablePair<>(sampleClinicalDataCollection, allSampleInternalIds.size()); - } -} diff --git a/src/main/java/org/cbioportal/service/impl/ClinicalEventServiceImpl.java b/src/main/java/org/cbioportal/service/impl/ClinicalEventServiceImpl.java deleted file mode 100644 index 187bec33ef1..00000000000 --- a/src/main/java/org/cbioportal/service/impl/ClinicalEventServiceImpl.java +++ /dev/null @@ -1,257 +0,0 @@ -package org.cbioportal.service.impl; - -import org.apache.commons.collections4.CollectionUtils; -import org.cbioportal.model.ClinicalData; -import org.cbioportal.model.ClinicalEvent; -import org.cbioportal.model.ClinicalEventData; -import org.cbioportal.model.ClinicalEventTypeCount; -import org.cbioportal.model.Patient; -import org.cbioportal.model.meta.BaseMeta; -import org.cbioportal.persistence.ClinicalEventRepository; -import org.cbioportal.service.ClinicalEventService; -import org.cbioportal.service.PatientService; -import org.cbioportal.service.exception.PatientNotFoundException; -import org.cbioportal.service.exception.StudyNotFoundException; -import org.cbioportal.web.parameter.ClinicalEventRequestIdentifier; -import org.cbioportal.web.parameter.OccurrencePosition; -import org.cbioportal.web.parameter.SurvivalRequest; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.Set; -import java.util.function.Function; -import java.util.function.ToIntFunction; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -@Service -public class ClinicalEventServiceImpl implements ClinicalEventService { - - @Autowired - private ClinicalEventRepository clinicalEventRepository; - @Autowired - private PatientService patientService; - - @Override - public List getAllClinicalEventsOfPatientInStudy(String studyId, String patientId, String projection, - Integer pageSize, Integer pageNumber, String sortBy, - String direction) throws PatientNotFoundException, - StudyNotFoundException { - - patientService.getPatientInStudy(studyId, patientId); - - List clinicalEvents = clinicalEventRepository.getAllClinicalEventsOfPatientInStudy(studyId, - patientId, projection, pageSize, pageNumber, sortBy, direction); - - if (!projection.equals("ID") && !clinicalEvents.isEmpty() ) { - - List clinicalEventDataList = clinicalEventRepository.getDataOfClinicalEvents( - clinicalEvents.stream().map(ClinicalEvent::getClinicalEventId).collect(Collectors.toList())); - - clinicalEvents.forEach(c -> c.setAttributes(clinicalEventDataList.stream().filter(a -> - a.getClinicalEventId().equals(c.getClinicalEventId())).collect(Collectors.toList()))); - } - - return clinicalEvents; - } - - @Override - public BaseMeta getMetaPatientClinicalEvents(String studyId, String patientId) throws PatientNotFoundException, - StudyNotFoundException { - - patientService.getPatientInStudy(studyId, patientId); - - return clinicalEventRepository.getMetaPatientClinicalEvents(studyId, patientId); - } - - @Override - public List getAllClinicalEventsInStudy(String studyId, String projection, Integer pageSize, - Integer pageNumber, String sortBy, String direction) - { - - List clinicalEvents = clinicalEventRepository.getAllClinicalEventsInStudy(studyId, - projection, pageSize, pageNumber, sortBy, direction); - - if (!projection.equals("ID")) { - - List clinicalEventDataList = clinicalEventRepository.getDataOfClinicalEvents( - clinicalEvents.stream().map(ClinicalEvent::getClinicalEventId).collect(Collectors.toList())); - - clinicalEvents.forEach(c -> c.setAttributes(clinicalEventDataList.stream().filter(a -> - a.getClinicalEventId().equals(c.getClinicalEventId())).collect(Collectors.toList()))); - } - - return clinicalEvents; - } - - @Override - public BaseMeta getMetaClinicalEvents(String studyId) throws StudyNotFoundException { - return clinicalEventRepository.getMetaClinicalEvents(studyId); - } - - @Override - public Map> getPatientsSamplesPerClinicalEventType(List studyIds, List sampleIds) { - - return clinicalEventRepository.getSamplesOfPatientsPerEventTypeInStudy(studyIds, sampleIds); - } - - @Override - public List getClinicalEventTypeCounts(List studyIds, List sampleIds) { - - List patients = patientService.getPatientsOfSamples(studyIds, sampleIds); - - List studies = patients.stream().map(Patient::getCancerStudyIdentifier) - .collect(Collectors.toList()); - List patientIds = patients.stream().map(Patient::getStableId) - .collect(Collectors.toList()); - - List clinicalEvents = clinicalEventRepository.getPatientsDistinctClinicalEventInStudies(studies, patientIds); - - Map clinicalEventTypeCountMap = new HashMap<>(); - for(ClinicalEvent e : clinicalEvents) { - clinicalEventTypeCountMap. - put(e.getEventType(), - clinicalEventTypeCountMap.getOrDefault(e.getEventType(),0) + 1); - } - - return clinicalEventTypeCountMap.entrySet() - .stream() - .map(e -> new ClinicalEventTypeCount(e.getKey(),e.getValue())) - .collect(Collectors.toList()); - } - - @Override - public List getSurvivalData(List studyIds, - List patientIds, - String attributeIdPrefix, - SurvivalRequest survivalRequest) { - List startClinicalEventsMeta = getToClinicalEvents(survivalRequest.getStartEventRequestIdentifier()); - List patientStartEvents = clinicalEventRepository.getTimelineEvents(studyIds, patientIds, startClinicalEventsMeta); - - // only fetch end timeline events for patients that have endClinicalEventsMeta and start timeline events - List patientEndEvents = filterClinicalEvents(patientStartEvents, survivalRequest.getEndEventRequestIdentifier()); - - ToIntFunction startPositionIdentifier = getPositionIdentifier(survivalRequest.getStartEventRequestIdentifier().getPosition()); - ToIntFunction endPositionIdentifier = getPositionIdentifier(survivalRequest.getEndEventRequestIdentifier().getPosition()); - Map patientEndEventsById = patientEndEvents.stream().collect(Collectors.toMap(ClinicalEventServiceImpl::getKey, Function.identity())); - - // filter out cases where start event is less than end event - patientStartEvents = patientStartEvents.stream() - .filter(event -> - Optional.ofNullable(patientEndEventsById.get(getKey(event))) - .map(endPositionIdentifier::applyAsInt) - .map(endDate -> startPositionIdentifier.applyAsInt(event) < endDate) - .orElse(true) - ).toList(); - - List patientCensoredEvents = filterClinicalEvents(patientStartEvents, survivalRequest.getCensoredEventRequestIdentifier()); - Map patientCensoredEventsById = patientCensoredEvents.stream().collect(Collectors.toMap(ClinicalEventServiceImpl::getKey, Function.identity())); - - return patientStartEvents.stream() - .flatMap(event -> { - ClinicalData clinicalDataMonths = buildClinicalSurvivalMonths(attributeIdPrefix, event, survivalRequest, patientEndEventsById, patientCensoredEventsById); - if (clinicalDataMonths == null) return Stream.empty(); - ClinicalData clinicalDataStatus = buildClinicalSurvivalStatus(attributeIdPrefix, event, patientEndEventsById); - - return Stream.of(clinicalDataMonths, clinicalDataStatus); - }).toList(); - } - - @Override - public List getClinicalEventsMeta(List studyIds, List patientIds, List clinicalEvents) { - return clinicalEventRepository.getClinicalEventsMeta(studyIds, patientIds, clinicalEvents); - } - - private static String getKey(ClinicalEvent clinicalEvent) { - return clinicalEvent.getStudyId() + clinicalEvent.getPatientId(); - } - - private static List getToClinicalEvents(ClinicalEventRequestIdentifier clinicalEventRequestIdentifier) { - return clinicalEventRequestIdentifier.getClinicalEventRequests().stream().map(x -> { - ClinicalEvent clinicalEvent = new ClinicalEvent(); - clinicalEvent.setEventType(x.getEventType()); - clinicalEvent.setAttributes(x.getAttributes()); - - return clinicalEvent; - }).toList(); - } - - private ToIntFunction getPositionIdentifier(OccurrencePosition position) { - return position.equals(OccurrencePosition.FIRST) ? ClinicalEvent::getStartDate : ClinicalEvent::getStopDate; - } - - private List filterClinicalEvents(List patientEvents, - ClinicalEventRequestIdentifier clinicalEventRequestIdentifier) { - List filteredStudyIds = new ArrayList<>(); - List filteredPatientIds = new ArrayList<>(); - for (ClinicalEvent clinicalEvent : patientEvents) { - filteredStudyIds.add(clinicalEvent.getStudyId()); - filteredPatientIds.add(clinicalEvent.getPatientId()); - } - - List clinicalEventsMeta = new ArrayList<>(); - if (clinicalEventRequestIdentifier != null) { - clinicalEventsMeta = getToClinicalEvents(clinicalEventRequestIdentifier); - } - - // only fetch end timeline events for patients that have endClinicalEventsMeta and start timeline events - List queriedPatientEvents = new ArrayList<>(); - if (CollectionUtils.isNotEmpty(filteredStudyIds)) { - queriedPatientEvents = clinicalEventRepository.getTimelineEvents(filteredStudyIds, filteredPatientIds, clinicalEventsMeta); - } - return queriedPatientEvents; - } - - private ClinicalData buildClinicalSurvivalMonths(String attributeIdPrefix, ClinicalEvent event, SurvivalRequest survivalRequest, Map patientEndEventsById, Map patientCensoredEventsById) { - final String SURVIVAL_MONTH_ATTRIBUTE = attributeIdPrefix + "_MONTHS"; - ClinicalData clinicalDataMonths = new ClinicalData(); - clinicalDataMonths.setStudyId(event.getStudyId()); - clinicalDataMonths.setPatientId(event.getPatientId()); - clinicalDataMonths.setAttrId(SURVIVAL_MONTH_ATTRIBUTE); - - ToIntFunction startPositionIdentifier = getPositionIdentifier(survivalRequest.getStartEventRequestIdentifier().getPosition()); - ToIntFunction endPositionIdentifier = survivalRequest.getEndEventRequestIdentifier() == null ? ClinicalEvent::getStopDate : getPositionIdentifier(survivalRequest.getEndEventRequestIdentifier().getPosition()); - ToIntFunction censoredPositionIdentifier = survivalRequest.getCensoredEventRequestIdentifier() == null ? ClinicalEvent::getStopDate : getPositionIdentifier(survivalRequest.getCensoredEventRequestIdentifier().getPosition()); - - int startDate = startPositionIdentifier.applyAsInt(event); - int endDate; - if (patientEndEventsById.containsKey(getKey(event))) { - endDate = endPositionIdentifier.applyAsInt(patientEndEventsById.get(getKey(event))); - } else { - // ignore cases where patient does not have censored timeline events or - // stop date of start event is less than start date of censored events - if (!patientCensoredEventsById.containsKey(getKey(event)) || - startDate >= censoredPositionIdentifier.applyAsInt(patientCensoredEventsById.get(getKey(event))) - ) { - return null; - } - - endDate = censoredPositionIdentifier.applyAsInt(patientCensoredEventsById.get(getKey(event))); - } - final String SURVIVAL_MONTH = String.valueOf((endDate - startDate) / 30.4); - clinicalDataMonths.setAttrValue(SURVIVAL_MONTH); - - return clinicalDataMonths; - } - - private ClinicalData buildClinicalSurvivalStatus(String attributeIdPrefix, ClinicalEvent event, Map patientEndEventsById) { - - ClinicalData clinicalDataStatus = new ClinicalData(); - clinicalDataStatus.setStudyId(event.getStudyId()); - clinicalDataStatus.setPatientId(event.getPatientId()); - clinicalDataStatus.setAttrId(attributeIdPrefix + "_STATUS"); - - if (patientEndEventsById.containsKey(getKey(event))) { - clinicalDataStatus.setAttrValue("1:EVENT"); - } else { - clinicalDataStatus.setAttrValue("0:CENSORED"); - } - - return clinicalDataStatus; - } -} diff --git a/src/main/java/org/cbioportal/service/impl/CoExpressionServiceImpl.java b/src/main/java/org/cbioportal/service/impl/CoExpressionServiceImpl.java deleted file mode 100644 index ced09b17dc5..00000000000 --- a/src/main/java/org/cbioportal/service/impl/CoExpressionServiceImpl.java +++ /dev/null @@ -1,266 +0,0 @@ -package org.cbioportal.service.impl; - -import org.cbioportal.model.*; -import org.cbioportal.persistence.MolecularDataRepository; -import org.cbioportal.persistence.SampleListRepository; -import org.cbioportal.service.*; -import org.cbioportal.service.exception.*; -import org.cbioportal.service.util.CoExpressionAsyncMethods; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.transaction.annotation.Transactional; -import org.springframework.stereotype.Service; - -import java.util.*; -import java.util.Map.Entry; -import java.util.function.Function; -import java.util.stream.Collectors; -import java.util.concurrent.CompletableFuture; - -@Service -public class CoExpressionServiceImpl implements CoExpressionService { - - @Autowired - private CoExpressionAsyncMethods asyncMethods; - @Autowired - private MolecularDataService molecularDataService; - @Autowired - private GenesetDataService genesetDataService; - @Autowired - private MolecularProfileService molecularProfileService; - @Autowired - private SampleListRepository sampleListRepository; - @Autowired - private MolecularDataRepository molecularDataRepository; - @Autowired - private SampleService sampleService; - - @Override - // transaction needs to be setup here in order to return Iterable from molecularDataService in fetchCoExpressions - @Transactional(readOnly=true) - public List getCoExpressions(String geneticEntityId, EntityType geneticEntityType, - String sampleListId, String molecularProfileIdA, String molecularProfileIdB, Double threshold) - throws MolecularProfileNotFoundException, SampleListNotFoundException, GenesetNotFoundException, - GeneNotFoundException { - - if (molecularProfileIdA.equals(molecularProfileIdB)) { - return getCoExpressions(molecularProfileIdA, sampleListId, geneticEntityId, geneticEntityType, threshold); - } - - List computedCoExpressions = null; - List molecularDataListA = null; - List molecularDataListB = null; - if (geneticEntityType.equals(EntityType.GENE)) { - molecularDataListA = molecularDataService.getMolecularData(molecularProfileIdA, sampleListId, null, - "SUMMARY"); - } else if (geneticEntityType.equals(EntityType.GENESET)) { - molecularDataListA = genesetDataService.fetchGenesetData(molecularProfileIdA, sampleListId, null); - } - MolecularProfile molecularProfileB = molecularProfileService.getMolecularProfile(molecularProfileIdB); - Boolean isMolecularProfileBOfGenesetType = molecularProfileB.getMolecularAlterationType() - .equals(MolecularProfile.MolecularAlterationType.GENESET_SCORE); - if (isMolecularProfileBOfGenesetType) { - molecularDataListB = genesetDataService.fetchGenesetData(molecularProfileIdB, sampleListId, null); - } else { - molecularDataListB = molecularDataService.getMolecularData(molecularProfileIdB, sampleListId, null, - "SUMMARY"); - } - Set samplesA = new HashSet( - (molecularDataListA.stream().map(g -> g.getSampleId()).collect(Collectors.toList()))); - Set samplesB = new HashSet( - (molecularDataListB.stream().map(g -> g.getSampleId()).collect(Collectors.toList()))); - Set sharedSamples = new HashSet(samplesA); // use the copy constructor - sharedSamples.retainAll(samplesB); - List finalmolecularDataListA = molecularDataListA.stream() - .filter(p -> sharedSamples.contains(p.getSampleId())).collect(Collectors.toList()); - List finalmolecularDataListB = molecularDataListB.stream() - .filter(p -> sharedSamples.contains(p.getSampleId())).collect(Collectors.toList()); - - return computeCoExpressionsFromMolecularData(finalmolecularDataListB, finalmolecularDataListA, geneticEntityId, threshold); - } - - @Override - public List getCoExpressions(String molecularProfileId, String sampleListId, String geneticEntityId, - EntityType geneticEntityType, Double threshold) - throws MolecularProfileNotFoundException, GenesetNotFoundException, GeneNotFoundException { - - List sampleIds = sampleListRepository.getAllSampleIdsInSampleList(sampleListId); - if (sampleIds.isEmpty()) { - return Collections.emptyList(); - } - - return fetchCoExpressions(molecularProfileId, sampleIds, geneticEntityId, geneticEntityType, threshold); - } - - @Override - public List fetchCoExpressions(String molecularProfileId, List sampleIds, - String queryGeneticEntityId, EntityType geneticEntityType, - Double threshold) - throws MolecularProfileNotFoundException, GenesetNotFoundException, GeneNotFoundException { - - // For the purpose of the CoExpression computation, we separate the MolecularAlteration - // (genetic_alteration table record) for the query gene/geneset from the MolecularAlteration(s) - // for the remaining genes/geneset in the profile. - MolecularAlteration queryMolecularDataList = null; - Iterable maItr = null; - if (geneticEntityType.equals(EntityType.GENE)) { - List queryGeneticEntityIds = Arrays.asList(Integer.valueOf(queryGeneticEntityId)); - maItr = molecularDataService.getMolecularAlterations(molecularProfileId, queryGeneticEntityIds, "SUMMARY"); - } else if (geneticEntityType.equals(EntityType.GENESET)) { - List queryGeneticEntityIds = Arrays.asList(queryGeneticEntityId); - maItr = genesetDataService.getGenesetAlterations(molecularProfileId, queryGeneticEntityIds); - } - for (MolecularAlteration ma : maItr) { - queryMolecularDataList = ma; - } - if (queryMolecularDataList == null) { - return Collections.emptyList(); - } - - // These next few lines are used to build a map of internal sample ids to - // indices into the genetic_alteration.VALUES column. Recall this column - // of the genetic_alteration table is a comma separated list of scalar values. - // Each value in this list is associated with a sample at the same position found in - // the genetic_profile_samples.ORDERED_SAMPLE_LIST column. - MolecularProfileSamples commaSeparatedSampleIdsOfMolecularProfile = molecularDataRepository - .getCommaSeparatedSampleIdsOfMolecularProfile(molecularProfileId); - List internalSampleIds = Arrays.stream(commaSeparatedSampleIdsOfMolecularProfile.getSplitSampleIds()) - .mapToInt(Integer::parseInt).boxed().collect(Collectors.toList()); - Map internalSampleIdToIndexMap = new HashMap<>(); - for (int lc = 0; lc < internalSampleIds.size(); lc++) { - internalSampleIdToIndexMap.put(internalSampleIds.get(lc), lc); - } - - // These next few lines build a list of Sample from the sampleIds method parameter (the user query). - // A map is then built of internal sample ids to indices into the Sample list (although the map is - // only used to quickly identify if a sample in the molecular profile is part of the user query - see below). - MolecularProfile molecularProfile = molecularProfileService.getMolecularProfile(molecularProfileId); - List studyIds = new ArrayList<>(); - sampleIds.forEach(s -> studyIds.add(molecularProfile.getCancerStudyIdentifier())); - List samples = sampleService.fetchSamples(studyIds, sampleIds, "ID"); - Map selectedSampleIdsMap = new HashMap<>(); - for (int lc = 0; lc < samples.size(); lc++) { - selectedSampleIdsMap.put(samples.get(lc).getInternalId(), lc); - } - - // These next few lines build a list of indices into the genetic_alteration.VALUES - // column by iterating over all the samples in the molecular profile (method parameter) - // and selecting only samples that are included in the user query. - Set includedIndexes = new HashSet<>(); - for (Integer internalSampleId : internalSampleIds) { - if (selectedSampleIdsMap.containsKey(internalSampleId)) { - includedIndexes.add(internalSampleIdToIndexMap.get(internalSampleId)); - } - } - - // These next few lines filter out genetic_alteration values from the query gene/geneset - // genetic_alteration.VALUES column by considering only the indices of the samples in the user query. - List queryValues = Arrays.asList(queryMolecularDataList.getSplitValues()); - List includedQueryValues = includedIndexes.stream().map(index -> queryValues.get(index)) - .collect(Collectors.toList()); - - // Get an iterator to all the MolecularAlteration (genetic_alteration table records) in the profile - if (geneticEntityType.equals(EntityType.GENE)) { - maItr = molecularDataService.getMolecularAlterations(molecularProfileId, null, "SUMMARY"); - } else if (geneticEntityType.equals(EntityType.GENESET)) { - maItr = genesetDataService.getGenesetAlterations(molecularProfileId, null); - } - - // For each MolecularAlteration in the profile, compute a CoExpression to return. - // If the MolecularAlteration is for the query gene/geneset, skip it. Otherwise, - // filter out genetic_alteration values from genetic_alteration.VALUES - // by considering oly the indices of the samples in the user query. - List> returnFutures = new ArrayList<>(); - for (MolecularAlteration ma : maItr) { - String entityId = ma.getStableId(); - if (entityId.equals(queryGeneticEntityId)) { - continue; - } - List internalValues = new ArrayList<>(Arrays.asList(ma.getSplitValues())); - List values = includedIndexes.stream().map(index -> internalValues.get(index)).collect(Collectors.toList()); - - CompletableFuture future = asyncMethods.computeCoExpression(entityId, values, includedQueryValues, threshold); - returnFutures.add(future); - } - return returnFutures.stream().map(CompletableFuture::join).filter(Objects::nonNull).collect(Collectors.toList()); - } - - @Override - // transaction needs to be setup here in order to return Iterable from molecularDataService in fetchCoExpressions - @Transactional(readOnly=true) - public List fetchCoExpressions(String geneticEntityId, - EntityType geneticEntityType, List sampleIds, String molecularProfileIdA, - String molecularProfileIdB, Double threshold) throws MolecularProfileNotFoundException, GenesetNotFoundException, GeneNotFoundException { - - if (molecularProfileIdA.equals(molecularProfileIdB)) { - return fetchCoExpressions(molecularProfileIdA, sampleIds, geneticEntityId, geneticEntityType, threshold); - } - - List computedCoExpressions = null; - List molecularDataListA = null; - List molecularDataListB = null; - if (geneticEntityType.equals(EntityType.GENE)) { - molecularDataListA = molecularDataService.fetchMolecularData(molecularProfileIdA, sampleIds, null, - "SUMMARY"); - } else if (geneticEntityType.equals(EntityType.GENESET)) { - molecularDataListA = genesetDataService.fetchGenesetData(molecularProfileIdA, sampleIds, null); - } - MolecularProfile molecularProfileB = molecularProfileService.getMolecularProfile(molecularProfileIdB); - Boolean isMolecularProfileBOfGenesetType = molecularProfileB.getMolecularAlterationType() - .equals(MolecularProfile.MolecularAlterationType.GENESET_SCORE); - if (isMolecularProfileBOfGenesetType) { - molecularDataListB = genesetDataService - .fetchGenesetData(molecularProfileIdB, sampleIds, null).stream() - .collect(Collectors.toList()); - } else { - molecularDataListB = molecularDataService - .fetchMolecularData(molecularProfileIdB, sampleIds, null, "SUMMARY").stream() - .collect(Collectors.toList()); - } - return computeCoExpressionsFromMolecularData(molecularDataListB, molecularDataListA, geneticEntityId, threshold); - } - - private List computeCoExpressionsFromMolecularData(List molecularDataListB, - List molecularDataListA, String queryGeneticEntityId, Double threshold) - throws GenesetNotFoundException, GeneNotFoundException { - - Map> molecularDataMapA = molecularDataListA.stream() - .collect(Collectors.groupingBy(MolecularData::getStableId)); - Map> molecularDataMapB = molecularDataListB.stream() - .collect(Collectors.groupingBy(MolecularData::getStableId)); - - if (!molecularDataMapA.keySet().contains(queryGeneticEntityId)) { - return Collections.emptyList(); - } - - List finalMolecularDataListA = (List)molecularDataMapA.remove(queryGeneticEntityId); - if (molecularDataMapB.get(queryGeneticEntityId) != null) { - List finalMolecularDataListB = (List)molecularDataMapB.remove(queryGeneticEntityId); - if (finalMolecularDataListB == null) { - return Collections.emptyList(); - } - } - - List> returnFutures = new ArrayList<>(); - - Map dataMapA = finalMolecularDataListA.stream() - .collect(Collectors.toMap(MolecularData::getSampleId, Function.identity())); - - for (Entry> entry : molecularDataMapB.entrySet()) { - List valuesA = new ArrayList<>(); - List valuesB = new ArrayList<>(); - - entry.getValue().stream().forEach(molecularData -> { - if (dataMapA.containsKey(molecularData.getSampleId())) { - valuesA.add(molecularData.getValue()); - valuesB.add(dataMapA.get(molecularData.getSampleId()).getValue()); - } - }); - - CompletableFuture future = asyncMethods.computeCoExpression(entry.getKey(), valuesA, valuesB, threshold); - returnFutures.add(future); - } - - return returnFutures.stream().map(CompletableFuture::join).filter(Objects::nonNull).collect(Collectors.toList()); - } - -} diff --git a/src/main/java/org/cbioportal/service/impl/CopyNumberSegmentServiceImpl.java b/src/main/java/org/cbioportal/service/impl/CopyNumberSegmentServiceImpl.java deleted file mode 100644 index efa3a34c482..00000000000 --- a/src/main/java/org/cbioportal/service/impl/CopyNumberSegmentServiceImpl.java +++ /dev/null @@ -1,68 +0,0 @@ -package org.cbioportal.service.impl; - -import org.cbioportal.model.CopyNumberSeg; -import org.cbioportal.model.meta.BaseMeta; -import org.cbioportal.persistence.CopyNumberSegmentRepository; -import org.cbioportal.service.CopyNumberSegmentService; -import org.cbioportal.service.SampleService; -import org.cbioportal.service.exception.SampleNotFoundException; -import org.cbioportal.service.exception.StudyNotFoundException; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -import java.util.List; - -@Service -public class CopyNumberSegmentServiceImpl implements CopyNumberSegmentService { - - @Autowired - private CopyNumberSegmentRepository copyNumberSegmentRepository; - @Autowired - private SampleService sampleService; - - @Override - public List getCopyNumberSegmentsInSampleInStudy(String studyId, String sampleId, String chromosome, - String projection, Integer pageSize, - Integer pageNumber, String sortBy, - String direction) throws SampleNotFoundException, - StudyNotFoundException { - - sampleService.getSampleInStudy(studyId, sampleId); - - return copyNumberSegmentRepository.getCopyNumberSegmentsInSampleInStudy(studyId, sampleId, chromosome, - projection, pageSize, pageNumber, sortBy, direction); - } - - @Override - public BaseMeta getMetaCopyNumberSegmentsInSampleInStudy(String studyId, String sampleId, String chromosome) - throws SampleNotFoundException, StudyNotFoundException { - - sampleService.getSampleInStudy(studyId, sampleId); - - return copyNumberSegmentRepository.getMetaCopyNumberSegmentsInSampleInStudy(studyId, sampleId, chromosome); - } - - @Override - public List fetchCopyNumberSegments(List studyIds, - List sampleIds, - String chromosome, - String projection) { - - return copyNumberSegmentRepository.fetchCopyNumberSegments(studyIds, sampleIds, chromosome, projection); - } - - @Override - public BaseMeta fetchMetaCopyNumberSegments(List studyIds, List sampleIds, String chromsome) { - - return copyNumberSegmentRepository.fetchMetaCopyNumberSegments(studyIds, sampleIds, chromsome); - } - - @Override - public List getCopyNumberSegmentsBySampleListId(String studyId, - String sampleListId, - String chromosome, - String projection) { - - return copyNumberSegmentRepository.getCopyNumberSegmentsBySampleListId(studyId, sampleListId, chromosome, projection); - } -} diff --git a/src/main/java/org/cbioportal/service/impl/CosmicCountServiceImpl.java b/src/main/java/org/cbioportal/service/impl/CosmicCountServiceImpl.java deleted file mode 100644 index 218201c21db..00000000000 --- a/src/main/java/org/cbioportal/service/impl/CosmicCountServiceImpl.java +++ /dev/null @@ -1,22 +0,0 @@ -package org.cbioportal.service.impl; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -import java.util.List; -import org.cbioportal.model.CosmicMutation; -import org.cbioportal.service.CosmicCountService; -import org.cbioportal.persistence.CosmicCountRepository; - -@Service -public class CosmicCountServiceImpl implements CosmicCountService { - - @Autowired - private CosmicCountRepository cosmicCountRepository; - - @Override - public List fetchCosmicCountsByKeywords(List keywords) { - - return cosmicCountRepository.fetchCosmicCountsByKeywords(keywords); - } -} diff --git a/src/main/java/org/cbioportal/service/impl/CustomDataServiceImpl.java b/src/main/java/org/cbioportal/service/impl/CustomDataServiceImpl.java deleted file mode 100644 index 3d339efb176..00000000000 --- a/src/main/java/org/cbioportal/service/impl/CustomDataServiceImpl.java +++ /dev/null @@ -1,58 +0,0 @@ -package org.cbioportal.service.impl; - -import com.fasterxml.jackson.databind.ObjectMapper; -import org.cbioportal.service.CustomDataService; -import org.cbioportal.service.util.CustomDataSession; -import org.cbioportal.service.util.SessionServiceRequestHandler; -import org.cbioportal.utils.removeme.Session; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -import java.util.List; -import java.util.Map; -import java.util.concurrent.CompletableFuture; -import java.util.stream.Collectors; - -@Service -public class CustomDataServiceImpl implements CustomDataService { - @Autowired - private SessionServiceRequestHandler sessionServiceRequestHandler; - - @Autowired - private ObjectMapper sessionServiceObjectMapper; - - /** - * Retrieve CustomDataSession from session service for custom data attributes. - * @param customAttributeIds - attribute id/hash of custom data used as session service key. - * @return Map of custom data attribute id to the CustomDataSession - */ - @Override - public Map getCustomDataSessions(List customAttributeIds) { - Map> postFuturesMap = customAttributeIds.stream() - .collect(Collectors.toMap( - attributeId -> attributeId, - attributeId -> CompletableFuture.supplyAsync(() -> { - try { - String customDataSessionJson = sessionServiceRequestHandler.getSessionDataJson( - Session.SessionType.custom_data, - attributeId - ); - return sessionServiceObjectMapper.readValue(customDataSessionJson, CustomDataSession.class); - } catch (Exception e) { - return null; - } - }) - )); - - CompletableFuture.allOf(postFuturesMap.values().toArray(new CompletableFuture[postFuturesMap.size()])).join(); - - Map customDataSessions = postFuturesMap.entrySet().stream() - .filter(entry -> entry.getValue().join() != null) - .collect(Collectors.toMap( - entry -> entry.getKey(), - entry -> entry.getValue().join() - )); - - return customDataSessions; - } -} diff --git a/src/main/java/org/cbioportal/service/impl/DiscreteCopyNumberServiceImpl.java b/src/main/java/org/cbioportal/service/impl/DiscreteCopyNumberServiceImpl.java deleted file mode 100644 index c862e7924ce..00000000000 --- a/src/main/java/org/cbioportal/service/impl/DiscreteCopyNumberServiceImpl.java +++ /dev/null @@ -1,256 +0,0 @@ -package org.cbioportal.service.impl; - -import org.cbioportal.model.CNA; -import org.cbioportal.model.CopyNumberCount; -import org.cbioportal.model.CopyNumberCountByGene; -import org.cbioportal.model.DiscreteCopyNumberData; -import org.cbioportal.model.GeneFilterQuery; -import org.cbioportal.model.GeneMolecularData; -import org.cbioportal.model.MolecularProfile; -import org.cbioportal.model.meta.BaseMeta; -import org.cbioportal.persistence.DiscreteCopyNumberRepository; -import org.cbioportal.service.DiscreteCopyNumberService; -import org.cbioportal.service.MolecularDataService; -import org.cbioportal.service.MolecularProfileService; -import org.cbioportal.service.exception.MolecularProfileNotFoundException; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Optional; -import java.util.stream.Collectors; - -@Service -public class DiscreteCopyNumberServiceImpl implements DiscreteCopyNumberService { - - @Autowired - private DiscreteCopyNumberRepository discreteCopyNumberRepository; - @Autowired - private MolecularDataService molecularDataService; - @Autowired - private MolecularProfileService molecularProfileService; - - @Override - public List getDiscreteCopyNumbersInMolecularProfileBySampleListId( - String molecularProfileId, - String sampleListId, - List entrezGeneIds, - List alterationTypes, - String projection) - throws MolecularProfileNotFoundException { - - validateMolecularProfile(molecularProfileId); - if (isHomdelOrAmpOnly(alterationTypes)) { - - return discreteCopyNumberRepository.getDiscreteCopyNumbersInMolecularProfileBySampleListId(molecularProfileId, - sampleListId, entrezGeneIds, alterationTypes, projection); - } - - return molecularDataService.getMolecularData(molecularProfileId, sampleListId, entrezGeneIds, projection).stream() - .filter(g -> isValidAlteration(alterationTypes, g)).map(this::convert).collect(Collectors.toList()); - } - - @Override - public BaseMeta getMetaDiscreteCopyNumbersInMolecularProfileBySampleListId(String molecularProfileId, - String sampleListId, - List entrezGeneIds, - List alterationTypes) - throws MolecularProfileNotFoundException { - - validateMolecularProfile(molecularProfileId); - if (isHomdelOrAmpOnly(alterationTypes)) { - return discreteCopyNumberRepository.getMetaDiscreteCopyNumbersInMolecularProfileBySampleListId( - molecularProfileId, sampleListId, entrezGeneIds, alterationTypes); - } - - long totalCount = molecularDataService.getMolecularData(molecularProfileId, sampleListId, entrezGeneIds, "ID") - .stream().filter(g -> isValidAlteration(alterationTypes, g)).count(); - - BaseMeta baseMeta = new BaseMeta(); - baseMeta.setTotalCount(Math.toIntExact(totalCount)); - - return baseMeta; - } - - @Override - public List fetchDiscreteCopyNumbersInMolecularProfile(String molecularProfileId, - List sampleIds, - List entrezGeneIds, - List alterationTypes, - String projection) - throws MolecularProfileNotFoundException { - - validateMolecularProfile(molecularProfileId); - if (isHomdelOrAmpOnly(alterationTypes)) { - return discreteCopyNumberRepository.fetchDiscreteCopyNumbersInMolecularProfile(molecularProfileId, - sampleIds, entrezGeneIds, alterationTypes, projection); - } - - return molecularDataService.fetchMolecularData(molecularProfileId, sampleIds, entrezGeneIds, projection) - .stream().filter(g -> isValidAlteration(alterationTypes, g)) - .map(this::convert).collect(Collectors.toList()); - } - - @Override - public List getDiscreteCopyNumbersInMultipleMolecularProfiles(List molecularProfileIds, - List sampleIds, - List entrezGeneIds, - List alterationTypes, - String projection) { - - if (isHomdelOrAmpOnly(alterationTypes)) { - return discreteCopyNumberRepository.getDiscreteCopyNumbersInMultipleMolecularProfiles(molecularProfileIds, - sampleIds, entrezGeneIds, alterationTypes, projection); - } - - return molecularDataService.getMolecularDataInMultipleMolecularProfiles( - molecularProfileIds, - sampleIds, - entrezGeneIds, - projection) - .stream() - .filter(g -> isValidAlteration(alterationTypes, g)) - .map(this::convert) - .collect(Collectors.toList()); - } - - @Override - public List getDiscreteCopyNumbersInMultipleMolecularProfilesByGeneQueries(List molecularProfileIds, - List sampleIds, - List geneQueries, - String projection) { - - List cnas = geneQueries.stream().map(q -> q.getAlterations()).flatMap(List::stream).collect(Collectors.toList()); - if (cnas.isEmpty()) - return Collections.emptyList(); - - if (isHomdelOrAmpOnlyCna(cnas)) { - return discreteCopyNumberRepository.getDiscreteCopyNumbersInMultipleMolecularProfilesByGeneQueries(molecularProfileIds, - sampleIds, geneQueries, projection); - } - - return molecularDataService.getMolecularDataInMultipleMolecularProfilesByGeneQueries(molecularProfileIds, sampleIds, - geneQueries, projection).stream() - .map(this::convert) - .collect(Collectors.toList()); - } - - @Override - public BaseMeta fetchMetaDiscreteCopyNumbersInMolecularProfile(String molecularProfileId, - List sampleIds, - List entrezGeneIds, - List alterationTypes) - throws MolecularProfileNotFoundException { - - validateMolecularProfile(molecularProfileId); - if (isHomdelOrAmpOnly(alterationTypes)) { - return discreteCopyNumberRepository.fetchMetaDiscreteCopyNumbersInMolecularProfile(molecularProfileId, - sampleIds, entrezGeneIds, alterationTypes); - } - - long totalCount = molecularDataService.fetchMolecularData(molecularProfileId, sampleIds, entrezGeneIds, "ID") - .stream().filter(g -> isValidAlteration(alterationTypes, g)).count(); - - BaseMeta baseMeta = new BaseMeta(); - baseMeta.setTotalCount(Math.toIntExact(totalCount)); - - return baseMeta; - } - - @Override - public List getSampleCountByGeneAndAlterationAndSampleIds(String molecularProfileId, - List sampleIds, - List entrezGeneIds, - List alterations) - throws MolecularProfileNotFoundException { - - validateMolecularProfile(molecularProfileId); - - return discreteCopyNumberRepository - .getSampleCountByGeneAndAlterationAndSampleIds(molecularProfileId, sampleIds, entrezGeneIds, alterations); - } - - @Override - public List fetchCopyNumberCounts(String molecularProfileId, List entrezGeneIds, - List alterations) - throws MolecularProfileNotFoundException { - - validateMolecularProfile(molecularProfileId); - - Integer numberOfSamplesInMolecularProfile = molecularDataService.getNumberOfSamplesInMolecularProfile( - molecularProfileId); - List copyNumberSampleCountByGeneList = - getSampleCountByGeneAndAlterationAndSampleIds(molecularProfileId, null, entrezGeneIds, alterations); - - List copyNumberCounts = new ArrayList<>(); - for (int i = 0; i < alterations.size(); i++) { - Integer alteration = alterations.get(i); - Integer entrezGeneId = entrezGeneIds.get(i); - - CopyNumberCount copyNumberCount = new CopyNumberCount(); - copyNumberCount.setMolecularProfileId(molecularProfileId); - copyNumberCount.setEntrezGeneId(entrezGeneId); - copyNumberCount.setAlteration(alteration); - copyNumberCount.setNumberOfSamples(numberOfSamplesInMolecularProfile); - - Optional copyNumberSampleCountByGene = copyNumberSampleCountByGeneList.stream() - .filter(p -> p.getEntrezGeneId().equals(entrezGeneId) && p.getAlteration().equals(alteration)) - .findFirst(); - copyNumberSampleCountByGene.ifPresent(m -> copyNumberCount.setNumberOfSamplesWithAlterationInGene(m - .getNumberOfAlteredCases())); - - copyNumberCounts.add(copyNumberCount); - } - - return copyNumberCounts; - } - - private DiscreteCopyNumberData convert(GeneMolecularData molecularData) { - - DiscreteCopyNumberData discreteCopyNumberData = new DiscreteCopyNumberData(); - discreteCopyNumberData.setMolecularProfileId(molecularData.getMolecularProfileId()); - discreteCopyNumberData.setStudyId(molecularData.getStudyId()); - discreteCopyNumberData.setPatientId(molecularData.getPatientId()); - discreteCopyNumberData.setSampleId(molecularData.getSampleId()); - discreteCopyNumberData.setEntrezGeneId(molecularData.getEntrezGeneId()); - discreteCopyNumberData.setGene(molecularData.getGene()); - discreteCopyNumberData.setAlteration(Integer.parseInt(molecularData.getValue())); - - return discreteCopyNumberData; - } - - private boolean isHomdelOrAmpOnly(List alterationTypes) { - return !alterationTypes.contains(-1) && !alterationTypes.contains(0) && !alterationTypes.contains(1); - } - - private boolean isHomdelOrAmpOnlyCna(List alterationTypes) { - return !alterationTypes.contains(CNA.HETLOSS) && !alterationTypes.contains(CNA.DIPLOID) && !alterationTypes.contains(CNA.GAIN); - } - - private boolean isValidAlteration(List alterationTypes, GeneMolecularData molecularData) { - - boolean result; - try { - result = alterationTypes.contains(Integer.parseInt(molecularData.getValue())); - } catch (NumberFormatException ex) { - result = false; - } - return result; - } - - private MolecularProfile validateMolecularProfile(String molecularProfileId) throws MolecularProfileNotFoundException { - - MolecularProfile molecularProfile = molecularProfileService.getMolecularProfile(molecularProfileId); - - if (!molecularProfile.getMolecularAlterationType() - .equals(MolecularProfile.MolecularAlterationType.COPY_NUMBER_ALTERATION) - || !MolecularProfile.DataType.DISCRETE.name().equals(molecularProfile.getDatatype()) - ) { - throw new MolecularProfileNotFoundException(molecularProfileId); - } - - return molecularProfile; - } -} diff --git a/src/main/java/org/cbioportal/service/impl/EhcacheStatisticsServiceImpl.java b/src/main/java/org/cbioportal/service/impl/EhcacheStatisticsServiceImpl.java deleted file mode 100644 index dfa1019e51f..00000000000 --- a/src/main/java/org/cbioportal/service/impl/EhcacheStatisticsServiceImpl.java +++ /dev/null @@ -1,22 +0,0 @@ -package org.cbioportal.service.impl; - -import org.cbioportal.persistence.util.EhcacheStatistics; -import org.cbioportal.utils.config.annotation.ConditionalOnProperty; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.annotation.Primary; -import org.springframework.stereotype.Service; - -@Primary // if there is another CacheStatisticsService bean this one should be the one selected -@Service -@ConditionalOnProperty(name = "persistence.cache_type", havingValue = {"ehcache-heap", "ehcache-disk", "ehcache-hybrid"}) -public class EhcacheStatisticsServiceImpl extends CacheStatisticsServiceImpl { - - @Autowired - public EhcacheStatistics ehcacheStatistics; - - @Override - public String getCacheStatistics() { - super.checkIfCacheStatisticsEndpointEnabled(); - return ehcacheStatistics.getCacheStatistics(); - } -} diff --git a/src/main/java/org/cbioportal/service/impl/ExpressionEnrichmentServiceImpl.java b/src/main/java/org/cbioportal/service/impl/ExpressionEnrichmentServiceImpl.java deleted file mode 100644 index 849983cbd3c..00000000000 --- a/src/main/java/org/cbioportal/service/impl/ExpressionEnrichmentServiceImpl.java +++ /dev/null @@ -1,275 +0,0 @@ -package org.cbioportal.service.impl; -import java.math.BigDecimal; -import java.util.*; -import java.util.function.Function; -import java.util.stream.Collectors; - -import org.apache.commons.lang3.BooleanUtils; -import org.cbioportal.model.MolecularProfile.MolecularAlterationType; -import org.cbioportal.model.meta.GenericAssayMeta; -import org.cbioportal.model.EnrichmentType; -import org.cbioportal.model.GenericAssayBinaryEnrichment; -import org.cbioportal.model.GenericAssayCategoricalEnrichment; -import org.cbioportal.model.GenericAssayMolecularAlteration; -import org.cbioportal.model.MolecularProfileCaseIdentifier; -import org.cbioportal.model.MolecularProfile; -import org.cbioportal.model.Sample; -import org.cbioportal.model.GenericAssayEnrichment; -import org.cbioportal.model.GenomicEnrichment; -import org.cbioportal.model.Gene; -import org.cbioportal.model.GeneMolecularAlteration; -import org.cbioportal.persistence.MolecularDataRepository; -import org.cbioportal.service.ExpressionEnrichmentService; -import org.cbioportal.service.GeneService; -import org.cbioportal.service.GenericAssayService; -import org.cbioportal.service.MolecularProfileService; -import org.cbioportal.service.SampleService; -import org.cbioportal.service.exception.MolecularProfileNotFoundException; -import org.cbioportal.service.util.ExpressionEnrichmentUtil; -import org.cbioportal.service.util.FisherExactTestCalculator; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -@Service -public class ExpressionEnrichmentServiceImpl implements ExpressionEnrichmentService { - - @Autowired - private MolecularProfileService molecularProfileService; - @Autowired - private MolecularDataRepository molecularDataRepository; - @Autowired - private GeneService geneService; - @Autowired - private ExpressionEnrichmentUtil expressionEnrichmentUtil; - @Autowired - private GenericAssayService genericAssayService; - @Autowired - private SampleService sampleService; - @Autowired - private FisherExactTestCalculator fisherExactTestCalculator = new FisherExactTestCalculator(); - @Override - // transaction needs to be setup here in order to return Iterable from - // molecularDataService in fetchCoExpressions - @Transactional(readOnly = true) - public List getGenomicEnrichments(String molecularProfileId, - Map> molecularProfileCaseSets, EnrichmentType enrichmentType) - throws MolecularProfileNotFoundException { - MolecularProfile molecularProfile = molecularProfileService.getMolecularProfile(molecularProfileId); - List validGenomicMolecularAlterationTypes = Arrays.asList( - MolecularAlterationType.MICRO_RNA_EXPRESSION, MolecularAlterationType.MRNA_EXPRESSION, - MolecularAlterationType.MRNA_EXPRESSION_NORMALS, MolecularAlterationType.RNA_EXPRESSION, - MolecularAlterationType.METHYLATION, MolecularAlterationType.METHYLATION_BINARY, - MolecularAlterationType.PHOSPHORYLATION, MolecularAlterationType.PROTEIN_LEVEL, - MolecularAlterationType.PROTEIN_ARRAY_PROTEIN_LEVEL, - MolecularAlterationType.PROTEIN_ARRAY_PHOSPHORYLATION); - validateMolecularProfile(molecularProfile, validGenomicMolecularAlterationTypes); - Iterable maItr = molecularDataRepository - .getGeneMolecularAlterationsIterableFast(molecularProfile.getStableId()); - List expressionEnrichments = expressionEnrichmentUtil.getEnrichments(molecularProfile, - molecularProfileCaseSets, enrichmentType, maItr); - List entrezGeneIds = expressionEnrichments.stream().map(GenomicEnrichment::getEntrezGeneId) - .collect(Collectors.toList()); - Map> geneMapByEntrezId = geneService - .fetchGenes(entrezGeneIds.stream().map(Object::toString).collect(Collectors.toList()), "ENTREZ_GENE_ID", - "SUMMARY") - .stream().collect(Collectors.groupingBy(Gene::getEntrezGeneId)); - return expressionEnrichments.stream() - // filter Enrichments having no gene reference object(this - // happens when multiple - // entrez ids map to same hugo gene symbol) - .filter(expressionEnrichment -> geneMapByEntrezId.containsKey(expressionEnrichment.getEntrezGeneId())) - .map(expressionEnrichment -> { - Gene gene = geneMapByEntrezId.get(expressionEnrichment.getEntrezGeneId()).get(0); - expressionEnrichment.setHugoGeneSymbol(gene.getHugoGeneSymbol()); - return expressionEnrichment; - }).collect(Collectors.toList()); - } - @Override - // transaction needs to be setup here in order to return Iterable from - // molecularDataRepository in getGenericAssayMolecularAlterationsIterable - @Transactional(readOnly = true) - public List getGenericAssayNumericalEnrichments(String molecularProfileId, - Map> molecularProfileCaseSets, EnrichmentType enrichmentType) - throws MolecularProfileNotFoundException { - MolecularProfile molecularProfile = molecularProfileService.getMolecularProfile(molecularProfileId); - validateMolecularProfile(molecularProfile, Arrays.asList(MolecularAlterationType.GENERIC_ASSAY)); - Iterable maItr = molecularDataRepository - .getGenericAssayMolecularAlterationsIterable(molecularProfile.getStableId(), null, "SUMMARY"); - Map> filteredMolecularProfileCaseSets; - if (BooleanUtils.isTrue(molecularProfile.getPatientLevel())) { - // Build sampleIdToPatientIdMap to quick find if a sample has shared patientId with other samples - List sampleIds = molecularProfileCaseSets.values().stream().flatMap(Collection::stream).map(MolecularProfileCaseIdentifier::getCaseId).collect(Collectors.toList()); - List studyIds = Collections.nCopies(sampleIds.size(), molecularProfile.getCancerStudyIdentifier()); - List samples = sampleService.fetchSamples(studyIds, sampleIds, "SUMMARY"); - Map sampleIdToPatientIdMap = samples.stream().collect(Collectors.toMap(Sample::getStableId, Sample::getPatientId)); - // Build filteredMolecularProfileCaseSets - filteredMolecularProfileCaseSets = new HashMap<>(); - for (Map.Entry> pair : molecularProfileCaseSets.entrySet()) { - Set patientSet = new HashSet(); - List identifierListUniqueByPatientId = new ArrayList<>(); - for (MolecularProfileCaseIdentifier caseIdentifier : pair.getValue()) { - if (!patientSet.contains(sampleIdToPatientIdMap.get(caseIdentifier.getCaseId()))) { - identifierListUniqueByPatientId.add(caseIdentifier); - patientSet.add(sampleIdToPatientIdMap.get(caseIdentifier.getCaseId())); - } - } - filteredMolecularProfileCaseSets.put(pair.getKey(), identifierListUniqueByPatientId); - } - } else { - filteredMolecularProfileCaseSets = molecularProfileCaseSets; - } - List genericAssayEnrichments = expressionEnrichmentUtil.getEnrichments(molecularProfile, - filteredMolecularProfileCaseSets, enrichmentType, maItr); - List getGenericAssayStableIds = genericAssayEnrichments.stream() - .map(GenericAssayEnrichment::getStableId).collect(Collectors.toList()); - Map genericAssayMetaByStableId = genericAssayService - .getGenericAssayMetaByStableIdsAndMolecularIds(getGenericAssayStableIds, - getGenericAssayStableIds.stream().map(stableId -> molecularProfileId) - .collect(Collectors.toList()), - "SUMMARY") - .stream().collect(Collectors.toMap(GenericAssayMeta::getStableId, Function.identity())); - return genericAssayEnrichments.stream().map(enrichmentDatum -> { - enrichmentDatum.setGenericEntityMetaProperties( - genericAssayMetaByStableId.get(enrichmentDatum.getStableId()).getGenericEntityMetaProperties()); - return enrichmentDatum; - }).collect(Collectors.toList()); - } - - @Override - @Transactional(readOnly = true) - public List getGenericAssayBinaryEnrichments( - String molecularProfileId, - Map> molecularProfileCaseSets, EnrichmentType enrichmentType) - throws MolecularProfileNotFoundException { - - // Validate and fetch molecular profile - MolecularProfile molecularProfile = getAndValidateMolecularProfile(molecularProfileId, "BINARY"); - - // Get the molecular alterations for the provided profile - Iterable maItr = molecularDataRepository - .getGenericAssayMolecularAlterationsIterable(molecularProfile.getStableId(), null, "SUMMARY"); - - // Filter the case sets based on molecular profile - Map> filteredMolecularProfileCaseSets = filterMolecularProfileCaseSets(molecularProfile, molecularProfileCaseSets); - - // Obtain binary enrichments from the utility - List genericAssayBinaryEnrichments = expressionEnrichmentUtil.getGenericAssayBinaryEnrichments(molecularProfile, - filteredMolecularProfileCaseSets, enrichmentType, maItr); - - // Calculate q-values for enrichments - calcQValues(genericAssayBinaryEnrichments); - - // Extract stable IDs from binary enrichments - List getGenericAssayStableIds = genericAssayBinaryEnrichments.stream() - .map(GenericAssayEnrichment::getStableId).collect(Collectors.toList()); - - // Fetch metadata of generic assays by their stable IDs - Map genericAssayMetaByStableId = getGenericAssayMetaByStableId(getGenericAssayStableIds, molecularProfileId); - - // Assign meta properties to each enrichment - return genericAssayBinaryEnrichments.stream().map(enrichmentDatum -> { - enrichmentDatum.setGenericEntityMetaProperties( - genericAssayMetaByStableId.get(enrichmentDatum.getStableId()).getGenericEntityMetaProperties()); - return enrichmentDatum; - }).collect(Collectors.toList()); - } - - @Override - @Transactional(readOnly = true) - public List getGenericAssayCategoricalEnrichments(String molecularProfileId, - Map> molecularProfileCaseSets, EnrichmentType enrichmentType) - throws MolecularProfileNotFoundException { - - MolecularProfile molecularProfile = getAndValidateMolecularProfile(molecularProfileId, "CATEGORICAL"); - - Iterable maItr = molecularDataRepository - .getGenericAssayMolecularAlterationsIterable(molecularProfile.getStableId(), null, "SUMMARY"); - - Map> filteredMolecularProfileCaseSets = filterMolecularProfileCaseSets(molecularProfile, molecularProfileCaseSets); - - List genericAssayCategoricalEnrichments = expressionEnrichmentUtil.getGenericAssayCategoricalEnrichments(molecularProfile, - filteredMolecularProfileCaseSets, enrichmentType, maItr); - - calcQValues(genericAssayCategoricalEnrichments); - - List getGenericAssayStableIds = genericAssayCategoricalEnrichments.stream() - .map(GenericAssayEnrichment::getStableId).collect(Collectors.toList()); - Map genericAssayMetaByStableId = getGenericAssayMetaByStableId(getGenericAssayStableIds, molecularProfileId); - - return genericAssayCategoricalEnrichments.stream().map(enrichmentDatum -> { - enrichmentDatum.setGenericEntityMetaProperties( - genericAssayMetaByStableId.get(enrichmentDatum.getStableId()).getGenericEntityMetaProperties()); - return enrichmentDatum; - }).collect(Collectors.toList()); - } - - private MolecularProfile getAndValidateMolecularProfile(String molecularProfileId, String dataType) throws MolecularProfileNotFoundException { - MolecularProfile molecularProfile = molecularProfileService.getMolecularProfile(molecularProfileId); - validateMolecularProfile(molecularProfile, Arrays.asList(MolecularProfile.MolecularAlterationType.GENERIC_ASSAY), dataType); - return molecularProfile; - } - - private void validateMolecularProfile(MolecularProfile molecularProfile, - List validMolecularAlterationTypes, - String dataType) throws MolecularProfileNotFoundException { - if (!validMolecularAlterationTypes.contains(molecularProfile.getMolecularAlterationType())) { - // Check alteration type - throw new MolecularProfileNotFoundException(molecularProfile.getStableId()); - } - // Check datatype for binary or categorical - if(molecularProfile.getMolecularAlterationType().equals(MolecularProfile.MolecularAlterationType.GENERIC_ASSAY) && - !molecularProfile.getDatatype().equals(dataType)) - throw new MolecularProfileNotFoundException(molecularProfile.getStableId()); - } - - private Map> filterMolecularProfileCaseSets(MolecularProfile molecularProfile, Map> molecularProfileCaseSets) { - if (BooleanUtils.isTrue(molecularProfile.getPatientLevel())) { - // If patient level, filter duplicates by patient id - // For now we only support sample level for samples - List sampleIds = molecularProfileCaseSets.values().stream().flatMap(Collection::stream).map(MolecularProfileCaseIdentifier::getCaseId).collect(Collectors.toList()); - List studyIds = Collections.nCopies(sampleIds.size(), molecularProfile.getCancerStudyIdentifier()); - List samples = sampleService.fetchSamples(studyIds, sampleIds, "ID"); - Map sampleIdToPatientIdMap = samples.stream().collect(Collectors.toMap(Sample::getStableId, Sample::getPatientId)); - - Map> filteredMolecularProfileCaseSets = new HashMap<>(); - for (Map.Entry> pair : molecularProfileCaseSets.entrySet()) { - Set patientSet = new HashSet(); - List identifierListUniqueByPatientId = new ArrayList<>(); - for (MolecularProfileCaseIdentifier caseIdentifier : pair.getValue()) { - if (!patientSet.contains(sampleIdToPatientIdMap.get(caseIdentifier.getCaseId()))) { - identifierListUniqueByPatientId.add(caseIdentifier); - patientSet.add(sampleIdToPatientIdMap.get(caseIdentifier.getCaseId())); - } - } - filteredMolecularProfileCaseSets.put(pair.getKey(), identifierListUniqueByPatientId); - } - return filteredMolecularProfileCaseSets; - } else { - return molecularProfileCaseSets; - } - } - - private Map getGenericAssayMetaByStableId(List stableIds, String molecularProfileId) { - return genericAssayService.getGenericAssayMetaByStableIdsAndMolecularIds(stableIds, stableIds.stream().map(sid -> molecularProfileId) - .collect(Collectors.toList()), "SUMMARY").stream() - .collect(Collectors.toMap(GenericAssayMeta::getStableId, Function.identity())); - } - - private void calcQValues(List enrichments) { - // Sort enrichments by pValue - Collections.sort(enrichments, GenericAssayEnrichment::compare); - BigDecimal[] pValues = enrichments.stream().map(T::getpValue).toArray(BigDecimal[]::new); - BigDecimal[] qValues = fisherExactTestCalculator.calcqValue(pValues); - // Assign q-values to enrichments - for (int i = 0; i < enrichments.size(); i++) { - enrichments.get(i).setqValue(qValues[i]); - } - } - private void validateMolecularProfile(MolecularProfile molecularProfile, - List validMolecularAlterationTypes) throws MolecularProfileNotFoundException { - if (!validMolecularAlterationTypes.contains(molecularProfile.getMolecularAlterationType())) { - throw new MolecularProfileNotFoundException(molecularProfile.getStableId()); - } - } -} diff --git a/src/main/java/org/cbioportal/service/impl/GeneMemoizerServiceImpl.java b/src/main/java/org/cbioportal/service/impl/GeneMemoizerServiceImpl.java deleted file mode 100644 index 2c0a097f16a..00000000000 --- a/src/main/java/org/cbioportal/service/impl/GeneMemoizerServiceImpl.java +++ /dev/null @@ -1,48 +0,0 @@ -package org.cbioportal.service.impl; - -import org.cbioportal.model.ReferenceGenomeGene; -import org.cbioportal.service.GeneMemoizerService; -import org.cbioportal.service.StaticDataTimestampService; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -import java.util.*; - -@Service -public class GeneMemoizerServiceImpl implements GeneMemoizerService { - @Autowired - private StaticDataTimestampService timestampService; - - private static final List TABLES = Arrays.asList("gene", "reference_genome_gene"); - - private static final Map> memoization = new HashMap<>(); - private static final Map expiry = new HashMap<>(); - private static final Object lock = new Object(); - - @Override - public List fetchGenes(String genomeName) { - synchronized (lock) { - if (memoization.containsKey(genomeName) && allTablesUpToDate(expiry.get(genomeName))) { - return memoization.get(genomeName); - } - } - - return null; - } - - private boolean allTablesUpToDate(Date expiration) { - Map timestamps = timestampService.getTimestampsAsDates(TABLES); - return TABLES.stream() - .map((table) -> timestamps.containsKey(table) && timestamps.get(table).before(expiration)) - .reduce((all, next) -> all && next) - .orElse(false); - } - - @Override - public void cacheGenes(List genes, String genomeName) { - synchronized (lock) { - expiry.put(genomeName, new Date()); - memoization.put(genomeName, genes); - } - } -} diff --git a/src/main/java/org/cbioportal/service/impl/GenePanelServiceImpl.java b/src/main/java/org/cbioportal/service/impl/GenePanelServiceImpl.java deleted file mode 100644 index cde04fc14d6..00000000000 --- a/src/main/java/org/cbioportal/service/impl/GenePanelServiceImpl.java +++ /dev/null @@ -1,214 +0,0 @@ -package org.cbioportal.service.impl; - -import org.apache.commons.collections4.CollectionUtils; -import org.cbioportal.model.*; -import org.cbioportal.model.meta.BaseMeta; -import org.cbioportal.persistence.GenePanelRepository; -import org.cbioportal.service.GenePanelService; -import org.cbioportal.service.MolecularProfileService; -import org.cbioportal.service.SampleListService; -import org.cbioportal.service.exception.GenePanelNotFoundException; -import org.cbioportal.service.exception.MolecularProfileNotFoundException; -import org.cbioportal.service.exception.SampleListNotFoundException; -import org.cbioportal.service.util.MolecularProfileUtil; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -import java.util.*; -import java.util.function.Function; -import java.util.stream.Collectors; - -import static java.util.stream.Collectors.*; - -@Service -public class GenePanelServiceImpl implements GenePanelService { - @Autowired - private GenePanelRepository genePanelRepository; - @Autowired - private MolecularProfileService molecularProfileService; - @Autowired - private SampleListService sampleListService; - @Autowired - private MolecularProfileUtil molecularProfileUtil; - - private final String SEQUENCED_LIST_SUFFIX = "_sequenced"; - - private final Function SAMPLE_IDENTIFIER_GENERATOR = d -> d.getMolecularProfileId() + d.getSampleId(); - private final Function PATIENT_IDENTIFIER_GENERATOR = d -> d.getMolecularProfileId() + d.getPatientId(); - - @Override - public List getAllGenePanels(String projection, Integer pageSize, Integer pageNumber, String sortBy, - String direction) { - - List genePanels = genePanelRepository.getAllGenePanels(projection, pageSize, pageNumber, sortBy, - direction); - - if (projection.equals("DETAILED")) { - - List genePanelToGeneList = genePanelRepository.getGenesOfPanels(genePanels - .stream().map(GenePanel::getStableId).collect(toList())); - - genePanels.forEach(g -> g.setGenes(genePanelToGeneList.stream().filter(p -> p.getGenePanelId() - .equals(g.getStableId())).collect(toList()))); - } - - return genePanels; - } - - @Override - public BaseMeta getMetaGenePanels() { - - return genePanelRepository.getMetaGenePanels(); - } - - @Override - public GenePanel getGenePanel(String genePanelId) throws GenePanelNotFoundException { - - GenePanel genePanel = genePanelRepository.getGenePanel(genePanelId); - if (genePanel == null) { - throw new GenePanelNotFoundException(genePanelId); - } - - genePanel.setGenes(genePanelRepository.getGenesOfPanels(Collections.singletonList(genePanelId))); - return genePanel; - } - - @Override - public List fetchGenePanels(List genePanelIds, String projection) { - - List genePanels = genePanelRepository.fetchGenePanels(genePanelIds, projection); - - if (projection.equals("DETAILED")) { - - List genePanelToGeneList = genePanelRepository.getGenesOfPanels(genePanels - .stream().map(GenePanel::getStableId).collect(toList())); - - genePanels.forEach(g -> g.setGenes(genePanelToGeneList.stream().filter(p -> p.getGenePanelId() - .equals(g.getStableId())).collect(toList()))); - } - - return genePanels; - } - - @Override - public List getGenePanelData(String molecularProfileId, String sampleListId) - throws MolecularProfileNotFoundException { - - MolecularProfile molecularProfile = molecularProfileService.getMolecularProfile(molecularProfileId); - - List genePanelData = genePanelRepository - .getGenePanelDataBySampleListId(molecularProfile.getStableId(), sampleListId); - - return annotateDataFromSequencedSampleLists(genePanelData, molecularProfile); - } - - @Override - public List fetchGenePanelData(String molecularProfileId, List sampleIds) - throws MolecularProfileNotFoundException { - - List molecularProfileSampleIdentifiers = sampleIds - .stream() - .map(sampleId -> new MolecularProfileCaseIdentifier(sampleId, molecularProfileId)) - .collect(toList()); - - return fetchGenePanelDataInMultipleMolecularProfiles(molecularProfileSampleIdentifiers); - } - - @Override - public List fetchGenePanelDataByMolecularProfileIds(Set molecularProfileIds) { - - List molecularProfiles = molecularProfileService - .getMolecularProfiles(molecularProfileIds, "SUMMARY"); - - Set uniqueMolecularProfileIds = molecularProfiles - .stream() - .map(MolecularProfile::getStableId) - .collect(toSet()); - - Map> molecularProfileIdToGenePanelDataMap = uniqueMolecularProfileIds - .stream() - //query database with each profile id so data cached in a modular way for each profile - .collect(Collectors.toMap(Function.identity(), profileId -> genePanelRepository - .fetchGenePanelDataByMolecularProfileId(profileId))); - - Map molecularProfileIdMap = molecularProfiles - .stream() - .collect(Collectors.toMap(MolecularProfile::getStableId, Function.identity())); - - return molecularProfileIds - .stream() - .flatMap(profileId -> { - List genePanelData = molecularProfileIdToGenePanelDataMap - .getOrDefault(profileId, new ArrayList<>()); - if (CollectionUtils.isNotEmpty(genePanelData)) { - genePanelData = annotateDataFromSequencedSampleLists(genePanelData, molecularProfileIdMap.get(profileId)); - } - return genePanelData.stream(); - }) - .collect(Collectors.toList()); - } - - @Override - public List fetchGenePanelDataInMultipleMolecularProfiles(List molecularProfileSampleIdentifiers) { - return getGenePanelData(molecularProfileSampleIdentifiers, SAMPLE_IDENTIFIER_GENERATOR); - } - - @Override - public List fetchGenePanelDataInMultipleMolecularProfilesByPatientIds(List molecularProfilePatientIdentifiers) { - return getGenePanelData(molecularProfilePatientIdentifiers, PATIENT_IDENTIFIER_GENERATOR); - } - - private List getGenePanelData(List molecularProfileCaseIdentifiers, - Function keyGenerator) { - Set molecularProfileIds = molecularProfileCaseIdentifiers - .stream() - .map(MolecularProfileCaseIdentifier::getMolecularProfileId) - .collect(toSet()); - - Map queriedMolecularProfileCaseIdentifierMap = - molecularProfileCaseIdentifiers - .stream() - .collect(Collectors - .toMap( - datum -> datum.getMolecularProfileId() + datum.getCaseId(), - datum -> true)); - - return fetchGenePanelDataByMolecularProfileIds(molecularProfileIds) - .stream() - .filter(datum -> queriedMolecularProfileCaseIdentifierMap.containsKey(keyGenerator.apply(datum))) - .collect(toList()); - - } - - /** - * For mutation use sequenced case/sample list to check if the sample are profiled or not - * @param genePanelData list of gene panel data objects - * @param molecularProfile MolecularProfile - * @return List of GenePanelData - */ - private List annotateDataFromSequencedSampleLists(List genePanelData, - MolecularProfile molecularProfile) { - - if (MolecularProfile.MolecularAlterationType.MUTATION_EXTENDED.equals(molecularProfile.getMolecularAlterationType())) { - try { - SampleList sampleList = sampleListService.getSampleList(molecularProfile.getCancerStudyIdentifier() + SEQUENCED_LIST_SUFFIX); - Map sampleSequencedBySampleList = sampleList - .getSampleIds() - .stream() - .collect(toMap(Function.identity(), d -> true)); - return genePanelData - .stream() - .peek(datum -> { - if(!datum.getProfiled()) { - datum.setProfiled(sampleSequencedBySampleList.getOrDefault(datum.getSampleId(), false)); - } - }) - .collect(toList()); - - } catch (SampleListNotFoundException ignored) { - } - } - return genePanelData; - } - -} diff --git a/src/main/java/org/cbioportal/service/impl/GeneServiceImpl.java b/src/main/java/org/cbioportal/service/impl/GeneServiceImpl.java deleted file mode 100644 index a8ae132a090..00000000000 --- a/src/main/java/org/cbioportal/service/impl/GeneServiceImpl.java +++ /dev/null @@ -1,175 +0,0 @@ -package org.cbioportal.service.impl; - -import jakarta.annotation.PostConstruct; -import org.cbioportal.model.Gene; -import org.cbioportal.model.GeneAlias; -import org.cbioportal.model.meta.BaseMeta; -import org.cbioportal.persistence.GeneRepository; -import org.cbioportal.service.GeneService; -import org.cbioportal.service.exception.GeneNotFoundException; -import org.cbioportal.service.exception.GeneWithMultipleEntrezIdsException; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; -import static java.util.stream.Collectors.*; - -@Service -public class GeneServiceImpl implements GeneService { - - public static final String ENTREZ_GENE_ID_GENE_ID_TYPE = "ENTREZ_GENE_ID"; - - @Autowired - private GeneRepository geneRepository; - - private Map> geneAliasMap = new HashMap<>(); - - @PostConstruct - public void init() { - // query all genes so they would be cached - getAllGenes(null, null, "SUMMARY", null, null, null, null); - - geneAliasMap = geneRepository.getAllAliases().stream().collect(Collectors.groupingBy( - GeneAlias::getEntrezGeneId, Collectors.mapping(GeneAlias::getGeneAlias, Collectors.toList()))); - } - - @Override - public List getAllGenes(String keyword, String alias, String projection, Integer pageSize, Integer pageNumber, String sortBy, - String direction) { - - List geneList = geneRepository.getAllGenes(keyword, alias, projection, pageSize, pageNumber, sortBy, direction); - - if (keyword != null && (pageSize == null || geneList.size() < pageSize)) { - List aliasMatchingGenes = findAliasMatchingGenes(keyword); - if (pageSize != null) { - int toIndex = aliasMatchingGenes.size() > pageSize - geneList.size() ? - pageSize - geneList.size() : aliasMatchingGenes.size(); - aliasMatchingGenes = aliasMatchingGenes.subList(0, toIndex); - } - for (Gene gene : aliasMatchingGenes) { - if (!geneList.stream().anyMatch(c -> c.getEntrezGeneId().equals(gene.getEntrezGeneId()))) { - geneList.add(gene); - } - } - } - - return filterGenesWithMultipleEntrezIds(geneList); - } - - @Override - public BaseMeta getMetaGenes(String keyword, String alias) { - - if (keyword == null) { - return geneRepository.getMetaGenes(keyword, alias); - } - else { - BaseMeta baseMeta = new BaseMeta(); - baseMeta.setTotalCount(getAllGenes(keyword, null, "SUMMARY", null, null, null, null).size()); - return baseMeta; - } - } - - @Override - public Gene getGeneByGeneticEntityId(Integer geneticEntityId) throws GeneNotFoundException { - - Gene gene; - gene = geneRepository.getGeneByGeneticEntityId(geneticEntityId); - if (gene == null) throw new GeneNotFoundException(Integer.toString(geneticEntityId)); - return gene; - } - - @Override - public Gene getGene(String geneId) throws GeneNotFoundException, GeneWithMultipleEntrezIdsException { - - Gene gene; - - if (isInteger(geneId)) { - gene = geneRepository.getGeneByEntrezGeneId(Integer.valueOf(geneId)); - } else { - gene = geneRepository.getGeneByHugoGeneSymbol(geneId); - } - if (gene == null) { - throw new GeneNotFoundException(geneId); - } - return gene; - - } - - @Override - public List getAliasesOfGene(String geneId) throws GeneNotFoundException, GeneWithMultipleEntrezIdsException { - - getGene(geneId); - - if (isInteger(geneId)) { - return geneRepository.getAliasesOfGeneByEntrezGeneId(Integer.valueOf(geneId)); - } else { - return geneRepository.getAliasesOfGeneByHugoGeneSymbol(geneId); - } - } - - @Override - public List fetchGenes(List geneIds, String geneIdType, String projection) { - - List geneList; - - if (geneIdType.equals(ENTREZ_GENE_ID_GENE_ID_TYPE)) { - geneList = geneRepository.fetchGenesByEntrezGeneIds(geneIds.stream().filter(this::isInteger) - .map(Integer::valueOf).collect(Collectors.toList()), projection); - } else { - geneList = geneRepository.fetchGenesByHugoGeneSymbols(geneIds, projection); - } - - return filterGenesWithMultipleEntrezIds(geneList); - } - - @Override - public BaseMeta fetchMetaGenes(List geneIds, String geneIdType) { - - BaseMeta baseMeta; - - if (geneIdType.equals(ENTREZ_GENE_ID_GENE_ID_TYPE)) { - baseMeta = geneRepository.fetchMetaGenesByEntrezGeneIds(geneIds.stream().filter(this::isInteger) - .map(Integer::valueOf).collect(Collectors.toList())); - } else { - baseMeta = geneRepository.fetchMetaGenesByHugoGeneSymbols(geneIds); - } - - return baseMeta; - } - - private boolean isInteger(String geneId) { - return geneId.matches("^-?\\d+$"); - } - - private List findAliasMatchingGenes(String keyword) { - - List matchingGenes = new ArrayList<>(); - - List matchingEntrezGeneIds = new ArrayList<>(); - for (Map.Entry> entry : geneAliasMap.entrySet()) { - if (entry.getValue().contains(keyword.toLowerCase())) { - matchingEntrezGeneIds.add(String.valueOf(entry.getKey())); - } - } - if (!matchingEntrezGeneIds.isEmpty()) { - matchingGenes = fetchGenes(matchingEntrezGeneIds, ENTREZ_GENE_ID_GENE_ID_TYPE, "SUMMARY"); - } - return matchingGenes; - } - - private List filterGenesWithMultipleEntrezIds(List geneList) { - return geneList - .stream() - .collect(groupingBy(Gene::getHugoGeneSymbol)) - .values() - .stream() - .filter(groupedGenes -> groupedGenes.size() == 1) // filter out genes having duplicate hugoGeneSymbol - .map(groupedGenes -> groupedGenes.get(0)) - .collect(toList()); - } -} diff --git a/src/main/java/org/cbioportal/service/impl/GenericAssayServiceImpl.java b/src/main/java/org/cbioportal/service/impl/GenericAssayServiceImpl.java deleted file mode 100644 index 9b8ddd1ba9b..00000000000 --- a/src/main/java/org/cbioportal/service/impl/GenericAssayServiceImpl.java +++ /dev/null @@ -1,210 +0,0 @@ -package org.cbioportal.service.impl; - -import java.util.*; -import java.util.function.Function; -import java.util.stream.Collectors; - -import org.cbioportal.model.GenericAssayAdditionalProperty; -import org.cbioportal.model.GenericAssayData; -import org.cbioportal.model.GenericAssayMolecularAlteration; -import org.cbioportal.model.MolecularProfile; -import org.cbioportal.model.MolecularProfile.MolecularAlterationType; -import org.cbioportal.model.MolecularProfileSamples; -import org.cbioportal.model.Sample; -import org.cbioportal.model.meta.GenericAssayMeta; -import org.cbioportal.persistence.GenericAssayRepository; -import org.cbioportal.persistence.MolecularDataRepository; -import org.cbioportal.persistence.SampleListRepository; -import org.cbioportal.service.GenericAssayService; -import org.cbioportal.service.MolecularProfileService; -import org.cbioportal.service.SampleService; -import org.cbioportal.service.exception.MolecularProfileNotFoundException; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - - -@Service -public class GenericAssayServiceImpl implements GenericAssayService { - - @Autowired - private GenericAssayRepository genericAssayRepository; - - @Autowired - private MolecularDataRepository molecularDataRepository; - - @Autowired - private SampleService sampleService; - - @Autowired - private MolecularProfileService molecularProfileService; - - @Autowired - private SampleListRepository sampleListRepository; - - @Override - public List getGenericAssayMetaByStableIdsAndMolecularIds(List stableIds, List molecularProfileIds, String projection) { - Set allStableIds = new HashSet(); - // extract genericAssayStableIds from the GENERIC_ASSAY profiles - if (molecularProfileIds != null) { - List distinctMolecularProfileIds = molecularProfileIds.stream().distinct().sorted().collect(Collectors.toList()); - if (distinctMolecularProfileIds.size() > 0) { - // fetch one profile at a time to improve cache performace for multiple profiles query - for (String distinctMolecularProfileId : distinctMolecularProfileIds) { - allStableIds.addAll(genericAssayRepository.getGenericAssayStableIdsByMolecularIds(Arrays.asList(distinctMolecularProfileId))); - } - } - // if stableIds and molecularProfileIds both exist, find the common - if (stableIds != null) { - Map allStableIdMap = allStableIds - .stream() - .collect(Collectors.toMap(stableId -> stableId, stableId -> stableId)); - - allStableIds = stableIds - .stream() - .filter(stableId -> allStableIdMap.containsKey(stableId)) - .collect(Collectors.toSet()); - } - } else { - // add all stableIds since molecularProfileIds is null - if (stableIds != null) { - allStableIds.addAll(stableIds); - } - } - List distinctStableIds = new ArrayList(allStableIds); - List metaResults = new ArrayList(); - //TODO: move below logic to sql query - if (distinctStableIds.size() > 0) { - List metaData = genericAssayRepository.getGenericAssayMeta(distinctStableIds); - // just return stable_id if projection is ID - if (projection.equals("ID")) { - for (GenericAssayMeta meta : metaData) { - metaResults.add(new GenericAssayMeta(meta.getStableId())); - } - } else { - Map> additionalPropertiesGroupedByStableId = - genericAssayRepository.getGenericAssayAdditionalproperties(distinctStableIds).stream() - .collect(Collectors.groupingBy(GenericAssayAdditionalProperty::getStableId)); - for (GenericAssayMeta meta : metaData) { - String stableId = meta.getStableId(); - HashMap map = new HashMap<>(); - if (additionalPropertiesGroupedByStableId.containsKey(stableId)) { - for (GenericAssayAdditionalProperty additionalProperty : additionalPropertiesGroupedByStableId.get(stableId)) { - map.put(additionalProperty.getName(), additionalProperty.getValue()); - } - } - meta.setGenericEntityMetaProperties(map); - metaResults.add(meta); - } - } - } - return metaResults; - } - - @Override - public List fetchGenericAssayData(List molecularProfileIds, - List sampleIds, List genericAssayStableIds, String projection) throws MolecularProfileNotFoundException { - List result = new ArrayList<>(); - - SortedSet distinctMolecularProfileIds = new TreeSet<>(molecularProfileIds); - - Map commaSeparatedSampleIdsOfMolecularProfilesMap = molecularDataRepository - .commaSeparatedSampleIdsOfMolecularProfilesMap(distinctMolecularProfileIds); - - Map> internalSampleIdsMap = new HashMap<>(); - List allInternalSampleIds = new ArrayList<>(); - - for (String molecularProfileId : distinctMolecularProfileIds) { - List internalSampleIds = Arrays - .stream(commaSeparatedSampleIdsOfMolecularProfilesMap.get(molecularProfileId).getSplitSampleIds()) - .mapToInt(Integer::parseInt).boxed().collect(Collectors.toList()); - HashMap molecularProfileSampleMap = new HashMap(); - for (int lc = 0; lc < internalSampleIds.size(); lc++) { - molecularProfileSampleMap.put(internalSampleIds.get(lc), lc); - } - internalSampleIdsMap.put(molecularProfileId, molecularProfileSampleMap); - allInternalSampleIds.addAll(internalSampleIds); - } - - List molecularProfiles = new ArrayList<>(); - List distinctMolecularProfiles = molecularProfileService.getMolecularProfiles( - distinctMolecularProfileIds, "SUMMARY"); - Map molecularProfileMapById = distinctMolecularProfiles.stream().collect( - Collectors.toMap(MolecularProfile::getStableId, Function.identity())); - Map> molecularProfileMapByStudyId = distinctMolecularProfiles.stream().collect( - Collectors.groupingBy(MolecularProfile::getCancerStudyIdentifier)); - List samples; - if (sampleIds == null) { - samples = sampleService.getSamplesByInternalIds(allInternalSampleIds); - for (String molecularProfileId : distinctMolecularProfileIds) { - internalSampleIdsMap.get(molecularProfileId).keySet().forEach(s -> molecularProfiles.add(molecularProfileMapById - .get(molecularProfileId))); - } - } else { - for (String molecularProfileId : molecularProfileIds) { - molecularProfiles.add(molecularProfileMapById.get(molecularProfileId)); - } - List studyIds = molecularProfiles.stream().map(MolecularProfile::getCancerStudyIdentifier) - .collect(Collectors.toList()); - samples = sampleService.fetchSamples(studyIds, sampleIds, "ID"); - } - - List molecularAlterations = new ArrayList<>(); - for (String distinctMolecularProfileId : distinctMolecularProfileIds) { - molecularAlterations.addAll(molecularDataRepository.getGenericAssayMolecularAlterations( - distinctMolecularProfileId, genericAssayStableIds, projection)); - } - Map> molecularAlterationsMap = molecularAlterations.stream().collect( - Collectors.groupingBy(GenericAssayMolecularAlteration::getMolecularProfileId)); - - for (Sample sample : samples) { - for (MolecularProfile molecularProfile : molecularProfileMapByStudyId.get(sample.getCancerStudyIdentifier())) { - String molecularProfileId = molecularProfile.getStableId(); - Integer indexOfSampleId = internalSampleIdsMap.get(molecularProfileId).get(sample.getInternalId()); - if (indexOfSampleId != null && molecularAlterationsMap.containsKey(molecularProfileId)) { - for (GenericAssayMolecularAlteration molecularAlteration : molecularAlterationsMap.get(molecularProfileId)) { - GenericAssayData molecularData = new GenericAssayData(); - molecularData.setMolecularProfileId(molecularProfileId); - molecularData.setSampleId(sample.getStableId()); - molecularData.setPatientId(sample.getPatientStableId()); - molecularData.setStudyId(sample.getCancerStudyIdentifier()); - molecularData.setGenericAssayStableId(molecularAlteration.getGenericAssayStableId()); - molecularData.setValue(molecularAlteration.getSplitValues()[indexOfSampleId]); - result.add(molecularData); - } - } - } - } - return result; - } - - @Override - public List getGenericAssayData(String molecularProfileId, String sampleListId, - List genericAssayStableIds, String projection) - throws MolecularProfileNotFoundException { - - validateMolecularProfile(molecularProfileId); - List sampleIds = sampleListRepository.getAllSampleIdsInSampleList(sampleListId); - if (sampleIds.isEmpty()) { - return Collections.emptyList(); - } - return fetchGenericAssayData(Arrays.asList(molecularProfileId), sampleIds, genericAssayStableIds, projection); - } - - @Override - public List fetchGenericAssayData(String molecularProfileId, List sampleIds, - List genericAssayStableIds, String projection) throws MolecularProfileNotFoundException { - - validateMolecularProfile(molecularProfileId); - return fetchGenericAssayData(Arrays.asList(molecularProfileId), sampleIds, genericAssayStableIds, projection); - } - - private void validateMolecularProfile(String molecularProfileId) throws MolecularProfileNotFoundException { - - MolecularProfile molecularProfile = molecularProfileService.getMolecularProfile(molecularProfileId); - - if (!molecularProfile.getMolecularAlterationType().equals(MolecularAlterationType.GENERIC_ASSAY)) { - - throw new MolecularProfileNotFoundException(molecularProfileId); - } - } -} \ No newline at end of file diff --git a/src/main/java/org/cbioportal/service/impl/GenesetCorrelationServiceImpl.java b/src/main/java/org/cbioportal/service/impl/GenesetCorrelationServiceImpl.java deleted file mode 100644 index ccf39027515..00000000000 --- a/src/main/java/org/cbioportal/service/impl/GenesetCorrelationServiceImpl.java +++ /dev/null @@ -1,259 +0,0 @@ -/* - * Copyright (c) 2016 The Hyve B.V. - * This code is licensed under the GNU Affero General Public License (AGPL), - * version 3, or (at your option) any later version. - */ - -/* - * This file is part of cBioPortal. - * - * cBioPortal is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . -*/ - -package org.cbioportal.service.impl; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - -import org.apache.commons.lang3.math.NumberUtils; -import org.apache.commons.math3.stat.correlation.SpearmansCorrelation; -import org.cbioportal.model.CancerStudy; -import org.cbioportal.model.Gene; -import org.cbioportal.model.GenesetCorrelation; -import org.cbioportal.model.GenesetMolecularData; -import org.cbioportal.model.GeneMolecularData; -import org.cbioportal.model.MolecularProfile; -import org.cbioportal.model.Sample; -import org.cbioportal.service.SampleListService; -import org.cbioportal.service.GenesetService; -import org.cbioportal.service.GenesetCorrelationService; -import org.cbioportal.service.GenesetDataService; -import org.cbioportal.service.MolecularDataService; -import org.cbioportal.service.MolecularProfileService; -import org.cbioportal.service.SampleService; -import org.cbioportal.service.exception.GenesetNotFoundException; -import org.cbioportal.service.exception.MolecularProfileNotFoundException; -import org.cbioportal.service.exception.SampleListNotFoundException; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -@Service -public class GenesetCorrelationServiceImpl implements GenesetCorrelationService { - - @Autowired - private MolecularDataService molecularDataService; - @Autowired - private GenesetDataService genesetDataService; - @Autowired - private MolecularProfileService molecularProfileService; - @Autowired - private GenesetService genesetService; - @Autowired - private SampleService sampleService; - @Autowired - private SampleListService sampleListService; - - - public List fetchCorrelatedGenes(String genesetId, String molecularProfileId, - double correlationThreshold) throws MolecularProfileNotFoundException, GenesetNotFoundException { - - // get sample ids from study - CancerStudy cancerStudy = molecularProfileService.getMolecularProfile(molecularProfileId).getCancerStudy(); - List samples = sampleService.fetchSamples(Arrays.asList(cancerStudy.getCancerStudyIdentifier()), null, "SUMMARY"); - // convert to string list: - List sampleIds = samples.stream().map(o -> o.getStableId()).collect( Collectors.toList() ); - return fetchCorrelatedGenes(genesetId, molecularProfileId, sampleIds, correlationThreshold); - } - - public List fetchCorrelatedGenes(String genesetId, String molecularProfileId, - String sampleListId, double correlationThreshold) - throws MolecularProfileNotFoundException, SampleListNotFoundException, GenesetNotFoundException { - - // get sample ids from sampleList - List sampleIds = sampleListService.getAllSampleIdsInSampleList(sampleListId); - return fetchCorrelatedGenes(genesetId, molecularProfileId, sampleIds, correlationThreshold); - } - - public List fetchCorrelatedGenes(String genesetId, String molecularProfileId, - List sampleIds, double correlationThreshold) - throws MolecularProfileNotFoundException, GenesetNotFoundException { - - List result = new ArrayList(); - - // find the genes in the geneset - List genes = genesetService.getGenesByGenesetId(genesetId); - - // the geneset data: - List genesetData = genesetDataService.fetchGenesetData(molecularProfileId, sampleIds, - Arrays.asList(genesetId)); - double[] genesetValues = getGenesetValues(sampleIds, genesetData); - // find the expression profile related to the given geneticProfileId - List expressionProfilesReferredByGenesetProfile = - molecularProfileService.getMolecularProfilesReferredBy(molecularProfileId); - //we expect only 1 in this case (a geneset only refers to 1 expression profile, so give error otherwise): - if (expressionProfilesReferredByGenesetProfile.size() != 1) { - throw new RuntimeException("Unexpected error: given geneset profile refers to " + - expressionProfilesReferredByGenesetProfile.size() + " profile(s). Should refer to only 1"); - } - MolecularProfile expressionProfile = expressionProfilesReferredByGenesetProfile.get(0); - MolecularProfile zscoresProfile = getLinkedZscoreProfile(expressionProfile); - - // TODO : if this turns out to take too long, we can always implement this loop in parallel to improve - // performance. Multi-threading is easy in this scenario. - // get genetic data for each gene and calculate correlation - for (Gene gene : genes) { - Integer entrezGeneId = gene.getEntrezGeneId(); - List geneData = molecularDataService.fetchMolecularData(expressionProfile.getStableId(), - sampleIds, Arrays.asList(entrezGeneId), "SUMMARY"); - double correlationValue = calculateCorrelation(sampleIds, geneData, genesetValues); - // filter out the ones below correlationThreshold - if (correlationValue < correlationThreshold) { - continue; - } - GenesetCorrelation genesetCorrelationItem = new GenesetCorrelation(); - genesetCorrelationItem.setEntrezGeneId(entrezGeneId); - genesetCorrelationItem.setHugoGeneSymbol(gene.getHugoGeneSymbol()); - genesetCorrelationItem.setCorrelationValue(correlationValue); - genesetCorrelationItem.setExpressionMolecularProfileId(expressionProfile.getStableId()); - genesetCorrelationItem.setzScoreMolecularProfileId(zscoresProfile.getStableId()); - result.add(genesetCorrelationItem); - } - // return sorted - sortResult(result); - return result; - } - - - private MolecularProfile getLinkedZscoreProfile(MolecularProfile expressionProfile) throws MolecularProfileNotFoundException { - - //Find the related z-score profile via the genetic_profile_link table: - List referringProfiles = molecularProfileService.getMolecularProfilesReferringTo(expressionProfile.getStableId()); - MolecularProfile zscoresProfile = null; - for (MolecularProfile referringProfile : referringProfiles) { - //use the first z-score profile we can find in this list of referring profiles (normally there should be only 1 anyway): - if (referringProfile.getDatatype().equals("Z-SCORE")) { - zscoresProfile = referringProfile; - break; - } - } - //if none found, give clear error message...something is wrong with this study: - if (zscoresProfile == null) { - throw new IllegalArgumentException("The expression profile [" + expressionProfile.getStableId() + "] linked to the given " - + "gene set scores profile does not have a corresponding z-scores profile in this study."); - } - return zscoresProfile; - } - - private void sortResult(List result) { - - result.sort((GenesetCorrelation o1, GenesetCorrelation o2)-> { - //descending order, also check for NaN - if (o1.getCorrelationValue().isNaN()) - return 1; - if (o2.getCorrelationValue().isNaN()) - return -1; - - if (o1.getCorrelationValue() < o2.getCorrelationValue()) - return 1; - if (o1.getCorrelationValue() > o2.getCorrelationValue()) - return -1; - - return 0; - }); - } - - - /** - * Calculates the Spearman correlation between the genesetValues list and the list built up from - * geneGeneticDataItems for the given sampleIds. - * - * Before calculating the correlation, this method prepares the gene values, filtering both them and genesetValues, - * removing samples where the value is not present in either gene or gene set dimension. - * - * @param sampleIds: samples over which to calculate correlation - * @param geneGeneticDataItems: gene (expression) values for the set of samples - * @param genesetValues: gene set scores for the set of samples - * - * @return: Spearman's correlation value between values in geneGeneticDataItems and genesetValues. - */ - private double calculateCorrelation(List sampleIds, List geneGeneticDataItems, double[] genesetValues) { - - //index geneData values - Map sampleValues = new HashMap(); - for (GeneMolecularData geneGeneticDataItem : geneGeneticDataItems) { - double value = Double.NaN; - if (NumberUtils.isNumber(geneGeneticDataItem.getValue())) { - value = Double.parseDouble(geneGeneticDataItem.getValue()); - } - sampleValues.put(geneGeneticDataItem.getSampleId(), value); - } - //get values - List geneValueList = new ArrayList(); - List genesetValueList = new ArrayList(); - for (int i = 0; i < sampleIds.size(); i++) { - String sampleId = sampleIds.get(i); - Double value = sampleValues.get(sampleId); - if (value == null) { - value = Double.NaN; //set to NaN when value is not available for this sample - } - // if both this value and genesetValues[i] are NaN, then skip this item (since it will not be allowed by the correlation method): - if (!Double.isNaN(value) && !Double.isNaN(genesetValues[i])) { - geneValueList.add(value); - // build up genesetValues is same way: - genesetValueList.add(genesetValues[i]); - } - } - // final filtered lists: - double[] geneValuesFiltered = geneValueList.stream().mapToDouble(d -> d).toArray(); - double[] genesetValuesFiltered = genesetValueList.stream().mapToDouble(d -> d).toArray(); - double correlationValue = 0; - // arrays need to be at least 2 long to calculate correlation: - if (geneValuesFiltered.length >= 2) { - // calculate spearman correlation - SpearmansCorrelation spearmansCorrelation = new SpearmansCorrelation(); - correlationValue = spearmansCorrelation.correlation(geneValuesFiltered, genesetValuesFiltered); - } - return correlationValue; - } - - - private double[] getGenesetValues(List sampleIds, List genesetDataItems) { - - //index genesetData values - Map sampleValues = new HashMap(); - for (GenesetMolecularData genesetDataItem : genesetDataItems) { - double value = Double.NaN; - if (NumberUtils.isNumber(genesetDataItem.getValue())) { - value = Double.parseDouble(genesetDataItem.getValue()); - } - sampleValues.put(genesetDataItem.getSampleId(), value); - } - //get values - double[] result = new double[sampleIds.size()]; - for (int i = 0; i < sampleIds.size(); i++) { - String sampleId = sampleIds.get(i); - Double value = sampleValues.get(sampleId); - if (value != null) { - result[i] = value; - } else { - result[i] = Double.NaN; //set to NaN when value is not available for this sample - } - } - return result; - } -} diff --git a/src/main/java/org/cbioportal/service/impl/GenesetDataServiceImpl.java b/src/main/java/org/cbioportal/service/impl/GenesetDataServiceImpl.java deleted file mode 100644 index 0b0a762fd61..00000000000 --- a/src/main/java/org/cbioportal/service/impl/GenesetDataServiceImpl.java +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Copyright (c) 2016 The Hyve B.V. - * This code is licensed under the GNU Affero General Public License (AGPL), - * version 3, or (at your option) any later version. - */ - -/* - * This file is part of cBioPortal. - * - * cBioPortal is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . -*/ - -package org.cbioportal.service.impl; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.stream.Collectors; - -import org.cbioportal.model.GenesetMolecularAlteration; -import org.cbioportal.model.GenesetMolecularData; -import org.cbioportal.model.MolecularProfile; -import org.cbioportal.model.MolecularProfileSamples; -import org.cbioportal.model.Sample; -import org.cbioportal.persistence.MolecularDataRepository; -import org.cbioportal.service.SampleListService; -import org.cbioportal.service.GenesetDataService; -import org.cbioportal.service.MolecularProfileService; -import org.cbioportal.service.SampleService; -import org.cbioportal.service.exception.MolecularProfileNotFoundException; -import org.cbioportal.service.exception.SampleListNotFoundException; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -@Service -public class GenesetDataServiceImpl implements GenesetDataService { - - @Autowired - private MolecularDataRepository molecularDataRepository; - @Autowired - private SampleService sampleService; - @Autowired - private MolecularProfileService molecularProfileService; - @Autowired - private SampleListService sampleListService; - - public List fetchGenesetData(String molecularProfileId, List sampleIds, List genesetIds) - throws MolecularProfileNotFoundException { - - //validate (throws exception if profile is not found): - MolecularProfile molecularProfile = molecularProfileService.getMolecularProfile(molecularProfileId); - - List genesetDataList = new ArrayList<>(); - - MolecularProfileSamples commaSeparatedSampleIdsOfGeneticProfile = molecularDataRepository - .getCommaSeparatedSampleIdsOfMolecularProfile(molecularProfileId); - if (commaSeparatedSampleIdsOfGeneticProfile == null) { - //no data, return empty list: - return genesetDataList; - } - List internalSampleIds = Arrays.stream(commaSeparatedSampleIdsOfGeneticProfile.getSplitSampleIds()) - .mapToInt(Integer::parseInt).boxed().collect(Collectors.toList()); - - List samples; - if (sampleIds == null) { - samples = sampleService.getSamplesByInternalIds(internalSampleIds); - } else { - List studyIds = new ArrayList<>(); - sampleIds.forEach(s -> studyIds.add(molecularProfile.getCancerStudyIdentifier())); - samples = sampleService.fetchSamples(studyIds, sampleIds, "ID"); - } - - List genesetAlterations = molecularDataRepository.getGenesetMolecularAlterations(molecularProfileId, - genesetIds, "SUMMARY"); - - for (Sample sample : samples) { - int indexOfSampleId = internalSampleIds.indexOf(sample.getInternalId()); - if (indexOfSampleId != -1) { - for (GenesetMolecularAlteration genesetAlteration : genesetAlterations) { - GenesetMolecularData genesetData = new GenesetMolecularData(); - genesetData.setMolecularProfileId(molecularProfileId); - genesetData.setSampleId(sample.getStableId()); - genesetData.setPatientId(sample.getPatientStableId()); - genesetData.setStudyId(sample.getCancerStudyIdentifier()); - genesetData.setGenesetId(genesetAlteration.getGenesetId()); - genesetData.setValue(genesetAlteration.getSplitValues()[indexOfSampleId]); - genesetDataList.add(genesetData); - } - } - } - - return genesetDataList; - } - - public List fetchGenesetData(String geneticProfileId, String sampleListId, List genesetIds) - throws MolecularProfileNotFoundException, SampleListNotFoundException { - - //get list of samples for given sampleListId: - List sampleIds = sampleListService.getAllSampleIdsInSampleList(sampleListId); - return fetchGenesetData(geneticProfileId, sampleIds, genesetIds); - } - - @Override - public List getGenesetAlterations(String molecularProfileId, List genesetIds) - throws MolecularProfileNotFoundException { - - return molecularDataRepository.getGenesetMolecularAlterations(molecularProfileId, genesetIds, "SUMMARY"); - } -} diff --git a/src/main/java/org/cbioportal/service/impl/GenesetHierarchyServiceImpl.java b/src/main/java/org/cbioportal/service/impl/GenesetHierarchyServiceImpl.java deleted file mode 100644 index 0c831bf19e3..00000000000 --- a/src/main/java/org/cbioportal/service/impl/GenesetHierarchyServiceImpl.java +++ /dev/null @@ -1,342 +0,0 @@ -/* - * Copyright (c) 2016 The Hyve B.V. - * This code is licensed under the GNU Affero General Public License (AGPL), - * version 3, or (at your option) any later version. - */ - -/* - * This file is part of cBioPortal. - * - * cBioPortal is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . -*/ -package org.cbioportal.service.impl; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.stream.Collectors; - -import org.apache.commons.lang3.math.NumberUtils; -import org.apache.commons.lang3.tuple.ImmutablePair; -import org.cbioportal.model.CancerStudy; -import org.cbioportal.model.Geneset; -import org.cbioportal.model.GenesetMolecularData; -import org.cbioportal.model.GenesetHierarchyInfo; -import org.cbioportal.model.MolecularProfile; -import org.cbioportal.model.Sample; -import org.cbioportal.persistence.GenesetHierarchyRepository; -import org.cbioportal.service.SampleListService; -import org.cbioportal.service.GenesetDataService; -import org.cbioportal.service.GenesetHierarchyService; -import org.cbioportal.service.MolecularProfileService; -import org.cbioportal.service.SampleService; -import org.cbioportal.service.exception.MolecularProfileNotFoundException; -import org.cbioportal.service.exception.SampleListNotFoundException; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -@Service -public class GenesetHierarchyServiceImpl implements GenesetHierarchyService { - - @Autowired - private GenesetDataService genesetDataService; - @Autowired - private MolecularProfileService geneticProfileService; - @Autowired - private GenesetHierarchyRepository genesetHierarchyRepository; - @Autowired - private SampleService sampleService; - @Autowired - private SampleListService sampleListService; - - public List fetchGenesetHierarchyInfo(String geneticProfileId, Integer percentile, - Double scoreThreshold, Double pvalueThreshold) throws MolecularProfileNotFoundException { - - // get sample ids from study - CancerStudy cancerStudy = geneticProfileService.getMolecularProfile(geneticProfileId).getCancerStudy(); - List samples = sampleService.fetchSamples(Arrays.asList(cancerStudy.getCancerStudyIdentifier()), null, "SUMMARY"); - // convert to string list: - List sampleIds = samples.stream().map(o -> o.getStableId()).collect( Collectors.toList() ); - return fetchGenesetHierarchyInfo(geneticProfileId, percentile, scoreThreshold, pvalueThreshold, sampleIds); - } - - public List fetchGenesetHierarchyInfo(String geneticProfileId, Integer percentile, - Double scoreThreshold, Double pvalueThreshold, String sampleListId) throws MolecularProfileNotFoundException, SampleListNotFoundException { - - // get sample ids from sampleList - List sampleIds = sampleListService.getAllSampleIdsInSampleList(sampleListId); - return fetchGenesetHierarchyInfo(geneticProfileId, percentile, scoreThreshold, pvalueThreshold, sampleIds); - } - - public List fetchGenesetHierarchyInfo(String geneticProfileId, Integer percentile, - Double scoreThreshold, Double pvalueThreshold, List sampleIds) throws MolecularProfileNotFoundException { - - //validate: - MolecularProfile geneticProfile = geneticProfileService.getMolecularProfile(geneticProfileId); - //also validate if profile is of geneset_score type: - if (!geneticProfile.getDatatype().equals("GSVA-SCORE")) { - throw new IllegalArgumentException("Genetic profile should be of DATA_TYPE = GSVA-SCORE, but found: " + - geneticProfile.getDatatype()); - } - - //get list of genesets and respective score records for gene sets that have data for this profile: - List genesetScores = genesetDataService.fetchGenesetData(geneticProfileId, sampleIds, null); - List genesetPvalues = getGenesetPvalues(geneticProfileId, sampleIds); - - return getGenesetHierarchyItems(genesetScores, genesetPvalues, percentile, scoreThreshold, pvalueThreshold); - } - - /** - * Finds and retrieves the gene set p-values of the profile linked to the given scoresGeneticProfileId. - * - * @param scoresGeneticProfileId: genetic profile containing gene set scores - * @param sampleIds: samples to use for the representative score calculation - * @return - * @throws MolecularProfileNotFoundException - */ - private List getGenesetPvalues(String scoresGeneticProfileId, List sampleIds) throws MolecularProfileNotFoundException { - - List pvaluesGeneticProfiles = geneticProfileService.getMolecularProfilesReferringTo(scoresGeneticProfileId); - //validate : - if (pvaluesGeneticProfiles == null || pvaluesGeneticProfiles.size() != 1) { - //unexpected, but could happen if dataset validation is skipped - throw new RuntimeException("The given gene set profile [" + scoresGeneticProfileId + "] should have (at least) 1 and only 1 linked p-values profile in DB"); - } - //validate if profile is of pvalue type: - if (!pvaluesGeneticProfiles.get(0).getDatatype().equals("P-VALUE")) { - throw new IllegalArgumentException("Genetic profile should be of DATA_TYPE = P-VALUE"); - } - - List genesetPvalues = genesetDataService.fetchGenesetData(pvaluesGeneticProfiles.get(0).getStableId(), sampleIds, null); - return genesetPvalues; - } - - /** - * Return the hierarchy nodes and leafs (gene sets) based on data found in genesetScores. - * - * @param genesetScores: gene set score data found for the given geneticProfileId and sampleIds - * @param percentile: percentile to use for the representative score calculation - * @param scoreThreshold: filter criterion - * @param pvalueThreshold: filter criterion - * - * @return - * @throws MolecularProfileNotFoundException - */ - private List getGenesetHierarchyItems(List genesetScores, - List genesetPvalues, - Integer percentile, Double scoreThreshold, Double pvalueThreshold) throws MolecularProfileNotFoundException { - - List genesetIds = new ArrayList(genesetScores.stream().map(o -> o.getGenesetId()).collect( Collectors.toSet() )); - - //add all hierarchy nodes that have no leafs, but are intermediate/super nodes: - List hierarchySuperNodes = genesetHierarchyRepository.getGenesetHierarchySuperNodes(genesetIds); - - //index genesetData : - Map> genesetScoresMap = - genesetScores.stream().collect(Collectors.groupingBy(GenesetMolecularData::getGenesetId)); - Map> genesetPvaluesMap = - genesetPvalues.stream().collect(Collectors.groupingBy(GenesetMolecularData::getGenesetId)); - - - //get the nodes that have gene sets as child/leafs: - List hierarchyGenesetParents = genesetHierarchyRepository.getGenesetHierarchyParents(genesetIds);//maybe rename to pre-leafItems? - if (genesetIds != null) { - //complement the result with the gene sets info: - for (GenesetHierarchyInfo hierarchyItem : hierarchyGenesetParents) { - List genesets = genesetHierarchyRepository.getGenesetHierarchyGenesets(hierarchyItem.getNodeId()); - //get only the ones that have data, filtering out the other ones (probably not needed, but just to be sure): - genesets = getFilteredGenesets(genesets, genesetScoresMap); - //for each gene set, calculate representative score: - fillRepresentativeScoresAndPvalues(genesets, genesetScoresMap, genesetPvaluesMap, percentile); - //filter out the ones that don't satisfy thresholds: - genesets = getFilteredGenesets(genesets, scoreThreshold, pvalueThreshold); - hierarchyItem.setGenesets(genesets); - //if genesets turns out to be empty, still consider it as a possible super node (will be filtered below if it is not): - if (genesets.size() == 0) { - hierarchySuperNodes.add(hierarchyItem); - } - } - } - //remove the hierarchyGenesetParents that have no gene set leaf nodes: - hierarchyGenesetParents = getFilteredHierarchyGenesetParents(hierarchyGenesetParents); - //remove nodes from hierarchySuperNodes that do not lead to a leaf node: - hierarchySuperNodes = getFilteredHierarchySuperNodes(hierarchySuperNodes, hierarchyGenesetParents); - //TODO could probably simplify some of this code above by merging hierarchySuperNodes and hierarchyGenesetParents at the start - //and filtering the tree in one recursive function... - - //join both lists: - hierarchySuperNodes.addAll(hierarchyGenesetParents); - - return hierarchySuperNodes; - } - - - private List getFilteredGenesets(List genesets, Double scoreThreshold, Double pvalueThreshold) { - - return genesets.stream().filter( - g -> Math.abs(g.getRepresentativeScore()) >= scoreThreshold && - g.getRepresentativePvalue() <= pvalueThreshold - ).collect(Collectors.toList()); - } - - private List getFilteredHierarchySuperNodes(List hierarchySuperNodes, - List referringNodes) { - - //index referred node ids: - Set referredNodesSet = - referringNodes.stream().map(GenesetHierarchyInfo::getParentId).collect(Collectors.toSet()); - - //also make index for super nodes as they could refer to each other - List referredNodes = new ArrayList(); - for (GenesetHierarchyInfo hierarchySuperNode: hierarchySuperNodes) { - if (referredNodesSet.contains(hierarchySuperNode.getNodeId())) { - //there are child nodes, so add this one: - if (!referredNodes.contains(hierarchySuperNode)) { - referredNodes.add(hierarchySuperNode); - } - } - } - if (referredNodes.size() > 0) { - //recursion: also add the parents of the referredNodes - List parents = getFilteredHierarchySuperNodes(hierarchySuperNodes, referredNodes); - for (GenesetHierarchyInfo parent: parents) { - if(!referredNodes.contains(parent)) - referredNodes.add(parent); - } - } - return referredNodes; - } - - private List getFilteredHierarchyGenesetParents( - List hierarchyGenesetParents) { - - List result = new ArrayList(); - for (GenesetHierarchyInfo hierarchyGenesetParent: hierarchyGenesetParents) { - if (hierarchyGenesetParent.getGenesets().size() > 0) { - //there are leaf nodes, so add this one: - result.add(hierarchyGenesetParent); - } - } - return result; - } - - private List getFilteredGenesets(List genesets, Map> genesetDataMap) { - - List result = new ArrayList(); - for (Geneset geneset: genesets) { - if (genesetDataMap.get(geneset.getGenesetId()) != null) { - //there is data, so add this one: - result.add(geneset); - } - } - return result; - } - - /** - * This will set the representativeScore attribute for each gene set, based on the data (the gene set - * scores per sample). - * @param sampleIds - * - * @param genesets: list of gene sets for which to calculate and record the representativeScore - * @param genesetDataMap: the set of GSVA(like) scores per sample for each gene set - * @param percentile: (optional) which percentile to use when determining the representativeScore. If not - * set, max of absolute score is returned. - * @throws MolecularProfileNotFoundException - */ - private void fillRepresentativeScoresAndPvalues(List genesets, - Map> genesetScoresMap, Map> genesetPvaluesMap, - Integer percentile) throws MolecularProfileNotFoundException { - - genesets.stream().forEach(g -> calculateAndSetRepresentativeScoreAndPvalue(g, genesetScoresMap, genesetPvaluesMap, percentile)); - } - - private void calculateAndSetRepresentativeScoreAndPvalue(Geneset geneset, - Map> genesetScoresMap, - Map> genesetPvaluesMap, - Integer percentile) { - - List genesetScoreData = genesetScoresMap.get(geneset.getGenesetId()); - List genesetPvalueData = genesetPvaluesMap.get(geneset.getGenesetId()); - - //lists to hold the score and p-value pairs: - List> positiveScoresAndPvalues = new ArrayList>(); - List> negativeScoresAndPvalues = new ArrayList>(); - - //return the maximum absolute value found: - double max = 0; - double pvalueOfMax = 1; - for (int i = 0; i < genesetScoreData.size(); i++) { - String scoreString = genesetScoreData.get(i).getValue(); - String pvalueString = genesetPvalueData.get(i).getValue(); - - if (!NumberUtils.isNumber(scoreString)) - continue; - - double score = Double.parseDouble(scoreString); - double pvalue = 1.0; - if (NumberUtils.isNumber(pvalueString)) - pvalue = Double.parseDouble(pvalueString); - if (score >= 0) { - positiveScoresAndPvalues.add(new ImmutablePair(score, pvalue)); - } else { - negativeScoresAndPvalues.add(new ImmutablePair(score, pvalue)); - } - - //keep track of max, in case percentile is null - if (Math.abs(score) > Math.abs(max)) { - max = score; //here no abs, since we want to get the raw score (could be negative) - pvalueOfMax = pvalue; - } - } - - if (percentile == null) { - geneset.setRepresentativeScore(max); - geneset.setRepresentativePvalue(pvalueOfMax); - } else { - //sort scores (NB: .getLeft() returns the score, .getRight() returns the pvalue of each pair): - positiveScoresAndPvalues.sort((ImmutablePair o1, ImmutablePair o2)-> Double.compare(o1.getLeft(), o2.getLeft())); - //negative scores descending: - negativeScoresAndPvalues.sort((ImmutablePair o1, ImmutablePair o2)-> Double.compare(o2.getLeft(), o1.getLeft())); - - //use percentile: - ImmutablePair representativePositiveScoreAndPvalue = new ImmutablePair(0.0, 1.0); - ImmutablePair representativeNegativeScoreAndPvalue = new ImmutablePair(0.0, 1.0); - if (positiveScoresAndPvalues.size() > 0) { - int idxPositiveScores = (int)Math.round(percentile * positiveScoresAndPvalues.size() / 100.0); - if (idxPositiveScores == 0) { //(can happen when positiveScoresAndPvalues.size() is small) - idxPositiveScores = 1; - } - representativePositiveScoreAndPvalue = positiveScoresAndPvalues.get(idxPositiveScores-1); - } - if (negativeScoresAndPvalues.size() > 0) { - int idxNegativeScores = (int)Math.round(percentile * negativeScoresAndPvalues.size() / 100.0); - if (idxNegativeScores == 0) { //(can happen when positiveScoresAndPvalues.size() is small) - idxNegativeScores = 1; - } - representativeNegativeScoreAndPvalue = negativeScoresAndPvalues.get(idxNegativeScores-1); - } - - //set best one: - if (Math.abs(representativePositiveScoreAndPvalue.getLeft()) > Math.abs(representativeNegativeScoreAndPvalue.getLeft())) { - geneset.setRepresentativeScore(representativePositiveScoreAndPvalue.getLeft()); - geneset.setRepresentativePvalue(representativePositiveScoreAndPvalue.getRight()); - } else { - geneset.setRepresentativeScore(representativeNegativeScoreAndPvalue.getLeft()); - geneset.setRepresentativePvalue(representativeNegativeScoreAndPvalue.getRight()); - } - } - } -} diff --git a/src/main/java/org/cbioportal/service/impl/GenesetServiceImpl.java b/src/main/java/org/cbioportal/service/impl/GenesetServiceImpl.java deleted file mode 100644 index d0184582870..00000000000 --- a/src/main/java/org/cbioportal/service/impl/GenesetServiceImpl.java +++ /dev/null @@ -1,66 +0,0 @@ -package org.cbioportal.service.impl; - -import java.util.List; - -import org.cbioportal.model.Gene; -import org.cbioportal.model.Geneset; -import org.cbioportal.model.meta.BaseMeta; -import org.cbioportal.persistence.GenesetRepository; -import org.cbioportal.service.GenesetService; -import org.cbioportal.service.exception.GenesetNotFoundException; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -@Service -public class GenesetServiceImpl implements GenesetService { - - - @Autowired - private GenesetRepository genesetRepository; - - - @Override - public List getAllGenesets(String projection, Integer pageSize, Integer pageNumber) { - List genesetList = genesetRepository.getAllGenesets(projection, pageSize, pageNumber); - return genesetList; - } - - @Override - public BaseMeta getMetaGenesets() { - return genesetRepository.getMetaGenesets(); - } - - @Override - public Geneset getGeneset(String genesetId) throws GenesetNotFoundException { - Geneset geneset = genesetRepository.getGeneset(genesetId); - - if (geneset == null) { - throw new GenesetNotFoundException(genesetId); - } - return geneset; - } - - @Override - public List getGenesByGenesetId(String genesetId) throws GenesetNotFoundException { - - //validate (throws exception if not found): - this.getGeneset(genesetId); - return genesetRepository.getGenesByGenesetId(genesetId); - } - - @Override - public List fetchGenesets(List genesetIds) { - - return genesetRepository.fetchGenesets(genesetIds); - } - - @Override - public String getGenesetVersion() { - String genesetVersion = genesetRepository.getGenesetVersion(); - if (genesetVersion == null) { - return ""; - } else { - return genesetVersion; - } - } -} diff --git a/src/main/java/org/cbioportal/service/impl/JwtDataAccessTokenServiceImpl.java b/src/main/java/org/cbioportal/service/impl/JwtDataAccessTokenServiceImpl.java deleted file mode 100644 index f3fbbe3b21f..00000000000 --- a/src/main/java/org/cbioportal/service/impl/JwtDataAccessTokenServiceImpl.java +++ /dev/null @@ -1,138 +0,0 @@ -/* - * Copyright (c) 2018 Memorial Sloan-Kettering Cancer Center. - * - * This library is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS - * FOR A PARTICULAR PURPOSE. The software and documentation provided hereunder - * is on an "as is" basis, and Memorial Sloan-Kettering Cancer Center has no - * obligations to provide maintenance, support, updates, enhancements or - * modifications. In no event shall Memorial Sloan-Kettering Cancer Center be - * liable to any party for direct, indirect, special, incidental or - * consequential damages, including lost profits, arising out of the use of this - * software and its documentation, even if Memorial Sloan-Kettering Cancer - * Center has been advised of the possibility of such damage. - */ - -/* - * This file is part of cBioPortal. - * - * cBioPortal is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . -*/ - -package org.cbioportal.service.impl; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.cbioportal.model.DataAccessToken; -import org.cbioportal.service.DataAccessTokenService; -import org.cbioportal.service.exception.InvalidDataAccessTokenException; -import org.cbioportal.service.util.JwtUtils; -import org.cbioportal.utils.config.annotation.ConditionalOnProperty; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.security.authentication.BadCredentialsException; -import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; -import org.springframework.security.core.Authentication; - -import java.util.Date; -import java.util.List; -import org.springframework.stereotype.Component; - -@Component -@ConditionalOnProperty(name = "dat.method", havingValue = "jwt") -public class JwtDataAccessTokenServiceImpl implements DataAccessTokenService { - - @Autowired - private JwtUtils jwtUtils; - - private static final Logger LOG = LoggerFactory.getLogger(JwtDataAccessTokenServiceImpl.class); - - //TODO : we could add a persistence layer to store pairs of ... then a user can revoke all thier tokens before a particular date and we would only need to store the most recent revoke date for that user. But it would have to be persisted, or else a restart of the server would lose the memory of revocation - - @Override - public DataAccessToken createDataAccessToken(String username) { - return jwtUtils.createToken(username); - } - - @Override - public List getAllDataAccessTokens(String username) { - throw new UnsupportedOperationException("this implementation of (pure) JWT Data Access Tokens does not allow retrieval of stored tokens"); - } - - @Override - public DataAccessToken getDataAccessToken(String username) { - throw new UnsupportedOperationException("this implementation of (pure) JWT Data Access Tokens does not allow retrieval of stored tokens"); - } - - @Override - public DataAccessToken getDataAccessTokenInfo(String token) { - throw new UnsupportedOperationException("this implementation of (pure) JWT Data Access Tokens does not allow this operation"); - } - - @Override - public void revokeAllDataAccessTokens(String username) { - throw new UnsupportedOperationException("this implementation of (pure) JWT Data Access Tokens does not allow revocation of tokens"); - } - - @Override - public void revokeDataAccessToken(String token) { - throw new UnsupportedOperationException("this implementation of (pure) JWT Data Access Tokens does not allow revocation of tokens"); - } - - @Override - public Boolean isValid(String token) { - try { - jwtUtils.validate(token); - } catch (InvalidDataAccessTokenException idate) { - LOG.error("isValid(), " + idate); - return Boolean.FALSE; - } - return Boolean.TRUE; - } - - @Override - public String getUsername(String token) { - try { - return jwtUtils.extractSubject(token); - } catch (InvalidDataAccessTokenException idate) { - // TODO is this what we want to do? - return null; - } - } - - @Override - public Date getExpiration(String token) { - try { - return jwtUtils.extractExpirationDate(token); - } catch (InvalidDataAccessTokenException idate) { - return null; - } - } - - @Override - public Authentication createAuthenticationRequest(String token) { - - if (!isValid(token)) { - LOG.error("invalid token = " + token); - throw new BadCredentialsException("Invalid access token"); - } - String userName = getUsername(token); - - // When DaoAuthenticationProvider does authentication on user returned by PortalUserDetailsService - // which has password "unused", this password won't match, and then there is a BadCredentials exception thrown - // this is a good way to catch that the wrong authetication provider is being used. - return new UsernamePasswordAuthenticationToken(userName, "does not match unused"); - - } - -} diff --git a/src/main/java/org/cbioportal/service/impl/MolecularDataServiceImpl.java b/src/main/java/org/cbioportal/service/impl/MolecularDataServiceImpl.java deleted file mode 100644 index 40f60c0dbff..00000000000 --- a/src/main/java/org/cbioportal/service/impl/MolecularDataServiceImpl.java +++ /dev/null @@ -1,303 +0,0 @@ -package org.cbioportal.service.impl; - -import org.cbioportal.model.*; -import org.cbioportal.model.GeneFilterQuery; -import org.cbioportal.model.MolecularProfile.MolecularAlterationType; -import org.cbioportal.model.meta.BaseMeta; -import org.cbioportal.persistence.DiscreteCopyNumberRepository; -import org.cbioportal.persistence.MolecularDataRepository; -import org.cbioportal.persistence.SampleListRepository; -import org.cbioportal.service.MolecularDataService; -import org.cbioportal.service.MolecularProfileService; -import org.cbioportal.service.SampleService; -import org.cbioportal.service.exception.MolecularProfileNotFoundException; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.stereotype.Service; - -import java.util.*; -import java.util.function.Function; -import java.util.stream.Collectors; - -import static java.util.stream.Collectors.groupingBy; -import static java.util.stream.Collectors.toMap; - -@Service -public class MolecularDataServiceImpl implements MolecularDataService { - - @Autowired - private MolecularDataRepository molecularDataRepository; - @Autowired - private SampleService sampleService; - @Autowired - private MolecularProfileService molecularProfileService; - @Autowired - private SampleListRepository sampleListRepository; - @Autowired - private DiscreteCopyNumberRepository discreteCopyNumberRepository; - - @Override - public List getMolecularData(String molecularProfileId, String sampleListId, - List entrezGeneIds, String projection) - throws MolecularProfileNotFoundException { - - validateMolecularProfile(molecularProfileId); - List sampleIds = sampleListRepository.getAllSampleIdsInSampleList(sampleListId); - if (sampleIds.isEmpty()) { - return Collections.emptyList(); - } - return fetchMolecularData(molecularProfileId, sampleIds, entrezGeneIds, projection); - } - - @Override - public BaseMeta getMetaMolecularData(String molecularProfileId, String sampleListId, List entrezGeneIds) - throws MolecularProfileNotFoundException { - - BaseMeta baseMeta = new BaseMeta(); - baseMeta.setTotalCount(getMolecularData(molecularProfileId, sampleListId, entrezGeneIds, "ID").size()); - return baseMeta; - } - - @Override - public List fetchMolecularData(String molecularProfileId, List sampleIds, - List entrezGeneIds, String projection) - throws MolecularProfileNotFoundException { - - validateMolecularProfile(molecularProfileId); - List molecularDataList = new ArrayList<>(); - - MolecularProfileSamples commaSeparatedSampleIdsOfMolecularProfile = molecularDataRepository - .getCommaSeparatedSampleIdsOfMolecularProfile(molecularProfileId); - if (commaSeparatedSampleIdsOfMolecularProfile == null) { - return molecularDataList; - } - List internalSampleIds = Arrays.stream(commaSeparatedSampleIdsOfMolecularProfile.getSplitSampleIds()) - .mapToInt(Integer::parseInt).boxed().collect(Collectors.toList()); - Map internalSampleIdsMap = new HashMap<>(); - for (int lc = 0; lc < internalSampleIds.size(); lc++) { - internalSampleIdsMap.put(internalSampleIds.get(lc), lc); - } - - List samples; - if (sampleIds == null) { - samples = sampleService.getSamplesByInternalIds(internalSampleIds); - } else { - MolecularProfile molecularProfile = molecularProfileService.getMolecularProfile(molecularProfileId); - List studyIds = new ArrayList<>(); - sampleIds.forEach(s -> studyIds.add(molecularProfile.getCancerStudyIdentifier())); - samples = sampleService.fetchSamples(studyIds, sampleIds, "ID"); - } - - List molecularAlterations = molecularDataRepository.getGeneMolecularAlterations( - molecularProfileId, entrezGeneIds, projection); - - for (Sample sample : samples) { - Integer indexOfSampleId = internalSampleIdsMap.get(sample.getInternalId()); - if (indexOfSampleId != null) { - for (GeneMolecularAlteration molecularAlteration : molecularAlterations) { - GeneMolecularData molecularData = new GeneMolecularData(); - molecularData.setMolecularProfileId(molecularProfileId); - molecularData.setSampleId(sample.getStableId()); - molecularData.setPatientId(sample.getPatientStableId()); - molecularData.setStudyId(sample.getCancerStudyIdentifier()); - molecularData.setEntrezGeneId(molecularAlteration.getEntrezGeneId()); - molecularData.setValue(molecularAlteration.getSplitValues()[indexOfSampleId]); - molecularData.setGene(molecularAlteration.getGene()); - molecularDataList.add(molecularData); - } - } - } - - return molecularDataList; - } - - @Override - public BaseMeta fetchMetaMolecularData(String molecularProfileId, List sampleIds, - List entrezGeneIds) throws MolecularProfileNotFoundException { - - BaseMeta baseMeta = new BaseMeta(); - baseMeta.setTotalCount(fetchMolecularData(molecularProfileId, sampleIds, entrezGeneIds, "ID").size()); - return baseMeta; - } - - @Override - public Iterable getMolecularAlterations(String molecularProfileId, - List entrezGeneIds, String projection) - throws MolecularProfileNotFoundException { - - validateMolecularProfile(molecularProfileId); - if ((entrezGeneIds == null || entrezGeneIds.isEmpty()) && projection.equals("SUMMARY")) { - return molecularDataRepository.getGeneMolecularAlterationsIterableFast(molecularProfileId); - } - return molecularDataRepository.getGeneMolecularAlterationsIterable(molecularProfileId, entrezGeneIds, projection); - } - - @Override - public Integer getNumberOfSamplesInMolecularProfile(String molecularProfileId) { - - MolecularProfileSamples commaSeparatedSampleIdsOfMolecularProfile = molecularDataRepository - .getCommaSeparatedSampleIdsOfMolecularProfile(molecularProfileId); - if (commaSeparatedSampleIdsOfMolecularProfile == null) { - return null; - } - - return commaSeparatedSampleIdsOfMolecularProfile.getSplitSampleIds().length; - } - - @Override - public List getMolecularDataInMultipleMolecularProfiles(List molecularProfileIds, - List sampleIds, List entrezGeneIds, String projection) { - - List molecularDataList = new ArrayList<>(); - SortedSet distinctMolecularProfileIds = new TreeSet<>(molecularProfileIds); - - Map commaSeparatedSampleIdsOfMolecularProfilesMap = molecularDataRepository - .commaSeparatedSampleIdsOfMolecularProfilesMap(distinctMolecularProfileIds); - if (commaSeparatedSampleIdsOfMolecularProfilesMap.size() == 0) { - return molecularDataList; - } - - Map> internalSampleIdsMap = new HashMap<>(); - List allInternalSampleIds = new ArrayList<>(); - - for (String molecularProfileId : distinctMolecularProfileIds) { - List internalSampleIds = Arrays - .stream(commaSeparatedSampleIdsOfMolecularProfilesMap.get(molecularProfileId).getSplitSampleIds()) - .mapToInt(Integer::parseInt).boxed().collect(Collectors.toList()); - HashMap molecularProfileSampleMap = new HashMap(); - for (int lc = 0; lc < internalSampleIds.size(); lc++) { - molecularProfileSampleMap.put(internalSampleIds.get(lc), lc); - } - internalSampleIdsMap.put(molecularProfileId, molecularProfileSampleMap); - allInternalSampleIds.addAll(internalSampleIds); - } - - List molecularProfiles = new ArrayList<>(); - List distinctMolecularProfiles = molecularProfileService.getMolecularProfiles( - distinctMolecularProfileIds, "SUMMARY"); - Map molecularProfileMapById = distinctMolecularProfiles.stream().collect( - Collectors.toMap(MolecularProfile::getStableId, Function.identity())); - Map> molecularProfileMapByStudyId = distinctMolecularProfiles.stream().collect( - groupingBy(MolecularProfile::getCancerStudyIdentifier)); - List samples; - if (sampleIds == null) { - samples = sampleService.getSamplesByInternalIds(allInternalSampleIds); - for (String molecularProfileId : distinctMolecularProfileIds) { - internalSampleIdsMap.get(molecularProfileId).keySet().forEach(s -> molecularProfiles.add(molecularProfileMapById - .get(molecularProfileId))); - } - } else { - for (String molecularProfileId : molecularProfileIds) { - molecularProfiles.add(molecularProfileMapById.get(molecularProfileId)); - } - List studyIds = molecularProfiles.stream().map(MolecularProfile::getCancerStudyIdentifier) - .collect(Collectors.toList()); - samples = sampleService.fetchSamples(studyIds, sampleIds, "ID"); - } - - // query each entrezGeneId separately so they can be cached - List molecularAlterations = entrezGeneIds.stream() - .flatMap(gene -> molecularDataRepository.getGeneMolecularAlterationsInMultipleMolecularProfiles( - distinctMolecularProfileIds, Collections.singletonList(gene), projection - ).stream() - ) - .collect(Collectors.toList()); - Map> molecularAlterationsMap = molecularAlterations.stream().collect( - groupingBy(GeneMolecularAlteration::getMolecularProfileId)); - - for (Sample sample : samples) { - for (MolecularProfile molecularProfile : molecularProfileMapByStudyId.get(sample.getCancerStudyIdentifier())) { - String molecularProfileId = molecularProfile.getStableId(); - Integer indexOfSampleId = internalSampleIdsMap.get(molecularProfileId).get(sample.getInternalId()); - if (indexOfSampleId != null && molecularAlterationsMap.containsKey(molecularProfileId)) { - for (GeneMolecularAlteration molecularAlteration : molecularAlterationsMap.get(molecularProfileId)) { - GeneMolecularData molecularData = new GeneMolecularData(); - molecularData.setMolecularProfileId(molecularProfileId); - molecularData.setSampleId(sample.getStableId()); - molecularData.setPatientId(sample.getPatientStableId()); - molecularData.setStudyId(sample.getCancerStudyIdentifier()); - molecularData.setEntrezGeneId(molecularAlteration.getEntrezGeneId()); - try { - molecularData.setValue(molecularAlteration.getSplitValues()[indexOfSampleId]); - } catch (ArrayIndexOutOfBoundsException e) { - molecularData.setValue(null); - } - molecularData.setGene(molecularAlteration.getGene()); - molecularDataList.add(molecularData); - } - } - } - } - - return molecularDataList; - } - - @Override - public List getMolecularDataInMultipleMolecularProfilesByGeneQueries(List molecularProfileIds, - List sampleIds, - List geneQueries, - String projection) { - // Molecular alterations for all genes in the geneQueries - List entrezGeneIds = geneQueries.stream() - .map(GeneFilterQuery::getEntrezGeneId) - .collect(Collectors.toList()); - List molecularDataList = getMolecularDataInMultipleMolecularProfiles(molecularProfileIds, sampleIds, entrezGeneIds, projection); - - // All CNA events that match requested geneQueries - List copyNumberData = discreteCopyNumberRepository - .getDiscreteCopyNumbersInMultipleMolecularProfilesByGeneQueries(molecularProfileIds, sampleIds, - geneQueries, projection); - - // molecularProfile->entrezGeneId->sampleId->alterationType lookup table for CNA events - Map cnaEventLookup = copyNumberData.stream() - .collect(toMap(d -> cnaEventKey(d), Function.identity())); - - // remove molecular data that is not covered by a CNA event - molecularDataList = molecularDataList.stream() - .filter(d -> cnaEventLookup.containsKey(cnaEventKey(d))) - .collect(Collectors.toList()); - - return molecularDataList; - } - - @Override - @PreAuthorize("hasPermission(#molecularProfileIds, 'Collection', T(org.cbioportal.utils.security.AccessLevel).READ)") - public BaseMeta getMetaMolecularDataInMultipleMolecularProfiles(List molecularProfileIds, - List sampleIds, List entrezGeneIds) { - - BaseMeta baseMeta = new BaseMeta(); - baseMeta.setTotalCount(getMolecularDataInMultipleMolecularProfiles(molecularProfileIds, sampleIds, entrezGeneIds, "ID") - .size()); - return baseMeta; - } - - private void validateMolecularProfile(String molecularProfileId) throws MolecularProfileNotFoundException { - - MolecularProfile molecularProfile = molecularProfileService.getMolecularProfile(molecularProfileId); - - if (molecularProfile.getMolecularAlterationType().equals(MolecularAlterationType.MUTATION_EXTENDED) || - molecularProfile.getMolecularAlterationType().equals(MolecularAlterationType.MUTATION_UNCALLED) || - molecularProfile.getMolecularAlterationType().equals(MolecularAlterationType.STRUCTURAL_VARIANT)) { - - throw new MolecularProfileNotFoundException(molecularProfileId); - } - } - - private String cnaEventKey(DiscreteCopyNumberData cna) { - StringJoiner stringJoiner = new StringJoiner("_"); - stringJoiner.add(cna.getMolecularProfileId()); - stringJoiner.add(String.valueOf(cna.getEntrezGeneId())); - stringJoiner.add(cna.getSampleId()); - stringJoiner.add(String.valueOf(cna.getAlteration())); - return stringJoiner.toString(); - } - - private String cnaEventKey(GeneMolecularData cna) { - StringJoiner stringJoiner = new StringJoiner("_"); - stringJoiner.add(cna.getMolecularProfileId()); - stringJoiner.add(String.valueOf(cna.getEntrezGeneId())); - stringJoiner.add(cna.getSampleId()); - stringJoiner.add(String.valueOf(cna.getValue())); - return stringJoiner.toString(); - } -} diff --git a/src/main/java/org/cbioportal/service/impl/MolecularProfileServiceImpl.java b/src/main/java/org/cbioportal/service/impl/MolecularProfileServiceImpl.java deleted file mode 100644 index 3a4d6c8a1d7..00000000000 --- a/src/main/java/org/cbioportal/service/impl/MolecularProfileServiceImpl.java +++ /dev/null @@ -1,160 +0,0 @@ -package org.cbioportal.service.impl; - -import org.cbioportal.model.MolecularProfile; -import org.cbioportal.model.MolecularProfileCaseIdentifier; -import org.cbioportal.model.meta.BaseMeta; -import org.cbioportal.persistence.MolecularProfileRepository; -import org.cbioportal.service.MolecularProfileService; -import org.cbioportal.service.StudyService; -import org.cbioportal.service.exception.MolecularProfileNotFoundException; -import org.cbioportal.service.exception.StudyNotFoundException; -import org.cbioportal.service.util.MolecularProfileUtil; -import org.cbioportal.web.parameter.Projection; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.security.access.prepost.PostFilter; -import org.springframework.stereotype.Service; - -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; -import java.util.Set; -import java.util.function.Predicate; - -@Service -public class MolecularProfileServiceImpl implements MolecularProfileService { - - @Autowired - private MolecularProfileRepository molecularProfileRepository; - @Autowired - private StudyService studyService; - @Autowired - private MolecularProfileUtil molecularProfileUtil; - @Value("${authenticate:false}") - private String AUTHENTICATE; - - @Override - @PostFilter("hasPermission(filterObject, T(org.cbioportal.utils.security.AccessLevel).READ)") - public List getAllMolecularProfiles(String projection, Integer pageSize, Integer pageNumber, - String sortBy, String direction) { - - List molecularProfiles = molecularProfileRepository.getAllMolecularProfiles(projection, pageSize, pageNumber, sortBy, direction); - // copy the list before returning so @PostFilter doesn't taint the list stored in the persistence layer cache - return (AUTHENTICATE.equals("false")) ? molecularProfiles : new ArrayList(molecularProfiles); - } - - @Override - public BaseMeta getMetaMolecularProfiles() { - - return molecularProfileRepository.getMetaMolecularProfiles(); - } - - @Override - public MolecularProfile getMolecularProfile(String molecularProfileId) throws MolecularProfileNotFoundException { - - MolecularProfile molecularProfile = molecularProfileRepository.getMolecularProfile(molecularProfileId); - if (molecularProfile == null) { - throw new MolecularProfileNotFoundException(molecularProfileId); - } - - return molecularProfile; - } - - @Override - public List getMolecularProfiles(Set molecularProfileIds, String projection) { - - return molecularProfileRepository.getMolecularProfiles(molecularProfileIds, projection); - } - - @Override - public BaseMeta getMetaMolecularProfiles(Set molecularProfileIds) { - - return molecularProfileRepository.getMetaMolecularProfiles(molecularProfileIds); - } - - @Override - public List getAllMolecularProfilesInStudy(String studyId, String projection, Integer pageSize, - Integer pageNumber, String sortBy, String direction) - throws StudyNotFoundException { - - studyService.getStudy(studyId); - - return molecularProfileRepository.getAllMolecularProfilesInStudy(studyId, projection, pageSize, pageNumber, - sortBy, direction); - } - - @Override - public BaseMeta getMetaMolecularProfilesInStudy(String studyId) throws StudyNotFoundException { - - studyService.getStudy(studyId); - - return molecularProfileRepository.getMetaMolecularProfilesInStudy(studyId); - } - - @Override - public List getMolecularProfilesInStudies(List studyIds, String projection) { - - return molecularProfileRepository.getMolecularProfilesInStudies(studyIds, projection); - } - - @Override - public BaseMeta getMetaMolecularProfilesInStudies(List studyIds) { - - return molecularProfileRepository.getMetaMolecularProfilesInStudies(studyIds); - } - - @Override - public List getMolecularProfilesReferredBy(String referringMolecularProfileId) - throws MolecularProfileNotFoundException { - - //validate (throws exception if profile not found): - this.getMolecularProfile(referringMolecularProfileId); - return molecularProfileRepository.getMolecularProfilesReferredBy(referringMolecularProfileId); - } - - @Override - public List getMolecularProfilesReferringTo(String referredMolecularProfileId) - throws MolecularProfileNotFoundException { - - //validate (throws exception if profile not found): - this.getMolecularProfile(referredMolecularProfileId); - return molecularProfileRepository.getMolecularProfilesReferringTo(referredMolecularProfileId); - } - - @Override - public List getMolecularProfileCaseIdentifiers(List studyIds, List sampleIds) { - return getFilteredMolecularProfileCaseIdentifiers(studyIds, sampleIds, Optional.empty()); - } - - @Override - public List getFirstMutationProfileCaseIdentifiers(List studyIds, List sampleIds) { - return getFirstFilteredMolecularProfileCaseIdentifiers(studyIds, sampleIds, Optional.of(molecularProfileUtil.isMutationProfile)); - } - - @Override - public List getMutationProfileCaseIdentifiers(List studyIds, List sampleIds) { - return getFilteredMolecularProfileCaseIdentifiers(studyIds, sampleIds, Optional.of(molecularProfileUtil.isMutationProfile)); - } - - @Override - public List getFirstDiscreteCNAProfileCaseIdentifiers(List studyIds, List sampleIds) { - return getFilteredMolecularProfileCaseIdentifiers(studyIds, sampleIds, Optional.of(molecularProfileUtil.isDiscreteCNAMolecularProfile)); - } - - @Override - public List getFirstStructuralVariantProfileCaseIdentifiers(List studyIds, List sampleIds) { - return getFirstFilteredMolecularProfileCaseIdentifiers(studyIds, sampleIds, Optional.of(molecularProfileUtil.isStructuralVariantMolecularProfile)); - } - - private List getFirstFilteredMolecularProfileCaseIdentifiers(List studyIds, List sampleIds, Optional> profileFilter) { - List molecularProfiles = - getMolecularProfilesInStudies(studyIds.stream().distinct().toList(), Projection.SUMMARY.name()); - return molecularProfileUtil.getFirstFilteredMolecularProfileCaseIdentifiers(molecularProfiles, studyIds, sampleIds, profileFilter); - } - - private List getFilteredMolecularProfileCaseIdentifiers(List studyIds, List sampleIds, Optional> profileFilter) { - List molecularProfiles = - getMolecularProfilesInStudies(studyIds.stream().distinct().toList(), Projection.SUMMARY.name()); - return molecularProfileUtil.getFilteredMolecularProfileCaseIdentifiers(molecularProfiles, studyIds, sampleIds, profileFilter); - } -} diff --git a/src/main/java/org/cbioportal/service/impl/MrnaPercentileServiceImpl.java b/src/main/java/org/cbioportal/service/impl/MrnaPercentileServiceImpl.java deleted file mode 100644 index af97c101c09..00000000000 --- a/src/main/java/org/cbioportal/service/impl/MrnaPercentileServiceImpl.java +++ /dev/null @@ -1,83 +0,0 @@ -package org.cbioportal.service.impl; - -import org.apache.commons.lang3.math.NumberUtils; -import org.apache.commons.math3.stat.ranking.NaNStrategy; -import org.apache.commons.math3.stat.ranking.NaturalRanking; -import org.apache.commons.math3.stat.ranking.TiesStrategy; -import org.cbioportal.model.GeneMolecularData; -import org.cbioportal.model.MolecularProfile; -import org.cbioportal.model.MrnaPercentile; -import org.cbioportal.service.MolecularDataService; -import org.cbioportal.service.MolecularProfileService; -import org.cbioportal.service.MrnaPercentileService; -import org.cbioportal.service.exception.MolecularProfileNotFoundException; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -import java.math.BigDecimal; -import java.util.ArrayList; -import java.util.List; -import java.util.stream.Collectors; - -@Service -public class MrnaPercentileServiceImpl implements MrnaPercentileService { - - @Autowired - private MolecularDataService molecularDataService; - @Autowired - private MolecularProfileService molecularProfileService; - - private NaturalRanking naturalRanking = new NaturalRanking(NaNStrategy.REMOVED, TiesStrategy.MAXIMUM); - - @Override - public List fetchMrnaPercentile(String molecularProfileId, String sampleId, - List entrezGeneIds) - throws MolecularProfileNotFoundException { - - validateMolecularProfile(molecularProfileId); - - List allMolecularDataList = molecularDataService.fetchMolecularData(molecularProfileId, null, - entrezGeneIds, "SUMMARY"); - - List molecularDataList = allMolecularDataList.stream().filter(g -> g.getSampleId() - .equals(sampleId)).collect(Collectors.toList()); - - List mrnaPercentileList = new ArrayList<>(); - for (GeneMolecularData molecularData : molecularDataList) { - if (NumberUtils.isNumber(molecularData.getValue())) { - MrnaPercentile mrnaPercentile = new MrnaPercentile(); - mrnaPercentile.setEntrezGeneId(molecularData.getEntrezGeneId()); - mrnaPercentile.setSampleId(sampleId); - mrnaPercentile.setPatientId(molecularData.getPatientId()); - mrnaPercentile.setStudyId(molecularData.getStudyId()); - mrnaPercentile.setMolecularProfileId(molecularProfileId); - mrnaPercentile.setzScore(new BigDecimal(molecularData.getValue())); - - List molecularDataListOfGene = allMolecularDataList.stream().filter(g -> - g.getEntrezGeneId().equals(molecularData.getEntrezGeneId()) && NumberUtils.isNumber(g.getValue())) - .collect(Collectors.toList()); - - double[] values = molecularDataListOfGene.stream().mapToDouble(g -> Double.parseDouble(g.getValue())) - .toArray(); - double[] ranks = naturalRanking.rank(values); - double rank = ranks[molecularDataListOfGene.indexOf(molecularData)]; - double percentile = (rank / ranks.length) * 100; - mrnaPercentile.setPercentile(BigDecimal.valueOf(percentile).setScale(2, BigDecimal.ROUND_HALF_UP)); - mrnaPercentileList.add(mrnaPercentile); - } - } - - return mrnaPercentileList; - } - - private void validateMolecularProfile(String molecularProfileId) throws MolecularProfileNotFoundException { - - MolecularProfile molecularProfile = molecularProfileService.getMolecularProfile(molecularProfileId); - - if (!molecularProfile.getMolecularAlterationType() - .equals(MolecularProfile.MolecularAlterationType.MRNA_EXPRESSION)) { - - throw new MolecularProfileNotFoundException(molecularProfileId); - } - } -} diff --git a/src/main/java/org/cbioportal/service/impl/MutationServiceImpl.java b/src/main/java/org/cbioportal/service/impl/MutationServiceImpl.java deleted file mode 100644 index 44602217b68..00000000000 --- a/src/main/java/org/cbioportal/service/impl/MutationServiceImpl.java +++ /dev/null @@ -1,146 +0,0 @@ -package org.cbioportal.service.impl; - -import org.cbioportal.model.GeneFilterQuery; -import org.cbioportal.model.GenomicDataCountItem; -import org.cbioportal.model.MolecularProfile; -import org.cbioportal.model.Mutation; -import org.cbioportal.model.MutationCountByPosition; -import org.cbioportal.model.meta.MutationMeta; -import org.cbioportal.persistence.MutationRepository; -import org.cbioportal.service.MolecularProfileService; -import org.cbioportal.service.MutationService; -import org.cbioportal.service.exception.MolecularProfileNotFoundException; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -import java.util.ArrayList; -import java.util.List; - -@Service -public class MutationServiceImpl implements MutationService { - - @Autowired - private MutationRepository mutationRepository; - @Autowired - private MolecularProfileService molecularProfileService; - - @Override - public List getMutationsInMolecularProfileBySampleListId(String molecularProfileId, String sampleListId, - List entrezGeneIds, boolean snpOnly, - String projection, Integer pageSize, - Integer pageNumber, String sortBy, - String direction) - throws MolecularProfileNotFoundException { - - validateMolecularProfile(molecularProfileId); - - List mutationList = mutationRepository.getMutationsInMolecularProfileBySampleListId(molecularProfileId, - sampleListId, entrezGeneIds, snpOnly, projection, pageSize, pageNumber, sortBy, direction); - - return mutationList; - } - - @Override - public MutationMeta getMetaMutationsInMolecularProfileBySampleListId(String molecularProfileId, String sampleListId, - List entrezGeneIds) - throws MolecularProfileNotFoundException { - - validateMolecularProfile(molecularProfileId); - - return mutationRepository.getMetaMutationsInMolecularProfileBySampleListId(molecularProfileId, sampleListId, - entrezGeneIds); - } - - public List getMutationsInMultipleMolecularProfilesByGeneQueries(List molecularProfileIds, List sampleIds, - List geneQueries, String projection, - Integer pageSize, Integer pageNumber, - String sortBy, String direction) { - - List mutationList = mutationRepository.getMutationsInMultipleMolecularProfilesByGeneQueries( - molecularProfileIds, sampleIds, geneQueries, projection, pageSize, pageNumber, sortBy, direction); - - return mutationList; - } - - @Override - public List getMutationsInMultipleMolecularProfiles(List molecularProfileIds, - List sampleIds, List entrezGeneIds, - String projection, Integer pageSize, - Integer pageNumber, String sortBy, String direction) { - - List mutationList = mutationRepository.getMutationsInMultipleMolecularProfiles(molecularProfileIds, - sampleIds, entrezGeneIds, projection, pageSize, pageNumber, sortBy, direction); - - return mutationList; - } - - @Override - public MutationMeta getMetaMutationsInMultipleMolecularProfiles(List molecularProfileIds, - List sampleIds, - List entrezGeneIds) { - - return mutationRepository.getMetaMutationsInMultipleMolecularProfiles(molecularProfileIds, sampleIds, - entrezGeneIds); - } - - @Override - public List fetchMutationsInMolecularProfile(String molecularProfileId, List sampleIds, - List entrezGeneIds, boolean snpOnly, - String projection, Integer pageSize, Integer pageNumber, - String sortBy, String direction) - throws MolecularProfileNotFoundException { - - validateMolecularProfile(molecularProfileId); - - List mutationList = mutationRepository.fetchMutationsInMolecularProfile(molecularProfileId, sampleIds, - entrezGeneIds, snpOnly, projection, pageSize, pageNumber, sortBy, direction); - - return mutationList; - } - - @Override - public MutationMeta fetchMetaMutationsInMolecularProfile(String molecularProfileId, List sampleIds, - List entrezGeneIds) - throws MolecularProfileNotFoundException { - - validateMolecularProfile(molecularProfileId); - - return mutationRepository.fetchMetaMutationsInMolecularProfile(molecularProfileId, sampleIds, entrezGeneIds); - } - - @Override - public List fetchMutationCountsByPosition(List entrezGeneIds, - List proteinPosStarts, - List proteinPosEnds) { - - List mutationCountByPositionList = new ArrayList<>(); - for (int i = 0; i < entrezGeneIds.size(); i++) { - - MutationCountByPosition mutationCountByPosition = mutationRepository.getMutationCountByPosition( - entrezGeneIds.get(i), proteinPosStarts.get(i), proteinPosEnds.get(i)); - mutationCountByPositionList.add(mutationCountByPosition); - } - - return mutationCountByPositionList; - } - - @Override - public GenomicDataCountItem getMutationCountsByType(List molecularProfileIds, List sampleIds, - List entrezGeneIds, String profileType) { - return mutationRepository.getMutationCountsByType(molecularProfileIds, sampleIds, entrezGeneIds, profileType); - } - - private MolecularProfile validateMolecularProfile(String molecularProfileId) throws MolecularProfileNotFoundException { - - MolecularProfile molecularProfile = molecularProfileService.getMolecularProfile(molecularProfileId); - - if (!(molecularProfile.getMolecularAlterationType() - .equals(MolecularProfile.MolecularAlterationType.MUTATION_EXTENDED) || molecularProfile.getMolecularAlterationType() - .equals(MolecularProfile.MolecularAlterationType.MUTATION_UNCALLED))) { - - throw new MolecularProfileNotFoundException(molecularProfileId); - } - - return molecularProfile; - } -} diff --git a/src/main/java/org/cbioportal/service/impl/MutationSpectrumServiceImpl.java b/src/main/java/org/cbioportal/service/impl/MutationSpectrumServiceImpl.java deleted file mode 100644 index 36c685b14f4..00000000000 --- a/src/main/java/org/cbioportal/service/impl/MutationSpectrumServiceImpl.java +++ /dev/null @@ -1,79 +0,0 @@ -package org.cbioportal.service.impl; - -import org.cbioportal.model.Mutation; -import org.cbioportal.model.MutationSpectrum; -import org.cbioportal.service.MutationService; -import org.cbioportal.service.MutationSpectrumService; -import org.cbioportal.service.exception.MolecularProfileNotFoundException; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - -@Service -public class MutationSpectrumServiceImpl implements MutationSpectrumService { - - @Autowired - private MutationService mutationService; - - @Override - public List getMutationSpectrums(String molecularProfileId, String sampleListId) - throws MolecularProfileNotFoundException { - - List mutations = mutationService.getMutationsInMolecularProfileBySampleListId(molecularProfileId, - sampleListId, null, true, "SUMMARY", null, null, null, null); - - return createMutationSpectrums(molecularProfileId, mutations); - } - - @Override - public List fetchMutationSpectrums(String molecularProfileId, List sampleIds) - throws MolecularProfileNotFoundException { - - List mutations = mutationService.fetchMutationsInMolecularProfile(molecularProfileId, sampleIds, null, - true, "SUMMARY", null, null, null, null); - - return createMutationSpectrums(molecularProfileId, mutations); - } - - private List createMutationSpectrums(String molecularProfileId, List mutations) { - - Map> mutationMap = mutations.stream().collect(Collectors.groupingBy( - Mutation::getSampleId)); - - List mutationSpectrums = new ArrayList<>(); - for (String sampleId : mutationMap.keySet()) { - - List mutationsInSample = mutationMap.get(sampleId); - MutationSpectrum mutationSpectrum = new MutationSpectrum(); - mutationSpectrum.setMolecularProfileId(molecularProfileId); - mutationSpectrum.setSampleId(sampleId); - mutationSpectrum.setPatientId(mutationsInSample.get(0).getPatientId()); - mutationSpectrum.setStudyId(mutationsInSample.get(0).getStudyId()); - mutationSpectrum.setCtoA(Math.toIntExact(mutationsInSample.stream().filter(m -> checkSpectrum(m, "C", "A") - || checkSpectrum(m, "G", "T")).count())); - mutationSpectrum.setCtoG(Math.toIntExact(mutationsInSample.stream().filter(m -> checkSpectrum(m, "C", "G") - || checkSpectrum(m, "G", "C")).count())); - mutationSpectrum.setCtoT(Math.toIntExact(mutationsInSample.stream().filter(m -> checkSpectrum(m, "C", "T") - || checkSpectrum(m, "G", "A")).count())); - mutationSpectrum.setTtoA(Math.toIntExact(mutationsInSample.stream().filter(m -> checkSpectrum(m, "T", "A") - || checkSpectrum(m, "A", "T")).count())); - mutationSpectrum.setTtoC(Math.toIntExact(mutationsInSample.stream().filter(m -> checkSpectrum(m, "T", "C") - || checkSpectrum(m, "A", "G")).count())); - mutationSpectrum.setTtoG(Math.toIntExact(mutationsInSample.stream().filter(m -> checkSpectrum(m, "T", "G") - || checkSpectrum(m, "A", "C")).count())); - mutationSpectrums.add(mutationSpectrum); - } - - return mutationSpectrums; - } - - private boolean checkSpectrum(Mutation mutation, String referenceAllele, String tumorSeqAllele) { - - return mutation.getReferenceAllele().equals(referenceAllele) && - mutation.getTumorSeqAllele().equals(tumorSeqAllele); - } -} diff --git a/src/main/java/org/cbioportal/service/impl/PatientServiceImpl.java b/src/main/java/org/cbioportal/service/impl/PatientServiceImpl.java deleted file mode 100644 index a317dce672f..00000000000 --- a/src/main/java/org/cbioportal/service/impl/PatientServiceImpl.java +++ /dev/null @@ -1,93 +0,0 @@ -package org.cbioportal.service.impl; - -import org.cbioportal.model.Patient; -import org.cbioportal.model.meta.BaseMeta; -import org.cbioportal.persistence.PatientRepository; -import org.cbioportal.service.PatientService; -import org.cbioportal.service.StudyService; -import org.cbioportal.service.exception.PatientNotFoundException; -import org.cbioportal.service.exception.StudyNotFoundException; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.security.access.prepost.PostFilter; -import org.springframework.stereotype.Service; - -import java.util.ArrayList; -import java.util.List; - -@Service -public class PatientServiceImpl implements PatientService { - - @Autowired - private PatientRepository patientRepository; - @Autowired - private StudyService studyService; - @Value("${authenticate:false}") - private String AUTHENTICATE; - - @Override - @PostFilter("hasPermission(filterObject, T(org.cbioportal.utils.security.AccessLevel).READ)") - public List getAllPatients(String keyword, String projection, Integer pageSize, Integer pageNumber, - String sortBy, String direction) { - - List patients = patientRepository.getAllPatients(keyword, projection, pageSize, pageNumber, sortBy, direction); - // copy the list before returning so @PostFilter doesn't taint the list stored in the persistence layer cache - return (AUTHENTICATE.equals("false")) ? patients : new ArrayList(patients); - } - - @Override - public BaseMeta getMetaPatients(String keyword) { - - return patientRepository.getMetaPatients(keyword); - } - - @Override - public List getAllPatientsInStudy(String studyId, String projection, Integer pageSize, Integer pageNumber, - String sortBy, String direction) throws StudyNotFoundException { - - studyService.getStudy(studyId); - - return patientRepository.getAllPatientsInStudy(studyId, projection, pageSize, pageNumber, sortBy, direction); - } - - @Override - public BaseMeta getMetaPatientsInStudy(String studyId) throws StudyNotFoundException { - - studyService.getStudy(studyId); - - return patientRepository.getMetaPatientsInStudy(studyId); - } - - @Override - public Patient getPatientInStudy(String studyId, String patientId) throws PatientNotFoundException, - StudyNotFoundException { - - studyService.getStudy(studyId); - - Patient patient = patientRepository.getPatientInStudy(studyId, patientId); - - if (patient == null) { - throw new PatientNotFoundException(studyId, patientId); - } - - return patient; - } - - @Override - public List fetchPatients(List studyIds, List patientIds, String projection) { - - return patientRepository.fetchPatients(studyIds, patientIds, projection); - } - - @Override - public BaseMeta fetchMetaPatients(List studyIds, List patientIds) { - - return patientRepository.fetchMetaPatients(studyIds, patientIds); - } - - @Override - public List getPatientsOfSamples(List studyIds, List sampleIds) { - - return patientRepository.getPatientsOfSamples(studyIds, sampleIds); - } -} diff --git a/src/main/java/org/cbioportal/service/impl/ReadPermissionServiceImpl.java b/src/main/java/org/cbioportal/service/impl/ReadPermissionServiceImpl.java deleted file mode 100644 index 0662008422b..00000000000 --- a/src/main/java/org/cbioportal/service/impl/ReadPermissionServiceImpl.java +++ /dev/null @@ -1,31 +0,0 @@ -package org.cbioportal.service.impl; - -import org.cbioportal.service.ReadPermissionService; -import org.cbioportal.model.ReadPermission; -import org.cbioportal.security.CancerStudyPermissionEvaluator; -import org.cbioportal.utils.security.AccessLevel; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.security.core.Authentication; -import org.springframework.stereotype.Service; - -import java.util.Collection; - -@Service -public class ReadPermissionServiceImpl implements ReadPermissionService { - - // The CancerStudyPermissionEvaluator bean does not exist on portals w/o user-authentication - @Autowired(required = false) - private CancerStudyPermissionEvaluator cancerStudyPermissionEvaluator; - - @Override - public void setReadPermission(Collection entities, Authentication authentication) { - entities.forEach(s -> { - // Add user read-permission to each entity when authentication is used (defaults - // to 'true' on portals w/o user-authentication). - boolean hasReadPermission = authentication == null || cancerStudyPermissionEvaluator == null || - cancerStudyPermissionEvaluator.hasPermission(authentication, s, AccessLevel.READ); - s.setReadPermission(hasReadPermission); - }); - } - -} \ No newline at end of file diff --git a/src/main/java/org/cbioportal/service/impl/RedisCacheStatisticsServiceImpl.java b/src/main/java/org/cbioportal/service/impl/RedisCacheStatisticsServiceImpl.java deleted file mode 100644 index ef8e447355a..00000000000 --- a/src/main/java/org/cbioportal/service/impl/RedisCacheStatisticsServiceImpl.java +++ /dev/null @@ -1,93 +0,0 @@ -package org.cbioportal.service.impl; - -import org.cbioportal.persistence.util.CustomKeyGenerator; -import org.cbioportal.persistence.util.CustomRedisCache; -import org.cbioportal.service.CacheStatisticsService; -import org.cbioportal.service.exception.CacheNotFoundException; -import org.cbioportal.utils.config.annotation.ConditionalOnProperty; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; -import org.springframework.cache.Cache; -import org.springframework.cache.CacheManager; -import org.springframework.security.access.AccessDeniedException; -import org.springframework.stereotype.Service; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.function.Function; -import java.util.stream.Collectors; - -@Service -@ConditionalOnExpression( - "#{environment['persistence.cache_type'] == 'redis' or environment['persistence.cache_type_clickhouse'] == 'redis'}" -) -public class RedisCacheStatisticsServiceImpl implements CacheStatisticsService { - - @Autowired - public CacheManager cacheManager; - - @Value("${cache.statistics_endpoint_enabled:false}") - public boolean cacheStatisticsEndpointEnabled; - - protected void checkIfCacheStatisticsEndpointEnabled() { - if (!cacheStatisticsEndpointEnabled) { - throw new AccessDeniedException("Cache statistics is not enabled for this instance of the portal."); - } - } - - @Override - public List getKeyCountsPerClass(String cacheName) throws CacheNotFoundException { - checkIfCacheStatisticsEndpointEnabled(); - if (!cacheManager.getCacheNames().contains(cacheName)) { - throw new CacheNotFoundException(cacheName); - } - - Cache cache = cacheManager.getCache(cacheName); - if (cache instanceof CustomRedisCache) { - CustomRedisCache redisCache = (CustomRedisCache) cache; - Map keyCountPerClass = redisCache.getNativeCache() - .getKeys() - .getKeysStream() - .filter(k -> k.startsWith(redisCache.getName())) - // cut off cache name from key - .map(k -> k.substring(redisCache.getName().length() + CustomRedisCache.DELIMITER.length())) - // cut off everything after the class of the class of the cached method - .map(k -> k.substring(0, k.indexOf(CustomKeyGenerator.CACHE_KEY_PARAM_DELIMITER))) - .collect(Collectors.groupingBy(Function.identity(), Collectors.counting())); - - return keyCountPerClass.entrySet().stream() - .map(e -> e.getKey() + ": " + e.getValue() + " keys") - .collect(Collectors.toList()); - } - - return new ArrayList<>(); - } - - @Override - public List getKeysInCache(String cacheName) throws CacheNotFoundException { - checkIfCacheStatisticsEndpointEnabled(); - if (!cacheManager.getCacheNames().contains(cacheName)) { - throw new CacheNotFoundException(cacheName); - } - - Cache cache = cacheManager.getCache(cacheName); - - if (cache instanceof CustomRedisCache) { - CustomRedisCache redisCache = (CustomRedisCache) cache; - return redisCache.getNativeCache() - .getKeys() - .getKeysStream() - .filter(k -> k.startsWith(redisCache.getName())) - .collect(Collectors.toList()); - } - - return new ArrayList<>(); - } - - @Override - public String getCacheStatistics() { - throw new UnsupportedOperationException("Requested API is not implemented yet"); - } -} diff --git a/src/main/java/org/cbioportal/service/impl/ReferenceGenomeGeneServiceImpl.java b/src/main/java/org/cbioportal/service/impl/ReferenceGenomeGeneServiceImpl.java deleted file mode 100644 index d371743f716..00000000000 --- a/src/main/java/org/cbioportal/service/impl/ReferenceGenomeGeneServiceImpl.java +++ /dev/null @@ -1,45 +0,0 @@ -package org.cbioportal.service.impl; - - -import org.cbioportal.model.ReferenceGenomeGene; -import org.cbioportal.persistence.ReferenceGenomeGeneRepository; -import org.cbioportal.service.ReferenceGenomeGeneService; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -import java.util.List; - -@Service -public class ReferenceGenomeGeneServiceImpl implements ReferenceGenomeGeneService { - - @Autowired - private ReferenceGenomeGeneRepository referenceGenomeGeneRepository; - - @Override - public List fetchAllReferenceGenomeGenes(String genomeName) { - - return referenceGenomeGeneRepository.getAllGenesByGenomeName(genomeName); - } - - @Override - public List fetchGenesByGenomeName(List geneIds, String genomeName) { - return referenceGenomeGeneRepository.getGenesByGenomeName(geneIds, genomeName); - } - - @Override - public List fetchGenesByHugoGeneSymbolsAndGenomeName(List geneIds, String genomeName) { - return referenceGenomeGeneRepository.getGenesByHugoGeneSymbolsAndGenomeName(geneIds, genomeName); - } - - @Override - public ReferenceGenomeGene getReferenceGenomeGene(Integer geneId, String genomeName) { - - return referenceGenomeGeneRepository.getReferenceGenomeGene(geneId, genomeName); - } - - @Override - public ReferenceGenomeGene getReferenceGenomeGeneByEntityId(Integer entityId, String genomeName) { - - return referenceGenomeGeneRepository.getReferenceGenomeGeneByEntityId(entityId, genomeName); - } -} diff --git a/src/main/java/org/cbioportal/service/impl/ResourceDataServiceImpl.java b/src/main/java/org/cbioportal/service/impl/ResourceDataServiceImpl.java deleted file mode 100644 index 6e1d94ebe77..00000000000 --- a/src/main/java/org/cbioportal/service/impl/ResourceDataServiceImpl.java +++ /dev/null @@ -1,78 +0,0 @@ -package org.cbioportal.service.impl; - -import java.util.List; -import java.util.ArrayList; - -import org.cbioportal.model.ResourceData; -import org.cbioportal.persistence.ResourceDataRepository; -import org.cbioportal.service.PatientService; -import org.cbioportal.service.ResourceDataService; -import org.cbioportal.service.SampleService; -import org.cbioportal.service.StudyService; -import org.cbioportal.service.exception.PatientNotFoundException; -import org.cbioportal.service.exception.SampleNotFoundException; -import org.cbioportal.service.exception.StudyNotFoundException; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -@Service -public class ResourceDataServiceImpl implements ResourceDataService { - - @Autowired - private ResourceDataRepository resourceDataRepository; - @Autowired - private StudyService studyService; - @Autowired - private PatientService patientService; - @Autowired - private SampleService sampleService; - - @Override - public List getAllResourceDataOfSampleInStudy(String studyId, String sampleId, String resourceId, - String projection, Integer pageSize, Integer pageNumber, String sortBy, String direction) - throws SampleNotFoundException, StudyNotFoundException { - sampleService.getSampleInStudy(studyId, sampleId); - - return resourceDataRepository.getAllResourceDataOfSampleInStudy(studyId, sampleId, resourceId, projection, - pageSize, pageNumber, sortBy, direction); - } - - @Override - public List getAllResourceDataOfPatientInStudy(String studyId, String patientId, String resourceId, - String projection, Integer pageSize, Integer pageNumber, String sortBy, String direction) - throws PatientNotFoundException, StudyNotFoundException { - - patientService.getPatientInStudy(studyId, patientId); - - return resourceDataRepository.getAllResourceDataOfPatientInStudy(studyId, patientId, resourceId, projection, - pageSize, pageNumber, sortBy, direction); - } - - @Override - public List getAllResourceDataForStudy(String studyId, String resourceId, String projection, - Integer pageSize, Integer pageNumber, String sortBy, String direction) throws StudyNotFoundException { - - studyService.getStudy(studyId); - - return resourceDataRepository.getAllResourceDataForStudy(studyId, resourceId, projection, pageSize, pageNumber, - sortBy, direction); - } - - @Override - public List getAllResourceDataForStudyPatientSample(String studyId, String resourceId, String projection, - Integer pageSize, Integer pageNumber, String sortBy, String direction) throws StudyNotFoundException { - - studyService.getStudy(studyId); - - List results = new ArrayList(); - - results.addAll(resourceDataRepository.getAllResourceDataForStudy(studyId, resourceId, projection, pageSize, pageNumber, - sortBy, direction)); - results.addAll(resourceDataRepository.getResourceDataForAllPatientsInStudy(studyId, resourceId, projection, pageSize, pageNumber, - sortBy, direction)); - results.addAll(resourceDataRepository.getResourceDataForAllSamplesInStudy(studyId, resourceId, projection, pageSize, pageNumber, - sortBy, direction)); - return results; - } - -} diff --git a/src/main/java/org/cbioportal/service/impl/ResourceDefinitionServiceImpl.java b/src/main/java/org/cbioportal/service/impl/ResourceDefinitionServiceImpl.java deleted file mode 100644 index 4fa493d1294..00000000000 --- a/src/main/java/org/cbioportal/service/impl/ResourceDefinitionServiceImpl.java +++ /dev/null @@ -1,53 +0,0 @@ -package org.cbioportal.service.impl; - -import java.util.Collections; -import java.util.List; - -import org.cbioportal.model.ResourceDefinition; -import org.cbioportal.persistence.ResourceDefinitionRepository; -import org.cbioportal.service.ResourceDefinitionService; -import org.cbioportal.service.StudyService; -import org.cbioportal.service.exception.ResourceDefinitionNotFoundException; -import org.cbioportal.service.exception.StudyNotFoundException; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -@Service -public class ResourceDefinitionServiceImpl implements ResourceDefinitionService { - - @Autowired - private ResourceDefinitionRepository resourceDefinitionRepository; - @Autowired - private StudyService studyService; - - @Override - public ResourceDefinition getResourceDefinition(String studyId, String resourceId) - throws ResourceDefinitionNotFoundException, StudyNotFoundException { - - studyService.getStudy(studyId); - - ResourceDefinition resourceDefinition = resourceDefinitionRepository.getResourceDefinition(studyId, resourceId); - - if (resourceDefinition == null) { - throw new ResourceDefinitionNotFoundException(studyId, resourceId); - } - - return resourceDefinition; - } - - @Override - public List getAllResourceDefinitionsInStudy(String studyId, String projection, - Integer pageSize, Integer pageNumber, String sortBy, String direction) throws StudyNotFoundException { - - studyService.getStudy(studyId); - - return resourceDefinitionRepository.fetchResourceDefinitions(Collections.singletonList(studyId), projection, pageSize, pageNumber, - sortBy, direction); - } - - @Override - public List fetchResourceDefinitions(List studyIds, String projection) throws StudyNotFoundException { - return resourceDefinitionRepository.fetchResourceDefinitions(studyIds, projection, null, null, null, null); - } - -} diff --git a/src/main/java/org/cbioportal/service/impl/SampleListServiceImpl.java b/src/main/java/org/cbioportal/service/impl/SampleListServiceImpl.java deleted file mode 100644 index 583a4a29fb9..00000000000 --- a/src/main/java/org/cbioportal/service/impl/SampleListServiceImpl.java +++ /dev/null @@ -1,144 +0,0 @@ -package org.cbioportal.service.impl; - -import org.cbioportal.model.SampleList; -import org.cbioportal.model.SampleListToSampleId; -import org.cbioportal.model.meta.BaseMeta; -import org.cbioportal.persistence.SampleListRepository; -import org.cbioportal.service.SampleListService; -import org.cbioportal.service.StudyService; -import org.cbioportal.service.exception.SampleListNotFoundException; -import org.cbioportal.service.exception.StudyNotFoundException; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.security.access.prepost.PostFilter; -import org.springframework.stereotype.Service; - -import java.util.List; -import java.util.Arrays; -import java.util.ArrayList; -import java.util.stream.Collectors; - -@Service -public class SampleListServiceImpl implements SampleListService { - - @Autowired - private SampleListRepository sampleListRepository; - @Autowired - private StudyService studyService; - @Value("${authenticate:false}") - private String AUTHENTICATE; - - @Override - @PostFilter("hasPermission(filterObject, T(org.cbioportal.utils.security.AccessLevel).READ)") - public List getAllSampleLists(String projection, Integer pageSize, Integer pageNumber, String sortBy, - String direction) { - - List sampleListsFromRepo = sampleListRepository.getAllSampleLists(projection, pageSize, pageNumber, sortBy, - direction); - // copy the list before returning so @PostFilter doesn't taint the list stored in the persistence layer cache - List sampleLists = (AUTHENTICATE.equals("false")) ? sampleListsFromRepo : new ArrayList(sampleListsFromRepo); - - if(projection.equals("DETAILED")) { - addSampleIds(sampleLists); - addSampleCounts(sampleLists); - } - - return sampleLists; - } - - @Override - public BaseMeta getMetaSampleLists() { - - return sampleListRepository.getMetaSampleLists(); - } - - @Override - public SampleList getSampleList(String sampleListId) throws SampleListNotFoundException { - - SampleList sampleList = sampleListRepository.getSampleList(sampleListId); - if (sampleList == null) { - throw new SampleListNotFoundException(sampleListId); - } - - List sampleListToSampleIds = sampleListRepository.getSampleListSampleIds( - Arrays.asList(sampleList.getListId())); - sampleList.setSampleIds(sampleListToSampleIds.stream().map(SampleListToSampleId::getSampleId) - .collect(Collectors.toList())); - sampleList.setSampleCount(sampleList.getSampleIds().size()); - return sampleList; - } - - @Override - public List getAllSampleListsInStudy(String studyId, String projection, Integer pageSize, - Integer pageNumber, String sortBy, String direction) - throws StudyNotFoundException { - - studyService.getStudy(studyId); - - List sampleLists = sampleListRepository.getAllSampleListsInStudies(Arrays.asList(studyId), projection, pageSize, - pageNumber, sortBy, direction); - - if(projection.equals("DETAILED")) { - addSampleIds(sampleLists); - addSampleCounts(sampleLists); - } - - return sampleLists; - } - - @Override - public BaseMeta getMetaSampleListsInStudy(String studyId) throws StudyNotFoundException { - - studyService.getStudy(studyId); - - return sampleListRepository.getMetaSampleListsInStudy(studyId); - } - - @Override - public List getAllSampleIdsInSampleList(String sampleListId) throws SampleListNotFoundException { - - getSampleList(sampleListId); - - return sampleListRepository.getAllSampleIdsInSampleList(sampleListId); - } - - @Override - public List fetchSampleLists(List sampleListIds, String projection) { - - List sampleLists = sampleListRepository.getSampleLists(sampleListIds, projection); - - if (projection.equals("DETAILED")) { - addSampleIds(sampleLists); - addSampleCounts(sampleLists); - } - - return sampleLists; - } - - private void addSampleCounts(List sampleLists) { - - sampleLists.forEach(s -> s.setSampleCount(s.getSampleIds().size())); - } - - private void addSampleIds(List sampleLists) { - - for(SampleList sampleList : sampleLists) { - sampleList.setSampleIds(sampleListRepository.getSampleListSampleIds(Arrays.asList(sampleList.getListId())) - .stream().map(SampleListToSampleId::getSampleId).collect(Collectors.toList())); - } - } - - @Override - public List getAllSampleListsInStudies(List studyIds, String projection) { - - List sampleLists = sampleListRepository.getAllSampleListsInStudies(studyIds, projection, null, null, - null, null); - - if (projection.equals("DETAILED")) { - addSampleIds(sampleLists); - addSampleCounts(sampleLists); - } - - return sampleLists; - } -} diff --git a/src/main/java/org/cbioportal/service/impl/SampleServiceImpl.java b/src/main/java/org/cbioportal/service/impl/SampleServiceImpl.java deleted file mode 100644 index 5d3bd389517..00000000000 --- a/src/main/java/org/cbioportal/service/impl/SampleServiceImpl.java +++ /dev/null @@ -1,209 +0,0 @@ -package org.cbioportal.service.impl; - -import org.cbioportal.model.Sample; -import org.cbioportal.model.meta.BaseMeta; -import org.cbioportal.persistence.CopyNumberSegmentRepository; -import org.cbioportal.persistence.MolecularProfileRepository; -import org.cbioportal.persistence.SampleListRepository; -import org.cbioportal.persistence.SampleRepository; -import org.cbioportal.service.PatientService; -import org.cbioportal.service.SampleService; -import org.cbioportal.service.StudyService; -import org.cbioportal.service.exception.PatientNotFoundException; -import org.cbioportal.service.exception.SampleNotFoundException; -import org.cbioportal.service.exception.StudyNotFoundException; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.cache.annotation.Cacheable; -import org.springframework.stereotype.Service; - -import java.util.*; -import java.util.stream.Collectors; - -@Service -public class SampleServiceImpl implements SampleService { - - private static final String SEQUENCED = "_sequenced"; - private static final String STRUCTURAL_VARIANT = "_sv"; - - @Autowired - private SampleRepository sampleRepository; - @Autowired - private StudyService studyService; - @Autowired - private PatientService patientService; - @Autowired - private SampleListRepository sampleListRepository; - @Autowired - private CopyNumberSegmentRepository copyNumberSegmentRepository; - @Autowired - private MolecularProfileRepository molecularProfileRepository; - - @Override - public List getAllSamples(String keyword, List studyIds, String projection, - Integer pageSize, Integer pageNumber, String sort, String direction) { - List samples = sampleRepository.getAllSamples(keyword, studyIds, projection, pageSize, pageNumber, sort, direction); - processSamples(samples, projection); - return samples; - } - - @Override - public BaseMeta getMetaSamples(String keyword, List studyIds) { - return sampleRepository.getMetaSamples(keyword, studyIds); - } - - @Override - public List getAllSamplesInStudy(String studyId, String projection, Integer pageSize, Integer pageNumber, - String sortBy, String direction) throws StudyNotFoundException { - - studyService.getStudy(studyId); - List samples = sampleRepository.getAllSamplesInStudy(studyId, projection, pageSize, pageNumber, sortBy, - direction); - - processSamples(samples, projection); - return samples; - } - - @Override - public BaseMeta getMetaSamplesInStudy(String studyId) throws StudyNotFoundException { - - studyService.getStudy(studyId); - - return sampleRepository.getMetaSamplesInStudy(studyId); - } - - @Override - public List getAllSamplesInStudies(List studyIds, String projection, Integer pageSize, - Integer pageNumber, String sortBy, String direction) { - - return sampleRepository.getAllSamplesInStudies(studyIds, projection, pageSize, pageNumber, sortBy, direction); - } - - @Override - public Sample getSampleInStudy(String studyId, String sampleId) throws SampleNotFoundException, - StudyNotFoundException { - - studyService.getStudy(studyId); - Sample sample = sampleRepository.getSampleInStudy(studyId, sampleId); - - if (sample == null) { - throw new SampleNotFoundException(studyId, sampleId); - } - - processSamples(Arrays.asList(sample), "DETAILED"); - return sample; - } - - @Override - public List getAllSamplesOfPatientInStudy(String studyId, String patientId, String projection, - Integer pageSize, Integer pageNumber, String sortBy, - String direction) throws StudyNotFoundException, - PatientNotFoundException { - - patientService.getPatientInStudy(studyId, patientId); - List samples = sampleRepository.getAllSamplesOfPatientInStudy(studyId, patientId, projection, pageSize, - pageNumber, sortBy, direction); - - processSamples(samples, projection); - return samples; - } - - @Override - public BaseMeta getMetaSamplesOfPatientInStudy(String studyId, String patientId) throws StudyNotFoundException, - PatientNotFoundException { - - patientService.getPatientInStudy(studyId, patientId); - - return sampleRepository.getMetaSamplesOfPatientInStudy(studyId, patientId); - } - - @Override - public List getAllSamplesOfPatientsInStudy(String studyId, List patientIds, String projection) { - - List samples = sampleRepository.getAllSamplesOfPatientsInStudy(studyId, patientIds, projection); - - processSamples(samples, projection); - return samples; - } - - @Override - public List getSamplesOfPatientsInMultipleStudies(List studyIds, List patientIds, - String projection) { - - List samples = sampleRepository.getSamplesOfPatientsInMultipleStudies(studyIds, patientIds, projection); - - processSamples(samples, projection); - return samples; - } - - @Override - public List fetchSamples(List studyIds, List sampleIds, String projection) { - - List samples = sampleRepository.fetchSamples(studyIds, sampleIds, projection); - processSamples(samples, projection); - return samples; - } - - @Override - @Cacheable( - cacheResolver = "staticRepositoryCacheOneResolver", - condition = "@cacheEnabledConfig.getEnabled()" - ) - public List fetchSamples(List sampleListIds, String projection) { - - List samples = sampleRepository.fetchSamplesBySampleListIds(sampleListIds, projection); - - processSamples(samples, projection); - return samples; - } - - @Override - public BaseMeta fetchMetaSamples(List studyIds, List sampleIds) { - - return sampleRepository.fetchMetaSamples(studyIds, sampleIds); - } - - @Override - public BaseMeta fetchMetaSamples(List sampleListIds) { - - return sampleRepository.fetchMetaSamples(sampleListIds); - } - - @Override - public List getSamplesByInternalIds(List internalIds) { - - return sampleRepository.getSamplesByInternalIds(internalIds); - } - - private void processSamples(List samples, String projection) { - if (projection.equals("DETAILED")) { - Map> sequencedSampleIdsMap = new HashMap<>(); - Map> structuralVariantSampleIdsMap = new HashMap<>(); - List distinctStudyIds = samples.stream().map(Sample::getCancerStudyIdentifier).distinct() - .collect(Collectors.toList()); - for (String studyId : distinctStudyIds) { - sequencedSampleIdsMap.put(studyId, - new HashSet(sampleListRepository.getAllSampleIdsInSampleList(studyId + SEQUENCED))); - // Seems like this is built for future use to support additional detailing about samples with sv data - // would be used to set a data member at the end of this function - Set svSamples = new HashSet(); - svSamples = new HashSet(sampleListRepository.getAllSampleIdsInSampleList(studyId + STRUCTURAL_VARIANT)); - structuralVariantSampleIdsMap.put(studyId, svSamples); - } - - List samplesWithCopyNumberSeg = copyNumberSegmentRepository.fetchSamplesWithCopyNumberSegments( - samples.stream().map(Sample::getCancerStudyIdentifier).collect(Collectors.toList()), - samples.stream().map(Sample::getStableId).collect(Collectors.toList()), - null - ); - - Set samplesWithCopyNumberSegMap = new HashSet<>(); - samplesWithCopyNumberSegMap.addAll(samplesWithCopyNumberSeg); - - samples.forEach(sample -> { - sample.setSequenced(sequencedSampleIdsMap.get(sample.getCancerStudyIdentifier()) - .contains(sample.getStableId())); - sample.setCopyNumberSegmentPresent(samplesWithCopyNumberSegMap.contains(sample.getInternalId())); - }); - } - } -} diff --git a/src/main/java/org/cbioportal/service/impl/ServerStatusServiceImpl.java b/src/main/java/org/cbioportal/service/impl/ServerStatusServiceImpl.java deleted file mode 100644 index 4a60a65ea58..00000000000 --- a/src/main/java/org/cbioportal/service/impl/ServerStatusServiceImpl.java +++ /dev/null @@ -1,49 +0,0 @@ -package org.cbioportal.service.impl; - -import java.io.Serializable; -import java.util.List; - -import org.cbioportal.model.TypeOfCancer; -import org.cbioportal.persistence.CancerTypeRepository; -import org.cbioportal.service.ServerStatusService; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - - -@Service -public class ServerStatusServiceImpl implements ServerStatusService { - - public static final String MESSAGE_RUNNING = "UP"; - public static final String MESSAGE_DOWN = "DOWN"; - - private static final ServerStatusMessage objRunning = new ServerStatusMessage(MESSAGE_RUNNING); - private static final ServerStatusMessage objDown = new ServerStatusMessage(MESSAGE_DOWN); - - @Autowired - private CancerTypeRepository cancerTypeRepository; - - @Override - public ServerStatusMessage getServerStatus() { - List allCancerTypes = cancerTypeRepository.getAllCancerTypes("SUMMARY", null, null, null, null); - if (allCancerTypes.size() > 0) { - return objRunning; - } - return objDown; - } - - public final static class ServerStatusMessage implements Serializable { - - private static final long serialVersionUID = 1L; - String status; - - ServerStatusMessage(String message) { - this.status = message; - } - - public String getStatus() { - return this.status; - } - - } - -} diff --git a/src/main/java/org/cbioportal/service/impl/SignificantCopyNumberRegionServiceImpl.java b/src/main/java/org/cbioportal/service/impl/SignificantCopyNumberRegionServiceImpl.java deleted file mode 100644 index c1616ac8473..00000000000 --- a/src/main/java/org/cbioportal/service/impl/SignificantCopyNumberRegionServiceImpl.java +++ /dev/null @@ -1,53 +0,0 @@ -package org.cbioportal.service.impl; - -import org.cbioportal.model.Gistic; -import org.cbioportal.model.GisticToGene; -import org.cbioportal.model.meta.BaseMeta; -import org.cbioportal.persistence.SignificantCopyNumberRegionRepository; -import org.cbioportal.service.SignificantCopyNumberRegionService; -import org.cbioportal.service.StudyService; -import org.cbioportal.service.exception.StudyNotFoundException; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -import java.util.List; -import java.util.stream.Collectors; - -@Service -public class SignificantCopyNumberRegionServiceImpl implements SignificantCopyNumberRegionService { - - @Autowired - private SignificantCopyNumberRegionRepository significantCopyNumberRegionRepository; - @Autowired - private StudyService studyService; - - @Override - public List getSignificantCopyNumberRegions(String studyId, String projection, Integer pageSize, - Integer pageNumber, String sortBy, String direction) - throws StudyNotFoundException { - - studyService.getStudy(studyId); - - List gisticList = significantCopyNumberRegionRepository.getSignificantCopyNumberRegions(studyId, - projection, pageSize, pageNumber, sortBy, direction); - - if (!projection.equals("ID") && !gisticList.isEmpty()) { - - List gisticToGeneList = significantCopyNumberRegionRepository.getGenesOfRegions(gisticList - .stream().map(Gistic::getGisticRoiId).collect(Collectors.toList())); - - gisticList.forEach(g -> g.setGenes(gisticToGeneList.stream().filter(p -> p.getGisticRoiId() - .equals(g.getGisticRoiId())).collect(Collectors.toList()))); - } - - return gisticList; - } - - @Override - public BaseMeta getMetaSignificantCopyNumberRegions(String studyId) throws StudyNotFoundException { - - studyService.getStudy(studyId); - - return significantCopyNumberRegionRepository.getMetaSignificantCopyNumberRegions(studyId); - } -} diff --git a/src/main/java/org/cbioportal/service/impl/SignificantlyMutatedGeneServiceImpl.java b/src/main/java/org/cbioportal/service/impl/SignificantlyMutatedGeneServiceImpl.java deleted file mode 100644 index e48c8c259fe..00000000000 --- a/src/main/java/org/cbioportal/service/impl/SignificantlyMutatedGeneServiceImpl.java +++ /dev/null @@ -1,40 +0,0 @@ -package org.cbioportal.service.impl; - -import org.cbioportal.model.MutSig; -import org.cbioportal.model.meta.BaseMeta; -import org.cbioportal.persistence.SignificantlyMutatedGeneRepository; -import org.cbioportal.service.SignificantlyMutatedGeneService; -import org.cbioportal.service.StudyService; -import org.cbioportal.service.exception.StudyNotFoundException; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -import java.util.List; - -@Service -public class SignificantlyMutatedGeneServiceImpl implements SignificantlyMutatedGeneService { - - @Autowired - private SignificantlyMutatedGeneRepository significantlyMutatedGeneRepository; - @Autowired - private StudyService studyService; - - @Override - public List getSignificantlyMutatedGenes(String studyId, String projection, Integer pageSize, - Integer pageNumber, String sortBy, String direction) - throws StudyNotFoundException { - - studyService.getStudy(studyId); - - return significantlyMutatedGeneRepository.getSignificantlyMutatedGenes(studyId, projection, pageSize, - pageNumber, sortBy, direction); - } - - @Override - public BaseMeta getMetaSignificantlyMutatedGenes(String studyId) throws StudyNotFoundException { - - studyService.getStudy(studyId); - - return significantlyMutatedGeneRepository.getMetaSignificantlyMutatedGenes(studyId); - } -} diff --git a/src/main/java/org/cbioportal/service/impl/StaticDataTimestampServiceImpl.java b/src/main/java/org/cbioportal/service/impl/StaticDataTimestampServiceImpl.java deleted file mode 100644 index 47ad5e78220..00000000000 --- a/src/main/java/org/cbioportal/service/impl/StaticDataTimestampServiceImpl.java +++ /dev/null @@ -1,48 +0,0 @@ -package org.cbioportal.service.impl; - -import org.cbioportal.model.TableTimestampPair; -import org.cbioportal.service.StaticDataTimestampService; -import org.cbioportal.persistence.StaticDataTimeStampRepository; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - -@Service -public class StaticDataTimestampServiceImpl implements StaticDataTimestampService { - @Autowired - private StaticDataTimeStampRepository staticDataTimeStampRepository; - - @Override - public Map getTimestamps(List tables) { - List timestamps = staticDataTimeStampRepository.getTimestamps(tables); - return timestamps.stream() - .collect(Collectors.toMap( - TableTimestampPair::getTableName, - TableTimestampPair::getUpdateTime)); - } - - @Override - public Map getTimestampsAsDates(List tables) { - List timestamps = staticDataTimeStampRepository.getTimestamps(tables); - return timestamps.stream() - .collect(Collectors.toMap( - TableTimestampPair::getTableName, - (pair) -> toDate(pair.getUpdateTime()))); - } - - private Date toDate(String date) { - try { - return new SimpleDateFormat("yyyy-MM-dd hh:mm:ss.sss").parse(date); - } catch (ParseException ignored) { - return new Date(); - } - } -} - - diff --git a/src/main/java/org/cbioportal/service/impl/StructuralVariantServiceImpl.java b/src/main/java/org/cbioportal/service/impl/StructuralVariantServiceImpl.java deleted file mode 100644 index 07222ad3ee6..00000000000 --- a/src/main/java/org/cbioportal/service/impl/StructuralVariantServiceImpl.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (c) 2018 - 2022 The Hyve B.V. - * This code is licensed under the GNU Affero General Public License (AGPL), - * version 3, or (at your option) any later version. - */ - -/* - * This file is part of cBioPortal. - * - * cBioPortal is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -package org.cbioportal.service.impl; - -import org.cbioportal.model.GeneFilterQuery; -import org.cbioportal.model.StructuralVariantFilterQuery; -import org.cbioportal.model.StructuralVariant; -import org.cbioportal.model.StructuralVariantQuery; -import org.cbioportal.persistence.StructuralVariantRepository; -import org.cbioportal.service.StructuralVariantService; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; -import java.util.List; -import java.util.*; -import java.util.stream.Collectors; -import java.util.stream.Stream; -import org.cbioportal.model.MolecularProfile; -import org.cbioportal.persistence.MolecularProfileRepository; -import org.springframework.util.CollectionUtils; - -@Service -public class StructuralVariantServiceImpl implements StructuralVariantService { - - @Autowired - private StructuralVariantRepository structuralVariantRepository; - - @Override - public List fetchStructuralVariants( - List molecularProfileIds, - List sampleIds, - List entrezGeneIds, - List structuralVariantQueries - ) { - return structuralVariantRepository.fetchStructuralVariants( - molecularProfileIds, sampleIds, entrezGeneIds, structuralVariantQueries - ); - } - - @Override - public List fetchStructuralVariantsByGeneQueries(List molecularProfileIds, - List sampleIds, - List geneQueries) { - - return structuralVariantRepository.fetchStructuralVariantsByGeneQueries( - molecularProfileIds, sampleIds, geneQueries); - } - - @Override - public List fetchStructuralVariantsByStructVarQueries(List molecularProfileIds, - List sampleIds, - List structVarQueries) { - return structuralVariantRepository.fetchStructuralVariantsByStructVarQueries( - molecularProfileIds, sampleIds, structVarQueries); - } - -} diff --git a/src/main/java/org/cbioportal/service/impl/StudyServiceImpl.java b/src/main/java/org/cbioportal/service/impl/StudyServiceImpl.java deleted file mode 100644 index a2209fe38d9..00000000000 --- a/src/main/java/org/cbioportal/service/impl/StudyServiceImpl.java +++ /dev/null @@ -1,138 +0,0 @@ -package org.cbioportal.service.impl; - -import org.cbioportal.model.CancerStudy; -import org.cbioportal.model.CancerStudyTags; -import org.cbioportal.model.TypeOfCancer; -import org.cbioportal.model.meta.BaseMeta; -import org.cbioportal.persistence.StudyRepository; -import org.cbioportal.service.CancerTypeService; -import org.cbioportal.service.ReadPermissionService; -import org.cbioportal.service.StudyService; -import org.cbioportal.service.exception.StudyNotFoundException; -import org.cbioportal.utils.security.AccessLevel; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.security.access.prepost.PostFilter; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.security.core.Authentication; -import org.springframework.stereotype.Service; - -import java.util.ArrayList; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - -@Service -public class StudyServiceImpl implements StudyService { - - @Autowired - private StudyRepository studyRepository; - - @Autowired - private CancerTypeService cancerTypeService; - - @Autowired - private ReadPermissionService readPermissionService; - - @Override - @PostFilter("hasPermission(filterObject,#accessLevel)") - public List getAllStudies(String keyword, String projection, Integer pageSize, Integer pageNumber, - String sortBy, String direction, Authentication authentication, AccessLevel accessLevel) { - - List allStudies = studyRepository.getAllStudies(keyword, projection, pageSize, pageNumber, sortBy, direction); - Map sortedAllStudiesByCancerStudyIdentifier = allStudies.stream().collect(Collectors.toMap(c -> c.getCancerStudyIdentifier(), c -> c, (e1, e2) -> e2, LinkedHashMap::new)); - if (keyword != null && (pageSize == null || allStudies.size() < pageSize)) { - List primarySiteMatchingStudies = findPrimarySiteMatchingStudies(keyword); - for (CancerStudy cancerStudy : primarySiteMatchingStudies) { - if (!sortedAllStudiesByCancerStudyIdentifier.containsKey(cancerStudy.getCancerStudyIdentifier())) { - sortedAllStudiesByCancerStudyIdentifier.put(cancerStudy.getCancerStudyIdentifier(), cancerStudy); - } - if (pageSize != null && sortedAllStudiesByCancerStudyIdentifier.size() == pageSize) { - break; - } - } - } - - // For authenticated portals it is essential to make a new list, such - // that @PostFilter does not taint the list stored in the mybatis - // second-level cache. When making changes to this make sure to copy the - // allStudies list at least for the AUTHENTICATE.equals("true") case - List returnedStudyObjects = sortedAllStudiesByCancerStudyIdentifier.values().stream().collect(Collectors.toList()); - - // When using prop. 'skin.home_page.show_unauthorized_studies' this endpoint - // returns the full list of studies, some of which can be accessed by the user. - readPermissionService.setReadPermission(returnedStudyObjects, authentication); - - return returnedStudyObjects; - } - - @Override - public BaseMeta getMetaStudies(String keyword) { - if (keyword == null) { - return studyRepository.getMetaStudies(keyword); - } - else { - BaseMeta baseMeta = new BaseMeta(); - baseMeta.setTotalCount(getAllStudies(keyword, "SUMMARY", null, null, null, null, null, AccessLevel.READ).size()); - return baseMeta; - } - } - - @Override - public CancerStudy getStudy(String studyId) throws StudyNotFoundException { - - CancerStudy cancerStudy = studyRepository.getStudy(studyId, "DETAILED"); - if (cancerStudy == null) { - throw new StudyNotFoundException(studyId); - } - - return cancerStudy; - } - - @Override - public List fetchStudies(List studyIds, String projection) { - - return studyRepository.fetchStudies(studyIds, projection); - } - - @Override - public BaseMeta fetchMetaStudies(List studyIds) { - - return studyRepository.fetchMetaStudies(studyIds); - } - - @Override - @PreAuthorize("hasPermission(#studyId, 'CancerStudyId', #accessLevel)") - public CancerStudyTags getTags(String studyId, AccessLevel accessLevel) { - - return studyRepository.getTags(studyId); - } - - @Override - public List getTagsForMultipleStudies(List studyIds) { - - return studyRepository.getTagsForMultipleStudies(studyIds); - } - - private List findPrimarySiteMatchingStudies(String keyword) { - - List matchingStudies = new ArrayList<>(); - - List matchingCancerTypes = new ArrayList<>(); - for (Map.Entry entry : cancerTypeService.getPrimarySiteMap().entrySet()) { - if (entry.getValue().getTypeOfCancerId().toLowerCase().contains(keyword.toLowerCase()) || - entry.getValue().getName().toLowerCase().contains(keyword.toLowerCase())) { - matchingCancerTypes.add(entry.getKey()); - } - } - if (!matchingCancerTypes.isEmpty()) { - List allUnfilteredStudies = studyRepository.getAllStudies(null, "SUMMARY", null, null, null, null); - for (CancerStudy cancerStudy : allUnfilteredStudies) { - if (matchingCancerTypes.contains(cancerStudy.getTypeOfCancerId())) { - matchingStudies.add(cancerStudy); - } - } - } - return matchingStudies; - } -} diff --git a/src/main/java/org/cbioportal/service/impl/StudyViewColumnarServiceImpl.java b/src/main/java/org/cbioportal/service/impl/StudyViewColumnarServiceImpl.java deleted file mode 100644 index f827a33411f..00000000000 --- a/src/main/java/org/cbioportal/service/impl/StudyViewColumnarServiceImpl.java +++ /dev/null @@ -1,325 +0,0 @@ -package org.cbioportal.service.impl; - -import org.cbioportal.model.AlterationCountByGene; -import org.cbioportal.model.CaseListDataCount; -import org.cbioportal.model.ClinicalAttribute; -import org.cbioportal.model.ClinicalData; -import org.cbioportal.model.ClinicalDataCount; -import org.cbioportal.model.ClinicalDataCountItem; -import org.cbioportal.model.ClinicalEventTypeCount; -import org.cbioportal.model.CopyNumberCountByGene; -import org.cbioportal.model.GenericAssayDataCountItem; -import org.cbioportal.model.GenomicDataCount; -import org.cbioportal.model.PatientTreatmentReport; -import org.cbioportal.model.GenomicDataCountItem; -import org.cbioportal.model.Sample; -import org.cbioportal.model.SampleTreatmentReport; -import org.cbioportal.model.StudyViewFilterContext; -import org.cbioportal.persistence.StudyViewRepository; -import org.cbioportal.service.StudyViewColumnarService; -import org.cbioportal.service.alteration.AlterationCountByGeneService; -import org.cbioportal.service.exception.StudyNotFoundException; -import org.cbioportal.service.treatment.TreatmentCountReportService; -import org.cbioportal.service.util.StudyViewColumnarServiceUtil; -import org.cbioportal.utils.config.annotation.ConditionalOnProperty; -import org.cbioportal.web.parameter.ClinicalDataType; -import org.cbioportal.web.parameter.CustomSampleIdentifier; -import org.cbioportal.web.parameter.GenericAssayDataBinFilter; -import org.cbioportal.web.parameter.GenericAssayDataFilter; -import org.cbioportal.web.parameter.GenomicDataBinFilter; -import org.cbioportal.web.parameter.GenomicDataFilter; -import org.cbioportal.web.parameter.StudyViewFilter; -import org.cbioportal.web.columnar.util.CustomDataFilterUtil; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.cache.annotation.Cacheable; -import org.springframework.stereotype.Service; - -import static org.cbioportal.web.columnar.util.ClinicalDataXyPlotUtil.combineClinicalDataForXyPlot; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - -@Service -@ConditionalOnProperty(name = "clickhouse_mode", havingValue = "true") -public class StudyViewColumnarServiceImpl implements StudyViewColumnarService { - - - private final StudyViewRepository studyViewRepository; - private final CustomDataFilterUtil customDataFilterUtil; - - private final AlterationCountByGeneService alterationCountByGeneService; - private final TreatmentCountReportService treatmentCountReportService; - - @Autowired - public StudyViewColumnarServiceImpl(StudyViewRepository studyViewRepository, AlterationCountByGeneService alterationCountByGeneService, TreatmentCountReportService treatmentCountReportService, CustomDataFilterUtil customDataFilterUtil) { - this.studyViewRepository = studyViewRepository; - this.alterationCountByGeneService = alterationCountByGeneService; - this.treatmentCountReportService = treatmentCountReportService; - this.customDataFilterUtil = customDataFilterUtil; - } - - @Cacheable( - cacheResolver = "staticRepositoryCacheOneResolver", - condition = "@cacheEnabledConfig.getEnabledClickhouse() && @studyViewFilterUtil.isUnfilteredQuery(#studyViewFilter)" - ) - @Override - public List getFilteredSamples(StudyViewFilter studyViewFilter) { - - return studyViewRepository.getFilteredSamples(createContext(studyViewFilter)); - } - - @Cacheable( - cacheResolver = "staticRepositoryCacheOneResolver", - condition = "@cacheEnabledConfig.getEnabledClickhouse() && @studyViewFilterUtil.isUnfilteredQuery(#studyViewFilter)" - ) - @Override - public List getMutatedGenes(StudyViewFilter studyViewFilter) throws StudyNotFoundException { - return alterationCountByGeneService.getMutatedGenes(createContext(studyViewFilter)); - } - - @Cacheable( - cacheResolver = "staticRepositoryCacheOneResolver", - condition = "@cacheEnabledConfig.getEnabledClickhouse() && @studyViewFilterUtil.isUnfilteredQuery(#studyViewFilter)" - ) - @Override - public List getMolecularProfileSampleCounts(StudyViewFilter studyViewFilter) { - return studyViewRepository.getMolecularProfileSampleCounts(createContext(studyViewFilter)); - } - - @Cacheable( - cacheResolver = "staticRepositoryCacheOneResolver", - condition = "@cacheEnabledConfig.getEnabledClickhouse() && @studyViewFilterUtil.isUnfilteredQuery(#studyViewFilter)" - ) - @Override - public List getClinicalEventTypeCounts(StudyViewFilter studyViewFilter) { - return studyViewRepository.getClinicalEventTypeCounts(createContext(studyViewFilter)); - } - - @Cacheable( - cacheResolver = "staticRepositoryCacheOneResolver", - condition = "@cacheEnabledConfig.getEnabledClickhouse() && @studyViewFilterUtil.isUnfilteredQuery(#studyViewFilter)" - ) - @Override - public PatientTreatmentReport getPatientTreatmentReport(StudyViewFilter studyViewFilter) { - return treatmentCountReportService.getPatientTreatmentReport(createContext(studyViewFilter)); - } - - @Cacheable( - cacheResolver = "staticRepositoryCacheOneResolver", - condition = "@cacheEnabledConfig.getEnabledClickhouse() && @studyViewFilterUtil.isUnfilteredQuery(#studyViewFilter)" - ) - @Override - public SampleTreatmentReport getSampleTreatmentReport(StudyViewFilter studyViewFilter) { - return treatmentCountReportService.getSampleTreatmentReport(createContext(studyViewFilter)); - } - - @Cacheable( - cacheResolver = "staticRepositoryCacheOneResolver", - condition = "@cacheEnabledConfig.getEnabledClickhouse() && @studyViewFilterUtil.isUnfilteredQuery(#studyViewFilter)" - ) - @Override - public List getGenomicDataBinCounts(StudyViewFilter studyViewFilter, List genomicDataBinFilters) { - return generateDataCountItemsFromDataCounts(studyViewRepository.getGenomicDataBinCounts(createContext(studyViewFilter), genomicDataBinFilters)); - } - - @Cacheable( - cacheResolver = "staticRepositoryCacheOneResolver", - condition = "@cacheEnabledConfig.getEnabledClickhouse() && @studyViewFilterUtil.isUnfilteredQuery(#studyViewFilter)" - ) - @Override - public List getGenericAssayDataBinCounts(StudyViewFilter studyViewFilter, List genericAssayDataBinFilters) { - return generateDataCountItemsFromDataCounts(studyViewRepository.getGenericAssayDataBinCounts(createContext(studyViewFilter), genericAssayDataBinFilters)); - } - - public List getCnaGenes(StudyViewFilter studyViewFilter) throws StudyNotFoundException { - return alterationCountByGeneService.getCnaGenes(createContext(studyViewFilter)); - } - - @Cacheable( - cacheResolver = "staticRepositoryCacheOneResolver", - condition = "@cacheEnabledConfig.getEnabledClickhouse() && @studyViewFilterUtil.isUnfilteredQuery(#studyViewFilter)" - ) - @Override - public List getStructuralVariantGenes(StudyViewFilter studyViewFilter) throws StudyNotFoundException { - return alterationCountByGeneService.getStructuralVariantGenes(createContext(studyViewFilter)); - } - - @Cacheable( - cacheResolver = "staticRepositoryCacheOneResolver", - condition = "@cacheEnabledConfig.getEnabledClickhouse() && @studyViewFilterUtil.isUnfilteredQuery(#studyViewFilter)" - ) - @Override - public Map getClinicalAttributeDatatypeMap(StudyViewFilter studyViewFilter) { - return studyViewRepository.getClinicalAttributeDatatypeMap(); - } - - @Cacheable( - cacheResolver = "staticRepositoryCacheOneResolver", - condition = "@cacheEnabledConfig.getEnabledClickhouse() && @studyViewFilterUtil.isUnfilteredQuery(#studyViewFilter)" - ) - @Override - public List getClinicalDataCounts(StudyViewFilter studyViewFilter, List filteredAttributes) { - - var context = createContext(studyViewFilter); - - List involvedCancerStudies = context.involvedCancerStudies(); - - var result = studyViewRepository.getClinicalDataCounts(context, filteredAttributes); - - // normalize data counts so that values like TRUE, True, and true are all merged in one count - result.forEach(item -> item.setCounts(StudyViewColumnarServiceUtil.normalizeDataCounts(item.getCounts()))); - - // attributes may be missing in result set because they have been filtered out - // e.g. if the filtered samples happen to have no SEX data, they will not appear in the list - // even though the inferred value of those attributes is NA - // the following code restores these counts for missing attributes - if (result.size() != filteredAttributes.size()) { - var attributes = getClinicalAttributesForStudies(involvedCancerStudies) - .stream() - .filter(attribute -> filteredAttributes.contains(attribute.getAttrId())) - .toList(); - - Integer filteredSampleCount = studyViewRepository.getFilteredSamplesCount(createContext(studyViewFilter)); - Integer filteredPatientCount = studyViewRepository.getFilteredPatientCount(createContext(studyViewFilter)); - - result = StudyViewColumnarServiceUtil.addClinicalDataCountsForMissingAttributes( - result, - attributes, - filteredSampleCount, - filteredPatientCount - ); - } - - return StudyViewColumnarServiceUtil.mergeClinicalDataCounts(result); - - } - - @Cacheable( - cacheResolver = "staticRepositoryCacheOneResolver", - condition = "@cacheEnabledConfig.getEnabledClickhouse()" - ) - public List getClinicalAttributesForStudies(List studyIds) { - return studyViewRepository.getClinicalAttributesForStudies(studyIds).stream().toList(); - } - - @Cacheable( - cacheResolver = "staticRepositoryCacheOneResolver", - condition = "@cacheEnabledConfig.getEnabledClickhouse() && @studyViewFilterUtil.isUnfilteredQuery(#studyViewFilter)" - ) - @Override - public List getCaseListDataCounts(StudyViewFilter studyViewFilter) { - // the study view merges case lists by type across studies - // type is determined by the suffix of case list name (after study name) - var caseListDataCountsPerStudy = studyViewRepository.getCaseListDataCountsPerStudy(createContext(studyViewFilter)); - return StudyViewColumnarServiceUtil.mergeCaseListCounts(caseListDataCountsPerStudy); - } - - @Cacheable( - cacheResolver = "staticRepositoryCacheOneResolver", - condition = "@cacheEnabledConfig.getEnabledClickhouse() && @studyViewFilterUtil.isUnfilteredQuery(#studyViewFilter)" - ) - @Override - public List getPatientClinicalData(StudyViewFilter studyViewFilter, List attributeIds) { - return studyViewRepository.getPatientClinicalData(createContext(studyViewFilter), attributeIds); - } - - @Cacheable( - cacheResolver = "staticRepositoryCacheOneResolver", - condition = "@cacheEnabledConfig.getEnabledClickhouse() && @studyViewFilterUtil.isUnfilteredQuery(#studyViewFilter)" - ) - @Override - public List getSampleClinicalData(StudyViewFilter studyViewFilter, List attributeIds) { - return studyViewRepository.getSampleClinicalData(createContext(studyViewFilter), attributeIds); - } - - @Cacheable( - cacheResolver = "staticRepositoryCacheOneResolver", - condition = "@cacheEnabledConfig.getEnabledClickhouse() && @studyViewFilterUtil.isUnfilteredQuery(#studyViewFilter)" - ) - @Override - public List getCNACountsByGeneSpecific(StudyViewFilter studyViewFilter, List genomicDataFilters) { - return studyViewRepository.getCNACounts(createContext(studyViewFilter), genomicDataFilters); - } - - @Cacheable( - cacheResolver = "staticRepositoryCacheOneResolver", - condition = "@cacheEnabledConfig.getEnabledClickhouse() && @studyViewFilterUtil.isUnfilteredQuery(#studyViewFilter)" - ) - @Override - public List getGenericAssayDataCounts(StudyViewFilter studyViewFilter, List genericAssayDataFilters) { - return studyViewRepository.getGenericAssayDataCounts(createContext(studyViewFilter), genericAssayDataFilters); - } - - @Cacheable( - cacheResolver = "staticRepositoryCacheOneResolver", - condition = "@cacheEnabledConfig.getEnabledClickhouse() && @studyViewFilterUtil.isUnfilteredQuery(#studyViewFilter)" - ) - @Override - public List getMutationCountsByGeneSpecific(StudyViewFilter studyViewFilter, List genomicDataFilters) { - List genomicDataCountItemList = new ArrayList<>(); - for (GenomicDataFilter genomicDataFilter : genomicDataFilters) { - Map counts = studyViewRepository.getMutationCounts(createContext(studyViewFilter), genomicDataFilter); - genomicDataCountItemList.add(StudyViewColumnarServiceUtil.createGenomicDataCountItemFromMutationCounts(genomicDataFilter, counts)); - } - return genomicDataCountItemList; - } - - @Cacheable( - cacheResolver = "staticRepositoryCacheOneResolver", - condition = "@cacheEnabledConfig.getEnabledClickhouse() && @studyViewFilterUtil.isUnfilteredQuery(#studyViewFilter)" - ) - @Override - public List getMutationTypeCountsByGeneSpecific(StudyViewFilter studyViewFilter, List genomicDataFilters) { - return studyViewRepository.getMutationCountsByType(createContext(studyViewFilter), genomicDataFilters); - } - - @Cacheable( - cacheResolver = "staticRepositoryCacheOneResolver", - condition = "@cacheEnabledConfig.getEnabledClickhouse() && @studyViewFilterUtil.isUnfilteredQuery(#studyViewFilter)" - ) - @Override - public List fetchClinicalDataForXyPlot( - StudyViewFilter studyViewFilter, - List attributeIds, - boolean shouldFilterNonEmptyClinicalData - ) { - List sampleClinicalDataList = this.getSampleClinicalData(studyViewFilter, attributeIds); - List patientClinicalDataList = this.getPatientClinicalData(studyViewFilter, attributeIds); - List samples = Collections.emptyList(); - - if (!patientClinicalDataList.isEmpty()) { - // fetch samples for the given study view filter. - // we need this to construct the complete patient to sample map. - samples = this.getFilteredSamples(studyViewFilter); - } - - return combineClinicalDataForXyPlot( - sampleClinicalDataList, - patientClinicalDataList, - samples, - shouldFilterNonEmptyClinicalData - ); - } - - private StudyViewFilterContext createContext(StudyViewFilter studyViewFilter) { - List customSampleIdentifiers = customDataFilterUtil.extractCustomDataSamples(studyViewFilter); - List involvedCancerStudies = customDataFilterUtil.extractInvolvedCancerStudies(studyViewFilter); - return new StudyViewFilterContext(studyViewFilter, customSampleIdentifiers, involvedCancerStudies); - } - - private List generateDataCountItemsFromDataCounts(List dataCounts) { - return dataCounts.stream().collect(Collectors.groupingBy(ClinicalDataCount::getAttributeId)) - .entrySet().parallelStream().map(e -> { - ClinicalDataCountItem item = new ClinicalDataCountItem(); - item.setAttributeId(e.getKey()); - item.setCounts(StudyViewColumnarServiceUtil.normalizeDataCounts(e.getValue())); - return item; - }).toList(); - } - - - -} diff --git a/src/main/java/org/cbioportal/service/impl/StudyViewServiceImpl.java b/src/main/java/org/cbioportal/service/impl/StudyViewServiceImpl.java deleted file mode 100644 index 67276a42b38..00000000000 --- a/src/main/java/org/cbioportal/service/impl/StudyViewServiceImpl.java +++ /dev/null @@ -1,503 +0,0 @@ -package org.cbioportal.service.impl; - -import org.apache.commons.collections4.map.MultiKeyMap; -import org.apache.commons.lang3.StringUtils; -import org.apache.commons.math3.util.Pair; -import org.cbioportal.model.AlterationCountByGene; -import org.cbioportal.model.AlterationCountByStructuralVariant; -import org.cbioportal.model.AlterationFilter; -import org.cbioportal.model.CNA; -import org.cbioportal.model.CopyNumberCountByGene; -import org.cbioportal.model.Gene; -import org.cbioportal.model.GeneMolecularData; -import org.cbioportal.model.GenePanelData; -import org.cbioportal.model.GenericAssayData; -import org.cbioportal.model.GenericAssayDataCount; -import org.cbioportal.model.GenericAssayDataCountItem; -import org.cbioportal.model.GenomicDataCount; -import org.cbioportal.model.GenomicDataCountItem; -import org.cbioportal.model.Gistic; -import org.cbioportal.model.MolecularProfile; -import org.cbioportal.model.MolecularProfileCaseIdentifier; -import org.cbioportal.model.MutSig; -import org.cbioportal.model.MutationFilterOption; -import org.cbioportal.model.util.Select; -import org.cbioportal.service.AlterationCountService; -import org.cbioportal.service.GenePanelService; -import org.cbioportal.service.GeneService; -import org.cbioportal.service.GenericAssayService; -import org.cbioportal.service.MolecularDataService; -import org.cbioportal.service.MolecularProfileService; -import org.cbioportal.service.MutationService; -import org.cbioportal.service.SignificantCopyNumberRegionService; -import org.cbioportal.service.SignificantlyMutatedGeneService; -import org.cbioportal.service.StudyViewService; -import org.cbioportal.service.exception.MolecularProfileNotFoundException; -import org.cbioportal.service.exception.StudyNotFoundException; -import org.cbioportal.service.util.MolecularProfileUtil; -import org.cbioportal.web.parameter.GeneIdType; -import org.cbioportal.web.parameter.Projection; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.Set; -import java.util.function.Function; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -@Service -public class StudyViewServiceImpl implements StudyViewService { - private static final List CNA_TYPES_AMP_AND_HOMDEL = Collections.unmodifiableList(Arrays.asList(CNA.AMP, CNA.HOMDEL)); - private final MolecularProfileService molecularProfileService; - private final GenePanelService genePanelService; - private final MolecularProfileUtil molecularProfileUtil; - private final AlterationCountService alterationCountService; - private final SignificantlyMutatedGeneService significantlyMutatedGeneService; - private final SignificantCopyNumberRegionService significantCopyNumberRegionService; - private final GenericAssayService genericAssayService; - private final GeneService geneService; - private final MolecularDataService molecularDataService; - private final MutationService mutationService; - - // constructor dependency injections - @Autowired - public StudyViewServiceImpl(MolecularProfileService molecularProfileService, GenePanelService genePanelService, MolecularProfileUtil molecularProfileUtil, AlterationCountService alterationCountService, SignificantlyMutatedGeneService significantlyMutatedGeneService, SignificantCopyNumberRegionService significantCopyNumberRegionService, GenericAssayService genericAssayService, GeneService geneService, MolecularDataService molecularDataService, MutationService mutationService) { - this.molecularProfileService = molecularProfileService; - this.genePanelService = genePanelService; - this.molecularProfileUtil = molecularProfileUtil; - this.alterationCountService = alterationCountService; - this.significantlyMutatedGeneService = significantlyMutatedGeneService; - this.significantCopyNumberRegionService = significantCopyNumberRegionService; - this.genericAssayService = genericAssayService; - this.geneService = geneService; - this.molecularDataService = molecularDataService; - this.mutationService = mutationService; - } - - @Override - public List getGenomicDataCounts(List studyIds, List sampleIds) { - List molecularProfileSampleIdentifiers = - molecularProfileService.getMolecularProfileCaseIdentifiers(studyIds, sampleIds); - - - // first get all molecular profiles - List molecularProfiles = molecularProfileService - .getMolecularProfilesInStudies(new ArrayList<>(new HashSet<>(studyIds)), Projection.SUMMARY.name()); - Map molecularProfileMap = molecularProfiles - .stream() - .collect(Collectors.toMap(MolecularProfile::getStableId, Function.identity())); - - // get gene panels - Map molecularProfileCaseCountSet = genePanelService - .fetchGenePanelDataInMultipleMolecularProfiles(molecularProfileSampleIdentifiers) - .stream() - .filter(GenePanelData::getProfiled) - .collect(Collectors.groupingBy(GenePanelData::getMolecularProfileId)) - .entrySet() - .stream() - .collect(Collectors.toMap(Map.Entry::getKey, entry -> (int) entry.getValue().stream().map(d -> molecularProfileMap.get(entry.getKey()).getPatientLevel() ? d.getPatientId() : d.getSampleId()).distinct().count())); - - return molecularProfileUtil - .categorizeMolecularProfilesByStableIdSuffixes(molecularProfiles) - .entrySet() - .stream() - .map(entry -> { - GenomicDataCount dataCount = new GenomicDataCount(); - dataCount.setValue(entry.getKey()); - - Integer count = entry - .getValue() - .stream() - .mapToInt(molecularProfile -> molecularProfileCaseCountSet.getOrDefault(molecularProfile.getStableId(), 0)) - .sum(); - - dataCount.setCount(count); - dataCount.setLabel(entry.getValue().get(0).getName()); - return dataCount; - }) - .filter(dataCount -> dataCount.getCount() > 0) - .toList(); - } - - @Override - public List getMutationAlterationCountByGenes(List studyIds, - List sampleIds, - AlterationFilter alterationFilter) - throws StudyNotFoundException { - List caseIdentifiers = - molecularProfileService.getFirstMutationProfileCaseIdentifiers(studyIds, sampleIds); - List alterationCountByGenes = alterationCountService.getSampleMutationGeneCounts( - caseIdentifiers, - Select.all(), - true, - false, - alterationFilter).getFirst(); - annotateDataWithQValue(studyIds, alterationCountByGenes); - return alterationCountByGenes; - } - - @Override - public List getMutationCountsByGeneSpecific(List studyIds, - List sampleIds, - List> genomicDataFilters, - AlterationFilter alterationFilter) { - List caseIdentifiers = - molecularProfileService.getMutationProfileCaseIdentifiers(studyIds, sampleIds); - - Set hugoGeneSymbols = genomicDataFilters.stream().map(Pair::getKey) - .collect(Collectors.toSet()); - - List entrezGeneIds = geneService - .fetchGenes(new ArrayList<>(hugoGeneSymbols), GeneIdType.HUGO_GENE_SYMBOL.name(), - Projection.SUMMARY.name()) - .stream() - .map(Gene::getEntrezGeneId) - .toList(); - - Pair, Long> alterationCountsWithProfiledTotal = alterationCountService.getSampleMutationGeneCounts( - caseIdentifiers, - Select.byValues(entrezGeneIds), - true, - false, - alterationFilter); - - List alterationCountByGenes = alterationCountsWithProfiledTotal.getFirst(); - Long totalProfiledCases = alterationCountsWithProfiledTotal.getSecond(); - - return genomicDataFilters - .stream() - .flatMap(genomicDataFilter -> { - GenomicDataCountItem genomicDataCountItem = new GenomicDataCountItem(); - String hugoGeneSymbol = genomicDataFilter.getKey(); - String profileType = genomicDataFilter.getValue(); - genomicDataCountItem.setHugoGeneSymbol(hugoGeneSymbol); - genomicDataCountItem.setProfileType(profileType); - - Optional filteredAlterationCount = alterationCountByGenes - .stream() - .filter(g -> StringUtils.isNotEmpty(g.getHugoGeneSymbol()) && g.getHugoGeneSymbol().equals(hugoGeneSymbol)) - .findFirst(); - - int totalCount = sampleIds.size(); - int mutatedCount = 0; - int profiledCount = Math.toIntExact(totalProfiledCases); - - if(filteredAlterationCount.isPresent()) { - mutatedCount = filteredAlterationCount.get().getNumberOfAlteredCases(); - profiledCount = filteredAlterationCount.get().getNumberOfProfiledCases(); - } - - List genomicDataCounts = new ArrayList<>(); - - GenomicDataCount genomicDataCountMutated = new GenomicDataCount(); - genomicDataCountMutated.setLabel(MutationFilterOption.MUTATED.getSelectedOption()); - genomicDataCountMutated.setValue(MutationFilterOption.MUTATED.name()); - genomicDataCountMutated.setCount(mutatedCount); - genomicDataCountMutated.setUniqueCount(mutatedCount); - if (genomicDataCountMutated.getCount() > 0) genomicDataCounts.add(genomicDataCountMutated); - - GenomicDataCount genomicDataCountWildType = new GenomicDataCount(); - genomicDataCountWildType.setLabel(MutationFilterOption.NOT_MUTATED.getSelectedOption()); - genomicDataCountWildType.setValue(MutationFilterOption.NOT_MUTATED.name()); - genomicDataCountWildType.setCount(profiledCount - mutatedCount); - genomicDataCountWildType.setUniqueCount(profiledCount - mutatedCount); - if (genomicDataCountWildType.getCount() > 0) genomicDataCounts.add(genomicDataCountWildType); - - GenomicDataCount genomicDataCountNotProfiled = new GenomicDataCount(); - genomicDataCountNotProfiled.setLabel(MutationFilterOption.NOT_PROFILED.getSelectedOption()); - genomicDataCountNotProfiled.setValue(MutationFilterOption.NOT_PROFILED.name()); - genomicDataCountNotProfiled.setCount(totalCount - profiledCount); - genomicDataCountNotProfiled.setUniqueCount(totalCount - profiledCount); - if (genomicDataCountNotProfiled.getCount() > 0) genomicDataCounts.add(genomicDataCountNotProfiled); - - genomicDataCountItem.setCounts(genomicDataCounts); - - return Stream.of(genomicDataCountItem); - }).toList(); - } - - @Override - public List getMutationTypeCountsByGeneSpecific(List studyIds, - List sampleIds, - List> genomicDataFilters) { - Set hugoGeneSymbols = genomicDataFilters.stream().map(Pair::getKey) - .collect(Collectors.toSet()); - - Map geneSymbolIdMap = geneService - .fetchGenes(new ArrayList<>(hugoGeneSymbols), GeneIdType.HUGO_GENE_SYMBOL.name(), - Projection.SUMMARY.name()) - .stream().collect(Collectors.toMap(Gene::getHugoGeneSymbol, Gene::getEntrezGeneId)); - - return genomicDataFilters - .stream() - .flatMap(genomicDataFilter -> { - String hugoGeneSymbol = genomicDataFilter.getKey(); - String profileType = genomicDataFilter.getValue(); - - List stableIds = Collections.singletonList(geneSymbolIdMap.get(hugoGeneSymbol)); - - Pair, List> sampleAndProfileIds = getMappedSampleAndProfileIds(studyIds, sampleIds, profileType); - List mappedSampleIds = sampleAndProfileIds.getFirst(); - List mappedProfileIds = sampleAndProfileIds.getSecond(); - - if (mappedSampleIds.isEmpty() || mappedProfileIds.isEmpty()) { - return Stream.of(); - } - - GenomicDataCountItem genomicDataCountItem = mutationService.getMutationCountsByType(mappedProfileIds, - mappedSampleIds, stableIds, profileType); - - return Stream.ofNullable(genomicDataCountItem); - }).toList(); - } - - @Override - public List getStructuralVariantAlterationCountByGenes(List studyIds, - List sampleIds, - AlterationFilter alterationFilter) - throws StudyNotFoundException { - List caseIdentifiers = - molecularProfileService.getFirstStructuralVariantProfileCaseIdentifiers(studyIds, sampleIds); - List alterationCountByGenes = alterationCountService.getSampleStructuralVariantGeneCounts( - caseIdentifiers, - Select.all(), - true, - false, - alterationFilter).getFirst(); - annotateDataWithQValue(studyIds, alterationCountByGenes); - return alterationCountByGenes; - } - - @Override - public List getStructuralVariantAlterationCounts(List studyIds, - List sampleIds, - AlterationFilter annotationFilters) { - List caseIdentifiers = - molecularProfileService.getFirstStructuralVariantProfileCaseIdentifiers(studyIds, sampleIds); - return alterationCountService.getSampleStructuralVariantCounts(caseIdentifiers, - true, - false, - annotationFilters).getFirst(); - } - - private void annotateDataWithQValue(List studyIds, List alterationCountByGenes) - throws StudyNotFoundException { - Set distinctStudyIds = new HashSet<>(studyIds); - if (!alterationCountByGenes.isEmpty() && distinctStudyIds.size() == 1) { - Map mutSigMap = - significantlyMutatedGeneService.getSignificantlyMutatedGenes( - studyIds.get(0), - Projection.SUMMARY.name(), - null, - null, - null, - null) - .stream() - .collect(Collectors.toMap(MutSig::getEntrezGeneId, Function.identity())); - alterationCountByGenes.forEach(r -> { - if (mutSigMap.containsKey(r.getEntrezGeneId())) { - r.setqValue(mutSigMap.get(r.getEntrezGeneId()).getqValue()); - } - }); - } - } - - @Override - public List getCNAAlterationCountByGenes(List studyIds, - List sampleIds, - AlterationFilter alterationFilter) - throws StudyNotFoundException { - List caseIdentifiers = - molecularProfileService.getFirstDiscreteCNAProfileCaseIdentifiers(studyIds, sampleIds); - - List copyNumberCountByGenes = alterationCountService.getSampleCnaGeneCounts( - caseIdentifiers, - Select.all(), - true, - false, - alterationFilter).getFirst(); - Set distinctStudyIds = new HashSet<>(studyIds); - if (distinctStudyIds.size() == 1 && !copyNumberCountByGenes.isEmpty()) { - List gisticList = significantCopyNumberRegionService.getSignificantCopyNumberRegions( - studyIds.get(0), - Projection.SUMMARY.name(), - null, - null, - null, - null); - MultiKeyMap gisticMap = new MultiKeyMap(); - gisticList.forEach(g -> g.getGenes().forEach(gene -> { - Gistic gistic = (Gistic) gisticMap.get(gene.getEntrezGeneId(), g.getAmp()); - if (gistic == null || g.getqValue().compareTo(gistic.getqValue()) < 0) { - gisticMap.put(gene.getEntrezGeneId(), g.getAmp(), g); - } - })); - copyNumberCountByGenes.forEach(r -> { - if (gisticMap.containsKey(r.getEntrezGeneId(), r.getAlteration().equals(2))) { - r.setqValue(((Gistic) gisticMap.get(r.getEntrezGeneId(), r.getAlteration().equals(2))).getqValue()); - } - }); - } - return copyNumberCountByGenes; - } - - @Override - public List getCNAAlterationCountsByGeneSpecific(List studyIds, - List sampleIds, - List> genomicDataFilters) { - Set hugoGeneSymbols = genomicDataFilters.stream().map(Pair::getKey) - .collect(Collectors.toSet()); - - Map geneSymbolIdMap = geneService - .fetchGenes(new ArrayList<>(hugoGeneSymbols), GeneIdType.HUGO_GENE_SYMBOL.name(), - Projection.SUMMARY.name()) - .stream().collect(Collectors.toMap(Gene::getHugoGeneSymbol, Gene::getEntrezGeneId)); - - return genomicDataFilters - .stream() - .flatMap(genomicDataFilter -> { - GenomicDataCountItem genomicDataCountItem = new GenomicDataCountItem(); - String hugoGeneSymbol = genomicDataFilter.getKey(); - String profileType = genomicDataFilter.getValue(); - genomicDataCountItem.setHugoGeneSymbol(hugoGeneSymbol); - genomicDataCountItem.setProfileType(profileType); - - List stableIds = List.of(geneSymbolIdMap.get(hugoGeneSymbol).toString()); - - Pair, List> sampleAndProfileIds = getMappedSampleAndProfileIds(studyIds, sampleIds, profileType); - List mappedSampleIds = sampleAndProfileIds.getFirst(); - List mappedProfileIds = sampleAndProfileIds.getSecond(); - - if (mappedSampleIds.isEmpty()) { - return Stream.of(); - } - - List geneMolecularDataList = molecularDataService.getMolecularDataInMultipleMolecularProfiles(mappedProfileIds, mappedSampleIds, - stableIds.stream().map(Integer::parseInt).toList(), Projection.SUMMARY.name()); - - List genomicDataCounts = geneMolecularDataList - .stream() - .filter(g -> StringUtils.isNotEmpty(g.getValue()) && !g.getValue().equals("NA")) - .collect(Collectors.groupingBy(GeneMolecularData::getValue)) - .entrySet() - .stream() - .map(entry -> { - Integer alteration = Integer.valueOf(entry.getKey()); - List geneMolecularData = entry.getValue(); - int count = geneMolecularData.size(); - - String label = CNA.getByCode(alteration.shortValue()).getDescription(); - - GenomicDataCount genomicDataCount = new GenomicDataCount(); - genomicDataCount.setLabel(label); - genomicDataCount.setValue(String.valueOf(alteration)); - genomicDataCount.setCount(count); - - return genomicDataCount; - }).collect(Collectors.toList()); - - int totalCount = genomicDataCounts.stream().mapToInt(GenomicDataCount::getCount).sum(); - int naCount = sampleIds.size() - totalCount; - - if (naCount > 0) { - GenomicDataCount genomicDataCount = new GenomicDataCount(); - genomicDataCount.setLabel("NA"); - genomicDataCount.setValue("NA"); - genomicDataCount.setCount(naCount); - genomicDataCounts.add(genomicDataCount); - } - - genomicDataCountItem.setCounts(genomicDataCounts); - return Stream.of(genomicDataCountItem); - }).toList(); - } - - @Override - public List fetchGenericAssayDataCounts(List sampleIds, List studyIds, - List stableIds, List profileTypes) { - if (stableIds.isEmpty()) { - return new ArrayList<>(); - } - - List data = profileTypes.stream().flatMap(profileType -> { - Pair, List> sampleAndProfileIds = getMappedSampleAndProfileIds(studyIds, sampleIds, profileType); - List mappedSampleIds = sampleAndProfileIds.getFirst(); - List mappedProfileIds = sampleAndProfileIds.getSecond(); - - try { - return genericAssayService.fetchGenericAssayData(mappedProfileIds, mappedSampleIds, stableIds, Projection.SUMMARY.name()).stream(); - } catch (MolecularProfileNotFoundException e) { - return new ArrayList().stream(); - } - }).toList(); - - return data - .stream() - .filter(g -> StringUtils.isNotEmpty(g.getValue()) && !g.getValue().equals("NA")) - .collect(Collectors.groupingBy(GenericAssayData::getGenericAssayStableId)) - .entrySet() - .stream() - .map(entry -> { - int totalCount = entry.getValue().size(); - int naCount = sampleIds.size() - totalCount; - List counts = entry.getValue() - .stream() - .collect(Collectors.groupingBy(GenericAssayData::getValue)) - .entrySet() - .stream() - .map(datum -> { - GenericAssayDataCount dataCount = new GenericAssayDataCount(); - dataCount.setValue(datum.getKey()); - dataCount.setCount(datum.getValue().size()); - return dataCount; - }).collect(Collectors.toList()); - - if (naCount > 0) { - GenericAssayDataCount dataCount = new GenericAssayDataCount(); - dataCount.setValue("NA"); - dataCount.setCount(naCount); - counts.add(dataCount); - } - - GenericAssayDataCountItem genericAssayDataCountItem = new GenericAssayDataCountItem(); - genericAssayDataCountItem.setStableId(entry.getKey()); - genericAssayDataCountItem.setCounts(counts); - return genericAssayDataCountItem; - }).toList(); - } - - private Pair, List> getMappedSampleAndProfileIds(List studyIds, List sampleIds, String profileType) { - List molecularProfiles = molecularProfileService.getMolecularProfilesInStudies(studyIds, - Projection.SUMMARY.name()); - - Map> molecularProfileMap = molecularProfileUtil - .categorizeMolecularProfilesByStableIdSuffixes(molecularProfiles); - - Map studyIdToMolecularProfileIdMap = molecularProfileMap - .getOrDefault(profileType, new ArrayList()).stream() - .collect(Collectors.toMap(MolecularProfile::getCancerStudyIdentifier, - MolecularProfile::getStableId)); - - List mappedSampleIds = new ArrayList<>(); - List mappedProfileIds = new ArrayList<>(); - - for (int i = 0; i < sampleIds.size(); i++) { - String studyId = studyIds.get(i); - - // add samples only if the studyId is existed in the map - if (studyIdToMolecularProfileIdMap.containsKey(studyId)) { - mappedSampleIds.add(sampleIds.get(i)); - mappedProfileIds.add(studyIdToMolecularProfileIdMap.get(studyId)); - } - } - - return new Pair<>(mappedSampleIds, mappedProfileIds); - } -} diff --git a/src/main/java/org/cbioportal/service/impl/TreatmentServiceImpl.java b/src/main/java/org/cbioportal/service/impl/TreatmentServiceImpl.java deleted file mode 100644 index 75784a01c15..00000000000 --- a/src/main/java/org/cbioportal/service/impl/TreatmentServiceImpl.java +++ /dev/null @@ -1,198 +0,0 @@ -package org.cbioportal.service.impl; - -import org.apache.commons.lang3.tuple.ImmutablePair; -import org.apache.commons.lang3.tuple.Pair; -import org.cbioportal.model.*; -import org.cbioportal.persistence.TreatmentRepository; -import org.cbioportal.service.TreatmentService; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -import java.util.*; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -@Service -public class TreatmentServiceImpl implements TreatmentService { - @Autowired - TreatmentRepository treatmentRepository; - - private Pair, List> filterIds(List sampleIds, List studyIds, ClinicalEventKeyCode key) { - if (sampleIds == null || studyIds == null || sampleIds.size() != studyIds.size()) { - return new ImmutablePair<>(sampleIds, studyIds); - } - Set studiesWithTreatments = studyIds.stream() - .distinct() - .filter(studyId -> treatmentRepository.hasTreatmentData(Collections.singletonList(studyId), key)) - .collect(Collectors.toSet()); - - ArrayList filteredSampleIds = new ArrayList<>(); - ArrayList filteredStudyIds = new ArrayList<>(); - for (int i = 0; i < sampleIds.size(); i++) { - String studyId = studyIds.get(i); - String sampleId = sampleIds.get(i); - if (studiesWithTreatments.contains(studyId)) { - filteredSampleIds.add(sampleId); - filteredStudyIds.add(studyId); - } - } - return new ImmutablePair<>(filteredSampleIds, filteredStudyIds); - } - - @Override - public List getAllSampleTreatmentRows(List sampleIds, List studyIds, ClinicalEventKeyCode key) { - Pair, List> filteredIds = filterIds(sampleIds, studyIds, key); - sampleIds = filteredIds.getLeft(); - studyIds = filteredIds.getRight(); - - Map> samplesByPatient = - treatmentRepository.getSamplesByPatientId(sampleIds, studyIds); - Map> treatmentsByPatient = - treatmentRepository.getTreatmentsByPatientId(sampleIds, studyIds, key); - - Stream rows = samplesByPatient.keySet().stream() - .flatMap(patientId -> getSampleTreatmentRowsForPatient(patientId, samplesByPatient, treatmentsByPatient)) - .filter(row -> row.getCount() != 0); - return flattenRows(rows); - } - - private Stream getSampleTreatmentRowsForPatient( - String patientId, - Map> samplesByPatient, - Map> treatmentsByPatient - ) { - List treatments = treatmentsByPatient.getOrDefault(patientId, new ArrayList<>()); - List samples = samplesByPatient.get(patientId); - - Map rows = new HashMap<>(); - - for (Treatment treatment : treatments) { - TreatmentRowTriplet triplet; - - if (!rows.containsKey(treatment.getTreatment())) { - triplet = new TreatmentRowTriplet(samples, treatment.getTreatment()); - rows.put(treatment.getTreatment(), triplet); - } else { - triplet = rows.get(treatment.getTreatment()); - } - - triplet.moveSamplesToPost(treatment); - } - - return rows.values().stream().flatMap(TreatmentRowTriplet::toRows); - } - - private List flattenRows(Stream rows) { - Map uniqueRows = new HashMap<>(); - rows.forEach(rowToAdd -> { - if (uniqueRows.containsKey(rowToAdd.key())) { - uniqueRows.get(rowToAdd.key()).add(rowToAdd); - } else { - uniqueRows.put(rowToAdd.key(), rowToAdd); - } - }); - - return new ArrayList<>(uniqueRows.values()); - } - - - /** - * For a given treatment, you can have samples that are taken - * before (pre), after (post), or that don't have a date (unknown) - * - * This class accepts an initial list of samples and a treatment. - * At the start, all samples are considered pre, as there hasn't been - * any treatment start / stop times. - * - * You then call moveSamplesToPost on this with a series of matching - * treatments. Each call will move samples taken - */ - private static class TreatmentRowTriplet { - private final Set pre, post; - private final String treatment; - - TreatmentRowTriplet(List samples, String treatment) { - this.treatment = treatment; - post = new HashSet<>(); - pre = samples.stream() - .filter(s -> s.getTimeTaken() != null) - .collect(Collectors.toSet()); - } - - /** - * Moves any samples marked as pre that were taken after the treatment - * started to post. - * - * @param treatment a treatment with a start value. It is assumed that - * the treatment matches the treatment stored in this triplet - */ - void moveSamplesToPost(Treatment treatment) { - for (Iterator iterator = pre.iterator(); iterator.hasNext(); ) { - ClinicalEventSample clinicalEventSample = iterator.next(); - // edge case: is a sample taken the same day a treatment starts pre or post? - // We're saying pre here - if (clinicalEventSample.getTimeTaken() > treatment.getStart()) { - iterator.remove(); - post.add(clinicalEventSample); - } - } - } - - Stream toRows() { - return Stream.of( - new SampleTreatmentRow(TemporalRelation.Pre, treatment, pre.size(), pre), - new SampleTreatmentRow(TemporalRelation.Post, treatment, post.size(), post) - // We made the decision to filter out unknown rows. I'm leaving this line of code - // to document this decision. - // new SampleTreatmentRow(TemporalRelation.Unknown, treatment, unknown.size(), unknown) - ); - } - } - @Override - public List getAllPatientTreatmentRows( - List sampleIds, List studyIds, ClinicalEventKeyCode key - ) { - Pair, List> filteredIds = filterIds(sampleIds, studyIds, key); - sampleIds = filteredIds.getLeft(); - studyIds = filteredIds.getRight(); - - Map> samplesByPatient = treatmentRepository - .getShallowSamplesByPatientId(sampleIds, studyIds); - - Map> treatmentSet = treatmentRepository.getTreatments(sampleIds, studyIds, key) - .stream() - .collect(Collectors.groupingBy(Treatment::getTreatment)); - - /* - This logic transforms treatmentSet to list of PatientTreatmentRow. transformation steps: - - key in treatmentSet is going to be treatment - - get all unique patient ids -> this is going to give count - - get all clinicalEventSamples using above unique patient ids - */ - return treatmentSet.entrySet() - .stream() - .map(entry -> { - String treatment = entry.getKey(); - Set patientIds = entry.getValue().stream().map(Treatment::getPatientId).collect(Collectors.toSet()); - Set clinicalEventSamples = patientIds - .stream() - .flatMap(patientId -> samplesByPatient.getOrDefault(patientId, new ArrayList<>()).stream()) - .collect(Collectors.toSet()); - return new PatientTreatmentRow(treatment, patientIds.size(), clinicalEventSamples); - }) - .collect(Collectors.toList()); - } - - @Override - public Boolean containsTreatmentData(List studies, ClinicalEventKeyCode key) { - return treatmentRepository.hasTreatmentData(studies, key); - } - - @Override - public Boolean containsSampleTreatmentData(List studyIds, ClinicalEventKeyCode key) { - studyIds = studyIds.stream() - .filter(studyId -> treatmentRepository.hasTreatmentData(Collections.singletonList(studyId), key)) - .collect(Collectors.toList()); - return studyIds.size() > 0 && treatmentRepository.hasSampleTimelineData(studyIds); - } -} diff --git a/src/main/java/org/cbioportal/service/impl/UnauthDataAccessTokenServiceImpl.java b/src/main/java/org/cbioportal/service/impl/UnauthDataAccessTokenServiceImpl.java deleted file mode 100644 index 11cb8749223..00000000000 --- a/src/main/java/org/cbioportal/service/impl/UnauthDataAccessTokenServiceImpl.java +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright (c) 2018 Memorial Sloan-Kettering Cancer Center. - * - * This library is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS - * FOR A PARTICULAR PURPOSE. The software and documentation provided hereunder - * is on an "as is" basis, and Memorial Sloan-Kettering Cancer Center has no - * obligations to provide maintenance, support, updates, enhancements or - * modifications. In no event shall Memorial Sloan-Kettering Cancer Center be - * liable to any party for direct, indirect, special, incidental or - * consequential damages, including lost profits, arising out of the use of this - * software and its documentation, even if Memorial Sloan-Kettering Cancer - * Center has been advised of the possibility of such damage. - */ - -/* - * This file is part of cBioPortal. - * - * cBioPortal is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . -*/ - -package org.cbioportal.service.impl; - -import org.cbioportal.model.DataAccessToken; -import org.cbioportal.service.DataAccessTokenService; -import org.cbioportal.utils.config.annotation.ConditionalOnProperty; -import org.springframework.security.access.AccessDeniedException; -import org.springframework.security.core.Authentication; - -import java.util.Date; -import java.util.List; -import org.springframework.stereotype.Component; - - -/** - * - * @author ochoaa - */ -@Component -@ConditionalOnProperty(name = "dat.method", havingValue = "none", matchIfMissing = true) -public class UnauthDataAccessTokenServiceImpl implements DataAccessTokenService { - - @Override - public DataAccessToken createDataAccessToken(String username) { - throw new AccessDeniedException("Data Access Tokens are not supported for unauthenticated portals."); - } - - @Override - public List getAllDataAccessTokens(String username) { - throw new AccessDeniedException("Data Access Tokens are not supported for unauthenticated portals."); - } - - @Override - public DataAccessToken getDataAccessToken(String username) { - throw new AccessDeniedException("Data Access Tokens are not supported for unauthenticated portals."); - } - - @Override - public DataAccessToken getDataAccessTokenInfo(String token) { - throw new AccessDeniedException("Data Access Tokens are not supported for unauthenticated portals."); - } - - @Override - public void revokeAllDataAccessTokens(String username) { - throw new AccessDeniedException("Data Access Tokens are not supported for unauthenticated portals."); - } - - @Override - public void revokeDataAccessToken(String token) { - throw new AccessDeniedException("Data Access Tokens are not supported for unauthenticated portals."); - } - - @Override - public String getUsername(String token) { - throw new AccessDeniedException("Data Access Tokens are not supported for unauthenticated portals."); - } - - @Override - public Date getExpiration(String token) { - throw new AccessDeniedException("Data Access Tokens are not supported for unauthenticated portals."); - } - - @Override - public Boolean isValid(String token) { - throw new AccessDeniedException("Data Access Tokens are not supported for unauthenticated portals."); - } - - @Override - public Authentication createAuthenticationRequest(String token) { - return null; - } - -} diff --git a/src/main/java/org/cbioportal/service/impl/UuidDataAccessTokenServiceImpl.java b/src/main/java/org/cbioportal/service/impl/UuidDataAccessTokenServiceImpl.java deleted file mode 100644 index b1c977edb75..00000000000 --- a/src/main/java/org/cbioportal/service/impl/UuidDataAccessTokenServiceImpl.java +++ /dev/null @@ -1,186 +0,0 @@ -/* - * Copyright (c) 2018 Memorial Sloan-Kettering Cancer Center. - * - * This library is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS - * FOR A PARTICULAR PURPOSE. The software and documentation provided hereunder - * is on an "as is" basis, and Memorial Sloan-Kettering Cancer Center has no - * obligations to provide maintenance, support, updates, enhancements or - * modifications. In no event shall Memorial Sloan-Kettering Cancer Center be - * liable to any party for direct, indirect, special, incidental or - * consequential damages, including lost profits, arising out of the use of this - * software and its documentation, even if Memorial Sloan-Kettering Cancer - * Center has been advised of the possibility of such damage. - */ - -/* - * This file is part of cBioPortal. - * - * cBioPortal is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . -*/ - -package org.cbioportal.service.impl; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.cbioportal.model.DataAccessToken; -import org.cbioportal.persistence.DataAccessTokenRepository; -import org.cbioportal.service.DataAccessTokenService; -import org.cbioportal.service.exception.TokenNotFoundException; -import org.cbioportal.utils.config.annotation.ConditionalOnProperty; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.security.authentication.BadCredentialsException; -import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; -import org.springframework.security.core.Authentication; - -import java.util.Calendar; -import java.util.Date; -import java.util.List; -import java.util.UUID; -import org.springframework.stereotype.Component; - -@Component -@ConditionalOnProperty(name = "dat.method", havingValue = "uuid") -public class UuidDataAccessTokenServiceImpl implements DataAccessTokenService { - - @Autowired - private DataAccessTokenRepository dataAccessTokenRepository; - - @Value("${dat.ttl_seconds:-1}") - private int datTtlSeconds; - - @Value("${dat.uuid.max_number_per_user:-1}") - private int maxNumberOfAccessTokens; - - private static final Logger log = LoggerFactory.getLogger(UuidDataAccessTokenServiceImpl.class); - - // create a data access token (randomly generated UUID) and insert corresponding record into table with parts: - // username - // uuid - // expiration date (current time + 1 month) - @Override - public DataAccessToken createDataAccessToken(String username) { - if (username == null || username.trim().length() == 0) { - throw new IllegalArgumentException("username cannot be empty"); - } - if (getNumberOfTokensForUsername(username) >= maxNumberOfAccessTokens) { - revokeOldestDataAccessTokenForUsername(username); - } - String uuid = UUID.randomUUID().toString(); - Calendar calendar = Calendar.getInstance(); - Date creationDate = calendar.getTime(); - calendar.add(Calendar.SECOND, datTtlSeconds); - Date expirationDate = calendar.getTime(); - - DataAccessToken dataAccessToken = new DataAccessToken(uuid, username, expirationDate, creationDate); - dataAccessTokenRepository.addDataAccessToken(dataAccessToken); - return dataAccessToken; - } - - // get all user tokens/uuids sorted from oldest to newest - @Override - public List getAllDataAccessTokens(String username) { - List allDataAccessTokens = dataAccessTokenRepository.getAllDataAccessTokensForUsername(username); - return allDataAccessTokens; - } - - // get newest data access token for a given username - @Override - public DataAccessToken getDataAccessToken(String username) { - List allDataAccessTokens = dataAccessTokenRepository.getAllDataAccessTokensForUsername(username); - DataAccessToken newestDataAccessToken = allDataAccessTokens.get(allDataAccessTokens.size() - 1); - return newestDataAccessToken; - } - - @Override - public DataAccessToken getDataAccessTokenInfo(String token) { - DataAccessToken dataAccessToken = dataAccessTokenRepository.getDataAccessToken(token); - if (dataAccessToken == null) { - throw new TokenNotFoundException("Specified token " + token + " does not exist"); - } - return dataAccessToken; - } - - @Override - public void revokeAllDataAccessTokens(String username) { - dataAccessTokenRepository.removeAllDataAccessTokensForUsername(username); - } - - @Override - public void revokeDataAccessToken(String token) { - DataAccessToken dataAccessToken = dataAccessTokenRepository.getDataAccessToken(token); - if (dataAccessToken == null) { - throw new TokenNotFoundException("Specified token " + token + " does not exist"); - } - dataAccessTokenRepository.removeDataAccessToken(token); - } - - @Override - public String getUsername(String token) { - DataAccessToken dataAccessToken = dataAccessTokenRepository.getDataAccessToken(token); - return dataAccessToken.getUsername(); - } - - @Override - public Date getExpiration(String token) { - DataAccessToken dataAccessToken = dataAccessTokenRepository.getDataAccessToken(token); - return dataAccessToken.getExpiration(); - } - - @Override - public Boolean isValid(String dataAccessToken) { - DataAccessToken storedDataAccessToken = null; - try { - storedDataAccessToken = dataAccessTokenRepository.getDataAccessToken(dataAccessToken); - } catch (Exception e) { - log.error("Error retrieving data access token, " + dataAccessToken + " from token store"); - return Boolean.FALSE; - } - Calendar calendar = Calendar.getInstance(); - Date currentDate = calendar.getTime(); - if (storedDataAccessToken == null || storedDataAccessToken.getExpiration().before(currentDate)) { - return Boolean.FALSE; - } - return Boolean.TRUE; - } - - private int getNumberOfTokensForUsername(String username) { - List allDataAccessTokens = dataAccessTokenRepository.getAllDataAccessTokensForUsername(username); - return allDataAccessTokens.size(); - } - - // revokes oldest token in token management system for a user - private void revokeOldestDataAccessTokenForUsername(String username) { - List allDataAccessTokens = dataAccessTokenRepository.getAllDataAccessTokensForUsername(username); - DataAccessToken oldestDataAccessToken = allDataAccessTokens.get(0); - dataAccessTokenRepository.removeDataAccessToken(oldestDataAccessToken.getToken()); - } - - @Override - public Authentication createAuthenticationRequest(String token) { - - if (!isValid(token)) { - log.error("invalid token = " + token); - throw new BadCredentialsException("Invalid access token"); - } - String userName = getUsername(token); - - // when DaoAuthenticationProvider does authentication on user returned by PortalUserDetailsService - // which has password "unused", this password won't match, and then there is a BadCredentials exception thrown - // this is a good way to catch that the wrong authetication provider is being used - return new UsernamePasswordAuthenticationToken(userName, "does not match unused"); - - } -} diff --git a/src/main/java/org/cbioportal/service/impl/VariantCountServiceImpl.java b/src/main/java/org/cbioportal/service/impl/VariantCountServiceImpl.java deleted file mode 100644 index 0c1bdfd2fbe..00000000000 --- a/src/main/java/org/cbioportal/service/impl/VariantCountServiceImpl.java +++ /dev/null @@ -1,70 +0,0 @@ -package org.cbioportal.service.impl; - -import org.cbioportal.model.MolecularProfile; -import org.cbioportal.model.VariantCount; -import org.cbioportal.persistence.VariantCountRepository; -import org.cbioportal.service.MolecularProfileService; -import org.cbioportal.service.MutationService; -import org.cbioportal.service.SampleListService; -import org.cbioportal.service.VariantCountService; -import org.cbioportal.service.exception.MolecularProfileNotFoundException; -import org.cbioportal.service.exception.SampleListNotFoundException; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -import java.util.List; - -@Service -public class VariantCountServiceImpl implements VariantCountService { - - private static final String SEQUENCED_LIST_SUFFIX = "_sequenced"; - - @Autowired - private VariantCountRepository variantCountRepository; - @Autowired - private MutationService mutationService; - @Autowired - private SampleListService sampleListService; - @Autowired - private MolecularProfileService molecularProfileService; - - @Override - public List fetchVariantCounts(String molecularProfileId, List entrezGeneIds, - List keywords) throws MolecularProfileNotFoundException { - - MolecularProfile molecularProfile = validateMolecularProfile(molecularProfileId); - - Integer numberOfSamplesInMolecularProfile = getNumberOfSamplesInMolecularProfile(molecularProfile); - - List variantCounts = variantCountRepository.fetchVariantCounts(molecularProfileId, entrezGeneIds, - keywords); - variantCounts.forEach(v -> v.setNumberOfSamples(numberOfSamplesInMolecularProfile)); - return variantCounts; - } - - private Integer getNumberOfSamplesInMolecularProfile(MolecularProfile molecularProfile) - throws MolecularProfileNotFoundException { - - try { - return sampleListService.getSampleList( - molecularProfile.getCancerStudyIdentifier() + SEQUENCED_LIST_SUFFIX).getSampleCount(); - } catch (SampleListNotFoundException ex) { - return mutationService.fetchMetaMutationsInMolecularProfile(molecularProfile.getStableId(), null, null) - .getSampleCount(); - } - } - - private MolecularProfile validateMolecularProfile(String molecularProfileId) throws MolecularProfileNotFoundException { - - MolecularProfile molecularProfile = molecularProfileService.getMolecularProfile(molecularProfileId); - - if (!(molecularProfile.getMolecularAlterationType() - .equals(MolecularProfile.MolecularAlterationType.MUTATION_EXTENDED) || molecularProfile.getMolecularAlterationType() - .equals(MolecularProfile.MolecularAlterationType.MUTATION_UNCALLED))) { - - throw new MolecularProfileNotFoundException(molecularProfileId); - } - - return molecularProfile; - } -} diff --git a/src/main/java/org/cbioportal/service/impl/ViolinPlotServiceImpl.java b/src/main/java/org/cbioportal/service/impl/ViolinPlotServiceImpl.java deleted file mode 100644 index 92c0ef233a9..00000000000 --- a/src/main/java/org/cbioportal/service/impl/ViolinPlotServiceImpl.java +++ /dev/null @@ -1,234 +0,0 @@ -package org.cbioportal.service.impl; - -import org.apache.commons.lang3.math.NumberUtils; -import org.apache.commons.math3.analysis.function.Gaussian; -import org.apache.commons.math3.stat.descriptive.rank.Percentile; -import org.cbioportal.model.*; -import org.cbioportal.service.ViolinPlotService; -import org.cbioportal.web.parameter.StudyViewFilter; -import org.springframework.cache.annotation.Cacheable; -import org.springframework.stereotype.Service; - -import java.math.BigDecimal; -import java.util.*; -import java.util.stream.Collectors; - -@Service -public class ViolinPlotServiceImpl implements ViolinPlotService { - // If a row has less than this many points, do not compute a - // violin, because it doesn't make sense. - static final int SHOW_ONLY_POINTS_THRESHOLD = 7; - - @Cacheable( - cacheResolver = "staticRepositoryCacheOneResolver", - condition = "@cacheEnabledConfig.getEnabledClickhouse() && @studyViewFilterUtil.isUnfilteredQuery(#studyViewFilter)" - ) - public ClinicalViolinPlotData getClinicalViolinPlotData( - List sampleClinicalDataForViolinPlot, - List samplesForSampleCounts, - BigDecimal axisStart, - BigDecimal axisEnd, - BigDecimal numCurvePoints, - Boolean useLogScale, - BigDecimal sigmaMultiplier, - StudyViewFilter studyViewFilter - ) { - ClinicalViolinPlotData result = new ClinicalViolinPlotData(); - result.setAxisStart(Double.POSITIVE_INFINITY); - result.setAxisEnd(Double.NEGATIVE_INFINITY); - result.setRows(new ArrayList<>()); - - // collect filtered samples into a set for quick lookup - Set samplesForSampleCountsIds = - samplesForSampleCounts.stream() - .map(Sample::getInternalId) - .collect(Collectors.toSet()); - - // clinicalDataMap is a map sampleId->studyId->data - Map>> clinicalDataMap = sampleClinicalDataForViolinPlot.stream() - .collect(Collectors.groupingBy(ClinicalData::getSampleId, Collectors.groupingBy(ClinicalData::getStudyId))); - - // Group data by category - Map> groupedDetailedData = new HashMap<>(); - clinicalDataMap.forEach((studyId, dataBySampleId) -> dataBySampleId.forEach((sampleId, sampleData) -> { - // sampleData.size() == 2 means we have clinical data for the sample for both of the queried attributes - // We also ensure that the second data is numerical, as expected - if (sampleData.size() == 2) { - int numericalIndex = 0; - int categoricalIndex = 1; - if (NumberUtils.isCreatable(sampleData.get(1).getAttrValue())) { - numericalIndex = 1; - categoricalIndex = 0; - } - String category = sampleData.get(categoricalIndex).getAttrValue(); - ClinicalData datum = sampleData.get(numericalIndex); - if (!groupedDetailedData.containsKey(category)) { - groupedDetailedData.put(category, new ArrayList<>()); - } - groupedDetailedData.get(category).add(datum); - } - })); - - if (groupedDetailedData.isEmpty()) { - return result; - } - - // Calculate boxes, outliers, and data bounds - Map boxData = new HashMap<>(); - Map> nonOutliers = new HashMap<>(); - Map> outliers = new HashMap<>(); - groupedDetailedData.forEach((category, data)->{ - Percentile percentile = new Percentile(); - // fill double[] to pass into Percentile - double[] values = new double[data.size()]; - double min = Double.POSITIVE_INFINITY; - double max = Double.NEGATIVE_INFINITY; - int valuesIndex = 0; - for (ClinicalData d: data) { - if (NumberUtils.isCreatable(d.getAttrValue())) { - Double value = useLogScale ? ViolinPlotServiceImpl.logScale(Double.parseDouble(d.getAttrValue())) : Double.parseDouble(d.getAttrValue()); - values[valuesIndex] = value; - min = Math.min(value, min); - max = Math.max(value, max); - valuesIndex += 1; - } - } - - percentile.setData(values); - - double q1 = percentile.evaluate(25); - double q3 = percentile.evaluate(75); - double IQR = q3 - q1; - double SUSPECTED_OUTLIER_MULTIPLE = 1.5; - double OUTLIER_MULTIPLE = 3; - double outlierThresholdLower = q1 - OUTLIER_MULTIPLE * IQR; - double outlierThresholdUpper = q3 + OUTLIER_MULTIPLE * IQR; - double suspectedOutlierThresholdLower = q1 - SUSPECTED_OUTLIER_MULTIPLE * IQR; - double suspectedOutlierThresholdUpper = q3 + SUSPECTED_OUTLIER_MULTIPLE * IQR; - - List _outliers = new ArrayList<>(); - List _nonOutliers = new ArrayList<>(); - List detailedData = groupedDetailedData.get(category); - int numSuspectedOutliers = 0; - for (ClinicalData d: detailedData) { - if (NumberUtils.isCreatable(d.getAttrValue())) { - Double value = useLogScale ? ViolinPlotServiceImpl.logScale(Double.parseDouble(d.getAttrValue())) : Double.parseDouble(d.getAttrValue()); - boolean isOutlier = false; - if (value <= suspectedOutlierThresholdLower) { - numSuspectedOutliers += 1; - if (value <= outlierThresholdLower) { - isOutlier = true; - } - } else if (value >= suspectedOutlierThresholdUpper) { - numSuspectedOutliers += 1; - if (value >= outlierThresholdUpper) { - isOutlier = true; - } - } - if (isOutlier) { - _outliers.add(d); - } else { - _nonOutliers.add(d); - } - } - } - - ClinicalViolinPlotBoxData _boxData = new ClinicalViolinPlotBoxData(); - _boxData.setMedian(percentile.evaluate(50)); - _boxData.setQ1(q1); - _boxData.setQ3(q3); - _boxData.setWhiskerLower(numSuspectedOutliers > 0 ? suspectedOutlierThresholdLower : min); - _boxData.setWhiskerUpper(numSuspectedOutliers > 0 ? suspectedOutlierThresholdUpper : max); - - result.setAxisStart(Math.min(result.getAxisStart(), min)); - result.setAxisEnd(Math.max(result.getAxisEnd(), max)); - - nonOutliers.put(category, _nonOutliers); - outliers.put(category, _outliers); - boxData.put(category, _boxData); - }); - - // Set axis bounds from parameters, if given - if (axisStart != null) { - result.setAxisStart(axisStart.doubleValue()); - } - if (axisEnd != null) { - result.setAxisEnd(axisEnd.doubleValue()); - } - - // Create curves - // By this point, we know the axis bounds - List curvePoints = new ArrayList<>(); - Double stepSize = (result.getAxisEnd() - result.getAxisStart()) / (numCurvePoints.doubleValue()-1); - for (int i=0; i rows = result.getRows(); - nonOutliers.forEach((category, data)->{ - ClinicalViolinPlotRowData row = new ClinicalViolinPlotRowData(); - row.setCategory(category); - row.setNumSamples(countFilteredSamples(samplesForSampleCountsIds, data, outliers.get(category))); - row.setBoxData(boxData.get(category).limitWhiskers(result)); - - List _individualPoints = new ArrayList<>(); - - if (data.size() + outliers.get(category).size() <= SHOW_ONLY_POINTS_THRESHOLD) { - // show only individual points when data is small - row.setCurveData(new ArrayList<>()); - _individualPoints.addAll(data); - _individualPoints.addAll(outliers.get(category)); - } else { - // build violin only based on non-outliers - List gaussians = new ArrayList<>(); - for (ClinicalData d : data) { - Double value = useLogScale ? ViolinPlotServiceImpl.logScale(Double.parseDouble(d.getAttrValue())) : Double.parseDouble(d.getAttrValue()); - gaussians.add(new Gaussian(value, sigma)); - } - - row.setCurveData( - curvePoints.parallelStream().map(p -> { - BigDecimal sum = new BigDecimal(0); - for (Gaussian g : gaussians) { - sum = sum.add(BigDecimal.valueOf(g.value(p))); - } - return sum.doubleValue(); - }).collect(Collectors.toList()) - ); - - // render outliers as individual points - _individualPoints = outliers.get(category); - } - - List individualPoints = new ArrayList<>(); - for (ClinicalData d: _individualPoints) { - ClinicalViolinPlotIndividualPoint p = new ClinicalViolinPlotIndividualPoint(); - p.setSampleId(d.getSampleId()); - p.setStudyId(d.getStudyId()); - p.setValue(useLogScale ? ViolinPlotServiceImpl.logScale(Double.parseDouble(d.getAttrValue())) : Double.parseDouble(d.getAttrValue())); - individualPoints.add(p); - } - row.setIndividualPoints(individualPoints); - rows.add(row); - }); - - // put everything into bins and then do one gaussian per bin, weighted by bin size - return result; - } - - @SafeVarargs - private static int countFilteredSamples( - Set filteredSampleIds, - List... dataLists - ) { - return (int) Arrays.stream(dataLists) - .flatMap(Collection::stream) - .map(ClinicalData::getInternalId) - .filter(filteredSampleIds::contains) - .count(); - } - - private static double logScale(double val) { - return Math.log(1+val); - } -} diff --git a/src/main/java/org/cbioportal/service/treatment/TreatmentCountReportService.java b/src/main/java/org/cbioportal/service/treatment/TreatmentCountReportService.java deleted file mode 100644 index 66305eb5fe8..00000000000 --- a/src/main/java/org/cbioportal/service/treatment/TreatmentCountReportService.java +++ /dev/null @@ -1,14 +0,0 @@ -package org.cbioportal.service.treatment; - -import org.cbioportal.model.PatientTreatmentReport; -import org.cbioportal.model.SampleTreatmentReport; -import org.cbioportal.model.StudyViewFilterContext; -import org.cbioportal.web.parameter.CustomSampleIdentifier; -import org.cbioportal.web.parameter.StudyViewFilter; - -import java.util.List; - -public interface TreatmentCountReportService { - PatientTreatmentReport getPatientTreatmentReport(StudyViewFilterContext studyViewFilterContext); - SampleTreatmentReport getSampleTreatmentReport(StudyViewFilterContext studyViewFilterContext); -} diff --git a/src/main/java/org/cbioportal/service/treatment/TreatmentCountReportServiceImpl.java b/src/main/java/org/cbioportal/service/treatment/TreatmentCountReportServiceImpl.java deleted file mode 100644 index 4a96bcdaf85..00000000000 --- a/src/main/java/org/cbioportal/service/treatment/TreatmentCountReportServiceImpl.java +++ /dev/null @@ -1,48 +0,0 @@ -package org.cbioportal.service.treatment; - -import org.cbioportal.model.PatientTreatmentReport; -import org.cbioportal.model.SampleTreatmentReport; -import org.cbioportal.model.SampleTreatmentRow; -import org.cbioportal.model.StudyViewFilterContext; -import org.cbioportal.model.TemporalRelation; -import org.cbioportal.persistence.StudyViewRepository; -import org.cbioportal.utils.config.annotation.ConditionalOnProperty; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -import java.util.Set; -import java.util.stream.Stream; - -@Service -@ConditionalOnProperty(name = "clickhouse_mode", havingValue = "true") -public class TreatmentCountReportServiceImpl implements TreatmentCountReportService { - - private final StudyViewRepository studyViewRepository; - - @Autowired - public TreatmentCountReportServiceImpl(StudyViewRepository studyViewRepository) { - this.studyViewRepository = studyViewRepository; - } - - @Override - public PatientTreatmentReport getPatientTreatmentReport(StudyViewFilterContext studyViewFilterContext) { - var patientTreatments = studyViewRepository.getPatientTreatments(studyViewFilterContext); - var totalPatientTreatmentCount = studyViewRepository.getTotalPatientTreatmentCount(studyViewFilterContext); - return new PatientTreatmentReport(totalPatientTreatmentCount, 0, patientTreatments); - } - - @Override - public SampleTreatmentReport getSampleTreatmentReport(StudyViewFilterContext studyViewFilterContext) { - var sampleTreatments = studyViewRepository.getSampleTreatments(studyViewFilterContext) - .stream() - .flatMap(sampleTreatment -> - Stream.of(new SampleTreatmentRow(TemporalRelation.Pre, sampleTreatment.treatment(), sampleTreatment.preSampleCount(), Set.of()), - new SampleTreatmentRow(TemporalRelation.Post, sampleTreatment.treatment(), sampleTreatment.postSampleCount(), Set.of() )) - ) - .filter(sampleTreatment -> sampleTreatment.getCount() > 0 ) - .toList(); - var totalSampleTreatmentCount = studyViewRepository.getTotalSampleTreatmentCount(studyViewFilterContext); - return new SampleTreatmentReport(totalSampleTreatmentCount, sampleTreatments); - } - -} diff --git a/src/main/java/org/cbioportal/service/util/AlterationCountServiceUtil.java b/src/main/java/org/cbioportal/service/util/AlterationCountServiceUtil.java deleted file mode 100644 index 9f565e216fc..00000000000 --- a/src/main/java/org/cbioportal/service/util/AlterationCountServiceUtil.java +++ /dev/null @@ -1,168 +0,0 @@ -package org.cbioportal.service.util; - -import org.apache.commons.math3.util.Pair; -import org.cbioportal.model.AlterationCountBase; -import org.cbioportal.model.AlterationCountByGene; -import org.cbioportal.model.CopyNumberCountByGene; -import org.cbioportal.model.Gistic; -import org.cbioportal.model.GisticToGene; -import org.cbioportal.model.MolecularProfile; -import org.cbioportal.model.MutSig; -import org.springframework.lang.NonNull; - -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.function.Function; -import java.util.stream.Collectors; - -public class AlterationCountServiceUtil { - - private AlterationCountServiceUtil() {} - - private static final String WHOLE_EXOME_SEQUENCING = "WES"; - - public static int computeTotalProfiledCount(boolean hasGenePanelData, int alterationsProfiledCount, int sampleProfileCountWithoutGenePanelData, int totalProfiledCount) { - int profiledCount = hasGenePanelData ? alterationsProfiledCount + sampleProfileCountWithoutGenePanelData - : sampleProfileCountWithoutGenePanelData; - return profiledCount == 0 ? totalProfiledCount : profiledCount; - } - - public static List updateAlterationCountsWithMutSigQValue( - List alterationCountByGenes, - Map mutSigs) { - - if (!mutSigs.isEmpty()) { - alterationCountByGenes.parallelStream() - .filter(alterationCount -> mutSigs.containsKey(alterationCount.getHugoGeneSymbol())) - .forEach(alterationCount -> - alterationCount.setqValue(mutSigs.get(alterationCount.getHugoGeneSymbol()).getqValue()) - ); - } - return alterationCountByGenes; - } - - public static List updateAlterationCountsWithCNASigQValue( - List alterationCountByGenes, - Map, Gistic> gisticMap) { - - if (!gisticMap.isEmpty()) { - alterationCountByGenes.parallelStream() - .filter(alterationCount -> gisticMap.containsKey(Pair.create(alterationCount.getHugoGeneSymbol(), alterationCount.getAlteration()))) - .forEach(alterationCount -> - alterationCount.setqValue(gisticMap.get(Pair.create(alterationCount.getHugoGeneSymbol(), alterationCount.getAlteration())).getqValue()) - ); - } - return alterationCountByGenes; - } - - public static List getFirstMolecularProfileGroupedByStudy(List molecularProfiles) { - return molecularProfiles.stream() - .collect(Collectors.toMap( - MolecularProfile::getCancerStudyIdentifier, - Function.identity(), - (existing, replacement) -> existing // Keep the first occurrence - )) - .values() - .stream() - .toList(); - } - - /** - * Combines alteration counts by Hugo gene symbols. If multiple entries exist for the same - * gene symbol, their number of altered cases and total counts are summed up. Returns a - * list of unique AlterationCountByGene objects where each gene symbol is represented only once. - * - * This appears in the Data where Genes have similar Hugo Gene Symbols but different Entrez Ids - * - * @param alterationCounts List of AlterationCountByGene objects, potentially with duplicate gene symbols - * @return List of AlterationCountByGene objects with unique gene symbols and combined counts - */ - public static List combineAlterationCountsWithConflictingHugoSymbols(List alterationCounts) { - Map alterationCountByGeneMap = new HashMap<>(); - for (var alterationCount : alterationCounts) { - if (alterationCountByGeneMap.containsKey(alterationCount.getHugoGeneSymbol())){ - AlterationCountByGene toUpdate = alterationCountByGeneMap.get(alterationCount.getHugoGeneSymbol()); - toUpdate.setNumberOfAlteredCases(toUpdate.getNumberOfAlteredCases() + alterationCount.getNumberOfAlteredCases()); - toUpdate.setTotalCount(toUpdate.getTotalCount() + alterationCount.getTotalCount()); - } else { - alterationCountByGeneMap.put(alterationCount.getHugoGeneSymbol(), alterationCount); - } - } - return alterationCountByGeneMap.values().stream().toList(); - } - - /** - * Combines alteration counts by Hugo gene symbols. If multiple entries exist for the same - * gene symbol, their number of altered cases and total counts are summed up. Returns a - * list of unique AlterationCountByGene objects where each gene symbol is represented only once. - * - * This appears in the Data where Genes have similar Hugo Gene Symbols but different Entrez Ids. - * This is a special case to handle Copy Number Mutations where the Alteration type should be a part of the key - * - * @param alterationCounts List of CopyNumberCountByGene objects, potentially with duplicate gene symbols - * @return List of AlterationCountByGene objects with unique gene symbols and combined counts - */ - public static List combineCopyNumberCountsWithConflictingHugoSymbols(List alterationCounts) { - Map, CopyNumberCountByGene> alterationCountByGeneMap = new HashMap<>(); - for (var alterationCount : alterationCounts) { - var copyNumberKey = Pair.create(alterationCount.getHugoGeneSymbol(), alterationCount.getAlteration()); - if (alterationCountByGeneMap.containsKey(copyNumberKey)) { - CopyNumberCountByGene toUpdate = alterationCountByGeneMap.get(copyNumberKey); - toUpdate.setNumberOfAlteredCases(toUpdate.getNumberOfAlteredCases() + alterationCount.getNumberOfAlteredCases()); - toUpdate.setTotalCount(toUpdate.getTotalCount() + alterationCount.getTotalCount()); - } else { - alterationCountByGeneMap.put(copyNumberKey, alterationCount); - } - } - return alterationCountByGeneMap.values().stream().toList(); - } - - public static boolean hasGenePanelData(@NonNull Set matchingGenePanelIds) { - return matchingGenePanelIds.contains(WHOLE_EXOME_SEQUENCING) - && matchingGenePanelIds.size() > 1 || !matchingGenePanelIds.contains(WHOLE_EXOME_SEQUENCING) && !matchingGenePanelIds.isEmpty(); - } - - public static void setupGisticMap(List gisticList, Map, Gistic> gisticMap) { - for (Gistic gistic : gisticList) { - var amp = gistic.getAmp().booleanValue() ? 2 : -2; - for (GisticToGene gene : gistic.getGenes()) { - var key = Pair.create(gene.getHugoGeneSymbol(), amp); - Gistic currentGistic = gisticMap.get(key); - if (currentGistic == null || gistic.getqValue().compareTo(currentGistic.getqValue()) < 0) { - gisticMap.put(key, gistic); - } - } - } - } - - public static void setupAlterationGeneCountsMap( - List studyAlterationCountByGenes, - Map totalResult) { - - studyAlterationCountByGenes.forEach(datum -> { - String key = datum.getUniqueEventKey(); - if (totalResult.containsKey(key)) { - S alterationCountByGene = totalResult.get(key); - alterationCountByGene.setTotalCount(alterationCountByGene.getTotalCount() + datum.getTotalCount()); - alterationCountByGene.setNumberOfAlteredCases(alterationCountByGene.getNumberOfAlteredCases() + datum.getNumberOfAlteredCases()); - alterationCountByGene.setNumberOfProfiledCases(alterationCountByGene.getNumberOfProfiledCases() + datum.getNumberOfProfiledCases()); - Set matchingGenePanelIds = new HashSet<>(); - if (!alterationCountByGene.getMatchingGenePanelIds().isEmpty()) { - matchingGenePanelIds.addAll(alterationCountByGene.getMatchingGenePanelIds()); - } - if (!datum.getMatchingGenePanelIds().isEmpty()) { - matchingGenePanelIds.addAll(datum.getMatchingGenePanelIds()); - } - alterationCountByGene.setMatchingGenePanelIds(matchingGenePanelIds); - totalResult.put(key, alterationCountByGene); - } else { - totalResult.put(key, datum); - } - }); - } - - -} \ No newline at end of file diff --git a/src/main/java/org/cbioportal/service/util/AlterationEnrichmentUtil.java b/src/main/java/org/cbioportal/service/util/AlterationEnrichmentUtil.java deleted file mode 100644 index 8113cc63f73..00000000000 --- a/src/main/java/org/cbioportal/service/util/AlterationEnrichmentUtil.java +++ /dev/null @@ -1,263 +0,0 @@ -package org.cbioportal.service.util; - -import org.apache.commons.math3.stat.inference.ChiSquareTest; -import org.apache.commons.math3.util.Pair; -import org.cbioportal.model.AlterationCountBase; -import org.cbioportal.model.AlterationCountByGene; -import org.cbioportal.model.AlterationEnrichment; -import org.cbioportal.model.CountSummary; -import org.cbioportal.model.Gene; -import org.cbioportal.model.MolecularProfile; -import org.cbioportal.model.MolecularProfile.MolecularAlterationType; -import org.cbioportal.model.GenePanelData; -import org.cbioportal.model.MolecularProfileCaseIdentifier; -import org.cbioportal.service.GenePanelService; -import org.cbioportal.service.GeneService; -import org.cbioportal.service.MolecularProfileService; -import org.cbioportal.service.exception.MolecularProfileNotFoundException; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -import java.math.BigDecimal; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.function.Function; -import java.util.stream.Collectors; -import java.util.Map.Entry; - -@Component -public class AlterationEnrichmentUtil { - - @Autowired - private FisherExactTestCalculator fisherExactTestCalculator; - @Autowired - private GeneService geneService; - @Autowired - private ProfiledCasesCounter profiledCasesCounter; - @Autowired - private GenePanelService genePanelService; - @Autowired - private MolecularProfileService molecularProfileService; - - public List createAlterationEnrichments(Map, Long>> mutationCountsbyGroup) { - - Map> mutationCountsbyEntrezGeneIdAndGroup = mutationCountsbyGroup - .entrySet() - .stream() - .collect(Collectors.toMap( - entry -> entry.getKey(), - entry -> { - //convert list of alterations to map with EntrezGeneId as key - return entry.getValue().getFirst().stream() - .collect(Collectors.toMap(AlterationCountByGene::getEntrezGeneId, c -> c)); - })); - Map profiledCaseCountsByGroup = mutationCountsbyGroup - .entrySet() - .stream() - .collect(Collectors.toMap( - Entry::getKey, - entry -> entry.getValue().getSecond())); - Set allGeneIds = mutationCountsbyEntrezGeneIdAndGroup - .values() - .stream() - .flatMap(x -> x.keySet().stream()) - .collect(Collectors.toSet()); - - Set groups = mutationCountsbyEntrezGeneIdAndGroup.keySet(); - - List genes = geneService.fetchGenes( - allGeneIds - .stream() - .map(Object::toString) - .collect(Collectors.toList()), - "ENTREZ_GENE_ID", - "SUMMARY"); - return genes - .stream() - .filter(gene -> { - // filter genes where number of altered cases in all groups is 0 - // or where number of altered cases > number of profiled cases - // (the latter can happen in targeted studies when the gene is not on a panel, - // but it is a participant in a structural variant, e.g. fusion, with a gene - // that is on the panel - return groups.stream().filter(group -> { - AlterationCountByGene mutationCountByGene = mutationCountsbyEntrezGeneIdAndGroup - .getOrDefault(group, new HashMap()) - .get(gene.getEntrezGeneId()); - return mutationCountByGene == null ? false : (mutationCountByGene.getNumberOfAlteredCases() != 0 - && mutationCountByGene.getNumberOfAlteredCases() <= - mutationCountByGene.getNumberOfProfiledCases()); - }).count() > 0; - }) - .map(gene -> { - AlterationEnrichment alterationEnrichment = new AlterationEnrichment(); - alterationEnrichment.setEntrezGeneId(gene.getEntrezGeneId()); - alterationEnrichment.setHugoGeneSymbol(gene.getHugoGeneSymbol()); - List counts = groups.stream().map(group -> { - CountSummary groupCasesCount = new CountSummary(); - AlterationCountByGene mutationCountByGene = mutationCountsbyEntrezGeneIdAndGroup - .getOrDefault(group, new HashMap()) - .get(gene.getEntrezGeneId()); - - Integer alteredCount = mutationCountByGene != null ? mutationCountByGene.getNumberOfAlteredCases() : 0; - Integer profiledCount = mutationCountByGene != null ? mutationCountByGene.getNumberOfProfiledCases() : profiledCaseCountsByGroup.get(group).intValue(); - groupCasesCount.setName(group); - groupCasesCount.setAlteredCount(alteredCount); - groupCasesCount.setProfiledCount(profiledCount); - return groupCasesCount; - }).collect(Collectors.toList()); - List filteredCounts = counts.stream() - .filter(groupCasesCount -> groupCasesCount.getProfiledCount() > 0) - .collect(Collectors.toList()); - - // groups where number of altered cases is greater than profiled cases. - // This is a temporary fix for https://github.com/cBioPortal/cbioportal/issues/7274 - // and https://github.com/cBioPortal/cbioportal/issues/7418 - long invalidDataGroups = filteredCounts - .stream() - .filter(groupCasesCount -> groupCasesCount.getAlteredCount() > groupCasesCount.getProfiledCount()) - .count(); - - // calculate p-value only if more than one group have profile cases count - // greater than 0 - if (filteredCounts.size() > 1 && invalidDataGroups == 0) { - double pValue; - // if groups size is two do Fisher Exact test else do Chi-Square test - if (groups.size() == 2) { - - int alteredInNoneCount = counts.get(1).getProfiledCount() - counts.get(1).getAlteredCount(); - int alteredOnlyInQueryGenesCount = counts.get(0).getProfiledCount() - - counts.get(0).getAlteredCount(); - - pValue = fisherExactTestCalculator.getTwoTailedPValue(alteredInNoneCount, - counts.get(1).getAlteredCount(), alteredOnlyInQueryGenesCount, - counts.get(0).getAlteredCount()); - } else { - - long[][] array = counts.stream().map(count -> { - return new long[]{count.getAlteredCount(), - count.getProfiledCount() - count.getAlteredCount()}; - }).toArray(long[][]::new); - - ChiSquareTest chiSquareTest = new ChiSquareTest(); - pValue = chiSquareTest.chiSquareTest(array); - - // set p-value to 1 when the cases in all groups are altered - if (Double.isNaN(pValue)) { - pValue = 1; - } - } - alterationEnrichment.setpValue(BigDecimal.valueOf(pValue)); - } - - alterationEnrichment.setCounts(counts); - return alterationEnrichment; - }).collect(Collectors.toList()); - - } - - public long includeFrequencyForSamples( - List molecularProfileCaseIdentifiers, - List alterationCounts, - boolean includeMissingAlterationsFromGenePanel) { - - // Collect profile id and sample id arrays. - // These are arrays of equal length, where every index - // represents a sample id / profile id-combination - List sampleIds = new ArrayList<>(); - List molecularProfileIds = new ArrayList<>(); - molecularProfileCaseIdentifiers.forEach(pair -> { - sampleIds.add(pair.getCaseId()); - molecularProfileIds.add(pair.getMolecularProfileId()); - }); - - List genePanelDataList = genePanelService - .fetchGenePanelDataInMultipleMolecularProfiles(molecularProfileCaseIdentifiers); - - profiledCasesCounter.calculate(alterationCounts, genePanelDataList, - includeMissingAlterationsFromGenePanel, profiledCasesCounter.sampleUniqueIdentifier); - - return genePanelDataList - .stream() - .filter(GenePanelData::getProfiled) - .map(profiledCasesCounter.sampleUniqueIdentifier) - .distinct() - .count(); - } - - public long includeFrequencyForPatients( - List molecularProfileCaseIdentifiers, - List alterationCounts, - boolean includeMissingAlterationsFromGenePanel) { - - // Collect profile id and sample id arrays. - // These are arrays of equal length, where every index - // represents a sample id / profile id-combination - List patientIds = new ArrayList<>(); - List molecularProfileIds = new ArrayList<>(); - molecularProfileCaseIdentifiers.forEach(pair -> { - patientIds.add(pair.getCaseId()); - molecularProfileIds.add(pair.getMolecularProfileId()); - }); - - List genePanelDataList = genePanelService - .fetchGenePanelDataInMultipleMolecularProfilesByPatientIds(molecularProfileCaseIdentifiers); - - profiledCasesCounter.calculate(alterationCounts, genePanelDataList, - includeMissingAlterationsFromGenePanel, profiledCasesCounter.patientUniqueIdentifier); - - return genePanelDataList - .stream() - .filter(GenePanelData::getProfiled) - .map(profiledCasesCounter.patientUniqueIdentifier) - .distinct() - .count(); - } - - public void validateMolecularProfiles(Map> molecularProfileCaseSets, - List validMolecularAlterationTypes, String dataType) - throws MolecularProfileNotFoundException { - - Set molecularProfileIds = molecularProfileCaseSets.values().stream() - .flatMap(molecularProfileCaseIdentifiers -> molecularProfileCaseIdentifiers.stream() - .map(MolecularProfileCaseIdentifier::getMolecularProfileId)) - .collect(Collectors.toSet()); - - List molecularProfiles = molecularProfileService - .getMolecularProfiles(molecularProfileIds, "SUMMARY"); - - if (molecularProfileIds.size() != molecularProfiles.size()) { - Map molecularProfileMap = molecularProfiles.stream() - .collect(Collectors.toMap(MolecularProfile::getStableId, Function.identity())); - String invalidMolecularProfileIds = molecularProfileIds.stream() - .filter(molecularProfileId -> !molecularProfileMap.containsKey(molecularProfileId)) - .collect(Collectors.joining(",")); - throw new MolecularProfileNotFoundException(invalidMolecularProfileIds); - } - - Map validMolecularAlterationTypeMap = validMolecularAlterationTypes - .stream().collect(Collectors.toMap(Function.identity(), Function.identity())); - - List invalidMolecularProfiles = molecularProfiles.stream().filter(molecularProfile -> { - - if (validMolecularAlterationTypeMap.containsKey(molecularProfile.getMolecularAlterationType())) { - if (dataType != null) { - return !molecularProfile.getDatatype().equals(dataType); - } - // valid profile - return false; - } - // invalid profile - return true; - }).collect(Collectors.toList()); - - if (!invalidMolecularProfiles.isEmpty()) { - throw new MolecularProfileNotFoundException(invalidMolecularProfiles.stream() - .map(MolecularProfile::getStableId).collect(Collectors.joining(","))); - } - } - -} diff --git a/src/main/java/org/cbioportal/service/util/BinnableCustomDataValue.java b/src/main/java/org/cbioportal/service/util/BinnableCustomDataValue.java deleted file mode 100644 index a8b07f0dd4a..00000000000 --- a/src/main/java/org/cbioportal/service/util/BinnableCustomDataValue.java +++ /dev/null @@ -1,49 +0,0 @@ -package org.cbioportal.service.util; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import org.cbioportal.model.Binnable; - -import java.io.Serializable; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class BinnableCustomDataValue implements Binnable, Serializable { - - private final CustomDataValue customDataValue; - private final String attrId; - private final Boolean patientAttribute; - - public BinnableCustomDataValue( - CustomDataValue customDataValue, - String attributeId, - Boolean patientAttribute - ) { - this.customDataValue = customDataValue; - this.attrId = attributeId; - this.patientAttribute = patientAttribute; - } - - public String getSampleId() { - return customDataValue.getSampleId(); - } - - public String getPatientId() { - return customDataValue.getPatientId(); - } - - public String getStudyId() { - return customDataValue.getStudyId(); - } - - public String getAttrId() { - return attrId; - } - - public Boolean isPatientAttribute() { - return patientAttribute; - } - - public String getAttrValue() { - return customDataValue.getValue(); - } - -} diff --git a/src/main/java/org/cbioportal/service/util/ChromosomeCalculator.java b/src/main/java/org/cbioportal/service/util/ChromosomeCalculator.java deleted file mode 100644 index 21b81cdd73f..00000000000 --- a/src/main/java/org/cbioportal/service/util/ChromosomeCalculator.java +++ /dev/null @@ -1,32 +0,0 @@ -package org.cbioportal.service.util; - -import org.springframework.stereotype.Component; - -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -@Component -public class ChromosomeCalculator { - - private String getChromosome(String cytoband) { - - if (cytoband == null) { - return null; - } - - cytoband = cytoband.toUpperCase(); - if (cytoband.startsWith("X")) { - return "X"; - } else if (cytoband.startsWith("Y")) { - return "Y"; - } - - Pattern p = Pattern.compile("([0-9]+).*"); - Matcher m = p.matcher(cytoband); - if (m.find()) { - return m.group(1); - } - - return null; - } -} diff --git a/src/main/java/org/cbioportal/service/util/ClinicalAttributeUtil.java b/src/main/java/org/cbioportal/service/util/ClinicalAttributeUtil.java deleted file mode 100644 index fc64d5b8d58..00000000000 --- a/src/main/java/org/cbioportal/service/util/ClinicalAttributeUtil.java +++ /dev/null @@ -1,57 +0,0 @@ -package org.cbioportal.service.util; - -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.stream.Collectors; - -import org.cbioportal.model.ClinicalAttribute; -import org.springframework.stereotype.Component; - -@Component -public class ClinicalAttributeUtil { - - public void extractCategorizedClinicalAttributes( - List clinicalAttributes, - List sampleAttributeIds, - List patientAttributeIds, - List conflictingPatientAttributeIds - ) { - - Set sampleAttributeIdsSet = new HashSet(); - Set patientAttributeIdsSet = new HashSet(); - Set conflictingPatientAttributeIdsSet = new HashSet(); - - Map>> groupedAttributesByIdAndType = clinicalAttributes - .stream() - .collect(Collectors.groupingBy( - ClinicalAttribute::getAttrId, - Collectors.groupingBy(ClinicalAttribute::getPatientAttribute) - )); - - groupedAttributesByIdAndType.entrySet().forEach(entry -> { - if (entry.getValue().keySet().size() == 1) { - entry.getValue().entrySet().stream().forEach(x -> { - if (x.getKey()) { - patientAttributeIdsSet.add(entry.getKey()); - } else { - sampleAttributeIdsSet.add(entry.getKey()); - } - }); - } else { - entry.getValue().entrySet().forEach(x -> { - if (x.getKey()) { - conflictingPatientAttributeIdsSet.add(entry.getKey()); - } else { - sampleAttributeIdsSet.add(entry.getKey()); - } - }); - } - }); - - sampleAttributeIds.addAll(sampleAttributeIdsSet); - patientAttributeIds.addAll(patientAttributeIdsSet); - conflictingPatientAttributeIds.addAll(conflictingPatientAttributeIdsSet); - } -} diff --git a/src/main/java/org/cbioportal/service/util/CoExpressionAsyncMethods.java b/src/main/java/org/cbioportal/service/util/CoExpressionAsyncMethods.java deleted file mode 100644 index 6e07ab2c1a9..00000000000 --- a/src/main/java/org/cbioportal/service/util/CoExpressionAsyncMethods.java +++ /dev/null @@ -1,62 +0,0 @@ -package org.cbioportal.service.util; - -import org.springframework.stereotype.Component; -import org.springframework.scheduling.annotation.Async; -import org.cbioportal.model.CoExpression; -import org.apache.commons.lang3.math.NumberUtils; -import org.apache.commons.math3.linear.Array2DRowRealMatrix; -import org.apache.commons.math3.linear.RealMatrix; -import org.apache.commons.math3.stat.correlation.SpearmansCorrelation; - -import java.util.List; -import java.util.ArrayList; -import java.util.Iterator; -import java.math.BigDecimal; -import java.util.concurrent.CompletableFuture; - -@Component -public class CoExpressionAsyncMethods { - - @Async - public CompletableFuture computeCoExpression(String entityId, List valuesA, List valuesB, Double threshold) { - - List valuesACopy = new ArrayList<>(valuesA); - List valuesBCopy = new ArrayList<>(valuesB); - - Iterator itA = valuesACopy.listIterator(); - Iterator itB = valuesBCopy.listIterator(); - while (itA.hasNext() && itB.hasNext()) { - if (!NumberUtils.isCreatable(itA.next()) | !NumberUtils.isCreatable(itB.next())) { - itA.remove(); - itB.remove(); - } - } - - CoExpression coExpression = new CoExpression(); - coExpression.setGeneticEntityId(entityId); - - double[] valuesBNumber = valuesBCopy.stream().mapToDouble(Double::parseDouble).toArray(); - double[] valuesANumber = valuesACopy.stream().mapToDouble(Double::parseDouble).toArray(); - - if (valuesANumber.length <= 2) { - return null; - } - - double[][] arrays = new double[2][valuesANumber.length]; - arrays[0] = valuesBNumber; - arrays[1] = valuesANumber; - SpearmansCorrelation spearmansCorrelation = new SpearmansCorrelation((new Array2DRowRealMatrix(arrays, false)).transpose()); - - double spearmansValue = spearmansCorrelation.correlation(valuesBNumber, valuesANumber); - if (Double.isNaN(spearmansValue) || Math.abs(spearmansValue) < threshold) { - return null; - } - coExpression.setSpearmansCorrelation(BigDecimal.valueOf(spearmansValue)); - - RealMatrix resultMatrix = spearmansCorrelation.getRankCorrelation().getCorrelationPValues(); - coExpression.setpValue(BigDecimal.valueOf(resultMatrix.getEntry(0, 1))); - - return CompletableFuture.supplyAsync(() -> coExpression); - } - -} diff --git a/src/main/java/org/cbioportal/service/util/CustomAttributeWithData.java b/src/main/java/org/cbioportal/service/util/CustomAttributeWithData.java deleted file mode 100644 index ce7e5bcd159..00000000000 --- a/src/main/java/org/cbioportal/service/util/CustomAttributeWithData.java +++ /dev/null @@ -1,121 +0,0 @@ -package org.cbioportal.service.util; - -import java.io.Serializable; -import java.util.Arrays; -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import java.util.stream.Collectors; - - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import jakarta.validation.constraints.NotNull; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class CustomAttributeWithData implements Serializable { - - private String owner = "anonymous"; - private Set origin = new HashSet<>(); - private Long created = System.currentTimeMillis(); - private Long lastUpdated = System.currentTimeMillis(); - private Set users = new HashSet<>(); - - @NotNull - private String displayName; - private String description; - private String datatype; - @NotNull - private Boolean patientAttribute; - private String priority; - - private List data; - - public String getOwner() { - return owner; - } - - public void setOwner(String owner) { - this.owner = owner; - } - - public void setOrigin(Set origin) { - this.origin = origin; - } - - public Long getCreated() { - return created; - } - - public void setCreated(Long created) { - this.created = created; - } - - public Long getLastUpdated() { - return lastUpdated; - } - - public void setLastUpdated(Long lastUpdated) { - this.lastUpdated = lastUpdated; - } - - public Set getUsers() { - return users; - } - - public void setUsers(Set users) { - this.users = users; - } - - public Set getOrigin() { - return this.origin; - } - - public List getData() { - return data; - } - - public void setData(List data) { - this.data = data; - } - - public String getDisplayName() { - return displayName; - } - - public void setDisplayName(String displayName) { - this.displayName = displayName; - } - - public String getDescription() { - return description; - } - - public void setDescription(String description) { - this.description = description; - } - - public String getDatatype() { - return datatype; - } - - public void setDatatype(String datatype) { - this.datatype = datatype; - } - - public Boolean getPatientAttribute() { - return patientAttribute; - } - - public void setPatientAttribute(Boolean patientAttribute) { - this.patientAttribute = patientAttribute; - } - - public String getPriority() { - return priority; - } - - public void setPriority(String priority) { - this.priority = priority; - } - -} diff --git a/src/main/java/org/cbioportal/service/util/CustomDataSession.java b/src/main/java/org/cbioportal/service/util/CustomDataSession.java deleted file mode 100644 index 151af9b4227..00000000000 --- a/src/main/java/org/cbioportal/service/util/CustomDataSession.java +++ /dev/null @@ -1,45 +0,0 @@ -package org.cbioportal.service.util; - -import java.io.IOException; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.cbioportal.utils.removeme.Session; -import com.fasterxml.jackson.annotation.JsonIgnore; -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.databind.ObjectMapper; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class CustomDataSession extends Session { - - private static final Logger LOG = LoggerFactory.getLogger(CustomDataSession.class); - private CustomAttributeWithData data; - - @Override - public void setData(Object data) { - ObjectMapper mapper = new ObjectMapper(); - try { - this.data = mapper.readValue(mapper.writeValueAsString(data), CustomAttributeWithData.class); - } catch (IOException e) { - LOG.error("Error occurred", e); - } - } - - @Override - public CustomAttributeWithData getData() { - return data; - } - - @JsonIgnore - @Override - public String getSource() { - return super.getSource(); - } - - @JsonIgnore - @Override - public SessionType getType() { - return super.getType(); - } - -} diff --git a/src/main/java/org/cbioportal/service/util/CustomDataValue.java b/src/main/java/org/cbioportal/service/util/CustomDataValue.java deleted file mode 100644 index 9e9343a7e2a..00000000000 --- a/src/main/java/org/cbioportal/service/util/CustomDataValue.java +++ /dev/null @@ -1,52 +0,0 @@ -package org.cbioportal.service.util; - -import java.io.Serializable; - - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import jakarta.validation.constraints.NotNull; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class CustomDataValue implements Serializable { - - private String sampleId; - @NotNull - private String patientId; - @NotNull - private String studyId; - - private String value; - - public String getSampleId() { - return sampleId; - } - - public void setSampleId(String sampleId) { - this.sampleId = sampleId; - } - - public String getPatientId() { - return patientId; - } - - public void setPatientId(String patientId) { - this.patientId = patientId; - } - - public String getStudyId() { - return studyId; - } - - public void setStudyId(String studyId) { - this.studyId = studyId; - } - - public String getValue() { - return value; - } - - public void setValue(String value) { - this.value = value; - } - -} diff --git a/src/main/java/org/cbioportal/service/util/ExpressionEnrichmentUtil.java b/src/main/java/org/cbioportal/service/util/ExpressionEnrichmentUtil.java deleted file mode 100644 index 2fedb6eb5dd..00000000000 --- a/src/main/java/org/cbioportal/service/util/ExpressionEnrichmentUtil.java +++ /dev/null @@ -1,416 +0,0 @@ -package org.cbioportal.service.util; - -import java.math.BigDecimal; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.Map; -import java.util.Set; -import java.util.List; -import java.util.Map.Entry; -import java.util.function.Function; -import java.util.stream.Collectors; -import java.util.stream.IntStream; - -import org.cbioportal.model.EnrichmentType; -import org.cbioportal.model.ExpressionEnrichment; -import org.cbioportal.model.GenericAssayEnrichment; -import org.cbioportal.model.GenericAssayBinaryEnrichment; -import org.cbioportal.model.GenericAssayCategoricalEnrichment; -import org.cbioportal.model.GenericAssayMolecularAlteration; -import org.cbioportal.model.GenomicEnrichment; -import org.cbioportal.model.GroupStatistics; -import org.cbioportal.model.GenericAssayCountSummary; -import org.cbioportal.model.MolecularAlteration; -import org.cbioportal.model.MolecularProfile; -import org.cbioportal.model.MolecularProfileCaseIdentifier; -import org.cbioportal.model.MolecularProfileSamples; -import org.cbioportal.model.Sample; -import org.apache.commons.lang3.StringUtils; -import org.apache.commons.lang3.math.NumberUtils; -import org.apache.commons.math3.stat.StatUtils; -import org.apache.commons.math3.stat.descriptive.DescriptiveStatistics; -import org.apache.commons.math3.stat.inference.ChiSquareTest; -import org.apache.commons.math3.stat.inference.OneWayAnova; -import org.apache.commons.math3.stat.inference.TestUtils; -import org.cbioportal.persistence.MolecularDataRepository; -import org.cbioportal.service.SampleService; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -@Component -public class ExpressionEnrichmentUtil { - - @Autowired - private SampleService sampleService; - @Autowired - private MolecularDataRepository molecularDataRepository; - - private static final double LOG2 = Math.log(2); - private static final String RNA_SEQ = "rna_seq"; - private static final List posTypeList = Arrays.asList("true", "yes"); - private static final List negTypeList = Arrays.asList("false", "no"); - private static final String ALTERED = "1"; - private static final String UNALTERED = "0"; - public List getEnrichments( - MolecularProfile molecularProfile, - Map> molecularProfileCaseSets, EnrichmentType enrichmentType, - Iterable maItr) { - List expressionEnrichments = new ArrayList<>(); - - Map> groupIndicesMap = getGroupIndicesMap(molecularProfileCaseSets, enrichmentType, - molecularProfile); - for (MolecularAlteration ma : maItr) { - List groupsStatistics = new ArrayList(); - // used for p-value calculation - List groupedValues = new ArrayList(); - - for (Entry> group : groupIndicesMap.entrySet()) { - - // get expression values to all the indices in the group - List molecularDataValues = group.getValue().stream() - .map(sampleIndex -> ma.getSplitValues()[sampleIndex]) - .filter(a -> NumberUtils.isNumber(a)) - .collect(Collectors.toList()); - - // ignore group if there are less than 2 values - if (molecularDataValues.size() < 2) { - continue; - } - - double[] values = getAlterationValues(molecularDataValues, molecularProfile.getStableId()); - - GroupStatistics groupStatistics = new GroupStatistics(); - double alteredMean = StatUtils.mean(values); - double alteredStandardDeviation = calculateStandardDeviation(values); - - // ignore if mean or standard deviation are not numbers - if (Double.isNaN(alteredMean) || Double.isNaN(alteredStandardDeviation)) { - continue; - } - - groupedValues.add(values); - groupStatistics.setName(group.getKey()); - groupStatistics.setMeanExpression(BigDecimal.valueOf(alteredMean)); - groupStatistics.setStandardDeviation(BigDecimal.valueOf(alteredStandardDeviation)); - groupsStatistics.add(groupStatistics); - } - - // calculate p-value and add enrichment if atleast 2 groups have data - if (groupsStatistics.size() > 1) { - double pValue = calculatePValue(groupedValues); - if (Double.isNaN(pValue)) { - continue; - } - S expressionEnrichment = null; - if (ma instanceof GenericAssayMolecularAlteration) { - GenericAssayEnrichment genericAssayEnrichment = new GenericAssayEnrichment(); - genericAssayEnrichment.setStableId(ma.getStableId()); - expressionEnrichment = (S) genericAssayEnrichment; - } else { - GenomicEnrichment genomicEnrichment = new GenomicEnrichment(); - genomicEnrichment.setEntrezGeneId(Integer.valueOf(ma.getStableId())); - expressionEnrichment = (S) genomicEnrichment; - } - expressionEnrichment.setpValue(BigDecimal.valueOf(pValue)); - expressionEnrichment.setGroupsStatistics(groupsStatistics); - expressionEnrichments.add(expressionEnrichment); - } - } - return expressionEnrichments; - } - - public List getGenericAssayCategoricalEnrichments( - MolecularProfile molecularProfile, - Map> molecularProfileCaseSets, EnrichmentType enrichmentType, - Iterable maItr) { - - List expressionEnrichments = new ArrayList<>(); - Map> groupCategoryStatistics = new HashMap<>(); - Map> groupIndicesMap = getGroupIndicesMap(molecularProfileCaseSets, enrichmentType, - molecularProfile); - - for (MolecularAlteration ma : maItr) { - List groupsStatistics = new ArrayList(); - for (Entry> group : groupIndicesMap.entrySet()) { - // Get the corresponding split values for the group - List groupValues = group.getValue().stream() - .map(sampleIndex -> ma.getSplitValues()[sampleIndex]) - .collect(Collectors.toList()); - // Group and count the split values - Map groupedSplitValues = groupValues.stream() - .collect(Collectors.toMap(Function.identity(), v -> 1, Integer::sum)); - - // ignore group if there are less than 2 values - if (groupValues.size() < 2) { - continue; - } - - GroupStatistics groupStatistics = new GroupStatistics(); - groupStatistics.setName(group.getKey()); - groupsStatistics.add(groupStatistics); - groupCategoryStatistics.put(group.getKey(), groupedSplitValues); - } - - // calculate p-value and add enrichment if atleast 2 groups have data - - if (groupsStatistics.size() > 1) { - long[][] array = getCategoricalValues(groupCategoryStatistics); - double pValue; - if(array[0].length <= 1) { - pValue = 1; - } else { - ChiSquareTest chiSquareTest = new ChiSquareTest(); - pValue = chiSquareTest.chiSquareTest(array); - } - - // set p-value to 1 when the cases in all groups are altered - if (Double.isNaN(pValue)) { - pValue = 1; - } - - S expressionEnrichment = null; - GenericAssayCategoricalEnrichment genericAssayCategoricalEnrichment = new GenericAssayCategoricalEnrichment(); - genericAssayCategoricalEnrichment.setStableId(ma.getStableId()); - expressionEnrichment = (S) genericAssayCategoricalEnrichment; - - expressionEnrichment.setpValue(BigDecimal.valueOf(pValue)); - expressionEnrichment.setGroupsStatistics(groupsStatistics); - expressionEnrichments.add(expressionEnrichment); - } - } - return expressionEnrichments; - } - - public List getGenericAssayBinaryEnrichments( - MolecularProfile molecularProfile, - Map> molecularProfileCaseSets, EnrichmentType enrichmentType, - Iterable maItr) { - List expressionEnrichments = new ArrayList<>(); - - Map> groupIndicesMap = getGroupIndicesMap(molecularProfileCaseSets, enrichmentType, - molecularProfile); - - for (MolecularAlteration ma : maItr) { - List genericAssayCountSummaries = new ArrayList<>(); - List groupsStatistics = new ArrayList(); - // used for p-value calculation - List groupedValues = new ArrayList(); - - for (Entry> group : groupIndicesMap.entrySet()) { - GenericAssayCountSummary genericAssayCountSummary = new GenericAssayCountSummary(); - genericAssayCountSummary.setName(group.getKey()); - - // get expression values to all the indices in the group, filter NA and map binary values - List molecularDataValues = group.getValue().stream() - .map(sampleIndex -> ma.getSplitValues()[sampleIndex]) - .filter(StringUtils::isNotEmpty) - .map(a ->{ - if (posTypeList.contains(a)) { - return ALTERED; - } else if (negTypeList.contains(a)) { - return UNALTERED; - } else { - return a; - } - }) - .collect(Collectors.toList()); - - // ignore group if there are less than 2 values - if (molecularDataValues.size() < 2) { - continue; - } - genericAssayCountSummary.setTotalCount(molecularDataValues.size()); - - double[] values = getAlterationValues(molecularDataValues, molecularProfile.getStableId()); - genericAssayCountSummary.setCount((int) Arrays.stream(values) - .filter(num -> num == 1) - .count()); - GroupStatistics groupStatistics = new GroupStatistics(); - double alteredMean = StatUtils.mean(values); - double alteredStandardDeviation = calculateStandardDeviation(values); - - // ignore if mean or standard deviation are not numbers - if (Double.isNaN(alteredMean) || Double.isNaN(alteredStandardDeviation)) { - continue; - } - - groupedValues.add(values); - groupStatistics.setName(group.getKey()); - groupStatistics.setMeanExpression(BigDecimal.valueOf(alteredMean)); - groupStatistics.setStandardDeviation(BigDecimal.valueOf(alteredStandardDeviation)); - groupsStatistics.add(groupStatistics); - genericAssayCountSummaries.add(genericAssayCountSummary); - } - - // calculate p-value and add enrichment if atleast 2 groups have data - if (groupsStatistics.size() > 1) { - - double pValue = calculatePValue(groupedValues); - if (Double.isNaN(pValue)) { - continue; - } - S expressionEnrichment = null; - GenericAssayBinaryEnrichment genericAssayBinaryEnrichment = new GenericAssayBinaryEnrichment(); - genericAssayBinaryEnrichment.setStableId(ma.getStableId()); - genericAssayBinaryEnrichment.setCounts(genericAssayCountSummaries); - expressionEnrichment = (S) genericAssayBinaryEnrichment; - - expressionEnrichment.setpValue(BigDecimal.valueOf(pValue)); - expressionEnrichment.setGroupsStatistics(groupsStatistics); - expressionEnrichments.add(expressionEnrichment); - } - } - return expressionEnrichments; - } - - private double[] getAlterationValues(List molecularDataValues, String molecularProfileId) { - - if (molecularProfileId.contains(RNA_SEQ)) { - return molecularDataValues.stream().mapToDouble(d -> { - double datum = Double.parseDouble(d); - // reset to 0 if there are any negative values and then do log1p - return Math.log1p(datum < 0 ? 0 : datum) / LOG2; - }).toArray(); - } else { - return molecularDataValues.stream().mapToDouble(g -> Double.parseDouble(g)).toArray(); - } - } - - private long[][] getCategoricalValues(Map> groupCategoryStatistics) { - // Determine the number of rows and columns - int numRows = groupCategoryStatistics.size(); - Set allCategories = groupCategoryStatistics.values().stream() - .flatMap(innerMap -> innerMap.keySet().stream()) - .collect(Collectors.toSet()); - int numCols = allCategories.size(); - - // Create the 2-dimensional long array - long[][] array = new long[numRows][numCols]; - - // Iterate over the outer map (group -> categories) - List groupKeys = new ArrayList<>(groupCategoryStatistics.keySet()); - for (int row = 0; row < numRows; row++) { - String groupKey = groupKeys.get(row); - Map innerMap = groupCategoryStatistics.get(groupKey); - - // Iterate over all categories - List categoryKeys = new ArrayList<>(allCategories); - for (int col = 0; col < numCols; col++) { - String categoryKey = categoryKeys.get(col); - - // Get the count from the inner map, or set as zero if the category doesn't exist - int count = innerMap.getOrDefault(categoryKey, 0); - array[row][col] = count; - } - } - return array; - } - - private double calculatePValue(List alteredValues) { - - if (alteredValues.size() == 2) { - return TestUtils.tTest(alteredValues.get(0), alteredValues.get(1)); - } else { - // calculate Anova statisitcs if there are more than 2 groups - OneWayAnova oneWayAnova = new OneWayAnova(); - return oneWayAnova.anovaPValue(alteredValues); - } - } - - private double calculateStandardDeviation(double[] values) { - - DescriptiveStatistics descriptiveStatistics = new DescriptiveStatistics(); - for (double value : values) { - descriptiveStatistics.addValue(value); - } - return descriptiveStatistics.getStandardDeviation(); - } - - /** - * - * This method maps valid samples in molecularProfileCaseSets to indices in - * genetic_alteration.VALUES column. Recall this column of the - * genetic_alteration table is a comma separated list of scalar values. Each - * value in this list is associated with a sample at the same position found in - * the genetic_profile_samples.ORDERED_SAMPLE_LIST column. - * - * @param molecularProfileCaseSets - * @param enrichmentType - * @param molecularProfile - * @return - */ - private Map> getGroupIndicesMap( - Map> molecularProfileCaseSets, EnrichmentType enrichmentType, - MolecularProfile molecularProfile) { - - MolecularProfileSamples commaSeparatedSampleIdsOfMolecularProfile = molecularDataRepository - .getCommaSeparatedSampleIdsOfMolecularProfile(molecularProfile.getStableId()); - - List internalSampleIds = Arrays.stream(commaSeparatedSampleIdsOfMolecularProfile.getSplitSampleIds()) - .mapToInt(Integer::parseInt).boxed().collect(Collectors.toList()); - - Map internalSampleIdToIndexMap = IntStream.range(0, internalSampleIds.size()).boxed() - .collect(Collectors.toMap(internalSampleIds::get, Function.identity())); - - Map> selectedCaseIdToInternalIdsMap = getCaseIdToInternalIdsMap(molecularProfileCaseSets, - enrichmentType, molecularProfile); - - // this block map caseIds(sampleIds or patientids) to sampleIndices which - // represents the position fount in the - // genetic_profile_samples.ORDERED_SAMPLE_LIST column - Map> groupIndicesMap = molecularProfileCaseSets.entrySet().stream() - .collect(Collectors.toMap(entity -> entity.getKey(), entity -> { - List sampleIndices = new ArrayList<>(); - entity.getValue().forEach(molecularProfileCaseIdentifier -> { - // consider only valid samples - if (selectedCaseIdToInternalIdsMap.containsKey(molecularProfileCaseIdentifier.getCaseId())) { - List sampleInternalIds = selectedCaseIdToInternalIdsMap - .get(molecularProfileCaseIdentifier.getCaseId()); - - // only consider samples which are profiled for the give molecular profile id - sampleInternalIds.forEach(sampleInternalId -> { - if (internalSampleIdToIndexMap.containsKey(sampleInternalId)) { - sampleIndices.add(internalSampleIdToIndexMap.get(sampleInternalId)); - } - }); - } - }); - return sampleIndices; - })); - return groupIndicesMap; - } - - private Map> getCaseIdToInternalIdsMap( - Map> molecularProfileCaseSets, EnrichmentType enrichmentType, - MolecularProfile molecularProfile) { - - if (enrichmentType.equals(EnrichmentType.PATIENT)) { - List patientIds = molecularProfileCaseSets.values().stream() - .flatMap(molecularProfileCaseSet -> molecularProfileCaseSet.stream() - .map(MolecularProfileCaseIdentifier::getCaseId)) - .collect(Collectors.toList()); - - List samples = sampleService - .getAllSamplesOfPatientsInStudy(molecularProfile.getCancerStudyIdentifier(), patientIds, "SUMMARY"); - - return samples.stream().collect(Collectors.groupingBy(Sample::getPatientStableId, - Collectors.mapping(Sample::getInternalId, Collectors.toList()))); - } else { - List sampleIds = new ArrayList<>(); - List studyIds = new ArrayList<>(); - - molecularProfileCaseSets.values().forEach(molecularProfileCaseIdentifiers -> { - molecularProfileCaseIdentifiers.forEach(molecularProfileCaseIdentifier -> { - sampleIds.add(molecularProfileCaseIdentifier.getCaseId()); - studyIds.add(molecularProfile.getCancerStudyIdentifier()); - }); - }); - List samples = sampleService.fetchSamples(studyIds, sampleIds, "ID"); - - return samples.stream() - .collect(Collectors.toMap(Sample::getStableId, x -> Arrays.asList(x.getInternalId()))); - } - } - -} \ No newline at end of file diff --git a/src/main/java/org/cbioportal/service/util/FisherExactTestCalculator.java b/src/main/java/org/cbioportal/service/util/FisherExactTestCalculator.java deleted file mode 100644 index 150fb370178..00000000000 --- a/src/main/java/org/cbioportal/service/util/FisherExactTestCalculator.java +++ /dev/null @@ -1,124 +0,0 @@ -package org.cbioportal.service.util; - -import org.springframework.stereotype.Component; - -import java.math.BigDecimal; - -@Component -public class FisherExactTestCalculator { - - private double getPValue(int a, int b, int c, int d, double[] f) { - - int n = a + b + c + d; - double p = (f[a + b] + f[c + d] + f[a + c] + f[b + d]) - (f[a] + f[b] + f[c] + f[d] + f[n]); - return Math.exp(p); - } - - public double getCumulativePValue(int a, int b, int c, int d) { - - int min, i; - int n = a + b + c + d; - double p = 0; - double[] f = new double[n + 1]; - f[0] = 0.0; - - for (int j = 1; j <= n; j++) { - f[j] = f[j - 1] + Math.log(j); - } - - p += getPValue(a, b, c, d, f); - if ((a * d) >= (b * c)) { - min = (c < b) ? c : b; - for (i = 0; i < min; i++) { - p += getPValue(++a, --b, --c, ++d, f); - } - } - - if ((a * d) < (b * c)) { - min = (a < d) ? a : d; - for (i = 0; i < min; i++) { - p += getPValue(--a, ++b, ++c, --d, f); - } - } - return p; - } - - public double getTwoTailedPValue(int a, int b, int c, int d) { - - int min, i; - int n = a + b + c + d; - double p = 0; - double[] f = new double[n + 1]; - f[0] = 0.0; - - for (int j = 1; j <= n; j++) { - f[j] = f[j - 1] + Math.log(j); - } - - double baseP = getPValue(a, b, c, d, f); -// in order for a table under consideration to have its p-value included -// in the final result, it must have a p-value less than the baseP, i.e. -// Fisher's exact test computes the probability, given the observed marginal -// frequencies, of obtaining exactly the frequencies observed and any configuration more extreme. -// By "more extreme," we mean any configuration (given observed marginals) with a smaller probability of -// occurrence in the same direction (one-tailed) or in both directions (two-tailed). - - int initialA = a, initialB = b, initialC = c, initialD = d; - p += baseP; - - min = (c < b) ? c : b; - for (i = 0; i < min; i++) { - double tempP = getPValue(++a, --b, --c, ++d, f); - if (tempP <= baseP) { - p += tempP; - } - } - - // reset the values to their original so we can repeat this process for the other side - a = initialA; - b = initialB; - c = initialC; - d = initialD; - - min = (a < d) ? a : d; - for (i = 0; i < min; i++) { - double pTemp = getPValue(--a, ++b, ++c, --d, f); - if (pTemp <= baseP) { - p += pTemp; - } - } - return p; - } - public BigDecimal[] calcqValue(BigDecimal[] pValuesInIncreasingOrder) { - BigDecimal cachedElement = BigDecimal.valueOf(0.0); - int dataLength = pValuesInIncreasingOrder.length; - BigDecimal[] reversedQValues = new BigDecimal[dataLength]; - - reverseValues(dataLength, pValuesInIncreasingOrder); - - for (int i = 0; i < dataLength; i++) { - if (i > 0) { - BigDecimal calculatedValue = cachedElement.min( - (pValuesInIncreasingOrder[i].multiply(new BigDecimal(dataLength))).divide(new BigDecimal(dataLength - i), BigDecimal.ROUND_HALF_UP) - ); - cachedElement = calculatedValue; - reversedQValues[i] = calculatedValue; - } else { - cachedElement = pValuesInIncreasingOrder[i]; - reversedQValues[i] = pValuesInIncreasingOrder[i]; - } - } - - reverseValues(dataLength, reversedQValues); - - return reversedQValues; - } - - private void reverseValues(int dataLength, BigDecimal[] reversedQValues) { - for (int i = 0; i < dataLength / 2; i++) { - BigDecimal temp = reversedQValues[i]; - reversedQValues[i] = reversedQValues[dataLength - i - 1]; - reversedQValues[dataLength - i - 1] = temp; - } - } -} diff --git a/src/main/java/org/cbioportal/service/util/JwtUtils.java b/src/main/java/org/cbioportal/service/util/JwtUtils.java deleted file mode 100644 index e7022de31a7..00000000000 --- a/src/main/java/org/cbioportal/service/util/JwtUtils.java +++ /dev/null @@ -1,154 +0,0 @@ -/* - * Copyright (c) 2018 Memorial Sloan-Kettering Cancer Center. - * - * This library is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS - * FOR A PARTICULAR PURPOSE. The software and documentation provided hereunder - * is on an "as is" basis, and Memorial Sloan-Kettering Cancer Center has no - * obligations to provide maintenance, support, updates, enhancements or - * modifications. In no event shall Memorial Sloan-Kettering Cancer Center be - * liable to any party for direct, indirect, special, incidental or - * consequential damages, including lost profits, arising out of the use of this - * software and its documentation, even if Memorial Sloan-Kettering Cancer - * Center has been advised of the possibility of such damage. - */ - -/* - * Copyright 2002-2018 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* - * This file is part of cBioPortal. - * - * cBioPortal is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . -*/ - -package org.cbioportal.service.util; - -import org.cbioportal.model.DataAccessToken; -import org.cbioportal.service.exception.InvalidDataAccessTokenException; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import io.jsonwebtoken.Claims; -import io.jsonwebtoken.ExpiredJwtException; -import io.jsonwebtoken.io.Decoders; -import io.jsonwebtoken.Jws; -import io.jsonwebtoken.Jwts; -import io.jsonwebtoken.security.Keys; -import io.jsonwebtoken.SignatureAlgorithm; -import io.jsonwebtoken.SignatureException; -import java.util.*; -import javax.crypto.SecretKey; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.stereotype.Component; - -@Component -public class JwtUtils { - - private byte[] decodedSecretKey; - @Value("${dat.jwt.secret_key:none}") // default value is none - private void setDecodedSecretKey(String secretKey) { - if (!secretKey.isEmpty() && !secretKey.equalsIgnoreCase("none")) { - this.decodedSecretKey = Decoders.BASE64.decode(secretKey); - } - } - - @Value("${dat.ttl_seconds:-1}") // default value is -1 - private int jwtTtlSeconds; - - private static final Logger LOG = LoggerFactory.getLogger(JwtUtils.class); - - public DataAccessToken createToken(String username) { - return this.createToken(username, this.jwtTtlSeconds); - } - - public DataAccessToken createToken(String username, int jwtTtlSeconds) { - if (username == null || username.trim().length() == 0) { - throw new IllegalArgumentException("subject cannot be empty"); - } - Calendar calendar = Calendar.getInstance(); - Date creationDate = calendar.getTime(); - calendar.add(Calendar.SECOND, jwtTtlSeconds); - Date expirationDate = calendar.getTime(); - String jws = Jwts.builder() - .setSubject(username) - .setIssuedAt(creationDate) - .setExpiration(expirationDate) - .signWith(SignatureAlgorithm.HS256, decodedSecretKey).compact(); - return new DataAccessToken(jws, username, expirationDate, creationDate); - } - - public void validate(String token) throws InvalidDataAccessTokenException { - Map properties = extractClaims(token); - } - - public String extractSubject(String token) throws InvalidDataAccessTokenException { - Claims claims = extractClaims(token); - return claims.getSubject(); - } - - public Date extractExpirationDate(String token) throws InvalidDataAccessTokenException { - Claims claims = extractClaims(token); - return claims.getExpiration(); - } - - public Map extractProperties(String token) throws InvalidDataAccessTokenException { - return extractClaims(token); - } - - public Claims extractClaims(String token) throws InvalidDataAccessTokenException { - Claims claims = null; - try { - Jws jwsClaims = Jwts.parser() - .setSigningKey(decodedSecretKey) - .parseClaimsJws(token); - claims = jwsClaims.getBody(); - } catch (SignatureException e) { - LOG.error("Error occurred", e); - throw new InvalidDataAccessTokenException("signature not valid"); - } catch (ExpiredJwtException e) { - LOG.error("Error occurred", e); - throw new InvalidDataAccessTokenException("token has expired"); - } - return claims; - } - - public static String createNewSecretKey() { - SecretKey key = Keys.secretKeyFor(SignatureAlgorithm.HS256); // TODO: consider other Algorithms .. or parameterizing this choice - String encodedKey = Base64.getEncoder().encodeToString(key.getEncoded()); - return encodedKey; - } - - public static void main(String[] args) { - if (args.length == 1 && args[0].equals("--make-key")) { - System.out.println("Creating new secret key for JWTS token signing:"); - System.out.println(createNewSecretKey()); - } else { - System.out.println("usage: JwtUtils --make-key"); - } - } -} diff --git a/src/main/java/org/cbioportal/service/util/MolecularProfileUtil.java b/src/main/java/org/cbioportal/service/util/MolecularProfileUtil.java deleted file mode 100644 index a9cbfa3839e..00000000000 --- a/src/main/java/org/cbioportal/service/util/MolecularProfileUtil.java +++ /dev/null @@ -1,86 +0,0 @@ -package org.cbioportal.service.util; - -import org.cbioportal.model.MolecularProfile; -import org.cbioportal.model.MolecularProfileCaseIdentifier; -import org.springframework.stereotype.Component; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.function.Predicate; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -@Component -public class MolecularProfileUtil { - - public final String MUTATION_PROFILE_SUFFIX = "_mutations"; - public final String STRUCTURAL_VARIANT_PROFILE_SUFFIX = "_structural_variants"; - - public Predicate isStructuralVariantMolecularProfile = - m -> m.getMolecularAlterationType().equals(MolecularProfile.MolecularAlterationType.STRUCTURAL_VARIANT); - - public Predicate isDiscreteCNAMolecularProfile = - m -> m.getMolecularAlterationType().equals(MolecularProfile.MolecularAlterationType.COPY_NUMBER_ALTERATION) && - m.getDatatype().equals("DISCRETE"); - - public Predicate isMutationProfile = - m -> m.getMolecularAlterationType().equals(MolecularProfile.MolecularAlterationType.MUTATION_EXTENDED); - - public Map> categorizeMolecularProfilesByStableIdSuffixes(List molecularProfiles) { - return molecularProfiles - .stream() - .collect(Collectors - .groupingBy(molecularProfile -> - molecularProfile.getStableId().replace(molecularProfile.getCancerStudyIdentifier() + "_", ""))); - } - - public List getFirstFilteredMolecularProfileCaseIdentifiers(List molecularProfiles, - List studyIds, - List sampleIds, - Optional> profileFilter) { - Map> mapByStudyId = getFilteredMolecularProfilesByStudyId(molecularProfiles, profileFilter); - List caseIdentifiers = new ArrayList<>(); - for (int studyIdIdx = 0; studyIdIdx < studyIds.size(); studyIdIdx++) { - String studyId = studyIds.get(studyIdIdx); - if (mapByStudyId.containsKey(studyId)) { - // only add identifier for one molecular profile - caseIdentifiers.add(new MolecularProfileCaseIdentifier(sampleIds.get(studyIdIdx), mapByStudyId.get(studyId).getFirst().getStableId())); - } - } - return caseIdentifiers; - } - - public List getFilteredMolecularProfileCaseIdentifiers(List molecularProfiles, - List studyIds, - List sampleIds, - Optional> profileFilter) { - Map> mapByStudyId = getFilteredMolecularProfilesByStudyId(molecularProfiles, profileFilter); - List caseIdentifiers = new ArrayList<>(); - for (int studyIdIdx = 0; studyIdIdx < studyIds.size(); studyIdIdx++) { - String studyId = studyIds.get(studyIdIdx); - if (mapByStudyId.containsKey(studyId)) { - // add case identifiers for all molecular profiles - int finalStudyIdIdx = studyIdIdx; - mapByStudyId - .getOrDefault(studyId, new ArrayList<>()) - .forEach(molecularProfile -> - caseIdentifiers.add(new MolecularProfileCaseIdentifier(sampleIds.get(finalStudyIdIdx), molecularProfile.getStableId())) - ); - } - } - return caseIdentifiers; - } - - private Map> getFilteredMolecularProfilesByStudyId(List molecularProfiles, - Optional> profileFilter) { - Stream molecularProfileStream = molecularProfiles.stream(); - if (profileFilter.isPresent()) { - molecularProfileStream = molecularProfileStream.filter(profileFilter.get()); - } - return molecularProfileStream - .collect(Collectors.groupingBy(MolecularProfile::getCancerStudyIdentifier)); - } - -} diff --git a/src/main/java/org/cbioportal/service/util/MskWholeSlideViewerTokenGenerator.java b/src/main/java/org/cbioportal/service/util/MskWholeSlideViewerTokenGenerator.java deleted file mode 100644 index 22ac7e776ae..00000000000 --- a/src/main/java/org/cbioportal/service/util/MskWholeSlideViewerTokenGenerator.java +++ /dev/null @@ -1,37 +0,0 @@ - -package org.cbioportal.service.util; - -import java.util.Base64; -import javax.crypto.Mac; -import javax.crypto.spec.SecretKeySpec; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class MskWholeSlideViewerTokenGenerator { - // ~ Static fields - // ======================================================================================================== - - private final static Logger logger = LoggerFactory.getLogger(MskWholeSlideViewerTokenGenerator.class); - private static final String PORTAL_NAME = "cbioportal"; - - // ~ Methods - // ======================================================================================================== - - public static String generateTokenByHmacSHA256(String username, String secretKey, String timeStamp) { - try { - String message = PORTAL_NAME + "?" + "user=" + username + "&t=" + timeStamp; - - Mac sha256_HMAC = Mac.getInstance("HmacSHA256"); - SecretKeySpec secret_key = new SecretKeySpec(secretKey.getBytes(), "HmacSHA256"); - sha256_HMAC.init(secret_key); - String hash = Base64.getEncoder().encodeToString(sha256_HMAC.doFinal(message.getBytes())); - return hash; - } - catch (Exception e) { - if (logger.isErrorEnabled()) { - logger.error("Error generate msk Whole slide viewer token: " + e.getMessage()); - } - return null; - } - } -} diff --git a/src/main/java/org/cbioportal/service/util/ProfiledCasesCounter.java b/src/main/java/org/cbioportal/service/util/ProfiledCasesCounter.java deleted file mode 100644 index 874a2cd0652..00000000000 --- a/src/main/java/org/cbioportal/service/util/ProfiledCasesCounter.java +++ /dev/null @@ -1,220 +0,0 @@ -package org.cbioportal.service.util; - -import org.apache.commons.math3.util.Pair; -import org.cbioportal.model.AlterationCountBase; -import org.cbioportal.model.AlterationCountByGene; -import org.cbioportal.model.AlterationCountByStructuralVariant; -import org.cbioportal.model.GenePanel; -import org.cbioportal.model.GenePanelData; -import org.cbioportal.model.GenePanelToGene; -import org.cbioportal.service.GenePanelService; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -import java.util.Arrays; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.function.Function; -import java.util.stream.Collectors; - -@Component -public class ProfiledCasesCounter { - - @Autowired - private GenePanelService genePanelService; - - Function sampleUniqueIdentifier = sample -> sample.getStudyId() + sample.getSampleId(); - Function patientUniqueIdentifier = sample -> sample.getStudyId() + sample.getPatientId(); - - private enum ProfiledCaseType { - SAMPLE, PATIENT - } - - public void calculate(List alterationCounts, - List genePanelDataList, - boolean includeMissingAlterationsFromGenePanel, - Function caseUniqueIdentifier) { - - ProfiledCaseType profiledCaseType = (caseUniqueIdentifier == patientUniqueIdentifier) ? - ProfiledCaseType.PATIENT : ProfiledCaseType.SAMPLE; - Map> casesWithDataInGenePanel = extractCasesWithDataInGenePanel(genePanelDataList, caseUniqueIdentifier); - List genePanels = new ArrayList<>(); - if (!casesWithDataInGenePanel.isEmpty()) { - genePanels = genePanelService.fetchGenePanels(new ArrayList<>(casesWithDataInGenePanel.keySet()), "DETAILED"); - } - - Map, List> geneToGenePanel = new HashMap<>(); - for (GenePanel genePanel : genePanels) { - for (GenePanelToGene genePanelToGene : genePanel.getGenes()) { - // TODO I am not sure whether it is smart to include the HUGO gene suymbol in the key here. - // What if two panels have the same Entrez gene id with different Hugo gene symbols? If that situation - // can never occur, better not include the HUGO symbol in the key and only use entrez gene id. It confuses - // developers that may think it is an important key element. - Pair key = new Pair<>(genePanelToGene.getEntrezGeneId(), genePanelToGene.getHugoGeneSymbol()); - if (geneToGenePanel.containsKey(key)) { - geneToGenePanel.get(key).add(genePanel); - } else { - List geneGenePanelList = new ArrayList<>(); - geneGenePanelList.add(genePanel); - geneToGenePanel.put(key, geneGenePanelList); - } - } - } - - List genePanelData = genePanelDataList - .stream() - .filter(GenePanelData::getProfiled) - .collect(Collectors.toList()); - - Set profiledCases = genePanelData - .stream() - // there can be duplicate patient or sample id, append study id - .map(caseUniqueIdentifier) - .collect(Collectors.toSet()); - int profiledCasesCount = profiledCases.size(); - - // here we look for cases where none of the profiles have gene panel ids - // a case with at least one profile with gene panel id is considered as a case with gene panel data - // so a case is considered without panel data only if none of the profiles has a gene panel id - - // first identify cases with gene panel data - Set casesWithPanelData = genePanelData - .stream() - .filter(g -> g.getGenePanelId() != null) - // there can be duplicate patient or sample id, append study id - .map(caseUniqueIdentifier) - .collect(Collectors.toSet()); - - // find all unique cases - Set casesWithoutPanelData = genePanelData - .stream() - // there can be duplicate patient or sample id, append study id - .map(caseUniqueIdentifier) - .collect(Collectors.toSet()); - - // removing cases with panel data from all unique cases gives us the cases without panel data - casesWithoutPanelData.removeAll(casesWithPanelData); - - for (T alterationCount : alterationCounts) { - Set totalProfiledPatients = new HashSet<>(); - Set allMatchingGenePanelIds = new HashSet<>(); - int totalProfiledSamples = 0; - // different calculations depending on if gene is linked to gene panels - if (alterationIsCoveredByGenePanel(alterationCount, geneToGenePanel)) { - // for every gene panel associated containing the gene, use the sum of unique cases - // as well as cases without panel data - for (GenePanel genePanel : getGenePanelsForAlterationCount(alterationCount, geneToGenePanel)) { - allMatchingGenePanelIds.add(genePanel.getStableId()); - if (profiledCaseType == ProfiledCaseType.PATIENT) { - totalProfiledPatients.addAll(casesWithDataInGenePanel.get(genePanel.getStableId())); - } else { - totalProfiledSamples += casesWithDataInGenePanel.get(genePanel.getStableId()).size(); - } - } - if (profiledCaseType == ProfiledCaseType.PATIENT) { - totalProfiledPatients.addAll(casesWithoutPanelData); - alterationCount.setNumberOfProfiledCases(totalProfiledPatients.size()); - } else { - totalProfiledSamples += casesWithoutPanelData.size(); - alterationCount.setNumberOfProfiledCases(totalProfiledSamples); - } - } else { - // we use profiledCasesCount instead of casesWithoutPanelData to - // prevent a divide by zero error which can happen for targeted studies - // in which certain genes have events that are not captured by the panel. - alterationCount.setNumberOfProfiledCases(profiledCasesCount); - } - alterationCount.setMatchingGenePanelIds(allMatchingGenePanelIds); - } - - if (includeMissingAlterationsFromGenePanel) { - Set genesWithAlteration = alterationCounts.stream() - .flatMap(count -> Arrays.stream(count.getEntrezGeneIds())) - .collect(Collectors.toSet()); - - geneToGenePanel.entrySet().forEach(entry -> { - Integer entrezGeneId = entry.getKey().getFirst(); - String hugoGeneSymbol = entry.getKey().getSecond(); - // add alterationCount object where there are no alterations but have genePanel - // object - if (!genesWithAlteration.contains(entrezGeneId)) { - AlterationCountByGene alterationCountByGene = new AlterationCountByGene(); - - Set totalProfiledPatients = new HashSet<>(); - Set allMatchingGenePanelIds = new HashSet<>(); - int totalProfiledSamples = 0; - for (GenePanel genePanel : geneToGenePanel.get(new Pair<>(entrezGeneId, hugoGeneSymbol))) { - allMatchingGenePanelIds.add(genePanel.getStableId()); - if (profiledCaseType == ProfiledCaseType.PATIENT) { - totalProfiledPatients.addAll(casesWithDataInGenePanel.get(genePanel.getStableId())); - } else { - totalProfiledSamples += casesWithDataInGenePanel.get(genePanel.getStableId()).size(); - } - } - if (profiledCaseType == ProfiledCaseType.PATIENT) { - totalProfiledPatients.addAll(casesWithoutPanelData); - } else { - totalProfiledSamples += casesWithoutPanelData.size(); - } - - alterationCountByGene.setEntrezGeneId(entrezGeneId); - alterationCountByGene.setMatchingGenePanelIds(allMatchingGenePanelIds); - if (profiledCaseType == ProfiledCaseType.PATIENT) { - alterationCountByGene.setNumberOfProfiledCases(totalProfiledPatients.size()); - } else { - alterationCountByGene.setNumberOfProfiledCases(totalProfiledSamples); - } - alterationCountByGene.setNumberOfAlteredCases(0); - alterationCountByGene.setTotalCount(0); - alterationCountByGene.setHugoGeneSymbol(hugoGeneSymbol); - - alterationCounts.add((T) alterationCountByGene); - } - }); - } - } - - private Map> extractCasesWithDataInGenePanel( - List genePanelDataList, - Function caseUniqueIdentifier) { - - Map> casesWithDataInGenePanel = new HashMap<>(); - // loop through all membership records -- ignore any where g.getGenePanelId == null - for (GenePanelData genePanelDataRecord : genePanelDataList) { - String associatedGenePanel = genePanelDataRecord.getGenePanelId(); - if (associatedGenePanel != null) { - casesWithDataInGenePanel.putIfAbsent(associatedGenePanel, new HashSet<>()); - Set casesForThisGenePanel = casesWithDataInGenePanel.get(associatedGenePanel); - casesForThisGenePanel.add(caseUniqueIdentifier.apply(genePanelDataRecord)); - } - } - return casesWithDataInGenePanel; - } - - private boolean alterationIsCoveredByGenePanel(T alterationCount, Map, List> entrezIdToGenePanel) { - return !getGenePanelsForAlterationCount(alterationCount, entrezIdToGenePanel).isEmpty(); - } - - private List getGenePanelsForAlterationCount(T alterationCount, Map, List> entrezIdToGenePanel) { - if (alterationCount instanceof AlterationCountByGene) { - Integer entrezId = ((AlterationCountByGene) alterationCount).getEntrezGeneId(); - String hugoSymbol = ((AlterationCountByGene) alterationCount).getHugoGeneSymbol(); - return entrezIdToGenePanel.getOrDefault(new Pair<>(entrezId, hugoSymbol), new ArrayList<>()); - } - if (alterationCount instanceof AlterationCountByStructuralVariant) { - Integer gene1EntrezId = ((AlterationCountByStructuralVariant) alterationCount).getGene1EntrezGeneId(); - String gene1HugoSymbol = ((AlterationCountByStructuralVariant) alterationCount).getGene1HugoGeneSymbol(); - Integer gene2EntrezId = ((AlterationCountByStructuralVariant) alterationCount).getGene2EntrezGeneId(); - String gene2HugoSymbol = ((AlterationCountByStructuralVariant) alterationCount).getGene2HugoGeneSymbol(); - List panels = entrezIdToGenePanel.getOrDefault(new Pair<>(gene1EntrezId, gene2HugoSymbol), new ArrayList<>()); - panels.addAll(entrezIdToGenePanel.getOrDefault(new Pair<>(gene2EntrezId, gene2HugoSymbol), new ArrayList<>())); - return panels.stream().distinct().collect(Collectors.toList()); - } - throw new IllegalArgumentException("At present only AlterationCountByGene or AlterationCountByStructuralVariant are " + - "supported."); - } -} diff --git a/src/main/java/org/cbioportal/service/util/SessionServiceConfig.java b/src/main/java/org/cbioportal/service/util/SessionServiceConfig.java deleted file mode 100644 index ff0adc546ef..00000000000 --- a/src/main/java/org/cbioportal/service/util/SessionServiceConfig.java +++ /dev/null @@ -1,16 +0,0 @@ -package org.cbioportal.service.util; - -import com.fasterxml.jackson.databind.DeserializationFeature; -import com.fasterxml.jackson.databind.ObjectMapper; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; - -@Configuration -public class SessionServiceConfig { - - @Bean - public ObjectMapper sessionServiceObjectMapper() { - return new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); - } - -} \ No newline at end of file diff --git a/src/main/java/org/cbioportal/service/util/SessionServiceRequestHandler.java b/src/main/java/org/cbioportal/service/util/SessionServiceRequestHandler.java deleted file mode 100644 index af9749ee052..00000000000 --- a/src/main/java/org/cbioportal/service/util/SessionServiceRequestHandler.java +++ /dev/null @@ -1,153 +0,0 @@ -package org.cbioportal.service.util; - -import static org.cbioportal.utils.removeme.Session.*; - - -import java.nio.charset.Charset; -import java.util.Collections; -import java.util.List; - -import com.mongodb.BasicDBObject; -import org.apache.commons.codec.binary.Base64; -import org.apache.commons.lang3.StringUtils; -import org.cbioportal.web.parameter.VirtualStudy; -import org.cbioportal.web.parameter.VirtualStudyData; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.core.ParameterizedTypeReference; -import org.springframework.http.HttpEntity; -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpMethod; -import org.springframework.http.HttpStatusCode; -import org.springframework.http.ResponseEntity; -import org.springframework.stereotype.Component; -import org.springframework.web.client.RestTemplate; - -@Component -public class SessionServiceRequestHandler { - - private static final Logger LOG = LoggerFactory.getLogger(SessionServiceRequestHandler.class); - - @Value("${session.service.url:}") - private String sessionServiceURL; - - @Value("${session.service.user:}") - private String sessionServiceUser; - - @Value("${session.service.password:}") - private String sessionServicePassword; - - private Boolean isBasicAuthEnabled() { - return isSessionServiceEnabled() && sessionServicePassword != null && !sessionServicePassword.equals(""); - } - - public Boolean isSessionServiceEnabled() { - return !StringUtils.isEmpty(sessionServiceURL); - } - - public HttpHeaders getHttpHeaders() { - - return new HttpHeaders() { - { - if (isBasicAuthEnabled()) { - String auth = sessionServiceUser + ":" + sessionServicePassword; - byte[] encodedAuth = Base64.encodeBase64(auth.getBytes(Charset.forName("US-ASCII"))); - String authHeader = "Basic " + new String(encodedAuth); - set("Authorization", authHeader); - } - set("Content-Type", "application/json"); - } - }; - } - - public String getSessionDataJson(SessionType type, String id) throws Exception { - - RestTemplate restTemplate = new RestTemplate(); - - // add basic authentication in header - HttpEntity headers = new HttpEntity<>(getHttpHeaders()); - ResponseEntity responseEntity = restTemplate.exchange(sessionServiceURL + type + "/" + id, - HttpMethod.GET, headers, String.class); - - return responseEntity.getBody(); - } - - /** - * Gets virtual study by id - * @param id - id of the virtual study to read - * @return virtual study - */ - public VirtualStudy getVirtualStudyById(String id) { - ResponseEntity responseEntity = new RestTemplate() - .exchange(sessionServiceURL + "/virtual_study/" + id, - HttpMethod.GET, - new HttpEntity<>(getHttpHeaders()), - VirtualStudy.class); - HttpStatusCode statusCode = responseEntity.getStatusCode(); - VirtualStudy virtualStudy = responseEntity.getBody(); - if (!statusCode.is2xxSuccessful() || virtualStudy == null) { - LOG.error("The downstream server replied with statusCode={} and body={}." + - " Replying with the same status code to the client.", - statusCode, virtualStudy); - throw new IllegalStateException("The downstream server response is not successful"); - } - return responseEntity.getBody(); - } - - /** - * Get list of virtual studies accessible to user - * @param username - user for whom get list of virtual studies - * @return - list of virtual studies - */ - public List getVirtualStudiesAccessibleToUser(String username) { - BasicDBObject basicDBObject = new BasicDBObject(); - basicDBObject.put("data.users", username); - ResponseEntity> responseEntity = new RestTemplate().exchange( - sessionServiceURL + "/virtual_study/query/fetch", - HttpMethod.POST, - new HttpEntity<>(basicDBObject.toString(), getHttpHeaders()), - new ParameterizedTypeReference<>() { - }); - - return responseEntity.getBody(); - } - - /** - * Creates a virtual study out of virtual study definition (aka virtualStudyData) - * @param virtualStudyData - definition of virtual study - * @return virtual study object with id and the virtualStudyData - */ - public VirtualStudy createVirtualStudy(VirtualStudyData virtualStudyData) { - ResponseEntity responseEntity = new RestTemplate().exchange( - sessionServiceURL + "/virtual_study", - HttpMethod.POST, - new HttpEntity<>(virtualStudyData, getHttpHeaders()), - new ParameterizedTypeReference<>() { - }); - - return responseEntity.getBody(); - } - - - /** - * Soft delete of the virtual study by de-associating all assigned users. - * @param id - id of virtual study to soft delete - */ - public void softRemoveVirtualStudy(String id) { - VirtualStudy virtualStudy = getVirtualStudyById(id); - VirtualStudyData data = virtualStudy.getData(); - data.setUsers(Collections.emptySet()); - updateVirtualStudy(virtualStudy); - } - - /** - * Updates virtual study - * @param virtualStudy - virtual study to update - */ - public void updateVirtualStudy(VirtualStudy virtualStudy) { - new RestTemplate() - .put(sessionServiceURL + "/virtual_study/" + virtualStudy.getId(), - new HttpEntity<>(virtualStudy.getData(), getHttpHeaders())); - } -} diff --git a/src/main/java/org/cbioportal/service/util/StudyViewColumnarServiceUtil.java b/src/main/java/org/cbioportal/service/util/StudyViewColumnarServiceUtil.java deleted file mode 100644 index 981dbb80cf2..00000000000 --- a/src/main/java/org/cbioportal/service/util/StudyViewColumnarServiceUtil.java +++ /dev/null @@ -1,176 +0,0 @@ -package org.cbioportal.service.util; - -import org.cbioportal.model.CaseListDataCount; -import org.cbioportal.model.ClinicalAttribute; -import org.cbioportal.model.ClinicalDataCount; -import org.cbioportal.model.ClinicalDataCountItem; -import org.cbioportal.model.GenomicDataCount; -import org.cbioportal.model.GenomicDataCountItem; -import org.cbioportal.web.parameter.GenomicDataFilter; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - -public class StudyViewColumnarServiceUtil { - - private StudyViewColumnarServiceUtil() {} - - public static final String MUTATED_COUNT = "mutatedCount"; - public static final String NOT_MUTATED_COUNT = "notMutatedCount"; - public static final String NOT_PROFILED_COUNT = "notProfiledCount"; - - public static List mergeClinicalDataCounts( - List items - ) { - items.forEach(attr -> { - Map> countsPerType = attr.getCounts().stream() - .collect(Collectors.groupingBy(ClinicalDataCount::getValue)); - List res = countsPerType.entrySet().stream().map(entry -> { - ClinicalDataCount mergedCount = new ClinicalDataCount(); - mergedCount.setAttributeId(attr.getAttributeId()); - mergedCount.setValue(entry.getKey()); - mergedCount.setCount(entry.getValue().stream().mapToInt(ClinicalDataCount::getCount).sum()); - return mergedCount; - }).toList(); - attr.setCounts(res); - }); - return items; - } - - public static List addClinicalDataCountsForMissingAttributes( - List counts, - List attributes, - Integer filteredSampleCount, - Integer filteredPatientCount - ) { - Map map = counts.stream() - .collect(Collectors.toMap(ClinicalDataCountItem::getAttributeId, item -> item)); - - List result = new ArrayList<>(counts); - - attributes.forEach(attr -> { - Integer count = attr.getPatientAttribute().booleanValue() ? filteredPatientCount : filteredSampleCount; - - if (!map.containsKey(attr.getAttrId())) { - ClinicalDataCountItem newItem = new ClinicalDataCountItem(); - newItem.setAttributeId(attr.getAttrId()); - ClinicalDataCount countObj = new ClinicalDataCount(); - countObj.setCount(count); - countObj.setValue("NA"); - countObj.setAttributeId(attr.getAttrId()); - newItem.setCounts(List.of(countObj)); - result.add(newItem); - } - }); - - return result; - } - - public static List mergeGenomicDataCounts(List sampleCounts) { - Map> countsPerType = sampleCounts.stream() - .collect(Collectors.groupingBy(GenomicDataCount::getValue)); - - List mergedCounts = new ArrayList<>(); - for (Map.Entry> entry : countsPerType.entrySet()) { - var dc = new GenomicDataCount(); - dc.setValue(entry.getKey()); - dc.setLabel(entry.getValue().get(0).getLabel()); - Integer sum = entry.getValue().stream() - .map(GenomicDataCount::getCount) - .collect(Collectors.summingInt(Integer::intValue)); - dc.setCount(sum); - mergedCounts.add(dc); - } - return mergedCounts; - } - - public static List mergeCaseListCounts(List counts) { - Map> countsPerListType = counts.stream() - .collect((Collectors.groupingBy(CaseListDataCount::getValue))); - - // different cancer studies combined into one cohort will have separate case lists - // of a given type (e.g. rppa). We need to merge the counts for these - // different lists based on the type and choose a label - // this code just picks the first label, which assumes that the labels will match for a give type - List mergedCounts = new ArrayList<>(); - for (Map.Entry> entry : countsPerListType.entrySet()) { - var dc = new CaseListDataCount(); - dc.setValue(entry.getKey()); - // here just snatch the label of the first profile - dc.setLabel(entry.getValue().get(0).getLabel()); - Integer sum = entry.getValue().stream() - .map(x -> x.getCount()) - .collect(Collectors.summingInt(Integer::intValue)); - dc.setCount(sum); - mergedCounts.add(dc); - } - return mergedCounts; - } - - /** - * Normalizes data counts by merging attribute values in a case-insensitive way. - * For example attribute values "TRUE", "True", and 'true' will be merged into a single aggregated count. - * This method assumes that all the counts in the given dataCounts list has the same attributeId. - * - * @param dataCounts list of data counts for a single attribute - * - * @return normalized list of data counts - */ - public static List normalizeDataCounts(List dataCounts) { - Collection normalizedDataCounts = dataCounts - .stream() - .collect( - Collectors.groupingBy( - c -> c.getValue().toLowerCase(), - Collectors.reducing(new ClinicalDataCount(), (count1, count2) -> { - // assuming attribute ids are the same for all data counts, just pick the first one - String attributeId = - count1.getAttributeId() != null - ? count1.getAttributeId() - : count2.getAttributeId(); - - // pick the value in a deterministic way by prioritizing lower case over upper case. - // for example, 'True' will be picked in case of 2 different values like 'TRUE', and 'True', - // and 'true' will be picked in case of 3 different values like 'TRUE', 'True', and 'true' - String value = count1.getValue() != null - ? count1.getValue() - : count2.getValue(); - if (count1.getValue() != null && count2.getValue() != null) { - value = count1.getValue().compareTo(count2.getValue()) > 0 - ? count1.getValue() - : count2.getValue(); - } - - // aggregate counts for the merged values - Integer count = (count1.getCount() != null ? count1.getCount(): 0) + - (count2.getCount() != null ? count2.getCount(): 0); - - ClinicalDataCount aggregated = new ClinicalDataCount(); - aggregated.setAttributeId(attributeId); - aggregated.setValue(value); - aggregated.setCount(count); - return aggregated; - }) - ) - ) - .values(); - - return new ArrayList<>(normalizedDataCounts); - } - - public static GenomicDataCountItem createGenomicDataCountItemFromMutationCounts(GenomicDataFilter genomicDataFilter, Map counts) { - List genomicDataCountList = new ArrayList<>(); - if (counts.getOrDefault(MUTATED_COUNT, 0) > 0) - genomicDataCountList.add(new GenomicDataCount("Mutated", "MUTATED", counts.get(MUTATED_COUNT), counts.get(MUTATED_COUNT))); - if (counts.getOrDefault(NOT_MUTATED_COUNT, 0) > 0) - genomicDataCountList.add(new GenomicDataCount("Not Mutated", "NOT_MUTATED", counts.get(NOT_MUTATED_COUNT), counts.get(NOT_MUTATED_COUNT))); - if (counts.getOrDefault(NOT_PROFILED_COUNT, 0) > 0) - genomicDataCountList.add(new GenomicDataCount("Not Profiled", "NOT_PROFILED", counts.get(NOT_PROFILED_COUNT), counts.get(NOT_PROFILED_COUNT))); - return new GenomicDataCountItem(genomicDataFilter.getHugoGeneSymbol(), "mutations", genomicDataCountList); - } - - -} \ No newline at end of file diff --git a/src/main/java/org/cbioportal/shared/DataFilterUtil.java b/src/main/java/org/cbioportal/shared/DataFilterUtil.java new file mode 100644 index 00000000000..4643e0935b1 --- /dev/null +++ b/src/main/java/org/cbioportal/shared/DataFilterUtil.java @@ -0,0 +1,134 @@ +package org.cbioportal.shared; + +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.List; +import org.cbioportal.legacy.web.parameter.DataFilter; +import org.cbioportal.legacy.web.parameter.DataFilterValue; + +public abstract class DataFilterUtil { + private DataFilterUtil() {} + + /** + * Merge the range of numerical bins in DataFilters to reduce the number of scans that runs on the + * database when filtering. + */ + public static List mergeDataFilters(List filters) { + // this should throw error or move to all binning endpoints in the future for input validation + if (!areValidFilters(filters)) { + return filters; + } + + boolean hasNumericalValue = false; + List mergedDataFilters = new ArrayList<>(); + + for (T filter : filters) { + List mergedValues = new ArrayList<>(); + List nonNumericalValues = new ArrayList<>(); + + // record the start and end of current merging range + BigDecimal mergedStart = null; + BigDecimal mergedEnd = null; + // for each value + for (DataFilterValue dataFilterValue : filter.getValues()) { + // if it is non-numerical, leave it as is + if (dataFilterValue.getValue() != null) { + nonNumericalValues.add(dataFilterValue); + continue; + } + // else it is numerical so start merging process + hasNumericalValue = true; + BigDecimal start = dataFilterValue.getStart(); + BigDecimal end = dataFilterValue.getEnd(); + + // if current merging range is null, we take current bin's range + if (mergedStart == null && mergedEnd == null) { + mergedStart = start; + mergedEnd = end; + } + // else we already has a merging range, we check if this one is consecutive of our range + else if (mergedEnd.equals(start)) { + // if true, we expand our range + mergedEnd = end; + } else { + // otherwise it's a gap, so we save our current range first, and then use current bin to + // start the next range + mergedValues.add(new DataFilterValue(mergedStart, mergedEnd)); + mergedStart = start; + mergedEnd = end; + } + } + + // in the end we need to save the final range, but if everything is non-numerical then no need + // to + if (hasNumericalValue) { + mergedValues.add(new DataFilterValue(mergedStart, mergedEnd)); + } + mergedValues.addAll(nonNumericalValues); + filter.setValues(mergedValues); + mergedDataFilters.add(filter); + } + + return mergedDataFilters; + } + + public static boolean areValidFilters(List filters) { + if (filters == null || filters.isEmpty()) { + return false; + } + + for (T filter : filters) { + if (!isValidFilter(filter)) { + return false; + } + } + return true; + } + + private static boolean isValidFilter(T filter) { + if (filter == null || filter.getValues() == null || filter.getValues().isEmpty()) { + return false; + } + + BigDecimal start = null; + BigDecimal end = null; + for (DataFilterValue value : filter.getValues()) { + if (!validateDataFilterValue(value, start, end)) { + return false; + } + // update start and end values to check next bin range + if (value.getStart() != null) { + start = value.getStart(); + } + if (value.getEnd() != null) { + end = value.getEnd(); + } + } + return true; + } + + private static boolean validateDataFilterValue( + DataFilterValue value, BigDecimal lastStart, BigDecimal lastEnd) { + // non-numerical value should not have numerical value + if (value.getValue() != null) { + return value.getStart() == null && value.getEnd() == null; + } + + // check if start < end + if (value.getStart() != null + && value.getEnd() != null + && value.getStart().compareTo(value.getEnd()) >= 0) { + return false; + } + + // check if start stays increasing and no overlapping + if (value.getStart() != null + && ((lastStart != null && lastStart.compareTo(value.getStart()) >= 0) + || (lastEnd != null && value.getStart().compareTo(lastEnd) < 0))) { + return false; + } + + // check if end stays increasing + return value.getEnd() == null || lastEnd == null || lastEnd.compareTo(value.getEnd()) < 0; + } +} diff --git a/src/main/java/org/cbioportal/shared/SortAndSearchCriteria.java b/src/main/java/org/cbioportal/shared/SortAndSearchCriteria.java new file mode 100644 index 00000000000..84c137d3eae --- /dev/null +++ b/src/main/java/org/cbioportal/shared/SortAndSearchCriteria.java @@ -0,0 +1,12 @@ +package org.cbioportal.shared; + +public record SortAndSearchCriteria(String searchTerm, String sortField, String sortOrder) { + boolean isSortable() { + return (sortField != null && !sortField.isEmpty()) + && (sortOrder != null && !sortOrder.isEmpty()); + } + + boolean isSearchable() { + return searchTerm != null && !searchTerm.isEmpty(); + } +} diff --git a/src/main/java/org/cbioportal/shared/enums/ProjectionType.java b/src/main/java/org/cbioportal/shared/enums/ProjectionType.java new file mode 100644 index 00000000000..3ec5907db30 --- /dev/null +++ b/src/main/java/org/cbioportal/shared/enums/ProjectionType.java @@ -0,0 +1,72 @@ +package org.cbioportal.shared.enums; + +/** + * Enum representing different levels of data projection for API responses. + * + *

This enum is used in the domain layer to control the amount of data included in API + * responses, ensuring that only the necessary fields are returned based on the specific use case. + * By limiting the data returned, this enum helps improve performance, reduce network overhead, and + * simplify client-side processing. + * + *

Each projection level corresponds to a specific set of fields or data representation, allowing + * the domain layer to tailor responses to the requirements of the client or the context of the + * request. + * + *

Usage Example: + * + *

{@code
+ * public ResponseEntity getEntity(@RequestParam Projection projection) {
+ *     Entity entity = entityService.getEntity(projection);
+ *     EntityDto dto = entityMapper.toDto(entity, projection);
+ *     return ResponseEntity.ok(dto);
+ * }
+ * }
+ */ +public enum ProjectionType { + + /** + * ID Projection - Includes only the essential identifier fields of the entity. + * + *

This projection is suitable for scenarios where only the unique identifier of the entity is + * required, such as when referencing the entity in another context or performing lightweight + * operations. + * + *

Example Use Case: Fetching entity IDs for batch processing or creating relationships + * between entities. + */ + ID, + + /** + * SUMMARY Projection - Includes a limited set of fields to provide a high-level overview + * of the entity. + * + *

This projection is useful for lightweight data representations, such as displaying a list of + * entities in a UI or providing a quick summary without the full details. + * + *

Example Use Case: Displaying a list of entities in a dropdown or search results. + */ + SUMMARY, + + /** + * DETAILED Projection - Includes all available fields of the entity. + * + *

This projection provides a complete representation of the entity, including all attributes + * and relationships. It is best suited for scenarios where the client requires a full view of the + * entity. + * + *

Example Use Case: Viewing the full details of an entity in a detailed view or edit + * form. + */ + DETAILED, + + /** + * META Projection - Focuses on metadata, such as counts, statistics, or aggregated + * information about the underlying data. + * + *

This projection is useful for scenarios where the client needs summary information rather + * than individual records, such as displaying totals, averages, or other aggregated data. + * + *

Example Use Case: Displaying dashboard metrics or summary reports. + */ + META +} diff --git a/src/main/java/org/cbioportal/shared/util/ClinicalDataCountItemUtil.java b/src/main/java/org/cbioportal/shared/util/ClinicalDataCountItemUtil.java new file mode 100644 index 00000000000..ae63edc4c4f --- /dev/null +++ b/src/main/java/org/cbioportal/shared/util/ClinicalDataCountItemUtil.java @@ -0,0 +1,27 @@ +package org.cbioportal.shared.util; + +import java.util.List; +import java.util.stream.Collectors; +import org.cbioportal.legacy.model.ClinicalDataCount; +import org.cbioportal.legacy.model.ClinicalDataCountItem; +import org.cbioportal.legacy.service.util.StudyViewColumnarServiceUtil; + +public abstract class ClinicalDataCountItemUtil { + private ClinicalDataCountItemUtil() {} + + public static List generateDataCountItems( + List dataCounts) { + return dataCounts.stream() + .collect(Collectors.groupingBy(ClinicalDataCount::getAttributeId)) + .entrySet() + .parallelStream() + .map( + e -> { + ClinicalDataCountItem item = new ClinicalDataCountItem(); + item.setAttributeId(e.getKey()); + item.setCounts(StudyViewColumnarServiceUtil.normalizeDataCounts(e.getValue())); + return item; + }) + .toList(); + } +} diff --git a/src/main/java/org/cbioportal/shared/util/SampleDataFilterUtil.java b/src/main/java/org/cbioportal/shared/util/SampleDataFilterUtil.java new file mode 100644 index 00000000000..dfb1072269d --- /dev/null +++ b/src/main/java/org/cbioportal/shared/util/SampleDataFilterUtil.java @@ -0,0 +1,40 @@ +package org.cbioportal.shared.util; + +import java.util.ArrayList; +import java.util.List; +import org.cbioportal.legacy.web.parameter.SampleFilter; +import org.cbioportal.legacy.web.parameter.SampleIdentifier; +import org.cbioportal.legacy.web.util.UniqueKeyExtractor; +import org.springframework.data.util.Pair; +import org.springframework.data.util.StreamUtils; + +public abstract class SampleDataFilterUtil { + private SampleDataFilterUtil() {} + + public static Pair, List> extractStudyAndSampleIds( + SampleFilter sampleFilter) { + List studyIds = new ArrayList<>(); + List sampleIds = new ArrayList<>(); + + if (sampleFilter.getSampleIdentifiers() != null) { + for (SampleIdentifier sampleIdentifier : sampleFilter.getSampleIdentifiers()) { + studyIds.add(sampleIdentifier.getStudyId()); + sampleIds.add(sampleIdentifier.getSampleId()); + } + } else { + UniqueKeyExtractor.extractUniqueKeys(sampleFilter.getUniqueSampleKeys(), studyIds, sampleIds); + } + + return Pair.of(studyIds, sampleIds); + } + + public static String[] generateStudyAndSampleTuples( + List studyIds, List sampleIds) { + return StreamUtils.zip( + studyIds.stream(), + sampleIds.stream(), + (studyId, sampleId) -> String.format("%s_%s", studyId, sampleId)) + .toList() + .toArray(new String[sampleIds.size()]); + } +} diff --git a/src/main/java/org/cbioportal/url_shortener/URLShortenerController.java b/src/main/java/org/cbioportal/url_shortener/URLShortenerController.java deleted file mode 100644 index 00804ca9769..00000000000 --- a/src/main/java/org/cbioportal/url_shortener/URLShortenerController.java +++ /dev/null @@ -1,38 +0,0 @@ -package org.cbioportal.url_shortener; - -import fr.plaisance.bitly.Bit; -import fr.plaisance.bitly.Bitly; -import org.apache.commons.validator.routines.UrlValidator; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; -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.bind.annotation.RestController; - -// TODO Consider creating separate DispatcherServlets as in the original web.xml -// See: https://stackoverflow.com/a/30686733/11651683 -@RestController -public class URLShortenerController { - - @Value("${bitly.access.token}") - private String bitlyAccessToken; - - private Bitly bitly ; - private UrlValidator urlValidator = new UrlValidator(); - - @RequestMapping(path = "/api/url-shortener", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) - public ResponseEntity urlShortener(@RequestParam String url) { - - if (urlValidator.isValid(url)) { - if (bitly == null) { - bitly = Bit.ly(bitlyAccessToken); - } - return new ResponseEntity<>(new URLShortenerResponse(bitly.shorten(url), null), HttpStatus.OK); - } else { - return new ResponseEntity<>(new URLShortenerResponse(null, "Invalid URL"), HttpStatus.BAD_REQUEST); - } - } -} diff --git a/src/main/java/org/cbioportal/url_shortener/URLShortenerResponse.java b/src/main/java/org/cbioportal/url_shortener/URLShortenerResponse.java deleted file mode 100644 index bf822857b05..00000000000 --- a/src/main/java/org/cbioportal/url_shortener/URLShortenerResponse.java +++ /dev/null @@ -1,28 +0,0 @@ -package org.cbioportal.url_shortener; - -public class URLShortenerResponse { - - private String shortURL; - private String error; - - public URLShortenerResponse(String shortURL, String error) { - this.shortURL = shortURL; - this.error = error; - } - - public String getShortURL() { - return shortURL; - } - - public void setShortURL(String shortURL) { - this.shortURL = shortURL; - } - - public String getError() { - return error; - } - - public void setError(String error) { - this.error = error; - } -} diff --git a/src/main/java/org/cbioportal/utils/Encoder.java b/src/main/java/org/cbioportal/utils/Encoder.java deleted file mode 100644 index 4cbe5f3f8dc..00000000000 --- a/src/main/java/org/cbioportal/utils/Encoder.java +++ /dev/null @@ -1,22 +0,0 @@ -package org.cbioportal.utils; - -import java.util.Base64; - -public class Encoder { - - private Encoder() {} - - private static final Base64.Encoder BASE64_ENCODER = Base64.getEncoder().withoutPadding(); - private static final Base64.Decoder BASE64_DECODER = Base64.getDecoder(); - - public static final String DELIMITER = ":"; - - public static String calculateBase64(String firstInput, String secondInput) { - return BASE64_ENCODER.encodeToString((firstInput + DELIMITER + secondInput).getBytes()); - } - - public static String decodeBase64(String input) { - return new String(BASE64_DECODER.decode(input)); - } - -} diff --git a/src/main/java/org/cbioportal/utils/config/PropertyCondition.java b/src/main/java/org/cbioportal/utils/config/PropertyCondition.java deleted file mode 100644 index 42a61f22f9b..00000000000 --- a/src/main/java/org/cbioportal/utils/config/PropertyCondition.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (c) 2020 The Hyve B.V. - * - * This library is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS - * FOR A PARTICULAR PURPOSE. The software and documentation provided hereunder - * is on an "as is" basis, and Memorial Sloan-Kettering Cancer Center has no - * obligations to provide maintenance, support, updates, enhancements or - * modifications. In no event shall Memorial Sloan-Kettering Cancer Center be - * liable to any party for direct, indirect, special, incidental or - * consequential damages, including lost profits, arising out of the use of this - * software and its documentation, even if Memorial Sloan-Kettering Cancer - * Center has been advised of the possibility of such damage. - */ - -/* - * This file is part of cBioPortal. - * - * cBioPortal is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . -*/ -package org.cbioportal.utils.config; - -import org.cbioportal.utils.config.annotation.ConditionalOnProperty; -import org.springframework.context.annotation.Condition; -import org.springframework.context.annotation.ConditionContext; -import org.springframework.context.annotation.PropertySource; -import org.springframework.context.annotation.PropertySources; -import org.springframework.core.type.AnnotatedTypeMetadata; - -import java.util.Map; -import java.util.stream.Stream; - -@PropertySources({ - @PropertySource(value="classpath:application.properties", ignoreResourceNotFound=true), - @PropertySource(value="file:///${PORTAL_HOME}/application.properties", ignoreResourceNotFound=true) -}) -// Adapted from Spring Boot -public class PropertyCondition implements Condition { - - public PropertyCondition() { - super(); - } - - @Override - public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { - Map attributes = metadata.getAnnotationAttributes(ConditionalOnProperty.class.getName()); - String name = (String) attributes.get("name"); - Object requiredValue = attributes.get("havingValue"); - boolean matchIfMissing = (boolean) attributes.get("matchIfMissing"); - boolean isNot = (boolean) attributes.get("isNot"); - String actualValue = context.getEnvironment().getProperty(name); - if (actualValue == null) - return matchIfMissing; - if (requiredValue instanceof String[]) { - if (isNot) - return Stream.of((String[]) requiredValue).noneMatch(value -> value.equalsIgnoreCase(actualValue)); - return Stream.of((String[]) requiredValue).anyMatch(value -> value.equalsIgnoreCase(actualValue)); - } - return isNot ? !((String) requiredValue).equalsIgnoreCase(actualValue) : ((String) requiredValue).equalsIgnoreCase(actualValue); - } - -} diff --git a/src/main/java/org/cbioportal/utils/config/annotation/ConditionalOnProperty.java b/src/main/java/org/cbioportal/utils/config/annotation/ConditionalOnProperty.java deleted file mode 100644 index 57257cb4908..00000000000 --- a/src/main/java/org/cbioportal/utils/config/annotation/ConditionalOnProperty.java +++ /dev/null @@ -1,56 +0,0 @@ -package org.cbioportal.utils.config.annotation; - -import org.cbioportal.utils.config.PropertyCondition; -import org.springframework.context.annotation.Conditional; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/* -Examples: - -Only instantiate when property my_prop has value correct_value: -- @ConditionalOnProperty(name = "my_prop", havingValue = "correct_value") - -Only instantiate when property my_prop does not have value correct_value: -- @ConditionalOnProperty(name = "my_prop", havingValue = "correct_value", isNot = true) - -Only instantiate when property my_prop has value correct_value_1 or correct_value_2: -- @ConditionalOnProperty(name = "my_prop", havingValue = { "correct_value_1", "correct_value_2"} ) - -Only instantiate when property my_prop does not have value correct_value_1 and not value correct_value_2: -- @ConditionalOnProperty(name = "my_prop", havingValue = { "correct_value_1", "correct_value_2"}, isNot = true) - -Instantiate by default (when property is not defined in portal properties: -- @ConditionalOnProperty(name = "not_existing_prop", havingValue = "correct_value", matchIfMissing = true) -*/ - -@Target({ElementType.TYPE, ElementType.METHOD}) -@Retention(RetentionPolicy.RUNTIME) -@Conditional(value = PropertyCondition.class) -public @interface ConditionalOnProperty { - /** - * Name string. Name of the application property. - */ - String name() default ""; - - /** - * havingValue string [ ]. Value or values compared with application - * property (can be string or string[]). - */ - String[] havingValue() default {}; - - /** - * isNot boolean. When true a bean will be created when the application property is not - * equal to any of the values passed by havingValues. - */ - boolean isNot() default false; - - /** - * matchIfMissing boolean. Default behavior when application property is not defined. - * Default is false, which means the bean is not created when property is undefined. - */ - boolean matchIfMissing() default false; -} diff --git a/src/main/java/org/cbioportal/utils/removeme/Session.java b/src/main/java/org/cbioportal/utils/removeme/Session.java deleted file mode 100644 index 6d12df58d79..00000000000 --- a/src/main/java/org/cbioportal/utils/removeme/Session.java +++ /dev/null @@ -1,90 +0,0 @@ -package org.cbioportal.utils.removeme; - -import com.fasterxml.jackson.annotation.JsonInclude; -import com.fasterxml.jackson.annotation.JsonView; -import jakarta.validation.constraints.NotNull; -import jakarta.validation.constraints.Size; -import org.bson.Document; -import org.springframework.data.annotation.Id; -import org.springframework.util.DigestUtils; - -// TODO this class was taken from session service. The session service dependency had to be dropped -// since it forced cbioportal into autoconfiguration of mongoDB connections. -// When session service is updated reinstate the correct session service dependency. - -@JsonInclude(JsonInclude.Include.NON_NULL) -public class Session { - - public enum SessionType { - main_session, - virtual_study, - group, - comparison_session, - settings, - custom_data, - genomic_chart, - custom_gene_list - } - - @Id - private String id; - @NotNull - private String checksum; - @NotNull - private Object data; - @NotNull - @Size(min=3, message="source has a minimum length of 3") - private String source; - @NotNull - private SessionType type; - - - @JsonView(Session.Views.IdOnly.class) - public String getId() { - return id; - } - - public String getChecksum() { - return checksum; - } - - public void setData(Object data) { - if(data instanceof String) { - this.data = Document.parse((String)data); - } else { - this.data = data; - } - this.checksum = DigestUtils.md5DigestAsHex(this.data.toString().getBytes()); - } - - @JsonView(Session.Views.Full.class) - public Object getData() { - return data; - } - - public void setType(SessionType type) { - this.type = type; - } - - @JsonView(org.cbioportal.utils.removeme.Session.Views.Full.class) - public SessionType getType() { - return type; - } - - public void setSource(String source) { - this.source = source; - } - - @JsonView(Session.Views.Full.class) - public String getSource() { - return source; - } - - public static final class Views { - // show only id - public interface IdOnly {} - - // show all data - public interface Full extends Session.Views.IdOnly {} - } -} diff --git a/src/main/java/org/cbioportal/utils/security/AccessLevel.java b/src/main/java/org/cbioportal/utils/security/AccessLevel.java deleted file mode 100644 index bdd3c9024f0..00000000000 --- a/src/main/java/org/cbioportal/utils/security/AccessLevel.java +++ /dev/null @@ -1,5 +0,0 @@ -package org.cbioportal.utils.security; - -public enum AccessLevel { - READ, LIST -} diff --git a/src/main/java/org/cbioportal/utils/security/PortalSecurityConfig.java b/src/main/java/org/cbioportal/utils/security/PortalSecurityConfig.java deleted file mode 100644 index 068a1641d68..00000000000 --- a/src/main/java/org/cbioportal/utils/security/PortalSecurityConfig.java +++ /dev/null @@ -1,12 +0,0 @@ -package org.cbioportal.utils.security; - -public class PortalSecurityConfig { - - // This method is the equivalent of GlobalProperties.usersMustAuthenticate() - // method in the org.mskcc.cbio.portal.util package. Update both when changes are needed. - public static boolean userAuthorizationEnabled(String authenticate) { - return authenticate != null - && !authenticate.equals("false"); - } - -} diff --git a/src/main/java/org/cbioportal/utils/validation/AllowedValues.java b/src/main/java/org/cbioportal/utils/validation/AllowedValues.java deleted file mode 100644 index b42d3b0679b..00000000000 --- a/src/main/java/org/cbioportal/utils/validation/AllowedValues.java +++ /dev/null @@ -1,27 +0,0 @@ -package org.cbioportal.utils.validation; - -import jakarta.validation.Constraint; -import jakarta.validation.Payload; -import jakarta.validation.ReportAsSingleViolation; -import jakarta.validation.constraints.NotNull; - -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -@Documented -@Constraint(validatedBy = AllowedValuesValidatorImpl.class) -@Retention(RetentionPolicy.RUNTIME) -@Target(ElementType.FIELD) -@NotNull(message = "Value cannot be null") -@ReportAsSingleViolation -public @interface AllowedValues { - - String[] values() default {}; - String message() default "Value is not valid"; - Class[] groups() default {}; - Class[] payload() default {}; - -} \ No newline at end of file diff --git a/src/main/java/org/cbioportal/utils/validation/AllowedValuesValidatorImpl.java b/src/main/java/org/cbioportal/utils/validation/AllowedValuesValidatorImpl.java deleted file mode 100644 index 08eb9800b5c..00000000000 --- a/src/main/java/org/cbioportal/utils/validation/AllowedValuesValidatorImpl.java +++ /dev/null @@ -1,31 +0,0 @@ -package org.cbioportal.utils.validation; - -import jakarta.validation.ConstraintValidator; -import jakarta.validation.ConstraintValidatorContext; - -import java.util.Arrays; -import java.util.stream.Collectors; - -public class AllowedValuesValidatorImpl implements ConstraintValidator { - - String[] valueList; - - @Override - public boolean isValid(String value, ConstraintValidatorContext context) { - boolean isValid = Arrays.stream(valueList) - .anyMatch(allowedValue -> allowedValue.equals(value)); - if (!isValid) { - context.disableDefaultConstraintViolation(); - context.buildConstraintViolationWithTemplate("Allowed values are: " + - Arrays.stream(valueList).collect(Collectors.joining(", "))) - .addConstraintViolation(); - } - return isValid; - } - - @Override - public void initialize(AllowedValues constraintAnnotation) { - valueList = constraintAnnotation.values(); - } - -} \ No newline at end of file diff --git a/src/main/java/org/cbioportal/web/AlterationDriverAnnotationController.java b/src/main/java/org/cbioportal/web/AlterationDriverAnnotationController.java deleted file mode 100644 index 35880303b77..00000000000 --- a/src/main/java/org/cbioportal/web/AlterationDriverAnnotationController.java +++ /dev/null @@ -1,51 +0,0 @@ -package org.cbioportal.web; - -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.media.Content; -import io.swagger.v3.oas.annotations.media.Schema; -import io.swagger.v3.oas.annotations.responses.ApiResponse; -import io.swagger.v3.oas.annotations.tags.Tag; -import org.cbioportal.model.CustomDriverAnnotationReport; -import org.cbioportal.service.AlterationDriverAnnotationService; -import org.cbioportal.web.config.annotation.InternalApi; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestMethod; -import org.springframework.web.bind.annotation.RestController; - -import java.util.List; - -@InternalApi -@RestController() -@RequestMapping("/api") -@Validated -@Tag(name = "Custom driver annotations", description = " ") -public class AlterationDriverAnnotationController { - - @Autowired - private AlterationDriverAnnotationService alterationDriverAnnotationService; - - @PreAuthorize("hasPermission(#molecularProfileIds, 'Collection', T(org.cbioportal.utils.security.AccessLevel).READ)") - @RequestMapping(value = "/custom-driver-annotation-report/fetch", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE, - produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(summary = "Return availability of custom driver annotations for molecular profiles") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(schema = @Schema(implementation = CustomDriverAnnotationReport.class))) - public ResponseEntity fetchAlterationDriverAnnotationReport( - @Parameter(required = true, description = "List of Molecular Profile Ids") - @RequestBody List molecularProfileIds) { - - CustomDriverAnnotationReport customDriverAnnotationReport = alterationDriverAnnotationService.getCustomDriverAnnotationProps(molecularProfileIds); - - return new ResponseEntity<>(customDriverAnnotationReport, HttpStatus.OK); - } -} - diff --git a/src/main/java/org/cbioportal/web/AlterationEnrichmentController.java b/src/main/java/org/cbioportal/web/AlterationEnrichmentController.java deleted file mode 100644 index 2d635e1e3e9..00000000000 --- a/src/main/java/org/cbioportal/web/AlterationEnrichmentController.java +++ /dev/null @@ -1,80 +0,0 @@ -package org.cbioportal.web; - -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.media.ArraySchema; -import io.swagger.v3.oas.annotations.media.Content; -import io.swagger.v3.oas.annotations.media.Schema; -import io.swagger.v3.oas.annotations.responses.ApiResponse; -import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.validation.Valid; -import org.cbioportal.model.AlterationEnrichment; -import org.cbioportal.model.AlterationFilter; -import org.cbioportal.model.EnrichmentType; -import org.cbioportal.model.MolecularProfileCaseIdentifier; -import org.cbioportal.service.AlterationEnrichmentService; -import org.cbioportal.service.exception.MolecularProfileNotFoundException; -import org.cbioportal.web.config.annotation.InternalApi; -import org.cbioportal.web.parameter.MolecularProfileCasesGroupAndAlterationTypeFilter; -import org.cbioportal.web.parameter.MolecularProfileCasesGroupFilter; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestAttribute; -import org.springframework.web.bind.annotation.RequestBody; -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.bind.annotation.RestController; - -import java.util.Collection; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - -@InternalApi -@RestController() -@RequestMapping("/api") -@Validated -@Tag(name = "Alteration Enrichments", description = " ") -public class AlterationEnrichmentController { - - @Autowired - private AlterationEnrichmentService alterationEnrichmentService; - - @PreAuthorize("hasPermission(#involvedCancerStudies, 'Collection', T(org.cbioportal.utils.security.AccessLevel).READ)") - @RequestMapping(value = "/alteration-enrichments/fetch", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE, - produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(summary ="Fetch alteration enrichments in molecular profiles") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(array = @ArraySchema(schema = @Schema(implementation = AlterationEnrichment.class)))) - public ResponseEntity> fetchAlterationEnrichments( - @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface - @RequestAttribute(required = false, value = "involvedCancerStudies") Collection involvedCancerStudies, - @Parameter(hidden = true) - // prevent reference to this attribute in the swagger-ui interface. this attribute is needed for the @PreAuthorize tag above. - @Valid @RequestAttribute(required = false, value = "interceptedMolecularProfileCasesGroupFilters") List interceptedMolecularProfileCasesGroupFilters, - @Parameter(hidden = true) - @Valid @RequestAttribute(required = false, value = "alterationEventTypes") AlterationFilter alterationEventTypes, - @Parameter(description = "Type of the enrichment e.g. SAMPLE or PATIENT") - @RequestParam(defaultValue = "SAMPLE") EnrichmentType enrichmentType, - @Parameter(required = true, description = "List of groups containing sample identifiers and list of Alteration Types") - @Valid @RequestBody(required = false) MolecularProfileCasesGroupAndAlterationTypeFilter groupsAndAlterationTypes) throws MolecularProfileNotFoundException { - - Map> groupCaseIdentifierSet = interceptedMolecularProfileCasesGroupFilters.stream() - .collect(Collectors.toMap(MolecularProfileCasesGroupFilter::getName, - MolecularProfileCasesGroupFilter::getMolecularProfileCaseIdentifiers)); - - List alterationEnrichments = alterationEnrichmentService.getAlterationEnrichments( - groupCaseIdentifierSet, - enrichmentType, - alterationEventTypes); - - return new ResponseEntity<>(alterationEnrichments, HttpStatus.OK); - } -} - diff --git a/src/main/java/org/cbioportal/web/CacheController.java b/src/main/java/org/cbioportal/web/CacheController.java deleted file mode 100644 index c86982c2b6f..00000000000 --- a/src/main/java/org/cbioportal/web/CacheController.java +++ /dev/null @@ -1,82 +0,0 @@ -package org.cbioportal.web; - -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.media.Content; -import io.swagger.v3.oas.annotations.media.Schema; -import io.swagger.v3.oas.annotations.responses.ApiResponse; -import io.swagger.v3.oas.annotations.tags.Tag; -import org.cbioportal.service.CacheService; -import org.cbioportal.service.exception.CacheOperationException; -import org.cbioportal.web.config.annotation.InternalApi; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RequestHeader; -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.bind.annotation.RestController; - - -@RestController -@Validated -@InternalApi -@Tag(name = "Cache") -public class CacheController { - - @Autowired - private CacheService cacheService; - - @Value("${cache.endpoint.api-key:not set}") - private String requiredApiKey; - - @Value("${cache.endpoint.enabled:false}") - private boolean cacheEndpointEnabled; - - @RequestMapping(value = "/api/cache", method = RequestMethod.DELETE, produces = MediaType.TEXT_PLAIN_VALUE) - @Operation(summary ="Clear and reinitialize caches") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(schema = @Schema(implementation = String.class))) - public ResponseEntity clearAllCaches( - @Parameter(description = "Secret API key passed in HTTP header. The key is configured in application.properties of the portal instance.") - @RequestHeader(value = "X-API-KEY") String providedApiKey, - @Parameter(description = "Clear Spring-managed caches") - @RequestParam(defaultValue = "true", required = false) final boolean springManagedCache) - throws CacheOperationException { - if (!cacheEndpointEnabled) { - return new ResponseEntity<>("Cache endpoint is disabled for this instance.", HttpStatus.NOT_FOUND); - } - if ("not set".equals(requiredApiKey) || ! requiredApiKey.equals(providedApiKey)) { - return new ResponseEntity<>("", HttpStatus.UNAUTHORIZED); - } - cacheService.clearCaches(springManagedCache); - return new ResponseEntity<>("Flushed all caches!!!", HttpStatus.OK); - } - - @RequestMapping(value = "/cache/{studyId}", method = RequestMethod.DELETE, produces = MediaType.TEXT_PLAIN_VALUE) - @Operation(summary ="Clear and reinitialize caches after import/removal/update of a study") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(schema = @Schema(implementation = String.class))) - public ResponseEntity clearCachesForStudy( - @Parameter(description = "Secret API key passed in HTTP header. The key is configured in application.properties of the portal instance.") - @RequestHeader(value = "X-API-KEY") String providedApiKey, - @PathVariable String studyId, - @Parameter(description = "Clear Spring-managed caches") - @RequestParam(defaultValue = "true", required = false) final boolean springManagedCache) - throws CacheOperationException { - if (!cacheEndpointEnabled) { - return new ResponseEntity<>("Cache endpoint is disabled for this instance.", HttpStatus.NOT_FOUND); - } - if ("not set".equals(requiredApiKey) || ! requiredApiKey.equals(providedApiKey)) { - return new ResponseEntity<>("", HttpStatus.UNAUTHORIZED); - } - - cacheService.clearCachesForStudy(studyId, springManagedCache); - return new ResponseEntity<>("Flushed "+ studyId +" caches!!!", HttpStatus.OK); - } -} diff --git a/src/main/java/org/cbioportal/web/CacheStatsController.java b/src/main/java/org/cbioportal/web/CacheStatsController.java deleted file mode 100644 index abcdff97a9d..00000000000 --- a/src/main/java/org/cbioportal/web/CacheStatsController.java +++ /dev/null @@ -1,65 +0,0 @@ -package org.cbioportal.web; - -import io.swagger.v3.oas.annotations.Hidden; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.media.ArraySchema; -import io.swagger.v3.oas.annotations.media.Content; -import io.swagger.v3.oas.annotations.media.Schema; -import io.swagger.v3.oas.annotations.responses.ApiResponse; -import io.swagger.v3.oas.annotations.tags.Tag; -import org.cbioportal.service.CacheStatisticsService; -import org.cbioportal.service.exception.CacheNotFoundException; -import org.cbioportal.utils.config.annotation.ConditionalOnProperty; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestMethod; -import org.springframework.web.bind.annotation.RestController; - -import java.util.List; - -@RestController -@Validated -@Tag(name = "CacheStats", description = " ") -@Hidden -@ConditionalOnProperty(name = "persistence.cache_type", havingValue = {"ehcache-heap", "ehcache-disk", "ehcache-hybrid", "redis"}) -public class CacheStatsController { - - @Autowired - public CacheStatisticsService cacheStatisticsService; - - @RequestMapping(value = "/api/{cache}/keysInCache", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "Get list of keys in cache") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(array = @ArraySchema(schema = @Schema(implementation = String.class)))) - public ResponseEntity> getKeysInCache( - @Parameter(required = true, description = "Cache name") - @PathVariable String cache) throws CacheNotFoundException { - List strings = cacheStatisticsService.getKeysInCache(cache); - return new ResponseEntity<>(strings, HttpStatus.OK); - } - - @RequestMapping(value = "/api/{cache}/keyCountsPerClass", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "Get counts of keys per repository class") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(array = @ArraySchema(schema = @Schema(implementation = String.class)))) - public ResponseEntity> getKeyCountsPerClass( - @Parameter(required = true, description = "Cache name") - @PathVariable String cache) throws CacheNotFoundException { - List strings = cacheStatisticsService.getKeyCountsPerClass(cache); - return new ResponseEntity<>(strings, HttpStatus.OK); - } - - @RequestMapping(value = "/api/cacheStatistics", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "Get general cache statistics") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(schema = @Schema(implementation = String.class))) - public ResponseEntity getCacheStatistics() throws CacheNotFoundException { - return new ResponseEntity<>(cacheStatisticsService.getCacheStatistics(), HttpStatus.OK); - } -} diff --git a/src/main/java/org/cbioportal/web/CancerTypeController.java b/src/main/java/org/cbioportal/web/CancerTypeController.java deleted file mode 100644 index 3ea034f775a..00000000000 --- a/src/main/java/org/cbioportal/web/CancerTypeController.java +++ /dev/null @@ -1,86 +0,0 @@ -package org.cbioportal.web; - -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.media.ArraySchema; -import io.swagger.v3.oas.annotations.media.Content; -import io.swagger.v3.oas.annotations.media.Schema; -import io.swagger.v3.oas.annotations.responses.ApiResponse; -import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.validation.constraints.Max; -import jakarta.validation.constraints.Min; -import org.cbioportal.model.TypeOfCancer; -import org.cbioportal.service.CancerTypeService; -import org.cbioportal.service.exception.CancerTypeNotFoundException; -import org.cbioportal.web.config.PublicApiTags; -import org.cbioportal.web.config.annotation.PublicApi; -import org.cbioportal.web.parameter.Direction; -import org.cbioportal.web.parameter.HeaderKeyConstants; -import org.cbioportal.web.parameter.PagingConstants; -import org.cbioportal.web.parameter.Projection; -import org.cbioportal.web.parameter.sort.CancerTypeSortBy; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.PathVariable; -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.bind.annotation.RestController; - -import java.util.List; - -@PublicApi -@RestController -@Validated -@Tag(name = PublicApiTags.CANCER_TYPES, description = " ") -public class CancerTypeController { - - @Autowired - private CancerTypeService cancerTypeService; - - @RequestMapping(value = "/api/cancer-types", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "Get all cancer types") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(array = @ArraySchema(schema = @Schema(implementation = TypeOfCancer.class)))) - public ResponseEntity> getAllCancerTypes( - @Parameter(description = "Level of detail of the response") - @RequestParam(defaultValue = "SUMMARY") final Projection projection, - @Parameter(description = "Page size of the result list") - @Max(PagingConstants.MAX_PAGE_SIZE) - @Min(PagingConstants.MIN_PAGE_SIZE) - @RequestParam(defaultValue = PagingConstants.DEFAULT_PAGE_SIZE) final Integer pageSize, - @Parameter(description = "Page number of the result list") - @Min(PagingConstants.MIN_PAGE_NUMBER) - @RequestParam(defaultValue = PagingConstants.DEFAULT_PAGE_NUMBER) final Integer pageNumber, - @Parameter(description = "Name of the property that the result list is sorted by") - @RequestParam(required = false) final CancerTypeSortBy sortBy, - @Parameter(description = "Direction of the sort") - @RequestParam(defaultValue = "ASC") final Direction direction) { - - if (projection == Projection.META) { - final HttpHeaders responseHeaders = new HttpHeaders(); - responseHeaders.add(HeaderKeyConstants.TOTAL_COUNT, cancerTypeService.getMetaCancerTypes().getTotalCount() - .toString()); - return new ResponseEntity<>(responseHeaders, HttpStatus.OK); - } else { - return new ResponseEntity<>( - cancerTypeService.getAllCancerTypes(projection.name(), pageSize, pageNumber, - sortBy == null ? null : sortBy.getOriginalValue(), direction.name()), HttpStatus.OK); - } - } - - @RequestMapping(value = "/api/cancer-types/{cancerTypeId}", method = RequestMethod.GET, - produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "Get a cancer type") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(schema = @Schema(implementation = String.class))) - public ResponseEntity getCancerType( - @Parameter(required = true, description = "Cancer Type ID e.g. acc") - @PathVariable final String cancerTypeId) throws CancerTypeNotFoundException { - return new ResponseEntity<>(cancerTypeService.getCancerType(cancerTypeId), HttpStatus.OK); - } -} diff --git a/src/main/java/org/cbioportal/web/ClinicalAttributeController.java b/src/main/java/org/cbioportal/web/ClinicalAttributeController.java deleted file mode 100644 index 730b8925810..00000000000 --- a/src/main/java/org/cbioportal/web/ClinicalAttributeController.java +++ /dev/null @@ -1,159 +0,0 @@ -package org.cbioportal.web; - -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.media.ArraySchema; -import io.swagger.v3.oas.annotations.media.Content; -import io.swagger.v3.oas.annotations.media.Schema; -import io.swagger.v3.oas.annotations.responses.ApiResponse; -import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.validation.constraints.Max; -import jakarta.validation.constraints.Min; -import jakarta.validation.constraints.Size; -import org.cbioportal.model.ClinicalAttribute; -import org.cbioportal.service.ClinicalAttributeService; -import org.cbioportal.service.exception.ClinicalAttributeNotFoundException; -import org.cbioportal.service.exception.StudyNotFoundException; -import org.cbioportal.web.config.PublicApiTags; -import org.cbioportal.web.config.annotation.PublicApi; -import org.cbioportal.web.parameter.Direction; -import org.cbioportal.web.parameter.HeaderKeyConstants; -import org.cbioportal.web.parameter.PagingConstants; -import org.cbioportal.web.parameter.Projection; -import org.cbioportal.web.parameter.sort.ClinicalAttributeSortBy; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RequestBody; -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.bind.annotation.RestController; - -import java.util.List; - -@PublicApi -@RestController() -@RequestMapping("/api") -@Validated -@Tag(name = PublicApiTags.CLINICAL_ATTRIBUTES, description = " ") -public class ClinicalAttributeController { - - @Autowired - private ClinicalAttributeService clinicalAttributeService; - - @RequestMapping(value = "/clinical-attributes", method = RequestMethod.GET, - produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "Get all clinical attributes") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(array = @ArraySchema(schema = @Schema(implementation = ClinicalAttribute.class)))) - public ResponseEntity> getAllClinicalAttributes( - @Parameter(description = "Level of detail of the response") - @RequestParam(defaultValue = "SUMMARY") Projection projection, - @Parameter(description = "Page size of the result list") - @Max(PagingConstants.MAX_PAGE_SIZE) - @Min(PagingConstants.MIN_PAGE_SIZE) - @RequestParam(defaultValue = PagingConstants.DEFAULT_PAGE_SIZE) Integer pageSize, - @Parameter(description = "Page number of the result list") - @Min(PagingConstants.MIN_PAGE_NUMBER) - @RequestParam(defaultValue = PagingConstants.DEFAULT_PAGE_NUMBER) Integer pageNumber, - @Parameter(description = "Name of the property that the result list is sorted by") - @RequestParam(required = false) ClinicalAttributeSortBy sortBy, - @Parameter(description = "Direction of the sort") - @RequestParam(defaultValue = "ASC") Direction direction) { - - if (projection == Projection.META) { - HttpHeaders responseHeaders = new HttpHeaders(); - responseHeaders.add(HeaderKeyConstants.TOTAL_COUNT, clinicalAttributeService.getMetaClinicalAttributes() - .getTotalCount().toString()); - return new ResponseEntity<>(responseHeaders, HttpStatus.OK); - } else { - return new ResponseEntity<>( - clinicalAttributeService.getAllClinicalAttributes(projection.name(), pageSize, pageNumber, - sortBy == null ? null : sortBy.getOriginalValue(), direction.name()), HttpStatus.OK); - } - } - - @PreAuthorize("hasPermission(#studyId, 'CancerStudyId', T(org.cbioportal.utils.security.AccessLevel).READ)") - @RequestMapping(value = "/studies/{studyId}/clinical-attributes", method = RequestMethod.GET, - produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "Get all clinical attributes in the specified study") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(array = @ArraySchema(schema = @Schema(implementation = ClinicalAttribute.class)))) - public ResponseEntity> getAllClinicalAttributesInStudy( - @Parameter(required = true, description = "Study ID e.g. acc_tcga") - @PathVariable String studyId, - @Parameter(description = "Level of detail of the response") - @RequestParam(defaultValue = "SUMMARY") Projection projection, - @Parameter(description = "Page size of the result list") - @Max(PagingConstants.MAX_PAGE_SIZE) - @Min(PagingConstants.MIN_PAGE_SIZE) - @RequestParam(defaultValue = PagingConstants.DEFAULT_PAGE_SIZE) Integer pageSize, - @Parameter(description = "Page number of the result list") - @Min(PagingConstants.MIN_PAGE_NUMBER) - @RequestParam(defaultValue = PagingConstants.DEFAULT_PAGE_NUMBER) Integer pageNumber, - @Parameter(description = "Name of the property that the result list is sorted by") - @RequestParam(required = false) ClinicalAttributeSortBy sortBy, - @Parameter(description = "Direction of the sort") - @RequestParam(defaultValue = "ASC") Direction direction) throws StudyNotFoundException { - - if (projection == Projection.META) { - HttpHeaders responseHeaders = new HttpHeaders(); - responseHeaders.add(HeaderKeyConstants.TOTAL_COUNT, clinicalAttributeService - .getMetaClinicalAttributesInStudy(studyId).getTotalCount().toString()); - return new ResponseEntity<>(responseHeaders, HttpStatus.OK); - } else { - return new ResponseEntity<>( - clinicalAttributeService.getAllClinicalAttributesInStudy(studyId, projection.name(), pageSize, - pageNumber, sortBy == null ? null : sortBy.getOriginalValue(), direction.name()), - HttpStatus.OK); - } - } - - @PreAuthorize("hasPermission(#studyId, 'CancerStudyId', T(org.cbioportal.utils.security.AccessLevel).READ)") - @RequestMapping(value = "/studies/{studyId}/clinical-attributes/{clinicalAttributeId}", method = RequestMethod.GET, - produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "Get specified clinical attribute") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(schema = @Schema(implementation = ClinicalAttribute.class))) - public ResponseEntity getClinicalAttributeInStudy( - @Parameter(required = true, description = "Study ID e.g. acc_tcga") - @PathVariable String studyId, - @Parameter(required = true, description= "Clinical Attribute ID e.g. CANCER_TYPE") - @PathVariable String clinicalAttributeId) - throws ClinicalAttributeNotFoundException, StudyNotFoundException { - - return new ResponseEntity<>(clinicalAttributeService.getClinicalAttribute(studyId, clinicalAttributeId), - HttpStatus.OK); - } - - @PreAuthorize("hasPermission(#studyIds, 'Collection', T(org.cbioportal.utils.security.AccessLevel).READ)") - @RequestMapping(value = "/clinical-attributes/fetch", method = RequestMethod.POST, - consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "Fetch clinical attributes") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(array = @ArraySchema(schema = @Schema(implementation = ClinicalAttribute.class)))) - public ResponseEntity> fetchClinicalAttributes( - @Parameter(required = true, description = "List of Study IDs") - @Size(min = 1, max = PagingConstants.MAX_PAGE_SIZE) - @RequestBody List studyIds, - @Parameter(description = "Level of detail of the response") - @RequestParam(defaultValue = "SUMMARY") Projection projection) { - - if (projection == Projection.META) { - HttpHeaders responseHeaders = new HttpHeaders(); - responseHeaders.add(HeaderKeyConstants.TOTAL_COUNT, clinicalAttributeService.fetchMetaClinicalAttributes( - studyIds).getTotalCount().toString()); - return new ResponseEntity<>(responseHeaders, HttpStatus.OK); - } else { - return new ResponseEntity<>(clinicalAttributeService.fetchClinicalAttributes(studyIds, projection.name()), - HttpStatus.OK); - } - } - -} diff --git a/src/main/java/org/cbioportal/web/ClinicalAttributeCountController.java b/src/main/java/org/cbioportal/web/ClinicalAttributeCountController.java deleted file mode 100644 index 7bf96005675..00000000000 --- a/src/main/java/org/cbioportal/web/ClinicalAttributeCountController.java +++ /dev/null @@ -1,74 +0,0 @@ -package org.cbioportal.web; - -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.media.ArraySchema; -import io.swagger.v3.oas.annotations.media.Content; -import io.swagger.v3.oas.annotations.media.Schema; -import io.swagger.v3.oas.annotations.responses.ApiResponse; -import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.validation.Valid; -import org.cbioportal.model.ClinicalAttributeCount; -import org.cbioportal.service.ClinicalAttributeService; -import org.cbioportal.web.config.InternalApiTags; -import org.cbioportal.web.config.annotation.InternalApi; -import org.cbioportal.web.parameter.ClinicalAttributeCountFilter; -import org.cbioportal.web.parameter.SampleIdentifier; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.RequestAttribute; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestMethod; -import org.springframework.web.bind.annotation.RestController; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; - -@InternalApi -@RestController() -@RequestMapping("/api") -@Validated -@Tag(name = InternalApiTags.CLINICAL_ATTRIBUTES_COUNT, description = " ") -public class ClinicalAttributeCountController { - - @Autowired - private ClinicalAttributeService clinicalAttributeService; - - @PreAuthorize("hasPermission(#involvedCancerStudies, 'Collection', T(org.cbioportal.utils.security.AccessLevel).READ)") - @RequestMapping(value = "/clinical-attributes/counts/fetch", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE, - produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "Get counts for clinical attributes according to their data availability for selected samples/patients") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(array = @ArraySchema(schema = @Schema(implementation = ClinicalAttributeCount.class)))) - public ResponseEntity> getClinicalAttributeCounts( - @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface - @RequestAttribute(required = false, value = "involvedCancerStudies") Collection involvedCancerStudies, - @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface. this attribute is needed for the @PreAuthorize tag above. - @Valid @RequestAttribute(required = false, value = "interceptedClinicalAttributeCountFilter") ClinicalAttributeCountFilter interceptedClinicalAttributeCountFilter, - @Parameter(required = true, description = "List of SampleIdentifiers or Sample List ID") - @Valid @RequestBody(required = false) ClinicalAttributeCountFilter clinicalAttributeCountFilter) { - - List clinicalAttributeCountList; - if (interceptedClinicalAttributeCountFilter.getSampleListId() != null) { - clinicalAttributeCountList = clinicalAttributeService.getClinicalAttributeCountsBySampleListId( - interceptedClinicalAttributeCountFilter.getSampleListId()); - } else { - List sampleIdentifiers = interceptedClinicalAttributeCountFilter.getSampleIdentifiers(); - List studyIds = new ArrayList<>(); - List sampleIds = new ArrayList<>(); - for (SampleIdentifier sampleIdentifier : sampleIdentifiers) { - studyIds.add(sampleIdentifier.getStudyId()); - sampleIds.add(sampleIdentifier.getSampleId()); - } - clinicalAttributeCountList = clinicalAttributeService.getClinicalAttributeCountsBySampleIds(studyIds, sampleIds); - } - - return new ResponseEntity<>(clinicalAttributeCountList, HttpStatus.OK); - } -} diff --git a/src/main/java/org/cbioportal/web/ClinicalDataController.java b/src/main/java/org/cbioportal/web/ClinicalDataController.java deleted file mode 100644 index 1831c3b5689..00000000000 --- a/src/main/java/org/cbioportal/web/ClinicalDataController.java +++ /dev/null @@ -1,251 +0,0 @@ -package org.cbioportal.web; - -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.media.ArraySchema; -import io.swagger.v3.oas.annotations.media.Content; -import io.swagger.v3.oas.annotations.media.Schema; -import io.swagger.v3.oas.annotations.responses.ApiResponse; -import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.validation.Valid; -import jakarta.validation.constraints.Max; -import jakarta.validation.constraints.Min; -import org.cbioportal.model.CancerStudy; -import org.cbioportal.model.ClinicalData; -import org.cbioportal.service.ClinicalDataService; -import org.cbioportal.service.exception.PatientNotFoundException; -import org.cbioportal.service.exception.SampleNotFoundException; -import org.cbioportal.service.exception.StudyNotFoundException; -import org.cbioportal.web.config.PublicApiTags; -import org.cbioportal.web.config.annotation.PublicApi; -import org.cbioportal.web.parameter.ClinicalDataIdentifier; -import org.cbioportal.web.parameter.ClinicalDataMultiStudyFilter; -import org.cbioportal.web.parameter.ClinicalDataSingleStudyFilter; -import org.cbioportal.web.parameter.ClinicalDataType; -import org.cbioportal.web.parameter.Direction; -import org.cbioportal.web.parameter.HeaderKeyConstants; -import org.cbioportal.web.parameter.PagingConstants; -import org.cbioportal.web.parameter.Projection; -import org.cbioportal.web.parameter.sort.ClinicalDataSortBy; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RequestAttribute; -import org.springframework.web.bind.annotation.RequestBody; -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.bind.annotation.RestController; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; - -@PublicApi -@RestController() -@RequestMapping("/api") -@Validated -@Tag(name = PublicApiTags.CLINICAL_DATA, description = " ") -public class ClinicalDataController { - - public static final int CLINICAL_DATA_MAX_PAGE_SIZE = 10000000; - private static final String CLINICAL_DATA_DEFAULT_PAGE_SIZE = "10000000"; - - @Autowired - private ClinicalDataService clinicalDataService; - - @PreAuthorize("hasPermission(#studyId, 'CancerStudyId', T(org.cbioportal.utils.security.AccessLevel).READ)") - @RequestMapping(value = "/studies/{studyId}/samples/{sampleId}/clinical-data", method = RequestMethod.GET, - produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "Get all clinical data of a sample in a study") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(array = @ArraySchema(schema = @Schema(implementation = ClinicalData.class)))) - public ResponseEntity> getAllClinicalDataOfSampleInStudy( - @Parameter(required = true, description = "Study ID e.g. acc_tcga") - @PathVariable String studyId, - @Parameter(required = true, description = "Sample ID e.g. TCGA-OR-A5J2-01") - @PathVariable String sampleId, - @Parameter(description = "Attribute ID e.g. CANCER_TYPE") - @RequestParam(required = false) String attributeId, - @Parameter(description = "Level of detail of the response") - @RequestParam(defaultValue = "SUMMARY") Projection projection, - @Parameter(description = "Page size of the result list") - @Max(CLINICAL_DATA_MAX_PAGE_SIZE) - @Min(PagingConstants.MIN_PAGE_SIZE) - @RequestParam(defaultValue = CLINICAL_DATA_DEFAULT_PAGE_SIZE) Integer pageSize, - @Parameter(description = "Page number of the result list") - @Min(PagingConstants.MIN_PAGE_NUMBER) - @RequestParam(defaultValue = PagingConstants.DEFAULT_PAGE_NUMBER) Integer pageNumber, - @Parameter(description = "Name of the property that the result list is sorted by") - @RequestParam(required = false) ClinicalDataSortBy sortBy, - @Parameter(description = "Direction of the sort") - @RequestParam(defaultValue = "ASC") Direction direction) throws SampleNotFoundException, - StudyNotFoundException { - - if (projection == Projection.META) { - HttpHeaders responseHeaders = new HttpHeaders(); - responseHeaders.add(HeaderKeyConstants.TOTAL_COUNT, clinicalDataService.getMetaSampleClinicalData( - studyId, sampleId, attributeId).getTotalCount().toString()); - return new ResponseEntity<>(responseHeaders, HttpStatus.OK); - } else { - return new ResponseEntity<>( - clinicalDataService.getAllClinicalDataOfSampleInStudy( - studyId, sampleId, attributeId, projection.name(), pageSize, pageNumber, - sortBy == null ? null : sortBy.getOriginalValue(), direction.name()), HttpStatus.OK); - } - } - - @PreAuthorize("hasPermission(#studyId, 'CancerStudyId', T(org.cbioportal.utils.security.AccessLevel).READ)") - @RequestMapping(value = "/studies/{studyId}/patients/{patientId}/clinical-data", method = RequestMethod.GET, - produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "Get all clinical data of a patient in a study") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(array = @ArraySchema(schema = @Schema(implementation = ClinicalData.class)))) - public ResponseEntity> getAllClinicalDataOfPatientInStudy( - @Parameter(required = true, description = "Study ID e.g. acc_tcga") - @PathVariable String studyId, - @Parameter(required = true, description = "Patient ID e.g. TCGA-OR-A5J2") - @PathVariable String patientId, - @Parameter(description = "Attribute ID e.g. AGE") - @RequestParam(required = false) String attributeId, - @Parameter(description = "Level of detail of the response") - @RequestParam(defaultValue = "SUMMARY") Projection projection, - @Parameter(description = "Page size of the result list") - @Max(CLINICAL_DATA_MAX_PAGE_SIZE) - @Min(PagingConstants.MIN_PAGE_SIZE) - @RequestParam(defaultValue = CLINICAL_DATA_DEFAULT_PAGE_SIZE) Integer pageSize, - @Parameter(description = "Page number of the result list") - @Min(PagingConstants.MIN_PAGE_NUMBER) - @RequestParam(defaultValue = PagingConstants.DEFAULT_PAGE_NUMBER) Integer pageNumber, - @Parameter(description = "Name of the property that the result list is sorted by") - @RequestParam(required = false) ClinicalDataSortBy sortBy, - @Parameter(description = "Direction of the sort") - @RequestParam(defaultValue = "ASC") Direction direction) throws PatientNotFoundException, - StudyNotFoundException { - - if (projection == Projection.META) { - HttpHeaders responseHeaders = new HttpHeaders(); - responseHeaders.add(HeaderKeyConstants.TOTAL_COUNT, clinicalDataService.getMetaPatientClinicalData( - studyId, patientId, attributeId).getTotalCount().toString()); - return new ResponseEntity<>(responseHeaders, HttpStatus.OK); - } else { - return new ResponseEntity<>( - clinicalDataService.getAllClinicalDataOfPatientInStudy( - studyId, patientId, attributeId, projection.name(), pageSize, pageNumber, - sortBy == null ? null : sortBy.getOriginalValue(), direction.name()), HttpStatus.OK); - } - } - - @PreAuthorize("hasPermission(#studyId, 'CancerStudyId', T(org.cbioportal.utils.security.AccessLevel).READ)") - @RequestMapping(value = "/studies/{studyId}/clinical-data", method = RequestMethod.GET, - produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "Get all clinical data in a study") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(array = @ArraySchema(schema = @Schema(implementation = ClinicalData.class)))) - public ResponseEntity> getAllClinicalDataInStudy( - @Parameter(required = true, description = "Study ID e.g. acc_tcga") - @PathVariable String studyId, - @Parameter(description = "Attribute ID e.g. CANCER_TYPE") - @RequestParam(required = false) String attributeId, - @Parameter(description = "Type of the clinical data") - @RequestParam(defaultValue = "SAMPLE") ClinicalDataType clinicalDataType, - @Parameter(description = "Level of detail of the response") - @RequestParam(defaultValue = "SUMMARY") Projection projection, - @Parameter(description = "Page size of the result list") - @Max(CLINICAL_DATA_MAX_PAGE_SIZE) - @Min(PagingConstants.MIN_PAGE_SIZE) - @RequestParam(defaultValue = CLINICAL_DATA_DEFAULT_PAGE_SIZE) Integer pageSize, - @Parameter(description = "Page number of the result list") - @Min(PagingConstants.MIN_PAGE_NUMBER) - @RequestParam(defaultValue = PagingConstants.DEFAULT_PAGE_NUMBER) Integer pageNumber, - @Parameter(description = "Name of the property that the result list is sorted by") - @RequestParam(required = false) ClinicalDataSortBy sortBy, - @Parameter(description = "Direction of the sort") - @RequestParam(defaultValue = "ASC") Direction direction) throws StudyNotFoundException { - - if (projection == Projection.META) { - HttpHeaders responseHeaders = new HttpHeaders(); - responseHeaders.add(HeaderKeyConstants.TOTAL_COUNT, clinicalDataService.getMetaAllClinicalData(studyId, - attributeId, clinicalDataType.name()).getTotalCount().toString()); - return new ResponseEntity<>(responseHeaders, HttpStatus.OK); - } else { - return new ResponseEntity<>( - clinicalDataService.getAllClinicalDataInStudy(studyId, attributeId, - clinicalDataType.name(), projection.name(), pageSize, pageNumber, - sortBy == null ? null : sortBy.getOriginalValue(), direction.name()), HttpStatus.OK); - } - } - - @PreAuthorize("hasPermission(#studyId, 'CancerStudyId', T(org.cbioportal.utils.security.AccessLevel).READ)") - @RequestMapping(value = "/studies/{studyId}/clinical-data/fetch", method = RequestMethod.POST, - consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "Fetch clinical data by patient IDs or sample IDs (specific study)") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(array = @ArraySchema(schema = @Schema(implementation = ClinicalData.class)))) - public ResponseEntity> fetchAllClinicalDataInStudy( - @Parameter(required = true, description = "Study ID e.g. acc_tcga") - @PathVariable String studyId, - @Parameter(description = "Type of the clinical data") - @RequestParam(defaultValue = "SAMPLE") ClinicalDataType clinicalDataType, - @Parameter(required = true, description = "List of patient or sample IDs and attribute IDs") - @Valid @RequestBody ClinicalDataSingleStudyFilter clinicalDataSingleStudyFilter, - @Parameter(description = "Level of detail of the response") - @RequestParam(defaultValue = "SUMMARY") Projection projection) throws StudyNotFoundException { - - if (projection == Projection.META) { - HttpHeaders responseHeaders = new HttpHeaders(); - responseHeaders.add(HeaderKeyConstants.TOTAL_COUNT, clinicalDataService.fetchMetaClinicalDataInStudy( - studyId, clinicalDataSingleStudyFilter.getIds(), clinicalDataSingleStudyFilter.getAttributeIds(), - clinicalDataType.name()).getTotalCount().toString()); - return new ResponseEntity<>(responseHeaders, HttpStatus.OK); - } else { - return new ResponseEntity<>( - clinicalDataService.fetchAllClinicalDataInStudy(studyId, clinicalDataSingleStudyFilter.getIds(), - clinicalDataSingleStudyFilter.getAttributeIds(), clinicalDataType.name(), projection.name()), - HttpStatus.OK); - } - } - - @PreAuthorize("hasPermission(#involvedCancerStudies, 'Collection', T(org.cbioportal.utils.security.AccessLevel).READ)") - @RequestMapping(value = "/clinical-data/fetch", method = RequestMethod.POST, - consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "Fetch clinical data by patient IDs or sample IDs (all studies)") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(array = @ArraySchema(schema = @Schema(implementation = ClinicalData.class)))) - public ResponseEntity> fetchClinicalData( - @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface - @RequestAttribute(required = false, value = "involvedCancerStudies") Collection involvedCancerStudies, - @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface. this attribute is needed for the @PreAuthorize tag above. - @Valid @RequestAttribute(required = false, value = "interceptedClinicalDataMultiStudyFilter") ClinicalDataMultiStudyFilter interceptedClinicalDataMultiStudyFilter, - @Parameter(description = "Type of the clinical data") - @RequestParam(defaultValue = "SAMPLE") ClinicalDataType clinicalDataType, - @Parameter(required = true, description = "List of patient or sample identifiers and attribute IDs") - @Valid @RequestBody(required = false) ClinicalDataMultiStudyFilter clinicalDataMultiStudyFilter, - @Parameter(description = "Level of detail of the response") - @RequestParam(defaultValue = "SUMMARY") Projection projection) { - - List studyIds = new ArrayList<>(); - List ids = new ArrayList<>(); - - for (ClinicalDataIdentifier identifier : interceptedClinicalDataMultiStudyFilter.getIdentifiers()) { - studyIds.add(identifier.getStudyId()); - ids.add(identifier.getEntityId()); - } - - if (projection == Projection.META) { - HttpHeaders responseHeaders = new HttpHeaders(); - responseHeaders.add(HeaderKeyConstants.TOTAL_COUNT, clinicalDataService.fetchMetaClinicalData(studyIds, ids, - interceptedClinicalDataMultiStudyFilter.getAttributeIds(), clinicalDataType.name()).getTotalCount().toString()); - return new ResponseEntity<>(responseHeaders, HttpStatus.OK); - } else { - return new ResponseEntity<>( - clinicalDataService.fetchClinicalData(studyIds, ids, interceptedClinicalDataMultiStudyFilter.getAttributeIds(), - clinicalDataType.name(), projection.name()), HttpStatus.OK); - } - } -} diff --git a/src/main/java/org/cbioportal/web/ClinicalDataEnrichmentController.java b/src/main/java/org/cbioportal/web/ClinicalDataEnrichmentController.java deleted file mode 100644 index 7e880875916..00000000000 --- a/src/main/java/org/cbioportal/web/ClinicalDataEnrichmentController.java +++ /dev/null @@ -1,123 +0,0 @@ -package org.cbioportal.web; - -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.media.ArraySchema; -import io.swagger.v3.oas.annotations.media.Content; -import io.swagger.v3.oas.annotations.media.Schema; -import io.swagger.v3.oas.annotations.responses.ApiResponse; -import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.validation.Valid; -import org.apache.commons.collections4.map.MultiKeyMap; -import org.cbioportal.model.ClinicalAttribute; -import org.cbioportal.model.ClinicalDataEnrichment; -import org.cbioportal.model.Sample; -import org.cbioportal.service.ClinicalAttributeService; -import org.cbioportal.service.SampleService; -import org.cbioportal.web.config.annotation.InternalApi; -import org.cbioportal.web.parameter.GroupFilter; -import org.cbioportal.web.parameter.Projection; -import org.cbioportal.web.parameter.SampleIdentifier; -import org.cbioportal.web.util.ClinicalDataEnrichmentUtil; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.RequestAttribute; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestMethod; -import org.springframework.web.bind.annotation.RestController; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.stream.Collectors; - -@InternalApi -@RestController -@RequestMapping("/api") -@Validated -@Tag(name = "Clinical Data Enrichments", description = " ") -public class ClinicalDataEnrichmentController { - - @Autowired - private ClinicalDataEnrichmentUtil clinicalDataEnrichmentUtil; - - @Autowired - private ClinicalAttributeService clinicalAttributeService; - - @Autowired - private SampleService sampleService; - - @PreAuthorize("hasPermission(#involvedCancerStudies, 'Collection', T(org.cbioportal.utils.security.AccessLevel).READ)") - @RequestMapping(value = "/clinical-data-enrichments/fetch", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "Fetch clinical data enrichments for the sample groups") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(array = @ArraySchema(schema = @Schema(implementation = ClinicalDataEnrichment.class)))) - public ResponseEntity> fetchClinicalEnrichments( - @Parameter(required = true, description = "List of altered and unaltered Sample/Patient IDs") - @Valid @RequestBody(required = false) GroupFilter groupFilter, - @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface - @RequestAttribute(required = false, value = "involvedCancerStudies") Collection involvedCancerStudies, - @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface. this attribute is needed for the @PreAuthorize tag above. - @Valid @RequestAttribute(required = false, value = "interceptedGroupFilter") GroupFilter interceptedGroupFilter) { - - List studyIds = interceptedGroupFilter.getGroups().stream() - .flatMap(group -> group.getSampleIdentifiers().stream().map(SampleIdentifier::getStudyId)) - .collect(Collectors.toList()); - - List sampleIds = interceptedGroupFilter.getGroups().stream() - .flatMap(group -> group.getSampleIdentifiers().stream().map(SampleIdentifier::getSampleId)) - .collect(Collectors.toList()); - - List samples = sampleService.fetchSamples(studyIds, sampleIds, Projection.SUMMARY.name()); - - MultiKeyMap sampleSet = new MultiKeyMap(); - - samples.stream() - .forEach(sample -> sampleSet.put(sample.getCancerStudyIdentifier(), sample.getStableId(), sample)); - - // samples for each group - List> groupedSamples = interceptedGroupFilter.getGroups().stream() - .map(group -> group.getSampleIdentifiers().stream() - .map(sampleIdentifier -> (Sample) sampleSet.get(sampleIdentifier.getStudyId(), - sampleIdentifier.getSampleId())) - .filter(sample -> sample != null).collect(Collectors.toList())) - .filter(validSamples -> validSamples.size() > 0).collect(Collectors.toList()); - - return new ResponseEntity<>(fetchClinicalDataEnrichemnts(groupedSamples), HttpStatus.OK); - } - - private List fetchClinicalDataEnrichemnts(List> groupedSamples) { - - List clinicalEnrichments = new ArrayList(); - - if (!groupedSamples.isEmpty()) { - Set studyIds = groupedSamples.stream() - .flatMap(samples -> samples.stream().map(Sample::getCancerStudyIdentifier)) - .collect(Collectors.toSet()); - - List clinicalAttributes = clinicalAttributeService - .fetchClinicalAttributes(new ArrayList(studyIds), "SUMMARY"); - - // remove all duplicate attributes - Map clinicalAttributesByUniqId = clinicalAttributes.stream() - .collect(Collectors.toMap(c -> c.getAttrId() + c.getPatientAttribute(), c -> c, (e1, e2) -> e2)); - - clinicalAttributes = new ArrayList<>(clinicalAttributesByUniqId.values()); - - clinicalEnrichments.addAll( - clinicalDataEnrichmentUtil.createEnrichmentsForCategoricalData(clinicalAttributes, groupedSamples)); - - clinicalEnrichments.addAll( - clinicalDataEnrichmentUtil.createEnrichmentsForNumericData(clinicalAttributes, groupedSamples)); - } - return clinicalEnrichments; - } - -} diff --git a/src/main/java/org/cbioportal/web/ClinicalEventController.java b/src/main/java/org/cbioportal/web/ClinicalEventController.java deleted file mode 100644 index 487adbd479d..00000000000 --- a/src/main/java/org/cbioportal/web/ClinicalEventController.java +++ /dev/null @@ -1,171 +0,0 @@ -package org.cbioportal.web; - -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.media.ArraySchema; -import io.swagger.v3.oas.annotations.media.Content; -import io.swagger.v3.oas.annotations.media.Schema; -import io.swagger.v3.oas.annotations.responses.ApiResponse; -import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.validation.Valid; -import jakarta.validation.constraints.Max; -import jakarta.validation.constraints.Min; -import org.cbioportal.model.ClinicalEvent; -import org.cbioportal.service.ClinicalEventService; -import org.cbioportal.service.exception.PatientNotFoundException; -import org.cbioportal.service.exception.StudyNotFoundException; -import org.cbioportal.web.config.InternalApiTags; -import org.cbioportal.web.config.annotation.InternalApi; -import org.cbioportal.web.parameter.*; -import org.cbioportal.web.parameter.sort.ClinicalEventSortBy; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.cache.annotation.Cacheable; -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RequestAttribute; -import org.springframework.web.bind.annotation.RequestBody; -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.bind.annotation.RestController; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; - -@InternalApi -@RestController() -@RequestMapping("/api") -@Validated -@Tag(name = InternalApiTags.CLINICAL_EVENTS, description = " ") -public class ClinicalEventController { - - @Autowired - private ClinicalEventService clinicalEventService; - - @PreAuthorize("hasPermission(#studyId, 'CancerStudyId', T(org.cbioportal.utils.security.AccessLevel).READ)") - @RequestMapping(value = "/studies/{studyId}/patients/{patientId}/clinical-events", method = RequestMethod.GET, - produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "Get all clinical events of a patient in a study") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(array = @ArraySchema(schema = @Schema(implementation = ClinicalEvent.class)))) - public ResponseEntity> getAllClinicalEventsOfPatientInStudy( - @Parameter(required = true, description = "Study ID e.g. lgg_ucsf_2014") - @PathVariable String studyId, - @Parameter(required = true, description = "Patient ID e.g. P01") - @PathVariable String patientId, - @Parameter(description = "Level of detail of the response") - @RequestParam(defaultValue = "SUMMARY") Projection projection, - @Parameter(description = "Page size of the result list") - @Max(PagingConstants.MAX_PAGE_SIZE) - @Min(PagingConstants.MIN_PAGE_SIZE) - @RequestParam(defaultValue = PagingConstants.DEFAULT_PAGE_SIZE) Integer pageSize, - @Parameter(description = "Page number of the result list") - @Min(PagingConstants.MIN_PAGE_NUMBER) - @RequestParam(defaultValue = PagingConstants.DEFAULT_PAGE_NUMBER) Integer pageNumber, - @Parameter(description = "Name of the property that the result list is sorted by") - @RequestParam(required = false) ClinicalEventSortBy sortBy, - @Parameter(description = "Direction of the sort") - @RequestParam(defaultValue = "ASC") Direction direction) throws PatientNotFoundException, - StudyNotFoundException { - - if (projection == Projection.META) { - HttpHeaders responseHeaders = new HttpHeaders(); - responseHeaders.add(HeaderKeyConstants.TOTAL_COUNT, clinicalEventService.getMetaPatientClinicalEvents( - studyId, patientId).getTotalCount().toString()); - return new ResponseEntity<>(responseHeaders, HttpStatus.OK); - } else { - return new ResponseEntity<>( - clinicalEventService.getAllClinicalEventsOfPatientInStudy( - studyId, patientId, projection.name(), pageSize, pageNumber, - sortBy == null ? null : sortBy.getOriginalValue(), direction.name()), HttpStatus.OK); - } - } - - @PreAuthorize("hasPermission(#studyId, 'CancerStudyId', T(org.cbioportal.utils.security.AccessLevel).READ)") - @RequestMapping(value = "/studies/{studyId}/clinical-events", method = RequestMethod.GET, - produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "Get all clinical events in a study") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(array = @ArraySchema(schema = @Schema(implementation = ClinicalEvent.class)))) - public ResponseEntity> getAllClinicalEventsInStudy( - @Parameter(required = true, description = "Study ID e.g. lgg_ucsf_2014") - @PathVariable String studyId, - @Parameter(description = "Level of detail of the response") - @RequestParam(defaultValue = "SUMMARY") Projection projection, - @Parameter(description = "Page size of the result list") - @Max(PagingConstants.MAX_PAGE_SIZE) - @Min(PagingConstants.MIN_PAGE_SIZE) - @RequestParam(defaultValue = PagingConstants.DEFAULT_PAGE_SIZE) Integer pageSize, - @Parameter(description = "Page number of the result list") - @Min(PagingConstants.MIN_PAGE_NUMBER) - @RequestParam(defaultValue = PagingConstants.DEFAULT_PAGE_NUMBER) Integer pageNumber, - @Parameter(description = "Name of the property that the result list is sorted by") - @RequestParam(required = false) ClinicalEventSortBy sortBy, - @Parameter(description = "Direction of the sort") - @RequestParam(defaultValue = "ASC") Direction direction) throws PatientNotFoundException, - StudyNotFoundException { - - if (projection == Projection.META) { - HttpHeaders responseHeaders = new HttpHeaders(); - responseHeaders.add(HeaderKeyConstants.TOTAL_COUNT, clinicalEventService.getMetaClinicalEvents( - studyId).getTotalCount().toString()); - return new ResponseEntity<>(responseHeaders, HttpStatus.OK); - } else { - return new ResponseEntity<>( - clinicalEventService.getAllClinicalEventsInStudy( - studyId, projection.name(), pageSize, pageNumber, - sortBy == null ? null : sortBy.getOriginalValue(), direction.name()), HttpStatus.OK); - } - } - - @PreAuthorize("hasPermission(#involvedCancerStudies, 'Collection', T(org.cbioportal.utils.security.AccessLevel).READ)") - @RequestMapping(value = "/clinical-events-meta/fetch", - method = RequestMethod.POST, - consumes = MediaType.APPLICATION_JSON_VALUE, - produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "Fetch clinical events meta") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(array = @ArraySchema(schema = @Schema(implementation = ClinicalEvent.class)))) - public ResponseEntity> fetchClinicalEventsMeta( - @Parameter(required = true, description = "clinical events Request") - @Valid @RequestBody(required = false) ClinicalEventAttributeRequest clinicalEventAttributeRequest, - @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface - @RequestAttribute(required = false, value = "involvedCancerStudies") Collection involvedCancerStudies, - @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface. This attribute is needed for the @PreAuthorize tag above. - @Valid @RequestAttribute(required = false, value = "interceptedClinicalEventAttributeRequest") ClinicalEventAttributeRequest interceptedClinicalEventAttributeRequest) { - - return new ResponseEntity<>(cachedClinicalEventsMeta(interceptedClinicalEventAttributeRequest), HttpStatus.OK); - - } - - @Cacheable( - cacheResolver = "generalRepositoryCacheResolver", - condition = "@cacheEnabledConfig.getEnabled()" - ) - public List cachedClinicalEventsMeta(ClinicalEventAttributeRequest interceptedClinicalEventAttributeRequest) { - List studyIds = new ArrayList<>(); - List patientIds = new ArrayList<>(); - for (PatientIdentifier patientIdentifier : interceptedClinicalEventAttributeRequest.getPatientIdentifiers()) { - studyIds.add(patientIdentifier.getStudyId()); - patientIds.add(patientIdentifier.getPatientId()); - } - - List clinicalEventsRequest = interceptedClinicalEventAttributeRequest.getClinicalEventRequests() - .stream() - .map(x -> { - ClinicalEvent clinicalEvent = new ClinicalEvent(); - clinicalEvent.setEventType(x.getEventType()); - clinicalEvent.setAttributes(x.getAttributes()); - return clinicalEvent; - }) - .toList(); - return clinicalEventService.getClinicalEventsMeta( - studyIds, patientIds, clinicalEventsRequest); - } -} diff --git a/src/main/java/org/cbioportal/web/CoExpressionController.java b/src/main/java/org/cbioportal/web/CoExpressionController.java deleted file mode 100644 index fd71a7fabc7..00000000000 --- a/src/main/java/org/cbioportal/web/CoExpressionController.java +++ /dev/null @@ -1,82 +0,0 @@ -package org.cbioportal.web; - -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.media.ArraySchema; -import io.swagger.v3.oas.annotations.media.Content; -import io.swagger.v3.oas.annotations.media.Schema; -import io.swagger.v3.oas.annotations.responses.ApiResponse; -import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.validation.Valid; -import org.cbioportal.model.CoExpression; -import org.cbioportal.model.EntityType; -import org.cbioportal.service.CoExpressionService; -import org.cbioportal.web.config.annotation.InternalApi; -import org.cbioportal.web.parameter.CoExpressionFilter; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.RequestBody; -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.bind.annotation.RestController; - -import java.util.List; - -@InternalApi -@RestController() -@RequestMapping("/api") -@Validated -@Tag(name = "Co-Expressions", description = " ") -public class CoExpressionController { - - @Autowired - private CoExpressionService coExpressionService; - - // requires permission to access both molecularProfileIdA and molecularProfileIdB because service layer does not enforce requirement that both profiles are in the same study - @PreAuthorize("hasPermission(#molecularProfileIdA, 'MolecularProfileId', T(org.cbioportal.utils.security.AccessLevel).READ) and hasPermission(#molecularProfileIdB, 'MolecularProfileId', T(org.cbioportal.utils.security.AccessLevel).READ)") - @RequestMapping(value = "/molecular-profiles/co-expressions/fetch", - method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE, - produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "Calculates correlations between a genetic entity from a specific profile and another profile from the same study") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(array = @ArraySchema(schema = @Schema(implementation = CoExpression.class)))) - public ResponseEntity> fetchCoExpressions( - @Parameter(required = true, description = "Molecular Profile ID from the Genetic Entity referenced in the co-expression filter e.g. acc_tcga_rna_seq_v2_mrna") - @RequestParam String molecularProfileIdA, - @Parameter(required = true, description = "Molecular Profile ID (can be the same as molecularProfileIdA) e.g. acc_tcga_rna_seq_v2_mrna") - @RequestParam String molecularProfileIdB, - @Parameter(required = true, description = "List of Sample IDs/Sample List ID and Entrez Gene ID/Gene set ID") - @Valid @RequestBody CoExpressionFilter coExpressionFilter, - @Parameter(description = "Threshold") - @RequestParam(defaultValue = "0.3") Double threshold) throws Exception { - - List coExpressionList; - String geneticEntityId = null; - EntityType geneticEntityType = null; - - if (coExpressionFilter.getEntrezGeneId() != null) { - geneticEntityId = coExpressionFilter.getEntrezGeneId().toString(); - geneticEntityType = EntityType.GENE; - } else { - geneticEntityId = coExpressionFilter.getGenesetId(); - geneticEntityType = EntityType.GENESET; - } - - if (coExpressionFilter.getSampleListId() != null) { - coExpressionList = coExpressionService.getCoExpressions(geneticEntityId, - geneticEntityType, coExpressionFilter.getSampleListId(), molecularProfileIdA, molecularProfileIdB, - threshold); - } else { - coExpressionList = coExpressionService.fetchCoExpressions(geneticEntityId, - geneticEntityType, coExpressionFilter.getSampleIds(), molecularProfileIdA, molecularProfileIdB, - threshold); - } - - return new ResponseEntity<>(coExpressionList, HttpStatus.OK); - } -} diff --git a/src/main/java/org/cbioportal/web/CopyNumberSegmentController.java b/src/main/java/org/cbioportal/web/CopyNumberSegmentController.java deleted file mode 100644 index c16406066f1..00000000000 --- a/src/main/java/org/cbioportal/web/CopyNumberSegmentController.java +++ /dev/null @@ -1,136 +0,0 @@ -package org.cbioportal.web; - -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.media.ArraySchema; -import io.swagger.v3.oas.annotations.media.Content; -import io.swagger.v3.oas.annotations.media.Schema; -import io.swagger.v3.oas.annotations.responses.ApiResponse; -import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.validation.constraints.Max; -import jakarta.validation.constraints.Min; -import jakarta.validation.constraints.Size; -import org.cbioportal.model.CopyNumberSeg; -import org.cbioportal.service.CopyNumberSegmentService; -import org.cbioportal.service.exception.SampleNotFoundException; -import org.cbioportal.service.exception.StudyNotFoundException; -import org.cbioportal.web.config.PublicApiTags; -import org.cbioportal.web.config.annotation.PublicApi; -import org.cbioportal.web.parameter.Direction; -import org.cbioportal.web.parameter.HeaderKeyConstants; -import org.cbioportal.web.parameter.PagingConstants; -import org.cbioportal.web.parameter.Projection; -import org.cbioportal.web.parameter.SampleIdentifier; -import org.cbioportal.web.parameter.sort.CopyNumberSegmentSortBy; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RequestAttribute; -import org.springframework.web.bind.annotation.RequestBody; -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.bind.annotation.RestController; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; - -@PublicApi -@RestController() -@RequestMapping("/api") -@Validated -@Tag(name = PublicApiTags.COPY_NUMBER_SEGMENTS, description = " ") -public class CopyNumberSegmentController { - - private static final int COPY_NUMBER_SEGMENT_MAX_PAGE_SIZE = 20000; - private static final String COPY_NUMBER_SEGMENT_DEFAULT_PAGE_SIZE = "20000"; - - @Autowired - private CopyNumberSegmentService copyNumberSegmentService; - - @PreAuthorize("hasPermission(#studyId, 'CancerStudyId', T(org.cbioportal.utils.security.AccessLevel).READ)") - @RequestMapping(value = "/studies/{studyId}/samples/{sampleId}/copy-number-segments", method = RequestMethod.GET, - produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "Get copy number segments in a sample in a study") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(array = @ArraySchema(schema = @Schema(implementation = CopyNumberSeg.class)))) - public ResponseEntity> getCopyNumberSegmentsInSampleInStudy( - @Parameter(required = true, description = "Study ID e.g. acc_tcga") - @PathVariable String studyId, - @Parameter(required = true, description = "Sample ID e.g. TCGA-OR-A5J2-01") - @PathVariable String sampleId, - @Parameter(description = "Chromosome") - @RequestParam(required = false) String chromosome, - @Parameter(description = "Level of detail of the response") - @RequestParam(defaultValue = "SUMMARY") Projection projection, - @Parameter(description = "Page size of the result list") - @Max(COPY_NUMBER_SEGMENT_MAX_PAGE_SIZE) - @Min(PagingConstants.MIN_PAGE_SIZE) - @RequestParam(defaultValue = COPY_NUMBER_SEGMENT_DEFAULT_PAGE_SIZE) Integer pageSize, - @Parameter(description = "Page number of the result list") - @Min(PagingConstants.MIN_PAGE_NUMBER) - @RequestParam(defaultValue = PagingConstants.DEFAULT_PAGE_NUMBER) Integer pageNumber, - @Parameter(description = "Name of the property that the result list is sorted by") - @RequestParam(required = false) CopyNumberSegmentSortBy sortBy, - @Parameter(description = "Direction of the sort") - @RequestParam(defaultValue = "ASC") Direction direction) throws SampleNotFoundException, - StudyNotFoundException { - - if (projection == Projection.META) { - HttpHeaders responseHeaders = new HttpHeaders(); - responseHeaders.add(HeaderKeyConstants.TOTAL_COUNT, copyNumberSegmentService - .getMetaCopyNumberSegmentsInSampleInStudy(studyId, sampleId, chromosome).getTotalCount().toString()); - return new ResponseEntity<>(responseHeaders, HttpStatus.OK); - } else { - return new ResponseEntity<>( - copyNumberSegmentService.getCopyNumberSegmentsInSampleInStudy(studyId, sampleId, chromosome, - projection.name(), pageSize, pageNumber, sortBy == null ? null : sortBy.getOriginalValue(), - direction.name()), HttpStatus.OK); - } - } - - @PreAuthorize("hasPermission(#involvedCancerStudies, 'Collection', T(org.cbioportal.utils.security.AccessLevel).READ)") - @RequestMapping(value = "/copy-number-segments/fetch", method = RequestMethod.POST, - consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "Fetch copy number segments by sample ID") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(array = @ArraySchema(schema = @Schema(implementation = CopyNumberSeg.class)))) - public ResponseEntity> fetchCopyNumberSegments( - @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface - @RequestAttribute(required = false, value = "involvedCancerStudies") Collection involvedCancerStudies, - @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface. this attribute is needed for the @PreAuthorize tag above. - @RequestAttribute(required = false, value = "interceptedSampleIdentifiers") List interceptedSampleIdentifiers, - @Parameter(required = true, description = "List of sample identifiers") - @Size(min = 1, max = PagingConstants.MAX_PAGE_SIZE) - @RequestBody(required = false) List sampleIdentifiers, - @Parameter(description = "Chromosome") - @RequestParam(required = false) String chromosome, - @Parameter(description = "Level of detail of the response") - @RequestParam(defaultValue = "SUMMARY") Projection projection) { - - List studyIds = new ArrayList<>(); - List sampleIds = new ArrayList<>(); - - for (SampleIdentifier sampleIdentifier : interceptedSampleIdentifiers) { - studyIds.add(sampleIdentifier.getStudyId()); - sampleIds.add(sampleIdentifier.getSampleId()); - } - - if (projection == Projection.META) { - HttpHeaders responseHeaders = new HttpHeaders(); - responseHeaders.add(HeaderKeyConstants.TOTAL_COUNT, copyNumberSegmentService - .fetchMetaCopyNumberSegments(studyIds, sampleIds, chromosome).getTotalCount().toString()); - return new ResponseEntity<>(responseHeaders, HttpStatus.OK); - } else { - return new ResponseEntity<>( - copyNumberSegmentService.fetchCopyNumberSegments(studyIds, sampleIds, chromosome, projection.name()), - HttpStatus.OK); - } - } -} diff --git a/src/main/java/org/cbioportal/web/CosmicCountController.java b/src/main/java/org/cbioportal/web/CosmicCountController.java deleted file mode 100644 index b696179554a..00000000000 --- a/src/main/java/org/cbioportal/web/CosmicCountController.java +++ /dev/null @@ -1,49 +0,0 @@ -package org.cbioportal.web; - -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.media.ArraySchema; -import io.swagger.v3.oas.annotations.media.Content; -import io.swagger.v3.oas.annotations.media.Schema; -import io.swagger.v3.oas.annotations.responses.ApiResponse; -import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.validation.constraints.Size; -import org.cbioportal.model.CosmicMutation; -import org.cbioportal.service.CosmicCountService; -import org.cbioportal.web.config.annotation.InternalApi; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestMethod; -import org.springframework.web.bind.annotation.RestController; - -import java.util.List; - -@InternalApi -@RestController -@Validated -@Tag(name = "Cosmic Counts", description = " ") -public class CosmicCountController { - - private static final int COSMIC_COUNT_MAX_PAGE_SIZE = 50000; - - @Autowired - private CosmicCountService cosmicCountService; - - @RequestMapping(value = "/api/cosmic-counts/fetch", method = RequestMethod.POST, - consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "Get counts within the COSMIC database by keywords") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(array = @ArraySchema(schema = @Schema(implementation = CosmicMutation.class)))) - public ResponseEntity> fetchCosmicCounts( - @Parameter(required = true, description = "List of keywords") - @Size(min = 1, max = COSMIC_COUNT_MAX_PAGE_SIZE) - @RequestBody List keywords) { - - return new ResponseEntity<>(cosmicCountService.fetchCosmicCountsByKeywords(keywords), HttpStatus.OK); - } -} diff --git a/src/main/java/org/cbioportal/web/DataAccessTokenController.java b/src/main/java/org/cbioportal/web/DataAccessTokenController.java deleted file mode 100644 index ca3681d1aec..00000000000 --- a/src/main/java/org/cbioportal/web/DataAccessTokenController.java +++ /dev/null @@ -1,170 +0,0 @@ -/* -* This file is part of cBioPortal. -* -* cBioPortal is free software: you can redistribute it and/or modify -* it under the terms of the GNU Affero General Public License as -* published by the Free Software Foundation, either version 3 of the -* License. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU Affero General Public License for more details. -* -* You should have received a copy of the GNU Affero General Public License -* along with this program. If not, see . -*/ - -package org.cbioportal.web; - -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.media.ArraySchema; -import io.swagger.v3.oas.annotations.media.Content; -import io.swagger.v3.oas.annotations.media.Schema; -import io.swagger.v3.oas.annotations.responses.ApiResponse; -import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; -import org.apache.commons.lang3.StringUtils; -import org.cbioportal.model.DataAccessToken; -import org.cbioportal.service.DataAccessTokenService; -import org.cbioportal.service.exception.DataAccessTokenNoUserIdentityException; -import org.cbioportal.service.exception.DataAccessTokenProhibitedUserException; -import org.cbioportal.utils.config.annotation.ConditionalOnProperty; -import org.cbioportal.web.config.annotation.InternalApi; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; -import org.springframework.security.core.Authentication; -import org.springframework.security.core.authority.SimpleGrantedAuthority; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestMethod; -import org.springframework.web.bind.annotation.RestController; -import org.springframework.web.client.HttpClientErrorException; - -import java.io.IOException; -import java.util.HashSet; -import java.util.List; -import java.util.Objects; -import java.util.Set; - -@InternalApi -@Validated -@RestController -@ConditionalOnProperty(name = "dat.method", havingValue = "oauth2", isNot = true, matchIfMissing = true) -@Tag(name = "Data Access Tokens", description = " ") -public class DataAccessTokenController { - - @Value("${dat.unauth_users:anonymousUser}") - private String usersWhoCannotUseTokens; - - private String userRoleToAccessToken; - @Value("${download_group:}") // default is empty string - public void setUserRoleToAccessToken(String property) { userRoleToAccessToken = property; } - - private final DataAccessTokenService tokenService; - private final Set usersWhoCannotUseTokenSet; - - private static final String FILE_NAME = "cbioportal_data_access_token.txt"; - - @Autowired - public DataAccessTokenController(DataAccessTokenService tokenService) { - this.tokenService = tokenService; - if(Objects.isNull(usersWhoCannotUseTokens)) { - usersWhoCannotUseTokens = ""; - } - usersWhoCannotUseTokenSet = new HashSet<>(List.of((usersWhoCannotUseTokens.split(",")))); - } - - @RequestMapping(method = RequestMethod.GET, value = "/api/data-access-token") - @Operation(description = "Create a new data access token") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(schema = @Schema(implementation = String.class))) - public ResponseEntity downloadDataAccessToken(Authentication authentication, - HttpServletRequest request, HttpServletResponse response) { - // for other methods add header to trigger download of the token by the browser - response.setHeader("Content-Disposition", "attachment; filename=" + FILE_NAME); - String userName = getAuthenticatedUser(authentication); - DataAccessToken token = tokenService.createDataAccessToken(userName); - if (token == null) { - return new ResponseEntity<>(HttpStatus.NOT_FOUND); - } - - return new ResponseEntity<>(token.toString(), HttpStatus.CREATED); - } - - // retrieve and trigger download OAuth2 offline token - @RequestMapping(method = RequestMethod.GET, value = "/api/data-access-token/oauth2") - @Parameter(hidden = true) - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(schema = @Schema(implementation = String.class))) - public ResponseEntity downloadOAuth2DataAccessToken(HttpServletRequest request, HttpServletResponse response) throws IOException { - throw new UnsupportedOperationException("this endpoint is only enabled when dat is set to oauth2."); - } - - @RequestMapping(method = RequestMethod.POST, value = "/api/data-access-tokens", produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "Get all data access tokens") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(schema = @Schema(implementation = DataAccessToken.class))) - public ResponseEntity createDataAccessToken(Authentication authentication) throws HttpClientErrorException { - String userName = getAuthenticatedUser(authentication); - DataAccessToken token = tokenService.createDataAccessToken(userName); - if (token == null) { - return new ResponseEntity<>(HttpStatus.NOT_FOUND); - } - return new ResponseEntity<>(token, HttpStatus.CREATED); - } - - @RequestMapping(method = RequestMethod.GET, value = "/api/data-access-tokens") - @Operation(description = "Retrieve all data access tokens") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(array = @ArraySchema(schema = @Schema(implementation = DataAccessToken.class)))) - public ResponseEntity> getAllDataAccessTokens(HttpServletRequest request, - Authentication authentication) { - String userName = getAuthenticatedUser(authentication); - List allDataAccessTokens = tokenService.getAllDataAccessTokens(userName); - return new ResponseEntity<>(allDataAccessTokens, HttpStatus.OK); - } - - @RequestMapping(method = RequestMethod.GET, value = "/api/data-access-tokens/{token}") - @Operation(description = "Retrieve an existing data access token") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(schema = @Schema(implementation = DataAccessToken.class))) - public ResponseEntity getDataAccessToken( - @Parameter(required = true, description = "token") @PathVariable String token) { - DataAccessToken dataAccessToken = tokenService.getDataAccessTokenInfo(token); - return new ResponseEntity<>(dataAccessToken, HttpStatus.OK); - } - - @RequestMapping(method = RequestMethod.DELETE, value = "/api/data-access-tokens") - @Operation(description = "Delete all data access tokens") - public void revokeAllDataAccessTokens(Authentication authentication) { - tokenService.revokeAllDataAccessTokens(getAuthenticatedUser(authentication)); - } - - @RequestMapping(method = RequestMethod.DELETE, value = "/api/data-access-tokens/{token}") - @Operation(description = "Delete a data access token") - public void revokeDataAccessToken(@Parameter(required = true, description = "token") @PathVariable String token) { - tokenService.revokeDataAccessToken(token); - } - - private String getAuthenticatedUser(Authentication authentication) { - if (authentication == null || !authentication.isAuthenticated()) { - throw new DataAccessTokenNoUserIdentityException(); - } - String username = authentication.getName(); - if (usersWhoCannotUseTokenSet.contains(username)) { - throw new DataAccessTokenProhibitedUserException(); - } - if(StringUtils.isNotEmpty(userRoleToAccessToken) && - !authentication.getAuthorities().contains(new SimpleGrantedAuthority(userRoleToAccessToken))) { - throw new DataAccessTokenProhibitedUserException(); - } - return username; - } -} diff --git a/src/main/java/org/cbioportal/web/DiscreteCopyNumberController.java b/src/main/java/org/cbioportal/web/DiscreteCopyNumberController.java deleted file mode 100644 index 5a865c054a0..00000000000 --- a/src/main/java/org/cbioportal/web/DiscreteCopyNumberController.java +++ /dev/null @@ -1,128 +0,0 @@ -package org.cbioportal.web; - -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.media.ArraySchema; -import io.swagger.v3.oas.annotations.media.Content; -import io.swagger.v3.oas.annotations.media.Schema; -import io.swagger.v3.oas.annotations.responses.ApiResponse; -import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.validation.Valid; -import org.cbioportal.model.DiscreteCopyNumberData; -import org.cbioportal.model.meta.BaseMeta; -import org.cbioportal.service.DiscreteCopyNumberService; -import org.cbioportal.service.exception.MolecularProfileNotFoundException; -import org.cbioportal.web.config.PublicApiTags; -import org.cbioportal.web.config.annotation.PublicApi; -import org.cbioportal.web.parameter.DiscreteCopyNumberEventType; -import org.cbioportal.web.parameter.DiscreteCopyNumberFilter; -import org.cbioportal.web.parameter.HeaderKeyConstants; -import org.cbioportal.web.parameter.Projection; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RequestBody; -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.bind.annotation.RestController; - -import java.util.List; - -@PublicApi -@RestController() -@RequestMapping("/api") -@Validated -@Tag(name = PublicApiTags.DISCRETE_COPY_NUMBER_ALTERATIONS, description = " ") -public class DiscreteCopyNumberController { - - @Autowired - private DiscreteCopyNumberService discreteCopyNumberService; - - @PreAuthorize("hasPermission(#molecularProfileId, 'MolecularProfileId', T(org.cbioportal.utils.security.AccessLevel).READ)") - @RequestMapping(value = "/molecular-profiles/{molecularProfileId}/discrete-copy-number", method = RequestMethod.GET, - produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "Get discrete copy number alterations in a molecular profile") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(array = @ArraySchema(schema = @Schema(implementation = DiscreteCopyNumberData.class)))) - public ResponseEntity> getDiscreteCopyNumbersInMolecularProfile( - @Parameter(required = true, description = "Molecular Profile ID e.g. acc_tcga_gistic") - @PathVariable String molecularProfileId, - @Parameter(required = true, description = "Sample List ID e.g. acc_tcga_all") - @RequestParam String sampleListId, - @Parameter(description = "Type of the copy number event") - @RequestParam(defaultValue = "HOMDEL_AND_AMP") DiscreteCopyNumberEventType discreteCopyNumberEventType, - @Parameter(description = "Level of detail of the response") - @RequestParam(defaultValue = "SUMMARY") Projection projection) throws MolecularProfileNotFoundException { - - if (projection == Projection.META) { - HttpHeaders responseHeaders = new HttpHeaders(); - responseHeaders.add(HeaderKeyConstants.TOTAL_COUNT, discreteCopyNumberService - .getMetaDiscreteCopyNumbersInMolecularProfileBySampleListId(molecularProfileId, sampleListId, null, - discreteCopyNumberEventType.getAlterationTypes()).getTotalCount().toString()); - return new ResponseEntity<>(responseHeaders, HttpStatus.OK); - } else { - return new ResponseEntity<>( - discreteCopyNumberService.getDiscreteCopyNumbersInMolecularProfileBySampleListId(molecularProfileId, - sampleListId, null, discreteCopyNumberEventType.getAlterationTypes(), projection.name()), - HttpStatus.OK); - } - } - - @PreAuthorize("hasPermission(#molecularProfileId, 'MolecularProfileId', T(org.cbioportal.utils.security.AccessLevel).READ)") - @RequestMapping(value = "/molecular-profiles/{molecularProfileId}/discrete-copy-number/fetch", - method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE, - produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "Fetch discrete copy number alterations in a molecular profile by sample ID") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(array = @ArraySchema(schema = @Schema(implementation = DiscreteCopyNumberData.class)))) - public ResponseEntity> fetchDiscreteCopyNumbersInMolecularProfile( - @Parameter(required = true, description = "Molecular Profile ID e.g. acc_tcga_gistic") - @PathVariable String molecularProfileId, - @Parameter(description = "Type of the copy number event") - @RequestParam(defaultValue = "HOMDEL_AND_AMP") DiscreteCopyNumberEventType discreteCopyNumberEventType, - @Parameter(required = true, description = "List of Sample IDs/Sample List ID and Entrez Gene IDs") - @Valid @RequestBody DiscreteCopyNumberFilter discreteCopyNumberFilter, - @Parameter(description = "Level of detail of the response") - @RequestParam(defaultValue = "SUMMARY") Projection projection) - throws MolecularProfileNotFoundException { - - if (projection == Projection.META) { - HttpHeaders responseHeaders = new HttpHeaders(); - BaseMeta baseMeta; - - if (discreteCopyNumberFilter.getSampleListId() != null) { - baseMeta = discreteCopyNumberService.getMetaDiscreteCopyNumbersInMolecularProfileBySampleListId( - molecularProfileId, discreteCopyNumberFilter.getSampleListId(), - discreteCopyNumberFilter.getEntrezGeneIds(), discreteCopyNumberEventType.getAlterationTypes()); - } else { - baseMeta = discreteCopyNumberService.fetchMetaDiscreteCopyNumbersInMolecularProfile(molecularProfileId, - discreteCopyNumberFilter.getSampleIds(), discreteCopyNumberFilter.getEntrezGeneIds(), - discreteCopyNumberEventType.getAlterationTypes()); - } - responseHeaders.add(HeaderKeyConstants.TOTAL_COUNT, baseMeta.getTotalCount().toString()); - return new ResponseEntity<>(responseHeaders, HttpStatus.OK); - } else { - List discreteCopyNumberDataList; - if (discreteCopyNumberFilter.getSampleListId() != null) { - discreteCopyNumberDataList = discreteCopyNumberService - .getDiscreteCopyNumbersInMolecularProfileBySampleListId(molecularProfileId, - discreteCopyNumberFilter.getSampleListId(), discreteCopyNumberFilter.getEntrezGeneIds(), - discreteCopyNumberEventType.getAlterationTypes(), projection.name()); - } else { - discreteCopyNumberDataList = discreteCopyNumberService.fetchDiscreteCopyNumbersInMolecularProfile( - molecularProfileId, discreteCopyNumberFilter.getSampleIds(), - discreteCopyNumberFilter.getEntrezGeneIds(), discreteCopyNumberEventType.getAlterationTypes(), - projection.name()); - } - - return new ResponseEntity<>(discreteCopyNumberDataList, HttpStatus.OK); - } - } - -} diff --git a/src/main/java/org/cbioportal/web/DiscreteCopyNumberCountController.java b/src/main/java/org/cbioportal/web/DiscreteCopyNumberCountController.java deleted file mode 100644 index da8952d57ee..00000000000 --- a/src/main/java/org/cbioportal/web/DiscreteCopyNumberCountController.java +++ /dev/null @@ -1,71 +0,0 @@ -package org.cbioportal.web; - -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.media.ArraySchema; -import io.swagger.v3.oas.annotations.media.Content; -import io.swagger.v3.oas.annotations.media.Schema; -import io.swagger.v3.oas.annotations.responses.ApiResponse; -import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.validation.constraints.Size; -import org.cbioportal.model.CopyNumberCount; -import org.cbioportal.service.DiscreteCopyNumberService; -import org.cbioportal.service.exception.MolecularProfileNotFoundException; -import org.cbioportal.web.config.InternalApiTags; -import org.cbioportal.web.config.annotation.InternalApi; -import org.cbioportal.web.parameter.CopyNumberCountIdentifier; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestMethod; -import org.springframework.web.bind.annotation.RestController; - -import java.util.ArrayList; -import java.util.List; - -@InternalApi -@RestController() -@RequestMapping("/api") -@Validated -@Tag(name = InternalApiTags.DISCRETE_COPY_NUMBER_ALTERATION_COUNTS, description = " ") -public class DiscreteCopyNumberCountController { - - private static final int COPY_NUMBER_COUNT_MAX_PAGE_SIZE = 50000; - - @Autowired - private DiscreteCopyNumberService discreteCopyNumberService; - - @PreAuthorize("hasPermission(#molecularProfileId, 'MolecularProfileId', T(org.cbioportal.utils.security.AccessLevel).READ)") - @RequestMapping(value = "/molecular-profiles/{molecularProfileId}/discrete-copy-number-counts/fetch", - method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE, - produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "Get counts of specific genes and alterations within a CNA molecular profile") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(array = @ArraySchema(schema = @Schema(implementation = CopyNumberCount.class)))) - public ResponseEntity> fetchCopyNumberCounts( - @Parameter(required = true, description = "Molecular Profile ID e.g. acc_tcga_gistic") - @PathVariable String molecularProfileId, - @Parameter(required = true, description = "List of copy number count identifiers") - @Size(min = 1, max = COPY_NUMBER_COUNT_MAX_PAGE_SIZE) - @RequestBody List copyNumberCountIdentifiers) - throws MolecularProfileNotFoundException { - - List entrezGeneIds = new ArrayList<>(); - List alterations = new ArrayList<>(); - - for (CopyNumberCountIdentifier copyNumberCountIdentifier : copyNumberCountIdentifiers) { - - entrezGeneIds.add(copyNumberCountIdentifier.getEntrezGeneId()); - alterations.add(copyNumberCountIdentifier.getAlteration()); - } - - return new ResponseEntity<>(discreteCopyNumberService.fetchCopyNumberCounts(molecularProfileId, entrezGeneIds, - alterations), HttpStatus.OK); - } -} diff --git a/src/main/java/org/cbioportal/web/DocRedirectController.java b/src/main/java/org/cbioportal/web/DocRedirectController.java deleted file mode 100644 index e04443556f0..00000000000 --- a/src/main/java/org/cbioportal/web/DocRedirectController.java +++ /dev/null @@ -1,48 +0,0 @@ -package org.cbioportal.web; - -import jakarta.servlet.http.HttpServletRequest; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.servlet.mvc.support.RedirectAttributes; -import org.springframework.web.servlet.view.RedirectView; - -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * Springfox 3.0 doesn't completely respect the path we specify for the swagger UI - * This redirect puts the api-doc json in the specified path so that the swagger UI works - * and the frontend can pull the json. - */ -//@Controller -public class DocRedirectController { - @GetMapping("/api-docs") - public RedirectView docRedirect( - @RequestParam(value = "group", defaultValue = "default") - String group, - final RedirectAttributes redirectAttributes, - HttpServletRequest request - ) { - redirectAttributes.addAttribute("group", group); - String baseUrl = getBaseUrl(request, "/api/api-docs"); - return new RedirectView(baseUrl + "/api/v2/api-docs"); - } - - @GetMapping({"/", "/swagger-ui.html"}) - public RedirectView swaggerUIRedirect( - @RequestParam(value = "group", defaultValue = "default") - String group, - final RedirectAttributes redirectAttributes, - HttpServletRequest request - ) { - redirectAttributes.addAttribute("group", group); - String baseUrl = getBaseUrl(request, "/api/(|swagger-ui.html)"); - return new RedirectView(baseUrl + "/api/swagger-ui/index.html"); - } - - private String getBaseUrl(HttpServletRequest request, String suffix) { - Pattern p = Pattern.compile("^(.*)(" + suffix + ")$"); - Matcher m = p.matcher(request.getRequestURI()); - return m.find() ? m.group(1) : ""; - } -} diff --git a/src/main/java/org/cbioportal/web/ExecuterTimeInterceptor.java b/src/main/java/org/cbioportal/web/ExecuterTimeInterceptor.java deleted file mode 100644 index cd53de8c347..00000000000 --- a/src/main/java/org/cbioportal/web/ExecuterTimeInterceptor.java +++ /dev/null @@ -1,27 +0,0 @@ -package org.cbioportal.web; - -import org.springframework.ui.ModelMap; -import org.springframework.web.context.request.WebRequest; -import org.springframework.web.context.request.WebRequestInterceptor; - -public class ExecuterTimeInterceptor implements WebRequestInterceptor { - - @Override - public void postHandle(WebRequest webRequest, ModelMap modelMap) { - //unimplemented - } - - @Override - public void afterCompletion(WebRequest webRequest, Exception e) { - //unimplemented - } - - @Override - public void preHandle(WebRequest webRequest) { - - long startTime = System.currentTimeMillis(); - webRequest.setAttribute("startTime", startTime, 0); - - } - -} \ No newline at end of file diff --git a/src/main/java/org/cbioportal/web/ExpressionEnrichmentController.java b/src/main/java/org/cbioportal/web/ExpressionEnrichmentController.java deleted file mode 100644 index a32ffd37a1d..00000000000 --- a/src/main/java/org/cbioportal/web/ExpressionEnrichmentController.java +++ /dev/null @@ -1,120 +0,0 @@ -package org.cbioportal.web; - -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.media.ArraySchema; -import io.swagger.v3.oas.annotations.media.Content; -import io.swagger.v3.oas.annotations.media.Schema; -import io.swagger.v3.oas.annotations.responses.ApiResponse; -import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.validation.Valid; -import org.cbioportal.model.EnrichmentType; -import org.cbioportal.model.ExpressionEnrichment; -import org.cbioportal.model.GenericAssayEnrichment; -import org.cbioportal.model.GenomicEnrichment; -import org.cbioportal.model.MolecularProfileCaseIdentifier; -import org.cbioportal.service.ExpressionEnrichmentService; -import org.cbioportal.service.exception.GenericAssayNotFoundException; -import org.cbioportal.service.exception.MolecularProfileNotFoundException; -import org.cbioportal.web.config.annotation.InternalApi; -import org.cbioportal.web.parameter.MolecularProfileCasesGroupFilter; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.RequestAttribute; -import org.springframework.web.bind.annotation.RequestBody; -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.bind.annotation.RestController; - -import java.util.Collection; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.stream.Collectors; - -@InternalApi -@RestController() -@RequestMapping("/api") -@Validated -@Tag(name = "Enrichments", description = " ") -public class ExpressionEnrichmentController { - @Autowired - private ExpressionEnrichmentService expressionEnrichmentService; - - @PreAuthorize("hasPermission(#involvedCancerStudies, 'Collection', T(org.cbioportal.utils.security.AccessLevel).READ)") - @RequestMapping(value = "/expression-enrichments/fetch", - method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE, - produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "Fetch genomic enrichments in a molecular profile") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(array = @ArraySchema(schema = @Schema(implementation = GenomicEnrichment.class)))) - public ResponseEntity> fetchGenomicEnrichments( - @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface - @RequestAttribute(required = false, value = "involvedCancerStudies") Collection involvedCancerStudies, - @Parameter(description = "Type of the enrichment e.g. SAMPLE or PATIENT") - @RequestParam(defaultValue = "SAMPLE") EnrichmentType enrichmentType, - @Parameter(required = true, description = "List of groups containing sample and molecular profile identifiers") - @Valid @RequestBody(required = false) List groups, - @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface. this attribute is needed for the @PreAuthorize tag above. - @Valid @RequestAttribute(required = false, value = "interceptedMolecularProfileCasesGroupFilters") List interceptedMolecularProfileCasesGroupFilters) throws MolecularProfileNotFoundException { - - return new ResponseEntity<>( - fetchExpressionEnrichments(enrichmentType, interceptedMolecularProfileCasesGroupFilters, false), - HttpStatus.OK); - } - - @PreAuthorize("hasPermission(#involvedCancerStudies, 'Collection', T(org.cbioportal.utils.security.AccessLevel).READ)") - @RequestMapping(value = "/generic-assay-enrichments/fetch", - method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE, - produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "Fetch generic assay enrichments in a molecular profile") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(array = @ArraySchema(schema = @Schema(implementation = GenericAssayEnrichment.class)))) - public ResponseEntity> fetchGenericAssayEnrichments( - @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface - @RequestAttribute(required = false, value = "involvedCancerStudies") Collection involvedCancerStudies, - @Parameter(description = "Type of the enrichment e.g. SAMPLE or PATIENT") - @RequestParam(defaultValue = "SAMPLE") EnrichmentType enrichmentType, - @Parameter(required = true, description = "List of groups containing sample and molecular profile identifiers") - @Valid @RequestBody(required = false) List groups, - @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface. this attribute is needed for the @PreAuthorize tag above. - @Valid @RequestAttribute(required = false, value = "interceptedMolecularProfileCasesGroupFilters") List interceptedMolecularProfileCasesGroupFilters) - throws MolecularProfileNotFoundException, UnsupportedOperationException, GenericAssayNotFoundException { - - return new ResponseEntity<>( - fetchExpressionEnrichments(enrichmentType, interceptedMolecularProfileCasesGroupFilters, true), - HttpStatus.OK); - } - - private List fetchExpressionEnrichments(EnrichmentType enrichmentType, - List interceptedMolecularProfileCasesGroupFilters, - Boolean isRequestForGenericAssayEnrichments) throws MolecularProfileNotFoundException { - - Map> groupCaseIdentifierSet = interceptedMolecularProfileCasesGroupFilters - .stream().collect(Collectors.toMap(MolecularProfileCasesGroupFilter::getName, - MolecularProfileCasesGroupFilter::getMolecularProfileCaseIdentifiers)); - - Set molecularProfileIds = groupCaseIdentifierSet.values().stream() - .flatMap(molecularProfileCaseSet -> molecularProfileCaseSet.stream() - .map(MolecularProfileCaseIdentifier::getMolecularProfileId)) - .collect(Collectors.toSet()); - - if (molecularProfileIds.size() > 1) { - throw new UnsupportedOperationException("Multi-study expression enrichments is not yet implemented"); - } - - if (isRequestForGenericAssayEnrichments) { - return (List) expressionEnrichmentService.getGenericAssayNumericalEnrichments( - molecularProfileIds.iterator().next(), groupCaseIdentifierSet, enrichmentType); - } - - return (List) expressionEnrichmentService.getGenomicEnrichments(molecularProfileIds.iterator().next(), - groupCaseIdentifierSet, enrichmentType); - - } -} diff --git a/src/main/java/org/cbioportal/web/GeneController.java b/src/main/java/org/cbioportal/web/GeneController.java deleted file mode 100644 index 51774d20bfa..00000000000 --- a/src/main/java/org/cbioportal/web/GeneController.java +++ /dev/null @@ -1,130 +0,0 @@ -package org.cbioportal.web; - -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.media.ArraySchema; -import io.swagger.v3.oas.annotations.media.Content; -import io.swagger.v3.oas.annotations.media.Schema; -import io.swagger.v3.oas.annotations.responses.ApiResponse; -import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.validation.constraints.Max; -import jakarta.validation.constraints.Min; -import jakarta.validation.constraints.Size; -import org.cbioportal.model.Gene; -import org.cbioportal.service.GeneService; -import org.cbioportal.service.exception.GeneNotFoundException; -import org.cbioportal.service.exception.GeneWithMultipleEntrezIdsException; -import org.cbioportal.web.config.PublicApiTags; -import org.cbioportal.web.config.annotation.PublicApi; -import org.cbioportal.web.parameter.Direction; -import org.cbioportal.web.parameter.GeneIdType; -import org.cbioportal.web.parameter.HeaderKeyConstants; -import org.cbioportal.web.parameter.PagingConstants; -import org.cbioportal.web.parameter.Projection; -import org.cbioportal.web.parameter.sort.GeneSortBy; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RequestBody; -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.bind.annotation.RestController; - -import java.util.List; - -@PublicApi -@RestController -@Validated -@Tag(name = PublicApiTags.GENES, description = " ") -public class GeneController { - - @Autowired - private GeneService geneService; - - @RequestMapping(value = "/api/genes", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "Get all genes") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(array = @ArraySchema(schema = @Schema(implementation = Gene.class)))) - public ResponseEntity> getAllGenes( - @Parameter(description = "Search keyword that applies to hugo gene symbol of the genes") - @RequestParam(required = false) String keyword, - @Parameter(description = "Alias of the gene") - @RequestParam(required = false) String alias, - @Parameter(description = "Level of detail of the response") - @RequestParam(defaultValue = "SUMMARY") Projection projection, - @Parameter(description = "Page size of the result list") - @Max(PagingConstants.MAX_PAGE_SIZE) - @Min(PagingConstants.MIN_PAGE_SIZE) - @RequestParam(defaultValue = PagingConstants.DEFAULT_PAGE_SIZE) Integer pageSize, - @Parameter(description = "Page number of the result list") - @Min(PagingConstants.MIN_PAGE_NUMBER) - @RequestParam(defaultValue = PagingConstants.DEFAULT_PAGE_NUMBER) Integer pageNumber, - @Parameter(description = "Name of the property that the result list is sorted by") - @RequestParam(required = false) GeneSortBy sortBy, - @Parameter(description = "Direction of the sort") - @RequestParam(defaultValue = "ASC") Direction direction) { - - if (projection == Projection.META) { - HttpHeaders responseHeaders = new HttpHeaders(); - responseHeaders.add(HeaderKeyConstants.TOTAL_COUNT, geneService.getMetaGenes(keyword, alias).getTotalCount() - .toString()); - return new ResponseEntity<>(responseHeaders, HttpStatus.OK); - } else { - return new ResponseEntity<>( - geneService.getAllGenes(keyword, alias, projection.name(), pageSize, pageNumber, - sortBy == null ? null : sortBy.getOriginalValue(), direction.name()), HttpStatus.OK); - } - } - - @RequestMapping(value = "/api/genes/{geneId}", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "Get a gene") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(schema = @Schema(implementation = Gene.class))) - public ResponseEntity getGene( - @Parameter(required = true, description = "Entrez Gene ID or Hugo Gene Symbol e.g. 1 or A1BG") - @PathVariable String geneId) throws GeneNotFoundException, GeneWithMultipleEntrezIdsException { - - return new ResponseEntity<>(geneService.getGene(geneId), HttpStatus.OK); - } - - @RequestMapping(value = "/api/genes/{geneId}/aliases", method = RequestMethod.GET, - produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "Get aliases of a gene") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(array = @ArraySchema(schema = @Schema(implementation = String.class)))) - public ResponseEntity> getAliasesOfGene( - @Parameter(required = true, description = "Entrez Gene ID or Hugo Gene Symbol e.g. 1 or A1BG") - @PathVariable String geneId) throws GeneNotFoundException, GeneWithMultipleEntrezIdsException { - - return new ResponseEntity<>(geneService.getAliasesOfGene(geneId), HttpStatus.OK); - } - - @RequestMapping(value = "/api/genes/fetch", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE, - produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "Fetch genes by ID") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(array = @ArraySchema(schema = @Schema(implementation = Gene.class)))) - public ResponseEntity> fetchGenes( - @RequestParam(defaultValue = "ENTREZ_GENE_ID") GeneIdType geneIdType, - @Parameter(required = true, description = "List of Gene IDs") - @Size(min = 1, max = PagingConstants.MAX_PAGE_SIZE) - @RequestBody List geneIds, - @Parameter(description = "Level of detail of the response") - @RequestParam(defaultValue = "SUMMARY") Projection projection) { - - if (projection == Projection.META) { - HttpHeaders responseHeaders = new HttpHeaders(); - responseHeaders.add(HeaderKeyConstants.TOTAL_COUNT, geneService.fetchMetaGenes(geneIds, geneIdType.name()) - .getTotalCount().toString()); - return new ResponseEntity<>(responseHeaders, HttpStatus.OK); - } else { - return new ResponseEntity<>(geneService.fetchGenes(geneIds, geneIdType.name(), projection.name()), - HttpStatus.OK); - } - } -} diff --git a/src/main/java/org/cbioportal/web/GenePanelController.java b/src/main/java/org/cbioportal/web/GenePanelController.java deleted file mode 100644 index 9bd73ff27bd..00000000000 --- a/src/main/java/org/cbioportal/web/GenePanelController.java +++ /dev/null @@ -1,127 +0,0 @@ -package org.cbioportal.web; - -import io.swagger.v3.oas.annotations.Hidden; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.extensions.Extension; -import io.swagger.v3.oas.annotations.media.ArraySchema; -import io.swagger.v3.oas.annotations.media.Content; -import io.swagger.v3.oas.annotations.media.ExampleObject; -import io.swagger.v3.oas.annotations.media.Schema; -import io.swagger.v3.oas.annotations.responses.ApiResponse; -import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.validation.constraints.Max; -import jakarta.validation.constraints.Min; -import jakarta.validation.constraints.Size; -import org.cbioportal.model.GenePanel; -import org.cbioportal.service.GenePanelService; -import org.cbioportal.service.exception.GenePanelNotFoundException; -import org.cbioportal.web.config.PublicApiTags; -import org.cbioportal.web.config.annotation.PublicApi; -import org.cbioportal.web.parameter.Direction; -import org.cbioportal.web.parameter.HeaderKeyConstants; -import org.cbioportal.web.parameter.PagingConstants; -import org.cbioportal.web.parameter.Projection; -import org.cbioportal.web.parameter.sort.GenePanelSortBy; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RequestBody; -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.bind.annotation.RestController; - -import java.util.List; - -@PublicApi -@RestController() -@RequestMapping("/api") -@Validated -@Tag(name = PublicApiTags.GENE_PANELS, description = " ") -public class GenePanelController { - - @Autowired - private GenePanelService genePanelService; - - @Hidden - @RequestMapping(value = "/gene-panels/", method = RequestMethod.GET, - produces = MediaType.APPLICATION_JSON_VALUE) - public ResponseEntity> getAllGenePanels_trailing( - @RequestParam(defaultValue = "SUMMARY") Projection projection, - @Parameter(description = "Page size of the result list") - @Max(PagingConstants.MAX_PAGE_SIZE) - @Min(PagingConstants.MIN_PAGE_SIZE) - @RequestParam(defaultValue = PagingConstants.DEFAULT_PAGE_SIZE) Integer pageSize, - @Parameter(description = "Page number of the result list") - @Min(PagingConstants.MIN_PAGE_NUMBER) - @RequestParam(defaultValue = PagingConstants.DEFAULT_PAGE_NUMBER) Integer pageNumber, - @RequestParam(required = false) GenePanelSortBy sortBy, - @Parameter(description = "Direction of the sort") - @RequestParam(defaultValue = "ASC") Direction direction) { - return getAllGenePanels(projection, pageSize, pageNumber, sortBy, direction); - } - - @RequestMapping(value = "/gene-panels", method = RequestMethod.GET, - produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "Get all gene panels") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(array = @ArraySchema(schema = @Schema(implementation = GenePanel.class)))) - public ResponseEntity> getAllGenePanels( - @Parameter(description = "Level of detail of the response") - @RequestParam(defaultValue = "SUMMARY") Projection projection, - @Parameter(description = "Page size of the result list") - @Max(PagingConstants.MAX_PAGE_SIZE) - @Min(PagingConstants.MIN_PAGE_SIZE) - @RequestParam(defaultValue = PagingConstants.DEFAULT_PAGE_SIZE) Integer pageSize, - @Parameter(description = "Page number of the result list") - @Min(PagingConstants.MIN_PAGE_NUMBER) - @RequestParam(defaultValue = PagingConstants.DEFAULT_PAGE_NUMBER) Integer pageNumber, - @Parameter(description = "Name of the property that the result list is sorted by") - @RequestParam(required = false) GenePanelSortBy sortBy, - @Parameter(description = "Direction of the sort") - @RequestParam(defaultValue = "ASC") Direction direction) { - - if (projection == Projection.META) { - HttpHeaders responseHeaders = new HttpHeaders(); - responseHeaders.add(HeaderKeyConstants.TOTAL_COUNT, genePanelService.getMetaGenePanels() - .getTotalCount().toString()); - return new ResponseEntity<>(responseHeaders, HttpStatus.OK); - } else { - return new ResponseEntity<>( - genePanelService.getAllGenePanels(projection.name(), pageSize, pageNumber, - sortBy == null ? null : sortBy.getOriginalValue(), direction.name()), HttpStatus.OK); - } - } - - @RequestMapping(value = "/gene-panels/{genePanelId}", method = RequestMethod.GET, - produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "Get gene panel") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(schema = @Schema(implementation = GenePanel.class))) - public ResponseEntity getGenePanel( - @Parameter(required = true, description = "Gene Panel ID e.g. NSCLC_UNITO_2016_PANEL") - @PathVariable String genePanelId) throws GenePanelNotFoundException { - - return new ResponseEntity<>(genePanelService.getGenePanel(genePanelId), HttpStatus.OK); - } - - @RequestMapping(value = "/gene-panels/fetch", method = RequestMethod.POST, - consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "Get gene panel") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(array = @ArraySchema(schema = @Schema(implementation = GenePanel.class)))) - public ResponseEntity> fetchGenePanels( - @Parameter(required = true, description = "List of Gene Panel IDs") - @Size(min = 1, max = PagingConstants.MAX_PAGE_SIZE) - @RequestBody List genePanelIds, - @Parameter(description = "Level of detail of the response") - @RequestParam(defaultValue = "SUMMARY") Projection projection) { - - return new ResponseEntity<>(genePanelService.fetchGenePanels(genePanelIds, projection.name()), HttpStatus.OK); - } -} diff --git a/src/main/java/org/cbioportal/web/GenePanelDataController.java b/src/main/java/org/cbioportal/web/GenePanelDataController.java deleted file mode 100644 index 6864a6c5db3..00000000000 --- a/src/main/java/org/cbioportal/web/GenePanelDataController.java +++ /dev/null @@ -1,105 +0,0 @@ -package org.cbioportal.web; - -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.media.ArraySchema; -import io.swagger.v3.oas.annotations.media.Content; -import io.swagger.v3.oas.annotations.media.Schema; -import io.swagger.v3.oas.annotations.responses.ApiResponse; -import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.validation.Valid; -import org.cbioportal.model.GenePanelData; -import org.cbioportal.model.MolecularProfileCaseIdentifier; -import org.cbioportal.service.GenePanelService; -import org.cbioportal.service.exception.MolecularProfileNotFoundException; -import org.cbioportal.web.config.PublicApiTags; -import org.cbioportal.web.config.annotation.PublicApi; -import org.cbioportal.web.parameter.GenePanelDataFilter; -import org.cbioportal.web.parameter.GenePanelDataMultipleStudyFilter; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.util.CollectionUtils; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RequestAttribute; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestMethod; -import org.springframework.web.bind.annotation.RestController; - -import java.util.Collection; -import java.util.HashSet; -import java.util.List; -import java.util.stream.Collectors; - -@PublicApi -@RestController -@RequestMapping("/api") -@Validated -@Tag(name = PublicApiTags.GENE_PANEL_DATA, description = " ") -public class GenePanelDataController { - - @Autowired - private GenePanelService genePanelService; - - @PreAuthorize("hasPermission(#molecularProfileId, 'MolecularProfileId', T(org.cbioportal.utils.security.AccessLevel).READ)") - @RequestMapping(value = "/molecular-profiles/{molecularProfileId}/gene-panel-data/fetch", method = RequestMethod.POST, - consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "Get gene panel data") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(array = @ArraySchema(schema = @Schema(implementation = GenePanelData.class)))) - public ResponseEntity> getGenePanelData( - @Parameter(required = true, description = "Molecular Profile ID e.g. nsclc_unito_2016_mutations") - @PathVariable String molecularProfileId, - @Parameter(required = true, description = "List of Sample IDs/Sample List ID and Entrez Gene IDs") - @Valid @RequestBody GenePanelDataFilter genePanelDataFilter) throws MolecularProfileNotFoundException { - - List genePanelDataList; - if (genePanelDataFilter.getSampleListId() != null) { - genePanelDataList = genePanelService.getGenePanelData(molecularProfileId, - genePanelDataFilter.getSampleListId()); - } else { - genePanelDataList = genePanelService.fetchGenePanelData(molecularProfileId, - genePanelDataFilter.getSampleIds()); - } - - return new ResponseEntity<>(genePanelDataList, HttpStatus.OK); - } - - @PreAuthorize("hasPermission(#involvedCancerStudies, 'Collection', T(org.cbioportal.utils.security.AccessLevel).READ)") - @RequestMapping(value = "/gene-panel-data/fetch", method = RequestMethod.POST, - consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "Fetch gene panel data") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(array = @ArraySchema(schema = @Schema(implementation = GenePanelData.class)))) - public ResponseEntity> fetchGenePanelDataInMultipleMolecularProfiles( - @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface - @RequestAttribute(required = false, value = "involvedCancerStudies") Collection involvedCancerStudies, - @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface. this attribute is needed for the @PreAuthorize tag above. - @Valid @RequestAttribute(required = false, value = "interceptedGenePanelDataMultipleStudyFilter") GenePanelDataMultipleStudyFilter interceptedGenePanelDataMultipleStudyFilter, - @Parameter(required = true, description = "Gene panel data filter object") - @RequestBody(required = false) GenePanelDataMultipleStudyFilter genePanelDataMultipleStudyFilter) { - - List genePanelDataList; - if(CollectionUtils.isEmpty(interceptedGenePanelDataMultipleStudyFilter.getMolecularProfileIds())) { - List molecularProfileSampleIdentifiers = interceptedGenePanelDataMultipleStudyFilter.getSampleMolecularIdentifiers() - .stream() - .map(sampleMolecularIdentifier -> { - MolecularProfileCaseIdentifier profileCaseIdentifier = new MolecularProfileCaseIdentifier(); - profileCaseIdentifier.setMolecularProfileId(sampleMolecularIdentifier.getMolecularProfileId()); - profileCaseIdentifier.setCaseId(sampleMolecularIdentifier.getSampleId()); - return profileCaseIdentifier; - }) - .collect(Collectors.toList()); - - genePanelDataList = genePanelService.fetchGenePanelDataInMultipleMolecularProfiles(molecularProfileSampleIdentifiers); - } else { - genePanelDataList = genePanelService.fetchGenePanelDataByMolecularProfileIds(new HashSet<>(interceptedGenePanelDataMultipleStudyFilter.getMolecularProfileIds())); - } - - return new ResponseEntity<>(genePanelDataList, HttpStatus.OK); - } -} diff --git a/src/main/java/org/cbioportal/web/GeneralControllerAdvice.java b/src/main/java/org/cbioportal/web/GeneralControllerAdvice.java deleted file mode 100644 index dbf2fc9d867..00000000000 --- a/src/main/java/org/cbioportal/web/GeneralControllerAdvice.java +++ /dev/null @@ -1,31 +0,0 @@ -package org.cbioportal.web; - -import org.springframework.core.MethodParameter; -import org.springframework.http.MediaType; -import org.springframework.http.converter.HttpMessageConverter; -import org.springframework.http.server.ServerHttpRequest; -import org.springframework.http.server.ServerHttpResponse; -import org.springframework.http.server.ServletServerHttpRequest; -import org.springframework.web.bind.annotation.ControllerAdvice; -import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice; - -@ControllerAdvice -public class GeneralControllerAdvice implements ResponseBodyAdvice { - - @Override - public boolean supports(MethodParameter returnType, Class> converterType) { - return true; - } - - @Override - public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) { - ServletServerHttpRequest servletServerRequest = (ServletServerHttpRequest) request; - - // report the procesing time of all api endpoints to aid in benchmarking as we transition - // to clickhouse - long startTime = (long) servletServerRequest.getServletRequest().getAttribute("startTime"); - long timeElapsed = System.currentTimeMillis() - startTime; - response.getHeaders().add("Elapsed-Time", String.valueOf(timeElapsed)); - return body; - } -} \ No newline at end of file diff --git a/src/main/java/org/cbioportal/web/GenericAssayController.java b/src/main/java/org/cbioportal/web/GenericAssayController.java deleted file mode 100644 index ae10b64c88b..00000000000 --- a/src/main/java/org/cbioportal/web/GenericAssayController.java +++ /dev/null @@ -1,101 +0,0 @@ -package org.cbioportal.web; - -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.media.ArraySchema; -import io.swagger.v3.oas.annotations.media.Content; -import io.swagger.v3.oas.annotations.media.Schema; -import io.swagger.v3.oas.annotations.responses.ApiResponse; -import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.validation.Valid; -import org.cbioportal.model.meta.GenericAssayMeta; -import org.cbioportal.service.GenericAssayService; -import org.cbioportal.service.exception.GenericAssayNotFoundException; -import org.cbioportal.web.config.PublicApiTags; -import org.cbioportal.web.config.annotation.PublicApi; -import org.cbioportal.web.parameter.GenericAssayMetaFilter; -import org.cbioportal.web.parameter.Projection; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RequestBody; -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.bind.annotation.RestController; - -import java.util.Arrays; -import java.util.List; - -@PublicApi -@RestController() -@RequestMapping("/api") -@Validated -@Tag(name = PublicApiTags.GENERIC_ASSAYS, description = " ") -public class GenericAssayController { - - @Autowired - private GenericAssayService genericAssayService; - - // PreAuthorize is removed for performance reason - @RequestMapping(value = "/generic_assay_meta/fetch", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE, - produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "Fetch meta data for generic-assay by ID") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(array = @ArraySchema(schema = @Schema(implementation = GenericAssayMeta.class)))) - public ResponseEntity> fetchGenericAssayMeta( - @Parameter(required = true, description = "List of Molecular Profile ID or List of Stable ID") - @Valid @RequestBody GenericAssayMetaFilter genericAssayMetaFilter, - @Parameter(description = "Level of detail of the response") - @RequestParam(defaultValue = "SUMMARY") Projection projection) throws GenericAssayNotFoundException { - List result; - - if (genericAssayMetaFilter.getGenericAssayStableIds() == null) { - result = genericAssayService.getGenericAssayMetaByStableIdsAndMolecularIds(null, genericAssayMetaFilter.getMolecularProfileIds(), projection.name()); - } else if (genericAssayMetaFilter.getMolecularProfileIds() == null) { - result = genericAssayService.getGenericAssayMetaByStableIdsAndMolecularIds(genericAssayMetaFilter.getGenericAssayStableIds(), null, projection.name()); - } else { - result = genericAssayService.getGenericAssayMetaByStableIdsAndMolecularIds(genericAssayMetaFilter.getGenericAssayStableIds(), genericAssayMetaFilter.getMolecularProfileIds(), projection.name()); - } - return new ResponseEntity<>(result, HttpStatus.OK); - } - - // PreAuthorize is removed for performance reason - @RequestMapping(value = "/generic-assay-meta/{molecularProfileId}", method = RequestMethod.GET, - produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "Fetch meta data for generic-assay by ID") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(array = @ArraySchema(schema = @Schema(implementation = GenericAssayMeta.class)))) - public ResponseEntity> getGenericAssayMeta( - @Parameter(required = true, description = "Molecular Profile ID") - @PathVariable String molecularProfileId, - @Parameter(description = "Level of detail of the response") - @RequestParam(defaultValue = "SUMMARY") Projection projection) throws GenericAssayNotFoundException { - List result; - - result = genericAssayService.getGenericAssayMetaByStableIdsAndMolecularIds(null, Arrays.asList(molecularProfileId), projection.name()); - - return new ResponseEntity<>(result, HttpStatus.OK); - } - - @RequestMapping(value = "/generic-assay-meta/generic-assay/{genericAssayStableId}", method = RequestMethod.GET, - produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "Fetch meta data for generic-assay by ID") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(array = @ArraySchema(schema = @Schema(implementation = GenericAssayMeta.class)))) - public ResponseEntity> getGenericAssayMeta_ga( - @Parameter(required = false, description = "Generic Assay stable ID") - @PathVariable String genericAssayStableId, - @Parameter(description = "Level of detail of the response") - @RequestParam(defaultValue = "SUMMARY") Projection projection) throws GenericAssayNotFoundException { - List result; - result = genericAssayService.getGenericAssayMetaByStableIdsAndMolecularIds(Arrays.asList(genericAssayStableId), null, projection.name()); - - return new ResponseEntity<>(result, HttpStatus.OK); - } - - -} diff --git a/src/main/java/org/cbioportal/web/GenericAssayDataController.java b/src/main/java/org/cbioportal/web/GenericAssayDataController.java deleted file mode 100644 index 8cfc55bdb7a..00000000000 --- a/src/main/java/org/cbioportal/web/GenericAssayDataController.java +++ /dev/null @@ -1,165 +0,0 @@ -package org.cbioportal.web; - -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.media.ArraySchema; -import io.swagger.v3.oas.annotations.media.Content; -import io.swagger.v3.oas.annotations.media.Schema; -import io.swagger.v3.oas.annotations.responses.ApiResponse; -import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.validation.Valid; -import org.apache.commons.lang3.StringUtils; -import org.cbioportal.model.GenericAssayData; -import org.cbioportal.service.GenericAssayService; -import org.cbioportal.service.exception.MolecularProfileNotFoundException; -import org.cbioportal.web.config.PublicApiTags; -import org.cbioportal.web.config.annotation.PublicApi; -import org.cbioportal.web.parameter.GenericAssayDataMultipleStudyFilter; -import org.cbioportal.web.parameter.GenericAssayFilter; -import org.cbioportal.web.parameter.HeaderKeyConstants; -import org.cbioportal.web.parameter.Projection; -import org.cbioportal.web.parameter.SampleMolecularIdentifier; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RequestAttribute; -import org.springframework.web.bind.annotation.RequestBody; -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.bind.annotation.RestController; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.List; -import java.util.stream.Collectors; - -@PublicApi -@RestController -@RequestMapping("/api") -@Validated -@Tag(name = PublicApiTags.GENERIC_ASSAY_DATA, description = " ") -public class GenericAssayDataController { - - @Autowired - private GenericAssayService genericAssayService; - - @PreAuthorize("hasPermission(#molecularProfileId, 'MolecularProfileId', T(org.cbioportal.utils.security.AccessLevel).READ)") - @RequestMapping(value = "/generic-assay-data/{molecularProfileId}/generic-assay/{genericAssayStableId}", method = RequestMethod.GET, - produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "Get generic_assay_data in a molecular profile") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(array = @ArraySchema(schema = @Schema(implementation = GenericAssayData.class)))) - public ResponseEntity> getGenericAssayDataInMolecularProfile( - @Parameter(required = true, description = "Molecular Profile ID") - @PathVariable String molecularProfileId, - @Parameter(required = true, description = "Generic Assay stable ID") - @PathVariable String genericAssayStableId, - @Parameter(description = "Level of detail of the response") - @RequestParam(defaultValue = "SUMMARY") Projection projection) throws MolecularProfileNotFoundException { - - List result; - result = filterEmptyGenericAssayData(genericAssayService.fetchGenericAssayData(molecularProfileId, - null, Arrays.asList(genericAssayStableId) , projection.name())); - - if (projection == Projection.META) { - HttpHeaders responseHeaders = new HttpHeaders(); - responseHeaders.add(HeaderKeyConstants.TOTAL_COUNT, String.valueOf(result.size())); - return new ResponseEntity<>(responseHeaders, HttpStatus.OK); - } else { - return new ResponseEntity<>(result, HttpStatus.OK); - } - } - - @PreAuthorize("hasPermission(#molecularProfileId, 'MolecularProfileId', T(org.cbioportal.utils.security.AccessLevel).READ)") - @RequestMapping(value = "/generic_assay_data/{molecularProfileId}/fetch", - method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE, - produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "fetch generic_assay_data in a molecular profile") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(array = @ArraySchema(schema = @Schema(implementation = GenericAssayData.class)))) - public ResponseEntity> fetchGenericAssayDataInMolecularProfile( - @Parameter(required = true, description = "Molecular Profile ID") - @PathVariable String molecularProfileId, - @Parameter(required = true, description = "List of Sample IDs/Sample List ID and Generic Assay IDs") - @Valid @RequestBody GenericAssayFilter genericAssayDataFilter, - @Parameter(description = "Level of detail of the response") - @RequestParam(defaultValue = "SUMMARY") Projection projection) throws MolecularProfileNotFoundException { - - List result; - if (genericAssayDataFilter.getSampleListId() != null) { - result = filterEmptyGenericAssayData(genericAssayService.getGenericAssayData(molecularProfileId, - genericAssayDataFilter.getSampleListId(), genericAssayDataFilter.getGenericAssayStableIds(), projection.name())); - } else { - result = filterEmptyGenericAssayData(genericAssayService.fetchGenericAssayData(molecularProfileId, - genericAssayDataFilter.getSampleIds(), genericAssayDataFilter.getGenericAssayStableIds(), projection.name())); - } - - if (projection == Projection.META) { - HttpHeaders responseHeaders = new HttpHeaders(); - responseHeaders.add(HeaderKeyConstants.TOTAL_COUNT, String.valueOf(result.size())); - return new ResponseEntity<>(responseHeaders, HttpStatus.OK); - } else { - return new ResponseEntity<>(result, HttpStatus.OK); - } - } - - @PreAuthorize("hasPermission(#involvedCancerStudies, 'Collection', T(org.cbioportal.utils.security.AccessLevel).READ)") - @RequestMapping(value = "/generic_assay_data/fetch", method = RequestMethod.POST, - consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "Fetch generic_assay_data") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(array = @ArraySchema(schema = @Schema(implementation = GenericAssayData.class)))) - public ResponseEntity> fetchGenericAssayDataInMultipleMolecularProfiles( - @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface - @RequestAttribute(required = false, value = "involvedCancerStudies") Collection involvedCancerStudies, - @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface. this attribute is needed for the @PreAuthorize tag above. - @RequestAttribute(required = false, value = "interceptedGenericAssayDataMultipleStudyFilter") GenericAssayDataMultipleStudyFilter interceptedGenericAssayDataMultipleStudyFilter, - @Parameter(required = true, description = "List of Molecular Profile ID and Sample ID pairs or List of Molecular" + - "Profile IDs and Generic Assay IDs") - @Valid @RequestBody(required = false) GenericAssayDataMultipleStudyFilter genericAssayDataMultipleStudyFilter, - @Parameter(description = "Level of detail of the response") - @RequestParam(defaultValue = "SUMMARY") Projection projection) throws MolecularProfileNotFoundException { - - List result; - if (interceptedGenericAssayDataMultipleStudyFilter.getMolecularProfileIds() != null) { - result = filterEmptyGenericAssayData(genericAssayService.fetchGenericAssayData( - interceptedGenericAssayDataMultipleStudyFilter.getMolecularProfileIds(), null, - interceptedGenericAssayDataMultipleStudyFilter.getGenericAssayStableIds(), projection.name())); - } else { - - List molecularProfileIds = new ArrayList<>(); - List sampleIds = new ArrayList<>(); - extractMolecularProfileAndSampleIds(interceptedGenericAssayDataMultipleStudyFilter, molecularProfileIds, sampleIds); - result = filterEmptyGenericAssayData(genericAssayService.fetchGenericAssayData(molecularProfileIds, - sampleIds, interceptedGenericAssayDataMultipleStudyFilter.getGenericAssayStableIds(), projection.name())); - } - - if (projection == Projection.META) { - HttpHeaders responseHeaders = new HttpHeaders(); - responseHeaders.add(HeaderKeyConstants.TOTAL_COUNT, String.valueOf(result.size())); - return new ResponseEntity<>(responseHeaders, HttpStatus.OK); - } else { - return new ResponseEntity<>(result, HttpStatus.OK); - } - } - - private void extractMolecularProfileAndSampleIds(GenericAssayDataMultipleStudyFilter molecularDataMultipleStudyFilter, List molecularProfileIds, List sampleIds) { - for (SampleMolecularIdentifier sampleMolecularIdentifier : molecularDataMultipleStudyFilter.getSampleMolecularIdentifiers()) { - molecularProfileIds.add(sampleMolecularIdentifier.getMolecularProfileId()); - sampleIds.add(sampleMolecularIdentifier.getSampleId()); - } - } - - private List filterEmptyGenericAssayData(List genericAssayDataList) { - return genericAssayDataList.stream() - .filter(g -> StringUtils.isNotEmpty(g.getValue()) && !g.getValue().equals("NA")) - .collect(Collectors.toList()); - } -} diff --git a/src/main/java/org/cbioportal/web/GenericAssayEnrichmentController.java b/src/main/java/org/cbioportal/web/GenericAssayEnrichmentController.java deleted file mode 100644 index 8959681e09b..00000000000 --- a/src/main/java/org/cbioportal/web/GenericAssayEnrichmentController.java +++ /dev/null @@ -1,123 +0,0 @@ -package org.cbioportal.web; - -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.media.ArraySchema; -import io.swagger.v3.oas.annotations.media.Content; -import io.swagger.v3.oas.annotations.media.Schema; -import io.swagger.v3.oas.annotations.responses.ApiResponse; -import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.validation.Valid; -import org.cbioportal.model.EnrichmentType; -import org.cbioportal.model.GenericAssayBinaryEnrichment; -import org.cbioportal.model.GenericAssayCategoricalEnrichment; -import org.cbioportal.model.MolecularProfileCaseIdentifier; -import org.cbioportal.service.ExpressionEnrichmentService; -import org.cbioportal.service.exception.MolecularProfileNotFoundException; -import org.cbioportal.web.config.annotation.InternalApi; -import org.cbioportal.web.parameter.MolecularProfileCasesGroupFilter; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.RequestAttribute; -import org.springframework.web.bind.annotation.RequestBody; -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.bind.annotation.RestController; - -import java.util.Collection; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.stream.Collectors; - -@InternalApi -@RestController -@Validated -@Tag(name = "Generic Assay Enrichment Data", description = " ") -public class GenericAssayEnrichmentController { - @Autowired - private ExpressionEnrichmentService expressionEnrichmentService; - - @PreAuthorize("hasPermission(#involvedCancerStudies, 'Collection', T(org.cbioportal.utils.security.AccessLevel).READ)") - @RequestMapping(value = "/api/generic-assay-categorical-enrichments/fetch", - method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE, - produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "Fetch generic assay categorical data enrichments in a molecular profile") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(array = @ArraySchema(schema = @Schema(implementation = GenericAssayCategoricalEnrichment.class)))) - public ResponseEntity> fetchGenericAssayCategoricalDataEnrichmentInMultipleMolecularProfiles( - @Parameter(hidden = true) - @RequestAttribute(required = false, value = "involvedCancerStudies") Collection involvedCancerStudies, - @Parameter(description = "Type of the enrichment e.g. SAMPLE or PATIENT") - @RequestParam(defaultValue = "SAMPLE") EnrichmentType enrichmentType, - @Parameter(required = true, description = "List of groups containing sample and molecular profile identifiers") - @Valid @RequestBody(required = false) List groups, - @Parameter(hidden = true) - @Valid @RequestAttribute(required = false, value = "interceptedMolecularProfileCasesGroupFilters") List interceptedMolecularProfileCasesGroupFilters) - throws MolecularProfileNotFoundException, UnsupportedOperationException { - - return new ResponseEntity<>(fetchExpressionEnrichments(enrichmentType, interceptedMolecularProfileCasesGroupFilters), - HttpStatus.OK); - } - - @PreAuthorize("hasPermission(#involvedCancerStudies, 'Collection', T(org.cbioportal.utils.security.AccessLevel).READ)") - @RequestMapping(value = "/api/generic-assay-binary-enrichments/fetch", - method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE, - produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "Fetch generic assay binary data enrichments in a molecular profile") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(array = @ArraySchema(schema = @Schema(implementation = GenericAssayBinaryEnrichment.class)))) - public ResponseEntity> fetchGenericAssayBinaryDataEnrichmentInMultipleMolecularProfiles( - @Parameter(hidden = true) - @RequestAttribute(required = false, value = "involvedCancerStudies") Collection involvedCancerStudies, - @Parameter(description = "Type of the enrichment e.g. SAMPLE or PATIENT") - @RequestParam(defaultValue = "SAMPLE") EnrichmentType enrichmentType, - @Parameter(required = true, description = "List of groups containing sample and molecular profile identifiers") - @Valid @RequestBody(required = false) List groups, - @Parameter(hidden = true) - @Valid @RequestAttribute(required = false, value = "interceptedMolecularProfileCasesGroupFilters") List interceptedMolecularProfileCasesGroupFilters) - throws MolecularProfileNotFoundException, UnsupportedOperationException { - - Map> groupCaseIdentifierSet = interceptedMolecularProfileCasesGroupFilters - .stream().collect(Collectors.toMap(MolecularProfileCasesGroupFilter::getName, - MolecularProfileCasesGroupFilter::getMolecularProfileCaseIdentifiers)); - - Set molecularProfileIds = groupCaseIdentifierSet.values().stream() - .flatMap(molecularProfileCaseSet -> molecularProfileCaseSet.stream() - .map(MolecularProfileCaseIdentifier::getMolecularProfileId)) - .collect(Collectors.toSet()); - - if (molecularProfileIds.size() > 1) { - throw new UnsupportedOperationException("Multi-study enrichments is not yet implemented"); - } - - return new ResponseEntity<>( - expressionEnrichmentService.getGenericAssayBinaryEnrichments( - molecularProfileIds.iterator().next(), groupCaseIdentifierSet, enrichmentType), - HttpStatus.OK); - } - - private List fetchExpressionEnrichments(EnrichmentType enrichmentType, - List interceptedMolecularProfileCasesGroupFilters - ) throws MolecularProfileNotFoundException { - Map> groupCaseIdentifierSet = interceptedMolecularProfileCasesGroupFilters - .stream().collect(Collectors.toMap(MolecularProfileCasesGroupFilter::getName, - MolecularProfileCasesGroupFilter::getMolecularProfileCaseIdentifiers)); - - Set molecularProfileIds = groupCaseIdentifierSet.values().stream() - .flatMap(molecularProfileCaseSet -> molecularProfileCaseSet.stream() - .map(MolecularProfileCaseIdentifier::getMolecularProfileId)) - .collect(Collectors.toSet()); - - if (molecularProfileIds.size() > 1) { - throw new UnsupportedOperationException("Multi-study expression enrichments is not yet implemented"); - } - return expressionEnrichmentService.getGenericAssayCategoricalEnrichments( - molecularProfileIds.iterator().next(), groupCaseIdentifierSet, enrichmentType); - } -} diff --git a/src/main/java/org/cbioportal/web/GenesetController.java b/src/main/java/org/cbioportal/web/GenesetController.java deleted file mode 100644 index 0e4eeb56bcc..00000000000 --- a/src/main/java/org/cbioportal/web/GenesetController.java +++ /dev/null @@ -1,102 +0,0 @@ -package org.cbioportal.web; - -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.media.ArraySchema; -import io.swagger.v3.oas.annotations.media.Content; -import io.swagger.v3.oas.annotations.media.Schema; -import io.swagger.v3.oas.annotations.responses.ApiResponse; -import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.validation.constraints.Max; -import jakarta.validation.constraints.Min; -import jakarta.validation.constraints.Size; -import org.cbioportal.model.Geneset; -import org.cbioportal.service.GenesetService; -import org.cbioportal.service.exception.GenesetNotFoundException; -import org.cbioportal.web.config.annotation.InternalApi; -import org.cbioportal.web.parameter.HeaderKeyConstants; -import org.cbioportal.web.parameter.PagingConstants; -import org.cbioportal.web.parameter.Projection; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RequestBody; -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.bind.annotation.RestController; - -import java.util.List; - -@InternalApi -@RestController -@Validated -@Tag(name = "Gene Sets", description = " ") -public class GenesetController { - - @Autowired - private GenesetService genesetService; - - @RequestMapping(value = "/api/genesets", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "Get all gene sets") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(array = @ArraySchema(schema = @Schema(implementation = Geneset.class)))) - public ResponseEntity> getAllGenesets( - @Parameter(description = "Level of detail of the response") - @RequestParam(defaultValue = "SUMMARY") Projection projection, - @Parameter(description = "Page size of the result list") - @Max(Integer.MAX_VALUE) - @Min(PagingConstants.MIN_PAGE_SIZE) - @RequestParam(defaultValue = PagingConstants.DEFAULT_PAGE_SIZE) Integer pageSize, - @Parameter(description = "Page number of the result list") - @Min(PagingConstants.MIN_PAGE_NUMBER) - @RequestParam(defaultValue = PagingConstants.DEFAULT_PAGE_NUMBER) Integer pageNumber) { - - if (projection == Projection.META) { - HttpHeaders responseHeaders = new HttpHeaders(); - responseHeaders.add(HeaderKeyConstants.TOTAL_COUNT, genesetService.getMetaGenesets().getTotalCount() - .toString()); - return new ResponseEntity<>(responseHeaders, HttpStatus.OK); - } else { - return new ResponseEntity<>( - genesetService.getAllGenesets(projection.name(), pageSize, pageNumber), HttpStatus.OK); - } - } - - @RequestMapping(value = "/api/genesets/{genesetId}", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "Get a gene set") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(schema = @Schema(implementation = Geneset.class))) - public ResponseEntity getGeneset( - @Parameter(required = true, description = "Gene set ID e.g. GNF2_ZAP70") - @PathVariable String genesetId) throws GenesetNotFoundException { - - return new ResponseEntity<>(genesetService.getGeneset(genesetId), HttpStatus.OK); - } - - @RequestMapping(value = "/api/genesets/fetch", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE, - produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "Fetch gene sets by ID") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(array = @ArraySchema(schema = @Schema(implementation = Geneset.class)))) - public ResponseEntity> fetchGenesets( - @Parameter(required = true, description = "List of Geneset IDs") - @Size(min = 1, max = PagingConstants.MAX_PAGE_SIZE) - @RequestBody List genesetIds) { - - return new ResponseEntity<>(genesetService.fetchGenesets(genesetIds), HttpStatus.OK); - } - - @RequestMapping(value = "/api/genesets/version", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "Get the geneset version") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(schema = @Schema(implementation = String.class))) - public ResponseEntity getGenesetVersion() { - - return new ResponseEntity<>("\""+genesetService.getGenesetVersion() +"\"", HttpStatus.OK); - } -} diff --git a/src/main/java/org/cbioportal/web/GenesetCorrelationController.java b/src/main/java/org/cbioportal/web/GenesetCorrelationController.java deleted file mode 100644 index 1859079bbbe..00000000000 --- a/src/main/java/org/cbioportal/web/GenesetCorrelationController.java +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright (c) 2016 The Hyve B.V. - * This code is licensed under the GNU Affero General Public License (AGPL), - * version 3, or (at your option) any later version. - */ - -/* - * This file is part of cBioPortal. - * - * cBioPortal is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . -*/ - -package org.cbioportal.web; - -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.media.ArraySchema; -import io.swagger.v3.oas.annotations.media.Content; -import io.swagger.v3.oas.annotations.media.Schema; -import io.swagger.v3.oas.annotations.responses.ApiResponse; -import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.validation.constraints.Max; -import jakarta.validation.constraints.Min; -import org.cbioportal.model.GenesetCorrelation; -import org.cbioportal.service.GenesetCorrelationService; -import org.cbioportal.service.exception.GenesetNotFoundException; -import org.cbioportal.service.exception.MolecularProfileNotFoundException; -import org.cbioportal.service.exception.SampleListNotFoundException; -import org.cbioportal.web.config.annotation.InternalApi; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RequestBody; -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.bind.annotation.RestController; - -import java.util.List; - -@InternalApi -@RestController() -@RequestMapping("/api") -@Validated -@Tag(name = "Gene Set Correlation", description = " ") -public class GenesetCorrelationController { - - @Autowired - private GenesetCorrelationService genesetCorrelationService; - - @PreAuthorize("hasPermission(#geneticProfileId, 'GeneticProfileId', T(org.cbioportal.utils.security.AccessLevel).READ)") - @RequestMapping(value = "/genesets/{genesetId}/expression-correlation/fetch", method = RequestMethod.POST, - consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "Get the genes in a gene set that have expression correlated to the gene set scores (calculated using Spearman's correlation)") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(array = @ArraySchema(schema = @Schema(implementation = GenesetCorrelation.class)))) - public ResponseEntity> fetchCorrelatedGenes( - @Parameter(required = true, description = "Gene set ID, e.g. HINATA_NFKB_MATRIX.") - @PathVariable String genesetId, - @Parameter(required = true, description = "Genetic Profile ID e.g. gbm_tcga_gsva_scores") - @RequestParam String geneticProfileId, - @Parameter(description = "Correlation threshold (for absolute correlation value, Spearman correlation)") - @Max(1) - @Min(0) - @RequestParam(defaultValue = "0.3") Double correlationThreshold, - @Parameter(description = "Identifier of pre-defined sample list with samples to query, e.g. brca_tcga_all") - @RequestParam(required = false) String sampleListId, - @Parameter(description = "Fill this one if you want to specify a subset of samples:" - + " sampleIds: custom list of samples or patients to query, e.g. [\"TCGA-A1-A0SD-01\", \"TCGA-A1-A0SE-01\"]") - @RequestBody(required = false) List sampleIds) - throws MolecularProfileNotFoundException, SampleListNotFoundException, GenesetNotFoundException { - - if (sampleListId != null && sampleListId.trim().length() > 0) { - return new ResponseEntity<>( - genesetCorrelationService.fetchCorrelatedGenes(genesetId, geneticProfileId, sampleListId, correlationThreshold.doubleValue()), - HttpStatus.OK); - } - if (sampleIds != null && sampleIds.size() > 0) { - return new ResponseEntity<>( - genesetCorrelationService.fetchCorrelatedGenes(genesetId, geneticProfileId, sampleIds, correlationThreshold.doubleValue()), - HttpStatus.OK); - } else { - return new ResponseEntity<>( - genesetCorrelationService.fetchCorrelatedGenes(genesetId, geneticProfileId, correlationThreshold.doubleValue()), - HttpStatus.OK); - } - } -} diff --git a/src/main/java/org/cbioportal/web/GenesetDataController.java b/src/main/java/org/cbioportal/web/GenesetDataController.java deleted file mode 100644 index 9c911d8d18e..00000000000 --- a/src/main/java/org/cbioportal/web/GenesetDataController.java +++ /dev/null @@ -1,68 +0,0 @@ -package org.cbioportal.web; - -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.media.ArraySchema; -import io.swagger.v3.oas.annotations.media.Content; -import io.swagger.v3.oas.annotations.media.Schema; -import io.swagger.v3.oas.annotations.responses.ApiResponse; -import io.swagger.v3.oas.annotations.tags.Tag; -import org.cbioportal.model.GenesetMolecularData; -import org.cbioportal.service.GenesetDataService; -import org.cbioportal.service.exception.MolecularProfileNotFoundException; -import org.cbioportal.service.exception.SampleListNotFoundException; -import org.cbioportal.web.config.annotation.InternalApi; -import org.cbioportal.web.parameter.GenesetDataFilterCriteria; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestMethod; -import org.springframework.web.bind.annotation.RestController; - -import java.util.List; - -@InternalApi -@RestController() -@RequestMapping("/api") -@Validated -@Tag(name = "Gene Set Scores", description = " ") -public class GenesetDataController { - - - @Autowired - private GenesetDataService genesetDataService; - - @PreAuthorize("hasPermission(#geneticProfileId, 'GeneticProfileId', T(org.cbioportal.utils.security.AccessLevel).READ)") - @RequestMapping(value = "/genetic-profiles/{geneticProfileId}/geneset-genetic-data/fetch", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE, - produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "Fetch gene set \"genetic data\" items (gene set scores) by profile Id, gene set ids and sample ids") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(array = @ArraySchema(schema = @Schema(implementation = GenesetMolecularData.class)))) - public ResponseEntity> fetchGeneticDataItems( - @Parameter(required = true, description = "Genetic profile ID, e.g. gbm_tcga_gsva_scores") - @PathVariable String geneticProfileId, - @Parameter(required = true, description = "Search criteria to return the values for a given set of samples and gene set items. " - + "genesetIds: The list of identifiers for the gene sets of interest, e.g. HINATA_NFKB_MATRIX. " - + "Use one of these if you want to specify a subset of samples:" - + "(1) sampleListId: Identifier of pre-defined sample list with samples to query, e.g. brca_tcga_all " - + "or (2) sampleIds: custom list of samples or patients to query, e.g. TCGA-BH-A1EO-01, TCGA-AR-A1AR-01") - @RequestBody GenesetDataFilterCriteria genesetDataFilterCriteria) throws MolecularProfileNotFoundException, SampleListNotFoundException { - - if (genesetDataFilterCriteria.getSampleListId() != null && genesetDataFilterCriteria.getSampleListId().trim().length() > 0) { - return new ResponseEntity<>( - genesetDataService.fetchGenesetData(geneticProfileId, genesetDataFilterCriteria.getSampleListId(), - genesetDataFilterCriteria.getGenesetIds()), HttpStatus.OK); - } else { - return new ResponseEntity<>( - genesetDataService.fetchGenesetData(geneticProfileId, genesetDataFilterCriteria.getSampleIds(), - genesetDataFilterCriteria.getGenesetIds()), HttpStatus.OK); - } - } - -} diff --git a/src/main/java/org/cbioportal/web/GenesetHierarchyController.java b/src/main/java/org/cbioportal/web/GenesetHierarchyController.java deleted file mode 100644 index 1efd7019138..00000000000 --- a/src/main/java/org/cbioportal/web/GenesetHierarchyController.java +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright (c) 2016 The Hyve B.V. - * This code is licensed under the GNU Affero General Public License (AGPL), - * version 3, or (at your option) any later version. - */ - -/* - * This file is part of cBioPortal. - * - * cBioPortal is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . -*/ - -package org.cbioportal.web; - -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.media.ArraySchema; -import io.swagger.v3.oas.annotations.media.Content; -import io.swagger.v3.oas.annotations.media.Schema; -import io.swagger.v3.oas.annotations.responses.ApiResponse; -import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.validation.constraints.Max; -import jakarta.validation.constraints.Min; -import org.cbioportal.model.GenesetHierarchyInfo; -import org.cbioportal.service.GenesetHierarchyService; -import org.cbioportal.service.exception.MolecularProfileNotFoundException; -import org.cbioportal.service.exception.SampleListNotFoundException; -import org.cbioportal.web.config.annotation.InternalApi; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.RequestBody; -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.bind.annotation.RestController; - -import java.util.List; - -@InternalApi -@RestController() -@RequestMapping("/api") -@Validated -@Tag(name = "Gene Set Hierarchy", description = " ") -public class GenesetHierarchyController { - - @Autowired - private GenesetHierarchyService genesetHierarchyService; - - @PreAuthorize("hasPermission(#geneticProfileId, 'GeneticProfileId', T(org.cbioportal.utils.security.AccessLevel).READ)") - @RequestMapping(value = "/geneset-hierarchy/fetch", method = RequestMethod.POST, - consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "Get gene set hierarchical organization information. I.e. how different gene sets relate to other gene sets, in a hierarchy") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(array = @ArraySchema(schema = @Schema(implementation = GenesetHierarchyInfo.class)))) - public ResponseEntity> fetchGenesetHierarchyInfo( - @Parameter(required = true, description = "Genetic Profile ID e.g. gbm_tcga_gsva_scores. The final hierarchy " - + " will only include gene sets scored in the specified profile.") - @RequestParam String geneticProfileId, - @Parameter(description = "Percentile (for score calculation). Which percentile to use when determining the *representative score*") - @Max(100) - @Min(1) - @RequestParam(defaultValue = "75") Integer percentile, - @Parameter(description = "Gene set score threshold (for absolute score value). Filters out gene sets where the GSVA(like) *representative score* is under this threshold.") - @Max(1) - @Min(0) - @RequestParam(defaultValue = "0.4") Double scoreThreshold, - @Parameter(description = "p-value threshold. Filters out gene sets for which the score p-value is higher than this threshold.") - @Max(1) - @Min(0) - @RequestParam(defaultValue = "0.05") Double pvalueThreshold, - @Parameter(description = "Identifier of pre-defined sample list with samples to query, e.g. brca_tcga_all") - @RequestParam(required = false) String sampleListId, - @Parameter(description = "Fill this one if you want to specify a subset of samples:" - + " sampleIds: custom list of samples or patients to query, e.g. [\"TCGA-A1-A0SD-01\", \"TCGA-A1-A0SE-01\"]") - @RequestBody(required = false) List sampleIds) - throws MolecularProfileNotFoundException, SampleListNotFoundException { - - if (sampleListId != null && sampleListId.trim().length() > 0) { - return new ResponseEntity<>( - genesetHierarchyService.fetchGenesetHierarchyInfo(geneticProfileId, percentile, scoreThreshold, pvalueThreshold, sampleListId), - HttpStatus.OK); - } else if (sampleIds != null && sampleIds.size() > 0){ - return new ResponseEntity<>( - genesetHierarchyService.fetchGenesetHierarchyInfo(geneticProfileId, percentile, scoreThreshold, pvalueThreshold, sampleIds), - HttpStatus.OK); - } else { - return new ResponseEntity<>( - genesetHierarchyService.fetchGenesetHierarchyInfo(geneticProfileId, percentile, scoreThreshold, pvalueThreshold), - HttpStatus.OK); - } - - } -} diff --git a/src/main/java/org/cbioportal/web/IndexPageController.java b/src/main/java/org/cbioportal/web/IndexPageController.java deleted file mode 100644 index 2bd3b95b66f..00000000000 --- a/src/main/java/org/cbioportal/web/IndexPageController.java +++ /dev/null @@ -1,135 +0,0 @@ -package org.cbioportal.web; - -import com.fasterxml.jackson.core.JsonGenerator; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.JsonSerializer; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.SerializerProvider; -import com.fasterxml.jackson.databind.module.SimpleModule; -import jakarta.servlet.http.HttpServletRequest; -import org.cbioportal.service.FrontendPropertiesService; -import org.cbioportal.service.util.MskWholeSlideViewerTokenGenerator; -import org.cbioportal.web.util.HttpRequestUtils; -import org.json.simple.JSONObject; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.http.ResponseEntity; -import org.springframework.security.core.Authentication; -import org.springframework.stereotype.Controller; -import org.springframework.ui.Model; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestMapping; - -import java.io.IOException; -import java.util.HashMap; -import java.util.Map; - -import static org.cbioportal.service.FrontendPropertiesServiceImpl.FrontendProperty; - -@Controller -public class IndexPageController { - private static final Logger log = LoggerFactory.getLogger(IndexPageController.class); - - @Autowired - private FrontendPropertiesService frontendPropertiesService; - - @Autowired - private HttpRequestUtils requestUtils; - - @Value("${authenticate}") - private String[] authenticate; - - @Value("${saml.idp.metadata.entityid:not_defined_in_portalproperties}") - private String samlIdpEntityId; - - @Value("${msk.whole.slide.viewer.secret.key:}") - private String wholeSlideViewerKey; - - private final ObjectMapper mapper = new ObjectMapper(); - - private Map getFrontendProperties(HttpServletRequest request, Authentication authentication) { - String baseUrl = requestUtils.getBaseUrl(request); - Map properties = new HashMap<>(); - - Map originalProperties = frontendPropertiesService.getFrontendProperties(); - - for (Map.Entry entry : originalProperties.entrySet()) { - String value = entry.getValue(); - if (value!=null && (value.equalsIgnoreCase("true") || value.equalsIgnoreCase("false"))) { - properties.put(entry.getKey(), Boolean.valueOf(value)); - } else { - properties.put(entry.getKey(), value); - } - } - properties.put("base_url", baseUrl); - properties.put("user_email_address", authentication != null ? authentication.getName(): "anonymousUser"); - // TODO: Support skin.user_display_name - properties.put("user_display_name", authentication != null ? authentication.getName(): "anonymousUser"); - // Set MSK slide viewer token at runtime - properties.put("mskWholeSlideViewerToken", getMskWholeSlideViewerToken(wholeSlideViewerKey, authentication)); - return properties; - } - - private String getMskWholeSlideViewerToken(String secretKey, Authentication authentication) { - // this token is for the msk portal - // the token is generated based on users' timestamp to let the slide viewer know whether the token is expired and then decide whether to allow the user to login the viewer - // every time when we refresh the page or goto the new page, a new token should be generated - if (secretKey != null) - secretKey = secretKey.trim(); - String timeStamp = String.valueOf(System.currentTimeMillis()); - - if (authentication != null && authentication.isAuthenticated() && secretKey != null && - !secretKey.isEmpty()) { - return "{ \"token\":\"" + MskWholeSlideViewerTokenGenerator.generateTokenByHmacSHA256( - authentication.getName(), secretKey, timeStamp) + "\", \"time\":\"" + timeStamp + - "\"}"; - } else { - return null; - } - } - - @RequestMapping({"/", "/index", "/index.html", "/study/summary", "/results" }) - public String showIndexPage(HttpServletRequest request, Authentication authentication, Model model) - throws JsonProcessingException { - - SimpleModule simpleModule = new SimpleModule(); - simpleModule.addSerializer(String.class, new CustomFrontendPropertiesSerializer()); - mapper.registerModule(simpleModule); - - String baseUrl = requestUtils.getBaseUrl(request); - JSONObject postData = requestUtils.getPostData(request); - - model.addAttribute("propertiesJson", mapper.writeValueAsString(getFrontendProperties(request, authentication))); - model.addAttribute("frontendUrl", frontendPropertiesService.getFrontendProperty(FrontendProperty.frontendUrl)); - model.addAttribute("baseUrl", baseUrl); - model.addAttribute("contextPath", request.getContextPath()); - model.addAttribute("appVersion", frontendPropertiesService.getFrontendProperty(FrontendProperty.app_version)); - model.addAttribute("postData", postData.isEmpty() ? "undefined" : postData); - - return "index"; - } - - @GetMapping("/config_service") - public ResponseEntity getConfigService(HttpServletRequest request, Authentication authentication) { - return ResponseEntity.ok(getFrontendProperties(request, authentication)); - } - - public FrontendPropertiesService getFrontendPropertiesService() { - return frontendPropertiesService; - } - - public static class CustomFrontendPropertiesSerializer extends JsonSerializer { - @Override - public void serialize(String value, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException { - if ("true".equalsIgnoreCase(value) || "false".equalsIgnoreCase((value))) { - jsonGenerator.writeBoolean("true".equalsIgnoreCase(value)); - } else if (value != null) { - jsonGenerator.writeString(value); - } else { - jsonGenerator.writeNull(); - } - } - } -} diff --git a/src/main/java/org/cbioportal/web/InfoController.java b/src/main/java/org/cbioportal/web/InfoController.java deleted file mode 100644 index 59e9352ca5b..00000000000 --- a/src/main/java/org/cbioportal/web/InfoController.java +++ /dev/null @@ -1,82 +0,0 @@ -package org.cbioportal.web; - -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.media.Content; -import io.swagger.v3.oas.annotations.media.Schema; -import io.swagger.v3.oas.annotations.responses.ApiResponse; -import io.swagger.v3.oas.annotations.tags.Tag; -import org.cbioportal.model.Info; -import org.cbioportal.web.config.PublicApiTags; -import org.cbioportal.web.config.annotation.PublicApi; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestMethod; -import org.springframework.web.bind.annotation.RestController; - -@PublicApi -@RestController -@Validated -@Tag(name = PublicApiTags.INFO, description = " ") -public class InfoController { - - @Value("${portal.version}") - private String portalVersion; - - @Value("${db.version}") - private String dbVersion; - - @Value("${git.branch:not set}") - private String gitBranch; - - @Value("${git.commit.id.full:not set}") - private String gitCommitId; - - @Value("${git.commit.id.abbrev:not set}") - private String gitCommitIdAbbrev; - - @Value("${git.commit.id.describe:not set}") - private String gitCommitIdDescribe; - - @Value("${git.commit.id.describe-short:not set}") - private String gitCommitIdDescribeShort; - - @Value("${git.commit.message.full:not set}") - private String gitCommitMessageFull; - - @Value("${git.commit.message.short:not set}") - private String gitCommitMessageShort; - - @Value("${git.commit.user.email:not set}") - private String gitCommitMessageUserEmail; - - @Value("${git.commit.user.name:not set}") - private String gitCommitMessageUserName; - - @Value("${git.dirty:not set}") - private String gitDirty; - - @RequestMapping(value = "/api/info", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "Get information about the running instance") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(schema = @Schema(implementation = Info.class))) - public ResponseEntity getInfo() { - - Info info = new Info(); - info.setPortalVersion(portalVersion); - info.setDbVersion(dbVersion); - info.setGitBranch(gitBranch); - info.setGitCommitId(gitCommitId); - info.setGitCommitIdDescribe(gitCommitIdDescribe); - info.setGitCommitIdDescribeShort(gitCommitIdDescribeShort); - info.setGitCommitMessageShort(gitCommitMessageShort); - info.setGitCommitMessageFull(gitCommitMessageFull); - info.setGitCommitMessageUserEmail(gitCommitMessageUserEmail); - info.setGitCommitMessageUserName(gitCommitMessageUserName); - info.isGitDirty(Boolean.valueOf(gitDirty)); - return new ResponseEntity<>(info, HttpStatus.OK); - } -} diff --git a/src/main/java/org/cbioportal/web/LegacyApiController.java b/src/main/java/org/cbioportal/web/LegacyApiController.java deleted file mode 100644 index 6e696460b59..00000000000 --- a/src/main/java/org/cbioportal/web/LegacyApiController.java +++ /dev/null @@ -1,57 +0,0 @@ -package org.cbioportal.web; - - -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.node.ObjectNode; -import jakarta.servlet.http.HttpServletRequest; -import org.springframework.core.io.ClassPathResource; -import org.springframework.core.io.Resource; -import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; -import org.springframework.lang.Nullable; -import org.springframework.util.FileCopyUtils; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RestController; - -import java.io.IOException; -import java.io.InputStreamReader; -import java.nio.charset.StandardCharsets; -import java.util.Objects; - -@RestController -public class LegacyApiController { - - private static final String JSON_HOST_KEY = "host"; - private static final String REQUEST_HEADER_HOST = "Host"; - private static final String LEGACY_API_FILE_JSON = "legacy-api.json"; - - @Nullable private String legacySwaggerJson; - - @GetMapping(value = "/api/v2/api-docs", produces = MediaType.APPLICATION_JSON_VALUE) - public ResponseEntity getLegacyAPI(HttpServletRequest request) throws IOException { - - if(Objects.isNull(legacySwaggerJson)) { - legacySwaggerJson = getLegacySwagger(request.getHeader(REQUEST_HEADER_HOST)); - } - return ResponseEntity.ok(legacySwaggerJson); - } - - private String getLegacySwagger(String host) throws IOException { - Resource resource = new ClassPathResource(LEGACY_API_FILE_JSON); - InputStreamReader reader = new InputStreamReader(resource.getInputStream(), StandardCharsets.UTF_8); - - String jsonData = FileCopyUtils.copyToString(reader); - - ObjectMapper objectMapper = new ObjectMapper(); - JsonNode jsonNode = objectMapper.readTree(jsonData); - - // Update key host - if(jsonNode.has(JSON_HOST_KEY)) { - ((ObjectNode) jsonNode).put(JSON_HOST_KEY, host); - } - - // Convert back to string - return objectMapper.writeValueAsString(jsonNode); - } -} diff --git a/src/main/java/org/cbioportal/web/LoginPageController.java b/src/main/java/org/cbioportal/web/LoginPageController.java deleted file mode 100644 index cadcdb10838..00000000000 --- a/src/main/java/org/cbioportal/web/LoginPageController.java +++ /dev/null @@ -1,82 +0,0 @@ -package org.cbioportal.web; - -import jakarta.servlet.http.HttpServletRequest; -import org.cbioportal.service.FrontendPropertiesService; -import org.cbioportal.service.FrontendPropertiesServiceImpl; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; -import org.springframework.http.MediaType; -import org.springframework.security.core.Authentication; -import org.springframework.security.oauth2.client.registration.ClientRegistration; -import org.springframework.security.oauth2.client.registration.InMemoryClientRegistrationRepository; -import org.springframework.security.oauth2.client.web.OAuth2AuthorizationRequestRedirectFilter; -import org.springframework.stereotype.Controller; -import org.springframework.ui.Model; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PostMapping; - -import java.util.HashMap; -import java.util.Map; -import java.util.Objects; - -@Controller -@ConditionalOnExpression("{'oauth2','saml','optional_oauth2'}.contains('${authenticate}')") -public class LoginPageController { - private static final Logger log = LoggerFactory.getLogger(LoginPageController.class); - - @Autowired - private FrontendPropertiesService frontendPropertiesService; - - @Autowired(required = false) - private InMemoryClientRegistrationRepository clientRegistrationRepository; - - @Value("${authenticate}") - private String authenticate; - - @Value("${security.force_redirect_on_one_idp:true}") - private boolean forceRedirectOnOneIdentityProvider; - - @PostMapping(value = "/login", produces = MediaType.APPLICATION_JSON_VALUE) - public String showLoginPagePost(HttpServletRequest request, Authentication authentication, Model model) { - populateModel(request, model, new HashMap<>()); - return "login"; - } - - @GetMapping(value = "/login", produces = MediaType.APPLICATION_JSON_VALUE) - public String showLoginPage(HttpServletRequest request, Authentication authentication, Model model) { - Map oauth2AuthenticationUrls = getOauth2AuthenticationUrls(); - boolean logoutFailure = request.getParameterMap().containsKey("logout_failure"); - if(oauth2AuthenticationUrls.size() == 1 && !logoutFailure && this.forceRedirectOnOneIdentityProvider) { - log.debug("Redirecting to Identity Provider"); - return "redirect:" + oauth2AuthenticationUrls.values().iterator().next(); - } - populateModel(request, model, oauth2AuthenticationUrls); - - return "login"; - } - private void populateModel(HttpServletRequest request, Model model, Map oauth2AuthenticationUrls) { - model.addAttribute("oauth_urls", oauth2AuthenticationUrls); - model.addAttribute("skin_title", frontendPropertiesService.getFrontendProperty(FrontendPropertiesServiceImpl.FrontendProperty.skin_title)); - model.addAttribute("skin_authorization_message", frontendPropertiesService.getFrontendProperty(FrontendPropertiesServiceImpl.FrontendProperty.skin_authorization_message)); - model.addAttribute("skin_login_contact_html", frontendPropertiesService.getFrontendProperty(FrontendPropertiesServiceImpl.FrontendProperty.skin_login_contact_html)); - model.addAttribute("skin_login_saml_registration_html", frontendPropertiesService.getFrontendProperty(FrontendPropertiesServiceImpl.FrontendProperty.skin_login_saml_registration_html)); - model.addAttribute("saml_idp_metadata_entityid", frontendPropertiesService.getFrontendProperty(FrontendPropertiesServiceImpl.FrontendProperty.saml_idp_metadata_entityid)); - model.addAttribute("logout_success", request.getParameterMap().containsKey("logout_success")); - model.addAttribute("login_error", request.getParameterMap().containsKey("logout_failure")); - model.addAttribute("show_saml", frontendPropertiesService.getFrontendProperty(FrontendPropertiesServiceImpl.FrontendProperty.authenticationMethod).equals("saml")); - } - - private Map getOauth2AuthenticationUrls() { - Map oauth2AuthenticationUrls = new HashMap<>(); - if(!Objects.isNull(clientRegistrationRepository) && !Objects.equals(authenticate, "saml")) { - for (ClientRegistration clientRegistration : clientRegistrationRepository) { - oauth2AuthenticationUrls.put(clientRegistration.getRegistrationId(), - OAuth2AuthorizationRequestRedirectFilter.DEFAULT_AUTHORIZATION_REQUEST_BASE_URI + "/" + clientRegistration.getRegistrationId()); - } - } - return oauth2AuthenticationUrls; - } -} diff --git a/src/main/java/org/cbioportal/web/MatchMinerController.java b/src/main/java/org/cbioportal/web/MatchMinerController.java deleted file mode 100644 index 3b1ad15f694..00000000000 --- a/src/main/java/org/cbioportal/web/MatchMinerController.java +++ /dev/null @@ -1,80 +0,0 @@ -package org.cbioportal.web; - -import io.swagger.v3.oas.annotations.media.Content; -import io.swagger.v3.oas.annotations.media.Schema; -import io.swagger.v3.oas.annotations.responses.ApiResponse; -import jakarta.servlet.http.HttpServletRequest; -import org.apache.commons.codec.binary.Base64; -import org.json.simple.JSONObject; -import org.json.simple.parser.JSONParser; -import org.json.simple.parser.ParseException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.http.HttpEntity; -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpMethod; -import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; -import org.springframework.http.converter.StringHttpMessageConverter; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; -import org.springframework.web.client.RestTemplate; - -import java.net.URI; -import java.net.URISyntaxException; -import java.nio.charset.Charset; -import java.nio.charset.StandardCharsets; - -@RestController -@RequestMapping("/api/matchminer") -public class MatchMinerController { - - private static final Logger LOG = LoggerFactory.getLogger( MatchMinerController.class); - - @Value("${matchminer.url:}") - private String url; - - @Value("${matchminer.token:}") - private String token; - - @RequestMapping(value = "/api/**", produces = "application/json") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(schema = @Schema(implementation = Object.class))) - public ResponseEntity proxy(@RequestBody(required = false) JSONObject body, HttpMethod method, HttpServletRequest request) { - try { - // TODO when reimplemeting different dispatcherservlets with different context roots - // reset this to 'String requestPathInfo = request.getPathInfo();' - String requestPathInfo = request.getPathInfo() == null? request.getServletPath() : request.getPathInfo(); - String path = requestPathInfo.replace("/matchminer", ""); - URI uri = new URI(this.url + path); - - HttpHeaders httpHeaders = new HttpHeaders(); - String contentType = request.getHeader("Content-Type"); - if (contentType != null) { - httpHeaders.setContentType(MediaType.valueOf(contentType)); - } - if (!this.token.equals("")) { - String auth = this.token + ":"; - byte[] encodedAuth = Base64.encodeBase64(auth.getBytes(Charset.forName("US-ASCII"))); - String authHeader = "Basic " + new String(encodedAuth); - httpHeaders.set("Authorization", authHeader); - } - - RestTemplate restTemplate = new RestTemplate(); - restTemplate.getMessageConverters().add(0, new StringHttpMessageConverter(StandardCharsets.UTF_8)); - ResponseEntity responseEntity = restTemplate.exchange(uri, method, new HttpEntity<>(body, httpHeaders), String.class); - // The response might be a json object or a json array, so I return Object to cover both cases. - Object response = new JSONParser().parse(responseEntity.getBody()); - return new ResponseEntity<>(response, responseEntity.getStatusCode()); - } catch (URISyntaxException e) { - LOG.error("Error occurred", e); - return new ResponseEntity<>(HttpStatus.BAD_REQUEST); - } catch (ParseException e) { - LOG.error("Error occurred", e); - return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR); - } - } -} \ No newline at end of file diff --git a/src/main/java/org/cbioportal/web/MolecularDataController.java b/src/main/java/org/cbioportal/web/MolecularDataController.java deleted file mode 100644 index 69ed27f83bf..00000000000 --- a/src/main/java/org/cbioportal/web/MolecularDataController.java +++ /dev/null @@ -1,186 +0,0 @@ -package org.cbioportal.web; - -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.media.ArraySchema; -import io.swagger.v3.oas.annotations.media.Content; -import io.swagger.v3.oas.annotations.media.Schema; -import io.swagger.v3.oas.annotations.responses.ApiResponse; -import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.validation.Valid; -import org.apache.commons.lang3.math.NumberUtils; -import org.cbioportal.model.GeneMolecularData; -import org.cbioportal.model.NumericGeneMolecularData; -import org.cbioportal.service.MolecularDataService; -import org.cbioportal.service.exception.MolecularProfileNotFoundException; -import org.cbioportal.web.config.PublicApiTags; -import org.cbioportal.web.config.annotation.PublicApi; -import org.cbioportal.web.parameter.HeaderKeyConstants; -import org.cbioportal.web.parameter.MolecularDataFilter; -import org.cbioportal.web.parameter.MolecularDataMultipleStudyFilter; -import org.cbioportal.web.parameter.Projection; -import org.cbioportal.web.parameter.SampleMolecularIdentifier; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RequestAttribute; -import org.springframework.web.bind.annotation.RequestBody; -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.bind.annotation.RestController; - -import java.math.BigDecimal; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.List; - -@PublicApi -@RestController() -@RequestMapping("/api") -@Validated -@Tag(name = PublicApiTags.MOLECULAR_DATA, description = " ") -public class MolecularDataController { - - @Autowired - private MolecularDataService molecularDataService; - - @PreAuthorize("hasPermission(#molecularProfileId, 'MolecularProfileId', T(org.cbioportal.utils.security.AccessLevel).READ)") - @RequestMapping(value = "/molecular-profiles/{molecularProfileId}/molecular-data", method = RequestMethod.GET, - produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "Get all molecular data in a molecular profile") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(array = @ArraySchema(schema = @Schema(implementation = NumericGeneMolecularData.class)))) - public ResponseEntity> getAllMolecularDataInMolecularProfile( - @Parameter(required = true, description = "Molecular Profile ID e.g. acc_tcga_rna_seq_v2_mrna") - @PathVariable String molecularProfileId, - @Parameter(required = true, description = "Sample List ID e.g. acc_tcga_all") - @RequestParam String sampleListId, - @Parameter(required = true, description = "Entrez Gene ID e.g. 1") - @RequestParam Integer entrezGeneId, - @Parameter(description = "Level of detail of the response") - @RequestParam(defaultValue = "SUMMARY") Projection projection) throws MolecularProfileNotFoundException { - - List result = filterNonNumberMolecularData(molecularDataService.getMolecularData( - molecularProfileId, sampleListId, Arrays.asList(entrezGeneId), projection.name())); - - if (projection == Projection.META) { - HttpHeaders responseHeaders = new HttpHeaders(); - responseHeaders.add(HeaderKeyConstants.TOTAL_COUNT, String.valueOf(result.size())); - return new ResponseEntity<>(responseHeaders, HttpStatus.OK); - } else { - return new ResponseEntity<>(result, HttpStatus.OK); - } - } - - @PreAuthorize("hasPermission(#molecularProfileId, 'MolecularProfileId', T(org.cbioportal.utils.security.AccessLevel).READ)") - @RequestMapping(value = "/molecular-profiles/{molecularProfileId}/molecular-data/fetch", - method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE, - produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "Fetch molecular data in a molecular profile") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(array = @ArraySchema(schema = @Schema(implementation = NumericGeneMolecularData.class)))) - public ResponseEntity> fetchAllMolecularDataInMolecularProfile( - @Parameter(required = true, description = "Molecular Profile ID e.g. acc_tcga_rna_seq_v2_mrna") - @PathVariable String molecularProfileId, - @Parameter(required = true, description = "List of Sample IDs/Sample List ID and Entrez Gene IDs") - @Valid @RequestBody MolecularDataFilter molecularDataFilter, - @Parameter(description = "Level of detail of the response") - @RequestParam(defaultValue = "SUMMARY") Projection projection) throws MolecularProfileNotFoundException { - - List result; - if (molecularDataFilter.getSampleListId() != null) { - result = filterNonNumberMolecularData(molecularDataService.getMolecularData(molecularProfileId, - molecularDataFilter.getSampleListId(), molecularDataFilter.getEntrezGeneIds(), projection.name())); - } else { - result = filterNonNumberMolecularData(molecularDataService.fetchMolecularData(molecularProfileId, - molecularDataFilter.getSampleIds(), molecularDataFilter.getEntrezGeneIds(), projection.name())); - } - - if (projection == Projection.META) { - HttpHeaders responseHeaders = new HttpHeaders(); - responseHeaders.add(HeaderKeyConstants.TOTAL_COUNT, String.valueOf(result.size())); - return new ResponseEntity<>(responseHeaders, HttpStatus.OK); - } else { - return new ResponseEntity<>(result, HttpStatus.OK); - } - } - - @PreAuthorize("hasPermission(#involvedCancerStudies, 'Collection', T(org.cbioportal.utils.security.AccessLevel).READ)") - @RequestMapping(value = "/molecular-data/fetch", method = RequestMethod.POST, - consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "Fetch molecular data") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(array = @ArraySchema(schema = @Schema(implementation = NumericGeneMolecularData.class)))) - public ResponseEntity> fetchMolecularDataInMultipleMolecularProfiles( - @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface - @RequestAttribute(required = false, value = "involvedCancerStudies") Collection involvedCancerStudies, - @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface. this attribute is needed for the @PreAuthorize tag above. - @Valid @RequestAttribute(required = false, value = "interceptedMolecularDataMultipleStudyFilter") MolecularDataMultipleStudyFilter interceptedMolecularDataMultipleStudyFilter, - @Parameter(required = true, description = "List of Molecular Profile ID and Sample ID pairs or List of Molecular" + - "Profile IDs and Entrez Gene IDs") - @Valid @RequestBody(required = false) MolecularDataMultipleStudyFilter molecularDataMultipleStudyFilter, - @Parameter(description = "Level of detail of the response") - @RequestParam(defaultValue = "SUMMARY") Projection projection) { - - List result; - if (interceptedMolecularDataMultipleStudyFilter.getMolecularProfileIds() != null) { - result = filterNonNumberMolecularData(molecularDataService.getMolecularDataInMultipleMolecularProfiles( - interceptedMolecularDataMultipleStudyFilter.getMolecularProfileIds(), null, - interceptedMolecularDataMultipleStudyFilter.getEntrezGeneIds(), projection.name())); - } else { - - List molecularProfileIds = new ArrayList<>(); - List sampleIds = new ArrayList<>(); - extractMolecularProfileAndSampleIds(interceptedMolecularDataMultipleStudyFilter, molecularProfileIds, sampleIds); - result = filterNonNumberMolecularData(molecularDataService.getMolecularDataInMultipleMolecularProfiles(molecularProfileIds, - sampleIds, interceptedMolecularDataMultipleStudyFilter.getEntrezGeneIds(), projection.name())); - } - - if (projection == Projection.META) { - HttpHeaders responseHeaders = new HttpHeaders(); - responseHeaders.add(HeaderKeyConstants.TOTAL_COUNT, String.valueOf(result.size())); - return new ResponseEntity<>(responseHeaders, HttpStatus.OK); - } else { - return new ResponseEntity<>(result, HttpStatus.OK); - } - } - - private void extractMolecularProfileAndSampleIds(MolecularDataMultipleStudyFilter molecularDataMultipleStudyFilter, - List molecularProfileIds, List sampleIds) { - - for (SampleMolecularIdentifier sampleMolecularIdentifier : - molecularDataMultipleStudyFilter.getSampleMolecularIdentifiers()) { - - molecularProfileIds.add(sampleMolecularIdentifier.getMolecularProfileId()); - sampleIds.add(sampleMolecularIdentifier.getSampleId()); - } - } - - private List filterNonNumberMolecularData(List geneMolecularDataList) { - - List result = new ArrayList<>(); - geneMolecularDataList.forEach(g -> { - String value = g.getValue(); - if (NumberUtils.isNumber(value)) { - NumericGeneMolecularData data = new NumericGeneMolecularData(); - data.setEntrezGeneId(g.getEntrezGeneId()); - data.setGene(g.getGene()); - data.setMolecularProfileId(g.getMolecularProfileId()); - data.setPatientId(g.getPatientId()); - data.setSampleId(g.getSampleId()); - data.setStudyId(g.getStudyId()); - data.setValue(new BigDecimal(g.getValue())); - result.add(data); - } - }); - - return result; - } -} diff --git a/src/main/java/org/cbioportal/web/MolecularProfileController.java b/src/main/java/org/cbioportal/web/MolecularProfileController.java deleted file mode 100644 index ee887e13eff..00000000000 --- a/src/main/java/org/cbioportal/web/MolecularProfileController.java +++ /dev/null @@ -1,175 +0,0 @@ -package org.cbioportal.web; - -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.media.ArraySchema; -import io.swagger.v3.oas.annotations.media.Content; -import io.swagger.v3.oas.annotations.media.Schema; -import io.swagger.v3.oas.annotations.responses.ApiResponse; -import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.validation.Valid; -import jakarta.validation.constraints.Max; -import jakarta.validation.constraints.Min; -import org.cbioportal.model.MolecularProfile; -import org.cbioportal.model.meta.BaseMeta; -import org.cbioportal.service.MolecularProfileService; -import org.cbioportal.service.exception.MolecularProfileNotFoundException; -import org.cbioportal.service.exception.StudyNotFoundException; -import org.cbioportal.web.config.PublicApiTags; -import org.cbioportal.web.config.annotation.PublicApi; -import org.cbioportal.web.parameter.Direction; -import org.cbioportal.web.parameter.HeaderKeyConstants; -import org.cbioportal.web.parameter.MolecularProfileFilter; -import org.cbioportal.web.parameter.PagingConstants; -import org.cbioportal.web.parameter.Projection; -import org.cbioportal.web.parameter.sort.MolecularProfileSortBy; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RequestAttribute; -import org.springframework.web.bind.annotation.RequestBody; -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.bind.annotation.RestController; - -import java.util.Collection; -import java.util.List; - -@PublicApi -@RestController() -@RequestMapping("/api") -@Validated -@Tag(name = PublicApiTags.MOLECULAR_PROFILES, description = " ") -public class MolecularProfileController { - - @Autowired - private MolecularProfileService molecularProfileService; - - @RequestMapping(value = "/molecular-profiles", method = RequestMethod.GET, - produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "Get all molecular profiles") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(array = @ArraySchema(schema = @Schema(implementation = MolecularProfile.class)))) - public ResponseEntity> getAllMolecularProfiles( - @Parameter(description = "Level of detail of the response") - @RequestParam(defaultValue = "SUMMARY") Projection projection, - @Parameter(description = "Page size of the result list") - @Max(PagingConstants.MAX_PAGE_SIZE) - @Min(PagingConstants.MIN_PAGE_SIZE) - @RequestParam(defaultValue = PagingConstants.DEFAULT_PAGE_SIZE) Integer pageSize, - @Parameter(description = "Page number of the result list") - @Min(PagingConstants.MIN_PAGE_NUMBER) - @RequestParam(defaultValue = PagingConstants.DEFAULT_PAGE_NUMBER) Integer pageNumber, - @Parameter(description = "Name of the property that the result list is sorted by") - @RequestParam(required = false) MolecularProfileSortBy sortBy, - @Parameter(description = "Direction of the sort") - @RequestParam(defaultValue = "ASC") Direction direction) { - - if (projection == Projection.META) { - HttpHeaders responseHeaders = new HttpHeaders(); - responseHeaders.add(HeaderKeyConstants.TOTAL_COUNT, molecularProfileService.getMetaMolecularProfiles() - .getTotalCount().toString()); - return new ResponseEntity<>(responseHeaders, HttpStatus.OK); - } else { - return new ResponseEntity<>( - molecularProfileService.getAllMolecularProfiles(projection.name(), pageSize, pageNumber, - sortBy == null ? null : sortBy.getOriginalValue(), direction.name()), HttpStatus.OK); - } - } - - @PreAuthorize("hasPermission(#molecularProfileId, 'MolecularProfileId', T(org.cbioportal.utils.security.AccessLevel).READ)") - @RequestMapping(value = "/molecular-profiles/{molecularProfileId}", method = RequestMethod.GET, - produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "Get molecular profile") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(schema = @Schema(implementation = MolecularProfile.class))) - public ResponseEntity getMolecularProfile( - @Parameter(required = true, description = "Molecular Profile ID e.g. acc_tcga_mutations") - @PathVariable String molecularProfileId) throws MolecularProfileNotFoundException { - - return new ResponseEntity<>(molecularProfileService.getMolecularProfile(molecularProfileId), HttpStatus.OK); - } - - @PreAuthorize("hasPermission(#studyId, 'CancerStudyId', T(org.cbioportal.utils.security.AccessLevel).READ)") - @RequestMapping(value = "/studies/{studyId}/molecular-profiles", method = RequestMethod.GET, - produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "Get all molecular profiles in a study") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(array = @ArraySchema(schema = @Schema(implementation = MolecularProfile.class)))) - public ResponseEntity> getAllMolecularProfilesInStudy( - @Parameter(required = true, description = "Study ID e.g. acc_tcga") - @PathVariable String studyId, - @Parameter(description = "Level of detail of the response") - @RequestParam(defaultValue = "SUMMARY") Projection projection, - @Parameter(description = "Page size of the result list") - @Max(PagingConstants.MAX_PAGE_SIZE) - @Min(PagingConstants.MIN_PAGE_SIZE) - @RequestParam(defaultValue = PagingConstants.DEFAULT_PAGE_SIZE) Integer pageSize, - @Parameter(description = "Page number of the result list") - @Min(PagingConstants.MIN_PAGE_NUMBER) - @RequestParam(defaultValue = PagingConstants.DEFAULT_PAGE_NUMBER) Integer pageNumber, - @Parameter(description = "Name of the property that the result list is sorted by") - @RequestParam(required = false) MolecularProfileSortBy sortBy, - @Parameter(description = "Direction of the sort") - @RequestParam(defaultValue = "ASC") Direction direction) throws StudyNotFoundException { - - if (projection == Projection.META) { - HttpHeaders responseHeaders = new HttpHeaders(); - responseHeaders.add(HeaderKeyConstants.TOTAL_COUNT, molecularProfileService - .getMetaMolecularProfilesInStudy(studyId).getTotalCount().toString()); - return new ResponseEntity<>(responseHeaders, HttpStatus.OK); - } else { - return new ResponseEntity<>( - molecularProfileService.getAllMolecularProfilesInStudy(studyId, projection.name(), pageSize, pageNumber, - sortBy == null ? null : sortBy.getOriginalValue(), direction.name()), HttpStatus.OK); - } - } - - @PreAuthorize("hasPermission(#involvedCancerStudies, 'Collection', T(org.cbioportal.utils.security.AccessLevel).READ)") - @RequestMapping(value = "/molecular-profiles/fetch", method = RequestMethod.POST, - consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "Fetch molecular profiles") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(array = @ArraySchema(schema = @Schema(implementation = MolecularProfile.class)))) - public ResponseEntity> fetchMolecularProfiles( - @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface - @RequestAttribute(required = false, value = "involvedCancerStudies") Collection involvedCancerStudies, - @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface. this attribute is needed for the @PreAuthorize tag above. - @Valid @RequestAttribute(required = false, value = "interceptedMolecularProfileFilter") MolecularProfileFilter interceptedMolecularProfileFilter, - @Parameter(required = true, description = "List of Molecular Profile IDs or List of Study IDs") - @Valid @RequestBody(required = false) MolecularProfileFilter molecularProfileFilter, - @Parameter(description = "Level of detail of the response") - @RequestParam(defaultValue = "SUMMARY") Projection projection) { - - if (projection == Projection.META) { - HttpHeaders responseHeaders = new HttpHeaders(); - BaseMeta baseMeta; - - if (interceptedMolecularProfileFilter.getStudyIds() != null) { - baseMeta = molecularProfileService.getMetaMolecularProfilesInStudies( - interceptedMolecularProfileFilter.getStudyIds()); - } else { - baseMeta = molecularProfileService.getMetaMolecularProfiles( - interceptedMolecularProfileFilter.getMolecularProfileIds()); - } - responseHeaders.add(HeaderKeyConstants.TOTAL_COUNT, baseMeta.getTotalCount().toString()); - return new ResponseEntity<>(responseHeaders, HttpStatus.OK); - } else { - List molecularProfiles; - if (interceptedMolecularProfileFilter.getStudyIds() != null) { - molecularProfiles = molecularProfileService.getMolecularProfilesInStudies( - interceptedMolecularProfileFilter.getStudyIds(), projection.name()); - } else { - molecularProfiles = molecularProfileService.getMolecularProfiles( - interceptedMolecularProfileFilter.getMolecularProfileIds(), projection.name()); - } - return new ResponseEntity<>(molecularProfiles, HttpStatus.OK); - } - } -} diff --git a/src/main/java/org/cbioportal/web/MrnaPercentileController.java b/src/main/java/org/cbioportal/web/MrnaPercentileController.java deleted file mode 100644 index 816da438e08..00000000000 --- a/src/main/java/org/cbioportal/web/MrnaPercentileController.java +++ /dev/null @@ -1,61 +0,0 @@ -package org.cbioportal.web; - -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.media.ArraySchema; -import io.swagger.v3.oas.annotations.media.Content; -import io.swagger.v3.oas.annotations.media.Schema; -import io.swagger.v3.oas.annotations.responses.ApiResponse; -import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.validation.constraints.Size; -import org.cbioportal.model.MrnaPercentile; -import org.cbioportal.service.MrnaPercentileService; -import org.cbioportal.service.exception.MolecularProfileNotFoundException; -import org.cbioportal.web.config.annotation.InternalApi; -import org.cbioportal.web.parameter.PagingConstants; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RequestBody; -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.bind.annotation.RestController; - -import java.util.List; - -@InternalApi -@RestController() -@RequestMapping("/api") -@Validated -@Tag(name = "mRNA Percentile", description = " ") -public class MrnaPercentileController { - - @Autowired - private MrnaPercentileService mrnaPercentileService; - - @PreAuthorize("hasPermission(#molecularProfileId, 'MolecularProfileId', T(org.cbioportal.utils.security.AccessLevel).READ)") - @RequestMapping(value = "/molecular-profiles/{molecularProfileId}/mrna-percentile/fetch", - method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE, - produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "Get mRNA expression percentiles for list of genes for a sample") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(array = @ArraySchema(schema = @Schema(implementation = MrnaPercentile.class)))) - public ResponseEntity> fetchMrnaPercentile( - @Parameter(required = true, description = "Molecular Profile ID e.g. acc_tcga_rna_seq_v2_mrna") - @PathVariable String molecularProfileId, - @Parameter(required = true, description = "Sample ID e.g. TCGA-OR-A5J2-01") - @RequestParam String sampleId, - @Parameter(required = true, description = "List of Entrez Gene IDs") - @Size(min = 1, max = PagingConstants.MAX_PAGE_SIZE) - @RequestBody List entrezGeneIds) - throws MolecularProfileNotFoundException { - - return new ResponseEntity<>( - mrnaPercentileService.fetchMrnaPercentile(molecularProfileId, sampleId, entrezGeneIds), HttpStatus.OK); - } -} diff --git a/src/main/java/org/cbioportal/web/MskEntityTranslationController.java b/src/main/java/org/cbioportal/web/MskEntityTranslationController.java deleted file mode 100644 index a9152a02716..00000000000 --- a/src/main/java/org/cbioportal/web/MskEntityTranslationController.java +++ /dev/null @@ -1,266 +0,0 @@ -/* - * Copyright (c) 2017-2021 Memorial Sloan-Kettering Cancer Center. - * - * This library is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS - * FOR A PARTICULAR PURPOSE. The software and documentation provided hereunder - * is on an "as is" basis, and Memorial Sloan-Kettering Cancer Center has no - * obligations to provide maintenance, support, updates, enhancements or - * modifications. In no event shall Memorial Sloan-Kettering Cancer Center be - * liable to any party for direct, indirect, special, incidental or - * consequential damages, including lost profits, arising out of the use of this - * software and its documentation, even if Memorial Sloan-Kettering Cancer - * Center has been advised of the possibility of such damage. - */ - -/* - * This file is part of cBioPortal. - * - * cBioPortal is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . -*/ - -package org.cbioportal.web; - -import org.cbioportal.service.PatientService; -import org.cbioportal.service.SampleService; -import org.cbioportal.service.exception.PatientNotFoundException; -import org.cbioportal.service.exception.SampleNotFoundException; -import org.cbioportal.service.exception.StudyNotFoundException; -import org.cbioportal.utils.config.annotation.ConditionalOnProperty; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.context.annotation.PropertySource; -import org.springframework.context.annotation.PropertySources; -import org.springframework.http.HttpEntity; -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpMethod; -import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; -import org.springframework.stereotype.Controller; -import org.springframework.ui.ModelMap; -import org.springframework.util.LinkedMultiValueMap; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestMethod; -import org.springframework.web.bind.annotation.ResponseBody; -import org.springframework.web.client.RestTemplate; -import org.springframework.web.servlet.ModelAndView; - -import java.util.HashMap; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * This class checks for the existence and location of entities {samples, patients} - * based on MSK entity stable id patterns, such as DMP (Department of Molecular Pathology) - * sample identifiers. - */ -@Controller -@PropertySources({ - @PropertySource(value="classpath:application.properties", ignoreResourceNotFound=true), - @PropertySource(value="file:///${PORTAL_HOME}/application.properties", ignoreResourceNotFound=true) -}) -@ConditionalOnProperty(name = "msk_entity_translation_enabled", havingValue = "true") -public class MskEntityTranslationController { - - @Autowired - private SampleService sampleService; - - @Autowired - private PatientService patientService; - - private String sampleViewURL; - @Value("${sample_view.url}") - public void setSampleViewURL(String property) { this.sampleViewURL = property; } - - private String patientViewURL; - @Value("${patient_view.url}") - public void setPatientViewURL(String property) { this.patientViewURL = property; } - - @Value("${mpath.decryption_url:}") - private String mpathDecryptionUrl; - - @Value("${mpath.token:}") - private String mpathToken; - - private static final String ARCHER = "mskarcher"; - private static final String RAINDANCE = "mskraindance"; - private static final String IMPACT = "mskimpact"; - - private static Pattern dmpSampleIDPattern = initDMPSampleIDPattern(); - private static Pattern initDMPSampleIDPattern() { - return Pattern.compile("(P-[0-9]{7,})-T[0-9]{2,}-(\\w{3,})"); - } - - @RequestMapping( - value={"/api-legacy/epic/sample/{sampleID}"}, - method=RequestMethod.GET - ) - public ModelAndView redirectIMPACTSampleForEpic(@PathVariable String sampleID, ModelMap model) { - String decryptedId = getDecryptedId(sampleID); - return new ModelAndView(getRedirectURL(decryptedId), model); - } - - @RequestMapping( - value={"/api-legacy/cis/{sampleID}", "/api-legacy/darwin/{sampleID}"}, - method=RequestMethod.GET - ) - public ModelAndView redirectIMPACT(@PathVariable String sampleID, ModelMap model) { - return new ModelAndView(getRedirectURL(sampleID), model); - } - - @RequestMapping( - value="/api-legacy/crdb/{sampleID}", - method=RequestMethod.GET - ) - public ModelAndView redirectCRDB(@PathVariable String sampleID, ModelMap model) { - return new ModelAndView(getRedirectURL(sampleID), model); - } - - // Decryption only works for Sample IDs (not patient IDs) - // Ids not found will not be decrypted -- will propagate down and result in 400 Error Request - // Should be avoided upstream in Epic by using /exists endpoint to check firstd - private String getDecryptedId(String id) { - String requestUrl = mpathDecryptionUrl + id; - RestTemplate restTemplate = new RestTemplate(); - LinkedMultiValueMap map = new LinkedMultiValueMap<>(); - HttpHeaders headers = new HttpHeaders(); - headers.setContentType(MediaType.APPLICATION_JSON); - headers.add("x-api-key", mpathToken); - HttpEntity> requestEntity = new HttpEntity<>(map, headers); - ResponseEntity responseEntity = restTemplate.exchange(requestUrl, HttpMethod.GET, requestEntity, Object.class); - String decryptedId = id; - if (responseEntity.getStatusCode().value() == 200 && responseEntity.getBody() != null) { - decryptedId = responseEntity.getBody().toString(); - } - return decryptedId; - } - - private String getRedirectURL(String sampleID) { - String redirectURL = "redirect:" + sampleViewURL; - String studyID = getCancerStudy(sampleID); - if (!checkIfSampleExistsInStudy(studyID, sampleID)) { - if (studyID.equals(ARCHER)) { - String patientID = getPatientID(sampleID); - if (patientID != null) { - return getPatientRedirectURL(patientID); - } - // else patientID is null - } - // else sample doesn't exist in this study and it is not archer - } - // this will not work for invalid sample ids and sample - // ids that do not belong to the expected study, - // but in practice that should not happen because users are meant to - // call /{cis|darwin|crdb}/{sampleID}/exists before displaying any URL - redirectURL = redirectURL.replace("STUDY_ID", studyID); - redirectURL = redirectURL.replace("SAMPLE_ID", sampleID); - return redirectURL; - } - - private String getPatientRedirectURL(String patientID) { - String redirectURL = "redirect:" + patientViewURL; - redirectURL = redirectURL.replace("STUDY_ID", IMPACT); - redirectURL = redirectURL.replace("CASE_ID", patientID); - return redirectURL; - } - - @RequestMapping( - value={"/api-legacy/cis/{sampleID}/exists", "/api-legacy/darwin/{sampleID}/exists", "/api-legacy/crdb/{sampleID}/exists"}, - method=RequestMethod.GET - ) - public @ResponseBody HashMap exists(@PathVariable String sampleID, ModelMap model) { - HashMap result = new HashMap(); - result.put("exists", new Boolean(checkIfSampleExists(sampleID))); - return result; - } - - @RequestMapping( - value={"/api-legacy/epic/{sampleID}/exists"}, - method=RequestMethod.GET - ) - public @ResponseBody HashMap existsForEpic(@PathVariable String sampleID, ModelMap model) { - HashMap result = new HashMap(); - String decryptedId = getDecryptedId(sampleID); - result.put("exists", new Boolean(checkIfSampleExists(decryptedId))); - return result; - } - - private boolean checkIfPatientExists(String studyID, String sampleID) { - try { - String patientID = getPatientID(sampleID); - if (patientID != null) { - patientService.getPatientInStudy(studyID, patientID); - } else { // could not parse out patient id - return false; - } - } catch (PatientNotFoundException e) { - return false; - } catch (StudyNotFoundException e) { - return false; - } - return true; - } - - private boolean checkIfSampleExists(String sampleID) { - String studyID = getCancerStudy(sampleID); - // note if we map to a study that they do not have permission to view - // then an AccessDeniedException will be thrown that we cannot catch here - if (!checkIfSampleExistsInStudy(studyID, sampleID)) { - if (studyID.equals(ARCHER)) { - // check if patient exists in mskimpact - return checkIfPatientExists(IMPACT, sampleID); - } else { - return false; - } - } - return true; - } - - private boolean checkIfSampleExistsInStudy(String studyID, String sampleID) { - try { - sampleService.getSampleInStudy(studyID, sampleID); - } catch (SampleNotFoundException e) { - return false; - } catch (StudyNotFoundException e) { - return false; - } - // note if we map to a study that they do not have permission to view - // then an AccessDeniedException will be thrown that we cannot catch here - return true; - } - - private String getPatientID(String sampleID) { - Matcher matcher = dmpSampleIDPattern.matcher(sampleID); - if (matcher.find()) { - return matcher.group(1); - } - return null; - } - - private String getCancerStudy(String sampleID) { - // TODO: create tech stack to get study id given sample id - Matcher matcher = dmpSampleIDPattern.matcher(sampleID); - if (matcher.find()) { - String sampleIDSuffix = matcher.group(2); - if (sampleIDSuffix.contains("TS") || sampleIDSuffix.contains("TB")) { - return RAINDANCE; - } - else if (sampleIDSuffix.contains("AS") || sampleIDSuffix.contains("AH")) { - return ARCHER; - } - } - return IMPACT; - } -} diff --git a/src/main/java/org/cbioportal/web/MutationController.java b/src/main/java/org/cbioportal/web/MutationController.java deleted file mode 100644 index 7c72d36db41..00000000000 --- a/src/main/java/org/cbioportal/web/MutationController.java +++ /dev/null @@ -1,232 +0,0 @@ -package org.cbioportal.web; - -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.media.ArraySchema; -import io.swagger.v3.oas.annotations.media.Content; -import io.swagger.v3.oas.annotations.media.Schema; -import io.swagger.v3.oas.annotations.responses.ApiResponse; -import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.validation.Valid; -import jakarta.validation.constraints.Max; -import jakarta.validation.constraints.Min; -import org.cbioportal.model.Mutation; -import org.cbioportal.model.meta.MutationMeta; -import org.cbioportal.service.MutationService; -import org.cbioportal.service.exception.MolecularProfileNotFoundException; -import org.cbioportal.web.config.PublicApiTags; -import org.cbioportal.web.config.annotation.PublicApi; -import org.cbioportal.web.parameter.Direction; -import org.cbioportal.web.parameter.HeaderKeyConstants; -import org.cbioportal.web.parameter.MutationFilter; -import org.cbioportal.web.parameter.MutationMultipleStudyFilter; -import org.cbioportal.web.parameter.PagingConstants; -import org.cbioportal.web.parameter.Projection; -import org.cbioportal.web.parameter.SampleMolecularIdentifier; -import org.cbioportal.web.parameter.sort.MutationSortBy; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RequestAttribute; -import org.springframework.web.bind.annotation.RequestBody; -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.bind.annotation.RestController; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.List; - -@PublicApi -@RestController() -@RequestMapping("/api") -@Validated -@Tag(name = PublicApiTags.MUTATIONS, description = " ") -public class MutationController { - - @Autowired - private MutationService mutationService; - - @PreAuthorize("hasPermission(#molecularProfileId, 'MolecularProfileId', T(org.cbioportal.utils.security.AccessLevel).READ)") - @RequestMapping(value = "/molecular-profiles/{molecularProfileId}/mutations", method = RequestMethod.GET, - produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "Get mutations in a molecular profile by Sample List ID") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(array = @ArraySchema(schema = @Schema(implementation = Mutation.class)))) - public ResponseEntity> getMutationsInMolecularProfileBySampleListId( - @Parameter(required = true, description = "Molecular Profile ID e.g. acc_tcga_mutations") - @PathVariable String molecularProfileId, - @Parameter(required = true, description = "Sample List ID e.g. acc_tcga_all") - @RequestParam String sampleListId, - @Parameter(description = "Entrez Gene ID") - @RequestParam(required = false) Integer entrezGeneId, - @Parameter(description = "Level of detail of the response") - @RequestParam(defaultValue = "SUMMARY") Projection projection, - @Parameter(description = "Page size of the result list") - @Max(PagingConstants.MAX_PAGE_SIZE) - @Min(PagingConstants.MIN_PAGE_SIZE) - @RequestParam(defaultValue = PagingConstants.DEFAULT_PAGE_SIZE) Integer pageSize, - @Parameter(description = "Page number of the result list") - @Min(PagingConstants.MIN_PAGE_NUMBER) - @RequestParam(defaultValue = PagingConstants.DEFAULT_PAGE_NUMBER) Integer pageNumber, - @Parameter(description = "Name of the property that the result list is sorted by") - @RequestParam(required = false) MutationSortBy sortBy, - @Parameter(description = "Direction of the sort") - @RequestParam(defaultValue = "ASC") Direction direction) throws MolecularProfileNotFoundException { - - if (projection == Projection.META) { - HttpHeaders responseHeaders = new HttpHeaders(); - MutationMeta mutationMeta = mutationService.getMetaMutationsInMolecularProfileBySampleListId( - molecularProfileId, sampleListId, entrezGeneId == null ? null : Arrays.asList(entrezGeneId)); - responseHeaders.add(HeaderKeyConstants.TOTAL_COUNT, mutationMeta.getTotalCount().toString()); - responseHeaders.add(HeaderKeyConstants.SAMPLE_COUNT, mutationMeta.getSampleCount().toString()); - return new ResponseEntity<>(responseHeaders, HttpStatus.OK); - } else { - return new ResponseEntity<>( - mutationService.getMutationsInMolecularProfileBySampleListId(molecularProfileId, sampleListId, - entrezGeneId == null ? null : Arrays.asList(entrezGeneId), false, projection.name(), pageSize, - pageNumber, sortBy == null ? null : sortBy.getOriginalValue(), direction.name()), HttpStatus.OK); - } - } - - @PreAuthorize("hasPermission(#molecularProfileId, 'MolecularProfileId', T(org.cbioportal.utils.security.AccessLevel).READ)") - @RequestMapping(value = "/molecular-profiles/{molecularProfileId}/mutations/fetch", method = RequestMethod.POST, - consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "Fetch mutations in a molecular profile") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(array = @ArraySchema(schema = @Schema(implementation = Mutation.class)))) - public ResponseEntity> fetchMutationsInMolecularProfile( - @Parameter(required = true, description = "Molecular Profile ID e.g. acc_tcga_mutations") - @PathVariable String molecularProfileId, - @Parameter(required = true, description = "List of Sample IDs/Sample List ID and Entrez Gene IDs") - @Valid @RequestBody MutationFilter mutationFilter, - @Parameter(description = "Level of detail of the response") - @RequestParam(defaultValue = "SUMMARY") Projection projection, - @Parameter(description = "Page size of the result list") - @Max(PagingConstants.MAX_PAGE_SIZE) - @Min(PagingConstants.MIN_PAGE_SIZE) - @RequestParam(defaultValue = PagingConstants.DEFAULT_PAGE_SIZE) Integer pageSize, - @Parameter(description = "Page number of the result list") - @Min(PagingConstants.MIN_PAGE_NUMBER) - @RequestParam(defaultValue = PagingConstants.DEFAULT_PAGE_NUMBER) Integer pageNumber, - @Parameter(description = "Name of the property that the result list is sorted by") - @RequestParam(required = false) MutationSortBy sortBy, - @Parameter(description = "Direction of the sort") - @RequestParam(defaultValue = "ASC") Direction direction) throws MolecularProfileNotFoundException { - - if (projection == Projection.META) { - HttpHeaders responseHeaders = new HttpHeaders(); - MutationMeta mutationMeta; - - if (mutationFilter.getSampleListId() != null) { - mutationMeta = mutationService.getMetaMutationsInMolecularProfileBySampleListId(molecularProfileId, - mutationFilter.getSampleListId(), mutationFilter.getEntrezGeneIds()); - } else { - mutationMeta = mutationService.fetchMetaMutationsInMolecularProfile(molecularProfileId, - mutationFilter.getSampleIds(), mutationFilter.getEntrezGeneIds()); - } - responseHeaders.add(HeaderKeyConstants.TOTAL_COUNT, mutationMeta.getTotalCount().toString()); - responseHeaders.add(HeaderKeyConstants.SAMPLE_COUNT, mutationMeta.getSampleCount().toString()); - return new ResponseEntity<>(responseHeaders, HttpStatus.OK); - } else { - List mutations; - if (mutationFilter.getSampleListId() != null) { - mutations = mutationService.getMutationsInMolecularProfileBySampleListId(molecularProfileId, - mutationFilter.getSampleListId(), mutationFilter.getEntrezGeneIds(), false, projection.name(), - pageSize, pageNumber, sortBy == null ? null : sortBy.getOriginalValue(), direction.name()); - } else { - mutations = mutationService.fetchMutationsInMolecularProfile(molecularProfileId, - mutationFilter.getSampleIds(), mutationFilter.getEntrezGeneIds(), false, projection.name(), pageSize, - pageNumber, sortBy == null ? null : sortBy.getOriginalValue(), direction.name()); - } - - return new ResponseEntity<>(mutations, HttpStatus.OK); - } - } - - @PreAuthorize("hasPermission(#involvedCancerStudies, 'Collection', T(org.cbioportal.utils.security.AccessLevel).READ)") - @RequestMapping(value = "/mutations/fetch", method = RequestMethod.POST, - consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "Fetch mutations in multiple molecular profiles by sample IDs") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(array = @ArraySchema(schema = @Schema(implementation = Mutation.class)))) - public ResponseEntity> fetchMutationsInMultipleMolecularProfiles( - @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface - @RequestAttribute(required = false, value = "involvedCancerStudies") Collection involvedCancerStudies, - @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface. this attribute is needed for the @PreAuthorize tag above. - @Valid @RequestAttribute(required = false, value = "interceptedMutationMultipleStudyFilter") MutationMultipleStudyFilter interceptedMutationMultipleStudyFilter, - @Parameter(required = true, description = "List of Molecular Profile IDs or List of Molecular Profile ID / Sample ID pairs," + - " and List of Entrez Gene IDs") - @Valid @RequestBody(required = false) MutationMultipleStudyFilter mutationMultipleStudyFilter, - @Parameter(description = "Level of detail of the response") - @RequestParam(defaultValue = "SUMMARY") Projection projection, - @Parameter(description = "Page size of the result list") - @Max(PagingConstants.MAX_PAGE_SIZE) - @Min(PagingConstants.MIN_PAGE_SIZE) - @RequestParam(defaultValue = PagingConstants.DEFAULT_PAGE_SIZE) Integer pageSize, - @Parameter(description = "Page number of the result list") - @Min(PagingConstants.MIN_PAGE_NUMBER) - @RequestParam(defaultValue = PagingConstants.DEFAULT_PAGE_NUMBER) Integer pageNumber, - @Parameter(description = "Name of the property that the result list is sorted by") - @RequestParam(required = false) MutationSortBy sortBy, - @Parameter(description = "Direction of the sort") - @RequestParam(defaultValue = "ASC") Direction direction) { - - if (projection == Projection.META) { - HttpHeaders responseHeaders = new HttpHeaders(); - MutationMeta mutationMeta; - - if (interceptedMutationMultipleStudyFilter.getMolecularProfileIds() != null) { - mutationMeta = mutationService.getMetaMutationsInMultipleMolecularProfiles( - interceptedMutationMultipleStudyFilter.getMolecularProfileIds(), null, - interceptedMutationMultipleStudyFilter.getEntrezGeneIds()); - } else { - - List molecularProfileIds = new ArrayList<>(); - List sampleIds = new ArrayList<>(); - extractMolecularProfileAndSampleIds(interceptedMutationMultipleStudyFilter, molecularProfileIds, sampleIds); - mutationMeta = mutationService.getMetaMutationsInMultipleMolecularProfiles(molecularProfileIds, - sampleIds, interceptedMutationMultipleStudyFilter.getEntrezGeneIds()); - } - responseHeaders.add(HeaderKeyConstants.TOTAL_COUNT, mutationMeta.getTotalCount().toString()); - responseHeaders.add(HeaderKeyConstants.SAMPLE_COUNT, mutationMeta.getSampleCount().toString()); - return new ResponseEntity<>(responseHeaders, HttpStatus.OK); - } else { - List mutations; - if (interceptedMutationMultipleStudyFilter.getMolecularProfileIds() != null) { - mutations = mutationService.getMutationsInMultipleMolecularProfiles( - interceptedMutationMultipleStudyFilter.getMolecularProfileIds(), null, - interceptedMutationMultipleStudyFilter.getEntrezGeneIds(), projection.name(), pageSize, pageNumber, - sortBy == null ? null : sortBy.getOriginalValue(), direction.name()); - } else { - - List molecularProfileIds = new ArrayList<>(); - List sampleIds = new ArrayList<>(); - extractMolecularProfileAndSampleIds(interceptedMutationMultipleStudyFilter, molecularProfileIds, sampleIds); - mutations = mutationService.getMutationsInMultipleMolecularProfiles(molecularProfileIds, - sampleIds, interceptedMutationMultipleStudyFilter.getEntrezGeneIds(), projection.name(), pageSize, - pageNumber, sortBy == null ? null : sortBy.getOriginalValue(), direction.name()); - } - - return new ResponseEntity<>(mutations, HttpStatus.OK); - } - } - - private void extractMolecularProfileAndSampleIds(MutationMultipleStudyFilter mutationMultipleStudyFilter, - List molecularProfileIds, List sampleIds) { - - for (SampleMolecularIdentifier sampleMolecularIdentifier : - mutationMultipleStudyFilter.getSampleMolecularIdentifiers()) { - - molecularProfileIds.add(sampleMolecularIdentifier.getMolecularProfileId()); - sampleIds.add(sampleMolecularIdentifier.getSampleId()); - } - } -} diff --git a/src/main/java/org/cbioportal/web/MutationCountController.java b/src/main/java/org/cbioportal/web/MutationCountController.java deleted file mode 100644 index 7450c7fe131..00000000000 --- a/src/main/java/org/cbioportal/web/MutationCountController.java +++ /dev/null @@ -1,65 +0,0 @@ -package org.cbioportal.web; - -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.media.ArraySchema; -import io.swagger.v3.oas.annotations.media.Content; -import io.swagger.v3.oas.annotations.media.Schema; -import io.swagger.v3.oas.annotations.responses.ApiResponse; -import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.validation.constraints.Size; -import org.cbioportal.model.MutationCountByPosition; -import org.cbioportal.service.MutationService; -import org.cbioportal.web.config.InternalApiTags; -import org.cbioportal.web.config.annotation.InternalApi; -import org.cbioportal.web.parameter.MutationPositionIdentifier; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestMethod; -import org.springframework.web.bind.annotation.RestController; - -import java.util.ArrayList; -import java.util.List; - -@InternalApi -@RestController -@Validated -@Tag(name = InternalApiTags.MUTATIONS_COUNT, description = " ") -public class MutationCountController { - - public static final int MUTATION_MAX_PAGE_SIZE = 10000000; - - @Autowired - private MutationService mutationService; - - @RequestMapping(value = "/api/mutation-counts-by-position/fetch", method = RequestMethod.POST, - consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "Fetch mutation counts in all studies by gene and position") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(array = @ArraySchema(schema = @Schema(implementation = MutationCountByPosition.class)))) - public ResponseEntity> fetchMutationCountsByPosition( - @Parameter(required = true, description = "List of Mutation Position Identifiers") - @Size(min = 1, max = MUTATION_MAX_PAGE_SIZE) - @RequestBody List mutationPositionIdentifiers) { - - List entrezGeneIds = new ArrayList<>(); - List proteinPosStarts = new ArrayList<>(); - List proteinPosEnds = new ArrayList<>(); - for (MutationPositionIdentifier mutationPositionIdentifier : mutationPositionIdentifiers) { - - entrezGeneIds.add(mutationPositionIdentifier.getEntrezGeneId()); - proteinPosStarts.add(mutationPositionIdentifier.getProteinPosStart()); - proteinPosEnds.add(mutationPositionIdentifier.getProteinPosEnd()); - } - - return new ResponseEntity<>(mutationService.fetchMutationCountsByPosition(entrezGeneIds, proteinPosStarts, - proteinPosEnds), HttpStatus.OK); - } - - -} diff --git a/src/main/java/org/cbioportal/web/MutationSpectrumController.java b/src/main/java/org/cbioportal/web/MutationSpectrumController.java deleted file mode 100644 index c6c8a28b718..00000000000 --- a/src/main/java/org/cbioportal/web/MutationSpectrumController.java +++ /dev/null @@ -1,64 +0,0 @@ -package org.cbioportal.web; - -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.media.ArraySchema; -import io.swagger.v3.oas.annotations.media.Content; -import io.swagger.v3.oas.annotations.media.Schema; -import io.swagger.v3.oas.annotations.responses.ApiResponse; -import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.validation.Valid; -import org.cbioportal.model.MutationSpectrum; -import org.cbioportal.service.MutationSpectrumService; -import org.cbioportal.service.exception.MolecularProfileNotFoundException; -import org.cbioportal.web.config.annotation.InternalApi; -import org.cbioportal.web.parameter.MutationSpectrumFilter; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestMethod; -import org.springframework.web.bind.annotation.RestController; - -import java.util.List; - -@InternalApi -@RestController() -@RequestMapping("/api") -@Validated -@Tag(name = "Mutation Spectrums", description = " ") -public class MutationSpectrumController { - - @Autowired - private MutationSpectrumService mutationSpectrumService; - - @PreAuthorize("hasPermission(#molecularProfileId, 'MolecularProfileId', T(org.cbioportal.utils.security.AccessLevel).READ)") - @RequestMapping(value = "/molecular-profiles/{molecularProfileId}/mutation-spectrums/fetch", - method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE, - produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "Fetch mutation spectrums in a molecular profile") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(array = @ArraySchema(schema = @Schema(implementation = MutationSpectrum.class)))) - public ResponseEntity> fetchMutationSpectrums( - @Parameter(required = true, description = "Molecular Profile ID e.g. acc_tcga_mutations") - @PathVariable String molecularProfileId, - @Parameter(required = true, description = "List of Sample IDs/Sample List ID") - @Valid @RequestBody MutationSpectrumFilter mutationSpectrumFilter) throws MolecularProfileNotFoundException { - - List mutationSpectrums; - if (mutationSpectrumFilter.getSampleListId() != null) { - mutationSpectrums = mutationSpectrumService.getMutationSpectrums(molecularProfileId, - mutationSpectrumFilter.getSampleListId()); - } else { - mutationSpectrums = mutationSpectrumService.fetchMutationSpectrums(molecularProfileId, - mutationSpectrumFilter.getSampleIds()); - } - - return new ResponseEntity<>(mutationSpectrums, HttpStatus.OK); - } -} diff --git a/src/main/java/org/cbioportal/web/OAuth2DataAccessTokenController.java b/src/main/java/org/cbioportal/web/OAuth2DataAccessTokenController.java deleted file mode 100644 index 94df3e2f7da..00000000000 --- a/src/main/java/org/cbioportal/web/OAuth2DataAccessTokenController.java +++ /dev/null @@ -1,195 +0,0 @@ -/* - * Copyright (c) 2020 The Hyve B.V. - * - * This library is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS - * FOR A PARTICULAR PURPOSE. The software and documentation provided hereunder - * is on an "as is" basis, and Memorial Sloan-Kettering Cancer Center has no - * obligations to provide maintenance, support, updates, enhancements or - * modifications. In no event shall Memorial Sloan-Kettering Cancer Center be - * liable to any party for direct, indirect, special, incidental or - * consequential damages, including lost profits, arising out of the use of this - * software and its documentation, even if Memorial Sloan-Kettering Cancer - * Center has been advised of the possibility of such damage. - */ - -/* - * This file is part of cBioPortal. - * - * cBioPortal is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . -*/ - -package org.cbioportal.web; - -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.media.ArraySchema; -import io.swagger.v3.oas.annotations.media.Content; -import io.swagger.v3.oas.annotations.media.Schema; -import io.swagger.v3.oas.annotations.responses.ApiResponse; -import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.annotation.PostConstruct; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; -import org.apache.commons.lang3.StringUtils; -import org.cbioportal.model.DataAccessToken; -import org.cbioportal.service.DataAccessTokenService; -import org.cbioportal.service.exception.DataAccessTokenNoUserIdentityException; -import org.cbioportal.service.exception.DataAccessTokenProhibitedUserException; -import org.cbioportal.utils.config.annotation.ConditionalOnProperty; -import org.cbioportal.web.config.annotation.InternalApi; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; -import org.springframework.security.core.Authentication; -import org.springframework.security.core.authority.SimpleGrantedAuthority; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestMethod; -import org.springframework.web.bind.annotation.RestController; -import org.springframework.web.client.HttpClientErrorException; - -import java.io.IOException; -import java.io.UnsupportedEncodingException; -import java.net.URLEncoder; -import java.nio.charset.StandardCharsets; -import java.util.List; - -@InternalApi -@Validated -@Tag(name = "Data Access Tokens", description = " ") -@RestController -@ConditionalOnProperty(name = "dat.method", havingValue = "oauth2") -public class OAuth2DataAccessTokenController { - - @Value("${dat.oauth2.userAuthorizationUri}") - private String userAuthorizationUri; - - @Value("${dat.oauth2.redirectUri}") - private String redirectUri; - - @Value("${dat.oauth2.clientId}") - private String clientId; - - @Value("${dat.filter_user_role:}") // default is empty string - private String userRoleToAccessToken; - - @Autowired - private DataAccessTokenService tokenService; - private String authorizationUrl; - private String fileName = "cbioportal_data_access_token.txt"; - - @PostConstruct - public void postConstruct() throws UnsupportedEncodingException { - - String scopeEncoded = URLEncoder.encode("openid offline_access", StandardCharsets.UTF_8.toString()); - String clientIdEncoded = URLEncoder.encode(clientId, StandardCharsets.UTF_8.toString()); - String redirUriEncode = URLEncoder.encode(redirectUri, StandardCharsets.UTF_8.toString()); - - authorizationUrl = String.format("%s?response_type=%s&scope=%s&client_id=%s&redirect_uri=%s", userAuthorizationUri, "code", scopeEncoded, clientIdEncoded, redirUriEncode); - } - - // This is the entrypoint for the cBioPortal frontend to download a single user token. - // Redirect the browser to the authorizationUrl. - @RequestMapping(method = RequestMethod.GET, value = "/api/data-access-token") - @Operation(description = "Create a new data access token") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(schema = @Schema(implementation = String.class))) - public ResponseEntity downloadDataAccessToken(Authentication authentication, - HttpServletRequest request, HttpServletResponse response) throws IOException { - - isUserAuthorizedToAccess(authentication); - - // redirect to authentication endpoint - HttpHeaders headers = new HttpHeaders(); - headers.add("Location", authorizationUrl); - return new ResponseEntity<>(headers, HttpStatus.FOUND); - - } - - // retrieve and trigger download OAuth2 offline token - @RequestMapping(method = RequestMethod.GET, value = "/api/data-access-token/oauth2") - @Parameter(hidden = true) - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(schema = @Schema(implementation = String.class))) - public ResponseEntity downloadOAuth2DataAccessToken(HttpServletRequest request, HttpServletResponse response) throws IOException { - - String accessCode = request.getParameter("code"); - DataAccessToken offlineToken = tokenService.createDataAccessToken(accessCode); - - if (offlineToken == null) { - throw new DataAccessTokenProhibitedUserException(); - } - - // add header to trigger download of the token by the browser - response.setHeader("Content-Disposition", "attachment; filename=" + fileName); - - return new ResponseEntity<>(offlineToken.toString(), HttpStatus.OK); - } - - @RequestMapping(method = RequestMethod.POST, value = "/api/data-access-tokens", produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "Get all data access tokens") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(schema = @Schema(implementation = DataAccessToken.class))) - public ResponseEntity createDataAccessToken(Authentication authentication) throws HttpClientErrorException { - throw new UnsupportedOperationException("this endpoint is does not apply to OAuth2 data access token method."); - } - - @RequestMapping(method = RequestMethod.GET, value = "/api/data-access-tokens") - @Operation(description = "Retrieve all data access tokens") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(array = @ArraySchema(schema = @Schema(implementation = DataAccessToken.class)))) - public ResponseEntity> getAllDataAccessTokens(HttpServletRequest request, - Authentication authentication) { - throw new UnsupportedOperationException("this endpoint is does not apply to OAuth2 data access token method."); - } - - @RequestMapping(method = RequestMethod.GET, value = "/api/data-access-tokens/{token}") - @Operation(description = "Retrieve an existing data access token") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(schema = @Schema(implementation = DataAccessToken.class))) - public ResponseEntity getDataAccessToken( - @Parameter(required = true, description = "token") @PathVariable String token) { - throw new UnsupportedOperationException("this endpoint is does not apply to OAuth2 data access token method."); - - } - - @RequestMapping(method = RequestMethod.DELETE, value = "/api/data-access-tokens") - @Operation(description = "Delete all data access tokens") - public void revokeAllDataAccessTokens(Authentication authentication) { - throw new UnsupportedOperationException("this endpoint is does not apply to OAuth2 data access token method."); - } - - @RequestMapping(method = RequestMethod.DELETE, value = "/api/data-access-tokens/{token}") - @Operation(description = "Delete a data access token") - public void revokeDataAccessToken(@Parameter(required = true, description = "token") @PathVariable String token) { - throw new UnsupportedOperationException("this endpoint is does not apply to OAuth2 data access token method."); - } - - private void isUserAuthorizedToAccess(Authentication authentication) { - if (authentication == null || !authentication.isAuthenticated()) { - throw new DataAccessTokenNoUserIdentityException(); - } - - if(StringUtils.isNotEmpty(userRoleToAccessToken) && - !authentication.getAuthorities().contains(new SimpleGrantedAuthority(userRoleToAccessToken))) { - throw new DataAccessTokenProhibitedUserException(); - } - } - -} diff --git a/src/main/java/org/cbioportal/web/PatientController.java b/src/main/java/org/cbioportal/web/PatientController.java deleted file mode 100644 index 7c082509bc9..00000000000 --- a/src/main/java/org/cbioportal/web/PatientController.java +++ /dev/null @@ -1,187 +0,0 @@ -package org.cbioportal.web; - -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.media.ArraySchema; -import io.swagger.v3.oas.annotations.media.Content; -import io.swagger.v3.oas.annotations.media.Schema; -import io.swagger.v3.oas.annotations.responses.ApiResponse; -import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.validation.Valid; -import jakarta.validation.constraints.Max; -import jakarta.validation.constraints.Min; -import org.cbioportal.model.Patient; -import org.cbioportal.service.PatientService; -import org.cbioportal.service.exception.PatientNotFoundException; -import org.cbioportal.service.exception.StudyNotFoundException; -import org.cbioportal.web.config.PublicApiTags; -import org.cbioportal.web.config.annotation.PublicApi; -import org.cbioportal.web.parameter.Direction; -import org.cbioportal.web.parameter.HeaderKeyConstants; -import org.cbioportal.web.parameter.PagingConstants; -import org.cbioportal.web.parameter.PatientFilter; -import org.cbioportal.web.parameter.PatientIdentifier; -import org.cbioportal.web.parameter.Projection; -import org.cbioportal.web.parameter.sort.PatientSortBy; -import org.cbioportal.web.util.UniqueKeyExtractor; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RequestAttribute; -import org.springframework.web.bind.annotation.RequestBody; -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.bind.annotation.RestController; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; - -@PublicApi -@RestController() -@RequestMapping("/api") -@Validated -@Tag(name = PublicApiTags.PATIENTS, description = " ") -public class PatientController { - - @Autowired - private PatientService patientService; - - @RequestMapping(value = "/patients", method = RequestMethod.GET, - produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "Get all patients") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(array = @ArraySchema(schema = @Schema(implementation = Patient.class)))) - public ResponseEntity> getAllPatients( - @Parameter(description = "Search keyword that applies to ID of the patients") - @RequestParam(required = false) String keyword, - @Parameter(description = "Level of detail of the response") - @RequestParam(defaultValue = "SUMMARY") Projection projection, - @Parameter(description = "Page size of the result list") - @Max(PagingConstants.MAX_PAGE_SIZE) - @Min(PagingConstants.MIN_PAGE_SIZE) - @RequestParam(defaultValue = PagingConstants.DEFAULT_PAGE_SIZE) Integer pageSize, - @Parameter(description = "Page number of the result list") - @Min(PagingConstants.MIN_PAGE_NUMBER) - @RequestParam(defaultValue = PagingConstants.DEFAULT_PAGE_NUMBER) Integer pageNumber, - @Parameter(description = "Name of the property that the result list is sorted by") - @RequestParam(required = false) PatientSortBy sortBy, - @Parameter(description = "Direction of the sort") - @RequestParam(defaultValue = "ASC") Direction direction) throws StudyNotFoundException { - - if (projection == Projection.META) { - HttpHeaders responseHeaders = new HttpHeaders(); - responseHeaders.add(HeaderKeyConstants.TOTAL_COUNT, patientService.getMetaPatients(keyword) - .getTotalCount().toString()); - return new ResponseEntity<>(responseHeaders, HttpStatus.OK); - } else { - return new ResponseEntity<>( - patientService.getAllPatients(keyword, projection.name(), pageSize, pageNumber, - sortBy == null ? null : sortBy.getOriginalValue(), direction.name()), HttpStatus.OK); - } - } - - @PreAuthorize("hasPermission(#studyId, 'CancerStudyId', T(org.cbioportal.utils.security.AccessLevel).READ)") - @RequestMapping(value = "/studies/{studyId}/patients", method = RequestMethod.GET, - produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "Get all patients in a study") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(array = @ArraySchema(schema = @Schema(implementation = Patient.class)))) - public ResponseEntity> getAllPatientsInStudy( - @Parameter(required = true, description = "Study ID e.g. acc_tcga") - @PathVariable String studyId, - @Parameter(description = "Level of detail of the response") - @RequestParam(defaultValue = "SUMMARY") Projection projection, - @Parameter(description = "Page size of the result list") - @Max(PagingConstants.MAX_PAGE_SIZE) - @Min(PagingConstants.MIN_PAGE_SIZE) - @RequestParam(defaultValue = PagingConstants.DEFAULT_PAGE_SIZE) Integer pageSize, - @Parameter(description = "Page number of the result list") - @Min(PagingConstants.MIN_PAGE_NUMBER) - @RequestParam(defaultValue = PagingConstants.DEFAULT_PAGE_NUMBER) Integer pageNumber, - @Parameter(description = "Name of the property that the result list is sorted by") - @RequestParam(required = false) PatientSortBy sortBy, - @Parameter(description = "Direction of the sort") - @RequestParam(defaultValue = "ASC") Direction direction) throws StudyNotFoundException { - - if (projection == Projection.META) { - HttpHeaders responseHeaders = new HttpHeaders(); - responseHeaders.add(HeaderKeyConstants.TOTAL_COUNT, patientService.getMetaPatientsInStudy(studyId) - .getTotalCount().toString()); - return new ResponseEntity<>(responseHeaders, HttpStatus.OK); - } else { - return new ResponseEntity<>( - patientService.getAllPatientsInStudy(studyId, projection.name(), pageSize, pageNumber, - sortBy == null ? null : sortBy.getOriginalValue(), direction.name()), HttpStatus.OK); - } - } - - @PreAuthorize("hasPermission(#studyId, 'CancerStudyId', T(org.cbioportal.utils.security.AccessLevel).READ)") - @RequestMapping(value = "/studies/{studyId}/patients/{patientId}", method = RequestMethod.GET, - produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "Get a patient in a study") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(schema = @Schema(implementation = Patient.class))) - public ResponseEntity getPatientInStudy( - @Parameter(required = true, description = "Study ID e.g. acc_tcga") - @PathVariable String studyId, - @Parameter(required = true, description = "Patient ID e.g. TCGA-OR-A5J2") - @PathVariable String patientId) throws PatientNotFoundException, StudyNotFoundException { - - return new ResponseEntity<>(patientService.getPatientInStudy(studyId, patientId), HttpStatus.OK); - } - - @PreAuthorize("hasPermission(#involvedCancerStudies, 'Collection', T(org.cbioportal.utils.security.AccessLevel).READ)") - @RequestMapping(value = "/patients/fetch", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE, - produces = MediaType.APPLICATION_JSON_VALUE) - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(array = @ArraySchema(schema = @Schema(implementation = Patient.class)))) - public ResponseEntity> fetchPatients( - @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface - @RequestAttribute(required = false, value = "involvedCancerStudies") Collection involvedCancerStudies, - @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface. this attribute is needed for the @PreAuthorize tag above. - @Valid @RequestAttribute(required = false, value = "interceptedPatientFilter") PatientFilter interceptedPatientFilter, - @Parameter(required = true, description = "List of patient identifiers") - @Valid @RequestBody(required = false) PatientFilter patientFilter, - @Parameter(description = "Level of detail of the response") - @RequestParam(defaultValue = "SUMMARY") Projection projection) { - - List studyIds = new ArrayList<>(); - List patientIds = new ArrayList<>(); - - if (projection == Projection.META) { - HttpHeaders responseHeaders = new HttpHeaders(); - if (interceptedPatientFilter.getPatientIdentifiers() != null) { - extractStudyAndPatientIds(interceptedPatientFilter, studyIds, patientIds); - } else { - UniqueKeyExtractor.extractUniqueKeys(interceptedPatientFilter.getUniquePatientKeys(), studyIds, patientIds); - } - responseHeaders.add(HeaderKeyConstants.TOTAL_COUNT, patientService.fetchMetaPatients(studyIds, patientIds) - .getTotalCount().toString()); - return new ResponseEntity<>(responseHeaders, HttpStatus.OK); - } else { - if (interceptedPatientFilter.getPatientIdentifiers() != null) { - extractStudyAndPatientIds(interceptedPatientFilter, studyIds, patientIds); - } else { - UniqueKeyExtractor.extractUniqueKeys(interceptedPatientFilter.getUniquePatientKeys(), studyIds, patientIds); - } - //TODO: since we are already extracting the studyIds in the interceptor, we might not need to use the service here - return new ResponseEntity<>( - patientService.fetchPatients(studyIds, patientIds, projection.name()), HttpStatus.OK); - } - } - - private void extractStudyAndPatientIds(PatientFilter patientFilter, List studyIds, List patientIds) { - - for (PatientIdentifier patientIdentifier : patientFilter.getPatientIdentifiers()) { - studyIds.add(patientIdentifier.getStudyId()); - patientIds.add(patientIdentifier.getPatientId()); - } - } -} diff --git a/src/main/java/org/cbioportal/web/PublicVirtualStudiesController.java b/src/main/java/org/cbioportal/web/PublicVirtualStudiesController.java deleted file mode 100644 index c48ac446041..00000000000 --- a/src/main/java/org/cbioportal/web/PublicVirtualStudiesController.java +++ /dev/null @@ -1,139 +0,0 @@ -package org.cbioportal.web; - -import io.swagger.v3.oas.annotations.media.Content; -import io.swagger.v3.oas.annotations.media.Schema; -import io.swagger.v3.oas.annotations.responses.ApiResponse; -import org.cbioportal.service.CancerTypeService; -import org.cbioportal.service.exception.AccessForbiddenException; -import org.cbioportal.service.exception.CancerTypeNotFoundException; -import org.cbioportal.service.util.SessionServiceRequestHandler; -import org.cbioportal.web.parameter.VirtualStudy; -import org.cbioportal.web.parameter.VirtualStudyData; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.stereotype.Controller; -import org.springframework.web.bind.annotation.DeleteMapping; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestHeader; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestParam; - -import java.util.List; -import java.util.NoSuchElementException; -import java.util.Set; - -@Controller -@RequestMapping("/api/public_virtual_studies") -public class PublicVirtualStudiesController { - - private static final Logger LOG = LoggerFactory.getLogger(PublicVirtualStudiesController.class); - - public static final String ALL_USERS = "*"; - - private final String requiredPublisherApiKey; - - private final SessionServiceRequestHandler sessionServiceRequestHandler; - - private final CancerTypeService cancerTypeService; - - public PublicVirtualStudiesController( - @Value("${session.endpoint.publisher-api-key:}") String requiredPublisherApiKey, - SessionServiceRequestHandler sessionServiceRequestHandler, - CancerTypeService cancerTypeService - ) { - this.requiredPublisherApiKey = requiredPublisherApiKey; - this.sessionServiceRequestHandler = sessionServiceRequestHandler; - this.cancerTypeService = cancerTypeService; - } - - @GetMapping - @ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = VirtualStudy.class))) - public ResponseEntity> getPublicVirtualStudies() { - List virtualStudies = sessionServiceRequestHandler.getVirtualStudiesAccessibleToUser(ALL_USERS); - return new ResponseEntity<>(virtualStudies, HttpStatus.OK); - } - - @PostMapping("/{id}") - @ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = VirtualStudy.class))) - public ResponseEntity publishVirtualStudy( - @PathVariable String id, - @RequestHeader(value = "X-PUBLISHER-API-KEY") String providedPublisherApiKey, - @RequestParam(required = false) String typeOfCancerId, - @RequestParam(required = false) String pmid - ) { - ensureProvidedPublisherApiKeyCorrect(providedPublisherApiKey); - publishVirtualStudy(id, typeOfCancerId, pmid); - return ResponseEntity.ok().build(); - } - - @DeleteMapping("/{id}") - @ApiResponse(responseCode = "200", description = "OK") - public ResponseEntity unPublishVirtualStudy( - @PathVariable String id, - @RequestHeader(value = "X-PUBLISHER-API-KEY") String providedPublisherApiKey - ) { - ensureProvidedPublisherApiKeyCorrect(providedPublisherApiKey); - unPublishVirtualStudy(id); - return ResponseEntity.ok().build(); - } - - /** - * Publishes virtual study optionally updating metadata fields - * @param id - id of public virtual study to publish - * @param typeOfCancerId - if specified (not null) update type of cancer of published virtual study - * @param pmid - if specified (not null) update PubMed ID of published virtual study - */ - private void publishVirtualStudy(String id, String typeOfCancerId, String pmid) { - VirtualStudy virtualStudyDataToPublish = sessionServiceRequestHandler.getVirtualStudyById(id); - VirtualStudyData virtualStudyData = virtualStudyDataToPublish.getData(); - updateStudyMetadataFieldsIfSpecified(virtualStudyData, typeOfCancerId, pmid); - virtualStudyData.setUsers(Set.of(ALL_USERS)); - sessionServiceRequestHandler.updateVirtualStudy(virtualStudyDataToPublish); - } - - /** - * Un-publish virtual study - * @param id - id of public virtual study to un-publish - */ - private void unPublishVirtualStudy(String id) { - VirtualStudy virtualStudyToUnPublish = sessionServiceRequestHandler.getVirtualStudyById(id); - if (virtualStudyToUnPublish == null) { - throw new NoSuchElementException("The virtual study with id=" + id + " has not been found in the public list."); - } - VirtualStudyData virtualStudyData = virtualStudyToUnPublish.getData(); - Set users = virtualStudyData.getUsers(); - if (users == null || users.isEmpty() || !users.contains(ALL_USERS)) { - throw new NoSuchElementException("The virtual study with id=" + id + " has not been found in the public list."); - } - virtualStudyData.setUsers(Set.of(virtualStudyData.getOwner())); - sessionServiceRequestHandler.updateVirtualStudy(virtualStudyToUnPublish); - } - - private void ensureProvidedPublisherApiKeyCorrect(String providedPublisherApiKey) { - if (requiredPublisherApiKey.isBlank() - || !requiredPublisherApiKey.equals(providedPublisherApiKey)) { - throw new AccessForbiddenException("The provided publisher API key is not correct."); - } - } - - private void updateStudyMetadataFieldsIfSpecified(VirtualStudyData virtualStudyData, String typeOfCancerId, String pmid) { - if (typeOfCancerId != null) { - try { - cancerTypeService.getCancerType(typeOfCancerId); - virtualStudyData.setTypeOfCancerId(typeOfCancerId); - } catch (CancerTypeNotFoundException e) { - LOG.error("No cancer type with id={} were found.", typeOfCancerId); - throw new IllegalArgumentException( "The cancer type is not valid: " + typeOfCancerId); - } - } - if (pmid != null) { - virtualStudyData.setPmid(pmid); - } - } - -} diff --git a/src/main/java/org/cbioportal/web/ReferenceGenomeGeneController.java b/src/main/java/org/cbioportal/web/ReferenceGenomeGeneController.java deleted file mode 100644 index 5273ba1a165..00000000000 --- a/src/main/java/org/cbioportal/web/ReferenceGenomeGeneController.java +++ /dev/null @@ -1,111 +0,0 @@ -package org.cbioportal.web; - -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.media.ArraySchema; -import io.swagger.v3.oas.annotations.media.Content; -import io.swagger.v3.oas.annotations.media.Schema; -import io.swagger.v3.oas.annotations.responses.ApiResponse; -import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.validation.constraints.Size; -import org.cbioportal.model.ReferenceGenomeGene; -import org.cbioportal.service.GeneMemoizerService; -import org.cbioportal.service.ReferenceGenomeGeneService; -import org.cbioportal.service.exception.GeneNotFoundException; -import org.cbioportal.web.config.InternalApiTags; -import org.cbioportal.web.config.annotation.InternalApi; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestMethod; -import org.springframework.web.bind.annotation.RestController; - -import java.util.List; -import java.util.stream.Collectors; - -@InternalApi -@RestController -@Validated -@Tag(name = InternalApiTags.REFERENCE_GENOME_GENES, description = " ") -public class ReferenceGenomeGeneController { - private static final int GENE_MAX_PAGE_SIZE = 100000; - private static final String GENE_DEFAULT_PAGE_SIZE = "100000"; - - @Autowired - private ReferenceGenomeGeneService referenceGenomeGeneService; - - @Autowired - private GeneMemoizerService geneMemoizerService; - - /** - * The memoization logic in this method is a temporary fix to make this work until - * Ehcache is working correctly on cbioportal.org. - * This endpoint creates a large response and seems to bloat the webserver's heap - * size, leading to poor performance and crashes. The caching seems to improve - * processor load, heap size and response time. - */ - @RequestMapping(value = "/api/reference-genome-genes/{genomeName}", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "Get all reference genes") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(array = @ArraySchema(schema = @Schema(implementation = ReferenceGenomeGene.class)))) - public ResponseEntity> getAllReferenceGenomeGenes( - @Parameter(required = true, description = "Name of Reference Genome hg19") - @PathVariable String genomeName) { - - List genes = geneMemoizerService.fetchGenes(genomeName); - if (genes == null) { - genes = referenceGenomeGeneService.fetchAllReferenceGenomeGenes(genomeName); - geneMemoizerService.cacheGenes(genes, genomeName); - } - return new ResponseEntity<>(genes, HttpStatus.OK); - } - - @RequestMapping(value = "/api/reference-genome-genes/{genomeName}/{geneId}", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "Get a gene of a reference genome of interest") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(schema = @Schema(implementation = ReferenceGenomeGene.class))) - public ResponseEntity getReferenceGenomeGene( - @Parameter(required = true, description = "Name of Reference Genome hg19") - @PathVariable String genomeName, - @Parameter(required = true, description = "Entrez Gene ID 207") - @PathVariable Integer geneId) throws GeneNotFoundException { - - return new ResponseEntity<>(referenceGenomeGeneService.getReferenceGenomeGene(geneId, genomeName), HttpStatus.OK); - } - - @RequestMapping(value = "/api/reference-genome-genes/{genomeName}/fetch", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE, - produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "Fetch genes of reference genome of interest") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(array = @ArraySchema(schema = @Schema(implementation = ReferenceGenomeGene.class)))) - public ResponseEntity> fetchReferenceGenomeGenes( - @Parameter(required = true, description = "Name of Reference Genome hg19") - @PathVariable String genomeName, - @Parameter(required = true, description = "List of Gene IDs") - @Size(min = 1, max = GENE_MAX_PAGE_SIZE) - @RequestBody List geneIds) { - - if (isInteger(geneIds.get(0))) { - List newIds = geneIds.stream().map(s -> Integer.parseInt(s)).collect(Collectors.toList()); - return new ResponseEntity<>(referenceGenomeGeneService.fetchGenesByGenomeName(newIds, genomeName), HttpStatus.OK); - } else { - return new ResponseEntity<>(referenceGenomeGeneService.fetchGenesByHugoGeneSymbolsAndGenomeName( - geneIds, genomeName), HttpStatus.OK); - } - } - - private boolean isInteger(String s) { - try { - Integer.parseInt(s); - } catch(NumberFormatException | NullPointerException e) { - return false; - } - return true; - } -} - diff --git a/src/main/java/org/cbioportal/web/ResourceDataController.java b/src/main/java/org/cbioportal/web/ResourceDataController.java deleted file mode 100644 index 4920791285a..00000000000 --- a/src/main/java/org/cbioportal/web/ResourceDataController.java +++ /dev/null @@ -1,220 +0,0 @@ -package org.cbioportal.web; - -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.media.ArraySchema; -import io.swagger.v3.oas.annotations.media.Content; -import io.swagger.v3.oas.annotations.media.Schema; -import io.swagger.v3.oas.annotations.responses.ApiResponse; -import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.validation.constraints.Max; -import jakarta.validation.constraints.Min; - -import org.cbioportal.model.ResourceData; -import org.cbioportal.service.ResourceDataService; -import org.cbioportal.service.exception.PatientNotFoundException; -import org.cbioportal.service.exception.SampleNotFoundException; -import org.cbioportal.service.exception.StudyNotFoundException; -import org.cbioportal.web.config.InternalApiTags; -import org.cbioportal.web.config.annotation.InternalApi; -import org.cbioportal.web.parameter.Direction; -import org.cbioportal.web.parameter.PagingConstants; -import org.cbioportal.web.parameter.Projection; -import org.cbioportal.web.parameter.sort.ResourceDataSortBy; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.ApplicationContext; -import org.springframework.cache.annotation.Cacheable; -import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.PathVariable; -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.bind.annotation.RestController; - -import java.util.List; -import java.util.Objects; - -@InternalApi -@RestController() -@RequestMapping("/api") -@Validated -@Tag(name = InternalApiTags.RESOURCE_DATA, description = " ") -public class ResourceDataController { - - public static final int RESOURCE_DATA_MAX_PAGE_SIZE = 10000000; - private static final String RESOURCE_DATA_DEFAULT_PAGE_SIZE = "10000000"; - - @Autowired - private ResourceDataService resourceDataService; - - @Autowired - private ApplicationContext applicationContext; - ResourceDataController instance; - - private ResourceDataController getInstance() { - if (Objects.isNull(instance)) { - instance = applicationContext.getBean(ResourceDataController.class); - } - return instance; - } - - @PreAuthorize("hasPermission(#studyId, 'CancerStudyId', T(org.cbioportal.utils.security.AccessLevel).READ)") - @RequestMapping(value = "/studies/{studyId}/samples/{sampleId}/resource-data", method = RequestMethod.GET, - produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "Get all resource data of a sample in a study") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(array = @ArraySchema(schema = @Schema(implementation = ResourceData.class)))) - public ResponseEntity> getAllResourceDataOfSampleInStudy( - @Parameter(required = true, description = "Study ID e.g. acc_tcga") - @PathVariable String studyId, - @Parameter(required = true, description = "Sample ID e.g. TCGA-OR-A5J2-01") - @PathVariable String sampleId, - @Parameter(description = "Resource ID") - @RequestParam(required = false) String resourceId, - @Parameter(description = "Level of detail of the response") - @RequestParam(defaultValue = "SUMMARY") Projection projection, - @Parameter(description = "Page size of the result list") - @Max(RESOURCE_DATA_MAX_PAGE_SIZE) - @Min(PagingConstants.MIN_PAGE_SIZE) - @RequestParam(defaultValue = RESOURCE_DATA_DEFAULT_PAGE_SIZE) Integer pageSize, - @Parameter(description = "Page number of the result list") - @Min(PagingConstants.MIN_PAGE_NUMBER) - @RequestParam(defaultValue = PagingConstants.DEFAULT_PAGE_NUMBER) Integer pageNumber, - @Parameter(description = "Name of the property that the result list is sorted by") - @RequestParam(required = false) ResourceDataSortBy sortBy, - @Parameter(description = "Direction of the sort") - @RequestParam(defaultValue = "ASC") Direction direction) throws SampleNotFoundException, - StudyNotFoundException { - - if (projection == Projection.META) { - throw new UnsupportedOperationException("Requested API is not implemented yet"); - } else { - return new ResponseEntity<>( - resourceDataService.getAllResourceDataOfSampleInStudy( - studyId, sampleId, resourceId, projection.name(), pageSize, pageNumber, - sortBy == null ? null : sortBy.getOriginalValue(), direction.name()), HttpStatus.OK); - } - } - - @PreAuthorize("hasPermission(#studyId, 'CancerStudyId', T(org.cbioportal.utils.security.AccessLevel).READ)") - @RequestMapping(value = "/studies/{studyId}/patients/{patientId}/resource-data", method = RequestMethod.GET, - produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "Get all resource data of a patient in a study") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(array = @ArraySchema(schema = @Schema(implementation = ResourceData.class)))) - public ResponseEntity> getAllResourceDataOfPatientInStudy( - @Parameter(required = true, description = "Study ID e.g. acc_tcga") - @PathVariable String studyId, - @Parameter(required = true, description = "Patient ID e.g. TCGA-OR-A5J2") - @PathVariable String patientId, - @Parameter(description = "Resource ID") - @RequestParam(required = false) String resourceId, - @Parameter(description = "Level of detail of the response") - @RequestParam(defaultValue = "SUMMARY") Projection projection, - @Parameter(description = "Page size of the result list") - @Max(RESOURCE_DATA_MAX_PAGE_SIZE) - @Min(PagingConstants.MIN_PAGE_SIZE) - @RequestParam(defaultValue = RESOURCE_DATA_DEFAULT_PAGE_SIZE) Integer pageSize, - @Parameter(description = "Page number of the result list") - @Min(PagingConstants.MIN_PAGE_NUMBER) - @RequestParam(defaultValue = PagingConstants.DEFAULT_PAGE_NUMBER) Integer pageNumber, - @Parameter(description = "Name of the property that the result list is sorted by") - @RequestParam(required = false) ResourceDataSortBy sortBy, - @Parameter(description = "Direction of the sort") - @RequestParam(defaultValue = "ASC") Direction direction) throws PatientNotFoundException, - StudyNotFoundException { - - if (projection == Projection.META) { - throw new UnsupportedOperationException("Requested API is not implemented yet"); - } else { - return new ResponseEntity<>( - resourceDataService.getAllResourceDataOfPatientInStudy( - studyId, patientId, resourceId, projection.name(), pageSize, pageNumber, - sortBy == null ? null : sortBy.getOriginalValue(), direction.name()), HttpStatus.OK); - } - } - - @PreAuthorize("hasPermission(#studyId, 'CancerStudyId', T(org.cbioportal.utils.security.AccessLevel).READ)") - @RequestMapping(value = "/studies/{studyId}/resource-data", method = RequestMethod.GET, - produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "Get all resource data for a study") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(array = @ArraySchema(schema = @Schema(implementation = ResourceData.class)))) - public ResponseEntity> getAllStudyResourceDataInStudy( - @Parameter(required = true, description = "Study ID e.g. acc_tcga") - @PathVariable String studyId, - @Parameter(description = "Resource ID") - @RequestParam(required = false) String resourceId, - @Parameter(description = "Level of detail of the response") - @RequestParam(defaultValue = "SUMMARY") Projection projection, - @Parameter(description = "Page size of the result list") - @Max(RESOURCE_DATA_MAX_PAGE_SIZE) - @Min(PagingConstants.MIN_PAGE_SIZE) - @RequestParam(defaultValue = RESOURCE_DATA_DEFAULT_PAGE_SIZE) Integer pageSize, - @Parameter(description = "Page number of the result list") - @Min(PagingConstants.MIN_PAGE_NUMBER) - @RequestParam(defaultValue = PagingConstants.DEFAULT_PAGE_NUMBER) Integer pageNumber, - @Parameter(description = "Name of the property that the result list is sorted by") - @RequestParam(required = false) ResourceDataSortBy sortBy, - @Parameter(description = "Direction of the sort") - @RequestParam(defaultValue = "ASC") Direction direction) throws StudyNotFoundException { - - if (projection == Projection.META) { - throw new UnsupportedOperationException("Requested API is not implemented yet"); - } else { - return new ResponseEntity<>( - resourceDataService.getAllResourceDataForStudy(studyId, resourceId, projection.name(), pageSize, pageNumber, - sortBy == null ? null : sortBy.getOriginalValue(), direction.name()), HttpStatus.OK); - } - } - - @PreAuthorize("hasPermission(#studyId, 'CancerStudyId', T(org.cbioportal.utils.security.AccessLevel).READ)") - @RequestMapping(value = "/studies/{studyId}/resource-data-all", method = RequestMethod.GET, - produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "Get all resource data for for all patients and all samples within a study") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(array = @ArraySchema(schema = @Schema(implementation = ResourceData.class)))) - public ResponseEntity> getAllStudyResourceDataInStudyPatientSample( - @Parameter(required = true, description = "Study ID e.g. acc_tcga") - @PathVariable String studyId, - @Parameter(description = "Resource ID") - @RequestParam(required = false) String resourceId, - @Parameter(description = "Level of detail of the response") - @RequestParam(defaultValue = "SUMMARY") Projection projection, - @Parameter(description = "Page size of the result list") - @Max(RESOURCE_DATA_MAX_PAGE_SIZE) - @Min(PagingConstants.MIN_PAGE_SIZE) - @RequestParam(defaultValue = RESOURCE_DATA_DEFAULT_PAGE_SIZE) Integer pageSize, - @Parameter(description = "Page number of the result list") - @Min(PagingConstants.MIN_PAGE_NUMBER) - @RequestParam(defaultValue = PagingConstants.DEFAULT_PAGE_NUMBER) Integer pageNumber, - @Parameter(description = "Name of the property that the result list is sorted by") - @RequestParam(required = false) ResourceDataSortBy sortBy, - @Parameter(description = "Direction of the sort") - @RequestParam(defaultValue = "ASC") Direction direction) throws StudyNotFoundException { - - if (projection == Projection.META) { - throw new UnsupportedOperationException("Requested API is not implemented yet"); - } else { - return new ResponseEntity<>(this.getInstance().cacheableFetchAllResourceDataForStudyPatientSample( - studyId, resourceId, projection.name(), pageSize, pageNumber, sortBy == null ? null : sortBy.getOriginalValue(), - direction.name()) , HttpStatus.OK); - } - } - - @Cacheable( - cacheResolver = "staticRepositoryCacheOneResolver", - condition = "@cacheEnabledConfig.getEnabled()" - ) - public List cacheableFetchAllResourceDataForStudyPatientSample(String studyId, String resourceId, String projectionName, - Integer pageSize, Integer pageNumber, String sortBy, String directionName) throws StudyNotFoundException { - - return resourceDataService.getAllResourceDataForStudyPatientSample(studyId, resourceId, projectionName, pageSize, pageNumber, - sortBy, directionName); - } - -} diff --git a/src/main/java/org/cbioportal/web/ResourceDefinitionController.java b/src/main/java/org/cbioportal/web/ResourceDefinitionController.java deleted file mode 100644 index 4f4658166c8..00000000000 --- a/src/main/java/org/cbioportal/web/ResourceDefinitionController.java +++ /dev/null @@ -1,114 +0,0 @@ -package org.cbioportal.web; - -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.media.ArraySchema; -import io.swagger.v3.oas.annotations.media.Content; -import io.swagger.v3.oas.annotations.media.Schema; -import io.swagger.v3.oas.annotations.responses.ApiResponse; -import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.validation.constraints.Max; -import jakarta.validation.constraints.Min; -import jakarta.validation.constraints.Size; -import org.cbioportal.model.ResourceDefinition; -import org.cbioportal.service.ResourceDefinitionService; -import org.cbioportal.service.exception.ResourceDefinitionNotFoundException; -import org.cbioportal.service.exception.StudyNotFoundException; -import org.cbioportal.web.config.InternalApiTags; -import org.cbioportal.web.config.annotation.InternalApi; -import org.cbioportal.web.parameter.Direction; -import org.cbioportal.web.parameter.PagingConstants; -import org.cbioportal.web.parameter.Projection; -import org.cbioportal.web.parameter.sort.ResourceDefinitionSortBy; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RequestBody; -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.bind.annotation.RestController; - -import java.util.List; - -@InternalApi -@RestController() -@RequestMapping("/api") -@Validated -@Tag(name = InternalApiTags.RESOURCE_DEFINITIONS, description = " ") -public class ResourceDefinitionController { - - @Autowired - private ResourceDefinitionService resourceDefinitionService; - - @PreAuthorize("hasPermission(#studyId, 'CancerStudyId', T(org.cbioportal.utils.security.AccessLevel).READ)") - @RequestMapping(value = "/studies/{studyId}/resource-definitions", method = RequestMethod.GET, - produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "Get all resource definitions in the specified study") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(array = @ArraySchema(schema = @Schema(implementation = ResourceDefinition.class)))) - public ResponseEntity> getAllResourceDefinitionsInStudy( - @Parameter(required = true, description = "Study ID e.g. acc_tcga") - @PathVariable String studyId, - @Parameter(description = "Level of detail of the response") - @RequestParam(defaultValue = "SUMMARY") Projection projection, - @Parameter(description = "Page size of the result list") - @Max(PagingConstants.MAX_PAGE_SIZE) - @Min(PagingConstants.MIN_PAGE_SIZE) - @RequestParam(defaultValue = PagingConstants.DEFAULT_PAGE_SIZE) Integer pageSize, - @Parameter(description = "Page number of the result list") - @Min(PagingConstants.MIN_PAGE_NUMBER) - @RequestParam(defaultValue = PagingConstants.DEFAULT_PAGE_NUMBER) Integer pageNumber, - @Parameter(description = "Name of the property that the result list is sorted by") - @RequestParam(required = false) ResourceDefinitionSortBy sortBy, - @Parameter(description = "Direction of the sort") - @RequestParam(defaultValue = "ASC") Direction direction) throws StudyNotFoundException { - - if (projection == Projection.META) { - throw new UnsupportedOperationException("Requested API is not implemented yet"); - } else { - return new ResponseEntity<>( - resourceDefinitionService.getAllResourceDefinitionsInStudy(studyId, projection.name(), pageSize, - pageNumber, sortBy == null ? null : sortBy.getOriginalValue(), direction.name()), - HttpStatus.OK); - } - } - - @PreAuthorize("hasPermission(#studyId, 'CancerStudyId', T(org.cbioportal.utils.security.AccessLevel).READ)") - @RequestMapping(value = "/studies/{studyId}/resource-definitions/{resourceId}", method = RequestMethod.GET, - produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "Get specified resource definition") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(schema = @Schema(implementation = ResourceDefinition.class))) - public ResponseEntity getResourceDefinitionInStudy( - @Parameter(required = true, description = "Study ID e.g. acc_tcga") - @PathVariable String studyId, - @Parameter(required = true, description= "Resource ID") - @PathVariable String resourceId) - throws StudyNotFoundException, ResourceDefinitionNotFoundException { - - return new ResponseEntity<>(resourceDefinitionService.getResourceDefinition(studyId, resourceId), - HttpStatus.OK); - } - - @PreAuthorize("hasPermission(#studyIds, 'Collection', T(org.cbioportal.utils.security.AccessLevel).READ)") - @RequestMapping(value = "/resource-definitions/fetch", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE, - produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "Get all resource definitions for specified studies") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(array = @ArraySchema(schema = @Schema(implementation = ResourceDefinition.class)))) - public ResponseEntity> fetchResourceDefinitions( - @Parameter(required = true, description = "List of Study IDs") - @Size(min = 1, max = PagingConstants.MAX_PAGE_SIZE) - @RequestBody List studyIds, - @Parameter(description = "Level of detail of the response") - @RequestParam(defaultValue = "SUMMARY") Projection projection) throws StudyNotFoundException { - - return new ResponseEntity<>(resourceDefinitionService.fetchResourceDefinitions(studyIds, projection.name()), - HttpStatus.OK); - } -} diff --git a/src/main/java/org/cbioportal/web/SamlAndBasicLoginController.java b/src/main/java/org/cbioportal/web/SamlAndBasicLoginController.java deleted file mode 100644 index 0364e0d981f..00000000000 --- a/src/main/java/org/cbioportal/web/SamlAndBasicLoginController.java +++ /dev/null @@ -1,29 +0,0 @@ -package org.cbioportal.web; - -import jakarta.servlet.http.HttpServletRequest; -import org.cbioportal.service.FrontendPropertiesService; -import org.cbioportal.service.FrontendPropertiesServiceImpl; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.http.MediaType; -import org.springframework.stereotype.Controller; -import org.springframework.ui.Model; -import org.springframework.web.bind.annotation.GetMapping; - -@Controller -@ConditionalOnProperty(value = "authenticate", havingValue = "saml_plus_basic") -public class SamlAndBasicLoginController { - - private final FrontendPropertiesService frontendPropertiesService; - - @Autowired - SamlAndBasicLoginController(FrontendPropertiesService frontendPropertiesService) { - this.frontendPropertiesService = frontendPropertiesService; - } - - @GetMapping(value = "/restful_login", produces = MediaType.APPLICATION_JSON_VALUE) - public String showRestfulLoginPage(HttpServletRequest request, Model model) { - model.addAttribute("skin_title", frontendPropertiesService.getFrontendProperty(FrontendPropertiesServiceImpl.FrontendProperty.skin_title)); - return "restful_login"; - } -} diff --git a/src/main/java/org/cbioportal/web/SampleController.java b/src/main/java/org/cbioportal/web/SampleController.java deleted file mode 100644 index 83cd4df45b5..00000000000 --- a/src/main/java/org/cbioportal/web/SampleController.java +++ /dev/null @@ -1,312 +0,0 @@ -package org.cbioportal.web; - -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.media.ArraySchema; -import io.swagger.v3.oas.annotations.media.Content; -import io.swagger.v3.oas.annotations.media.Schema; -import io.swagger.v3.oas.annotations.responses.ApiResponse; -import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.validation.Valid; -import jakarta.validation.constraints.Max; -import jakarta.validation.constraints.Min; -import org.cbioportal.model.CancerStudy; -import org.cbioportal.model.Sample; -import org.cbioportal.model.meta.BaseMeta; -import org.cbioportal.service.SampleListService; -import org.cbioportal.service.SampleService; -import org.cbioportal.service.StudyService; -import org.cbioportal.service.exception.PatientNotFoundException; -import org.cbioportal.service.exception.SampleListNotFoundException; -import org.cbioportal.service.exception.SampleNotFoundException; -import org.cbioportal.service.exception.StudyNotFoundException; -import org.cbioportal.utils.security.AccessLevel; -import org.cbioportal.utils.security.PortalSecurityConfig; -import org.cbioportal.web.config.PublicApiTags; -import org.cbioportal.web.config.annotation.PublicApi; -import org.cbioportal.web.parameter.Direction; -import org.cbioportal.web.parameter.HeaderKeyConstants; -import org.cbioportal.web.parameter.PagingConstants; -import org.cbioportal.web.parameter.Projection; -import org.cbioportal.web.parameter.SampleFilter; -import org.cbioportal.web.parameter.SampleIdentifier; -import org.cbioportal.web.parameter.sort.SampleSortBy; -import org.cbioportal.web.util.UniqueKeyExtractor; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RequestAttribute; -import org.springframework.web.bind.annotation.RequestBody; -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.bind.annotation.RestController; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.List; -import java.util.stream.Collectors; - -@PublicApi -@RestController() -@RequestMapping("/api") -@Validated -@Tag(name = PublicApiTags.SAMPLES, description = " ") -public class SampleController { - - public static final int SAMPLE_MAX_PAGE_SIZE = 10000000; - private static final String SAMPLE_DEFAULT_PAGE_SIZE = "10000000"; - - @Value("${authenticate}") - private String authenticate; - - @Autowired - private SampleService sampleService; - - @Autowired - private SampleListService sampleListService; - - @Autowired - private StudyService studyService; - - private boolean usingAuth() { - return !authenticate.isEmpty() - && !authenticate.equals("false") - && !authenticate.contains("optional_oauth2"); - } - - @RequestMapping(value = "/samples", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "Get all samples matching keyword") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(array = @ArraySchema(schema = @Schema(implementation = Sample.class)))) - public ResponseEntity> getSamplesByKeyword( - @Parameter(description = "Search keyword that applies to the study ID") - @RequestParam(required = false) String keyword, - - @Parameter(description = "Level of detail of the response") - @RequestParam(defaultValue = "SUMMARY") Projection projection, - - @Parameter(description = "Page size of the result list") - @Max(PagingConstants.MAX_PAGE_SIZE) - @Min(PagingConstants.MIN_PAGE_SIZE) - @RequestParam(defaultValue = PagingConstants.DEFAULT_PAGE_SIZE) Integer pageSize, - - @Parameter(description = "Page number of the result list") - @Min(PagingConstants.MIN_PAGE_NUMBER) - @RequestParam(defaultValue = PagingConstants.DEFAULT_PAGE_NUMBER) Integer pageNumber, - - @Parameter(description = "Name of the property that the result list is sorted by") - @RequestParam(required = false) SampleSortBy sortBy, - - @Parameter(description = "Direction of the sort") - @RequestParam(defaultValue = "ASC") Direction direction - ) { - String sort = sortBy == null ? null : sortBy.getOriginalValue(); - List studyIds = null; - if (PortalSecurityConfig.userAuthorizationEnabled(authenticate)) { - /* - If using auth, filter the list of samples returned using the list of study ids the - user has access to. If the user has access to no studies, the endpoint should not 403, - but instead return an empty list. - */ - studyIds = studyService - .getAllStudies( - null, - Projection.SUMMARY.name(), // force to summary so that post filter doesn't NPE - PagingConstants.MAX_PAGE_SIZE, - 0, - null, - direction.name(), - null, - AccessLevel.READ - ) - .stream() - .map(CancerStudy::getCancerStudyIdentifier) - .collect(Collectors.toList()); - } - - if (projection == Projection.META) { - HttpHeaders httpHeaders = new HttpHeaders(); - httpHeaders.add( - HeaderKeyConstants.TOTAL_COUNT, - sampleService.getMetaSamples(keyword, studyIds).getTotalCount().toString()); - return new ResponseEntity<>(httpHeaders, HttpStatus.OK); - } - return new ResponseEntity<>( - sampleService.getAllSamples(keyword, studyIds, projection.name(), pageSize, pageNumber, sort, direction.name()), - HttpStatus.OK - ); - } - - @PreAuthorize("hasPermission(#studyId, 'CancerStudyId', T(org.cbioportal.utils.security.AccessLevel).READ)") - @RequestMapping(value = "/studies/{studyId}/samples", method = RequestMethod.GET, - produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "Get all samples in a study") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(array = @ArraySchema(schema = @Schema(implementation = Sample.class)))) - public ResponseEntity> getAllSamplesInStudy( - @Parameter(required = true, description = "Study ID e.g. acc_tcga") - @PathVariable String studyId, - @Parameter(description = "Level of detail of the response") - @RequestParam(defaultValue = "SUMMARY") Projection projection, - @Parameter(description = "Page size of the result list") - @Max(SAMPLE_MAX_PAGE_SIZE) - @Min(PagingConstants.MIN_PAGE_SIZE) - @RequestParam(defaultValue = SAMPLE_DEFAULT_PAGE_SIZE) Integer pageSize, - @Parameter(description = "Page number of the result list") - @Min(PagingConstants.MIN_PAGE_NUMBER) - @RequestParam(defaultValue = PagingConstants.DEFAULT_PAGE_NUMBER) Integer pageNumber, - @Parameter(description = "Name of the property that the result list is sorted by") - @RequestParam(required = false) SampleSortBy sortBy, - @Parameter(description = "Direction of the sort") - @RequestParam(defaultValue = "ASC") Direction direction) throws StudyNotFoundException { - - if (projection == Projection.META) { - HttpHeaders responseHeaders = new HttpHeaders(); - responseHeaders.add(HeaderKeyConstants.TOTAL_COUNT, sampleService.getMetaSamplesInStudy(studyId) - .getTotalCount().toString()); - return new ResponseEntity<>(responseHeaders, HttpStatus.OK); - } else { - return new ResponseEntity<>( - sampleService.getAllSamplesInStudy(studyId, projection.name(), pageSize, pageNumber, - sortBy == null ? null : sortBy.getOriginalValue(), direction.name()), HttpStatus.OK); - } - } - - @PreAuthorize("hasPermission(#studyId, 'CancerStudyId', T(org.cbioportal.utils.security.AccessLevel).READ)") - @RequestMapping(value = "/studies/{studyId}/samples/{sampleId}", method = RequestMethod.GET, - produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "Get a sample in a study") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(schema = @Schema(implementation = Sample.class))) - public ResponseEntity getSampleInStudy( - @Parameter(required = true, description = "Study ID e.g. acc_tcga") - @PathVariable String studyId, - @Parameter(required = true, description = "Sample ID e.g. TCGA-OR-A5J2-01") - @PathVariable String sampleId) throws SampleNotFoundException, StudyNotFoundException { - - return new ResponseEntity<>(sampleService.getSampleInStudy(studyId, sampleId), HttpStatus.OK); - } - - @PreAuthorize("hasPermission(#studyId, 'CancerStudyId', T(org.cbioportal.utils.security.AccessLevel).READ)") - @RequestMapping(value = "/studies/{studyId}/patients/{patientId}/samples", method = RequestMethod.GET, - produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "Get all samples of a patient in a study") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(array = @ArraySchema(schema = @Schema(implementation = Sample.class)))) - public ResponseEntity> getAllSamplesOfPatientInStudy( - @Parameter(required = true, description = "Study ID e.g. acc_tcga") - @PathVariable String studyId, - @Parameter(required = true, description = "Patient ID e.g. TCGA-OR-A5J2") - @PathVariable String patientId, - @Parameter(description = "Level of detail of the response") - @RequestParam(defaultValue = "SUMMARY") Projection projection, - @Parameter(description = "Page size of the result list") - @Max(SAMPLE_MAX_PAGE_SIZE) - @Min(PagingConstants.MIN_PAGE_SIZE) - @RequestParam(defaultValue = SAMPLE_DEFAULT_PAGE_SIZE) Integer pageSize, - @Parameter(description = "Page number of the result list") - @Min(PagingConstants.MIN_PAGE_NUMBER) - @RequestParam(defaultValue = PagingConstants.DEFAULT_PAGE_NUMBER) Integer pageNumber, - @Parameter(description = "Name of the property that the result list is sorted by") - @RequestParam(required = false) SampleSortBy sortBy, - @Parameter(description = "Direction of the sort") - @RequestParam(defaultValue = "ASC") Direction direction) throws PatientNotFoundException, - StudyNotFoundException { - - if (projection == Projection.META) { - HttpHeaders responseHeaders = new HttpHeaders(); - responseHeaders.add(HeaderKeyConstants.TOTAL_COUNT, - sampleService.getMetaSamplesOfPatientInStudy(studyId, patientId).getTotalCount().toString()); - return new ResponseEntity<>(responseHeaders, HttpStatus.OK); - } else { - return new ResponseEntity<>( - sampleService.getAllSamplesOfPatientInStudy(studyId, patientId, projection.name(), pageSize, - pageNumber, sortBy == null ? null : sortBy.getOriginalValue(), direction.name()), HttpStatus.OK); - } - } - - @PreAuthorize("hasPermission(#involvedCancerStudies, 'Collection', T(org.cbioportal.utils.security.AccessLevel).READ)") - @RequestMapping(value = "/samples/fetch", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE, - produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "Fetch samples by ID") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(array = @ArraySchema(schema = @Schema(implementation = Sample.class)))) - public ResponseEntity> fetchSamples( - @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface - @RequestAttribute(required = false, value = "involvedCancerStudies") Collection involvedCancerStudies, - @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface. this attribute is needed for the @PreAuthorize tag above. - @Valid @RequestAttribute(required = false, value = "interceptedSampleFilter") SampleFilter interceptedSampleFilter, - @Parameter(required = true, description = "List of sample identifiers") - @Valid @RequestBody(required = false) SampleFilter sampleFilter, - @Parameter(description = "Level of detail of the response") - @RequestParam(defaultValue = "SUMMARY") Projection projection) throws SampleListNotFoundException { - - List studyIds = new ArrayList<>(); - List sampleIds = new ArrayList<>(); - - if (projection == Projection.META) { - HttpHeaders responseHeaders = new HttpHeaders(); - BaseMeta baseMeta; - - if (interceptedSampleFilter.getSampleListIds() != null) { - baseMeta = sampleService.fetchMetaSamples(interceptedSampleFilter.getSampleListIds()); - } else { - if (interceptedSampleFilter.getSampleIdentifiers() != null) { - extractStudyAndSampleIds(interceptedSampleFilter, studyIds, sampleIds); - } else { - UniqueKeyExtractor.extractUniqueKeys(interceptedSampleFilter.getUniqueSampleKeys(), studyIds, sampleIds); - } - baseMeta = sampleService.fetchMetaSamples(studyIds, sampleIds); - } - responseHeaders.add(HeaderKeyConstants.TOTAL_COUNT, baseMeta.getTotalCount().toString()); - return new ResponseEntity<>(responseHeaders, HttpStatus.OK); - } else { - List samples; - if (interceptedSampleFilter.getSampleListIds() != null) { - List sampleListIds = interceptedSampleFilter.getSampleListIds(); - - samples = new ArrayList(); - - for (String sampleListId : sampleListIds) { - // check that all sample lists exist (this method throws an exception if one does not) - sampleListService.getSampleList(sampleListId); - } - - for (String sampleListId : sampleListIds) { - // fetch by sampleId so that we get cache at level of id instead list of ids - samples.addAll( - sampleService.fetchSamples(Arrays.asList(sampleListId), projection.name()) - ); - } - - //samples = sampleService.fetchSamples(sampleListIds, projection.name()); - - } else { - if (interceptedSampleFilter.getSampleIdentifiers() != null) { - extractStudyAndSampleIds(interceptedSampleFilter, studyIds, sampleIds); - } else { - UniqueKeyExtractor.extractUniqueKeys(interceptedSampleFilter.getUniqueSampleKeys(), studyIds, sampleIds); - } - samples = sampleService.fetchSamples(studyIds, sampleIds, projection.name()); - } - - return new ResponseEntity<>(samples, HttpStatus.OK); - } - } - - private void extractStudyAndSampleIds(SampleFilter sampleFilter, List studyIds, List sampleIds) { - - for (SampleIdentifier sampleIdentifier : sampleFilter.getSampleIdentifiers()) { - studyIds.add(sampleIdentifier.getStudyId()); - sampleIds.add(sampleIdentifier.getSampleId()); - } - } -} diff --git a/src/main/java/org/cbioportal/web/SampleListController.java b/src/main/java/org/cbioportal/web/SampleListController.java deleted file mode 100644 index ce1e82eff1c..00000000000 --- a/src/main/java/org/cbioportal/web/SampleListController.java +++ /dev/null @@ -1,158 +0,0 @@ -package org.cbioportal.web; - -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.media.ArraySchema; -import io.swagger.v3.oas.annotations.media.Content; -import io.swagger.v3.oas.annotations.media.Schema; -import io.swagger.v3.oas.annotations.responses.ApiResponse; -import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.validation.constraints.Max; -import jakarta.validation.constraints.Min; -import jakarta.validation.constraints.Size; -import org.cbioportal.model.SampleList; -import org.cbioportal.service.SampleListService; -import org.cbioportal.service.exception.SampleListNotFoundException; -import org.cbioportal.service.exception.StudyNotFoundException; -import org.cbioportal.web.config.PublicApiTags; -import org.cbioportal.web.config.annotation.PublicApi; -import org.cbioportal.web.parameter.Direction; -import org.cbioportal.web.parameter.HeaderKeyConstants; -import org.cbioportal.web.parameter.PagingConstants; -import org.cbioportal.web.parameter.Projection; -import org.cbioportal.web.parameter.sort.SampleListSortBy; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RequestBody; -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.bind.annotation.RestController; - -import java.util.List; - -@PublicApi -@RestController() -@RequestMapping("/api") -@Validated -@Tag(name = PublicApiTags.SAMPLE_LISTS, description = " ") -public class SampleListController { - - @Autowired - private SampleListService sampleListService; - - @RequestMapping(value = "/sample-lists", method = RequestMethod.GET, - produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "Get all sample lists") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(array = @ArraySchema(schema = @Schema(implementation = SampleList.class)))) - public ResponseEntity> getAllSampleLists( - @Parameter(description = "Level of detail of the response") - @RequestParam(defaultValue = "SUMMARY") Projection projection, - @Parameter(description = "Page size of the result list") - @Max(PagingConstants.MAX_PAGE_SIZE) - @Min(PagingConstants.MIN_PAGE_SIZE) - @RequestParam(defaultValue = PagingConstants.DEFAULT_PAGE_SIZE) Integer pageSize, - @Parameter(description = "Page number of the result list") - @Min(PagingConstants.MIN_PAGE_NUMBER) - @RequestParam(defaultValue = PagingConstants.DEFAULT_PAGE_NUMBER) Integer pageNumber, - @Parameter(description = "Name of the property that the result list is sorted by") - @RequestParam(required = false) SampleListSortBy sortBy, - @Parameter(description = "Direction of the sort") - @RequestParam(defaultValue = "ASC") Direction direction) { - - if (projection == Projection.META) { - HttpHeaders responseHeaders = new HttpHeaders(); - responseHeaders.add(HeaderKeyConstants.TOTAL_COUNT, sampleListService.getMetaSampleLists() - .getTotalCount().toString()); - return new ResponseEntity<>(responseHeaders, HttpStatus.OK); - } else { - return new ResponseEntity<>( - sampleListService.getAllSampleLists(projection.name(), pageSize, pageNumber, - sortBy == null ? null : sortBy.getOriginalValue(), direction.name()), HttpStatus.OK); - } - } - - @PreAuthorize("hasPermission(#sampleListId, 'SampleListId', T(org.cbioportal.utils.security.AccessLevel).READ)") - @RequestMapping(value = "/sample-lists/{sampleListId}", method = RequestMethod.GET, - produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "Get sample list") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(schema = @Schema(implementation = SampleList.class))) - public ResponseEntity getSampleList( - @Parameter(required = true, description = "Sample List ID e.g. acc_tcga_all") - @PathVariable String sampleListId) throws SampleListNotFoundException { - - return new ResponseEntity<>(sampleListService.getSampleList(sampleListId), HttpStatus.OK); - } - - @PreAuthorize("hasPermission(#studyId, 'CancerStudyId', T(org.cbioportal.utils.security.AccessLevel).READ)") - @RequestMapping(value = "/studies/{studyId}/sample-lists", method = RequestMethod.GET, - produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "Get all sample lists in a study") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(array = @ArraySchema(schema = @Schema(implementation = SampleList.class)))) - public ResponseEntity> getAllSampleListsInStudy( - @Parameter(required = true, description = "Study ID e.g. acc_tcga") - @PathVariable String studyId, - @Parameter(description = "Level of detail of the response") - @RequestParam(defaultValue = "SUMMARY") Projection projection, - @Parameter(description = "Page size of the result list") - @Max(PagingConstants.MAX_PAGE_SIZE) - @Min(PagingConstants.MIN_PAGE_SIZE) - @RequestParam(defaultValue = PagingConstants.DEFAULT_PAGE_SIZE) Integer pageSize, - @Parameter(description = "Page number of the result list") - @Min(PagingConstants.MIN_PAGE_NUMBER) - @RequestParam(defaultValue = PagingConstants.DEFAULT_PAGE_NUMBER) Integer pageNumber, - @Parameter(description = "Name of the property that the result list is sorted by") - @RequestParam(required = false) SampleListSortBy sortBy, - @Parameter(description = "Direction of the sort") - @RequestParam(defaultValue = "ASC") Direction direction) throws StudyNotFoundException { - - if (projection == Projection.META) { - HttpHeaders responseHeaders = new HttpHeaders(); - responseHeaders.add(HeaderKeyConstants.TOTAL_COUNT, sampleListService - .getMetaSampleListsInStudy(studyId).getTotalCount().toString()); - return new ResponseEntity<>(responseHeaders, HttpStatus.OK); - } else { - return new ResponseEntity<>( - sampleListService.getAllSampleListsInStudy(studyId, projection.name(), pageSize, pageNumber, - sortBy == null ? null : sortBy.getOriginalValue(), direction.name()), HttpStatus.OK); - } - } - - @PreAuthorize("hasPermission(#sampleListId, 'SampleListId', T(org.cbioportal.utils.security.AccessLevel).READ)") - @RequestMapping(value = "/sample-lists/{sampleListId}/sample-ids", method = RequestMethod.GET, - produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "Get all sample IDs in a sample list") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(array = @ArraySchema(schema = @Schema(implementation = String.class)))) - public ResponseEntity> getAllSampleIdsInSampleList( - @Parameter(required = true, description = "Sample List ID e.g. acc_tcga_all") - @PathVariable String sampleListId) throws SampleListNotFoundException { - - return new ResponseEntity<>(sampleListService.getAllSampleIdsInSampleList(sampleListId), HttpStatus.OK); - } - - @PreAuthorize("hasPermission(#sampleListIds, 'Collection', T(org.cbioportal.utils.security.AccessLevel).READ)") - @RequestMapping(value = "/sample-lists/fetch", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE, - produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "Fetch sample lists by ID") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(array = @ArraySchema(schema = @Schema(implementation = SampleList.class)))) - public ResponseEntity> fetchSampleLists( - @Parameter(required = true, description = "List of sample list IDs") - @Size(min = 1, max = PagingConstants.MAX_PAGE_SIZE) - @RequestBody List sampleListIds, - @Parameter(description = "Level of detail of the response") - @RequestParam(defaultValue = "SUMMARY") Projection projection) { - - return new ResponseEntity<>(sampleListService.fetchSampleLists(sampleListIds, projection.name()), HttpStatus.OK); - } -} diff --git a/src/main/java/org/cbioportal/web/ServerStatusController.java b/src/main/java/org/cbioportal/web/ServerStatusController.java deleted file mode 100644 index 4aa7963a63b..00000000000 --- a/src/main/java/org/cbioportal/web/ServerStatusController.java +++ /dev/null @@ -1,38 +0,0 @@ -package org.cbioportal.web; - -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.media.Content; -import io.swagger.v3.oas.annotations.media.Schema; -import io.swagger.v3.oas.annotations.responses.ApiResponse; -import io.swagger.v3.oas.annotations.tags.Tag; -import org.cbioportal.service.ServerStatusService; -import org.cbioportal.service.impl.ServerStatusServiceImpl.ServerStatusMessage; -import org.cbioportal.web.config.annotation.PublicApi; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestMethod; -import org.springframework.web.bind.annotation.RestController; - - -@PublicApi -@RestController -@Validated -@Tag(name = "Server running status", description = "This end point does not require authentication") -public class ServerStatusController { - - @Autowired - private ServerStatusService serverStatusService; - - @RequestMapping(value = "/api/health", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "Get the running status of the server") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(schema = @Schema(implementation = ServerStatusMessage.class))) - public ResponseEntity getServerStatus() { - return new ResponseEntity<>(serverStatusService.getServerStatus(), HttpStatus.OK); - } - -} diff --git a/src/main/java/org/cbioportal/web/SessionServiceController.java b/src/main/java/org/cbioportal/web/SessionServiceController.java deleted file mode 100644 index d2ad7499c1f..00000000000 --- a/src/main/java/org/cbioportal/web/SessionServiceController.java +++ /dev/null @@ -1,603 +0,0 @@ -package org.cbioportal.web; - -import com.fasterxml.jackson.annotation.JsonInclude.Include; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.DeserializationFeature; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.google.common.collect.ImmutableMap; -import com.mongodb.BasicDBObject; -import io.swagger.v3.oas.annotations.media.ArraySchema; -import io.swagger.v3.oas.annotations.media.Content; -import io.swagger.v3.oas.annotations.media.Schema; -import io.swagger.v3.oas.annotations.responses.ApiResponse; -import jakarta.servlet.http.HttpServletResponse; -import jakarta.validation.constraints.Size; -import org.cbioportal.service.util.CustomAttributeWithData; -import org.cbioportal.service.util.CustomDataSession; -import org.cbioportal.service.util.SessionServiceRequestHandler; -import org.cbioportal.utils.removeme.Session; -import org.cbioportal.web.parameter.CustomGeneList; -import org.cbioportal.web.parameter.CustomGeneListData; -import org.cbioportal.web.parameter.PageSettings; -import org.cbioportal.web.parameter.PageSettingsData; -import org.cbioportal.web.parameter.PageSettingsIdentifier; -import org.cbioportal.web.parameter.PagingConstants; -import org.cbioportal.web.parameter.ResultsPageSettings; -import org.cbioportal.web.parameter.SampleIdentifier; -import org.cbioportal.web.parameter.SessionPage; -import org.cbioportal.web.parameter.StudyPageSettings; -import org.cbioportal.web.parameter.VirtualStudy; -import org.cbioportal.web.parameter.VirtualStudyData; -import org.cbioportal.web.parameter.VirtualStudySamples; -import org.cbioportal.web.util.StudyViewFilterApplier; -import org.json.simple.JSONObject; -import org.json.simple.parser.JSONParser; -import org.json.simple.parser.ParseException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.core.ParameterizedTypeReference; -import org.springframework.http.HttpEntity; -import org.springframework.http.HttpMethod; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.security.authentication.AnonymousAuthenticationToken; -import org.springframework.security.core.Authentication; -import org.springframework.security.core.context.SecurityContextHolder; -import org.springframework.stereotype.Controller; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestMethod; -import org.springframework.web.client.RestTemplate; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.Set; -import java.util.regex.Pattern; -import java.util.stream.Collectors; - -import static org.cbioportal.web.PublicVirtualStudiesController.ALL_USERS; - -@Controller -@RequestMapping("/api/session") -public class SessionServiceController { - - private static final Logger LOG = LoggerFactory.getLogger(SessionServiceController.class); - - private static final String QUERY_OPERATOR_ALL = "$all"; - private static final String QUERY_OPERATOR_SIZE = "$size"; - private static final String QUERY_OPERATOR_AND = "$and"; - - SessionServiceRequestHandler sessionServiceRequestHandler; - - private ObjectMapper sessionServiceObjectMapper; - - private StudyViewFilterApplier studyViewFilterApplier; - - public SessionServiceController(SessionServiceRequestHandler sessionServiceRequestHandler, - ObjectMapper sessionServiceObjectMapper, - StudyViewFilterApplier studyViewFilterApplier) { - this.sessionServiceRequestHandler = sessionServiceRequestHandler; - this.sessionServiceObjectMapper = sessionServiceObjectMapper; - this.studyViewFilterApplier = studyViewFilterApplier; - } - - @Value("${session.service.url:}") - private String sessionServiceURL; - - private static Map> pageToSettingsDataClass = ImmutableMap.of( - SessionPage.study_view, StudyPageSettings.class, - SessionPage.results_view, ResultsPageSettings.class - ); - - private boolean isAuthorized() { - Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); - return !(authentication == null || (authentication instanceof AnonymousAuthenticationToken)); - } - - private String userName() { - return SecurityContextHolder.getContext().getAuthentication().getName(); - } - - private boolean sameOrigin(Set set1, Set set2) { - if (set1 == null || set2 == null) { - return false; - } - if (set1.size() != set2.size()) { - return false; - } - return set1.containsAll(set2); - } - - private PageSettings getRecentlyUpdatePageSettings(String query) { - - RestTemplate restTemplate = new RestTemplate(); - - HttpEntity httpEntity = new HttpEntity(query, sessionServiceRequestHandler.getHttpHeaders()); - - ResponseEntity> responseEntity = restTemplate.exchange( - sessionServiceURL + Session.SessionType.settings + "/query/fetch", - HttpMethod.POST, - httpEntity, - new ParameterizedTypeReference>() {}); - - List sessions = responseEntity.getBody(); - - // sort last updated in descending order - sessions.sort((PageSettings s1, PageSettings s2) -> s1.getData().getLastUpdated() > s2.getData() - .getLastUpdated() ? -1 : 1); - - return sessions.isEmpty() ? null : sessions.get(0); - } - - private ResponseEntity addSession( - Session.SessionType type, - Optional operation, - JSONObject body - ) { - try { - HttpEntity httpEntity; - if (type.equals(Session.SessionType.virtual_study) || type.equals(Session.SessionType.group)) { - // JSON from file to Object - VirtualStudyData virtualStudyData = sessionServiceObjectMapper.readValue(body.toString(), VirtualStudyData.class); - //TODO sanitize what's supplied. e.g. anonymous user should not specify the users field! - - if (isAuthorized()) { - String userName = userName(); - if (userName.equals(ALL_USERS)) { - throw new IllegalStateException("Illegal username " + ALL_USERS + " for assigning virtual studies."); - } - virtualStudyData.setOwner(userName); - if ((operation.isPresent() && operation.get().equals(SessionOperation.save)) - || type.equals(Session.SessionType.group)) { - virtualStudyData.setUsers(Collections.singleton(userName)); - } - } - - // use basic authentication for session service if set - httpEntity = new HttpEntity<>(virtualStudyData, sessionServiceRequestHandler.getHttpHeaders()); - } else if (type.equals(Session.SessionType.settings)) { - if (!(isAuthorized())) { - return new ResponseEntity<>(HttpStatus.SERVICE_UNAVAILABLE); - } - Class pageDataClass = pageToSettingsDataClass.get( - SessionPage.valueOf((String) body.get("page")) - ); - PageSettingsData pageSettings = sessionServiceObjectMapper.readValue( - body.toString(), - pageDataClass - ); - pageSettings.setOwner(userName()); - httpEntity = new HttpEntity<>(pageSettings, sessionServiceRequestHandler.getHttpHeaders()); - - } else if(type.equals(Session.SessionType.custom_data)) { - // JSON from file to Object - CustomAttributeWithData customData = sessionServiceObjectMapper.readValue(body.toString(), CustomAttributeWithData.class); - - if (isAuthorized()) { - customData.setOwner(userName()); - customData.setUsers(Collections.singleton(userName())); - } - - // use basic authentication for session service if set - httpEntity = new HttpEntity<>(customData, sessionServiceRequestHandler.getHttpHeaders()); - } else if (type.equals(Session.SessionType.custom_gene_list)) { - if (!(isAuthorized())) { - return new ResponseEntity<>(HttpStatus.SERVICE_UNAVAILABLE); - } - CustomGeneListData customGeneListData = sessionServiceObjectMapper.readValue(body.toString(), CustomGeneListData.class); - customGeneListData.setUsers(Collections.singleton(userName())); - httpEntity = new HttpEntity<>(customGeneListData, sessionServiceRequestHandler.getHttpHeaders()); - } else { - httpEntity = new HttpEntity<>(body, sessionServiceRequestHandler.getHttpHeaders()); - } - // returns {"id":"5799648eef86c0e807a2e965"} - // using HashMap because converter is MappingJackson2HttpMessageConverter - // (Jackson 2 is on classpath) - // was String when default converter StringHttpMessageConverter was used - RestTemplate restTemplate = new RestTemplate(); - ResponseEntity resp = restTemplate.exchange(sessionServiceURL + type, HttpMethod.POST, httpEntity, - Session.class); - - return new ResponseEntity<>(resp.getBody(), resp.getStatusCode()); - - } catch (IOException e) { - LOG.error("Error occurred", e); - return new ResponseEntity<>(HttpStatus.BAD_REQUEST); - } - } - - @RequestMapping(value = "/{type}/{id}", method = RequestMethod.GET) - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(schema = @Schema(implementation = Session.class))) - public ResponseEntity getSession(@PathVariable Session.SessionType type, @PathVariable String id) { - - try { - String sessionDataJson = sessionServiceRequestHandler.getSessionDataJson(type, id); - Session session; - switch (type) { - case virtual_study: - VirtualStudy virtualStudy = sessionServiceObjectMapper.readValue(sessionDataJson, VirtualStudy.class); - VirtualStudyData virtualStudyData = virtualStudy.getData(); - if (Boolean.TRUE.equals(virtualStudyData.getDynamic())) { - populateVirtualStudySamples(virtualStudyData); - } - session = virtualStudy; - break; - case settings: - session = sessionServiceObjectMapper.readValue(sessionDataJson, PageSettings.class); - break; - case custom_data: - session = sessionServiceObjectMapper.readValue(sessionDataJson, CustomDataSession.class); - break; - case custom_gene_list: - session = sessionServiceObjectMapper.readValue(sessionDataJson, CustomGeneList.class); - break; - default: - session = sessionServiceObjectMapper.readValue(sessionDataJson, Session.class); - } - return new ResponseEntity<>(session, HttpStatus.OK); - } catch (Exception exception) { - LOG.error("Error occurred", exception); - return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR); - } - } - - /** - * This method populates the `virtualStudyData` object with a new set of sample IDs retrieved as the result of executing a query based on virtual study view filters. - * It first applies the filters defined within the study view, runs the query to fetch the relevant sample IDs, and then updates the virtualStudyData to reflect these fresh results. - * This ensures that the virtual study contains the latest sample IDs. - * @param virtualStudyData - */ - private void populateVirtualStudySamples(VirtualStudyData virtualStudyData) { - List sampleIdentifiers = studyViewFilterApplier.apply(virtualStudyData.getStudyViewFilter()); - Set virtualStudySamples = extractVirtualStudySamples(sampleIdentifiers); - virtualStudyData.setStudies(virtualStudySamples); - } - - /** - * Transforms list of sample identifiers to set of virtual study samples - * @param sampleIdentifiers - */ - private Set extractVirtualStudySamples(List sampleIdentifiers) { - Map> sampleIdsByStudyId = groupSampleIdsByStudyId(sampleIdentifiers); - return sampleIdsByStudyId.entrySet().stream().map(entry -> { - VirtualStudySamples vss = new VirtualStudySamples(); - vss.setId(entry.getKey()); - vss.setSamples(entry.getValue()); - return vss; - }).collect(Collectors.toSet()); - } - - /** - * Groups sample IDs by their study ID - * @param sampleIdentifiers - */ - private Map> groupSampleIdsByStudyId(List sampleIdentifiers) { - return sampleIdentifiers - .stream() - .collect( - Collectors.groupingBy( - SampleIdentifier::getStudyId, - Collectors.mapping(SampleIdentifier::getSampleId, Collectors.toSet()))); - } - - @RequestMapping(value = "/virtual_study", method = RequestMethod.GET) - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(array = @ArraySchema(schema = @Schema(implementation = VirtualStudy.class)))) - public ResponseEntity> getUserStudies() throws JsonProcessingException { - - if (sessionServiceRequestHandler.isSessionServiceEnabled() && isAuthorized()) { - try { - - BasicDBObject basicDBObject = new BasicDBObject(); - basicDBObject.put("data.users", Pattern.compile(userName(), Pattern.CASE_INSENSITIVE)); - - RestTemplate restTemplate = new RestTemplate(); - - HttpEntity httpEntity = new HttpEntity<>(basicDBObject.toString(), sessionServiceRequestHandler.getHttpHeaders()); - - ResponseEntity> responseEntity = restTemplate.exchange( - sessionServiceURL + Session.SessionType.virtual_study + "/query/fetch", - HttpMethod.POST, - httpEntity, - new ParameterizedTypeReference>() {}); - - List virtualStudyList = responseEntity.getBody(); - return new ResponseEntity<>(virtualStudyList, HttpStatus.OK); - } catch (Exception exception) { - LOG.error("Error occurred", exception); - return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR); - } - } - return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR); - } - - @RequestMapping(value = "/{type}", method = RequestMethod.POST) - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(schema = @Schema(implementation = Session.class))) - public ResponseEntity addSession(@PathVariable Session.SessionType type, @RequestBody JSONObject body) - throws IOException { - //FIXME? anonymous user can create sessions. Do we really want that? https://github.com/cBioPortal/cbioportal/issues/10843 - return addSession(type, Optional.empty(), body); - } - - @RequestMapping(value = "/virtual_study/save", method = RequestMethod.POST) - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(schema = @Schema(implementation = Session.class))) - public ResponseEntity addUserSavedVirtualStudy(@RequestBody JSONObject body) throws IOException { - //FIXME? anonymous user can create virtual studies. Do we really want that? https://github.com/cBioPortal/cbioportal/issues/10843 - return addSession(Session.SessionType.virtual_study, Optional.of(SessionOperation.save), body); - } - - @RequestMapping(value = "/{type:virtual_study|group|custom_data|custom_gene_list}/{operation}/{id}", method = RequestMethod.GET) - public void updateUsersInSession(@PathVariable Session.SessionType type, @PathVariable String id, - @PathVariable Operation operation, HttpServletResponse response) throws IOException { - - if (sessionServiceRequestHandler.isSessionServiceEnabled() && isAuthorized()) { - HttpEntity httpEntity; - if (type.equals(Session.SessionType.custom_data)) { - String virtualStudyStr = sessionServiceObjectMapper.writeValueAsString(getSession(type, id).getBody()); - CustomDataSession customDataSession = sessionServiceObjectMapper.readValue(virtualStudyStr, CustomDataSession.class); - CustomAttributeWithData customAttributeWithData = customDataSession.getData(); - Set users = customAttributeWithData.getUsers(); - updateUserList(operation, users); - customAttributeWithData.setUsers(users); - httpEntity = new HttpEntity<>(customAttributeWithData, sessionServiceRequestHandler.getHttpHeaders()); - } else if (type.equals(Session.SessionType.custom_gene_list)) { - String customGeneListStr = sessionServiceObjectMapper.writeValueAsString(getSession(type, id).getBody()); - CustomGeneList customGeneList = sessionServiceObjectMapper.readValue(customGeneListStr, CustomGeneList.class); - CustomGeneListData customGeneListData = customGeneList.getData(); - Set users = customGeneListData.getUsers(); - updateUserList(operation, users); - customGeneListData.setUsers(users); - httpEntity = new HttpEntity<>(customGeneListData, sessionServiceRequestHandler.getHttpHeaders()); - } else { - String virtualStudyStr = sessionServiceObjectMapper.writeValueAsString(getSession(type, id).getBody()); - VirtualStudy virtualStudy = sessionServiceObjectMapper.readValue(virtualStudyStr, VirtualStudy.class); - VirtualStudyData virtualStudyData = virtualStudy.getData(); - Set users = virtualStudyData.getUsers(); - updateUserList(operation, users); - virtualStudyData.setUsers(users); - httpEntity = new HttpEntity<>(virtualStudyData, sessionServiceRequestHandler.getHttpHeaders()); - } - - RestTemplate restTemplate = new RestTemplate(); - restTemplate.put(sessionServiceURL + type + "/" + id, httpEntity); - - response.sendError(HttpStatus.OK.value()); - } else { - response.sendError(HttpStatus.SERVICE_UNAVAILABLE.value()); - } - - } - - private void updateUserList(Operation operation, Set users) { - switch (operation) { - case add: { - users.add(userName()); - break; - } - case delete: { - users.remove(userName()); - break; - } - } - } - - @RequestMapping(value = "/groups/fetch", method = RequestMethod.POST) - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(array = @ArraySchema(schema = @Schema(implementation = VirtualStudy.class)))) - public ResponseEntity> fetchUserGroups( - @Size(min = 1, max = PagingConstants.MAX_PAGE_SIZE) @RequestBody List studyIds) throws IOException { - - if (sessionServiceRequestHandler.isSessionServiceEnabled() && isAuthorized()) { - // ignore origin studies order - // add $size to make sure origin studies is not a subset - List basicDBObjects = new ArrayList<>(); - basicDBObjects - .add(new BasicDBObject("data.users", Pattern.compile(userName(), Pattern.CASE_INSENSITIVE))); - basicDBObjects.add(new BasicDBObject("data.origin", - new BasicDBObject(QUERY_OPERATOR_ALL, studyIds))); - basicDBObjects.add(new BasicDBObject("data.origin", - new BasicDBObject(QUERY_OPERATOR_SIZE, studyIds.size()))); - - BasicDBObject queryDBObject = new BasicDBObject(QUERY_OPERATOR_AND, basicDBObjects); - - RestTemplate restTemplate = new RestTemplate(); - - HttpEntity httpEntity = new HttpEntity<>(queryDBObject.toString(), sessionServiceRequestHandler.getHttpHeaders()); - - ResponseEntity> responseEntity = restTemplate.exchange( - sessionServiceURL + Session.SessionType.group + "/query/fetch", - HttpMethod.POST, - httpEntity, - new ParameterizedTypeReference>() {}); - - return new ResponseEntity<>(responseEntity.getBody(), HttpStatus.OK); - - } - return new ResponseEntity<>(HttpStatus.SERVICE_UNAVAILABLE); - } - - @RequestMapping(value = "/settings", method = RequestMethod.POST) - public void updateUserPageSettings(@RequestBody PageSettingsData settingsData, HttpServletResponse response) { - - try { - ObjectMapper objectMapper = new ObjectMapper() - .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) - .setSerializationInclusion(Include.NON_NULL); - if (sessionServiceRequestHandler.isSessionServiceEnabled() && isAuthorized()) { - - List basicDBObjects = new ArrayList<>(); - basicDBObjects - .add(new BasicDBObject("data.owner", Pattern.compile(userName(), Pattern.CASE_INSENSITIVE))); - basicDBObjects.add(new BasicDBObject("data.origin", - new BasicDBObject(QUERY_OPERATOR_ALL, settingsData.getOrigin()))); - basicDBObjects.add(new BasicDBObject("data.origin", - new BasicDBObject(QUERY_OPERATOR_SIZE, settingsData.getOrigin().size()))); - basicDBObjects.add(new BasicDBObject("data.page", settingsData.getPage().name())); - - BasicDBObject queryDBObject = new BasicDBObject(QUERY_OPERATOR_AND, basicDBObjects); - - PageSettings pageSettings = getRecentlyUpdatePageSettings(queryDBObject.toString()); - - JSONParser parser = new JSONParser(); - JSONObject jsonObject = (JSONObject) parser.parse(objectMapper.writeValueAsString(settingsData)); - - if (pageSettings == null) { - addSession(Session.SessionType.settings, Optional.empty(), jsonObject); - } else { - updatedPageSettingSession(pageSettings, settingsData, response); - } - response.setStatus(HttpStatus.OK.value()); - } else { - response.setStatus(HttpStatus.SERVICE_UNAVAILABLE.value()); - } - } catch (IOException | ParseException e) { - LOG.error("Error occurred", e); - response.setStatus(HttpStatus.BAD_REQUEST.value()); - } - } - - // updates only allowed for type page settings session - private void updatedPageSettingSession( - PageSettings pageSettings, - @RequestBody PageSettingsData body, - HttpServletResponse response - ) throws IOException { - - if (isAuthorized()) { - - PageSettingsData pageSettingsData = pageSettings.getData(); - // only allow owner to update his session and see if the origin(studies) are same - if (userName().equals(pageSettingsData.getOwner()) && - sameOrigin(pageSettingsData.getOrigin(), body.getOrigin())) { - - body.setCreated(pageSettingsData.getCreated()); - body.setOwner(pageSettingsData.getOwner()); - body.setOrigin(pageSettingsData.getOrigin()); - - RestTemplate restTemplate = new RestTemplate(); - HttpEntity httpEntity = new HttpEntity<>(body, sessionServiceRequestHandler.getHttpHeaders()); - - Session.SessionType type = pageSettings.getType() == null ? Session.SessionType.settings : pageSettings.getType(); - restTemplate.put(sessionServiceURL + type + "/" + pageSettings.getId(), httpEntity); - response.setStatus(HttpStatus.OK.value()); - } else { - response.setStatus(HttpStatus.UNAUTHORIZED.value()); - } - } else { - response.setStatus(HttpStatus.SERVICE_UNAVAILABLE.value()); - } - } - - @RequestMapping(value = "/settings/fetch", method = RequestMethod.POST) - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(schema = @Schema(implementation = PageSettingsData.class))) - public ResponseEntity getPageSettings(@RequestBody PageSettingsIdentifier pageSettingsIdentifier) { - - try { - if (sessionServiceRequestHandler.isSessionServiceEnabled() && isAuthorized()) { - - List basicDBObjects = new ArrayList<>(); - basicDBObjects - .add(new BasicDBObject("data.owner", Pattern.compile(userName(), Pattern.CASE_INSENSITIVE))); - basicDBObjects.add(new BasicDBObject("data.origin", - new BasicDBObject(QUERY_OPERATOR_ALL, pageSettingsIdentifier.getOrigin()))); - basicDBObjects.add(new BasicDBObject("data.origin", - new BasicDBObject(QUERY_OPERATOR_SIZE, pageSettingsIdentifier.getOrigin().size()))); - basicDBObjects.add(new BasicDBObject("data.page", pageSettingsIdentifier.getPage().name())); - - BasicDBObject queryDBObject = new BasicDBObject(QUERY_OPERATOR_AND, basicDBObjects); - - PageSettings pageSettings = getRecentlyUpdatePageSettings(queryDBObject.toString()); - - return new ResponseEntity<>(pageSettings == null ? null : pageSettings.getData(), HttpStatus.OK); - } - return new ResponseEntity<>(HttpStatus.SERVICE_UNAVAILABLE); - } catch (Exception e) { - LOG.error("Error occurred", e); - return new ResponseEntity<>(HttpStatus.BAD_REQUEST); - } - } - - @RequestMapping(value = "/custom_data/fetch", method = RequestMethod.POST) - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(array = @ArraySchema(schema = @Schema(implementation = CustomDataSession.class)))) - public ResponseEntity> fetchCustomProperties( - @Size(min = 1, max = PagingConstants.MAX_PAGE_SIZE) @RequestBody List studyIds) throws IOException { - - if (sessionServiceRequestHandler.isSessionServiceEnabled() && isAuthorized()) { - - List basicDBObjects = new ArrayList<>(); - basicDBObjects.add(new BasicDBObject("data.users", Pattern.compile(userName(), Pattern.CASE_INSENSITIVE))); - basicDBObjects.add(new BasicDBObject("data.origin", new BasicDBObject(QUERY_OPERATOR_ALL, studyIds))); - basicDBObjects.add(new BasicDBObject("data.origin", new BasicDBObject(QUERY_OPERATOR_SIZE, studyIds.size()))); - - BasicDBObject queryDBObject = new BasicDBObject(QUERY_OPERATOR_AND, basicDBObjects); - - RestTemplate restTemplate = new RestTemplate(); - - HttpEntity httpEntity = new HttpEntity<>(queryDBObject.toString(), - sessionServiceRequestHandler.getHttpHeaders()); - - ResponseEntity> responseEntity = restTemplate.exchange( - sessionServiceURL + Session.SessionType.custom_data + "/query/fetch", - HttpMethod.POST, - httpEntity, - new ParameterizedTypeReference>() {}); - - return new ResponseEntity<>(responseEntity.getBody(), HttpStatus.OK); - - } - return new ResponseEntity<>(HttpStatus.SERVICE_UNAVAILABLE); - } - - @RequestMapping(value = "/custom_gene_list/save", method = RequestMethod.POST) - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(schema = @Schema(implementation = Session.class))) - public ResponseEntity addUserSavedCustomGeneList(@RequestBody JSONObject body) throws IOException { - return addSession(Session.SessionType.custom_gene_list, Optional.of(SessionOperation.save), body); - } - - @RequestMapping(value = "/custom_gene_list", method = RequestMethod.GET) - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(array = @ArraySchema(schema = @Schema(implementation = CustomGeneList.class)))) - public ResponseEntity> fetchCustomGeneList() throws IOException { - - if (sessionServiceRequestHandler.isSessionServiceEnabled() && isAuthorized()) { - - BasicDBObject basicDBObject = new BasicDBObject(); - basicDBObject.put("data.users", Pattern.compile(userName(), Pattern.CASE_INSENSITIVE)); - - RestTemplate restTemplate = new RestTemplate(); - - HttpEntity httpEntity = new HttpEntity<>(basicDBObject.toString(), sessionServiceRequestHandler.getHttpHeaders()); - - ResponseEntity> responseEntity = restTemplate.exchange( - sessionServiceURL + Session.SessionType.custom_gene_list + "/query/fetch", - HttpMethod.POST, - httpEntity, - new ParameterizedTypeReference>() {}); - - return new ResponseEntity<>(responseEntity.getBody(), HttpStatus.OK); - - } - return new ResponseEntity<>(HttpStatus.SERVICE_UNAVAILABLE); - } - -} - -enum Operation { - add, delete; -} - -enum SessionOperation { - save, share; -} diff --git a/src/main/java/org/cbioportal/web/SignificantCopyNumberRegionController.java b/src/main/java/org/cbioportal/web/SignificantCopyNumberRegionController.java deleted file mode 100644 index 48c4919003a..00000000000 --- a/src/main/java/org/cbioportal/web/SignificantCopyNumberRegionController.java +++ /dev/null @@ -1,81 +0,0 @@ -package org.cbioportal.web; - -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.media.ArraySchema; -import io.swagger.v3.oas.annotations.media.Content; -import io.swagger.v3.oas.annotations.media.Schema; -import io.swagger.v3.oas.annotations.responses.ApiResponse; -import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.validation.constraints.Max; -import jakarta.validation.constraints.Min; -import org.cbioportal.model.Gistic; -import org.cbioportal.service.SignificantCopyNumberRegionService; -import org.cbioportal.service.exception.StudyNotFoundException; -import org.cbioportal.web.config.annotation.InternalApi; -import org.cbioportal.web.parameter.Direction; -import org.cbioportal.web.parameter.HeaderKeyConstants; -import org.cbioportal.web.parameter.PagingConstants; -import org.cbioportal.web.parameter.Projection; -import org.cbioportal.web.parameter.sort.SignificantCopyNumberRegionSortBy; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.PathVariable; -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.bind.annotation.RestController; - -import java.util.List; - -@InternalApi -@RestController() -@RequestMapping("/api") -@Validated -@Tag(name = "Significant Copy Number Regions", description = " ") -public class SignificantCopyNumberRegionController { - - @Autowired - private SignificantCopyNumberRegionService significantCopyNumberRegionService; - - @PreAuthorize("hasPermission(#studyId, 'CancerStudyId', T(org.cbioportal.utils.security.AccessLevel).READ)") - @RequestMapping(value = "/studies/{studyId}/significant-copy-number-regions", method = RequestMethod.GET, - produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "Get significant copy number alteration regions in a study") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(array = @ArraySchema(schema = @Schema(implementation = Gistic.class)))) - public ResponseEntity> getSignificantCopyNumberRegions( - @Parameter(required = true, description = "Study ID e.g. acc_tcga") - @PathVariable String studyId, - @Parameter(description = "Level of detail of the response") - @RequestParam(defaultValue = "SUMMARY") Projection projection, - @Parameter(description = "Page size of the result list") - @Max(PagingConstants.MAX_PAGE_SIZE) - @Min(PagingConstants.MIN_PAGE_SIZE) - @RequestParam(defaultValue = PagingConstants.DEFAULT_PAGE_SIZE) Integer pageSize, - @Parameter(description = "Page number of the result list") - @Min(PagingConstants.MIN_PAGE_NUMBER) - @RequestParam(defaultValue = PagingConstants.DEFAULT_PAGE_NUMBER) Integer pageNumber, - @Parameter(description = "Name of the property that the result list is sorted by") - @RequestParam(required = false) SignificantCopyNumberRegionSortBy sortBy, - @Parameter(description = "Direction of the sort") - @RequestParam(defaultValue = "ASC") Direction direction) throws StudyNotFoundException { - - if (projection == Projection.META) { - HttpHeaders responseHeaders = new HttpHeaders(); - responseHeaders.add(HeaderKeyConstants.TOTAL_COUNT, - significantCopyNumberRegionService.getMetaSignificantCopyNumberRegions(studyId).getTotalCount() - .toString()); - return new ResponseEntity<>(responseHeaders, HttpStatus.OK); - } else { - return new ResponseEntity<>( - significantCopyNumberRegionService.getSignificantCopyNumberRegions(studyId, projection.name(), pageSize, - pageNumber, sortBy == null ? null : sortBy.getOriginalValue(), direction.name()), HttpStatus.OK); - } - } -} diff --git a/src/main/java/org/cbioportal/web/SignificantlyMutatedGenesController.java b/src/main/java/org/cbioportal/web/SignificantlyMutatedGenesController.java deleted file mode 100644 index 3a661feeae2..00000000000 --- a/src/main/java/org/cbioportal/web/SignificantlyMutatedGenesController.java +++ /dev/null @@ -1,80 +0,0 @@ -package org.cbioportal.web; - -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.media.ArraySchema; -import io.swagger.v3.oas.annotations.media.Content; -import io.swagger.v3.oas.annotations.media.Schema; -import io.swagger.v3.oas.annotations.responses.ApiResponse; -import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.validation.constraints.Max; -import jakarta.validation.constraints.Min; -import org.cbioportal.model.MutSig; -import org.cbioportal.service.SignificantlyMutatedGeneService; -import org.cbioportal.service.exception.StudyNotFoundException; -import org.cbioportal.web.config.annotation.InternalApi; -import org.cbioportal.web.parameter.Direction; -import org.cbioportal.web.parameter.HeaderKeyConstants; -import org.cbioportal.web.parameter.PagingConstants; -import org.cbioportal.web.parameter.Projection; -import org.cbioportal.web.parameter.sort.SignificantlyMutatedGeneSortBy; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.PathVariable; -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.bind.annotation.RestController; - -import java.util.List; - -@InternalApi -@RestController() -@RequestMapping("/api") -@Validated -@Tag(name = "Significantly Mutated Genes", description = " ") -public class SignificantlyMutatedGenesController { - - @Autowired - private SignificantlyMutatedGeneService significantlyMutatedGeneService; - - @PreAuthorize("hasPermission(#studyId, 'CancerStudyId', T(org.cbioportal.utils.security.AccessLevel).READ)") - @RequestMapping(value = "/studies/{studyId}/significantly-mutated-genes", method = RequestMethod.GET, - produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "Get significantly mutated genes in a study") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(array = @ArraySchema(schema = @Schema(implementation = MutSig.class)))) - public ResponseEntity> getSignificantlyMutatedGenes( - @Parameter(required = true, description = "Study ID e.g. acc_tcga") - @PathVariable String studyId, - @Parameter(description = "Level of detail of the response") - @RequestParam(defaultValue = "SUMMARY") Projection projection, - @Parameter(description = "Page size of the result list") - @Max(PagingConstants.MAX_PAGE_SIZE) - @Min(PagingConstants.MIN_PAGE_SIZE) - @RequestParam(defaultValue = PagingConstants.DEFAULT_PAGE_SIZE) Integer pageSize, - @Parameter(description = "Page number of the result list") - @Min(PagingConstants.MIN_PAGE_NUMBER) - @RequestParam(defaultValue = PagingConstants.DEFAULT_PAGE_NUMBER) Integer pageNumber, - @Parameter(description = "Name of the property that the result list is sorted by") - @RequestParam(required = false) SignificantlyMutatedGeneSortBy sortBy, - @Parameter(description = "Direction of the sort") - @RequestParam(defaultValue = "ASC") Direction direction) throws StudyNotFoundException { - - if (projection == Projection.META) { - HttpHeaders responseHeaders = new HttpHeaders(); - responseHeaders.add(HeaderKeyConstants.TOTAL_COUNT, - significantlyMutatedGeneService.getMetaSignificantlyMutatedGenes(studyId).getTotalCount().toString()); - return new ResponseEntity<>(responseHeaders, HttpStatus.OK); - } else { - return new ResponseEntity<>( - significantlyMutatedGeneService.getSignificantlyMutatedGenes(studyId, projection.name(), pageSize, - pageNumber, sortBy == null ? null : sortBy.getOriginalValue(), direction.name()), HttpStatus.OK); - } - } -} diff --git a/src/main/java/org/cbioportal/web/StaticDataTimestampController.java b/src/main/java/org/cbioportal/web/StaticDataTimestampController.java deleted file mode 100644 index 39f3d5da978..00000000000 --- a/src/main/java/org/cbioportal/web/StaticDataTimestampController.java +++ /dev/null @@ -1,40 +0,0 @@ -package org.cbioportal.web; - -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.media.Content; -import io.swagger.v3.oas.annotations.media.Schema; -import io.swagger.v3.oas.annotations.responses.ApiResponse; -import io.swagger.v3.oas.annotations.tags.Tag; -import org.cbioportal.service.StaticDataTimestampService; -import org.cbioportal.web.config.annotation.InternalApi; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestMethod; -import org.springframework.web.bind.annotation.RestController; - -import java.util.Arrays; -import java.util.List; -import java.util.Map; - -@InternalApi -@RestController -@Validated -@Tag(name = "Timestamps", description = " ") -public class StaticDataTimestampController { - public static final List TIMESTAMP_TABLES = Arrays.asList("gene", "reference_genome_gene"); - @Autowired - private StaticDataTimestampService service; - - @RequestMapping(value = "/api/timestamps", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "Get the last time each static resource was updated") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(schema = @Schema(implementation = Object.class))) - public ResponseEntity> getAllTimestamps() { - return new ResponseEntity<>(service.getTimestamps(TIMESTAMP_TABLES), HttpStatus.OK); - } - -} diff --git a/src/main/java/org/cbioportal/web/StructuralVariantController.java b/src/main/java/org/cbioportal/web/StructuralVariantController.java deleted file mode 100644 index 69e03bf3303..00000000000 --- a/src/main/java/org/cbioportal/web/StructuralVariantController.java +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright (c) 2018 The Hyve B.V. - * This code is licensed under the GNU Affero General Public License (AGPL), - * version 3, or (at your option) any later version. - */ - -/* - * This file is part of cBioPortal. - * - * cBioPortal is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -package org.cbioportal.web; - -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.media.ArraySchema; -import io.swagger.v3.oas.annotations.media.Content; -import io.swagger.v3.oas.annotations.media.Schema; -import io.swagger.v3.oas.annotations.responses.ApiResponse; -import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.validation.Valid; -import org.cbioportal.model.StructuralVariant; -import org.cbioportal.service.StructuralVariantService; -import org.cbioportal.web.config.InternalApiTags; -import org.cbioportal.web.config.annotation.InternalApi; -import org.cbioportal.web.parameter.StructuralVariantFilter; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.RequestAttribute; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestMethod; -import org.springframework.web.bind.annotation.RestController; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; - -@InternalApi -@RestController() -@RequestMapping("/api") -@Validated -@Tag(name = InternalApiTags.STRUCTURAL_VARIANTS, description = " ") -public class StructuralVariantController { - @Autowired - private StructuralVariantService structuralVariantService; - - @PreAuthorize("hasPermission(#involvedCancerStudies, 'Collection', T(org.cbioportal.utils.security.AccessLevel).READ)") - @RequestMapping(value = "/structural-variant/fetch", method = RequestMethod.POST, - consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "Fetch structural variants for entrezGeneIds and molecularProfileIds or sampleMolecularIdentifiers") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(array = @ArraySchema(schema = @Schema(implementation = StructuralVariant.class)))) - public ResponseEntity> fetchStructuralVariants( - @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface - @RequestAttribute(required = false, value = "involvedCancerStudies") Collection involvedCancerStudies, - @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface - @Valid @RequestAttribute(required = false, value = "interceptedStructuralVariantFilter") StructuralVariantFilter interceptedStructuralVariantFilter, - @Parameter(required = true, description = "List of entrezGeneIds, structural variant queries and molecularProfileIds or sampleMolecularIdentifiers") - @Valid @RequestBody(required = false) StructuralVariantFilter structuralVariantFilter) { - - List molecularProfileIds = new ArrayList<>(); - List sampleIds = new ArrayList<>(); - - if (interceptedStructuralVariantFilter.getSampleMolecularIdentifiers() != null) { - interceptedStructuralVariantFilter - .getSampleMolecularIdentifiers() - .forEach(sampleMolecularIdentifier -> { - sampleIds.add(sampleMolecularIdentifier.getSampleId()); - molecularProfileIds.add(sampleMolecularIdentifier.getMolecularProfileId()); - - }); - } else { - molecularProfileIds.addAll(interceptedStructuralVariantFilter.getMolecularProfileIds()); - } - List structuralVariantList = structuralVariantService.fetchStructuralVariants( - molecularProfileIds, - sampleIds, - interceptedStructuralVariantFilter.getEntrezGeneIds(), - interceptedStructuralVariantFilter.getStructuralVariantQueries() - ); - - return new ResponseEntity<>(structuralVariantList, HttpStatus.OK); - - } -} diff --git a/src/main/java/org/cbioportal/web/StudyController.java b/src/main/java/org/cbioportal/web/StudyController.java deleted file mode 100644 index 253b591719d..00000000000 --- a/src/main/java/org/cbioportal/web/StudyController.java +++ /dev/null @@ -1,218 +0,0 @@ -package org.cbioportal.web; - -import com.fasterxml.jackson.core.JsonParseException; -import com.fasterxml.jackson.databind.JsonMappingException; -import com.fasterxml.jackson.databind.ObjectMapper; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.media.ArraySchema; -import io.swagger.v3.oas.annotations.media.Content; -import io.swagger.v3.oas.annotations.media.Schema; -import io.swagger.v3.oas.annotations.responses.ApiResponse; -import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.annotation.PostConstruct; -import jakarta.validation.constraints.Max; -import jakarta.validation.constraints.Min; -import jakarta.validation.constraints.Size; -import org.cbioportal.model.CancerStudy; -import org.cbioportal.model.CancerStudyTags; -import org.cbioportal.service.StudyService; -import org.cbioportal.service.exception.StudyNotFoundException; -import org.cbioportal.utils.security.AccessLevel; -import org.cbioportal.utils.security.PortalSecurityConfig; -import org.cbioportal.web.config.PublicApiTags; -import org.cbioportal.web.config.annotation.PublicApi; -import org.cbioportal.web.parameter.Direction; -import org.cbioportal.web.parameter.HeaderKeyConstants; -import org.cbioportal.web.parameter.PagingConstants; -import org.cbioportal.web.parameter.Projection; -import org.cbioportal.web.parameter.sort.StudySortBy; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.security.access.prepost.PreFilter; -import org.springframework.security.core.Authentication; -import org.springframework.security.core.context.SecurityContextHolder; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RequestBody; -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.bind.annotation.RestController; - -import java.io.IOException; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -@PublicApi -@RestController() -@RequestMapping("/api") -@Validated -@Tag(name = PublicApiTags.STUDIES, description = " ") -public class StudyController { - - @Value("${app.name:unknown}") - private String appName; - - @Value("${authenticate}") - private String authenticate; - - @Value("${skin.home_page.show_unauthorized_studies:false}") - private boolean showUnauthorizedStudiesOnHomePage; - - @Autowired - private StudyService studyService; - - // This is a stop-gap solution because this endpoint needs caching - // Right now this method has spontaneous performance problems - // for the default query. We felt the best stop gap would be - // to just manually cache that one response. - private static List defaultResponse; - - @PostConstruct - private void warmDefaultResponseCache() { - if (!PortalSecurityConfig.userAuthorizationEnabled(authenticate)) { - defaultResponse = studyService.getAllStudies( - null, Projection.SUMMARY.name(), - 10000000, 0, - null, Direction.ASC.name(), null,AccessLevel.READ); - } - } - - @RequestMapping(value = "/studies", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "Get all studies") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(array = @ArraySchema(schema = @Schema(implementation = CancerStudy.class)))) - public ResponseEntity> getAllStudies( - @Parameter(description = "Search keyword that applies to name and cancer type of the studies") - @RequestParam(required = false) String keyword, - @Parameter(description = "Level of detail of the response") - @RequestParam(defaultValue = "SUMMARY") Projection projection, - @Parameter(description = "Page size of the result list") - @Max(PagingConstants.MAX_PAGE_SIZE) - @Min(PagingConstants.MIN_PAGE_SIZE) - @RequestParam(defaultValue = PagingConstants.DEFAULT_PAGE_SIZE) Integer pageSize, - @Parameter(description = "Page number of the result list") - @Min(PagingConstants.MIN_PAGE_NUMBER) - @RequestParam(defaultValue = PagingConstants.DEFAULT_PAGE_NUMBER) Integer pageNumber, - @Parameter(description = "Name of the property that the result list is sorted by") - @RequestParam(required = false) StudySortBy sortBy, - @Parameter(description = "Direction of the sort") - @RequestParam(defaultValue = "ASC") Direction direction) - { - - Authentication authentication = null; - // Only use this feature on the public portal and make sure it is never used - // on portals using auth, as in auth setting, different users will have different - // results. - if (!PortalSecurityConfig.userAuthorizationEnabled(authenticate) - && appName.equals("public-portal") - && keyword == null - && projection == Projection.SUMMARY - && pageSize == 10000000 - && pageNumber == 0 - && sortBy == null - && direction == Direction.ASC) { - return new ResponseEntity<>(defaultResponse, HttpStatus.OK); - } - else - authentication = SecurityContextHolder.getContext().getAuthentication(); - - if (projection == Projection.META) { - HttpHeaders responseHeaders = new HttpHeaders(); - responseHeaders.add(HeaderKeyConstants.TOTAL_COUNT, studyService.getMetaStudies(keyword).getTotalCount() - .toString()); - return new ResponseEntity<>(responseHeaders, HttpStatus.OK); - } else { - return new ResponseEntity<>( - studyService.getAllStudies(keyword, projection.name(), pageSize, pageNumber, - sortBy == null ? null : sortBy.getOriginalValue(), direction.name(), authentication, getAccessLevel()), HttpStatus.OK); - } - } - - @PreAuthorize("hasPermission(#studyId, 'CancerStudyId', T(org.cbioportal.utils.security.AccessLevel).READ)") - @RequestMapping(value = "/studies/{studyId}", method = RequestMethod.GET, - produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "Get a study") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content( schema = @Schema(implementation = CancerStudy.class))) - public ResponseEntity getStudy( - @Parameter(required = true, description = "Study ID e.g. acc_tcga") - @PathVariable String studyId) throws StudyNotFoundException { - - return new ResponseEntity<>(studyService.getStudy(studyId), HttpStatus.OK); - } - - @PreAuthorize("hasPermission(#studyIds, 'Collection', T(org.cbioportal.utils.security.AccessLevel).READ)") - @RequestMapping(value = "/studies/fetch", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE, - produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "Fetch studies by IDs") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(array = @ArraySchema(schema = @Schema(implementation = CancerStudy.class)))) - public ResponseEntity> fetchStudies( - @Parameter(required = true, description = "List of Study IDs") - @Size(min = 1, max = PagingConstants.MAX_PAGE_SIZE) - @RequestBody List studyIds, - @Parameter(description = "Level of detail of the response") - @RequestParam(defaultValue = "SUMMARY") Projection projection) { - - if (projection == Projection.META) { - HttpHeaders responseHeaders = new HttpHeaders(); - responseHeaders.add(HeaderKeyConstants.TOTAL_COUNT, studyService.fetchMetaStudies(studyIds).getTotalCount() - .toString()); - return new ResponseEntity<>(responseHeaders, HttpStatus.OK); - } else { - return new ResponseEntity<>( - studyService.fetchStudies(studyIds, projection.name()), HttpStatus.OK); - } - - } - - @RequestMapping(value = "/studies/{studyId}/tags", method = RequestMethod.GET, - produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "Get the tags of a study") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(schema = @Schema(implementation = Object.class))) - public ResponseEntity getTags( - @Parameter(required = true, description = "Study ID e.g. acc_tcga") - @PathVariable String studyId) throws JsonParseException, JsonMappingException, - IOException { - - Map map = new HashMap(); - ObjectMapper mapper = new ObjectMapper(); - CancerStudyTags cancerStudyTags = studyService.getTags(studyId, getAccessLevel()); - if (cancerStudyTags != null) { //If tags is null an empty map is returned - map = mapper.readValue(cancerStudyTags.getTags(), Map.class); - } - - return new ResponseEntity<>(map, HttpStatus.OK); - } - - @PreAuthorize("hasPermission(#studyIds, 'Collection', T(org.cbioportal.utils.security.AccessLevel).READ)") - @PreFilter("hasPermission(#studyIds, 'Collection', T(org.cbioportal.utils.security.AccessLevel).READ)") - @RequestMapping(value = "/studies/tags/fetch", method = RequestMethod.POST, - produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "Get the study tags by IDs") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(array = @ArraySchema(schema = @Schema(implementation = CancerStudyTags.class)))) - public ResponseEntity> getTagsForMultipleStudies( - @Parameter(required = true, description = "List of Study IDs") - @RequestBody List studyIds - ) { - - List cancerStudyTags = studyService.getTagsForMultipleStudies(studyIds); - - return new ResponseEntity<>(cancerStudyTags, HttpStatus.OK); - } - - private AccessLevel getAccessLevel() { - return PortalSecurityConfig.userAuthorizationEnabled(authenticate) - && showUnauthorizedStudiesOnHomePage ? AccessLevel.LIST : AccessLevel.READ; - } -} diff --git a/src/main/java/org/cbioportal/web/StudyViewController.java b/src/main/java/org/cbioportal/web/StudyViewController.java deleted file mode 100644 index 90e53af20b7..00000000000 --- a/src/main/java/org/cbioportal/web/StudyViewController.java +++ /dev/null @@ -1,1226 +0,0 @@ -package org.cbioportal.web; - -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.media.ArraySchema; -import io.swagger.v3.oas.annotations.media.Content; -import io.swagger.v3.oas.annotations.media.Schema; -import io.swagger.v3.oas.annotations.responses.ApiResponse; -import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.validation.Valid; -import jakarta.validation.constraints.Max; -import jakarta.validation.constraints.Min; -import org.apache.commons.collections4.CollectionUtils; -import org.apache.commons.lang3.math.NumberUtils; -import org.apache.commons.lang3.tuple.ImmutablePair; -import org.apache.commons.math3.stat.correlation.PearsonsCorrelation; -import org.apache.commons.math3.stat.correlation.SpearmansCorrelation; -import org.apache.commons.math3.util.Pair; -import org.cbioportal.model.AlterationCountByGene; -import org.cbioportal.model.AlterationCountByStructuralVariant; -import org.cbioportal.model.AlterationFilter; -import org.cbioportal.model.CaseListDataCount; -import org.cbioportal.model.ClinicalAttribute; -import org.cbioportal.model.ClinicalData; -import org.cbioportal.model.ClinicalDataBin; -import org.cbioportal.model.ClinicalDataCountItem; -import org.cbioportal.model.ClinicalEventTypeCount; -import org.cbioportal.model.ClinicalViolinPlotData; -import org.cbioportal.model.CopyNumberCountByGene; -import org.cbioportal.model.DensityPlotBin; -import org.cbioportal.model.DensityPlotData; -import org.cbioportal.model.GenericAssayDataBin; -import org.cbioportal.model.GenericAssayDataCountItem; -import org.cbioportal.model.GenomicDataBin; -import org.cbioportal.model.GenomicDataCount; -import org.cbioportal.model.GenomicDataCountItem; -import org.cbioportal.model.Patient; -import org.cbioportal.model.Sample; -import org.cbioportal.model.SampleClinicalDataCollection; -import org.cbioportal.model.SampleList; -import org.cbioportal.service.ClinicalAttributeService; -import org.cbioportal.service.ClinicalDataService; -import org.cbioportal.service.ClinicalEventService; -import org.cbioportal.service.PatientService; -import org.cbioportal.service.SampleListService; -import org.cbioportal.service.SampleService; -import org.cbioportal.service.StudyViewService; -import org.cbioportal.service.ViolinPlotService; -import org.cbioportal.service.exception.StudyNotFoundException; -import org.cbioportal.service.util.ClinicalAttributeUtil; -import org.cbioportal.web.config.annotation.InternalApi; -import org.cbioportal.web.parameter.ClinicalDataBinCountFilter; -import org.cbioportal.web.parameter.ClinicalDataBinFilter; -import org.cbioportal.web.parameter.ClinicalDataCountFilter; -import org.cbioportal.web.parameter.ClinicalDataFilter; -import org.cbioportal.web.parameter.DataBinMethod; -import org.cbioportal.web.parameter.Direction; -import org.cbioportal.web.parameter.GenericAssayDataBinCountFilter; -import org.cbioportal.web.parameter.GenericAssayDataCountFilter; -import org.cbioportal.web.parameter.GenericAssayDataFilter; -import org.cbioportal.web.parameter.GenomicDataBinCountFilter; -import org.cbioportal.web.parameter.GenomicDataCountFilter; -import org.cbioportal.web.parameter.GenomicDataFilter; -import org.cbioportal.web.parameter.HeaderKeyConstants; -import org.cbioportal.web.parameter.MutationOption; -import org.cbioportal.web.parameter.PagingConstants; -import org.cbioportal.web.parameter.Projection; -import org.cbioportal.web.parameter.SampleIdentifier; -import org.cbioportal.web.parameter.StudyViewFilter; -import org.cbioportal.web.util.ClinicalDataBinUtil; -import org.cbioportal.web.util.ClinicalDataFetcher; -import org.cbioportal.web.util.StudyViewFilterApplier; -import org.cbioportal.web.util.StudyViewFilterUtil; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.cache.annotation.Cacheable; -import org.springframework.context.ApplicationContext; -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.RequestAttribute; -import org.springframework.web.bind.annotation.RequestBody; -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.bind.annotation.RestController; - -import java.math.BigDecimal; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.function.Function; -import java.util.stream.Collectors; - -@InternalApi -@RestController() -@RequestMapping("/api") -@Validated -@Tag(name = "Study View", description = " ") -public class StudyViewController { - - public static final int CLINICAL_TAB_MAX_PAGE_SIZE = 1000000; - - @Autowired - private ApplicationContext applicationContext; - StudyViewController instance; - - @Autowired - private StudyViewFilterApplier studyViewFilterApplier; - @Autowired - private ClinicalDataService clinicalDataService; - @Autowired - private ClinicalDataFetcher clinicalDataFetcher; - @Autowired - private SampleService sampleService; - @Autowired - private PatientService patientService; - @Autowired - private StudyViewFilterUtil studyViewFilterUtil; - @Autowired - private ClinicalAttributeService clinicalAttributeService; - @Autowired - private ViolinPlotService violinPlotService; - @Autowired - private ClinicalAttributeUtil clinicalAttributeUtil; - @Autowired - private SampleListService sampleListService; - @Autowired - private StudyViewService studyViewService; - @Autowired - private ClinicalDataBinUtil clinicalDataBinUtil; - @Autowired - private ClinicalEventService clinicalEventService; - - private StudyViewController getInstance() { - if (Objects.isNull(instance)) { - instance = applicationContext.getBean(StudyViewController.class); - } - return instance; - } - @PreAuthorize("hasPermission(#involvedCancerStudies, 'Collection', T(org.cbioportal.utils.security.AccessLevel).READ)") - @RequestMapping(value = "/clinical-data-counts/fetch", method = RequestMethod.POST, - consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "Fetch clinical data counts by study view filter") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(array = @ArraySchema(schema = @Schema(implementation = ClinicalDataCountItem.class)))) - public ResponseEntity> fetchClinicalDataCounts( - @Parameter(required = true, description = "Clinical data count filter") - @Valid @RequestBody(required = false) ClinicalDataCountFilter clinicalDataCountFilter, - @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface - @RequestAttribute(required = false, value = "involvedCancerStudies") Collection involvedCancerStudies, - @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface. this attribute is needed for the @PreAuthorize tag above. - @Valid @RequestAttribute(required = false, value = "interceptedClinicalDataCountFilter") ClinicalDataCountFilter interceptedClinicalDataCountFilter) { - - List attributes = interceptedClinicalDataCountFilter.getAttributes(); - StudyViewFilter studyViewFilter = interceptedClinicalDataCountFilter.getStudyViewFilter(); - - if (attributes.size() == 1) { - studyViewFilterUtil.removeSelfFromFilter(attributes.get(0).getAttributeId(), studyViewFilter); - } - boolean unfilteredQuery = studyViewFilterUtil.isUnfilteredQuery(studyViewFilter); - List result = - this.getInstance().cachedClinicalDataCounts(interceptedClinicalDataCountFilter, - unfilteredQuery); - return new ResponseEntity<>(result, HttpStatus.OK); - - } - - @Cacheable( - cacheResolver = "staticRepositoryCacheOneResolver", - condition = "@cacheEnabledConfig.getEnabled() && #unfilteredQuery" - ) - public List cachedClinicalDataCounts(ClinicalDataCountFilter interceptedClinicalDataCountFilter, - boolean unfilteredQuery) { - List attributes = interceptedClinicalDataCountFilter.getAttributes(); - StudyViewFilter studyViewFilter = interceptedClinicalDataCountFilter.getStudyViewFilter(); - if (attributes.size() == 1) { - studyViewFilterUtil.removeSelfFromFilter(attributes.get(0).getAttributeId(), studyViewFilter); - } - List filteredSampleIdentifiers = studyViewFilterApplier.apply(studyViewFilter); - - if (filteredSampleIdentifiers.isEmpty()) { - return new ArrayList<>(); - } - List studyIds = new ArrayList<>(); - List sampleIds = new ArrayList<>(); - studyViewFilterUtil.extractStudyAndSampleIds(filteredSampleIdentifiers, studyIds, sampleIds); - - List result = clinicalDataService.fetchClinicalDataCounts( - studyIds, sampleIds, attributes.stream().map(a -> a.getAttributeId()).collect(Collectors.toList())); - - return result; - } - - @PreAuthorize("hasPermission(#involvedCancerStudies, 'Collection', T(org.cbioportal.utils.security.AccessLevel).READ)") - @RequestMapping(value = "/clinical-data-bin-counts/fetch", method = RequestMethod.POST, - consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "Fetch clinical data bin counts by study view filter") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(array = @ArraySchema(schema = @Schema(implementation = ClinicalDataBin.class)))) - public ResponseEntity> fetchClinicalDataBinCounts( - @Parameter(description = "Method for data binning") - @RequestParam(defaultValue = "DYNAMIC") DataBinMethod dataBinMethod, - @Parameter(required = true, description = "Clinical data bin count filter") - @Valid @RequestBody(required = false) ClinicalDataBinCountFilter clinicalDataBinCountFilter, - @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface - @RequestAttribute(required = false, value = "involvedCancerStudies") Collection involvedCancerStudies, - @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface. this attribute is needed for the @PreAuthorize tag above. - @Valid @RequestAttribute(required = false, value = "interceptedClinicalDataBinCountFilter") ClinicalDataBinCountFilter interceptedClinicalDataBinCountFilter - ) { - StudyViewFilter studyViewFilter = clinicalDataBinUtil.removeSelfFromFilter(interceptedClinicalDataBinCountFilter); - boolean unfilteredQuery = studyViewFilterUtil.isUnfilteredQuery(studyViewFilter); - List clinicalDataBins = - this.getInstance().cachableFetchClinicalDataBinCounts(dataBinMethod, - interceptedClinicalDataBinCountFilter, - unfilteredQuery); - - return new ResponseEntity<>(clinicalDataBins, HttpStatus.OK); - } - - @Cacheable( - cacheResolver = "staticRepositoryCacheOneResolver", - condition = "@cacheEnabledConfig.getEnabled() && #unfilteredQuery" - ) - public List cachableFetchClinicalDataBinCounts(DataBinMethod dataBinMethod, - ClinicalDataBinCountFilter interceptedClinicalDataBinCountFilter, - boolean unfilteredQuery - ) { - return clinicalDataBinUtil.fetchClinicalDataBinCounts( - dataBinMethod, - interceptedClinicalDataBinCountFilter, - // we don't need to remove filter again since we already did it in the previous step - false - ); - } - - @PreAuthorize("hasPermission(#involvedCancerStudies, 'Collection', T(org.cbioportal.utils.security.AccessLevel).READ)") - @RequestMapping(value = "/custom-data-bin-counts/fetch", method = RequestMethod.POST, - consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "Fetch custom data bin counts by study view filter") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(array = @ArraySchema(schema = @Schema(implementation = ClinicalDataBin.class)))) - public ResponseEntity> fetchCustomDataBinCounts( - @Parameter(description = "Method for data binning") - @RequestParam(defaultValue = "DYNAMIC") DataBinMethod dataBinMethod, - @Parameter(required = true, description = "Clinical data bin count filter") - @Valid @RequestBody(required = false) ClinicalDataBinCountFilter clinicalDataBinCountFilter, - @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface - @RequestAttribute(required = false, value = "involvedCancerStudies") Collection involvedCancerStudies, - @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface. this attribute is needed for the @PreAuthorize tag above. - @Valid @RequestAttribute(required = false, value = "interceptedClinicalDataBinCountFilter") ClinicalDataBinCountFilter interceptedClinicalDataBinCountFilter - ) { - // TODO code shared with ClinicalDataController.fetchCustomDataCounts - List attributes = interceptedClinicalDataBinCountFilter.getAttributes(); - StudyViewFilter studyViewFilter = interceptedClinicalDataBinCountFilter.getStudyViewFilter(); - if (attributes.size() == 1) { - studyViewFilterUtil.removeSelfCustomDataFromFilter(attributes.get(0).getAttributeId(), studyViewFilter); - } - List filteredSampleIdentifiers = studyViewFilterApplier.apply(studyViewFilter); - - if (filteredSampleIdentifiers.isEmpty()) { - return new ResponseEntity<>(new ArrayList<>(), HttpStatus.OK); - } - - final List clinicalDataBins = clinicalDataBinUtil.fetchCustomDataBinCounts(dataBinMethod, interceptedClinicalDataBinCountFilter, false); - - return new ResponseEntity<>(clinicalDataBins, HttpStatus.OK); - } - - @PreAuthorize("hasPermission(#involvedCancerStudies, 'Collection',T(org.cbioportal.utils.security.AccessLevel).READ)") - @RequestMapping(value = "/mutated-genes/fetch", method = RequestMethod.POST, - consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "Fetch mutated genes by study view filter") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(array = @ArraySchema(schema = @Schema(implementation = AlterationCountByGene.class)))) - public ResponseEntity> fetchMutatedGenes( - @Parameter(required = true, description = "Study view filter") - @Valid @RequestBody(required = false) StudyViewFilter studyViewFilter, - @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface - @RequestAttribute(required = false, value = "involvedCancerStudies") Collection involvedCancerStudies, - @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface. this attribute is needed for the @PreAuthorize tag above. - @Valid @RequestAttribute(required = false, value = "interceptedStudyViewFilter") StudyViewFilter interceptedStudyViewFilter - ) throws StudyNotFoundException { - boolean unfilteredQuery = studyViewFilterUtil.isUnfilteredQuery(interceptedStudyViewFilter); - List alterationCountByGenes = this.getInstance().cachedFetchMutatedGenes(interceptedStudyViewFilter, - unfilteredQuery); - return new ResponseEntity<>(alterationCountByGenes, HttpStatus.OK); - } - - @Cacheable( - cacheResolver = "staticRepositoryCacheOneResolver", - condition = "@cacheEnabledConfig.getEnabled() && #unfilteredQuery" - ) - public List cachedFetchMutatedGenes(StudyViewFilter interceptedStudyViewFilter, - boolean unfilteredQuery) throws StudyNotFoundException { - AlterationFilter annotationFilters = interceptedStudyViewFilter.getAlterationFilter(); - - List sampleIdentifiers = studyViewFilterApplier.apply(interceptedStudyViewFilter); - List alterationCountByGenes = new ArrayList<>(); - if(CollectionUtils.isNotEmpty(sampleIdentifiers)) { - List studyIds = new ArrayList<>(); - List sampleIds = new ArrayList<>(); - studyViewFilterUtil.extractStudyAndSampleIds(sampleIdentifiers, studyIds, sampleIds); - alterationCountByGenes = studyViewService.getMutationAlterationCountByGenes(studyIds, sampleIds, annotationFilters); - } - return alterationCountByGenes; - } - - @PreAuthorize("hasPermission(#involvedCancerStudies, 'Collection', T(org.cbioportal.utils.security.AccessLevel).READ)") - @RequestMapping(value = "/structuralvariant-genes/fetch", method = RequestMethod.POST, - consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "Fetch structural variant genes by study view filter") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(array = @ArraySchema(schema = @Schema(implementation = AlterationCountByGene.class)))) - public ResponseEntity> fetchStructuralVariantGenes( - @Parameter(required = true, description = "Study view filter") - @Valid @RequestBody(required = false) StudyViewFilter studyViewFilter, - @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface. This attribute is needed for the @PreAuthorize tag above. - @RequestAttribute(required = false, value = "involvedCancerStudies") Collection involvedCancerStudies, - @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface. - @Valid @RequestAttribute(required = false, value = "interceptedStudyViewFilter") StudyViewFilter interceptedStudyViewFilter - ) throws StudyNotFoundException { - - boolean unfilteredQuery = studyViewFilterUtil.isUnfilteredQuery(interceptedStudyViewFilter); - List alterationCountByGenes = - this.getInstance().cacheableFetchStructuralVariantGenes(interceptedStudyViewFilter, - unfilteredQuery); - return new ResponseEntity<>(alterationCountByGenes, HttpStatus.OK); - } - - @Cacheable( - cacheResolver = "staticRepositoryCacheOneResolver", - condition = "@cacheEnabledConfig.getEnabled() && #unfilteredQuery" - ) - public List cacheableFetchStructuralVariantGenes(StudyViewFilter interceptedStudyViewFilter, - boolean unfilteredQuery) throws StudyNotFoundException { - AlterationFilter annotationFilters = interceptedStudyViewFilter.getAlterationFilter(); - - List sampleIdentifiers = studyViewFilterApplier.apply(interceptedStudyViewFilter); - List alterationCountByGenes = new ArrayList<>(); - if(CollectionUtils.isNotEmpty(sampleIdentifiers)) { - List studyIds = new ArrayList<>(); - List sampleIds = new ArrayList<>(); - studyViewFilterUtil.extractStudyAndSampleIds(sampleIdentifiers, studyIds, sampleIds); - alterationCountByGenes = studyViewService.getStructuralVariantAlterationCountByGenes(studyIds, sampleIds, annotationFilters); - } - return alterationCountByGenes; - } - - @PreAuthorize("hasPermission(#involvedCancerStudies, 'Collection', T(org.cbioportal.utils.security.AccessLevel).READ)") - @RequestMapping(value = "/structuralvariant-counts/fetch", method = RequestMethod.POST, - consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "Fetch structural variant genes by study view filter") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(array = @ArraySchema(schema = @Schema(implementation = AlterationCountByStructuralVariant.class)))) - public ResponseEntity> fetchStructuralVariantCounts( - @Parameter(required = true, description = "Study view filter") - @Valid @RequestBody(required = false) StudyViewFilter studyViewFilter, - @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface. This attribute is needed for the @PreAuthorize tag above. - @RequestAttribute(required = false, value = "involvedCancerStudies") Collection involvedCancerStudies, - @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface. - @Valid @RequestAttribute(required = false, value = "interceptedStudyViewFilter") StudyViewFilter interceptedStudyViewFilter - ) throws StudyNotFoundException { - - boolean unfilteredQuery = studyViewFilterUtil.isUnfilteredQuery(interceptedStudyViewFilter); - List alterationCountByStructuralVariants = - this.getInstance().cacheableFetchStructuralVariantCounts(interceptedStudyViewFilter, - unfilteredQuery); - return new ResponseEntity<>(alterationCountByStructuralVariants, HttpStatus.OK); - } - - @Cacheable( - cacheResolver = "staticRepositoryCacheOneResolver", - condition = "@cacheEnabledConfig.getEnabled() && #unfilteredQuery" - ) - public List cacheableFetchStructuralVariantCounts(StudyViewFilter interceptedStudyViewFilter, - boolean unfilteredQuery) { - - List sampleIdentifiers = studyViewFilterApplier.apply(interceptedStudyViewFilter); - if(CollectionUtils.isNotEmpty(sampleIdentifiers)) { - List studyIds = new ArrayList<>(); - List sampleIds = new ArrayList<>(); - studyViewFilterUtil.extractStudyAndSampleIds(sampleIdentifiers, studyIds, sampleIds); - return studyViewService.getStructuralVariantAlterationCounts(studyIds, sampleIds, interceptedStudyViewFilter.getAlterationFilter()); - } - return new ArrayList<>(); - } - - @PreAuthorize("hasPermission(#involvedCancerStudies, 'Collection', T(org.cbioportal.utils.security.AccessLevel).READ)") - @RequestMapping(value = "/cna-genes/fetch", method = RequestMethod.POST, - consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "Fetch CNA genes by study view filter") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(array = @ArraySchema(schema = @Schema(implementation = CopyNumberCountByGene.class)))) - public ResponseEntity> fetchCNAGenes( - @Parameter(required = true, description = "Study view filter") - @Valid @RequestBody(required = false) StudyViewFilter studyViewFilter, - @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface - @RequestAttribute(required = false, value = "involvedCancerStudies") Collection involvedCancerStudies, - @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface. this attribute is needed for the @PreAuthorize tag above. - @Valid @RequestAttribute(required = false, value = "interceptedStudyViewFilter") StudyViewFilter interceptedStudyViewFilter - ) throws StudyNotFoundException { - boolean unfilteredQuery = studyViewFilterUtil.isUnfilteredQuery(interceptedStudyViewFilter); - List copyNumberCountByGenes = this.getInstance().cacheableFetchCNAGenes(interceptedStudyViewFilter, - unfilteredQuery); - return new ResponseEntity<>(copyNumberCountByGenes, HttpStatus.OK); - } - - @Cacheable( - cacheResolver = "staticRepositoryCacheOneResolver", - condition = "@cacheEnabledConfig.getEnabled() && #unfilteredQuery" - ) - public List cacheableFetchCNAGenes(StudyViewFilter interceptedStudyViewFilter, - boolean unfilteredQuery) throws StudyNotFoundException { - AlterationFilter alterationFilter = interceptedStudyViewFilter.getAlterationFilter(); - - List sampleIdentifiers = studyViewFilterApplier.apply(interceptedStudyViewFilter); - List copyNumberCountByGenes = new ArrayList<>(); - if(CollectionUtils.isNotEmpty(sampleIdentifiers)) { - List studyIds = new ArrayList<>(); - List sampleIds = new ArrayList<>(); - studyViewFilterUtil.extractStudyAndSampleIds(sampleIdentifiers, studyIds, sampleIds); - copyNumberCountByGenes = studyViewService.getCNAAlterationCountByGenes(studyIds, sampleIds, alterationFilter); - } - return copyNumberCountByGenes; - } - - @PreAuthorize("hasPermission(#involvedCancerStudies, 'Collection', T(org.cbioportal.utils.security.AccessLevel).READ)") - @RequestMapping(value = "/filtered-samples/fetch", method = RequestMethod.POST, - consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "Fetch sample IDs by study view filter") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(array = @ArraySchema(schema = @Schema(implementation = Sample.class)))) - public ResponseEntity> fetchFilteredSamples( - @Parameter(description = "Whether to negate the study view filters") - @RequestParam(defaultValue = "false") boolean negateFilters, - @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface - @RequestAttribute(required = false, value = "involvedCancerStudies") Collection involvedCancerStudies, - @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface. this attribute is needed for the @PreAuthorize tag above. - @Valid @RequestAttribute(required = false, value = "interceptedStudyViewFilter") StudyViewFilter interceptedStudyViewFilter, - @Parameter(required = true, description = "Study view filter") - @Valid @RequestBody(required = false) StudyViewFilter studyViewFilter) { - - List studyIds = new ArrayList<>(); - List sampleIds = new ArrayList<>(); - - studyViewFilterUtil.extractStudyAndSampleIds( - studyViewFilterApplier.apply(interceptedStudyViewFilter, negateFilters), studyIds, sampleIds); - - List result = new ArrayList<>(); - if (!sampleIds.isEmpty()) { - result = sampleService.fetchSamples(studyIds, sampleIds, Projection.ID.name()); - } - return new ResponseEntity<>(result, HttpStatus.OK); - } - - @PreAuthorize("hasPermission(#involvedCancerStudies, 'Collection', T(org.cbioportal.utils.security.AccessLevel).READ)") - @RequestMapping(value = "/molecular-profile-sample-counts/fetch", method = RequestMethod.POST, - consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "Fetch sample counts by study view filter") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(array = @ArraySchema(schema = @Schema(implementation = GenomicDataCount.class)))) - public ResponseEntity> fetchMolecularProfileSampleCounts( - @Parameter(required = true, description = "Study view filter") - @Valid @RequestBody(required = false) StudyViewFilter studyViewFilter, - @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface - @RequestAttribute(required = false, value = "involvedCancerStudies") Collection involvedCancerStudies, - @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface. this attribute is needed for the @PreAuthorize tag above. - @Valid @RequestAttribute(required = false, value = "interceptedStudyViewFilter") StudyViewFilter interceptedStudyViewFilter - ) - { - boolean unfilteredQuery = studyViewFilterUtil.isUnfilteredQuery(interceptedStudyViewFilter); - List sampleCounts = this.getInstance().cacheableFetchMolecularProfileSampleCounts(interceptedStudyViewFilter, - unfilteredQuery); - return new ResponseEntity<>(sampleCounts, HttpStatus.OK); - } - - @Cacheable( - cacheResolver = "staticRepositoryCacheOneResolver", - condition = "@cacheEnabledConfig.getEnabled() && #unfilteredQuery" - ) - public List cacheableFetchMolecularProfileSampleCounts(StudyViewFilter interceptedStudyViewFilter, - boolean unfilteredQuery) { - List sampleIdentifiers = studyViewFilterApplier.apply(interceptedStudyViewFilter); - List genomicDataCounts = new ArrayList<>(); - if(CollectionUtils.isNotEmpty(sampleIdentifiers)) { - List studyIds = new ArrayList<>(); - List sampleIds = new ArrayList<>(); - studyViewFilterUtil.extractStudyAndSampleIds(sampleIdentifiers, studyIds, sampleIds); - genomicDataCounts = studyViewService.getGenomicDataCounts(studyIds, sampleIds); - } - return genomicDataCounts; - } - - private static boolean isLogScalePossibleForAttribute(String clinicalAttributeId) { - return clinicalAttributeId.equals("MUTATION_COUNT"); - } - - private static double logScale(double val) { - return Math.log(1+val); - } - - private static double parseValueLog(ClinicalData c) { - return StudyViewController.logScale(Double.parseDouble(c.getAttrValue())); - } - - private static double parseValueLinear(ClinicalData c) { - return Double.parseDouble(c.getAttrValue()); - } - - @PreAuthorize("hasPermission(#involvedCancerStudies, 'Collection', T(org.cbioportal.utils.security.AccessLevel).READ)") - @RequestMapping(value = "/clinical-data-density-plot/fetch", method = RequestMethod.POST, - consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "Fetch clinical data density plot bins by study view filter") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(schema = @Schema(implementation = DensityPlotData.class))) - @Validated - public ResponseEntity fetchClinicalDataDensityPlot( - @Parameter(required = true, description = "Clinical Attribute ID of the X axis") - @RequestParam String xAxisAttributeId, - @Parameter(description = "Number of the bins in X axis") - @RequestParam(defaultValue = "50") Integer xAxisBinCount, - @Parameter(description = "Starting point of the X axis, if different than smallest value") - @RequestParam(required = false) BigDecimal xAxisStart, - @Parameter(description = "Starting point of the X axis, if different than largest value") - @RequestParam(required = false) BigDecimal xAxisEnd, - @Parameter(required = true, description = "Clinical Attribute ID of the Y axis") - @RequestParam String yAxisAttributeId, - @Parameter(description = "Number of the bins in Y axis") - @RequestParam(defaultValue = "50") Integer yAxisBinCount, - @Parameter(description = "Starting point of the Y axis, if different than smallest value") - @RequestParam(required = false) BigDecimal yAxisStart, - @Parameter(description = "Starting point of the Y axis, if different than largest value") - @RequestParam(required = false) BigDecimal yAxisEnd, - @Parameter(description="Use log scale for X axis") - @RequestParam(required = false, defaultValue = "false") Boolean xAxisLogScale, - @Schema(defaultValue = "false") - @Parameter(description="Use log scale for Y axis") - @RequestParam(required = false, defaultValue = "false") Boolean yAxisLogScale, - @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface - @RequestAttribute(required = false, value = "involvedCancerStudies") Collection involvedCancerStudies, - @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface. this attribute is needed for the @PreAuthorize tag above. - @Valid @RequestAttribute(required = false, value = "interceptedStudyViewFilter") StudyViewFilter interceptedStudyViewFilter, - @Parameter(required = true, description = "Study view filter") - @RequestBody(required = false) StudyViewFilter studyViewFilter) { - - List studyIds = new ArrayList<>(); - List sampleIds = new ArrayList<>(); - studyViewFilterUtil.extractStudyAndSampleIds(studyViewFilterApplier.apply(interceptedStudyViewFilter), studyIds, sampleIds); - DensityPlotData result = new DensityPlotData(); - result.setBins(new ArrayList<>()); - if (sampleIds.isEmpty()) { - return new ResponseEntity<>(result, HttpStatus.OK); - } - - List sampleAttributeIds = new ArrayList<>(); - List patientAttributeIds = new ArrayList<>(); - - List clinicalAttributes = clinicalAttributeService - .getClinicalAttributesByStudyIdsAndAttributeIds(studyIds, - Arrays.asList(xAxisAttributeId, yAxisAttributeId)); - - clinicalAttributeUtil.extractCategorizedClinicalAttributes(clinicalAttributes, sampleAttributeIds, patientAttributeIds, patientAttributeIds); - - List patientIds = new ArrayList<>(); - List studyIdsOfPatients = new ArrayList<>(); - Map>> patientToSamples = null; - - - if (CollectionUtils.isNotEmpty(patientAttributeIds)) { - List samples = sampleService.fetchSamples(studyIds, sampleIds, Projection.DETAILED.name()); - List patients = patientService.getPatientsOfSamples(studyIds, sampleIds); - patientIds = patients.stream().map(Patient::getStableId).toList(); - studyIdsOfPatients = patients.stream().map(Patient::getCancerStudyIdentifier).toList(); - patientToSamples = samples.stream().collect( - Collectors.groupingBy(Sample::getPatientStableId, Collectors.groupingBy(Sample::getCancerStudyIdentifier)) - ); - } - - List clinicalDataList = clinicalDataFetcher.fetchClinicalData( - studyIds, sampleIds, patientIds, studyIdsOfPatients, sampleAttributeIds, patientAttributeIds, null - ); - - List sampleClinicalDataList; - // put all clinical data into sample form - if (CollectionUtils.isNotEmpty(patientAttributeIds)) { - sampleClinicalDataList = new ArrayList<>(); - for (ClinicalData d: clinicalDataList) { - if (d.getSampleId() == null) { - // null sample id means its a patient data, - // we need to distribute the value to samples - List samplesForPatient = patientToSamples.get( - d.getPatientId() - ).get(d.getStudyId()); - if (samplesForPatient != null) { - for (Sample s: samplesForPatient) { - ClinicalData newData = new ClinicalData(); - newData.setAttrId(d.getAttrId()); - newData.setPatientId(d.getPatientId()); - newData.setStudyId(d.getStudyId()); - newData.setAttrValue(d.getAttrValue()); - newData.setSampleId(s.getStableId()); - sampleClinicalDataList.add(newData); - } - } else { - // patient has no samples - this shouldn't happen and could affect the integrity - // of the data analysis - return new ResponseEntity<>(null, HttpStatus.INTERNAL_SERVER_ERROR); - } - } else { - // if its a sample data, just add it to the list - sampleClinicalDataList.add(d); - } - } - } else { - sampleClinicalDataList = clinicalDataList; - } - - // clinicalDataMap is a map sampleId->studyId->data - Map>> clinicalDataMap = sampleClinicalDataList.stream().collect(Collectors.groupingBy(ClinicalData::getSampleId, - Collectors.groupingBy(ClinicalData::getStudyId))); - - List filteredClinicalDataList = new ArrayList<>(); - clinicalDataMap.forEach((k, v) -> v.forEach((m, n) -> { - if ( - // n.size() == 2 means we have clinical data for the sample for both of the queried attributes - n.size() == 2 && - // check if both of the sample data are numerical - NumberUtils.isCreatable(n.get(0).getAttrValue()) && NumberUtils.isCreatable(n.get(1).getAttrValue())) { - filteredClinicalDataList.addAll(n); - } - })); - if (filteredClinicalDataList.isEmpty()) { - return new ResponseEntity<>(result, HttpStatus.OK); - } - - Map> partition = filteredClinicalDataList.stream().collect( - Collectors.partitioningBy(c -> c.getAttrId().equals(xAxisAttributeId))); - - boolean useXLogScale = xAxisLogScale && StudyViewController.isLogScalePossibleForAttribute(xAxisAttributeId); - boolean useYLogScale = yAxisLogScale && StudyViewController.isLogScalePossibleForAttribute(yAxisAttributeId); - - double[] xValues = partition.get(true).stream().mapToDouble( - useXLogScale ? StudyViewController::parseValueLog : StudyViewController::parseValueLinear - ).toArray(); - double[] yValues = partition.get(false).stream().mapToDouble( - useYLogScale ? StudyViewController::parseValueLog : StudyViewController::parseValueLinear - ).toArray(); - double[] xValuesCopy = Arrays.copyOf(xValues, xValues.length); - double[] yValuesCopy = Arrays.copyOf(yValues, yValues.length); - Arrays.sort(xValuesCopy); - Arrays.sort(yValuesCopy); - - double xAxisStartValue = xAxisStart == null ? xValuesCopy[0] : - (useXLogScale ? StudyViewController.logScale(xAxisStart.doubleValue()) : xAxisStart.doubleValue()); - double xAxisEndValue = xAxisEnd == null ? xValuesCopy[xValuesCopy.length - 1] : - (useXLogScale ? StudyViewController.logScale(xAxisEnd.doubleValue()) : xAxisEnd.doubleValue()); - double yAxisStartValue = yAxisStart == null ? yValuesCopy[0] : - (useYLogScale ? StudyViewController.logScale(yAxisStart.doubleValue()) : yAxisStart.doubleValue()); - double yAxisEndValue = yAxisEnd == null ? yValuesCopy[yValuesCopy.length - 1] : - (useYLogScale ? StudyViewController.logScale(yAxisEnd.doubleValue()) : yAxisEnd.doubleValue()); - double xAxisBinInterval = (xAxisEndValue - xAxisStartValue) / xAxisBinCount; - double yAxisBinInterval = (yAxisEndValue - yAxisStartValue) / yAxisBinCount; - List bins = result.getBins(); - for (int i = 0; i < xAxisBinCount; i++) { - for (int j = 0; j < yAxisBinCount; j++) { - DensityPlotBin densityPlotBin = new DensityPlotBin(); - densityPlotBin.setBinX(BigDecimal.valueOf(xAxisStartValue + (i * xAxisBinInterval))); - densityPlotBin.setBinY(BigDecimal.valueOf(yAxisStartValue + (j * yAxisBinInterval))); - densityPlotBin.setCount(0); - bins.add(densityPlotBin); - } - } - - for (int i = 0; i < xValues.length; i++) { - double xValue = xValues[i]; - double yValue = yValues[i]; - int xBinIndex = (int) ((xValue - xAxisStartValue) / xAxisBinInterval); - int yBinIndex = (int) ((yValue - yAxisStartValue) / yAxisBinInterval); - int index = (int) (((xBinIndex - (xBinIndex == xAxisBinCount ? 1 : 0)) * yAxisBinCount) + - (yBinIndex - (yBinIndex == yAxisBinCount ? 1 : 0))); - DensityPlotBin densityPlotBin = bins.get(index); - densityPlotBin.setCount(densityPlotBin.getCount() + 1); - BigDecimal xValueBigDecimal = BigDecimal.valueOf(xValue); - BigDecimal yValueBigDecimal = BigDecimal.valueOf(yValue); - if (densityPlotBin.getMinX() != null) { - if (densityPlotBin.getMinX().compareTo(xValueBigDecimal) > 0) { - densityPlotBin.setMinX(xValueBigDecimal); - } - } else { - densityPlotBin.setMinX(xValueBigDecimal); - } - if (densityPlotBin.getMaxX() != null) { - if (densityPlotBin.getMaxX().compareTo(xValueBigDecimal) < 0) { - densityPlotBin.setMaxX(xValueBigDecimal); - } - } else { - densityPlotBin.setMaxX(xValueBigDecimal); - } - if (densityPlotBin.getMinY() != null) { - if (densityPlotBin.getMinY().compareTo(yValueBigDecimal) > 0) { - densityPlotBin.setMinY(yValueBigDecimal); - } - } else { - densityPlotBin.setMinY(yValueBigDecimal); - } - if (densityPlotBin.getMaxY() != null) { - if (densityPlotBin.getMaxY().compareTo(yValueBigDecimal) < 0) { - densityPlotBin.setMaxY(yValueBigDecimal); - } - } else { - densityPlotBin.setMaxY(yValueBigDecimal); - } - } - - if (xValues.length > 1) { - // need at least 2 entries in each to compute correlation - result.setPearsonCorr(new PearsonsCorrelation().correlation(xValues, yValues)); - result.setSpearmanCorr(new SpearmansCorrelation().correlation(xValues, yValues)); - } else { - // if less than 1 entry, just set 0 correlation - result.setSpearmanCorr(0.0); - result.setPearsonCorr(0.0); - } - - // filter out empty bins - result.setBins(result.getBins().stream().filter((bin)->(bin.getCount() > 0)).collect(Collectors.toList())); - - return new ResponseEntity<>(result, HttpStatus.OK); - } - - @PreAuthorize("hasPermission(#involvedCancerStudies, 'Collection', T(org.cbioportal.utils.security.AccessLevel).READ)") - @RequestMapping(value = "/clinical-data-violin-plots/fetch", method = RequestMethod.POST, - consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "Fetch violin plot curves per categorical clinical data value, filtered by study view filter") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(schema = @Schema(implementation = ClinicalViolinPlotData.class))) - public ResponseEntity fetchClinicalDataViolinPlots( - @Parameter(required = true, description = "Clinical Attribute ID of the categorical attribute") - @RequestParam String categoricalAttributeId, - @Parameter(required = true, description = "Clinical Attribute ID of the numerical attribute") - @RequestParam String numericalAttributeId, - @Parameter(description = "Starting point of the violin plot axis, if different than smallest value") - @RequestParam(required = false) BigDecimal axisStart, - @Parameter(description = "Ending point of the violin plot axis, if different than largest value") - @RequestParam(required = false) BigDecimal axisEnd, - @Parameter(description = "Number of points in the curve") - @RequestParam(required = false, defaultValue = "100") BigDecimal numCurvePoints, - @Parameter(description="Use log scale for the numerical attribute") - @RequestParam(required = false, defaultValue = "false") Boolean logScale, - @Parameter(description="Sigma stepsize multiplier") - @RequestParam(required = false, defaultValue = "1") BigDecimal sigmaMultiplier, - @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface - @RequestAttribute(required = false, value = "involvedCancerStudies") Collection involvedCancerStudies, - @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface. this attribute is needed for the @PreAuthorize tag above. - @Valid @RequestAttribute(required = false, value = "interceptedStudyViewFilter") StudyViewFilter interceptedStudyViewFilter, - @Parameter(required = true, description = "Study view filter") - @Valid @RequestBody(required = false) StudyViewFilter studyViewFilter) { - - ClinicalViolinPlotData result = new ClinicalViolinPlotData(); - - List studyIds = new ArrayList<>(); - List sampleIds = new ArrayList<>(); - // first get samples that are filtered by all current filters - this will give us - // the by-row sample counts - studyViewFilterUtil.extractStudyAndSampleIds(studyViewFilterApplier.apply(interceptedStudyViewFilter), studyIds, sampleIds); - List filteredSamples = sampleService.fetchSamples(studyIds, sampleIds, Projection.DETAILED.name()); - - List studyIdsWithoutNumericalFilter = new ArrayList<>(); - List sampleIdsWithoutNumericalFilter = new ArrayList<>(); - // next, get samples that are filtered without the numerical filter - this will - // give us the violin plot data - if (interceptedStudyViewFilter.getClinicalDataFilters() != null) { - // Remove numerical clinical data filter, if there is one - interceptedStudyViewFilter.getClinicalDataFilters().stream() - .filter(f->f.getAttributeId().equals(numericalAttributeId)) - .findAny() - .ifPresent(f->interceptedStudyViewFilter.getClinicalDataFilters().remove(f)); - } - studyViewFilterUtil.extractStudyAndSampleIds( - studyViewFilterApplier.apply(interceptedStudyViewFilter), - studyIdsWithoutNumericalFilter, - sampleIdsWithoutNumericalFilter - ); - - if (sampleIds.isEmpty()) { - return new ResponseEntity<>(result, HttpStatus.OK); - } - - List sampleAttributeIds = new ArrayList<>(); - List patientAttributeIds = new ArrayList<>(); - - List clinicalAttributes = clinicalAttributeService - .getClinicalAttributesByStudyIdsAndAttributeIds(studyIds, - Arrays.asList(categoricalAttributeId, numericalAttributeId)); - - clinicalAttributeUtil.extractCategorizedClinicalAttributes(clinicalAttributes, sampleAttributeIds, patientAttributeIds, patientAttributeIds); - - List patientIds = new ArrayList<>(); - List studyIdsOfPatients = new ArrayList<>(); - Map>> patientToSamples = null; - - if (CollectionUtils.isNotEmpty(patientAttributeIds)) { - List samplesWithoutNumericalFilter = sampleService.fetchSamples(studyIdsWithoutNumericalFilter, sampleIdsWithoutNumericalFilter, Projection.DETAILED.name()); - List patients = patientService.getPatientsOfSamples(studyIdsWithoutNumericalFilter, sampleIdsWithoutNumericalFilter); - patientIds = patients.stream().map(Patient::getStableId).toList(); - studyIdsOfPatients = patients.stream().map(Patient::getCancerStudyIdentifier).toList(); - patientToSamples = samplesWithoutNumericalFilter.stream().collect( - Collectors.groupingBy(Sample::getPatientStableId, Collectors.groupingBy(Sample::getCancerStudyIdentifier)) - ); - } - - List clinicalDataList = clinicalDataFetcher.fetchClinicalData( - studyIdsWithoutNumericalFilter, sampleIdsWithoutNumericalFilter, patientIds, studyIdsOfPatients, sampleAttributeIds, patientAttributeIds, null - ); - - List sampleClinicalDataList; - // put all clinical data into sample form - if (CollectionUtils.isNotEmpty(patientAttributeIds)) { - sampleClinicalDataList = new ArrayList<>(); - for (ClinicalData d: clinicalDataList) { - if (d.getSampleId() == null) { - // null sample id means its a patient data, - // we need to distribute the value to samples - List samplesForPatient = patientToSamples.get(d.getPatientId()).get(d.getStudyId()); - if (samplesForPatient != null) { - for (Sample s: samplesForPatient) { - ClinicalData newData = new ClinicalData(); - newData.setInternalId(s.getInternalId()); - newData.setAttrId(d.getAttrId()); - newData.setPatientId(d.getPatientId()); - newData.setStudyId(d.getStudyId()); - newData.setAttrValue(d.getAttrValue()); - newData.setSampleId(s.getStableId()); - sampleClinicalDataList.add(newData); - } - } else { - // patient has no samples - this shouldn't happen and could affect the integrity - // of the data analysis - return new ResponseEntity<>(null, HttpStatus.INTERNAL_SERVER_ERROR); - } - } else { - // if its a sample data, just add it to the list - sampleClinicalDataList.add(d); - } - } - } else { - sampleClinicalDataList = clinicalDataList; - } - - boolean useLogScale = logScale && StudyViewController.isLogScalePossibleForAttribute(numericalAttributeId); - - - result = violinPlotService.getClinicalViolinPlotData( - sampleClinicalDataList, - filteredSamples, - axisStart, - axisEnd, - numCurvePoints, - useLogScale, - sigmaMultiplier, - interceptedStudyViewFilter - ); - - return new ResponseEntity<>(result, HttpStatus.OK); - } - - @PreAuthorize("hasPermission(#involvedCancerStudies, 'Collection', T(org.cbioportal.utils.security.AccessLevel).READ)") - @RequestMapping(value = "/sample-lists-counts/fetch", method = RequestMethod.POST, - consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "Fetch case list sample counts by study view filter") - public List fetchCaseListCounts( - @Parameter(required = true, description = "Study view filter") - @Valid @RequestBody(required = false) StudyViewFilter studyViewFilter, - @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface - @RequestAttribute(required = false, value = "involvedCancerStudies") Collection involvedCancerStudies, - @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface. this attribute is needed for the @PreAuthorize tag above. - @Valid @RequestAttribute(required = false, value = "interceptedStudyViewFilter") StudyViewFilter interceptedStudyViewFilter) { - - List studyIds = new ArrayList<>(); - List sampleIds = new ArrayList<>(); - List filteredSampleIdentifiers = studyViewFilterApplier.apply(interceptedStudyViewFilter); - studyViewFilterUtil.extractStudyAndSampleIds(filteredSampleIdentifiers, studyIds, sampleIds); - List sampleLists = sampleListService.getAllSampleListsInStudies(studyIds, - Projection.DETAILED.name()); - - HashMap sampleCountBySampleListId = new HashMap(); - - Map filteredSampleSet = filteredSampleIdentifiers.stream() - .collect(Collectors.toMap(sampleidentifier -> studyViewFilterUtil - .getCaseUniqueKey(sampleidentifier.getStudyId(), sampleidentifier.getSampleId()), - Function.identity())); - - for (SampleList sampleList : sampleLists) { - for (String sampleId : sampleList.getSampleIds()) { - if (filteredSampleSet.containsKey( - studyViewFilterUtil.getCaseUniqueKey(sampleList.getCancerStudyIdentifier(), sampleId))) { - Integer count = sampleCountBySampleListId.getOrDefault(sampleList.getStableId(), 0); - sampleCountBySampleListId.put(sampleList.getStableId(), count + 1); - } - } - } - - return studyViewFilterUtil - .categorizeSampleLists(sampleLists) - .entrySet() - .stream() - .map(entry -> { - CaseListDataCount dataCount = new CaseListDataCount(); - dataCount.setValue(entry.getKey()); - - Integer count = entry.getValue().stream().mapToInt(sampleList -> { - return sampleCountBySampleListId.getOrDefault(sampleList.getStableId(), 0); - }).sum(); - - dataCount.setCount(count); - dataCount.setLabel(entry.getValue().get(0).getName()); - - return dataCount; - }) - .filter(dataCount -> dataCount.getCount() > 0) - .toList(); - - } - - @PreAuthorize("hasPermission(#involvedCancerStudies, 'Collection', T(org.cbioportal.utils.security.AccessLevel).READ)") - @RequestMapping(value = "/genomic-data-bin-counts/fetch", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "Fetch genomic data bin counts by study view filter") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(array = @ArraySchema(schema = @Schema(implementation = GenomicDataBin.class)))) - public ResponseEntity> fetchGenomicDataBinCounts( - @Parameter(description = "Method for data binning") @RequestParam(defaultValue = "DYNAMIC") DataBinMethod dataBinMethod, - @Parameter(required = true, description = "Genomic data bin count filter") @Valid @RequestBody(required = false) GenomicDataBinCountFilter genomicDataBinCountFilter, - @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface - @RequestAttribute(required = false, value = "involvedCancerStudies") Collection involvedCancerStudies, - @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface. this - // attribute is needed for the @PreAuthorize tag above. - @Valid @RequestAttribute(required = false, value = "interceptedGenomicDataBinCountFilter") GenomicDataBinCountFilter interceptedGenomicDataBinCountFilter) { - - return new ResponseEntity<>(studyViewFilterApplier.getDataBins(dataBinMethod, interceptedGenomicDataBinCountFilter), HttpStatus.OK); - } - - @PreAuthorize("hasPermission(#involvedCancerStudies, 'Collection', T(org.cbioportal.utils.security.AccessLevel).READ)") - @RequestMapping(value = "/genomic-data-counts/fetch", method = RequestMethod.POST, - consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "Fetch genomic data counts by GenomicDataCountFilter") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(array = @ArraySchema(schema = @Schema(implementation = GenomicDataCountItem.class)))) - public ResponseEntity> fetchGenomicDataCounts( - @Parameter(required = true, description = "Genomic data count filter") @Valid @RequestBody(required = false) GenomicDataCountFilter genomicDataCountFilter, - @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface - @RequestAttribute(required = false, value = "involvedCancerStudies") Collection involvedCancerStudies, - @Parameter(required = true, description = "Intercepted Genomic Data Count Filter") - @Valid @RequestAttribute(required = false, value = "interceptedGenomicDataCountFilter") GenomicDataCountFilter interceptedGenomicDataCountFilter - ) throws StudyNotFoundException { - List genomicDataFilters = interceptedGenomicDataCountFilter.getGenomicDataFilters(); - StudyViewFilter studyViewFilter = interceptedGenomicDataCountFilter.getStudyViewFilter(); - // when there is only one filter, it means study view is doing a single chart filter operation - // remove filter from studyViewFilter to return all data counts - // the reason we do this is to make sure after chart get filtered, user can still see unselected portion of the chart - if (genomicDataFilters.size() == 1) { - studyViewFilterUtil.removeSelfFromGenomicDataFilter( - genomicDataFilters.get(0).getHugoGeneSymbol(), - genomicDataFilters.get(0).getProfileType(), - studyViewFilter); - } - List filteredSampleIdentifiers = studyViewFilterApplier.apply(studyViewFilter); - - if (filteredSampleIdentifiers.isEmpty()) { - return new ResponseEntity<>(new ArrayList<>(), HttpStatus.OK); - } - - List studyIds = new ArrayList<>(); - List sampleIds = new ArrayList<>(); - studyViewFilterUtil.extractStudyAndSampleIds(filteredSampleIdentifiers, studyIds, sampleIds); - - List result = studyViewService.getCNAAlterationCountsByGeneSpecific( - studyIds, - sampleIds, - genomicDataFilters.stream().map(genomicDataFilter -> new Pair<>(genomicDataFilter.getHugoGeneSymbol(), genomicDataFilter.getProfileType())).collect(Collectors.toList())); - - return new ResponseEntity<>(result, HttpStatus.OK); - } - - @PreAuthorize("hasPermission(#involvedCancerStudies, 'Collection', T(org.cbioportal.utils.security.AccessLevel).READ)") - @RequestMapping(value = "/generic-assay-data-counts/fetch", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "Fetch generic assay data counts by study view filter") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(array = @ArraySchema(schema = @Schema(implementation = GenericAssayDataCountItem.class)))) - public ResponseEntity> fetchGenericAssayDataCounts( - @Parameter(required = true, description = "Generic assay data count filter") @Valid @RequestBody(required = false) GenericAssayDataCountFilter genericAssayDataCountFilter, - @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface - @RequestAttribute(required = false, value = "involvedCancerStudies") Collection involvedCancerStudies, - @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface. this - // attribute is needed for the @PreAuthorize tag above. - @Valid @RequestAttribute(required = false, value = "interceptedGenericAssayDataCountFilter") GenericAssayDataCountFilter interceptedGenericAssayDataCountFilter) { - - List gaFilters = interceptedGenericAssayDataCountFilter.getGenericAssayDataFilters(); - StudyViewFilter studyViewFilter = interceptedGenericAssayDataCountFilter.getStudyViewFilter(); - // when there is only one filter, it means study view is doing a single chart filter operation - // remove filter from studyViewFilter to return all data counts - // the reason we do this is to make sure after chart get filtered, user can still see unselected portion of the chart - if (gaFilters.size() == 1) { - studyViewFilterUtil.removeSelfFromGenericAssayFilter(gaFilters.get(0).getStableId(), studyViewFilter); - } - List filteredSampleIdentifiers = studyViewFilterApplier.apply(studyViewFilter); - - if (filteredSampleIdentifiers.isEmpty()) { - return new ResponseEntity<>(new ArrayList<>(), HttpStatus.OK); - } - - List studyIds = new ArrayList<>(); - List sampleIds = new ArrayList<>(); - studyViewFilterUtil.extractStudyAndSampleIds(filteredSampleIdentifiers, studyIds, sampleIds); - - List result = studyViewService.fetchGenericAssayDataCounts( - sampleIds, - studyIds, - gaFilters.stream().map(GenericAssayDataFilter::getStableId).toList(), - gaFilters.stream().map(GenericAssayDataFilter::getProfileType).collect(Collectors.toList())); - - return new ResponseEntity<>(result, HttpStatus.OK); - } - - @PreAuthorize("hasPermission(#involvedCancerStudies, 'Collection', T(org.cbioportal.utils.security.AccessLevel).READ)") - @RequestMapping(value = "/generic-assay-data-bin-counts/fetch", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "Fetch generic assay data bin counts by study view filter") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(array = @ArraySchema(schema = @Schema(implementation = GenericAssayDataBin.class)))) - public ResponseEntity> fetchGenericAssayDataBinCounts( - @Parameter(description = "Method for data binning") @RequestParam(defaultValue = "DYNAMIC") DataBinMethod dataBinMethod, - @Parameter(required = true, description = "Generic assay data bin count filter") @Valid @RequestBody(required = false) GenericAssayDataBinCountFilter genericAssayDataBinCountFilter, - @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface - @RequestAttribute(required = false, value = "involvedCancerStudies") Collection involvedCancerStudies, - @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface. this - // attribute is needed for the @PreAuthorize tag above. - @Valid @RequestAttribute(required = false, value = "interceptedGenericAssayDataBinCountFilter") GenericAssayDataBinCountFilter interceptedGenericAssayDataBinCountFilter) { - - return new ResponseEntity<>(studyViewFilterApplier.getDataBins(dataBinMethod, interceptedGenericAssayDataBinCountFilter), HttpStatus.OK); - } - - @PreAuthorize("hasPermission(#involvedCancerStudies, 'Collection', T(org.cbioportal.utils.security.AccessLevel).READ)") - @RequestMapping(value = "/clinical-data-table/fetch", method = RequestMethod.POST, - consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "Fetch clinical data for the Clinical Tab of Study View") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(schema = @Schema(implementation = SampleClinicalDataCollection.class))) - public ResponseEntity fetchClinicalDataClinicalTable( - @Parameter(required = true, description = "Study view filter") - @Valid @RequestBody(required = false) - StudyViewFilter studyViewFilter, - @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface - @RequestAttribute(required = false, value = "involvedCancerStudies") - Collection involvedCancerStudies, - @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface. this attribute is needed for the @PreAuthorize tag above. - @Valid @RequestAttribute(required = false, value = "interceptedStudyViewFilter") - StudyViewFilter interceptedStudyViewFilter, - @Parameter(description = "Page size of the result list") - @Max(CLINICAL_TAB_MAX_PAGE_SIZE) - @Min(PagingConstants.NO_PAGING_PAGE_SIZE) - @RequestParam(defaultValue = PagingConstants.DEFAULT_NO_PAGING_PAGE_SIZE) - Integer pageSize, - @Parameter(description = "Page number of the result list. Zero represents the first page.") - @Min(PagingConstants.MIN_PAGE_NUMBER) - @RequestParam(defaultValue = PagingConstants.DEFAULT_PAGE_NUMBER) - Integer pageNumber, - @Parameter(description = "Search term to filter sample rows. Samples are returned " + - "with a partial match to the search term for any sample clinical attribute.") - @RequestParam(defaultValue = "") - String searchTerm, - @Parameter(description = "sampleId, patientId, or the ATTR_ID to sorted by") - @RequestParam(required = false) - // TODO: Can we narrow down this string to a specific enum? - String sortBy, - @Parameter(description = "Direction of the sort") - @RequestParam(defaultValue = "ASC") - Direction direction - ) { - - boolean unfilteredQuery = studyViewFilterUtil.isUnfilteredQuery(interceptedStudyViewFilter); - ImmutablePair sampleClinicalData = cachedClinicalDataTableData( - interceptedStudyViewFilter, unfilteredQuery, pageNumber, pageSize, sortBy, searchTerm, direction.name() - ); - - // Because of pagination, the total number of sample matches can be larger than the items in the requested page. - SampleClinicalDataCollection aggregatedClinicalDataByUniqueSampleKey = sampleClinicalData.getLeft(); - Integer totalNumberOfResults = sampleClinicalData.getRight(); - - HttpHeaders responseHeaders = new HttpHeaders(); - responseHeaders.add(HeaderKeyConstants.TOTAL_COUNT, String.valueOf(totalNumberOfResults)); - return new ResponseEntity<>(aggregatedClinicalDataByUniqueSampleKey, responseHeaders, HttpStatus.OK); - } - - // Only cache when: - // 1) the request concerns the entire study - // 2) no sorting/searching - // 3) requesting the first page - @Cacheable( - cacheResolver = "staticRepositoryCacheOneResolver", - condition = "@cacheEnabledConfig.getEnabled() && #unfilteredQuery && (#sortBy == null || #sortBy.isEmpty()) && (#searchTerm == null || #searchTerm.isEmpty()) && #pageNumber == 0" - ) - public ImmutablePair cachedClinicalDataTableData( - StudyViewFilter interceptedStudyViewFilter, boolean unfilteredQuery, Integer pageNumber, - Integer pageSize, String sortBy, String searchTerm, String sortDirection - ) { - - List sampleStudyIds = new ArrayList<>(); - List sampleIds = new ArrayList<>(); - List filteredSampleIdentifiers = studyViewFilterApplier.apply(interceptedStudyViewFilter); - studyViewFilterUtil.extractStudyAndSampleIds(filteredSampleIdentifiers, sampleStudyIds, sampleIds); - - return clinicalDataService.fetchSampleClinicalTable( - sampleStudyIds, - sampleIds, - pageSize, - pageNumber, - searchTerm, - sortBy, - sortDirection - ); - } - - @PreAuthorize("hasPermission(#involvedCancerStudies, 'Collection', T(org.cbioportal.utils.security.AccessLevel).READ)") - @RequestMapping(value = "/clinical-event-type-counts/fetch", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE, - produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "Get Counts of Clinical Event Types by Study View Filter") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(array = @ArraySchema(schema = @Schema(implementation = ClinicalEventTypeCount.class)))) - public ResponseEntity> getClinicalEventTypeCounts( - @Parameter(required = true, description = "Study view filter") - @Valid - @RequestBody(required = false) - StudyViewFilter studyViewFilter, - - @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface - @RequestAttribute(required = false, value = "involvedCancerStudies") - Collection involvedCancerStudies, - - @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface. this attribute is needed for the @PreAuthorize tag above. - @Valid - @RequestAttribute(required = false, value = "interceptedStudyViewFilter") - StudyViewFilter interceptedStudyViewFilter - ) { - boolean unfilteredQuery = studyViewFilterUtil.isUnfilteredQuery(interceptedStudyViewFilter); - List eventTypeCounts = this.getInstance().cachedClinicalEventTypeCounts(interceptedStudyViewFilter, - unfilteredQuery); - return new ResponseEntity<>(eventTypeCounts, HttpStatus.OK); - } - - @Cacheable( - cacheResolver = "staticRepositoryCacheOneResolver", - condition = "@cacheEnabledConfig.getEnabled() && #unfilteredQuery" - ) - public List cachedClinicalEventTypeCounts(StudyViewFilter interceptedStudyViewFilter, - boolean unfilteredQuery - ) { - List filteredSampleIdentifiers = studyViewFilterApplier.apply(interceptedStudyViewFilter); - List sampleIds = new ArrayList<>(); - List studyIds = new ArrayList<>(); - studyViewFilterUtil.extractStudyAndSampleIds(filteredSampleIdentifiers, studyIds, sampleIds); - return clinicalEventService.getClinicalEventTypeCounts(studyIds, sampleIds); - } - - @PreAuthorize("hasPermission(#involvedCancerStudies, 'Collection', T(org.cbioportal.utils.security.AccessLevel).READ)") - @RequestMapping(value = "/mutation-data-counts/fetch", method = RequestMethod.POST, - consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "Fetch mutation data counts by GenomicDataCountFilter") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(array = @ArraySchema(schema = @Schema(implementation = GenomicDataCountItem.class)))) - public ResponseEntity> fetchMutationDataCounts( - @Parameter(description = "Level of detail of the response") - @RequestParam(defaultValue = "SUMMARY") Projection projection, - @Parameter(required = true, description = "Genomic data count filter") - @Valid @RequestBody(required = false) GenomicDataCountFilter genomicDataCountFilter, - @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface - @RequestAttribute(required = false, value = "involvedCancerStudies") Collection involvedCancerStudies, - @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface - @Valid @RequestAttribute(required = false, value = "interceptedGenomicDataCountFilter") GenomicDataCountFilter interceptedGenomicDataCountFilter - ) { - List genomicDataFilters = interceptedGenomicDataCountFilter.getGenomicDataFilters(); - StudyViewFilter studyViewFilter = interceptedGenomicDataCountFilter.getStudyViewFilter(); - // when there is only one filter, it means study view is doing a single chart filter operation - // remove filter from studyViewFilter to return all data counts - // the reason we do this is to make sure after chart get filtered, user can still see unselected portion of the chart - if (genomicDataFilters.size() == 1 && projection == Projection.SUMMARY) { - studyViewFilterUtil.removeSelfFromMutationDataFilter( - genomicDataFilters.get(0).getHugoGeneSymbol(), - genomicDataFilters.get(0).getProfileType(), - MutationOption.MUTATED, - studyViewFilter); - } - - List filteredSampleIdentifiers = studyViewFilterApplier.apply(studyViewFilter); - - if (filteredSampleIdentifiers.isEmpty()) { - return new ResponseEntity<>(new ArrayList<>(), HttpStatus.OK); - } - - List studyIds = new ArrayList<>(); - List sampleIds = new ArrayList<>(); - studyViewFilterUtil.extractStudyAndSampleIds(filteredSampleIdentifiers, studyIds, sampleIds); - - List result; - - result = projection == Projection.SUMMARY ? - studyViewService.getMutationCountsByGeneSpecific( - studyIds, - sampleIds, - genomicDataFilters.stream().map(genomicDataFilter -> new Pair<>(genomicDataFilter.getHugoGeneSymbol(), genomicDataFilter.getProfileType())).toList(), - studyViewFilter.getAlterationFilter() - ) : - studyViewService.getMutationTypeCountsByGeneSpecific( - studyIds, - sampleIds, - genomicDataFilters.stream().map(genomicDataFilter -> new Pair<>(genomicDataFilter.getHugoGeneSymbol(), genomicDataFilter.getProfileType())).toList() - ); - - return new ResponseEntity<>(result, HttpStatus.OK); - } -} diff --git a/src/main/java/org/cbioportal/web/SurvivalController.java b/src/main/java/org/cbioportal/web/SurvivalController.java deleted file mode 100644 index 06e5e68b74d..00000000000 --- a/src/main/java/org/cbioportal/web/SurvivalController.java +++ /dev/null @@ -1,84 +0,0 @@ -package org.cbioportal.web; - -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.media.ArraySchema; -import io.swagger.v3.oas.annotations.media.Content; -import io.swagger.v3.oas.annotations.media.Schema; -import io.swagger.v3.oas.annotations.responses.ApiResponse; -import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.validation.Valid; -import org.cbioportal.model.ClinicalData; -import org.cbioportal.service.ClinicalEventService; -import org.cbioportal.web.config.annotation.InternalApi; -import org.cbioportal.web.parameter.PatientIdentifier; -import org.cbioportal.web.parameter.SurvivalRequest; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.cache.annotation.Cacheable; -import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.RequestAttribute; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestMethod; -import org.springframework.web.bind.annotation.RestController; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; - -@InternalApi -@RestController() -@RequestMapping("/api") -@Validated -@Tag(name = "Survival", description = " ") -public class SurvivalController { - private final ClinicalEventService clinicalEventService; - - @Autowired - public SurvivalController(ClinicalEventService clinicalEventService) { - this.clinicalEventService = clinicalEventService; - } - - @PreAuthorize("hasPermission(#involvedCancerStudies, 'Collection', T(org.cbioportal.utils.security.AccessLevel).READ)") - @RequestMapping(value = "/survival-data/fetch", - method = RequestMethod.POST, - consumes = MediaType.APPLICATION_JSON_VALUE, - produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "Fetch survival data") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(array = @ArraySchema(schema = @Schema(implementation = ClinicalData.class)))) - public ResponseEntity> fetchSurvivalData( - @Parameter(required = true, description = "Survival Data Request") - @Valid @RequestBody(required = false) SurvivalRequest survivalRequest, - @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface - @RequestAttribute(required = false, value = "involvedCancerStudies") Collection involvedCancerStudies, - @Parameter(hidden = true) - // prevent reference to this attribute in the swagger-ui interface. this attribute is needed for the @PreAuthorize tag above. - @Valid @RequestAttribute(required = false, value = "interceptedSurvivalRequest") SurvivalRequest interceptedSurvivalRequest) { - - return new ResponseEntity<>(cachedSurvivalData(interceptedSurvivalRequest), - HttpStatus.OK); - } - - @Cacheable( - cacheResolver = "generalRepositoryCacheResolver", - condition = "@cacheEnabledConfig.getEnabled()" - ) - public List cachedSurvivalData(SurvivalRequest interceptedSurvivalRequest) { - List studyIds = new ArrayList<>(); - List patientIds = new ArrayList<>(); - for (PatientIdentifier patientIdentifier : interceptedSurvivalRequest.getPatientIdentifiers()) { - studyIds.add(patientIdentifier.getStudyId()); - patientIds.add(patientIdentifier.getPatientId()); - } - - return clinicalEventService.getSurvivalData(studyIds, - patientIds, - interceptedSurvivalRequest.getAttributeIdPrefix(), - interceptedSurvivalRequest); - } -} diff --git a/src/main/java/org/cbioportal/web/TestController.java b/src/main/java/org/cbioportal/web/TestController.java deleted file mode 100644 index 3c227e7a97b..00000000000 --- a/src/main/java/org/cbioportal/web/TestController.java +++ /dev/null @@ -1,14 +0,0 @@ -package org.cbioportal.web; - -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RestController; - -@RestController -public class TestController { - - @GetMapping("/api/hello") - public String index() { - return "Greetings from Spring Boot!"; - } - -} diff --git a/src/main/java/org/cbioportal/web/TreatmentController.java b/src/main/java/org/cbioportal/web/TreatmentController.java deleted file mode 100644 index 370b7e9e99a..00000000000 --- a/src/main/java/org/cbioportal/web/TreatmentController.java +++ /dev/null @@ -1,213 +0,0 @@ -package org.cbioportal.web; - -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.media.ArraySchema; -import io.swagger.v3.oas.annotations.media.Content; -import io.swagger.v3.oas.annotations.media.Schema; -import io.swagger.v3.oas.annotations.responses.ApiResponse; -import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.validation.Valid; -import jakarta.validation.constraints.Size; -import org.cbioportal.model.ClinicalEventKeyCode; -import org.cbioportal.model.PatientTreatmentRow; -import org.cbioportal.model.SampleTreatmentRow; -import org.cbioportal.service.TreatmentService; -import org.cbioportal.web.config.annotation.InternalApi; -import org.cbioportal.web.parameter.PagingConstants; -import org.cbioportal.web.parameter.SampleIdentifier; -import org.cbioportal.web.parameter.StudyViewFilter; -import org.cbioportal.web.util.StudyViewFilterApplier; -import org.cbioportal.web.util.StudyViewFilterUtil; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.cache.annotation.Cacheable; -import org.springframework.context.ApplicationContext; -import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.RequestAttribute; -import org.springframework.web.bind.annotation.RequestBody; -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.bind.annotation.RestController; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.Objects; -import java.util.Set; - -@InternalApi -@RestController() -@RequestMapping("/api") -@Validated -@Tag(name = "Treatments", description = " ") -public class TreatmentController { - @Autowired - private ApplicationContext applicationContext; - TreatmentController instance; - - - @Autowired - private StudyViewFilterUtil studyViewFilterUtil; - @Autowired - private StudyViewFilterUtil filterUtil; - - @Autowired - private TreatmentService treatmentService; - - @Autowired - private StudyViewFilterApplier studyViewFilterApplier; - - private TreatmentController getInstance() { - if (Objects.isNull(instance)) { - instance = applicationContext.getBean(TreatmentController.class); - } - return instance; - } - @PreAuthorize("hasPermission(#involvedCancerStudies, 'Collection', T(org.cbioportal.utils.security.AccessLevel).READ)") - @RequestMapping(value = "/treatments/patient", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "Get all patient level treatments") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(array = @ArraySchema(schema = @Schema(implementation = PatientTreatmentRow.class)))) - public ResponseEntity> getAllPatientTreatments( - @Parameter(required = false ) - @RequestParam(name = "tier", required = false, defaultValue = "Agent") - ClinicalEventKeyCode tier, - - @Parameter(required = true, description = "Study view filter") - @Valid - @RequestBody(required = false) - StudyViewFilter studyViewFilter, - - @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface - @RequestAttribute(required = false, value = "involvedCancerStudies") - Collection involvedCancerStudies, - - @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface. this attribute is needed for the @PreAuthorize tag above. - @Valid - @RequestAttribute(required = false, value = "interceptedStudyViewFilter") - StudyViewFilter interceptedStudyViewFilter - ) { - boolean unfilteredQuery = studyViewFilterUtil.isUnfilteredQuery(interceptedStudyViewFilter); - List treatments = - this.getInstance().cachableGetAllPatientTreatments(tier, interceptedStudyViewFilter, unfilteredQuery); - return new ResponseEntity<>(treatments, HttpStatus.OK); - } - - @Cacheable( - cacheResolver = "staticRepositoryCacheOneResolver", - condition = "@cacheEnabledConfig.getEnabled() && #unfilteredQuery" - ) - public List cachableGetAllPatientTreatments( - ClinicalEventKeyCode tier, StudyViewFilter interceptedStudyViewFilter, boolean unfilteredQuery - ) { - List sampleIdentifiers = studyViewFilterApplier.apply(interceptedStudyViewFilter); - List sampleIds = new ArrayList<>(); - List studyIds = new ArrayList<>(); - filterUtil.extractStudyAndSampleIds(sampleIdentifiers, studyIds, sampleIds); - - return treatmentService.getAllPatientTreatmentRows(sampleIds, studyIds, tier); - } - - - @PreAuthorize("hasPermission(#involvedCancerStudies, 'Collection', T(org.cbioportal.utils.security.AccessLevel).READ)") - @RequestMapping(value = "/treatments/sample", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "Get all sample level treatments") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(array = @ArraySchema(schema = @Schema(implementation = SampleTreatmentRow.class)))) - public ResponseEntity> getAllSampleTreatments( - @Schema(defaultValue = "Agent") - @Parameter(required = false) - @RequestParam(name = "tier", required = false, defaultValue = "Agent") - ClinicalEventKeyCode tier, - - @Parameter(required = true, description = "Study view filter") - @Valid - @RequestBody(required = false) - StudyViewFilter studyViewFilter, - - @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface - @RequestAttribute(required = false, value = "involvedCancerStudies") - Collection involvedCancerStudies, - - @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface. this attribute is needed for the @PreAuthorize tag above. - @Valid - @RequestAttribute(required = false, value = "interceptedStudyViewFilter") - StudyViewFilter interceptedStudyViewFilter - ) { - boolean unfilteredQuery = studyViewFilterUtil.isUnfilteredQuery(interceptedStudyViewFilter); - List treatments = - this.getInstance().cacheableGetAllSampleTreatments(tier, interceptedStudyViewFilter, unfilteredQuery); - return new ResponseEntity<>(treatments, HttpStatus.OK); - } - - @Cacheable( - cacheResolver = "staticRepositoryCacheOneResolver", - condition = "@cacheEnabledConfig.getEnabled() && #unfilteredQuery" - ) - public List cacheableGetAllSampleTreatments( - ClinicalEventKeyCode tier, StudyViewFilter interceptedStudyViewFilter, boolean unfilteredQuery - ) { - List sampleIdentifiers = studyViewFilterApplier.apply(interceptedStudyViewFilter); - List sampleIds = new ArrayList<>(); - List studyIds = new ArrayList<>(); - filterUtil.extractStudyAndSampleIds(sampleIdentifiers, studyIds, sampleIds); - - return treatmentService.getAllSampleTreatmentRows(sampleIds, studyIds, tier); - } - - @PreAuthorize("hasPermission(#studyIds, 'Collection', T(org.cbioportal.utils.security.AccessLevel).READ)") - @RequestMapping(value = "/treatments/display-patient", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "Should patient level treatments be displayed") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(schema = @Schema(implementation = Boolean.class))) - public ResponseEntity getContainsTreatmentData( - @Schema(defaultValue = "Agent") - @Parameter(required = false) - @RequestParam(name = "tier", required = false, defaultValue = "Agent") - ClinicalEventKeyCode tier, - - @Parameter(required = true, description = "List of Study IDs") - @Size(min = 1, max = PagingConstants.MAX_PAGE_SIZE) - @RequestBody - Set studyIds - ) { - Boolean containsTreatmentData = this.getInstance().cacheableGetContainsTreatmentData(studyIds, tier); - return new ResponseEntity<>(containsTreatmentData, HttpStatus.OK); - } - - // Caching enabled for any number of studies as the requests contains only studyIds and the response is a boolean - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - public Boolean cacheableGetContainsTreatmentData(Set studyIds, ClinicalEventKeyCode tier) { - return treatmentService.containsTreatmentData(new ArrayList<>(studyIds), tier); - } - - @PreAuthorize("hasPermission(#studyIds, 'Collection', T(org.cbioportal.utils.security.AccessLevel).READ)") - @RequestMapping(value = "/treatments/display-sample", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "Should sample level treatments be displayed") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(schema = @Schema(implementation = Boolean.class))) - public ResponseEntity getContainsSampleTreatmentData( - @Schema(defaultValue = "Agent") - @Parameter(required = false) - @RequestParam(name = "tier", required = false, defaultValue = "Agent") - ClinicalEventKeyCode tier, - - @Parameter(required = true, description = "List of Study IDs") - @Size(min = 1, max = PagingConstants.MAX_PAGE_SIZE) - @RequestBody - Set studyIds - ) { - Boolean containsTreatmentData = this.getInstance().cacheableGetContainsSampleTreatmentData(studyIds, tier); - return new ResponseEntity<>(containsTreatmentData, HttpStatus.OK); - } - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - public Boolean cacheableGetContainsSampleTreatmentData(Set studyIds, ClinicalEventKeyCode tier) { - return treatmentService.containsSampleTreatmentData(new ArrayList<>(studyIds), tier); - } -} diff --git a/src/main/java/org/cbioportal/web/VariantCountController.java b/src/main/java/org/cbioportal/web/VariantCountController.java deleted file mode 100644 index cff905808e4..00000000000 --- a/src/main/java/org/cbioportal/web/VariantCountController.java +++ /dev/null @@ -1,69 +0,0 @@ -package org.cbioportal.web; - -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.media.ArraySchema; -import io.swagger.v3.oas.annotations.media.Content; -import io.swagger.v3.oas.annotations.media.Schema; -import io.swagger.v3.oas.annotations.responses.ApiResponse; -import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.validation.constraints.Size; -import org.cbioportal.model.VariantCount; -import org.cbioportal.service.VariantCountService; -import org.cbioportal.service.exception.MolecularProfileNotFoundException; -import org.cbioportal.web.config.annotation.InternalApi; -import org.cbioportal.web.parameter.VariantCountIdentifier; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestMethod; -import org.springframework.web.bind.annotation.RestController; - -import java.util.ArrayList; -import java.util.List; - -@InternalApi -@RestController() -@RequestMapping("/api") -@Validated -@Tag(name = "Variant Counts", description = " ") -public class VariantCountController { - - private static final int VARIANT_COUNT_MAX_PAGE_SIZE = 50000; - - @Autowired - private VariantCountService variantCountService; - - @PreAuthorize("hasPermission(#molecularProfileId, 'MolecularProfileId', T(org.cbioportal.utils.security.AccessLevel).READ)") - @RequestMapping(value = "/molecular-profiles/{molecularProfileId}/variant-counts/fetch", - method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE, - produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "Get counts of specific variants within a mutation molecular profile") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(array = @ArraySchema(schema = @Schema(implementation = VariantCount.class)))) - public ResponseEntity> fetchVariantCounts( - @Parameter(required = true, description = "Molecular Profile ID e.g. acc_tcga_mutations") - @PathVariable String molecularProfileId, - @Parameter(required = true, description = "List of variant count identifiers") - @Size(min = 1, max = VARIANT_COUNT_MAX_PAGE_SIZE) - @RequestBody List variantCountIdentifiers) throws MolecularProfileNotFoundException { - - List entrezGeneIds = new ArrayList<>(); - List keywords = new ArrayList<>(); - - for (VariantCountIdentifier variantCountIdentifier : variantCountIdentifiers) { - - entrezGeneIds.add(variantCountIdentifier.getEntrezGeneId()); - keywords.add(variantCountIdentifier.getKeyword()); - } - - return new ResponseEntity<>(variantCountService.fetchVariantCounts(molecularProfileId, entrezGeneIds, keywords), - HttpStatus.OK); - } -} diff --git a/src/main/java/org/cbioportal/web/columnar/BasicDataBinner.java b/src/main/java/org/cbioportal/web/columnar/BasicDataBinner.java deleted file mode 100644 index 1efaa2b01b9..00000000000 --- a/src/main/java/org/cbioportal/web/columnar/BasicDataBinner.java +++ /dev/null @@ -1,349 +0,0 @@ -package org.cbioportal.web.columnar; - -import org.cbioportal.model.*; -import org.cbioportal.service.CustomDataService; -import org.cbioportal.service.StudyViewColumnarService; -import org.cbioportal.service.util.CustomDataSession; -import org.cbioportal.utils.config.annotation.ConditionalOnProperty; -import org.cbioportal.web.columnar.util.CustomDataFilterUtil; -import org.cbioportal.web.columnar.util.NewClinicalDataBinUtil; -import org.cbioportal.web.parameter.*; -import org.cbioportal.web.util.DataBinner; -import org.cbioportal.web.util.StudyViewFilterUtil; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.cache.annotation.Cacheable; -import org.springframework.stereotype.Component; - -import java.util.*; -import java.util.stream.Collectors; - -import static java.util.Collections.emptyList; -import static java.util.stream.Collectors.toMap; - -// BasicDataBinner is a generalized class derived from ClinicalDataBinner -// BasicDataBinner should eventually deprecate ClinicalDataBinner -// we are using BasicDataBinner for genomic data, generic assay, and custom data bin counts now -// but BasicDataBinner can support clinical data counts too -// after we switched clinical data counts to use this, then We can remove ClinicalDataBinner -@Component -@ConditionalOnProperty(name = "clickhouse_mode", havingValue = "true") -public class BasicDataBinner { - private final StudyViewColumnarService studyViewColumnarService; - private final DataBinner dataBinner; - private final CustomDataFilterUtil customDataFilterUtil; - private final CustomDataService customDataService; - private final StudyViewFilterUtil studyViewFilterUtil; - - @Autowired - public BasicDataBinner( - StudyViewColumnarService studyViewColumnarService, - DataBinner dataBinner, - CustomDataFilterUtil customDataFilterUtil, - CustomDataService customDataService, - StudyViewFilterUtil studyViewFilterUtil - ) { - this.studyViewColumnarService = studyViewColumnarService; - this.dataBinner = dataBinner; - this.customDataFilterUtil = customDataFilterUtil; - this.customDataService = customDataService; - this.studyViewFilterUtil = studyViewFilterUtil; - } - - // convert from counts to clinical data - private List convertCountsToData(List clinicalDataCounts) - { - return clinicalDataCounts - .stream() - .map(NewClinicalDataBinUtil::generateClinicalDataFromClinicalDataCount) - .flatMap(Collection::stream) - .toList(); - } - - @Cacheable(cacheResolver = "generalRepositoryCacheResolver", condition = "@cacheEnabledConfig.getEnabled()") - public List getDataBins( - DataBinMethod dataBinMethod, - T dataBinCountFilter, - boolean shouldRemoveSelfFromFilter) { - // get data bin filters based on the type of the filter - // either Genomic data or Generic Assay data or custom data or clinical data - List dataBinFilters = fetchDataBinFilters(dataBinCountFilter); - StudyViewFilter studyViewFilter = dataBinCountFilter.getStudyViewFilter(); - // define result variables - List resultDataBins = Collections.emptyList(); - // if no data bin filters or no study view filer object is passed in - // return empty result - if (dataBinFilters.isEmpty() || studyViewFilter == null) { - return resultDataBins; - } - - if (shouldRemoveSelfFromFilter && dataBinFilters.size() == 1) { - removeSelfFromFilter(dataBinFilters.get(0), studyViewFilter); - } - - List uniqueKeys = dataBinFilters.stream().map(this::getDataBinFilterUniqueKey).toList(); - - // a new StudyView filter to partially filter by study and sample ids only - // we need this additional partial filter because we always need to know the bins generated for the initial state - // which allows us to keep the number of bins and bin ranges consistent even if there are additional data filters. - // we only want to update the counts for each bin, we don't want to regenerate the bins for the filtered data. - // NOTE: partial filter is only needed when dataBinMethod == DataBinMethod.STATIC but that's always the case - // for the frontend implementation. we can't really use dataBinMethod == DataBinMethod.DYNAMIC because of the - // complication it brings to the frontend visualization and filtering - StudyViewFilter partialFilter = new StudyViewFilter(); - partialFilter.setStudyIds(studyViewFilter.getStudyIds()); - partialFilter.setSampleIdentifiers(studyViewFilter.getSampleIdentifiers()); - - // we need to fetch data for the partial filter in order to generate the bins for initial state - // we use the filtered data to calculate the counts for each bin, we do not regenerate bins for the filtered data - List unfilteredClinicalDataCounts; - List filteredClinicalDataCounts; - Map attributeDatatypeMap; - switch (dataBinCountFilter) { - // TODO: first case is to support clinical data, but clinical data is not using this now. We should update controller to use this method later - case ClinicalDataBinCountFilter clinicalDataBinCountFilter when !customDataService.getCustomDataSessions(uniqueKeys).isEmpty() -> { - Map customDataSessions = customDataService.getCustomDataSessions(uniqueKeys); - List unfilteredSampleIdentifiers = studyViewColumnarService.getFilteredSamples(partialFilter).stream().map(sample -> studyViewFilterUtil.buildSampleIdentifier(sample.getCancerStudyIdentifier(), sample.getStableId())).toList(); - unfilteredClinicalDataCounts = customDataFilterUtil.getCustomDataCounts(unfilteredSampleIdentifiers, customDataSessions); - List filteredSampleIdentifiers = studyViewColumnarService.getFilteredSamples(studyViewFilter).stream().map(sample -> studyViewFilterUtil.buildSampleIdentifier(sample.getCancerStudyIdentifier(), sample.getStableId())).toList(); - filteredClinicalDataCounts = customDataFilterUtil.getCustomDataCounts(filteredSampleIdentifiers, customDataSessions); - attributeDatatypeMap = customDataSessions.entrySet().stream().collect(toMap( - Map.Entry::getKey, - NewClinicalDataBinUtil::getDataType - )); - } - case ClinicalDataBinCountFilter clinicalDataBinCountFilter -> { - unfilteredClinicalDataCounts = studyViewColumnarService.getClinicalDataCounts(partialFilter, uniqueKeys); - filteredClinicalDataCounts = studyViewColumnarService.getClinicalDataCounts(studyViewFilter, uniqueKeys); - attributeDatatypeMap = studyViewColumnarService.getClinicalAttributeDatatypeMap(studyViewFilter); - } - case GenomicDataBinCountFilter genomicDataBinCountFilter -> { - unfilteredClinicalDataCounts = studyViewColumnarService.getGenomicDataBinCounts(partialFilter, genomicDataBinCountFilter.getGenomicDataBinFilters()); - filteredClinicalDataCounts = studyViewColumnarService.getGenomicDataBinCounts(studyViewFilter, genomicDataBinCountFilter.getGenomicDataBinFilters()); - attributeDatatypeMap = Collections.emptyMap(); - } - case GenericAssayDataBinCountFilter genericAssayDataBinCountFilter -> { - unfilteredClinicalDataCounts = studyViewColumnarService.getGenericAssayDataBinCounts(partialFilter, genericAssayDataBinCountFilter.getGenericAssayDataBinFilters()); - filteredClinicalDataCounts = studyViewColumnarService.getGenericAssayDataBinCounts(studyViewFilter, genericAssayDataBinCountFilter.getGenericAssayDataBinFilters()); - attributeDatatypeMap = Collections.emptyMap(); - } - default -> { - unfilteredClinicalDataCounts = Collections.emptyList(); - filteredClinicalDataCounts = Collections.emptyList(); - attributeDatatypeMap = Collections.emptyMap(); - } - } - - // TODO ignoring conflictingPatientAttributeIds for now - List unfilteredClinicalData = convertCountsToData( - unfilteredClinicalDataCounts.stream().flatMap(c -> c.getCounts().stream()).toList() - ); - List filteredClinicalData = convertCountsToData( - filteredClinicalDataCounts.stream().flatMap(c -> c.getCounts().stream()).toList() - ); - - Map> unfilteredClinicalDataByAttributeId = - unfilteredClinicalData.stream().collect(Collectors.groupingBy(Binnable::getAttrId)); - - Map> filteredClinicalDataByAttributeId = - filteredClinicalData.stream().collect(Collectors.groupingBy(Binnable::getAttrId)); - - // TODO: need to update attributeDatatypeMap to include patient level data for Generic Assay Profiles - if (dataBinMethod == DataBinMethod.STATIC) { - if (!unfilteredClinicalData.isEmpty()) { - resultDataBins = calculateStaticDataBins( - dataBinner, - dataBinFilters, - attributeDatatypeMap, - unfilteredClinicalDataByAttributeId, - filteredClinicalDataByAttributeId - ); - } - } - // TODO: need to update attributeDatatypeMap to include patient level data for Generic Assay Profiles - else { // dataBinMethod == DataBinMethod.DYNAMIC - // TODO we should consider removing dynamic binning support - // we never use dynamic binning in the frontend because number of bins and the bin ranges can change - // each time there is a new filter which makes the frontend implementation complicated - if (!filteredClinicalData.isEmpty()) { - resultDataBins = calculateDynamicDataBins( - dataBinner, - dataBinFilters, - attributeDatatypeMap, - filteredClinicalDataByAttributeId - ); - } - } - - return resultDataBins; - } - - private void removeSelfFromFilter(S dataBinFilter, StudyViewFilter studyViewFilter) { - switch (dataBinFilter) { - case ClinicalDataBinFilter clinicalDataBinFilter -> { - if (studyViewFilter.getClinicalDataFilters() != null) { - studyViewFilter.getClinicalDataFilters().removeIf(f -> f.getAttributeId().equals(clinicalDataBinFilter.getAttributeId())); - } - if (studyViewFilter.getCustomDataFilters() != null) { - studyViewFilter.getCustomDataFilters().removeIf(f -> f.getAttributeId().equals(clinicalDataBinFilter.getAttributeId())); - } - } - case GenomicDataBinFilter genomicDataBinFilter when studyViewFilter.getGenomicDataFilters() != null -> - studyViewFilter.getGenomicDataFilters().removeIf(f -> - f.getHugoGeneSymbol().equals(genomicDataBinFilter.getHugoGeneSymbol()) - && f.getProfileType().equals(genomicDataBinFilter.getProfileType()) - ); - case GenericAssayDataBinFilter genericAssayDataBinFilter when studyViewFilter.getGenericAssayDataFilters() != null -> - studyViewFilter.getGenericAssayDataFilters().removeIf(f -> - f.getStableId().equals(genericAssayDataBinFilter.getStableId()) - && f.getProfileType().equals(genericAssayDataBinFilter.getProfileType()) - ); - default -> { - // Do not remove any filters - } - } - } - - private List fetchDataBinFilters(T dataBinCountFilter) { - switch (dataBinCountFilter) { - case ClinicalDataBinCountFilter clinicalDataBinCountFilter -> { - return (List) clinicalDataBinCountFilter.getAttributes(); - } - case GenomicDataBinCountFilter genomicDataBinCountFilter -> { - return (List) genomicDataBinCountFilter.getGenomicDataBinFilters(); - } - case GenericAssayDataBinCountFilter genericAssayDataBinCountFilter -> { - return (List) genericAssayDataBinCountFilter.getGenericAssayDataBinFilters(); - } - default -> { - return new ArrayList<>(); - } - } - } - - private String getDataBinFilterUniqueKey(S dataBinFilter) { - switch (dataBinFilter) { - case ClinicalDataBinFilter clinicalDataBinFilter -> { - return clinicalDataBinFilter.getAttributeId(); - } - case GenomicDataBinFilter genomicDataBinFilter -> { - return genomicDataBinFilter.getHugoGeneSymbol() + genomicDataBinFilter.getProfileType(); - } - case GenericAssayDataBinFilter genericAssayDataBinFilter -> { - return genericAssayDataBinFilter.getStableId() + genericAssayDataBinFilter.getProfileType(); - } - default -> { - return null; - } - } - } - - private List calculateStaticDataBins( - DataBinner dataBinner, - List dataBinFilters, - Map attributeDatatypeMap, - Map> unfilteredClinicalDataByAttributeId, - Map> filteredClinicalDataByAttributeId - ) { - List result = new ArrayList<>(); - - for (T dataBinFilter : dataBinFilters) { - // if there is data for requested attribute - if (attributeDatatypeMap.isEmpty() || attributeDatatypeMap.containsKey(getDataBinFilterUniqueKey(dataBinFilter))) { - List dataBins = dataBinner - .calculateClinicalDataBins( - dataBinFilter, - filteredClinicalDataByAttributeId.getOrDefault(getDataBinFilterUniqueKey(dataBinFilter), emptyList()), - unfilteredClinicalDataByAttributeId.getOrDefault(getDataBinFilterUniqueKey(dataBinFilter), emptyList()) - ) - .stream() - .map(dataBin -> (U) transform(dataBinFilter, dataBin)) - .toList(); - - result.addAll(dataBins); - } - } - - return result; - } - - private List calculateDynamicDataBins( - DataBinner dataBinner, - List dataBinFilters, - Map attributeDatatypeMap, - Map> filteredClinicalDataByAttributeId - ) { - List result = new ArrayList<>(); - - for (T dataBinFilter : dataBinFilters) { - // if there is data for requested attribute - if (attributeDatatypeMap.isEmpty() || attributeDatatypeMap.containsKey(getDataBinFilterUniqueKey(dataBinFilter))) { - List dataBins = dataBinner - .calculateDataBins( - dataBinFilter, - filteredClinicalDataByAttributeId.getOrDefault(getDataBinFilterUniqueKey(dataBinFilter), emptyList()) - ) - .stream() - .map(dataBin -> (U) transform(dataBinFilter, dataBin)) - .toList(); - result.addAll(dataBins); - } - } - - return result; - } - - private T transform(S dataBinFilter, DataBin dataBin) { - switch (dataBinFilter) { - case ClinicalDataBinFilter clinicalDataBinFilter -> { - return (T) dataBinToClinicalDataBin(clinicalDataBinFilter, dataBin); - } - case GenomicDataBinFilter genomicDataBinFilter -> { - return (T) dataBintoGenomicDataBin(genomicDataBinFilter, dataBin); - } - case GenericAssayDataBinFilter genericAssayDataBinFilter -> { - return (T) dataBintoGenericAssayDataBin(genericAssayDataBinFilter, dataBin); - } - default -> { - return null; - } - } - } - - private ClinicalDataBin dataBinToClinicalDataBin(ClinicalDataBinFilter attribute, DataBin dataBin) { - ClinicalDataBin clinicalDataBin = new ClinicalDataBin(); - clinicalDataBin.setAttributeId(attribute.getAttributeId()); - setCommonDataBinProperties(dataBin, clinicalDataBin); - return clinicalDataBin; - } - - private GenomicDataBin dataBintoGenomicDataBin(GenomicDataBinFilter genomicDataBinFilter, DataBin dataBin) { - GenomicDataBin genomicDataBin = new GenomicDataBin(); - genomicDataBin.setHugoGeneSymbol(genomicDataBinFilter.getHugoGeneSymbol()); - genomicDataBin.setProfileType(genomicDataBinFilter.getProfileType()); - setCommonDataBinProperties(dataBin, genomicDataBin); - return genomicDataBin; - } - - private GenericAssayDataBin dataBintoGenericAssayDataBin(GenericAssayDataBinFilter genericAssayDataBinFilter, - DataBin dataBin) { - GenericAssayDataBin genericAssayDataBin = new GenericAssayDataBin(); - genericAssayDataBin.setStableId(genericAssayDataBinFilter.getStableId()); - genericAssayDataBin.setProfileType(genericAssayDataBinFilter.getProfileType()); - setCommonDataBinProperties(dataBin, genericAssayDataBin); - return genericAssayDataBin; - } - - private void setCommonDataBinProperties(DataBin originalDataBin, U targetDatabin) { - targetDatabin.setCount(originalDataBin.getCount()); - if (originalDataBin.getSpecialValue() != null) { - targetDatabin.setSpecialValue(originalDataBin.getSpecialValue()); - } - if (originalDataBin.getStart() != null) { - targetDatabin.setStart(originalDataBin.getStart()); - } - if (originalDataBin.getEnd() != null) { - targetDatabin.setEnd(originalDataBin.getEnd()); - } - } - -} diff --git a/src/main/java/org/cbioportal/web/columnar/ClinicalDataBinner.java b/src/main/java/org/cbioportal/web/columnar/ClinicalDataBinner.java deleted file mode 100644 index b14d6726dbc..00000000000 --- a/src/main/java/org/cbioportal/web/columnar/ClinicalDataBinner.java +++ /dev/null @@ -1,127 +0,0 @@ -package org.cbioportal.web.columnar; - -import org.cbioportal.model.Binnable; -import org.cbioportal.model.ClinicalData; -import org.cbioportal.model.ClinicalDataBin; -import org.cbioportal.model.ClinicalDataCount; -import org.cbioportal.model.ClinicalDataCountItem; -import org.cbioportal.service.StudyViewColumnarService; -import org.cbioportal.utils.config.annotation.ConditionalOnProperty; -import org.cbioportal.web.columnar.util.NewClinicalDataBinUtil; -import org.cbioportal.web.parameter.ClinicalDataBinCountFilter; -import org.cbioportal.web.parameter.ClinicalDataBinFilter; -import org.cbioportal.web.parameter.ClinicalDataType; -import org.cbioportal.web.parameter.DataBinMethod; -import org.cbioportal.web.parameter.StudyViewFilter; -import org.cbioportal.web.util.DataBinner; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.cache.annotation.Cacheable; -import org.springframework.stereotype.Component; - -import java.util.*; -import java.util.stream.Collectors; - -@Component -@ConditionalOnProperty(name = "clickhouse_mode", havingValue = "true") -public class ClinicalDataBinner { - private final StudyViewColumnarService studyViewColumnarService; - private final DataBinner dataBinner; - - @Autowired - public ClinicalDataBinner( - StudyViewColumnarService studyViewColumnarService, - DataBinner dataBinner - ) { - this.studyViewColumnarService = studyViewColumnarService; - this.dataBinner = dataBinner; - } - - private List convertCountsToData(List clinicalDataCounts) - { - return clinicalDataCounts - .stream() - .map(NewClinicalDataBinUtil::generateClinicalDataFromClinicalDataCount) - .flatMap(Collection::stream) - .toList(); - } - - @Cacheable( - cacheResolver = "staticRepositoryCacheOneResolver", - condition = "@cacheEnabledConfig.getEnabled()" - ) - public List fetchClinicalDataBinCounts( - DataBinMethod dataBinMethod, - ClinicalDataBinCountFilter dataBinCountFilter, - boolean shouldRemoveSelfFromFilter - ) { - List attributes = dataBinCountFilter.getAttributes(); - StudyViewFilter studyViewFilter = dataBinCountFilter.getStudyViewFilter(); - - if (shouldRemoveSelfFromFilter) { - studyViewFilter = NewClinicalDataBinUtil.removeSelfFromFilter(dataBinCountFilter); - } - - List attributeIds = attributes.stream().map(ClinicalDataBinFilter::getAttributeId).collect(Collectors.toList()); - - // a new StudyView filter to partially filter by study and sample ids only - // we need this additional partial filter because we always need to know the bins generated for the initial state - // which allows us to keep the number of bins and bin ranges consistent even if there are additional data filters. - // we only want to update the counts for each bin, we don't want to regenerate the bins for the filtered data. - // NOTE: partial filter is only needed when dataBinMethod == DataBinMethod.STATIC but that's always the case - // for the frontend implementation. we can't really use dataBinMethod == DataBinMethod.DYNAMIC because of the - // complication it brings to the frontend visualization and filtering - StudyViewFilter partialFilter = new StudyViewFilter(); - partialFilter.setStudyIds(studyViewFilter.getStudyIds()); - partialFilter.setSampleIdentifiers(studyViewFilter.getSampleIdentifiers()); - - // we need the clinical data for the partial filter in order to generate the bins for initial state - // we use the filtered data to calculate the counts for each bin, we do not regenerate bins for the filtered data - List unfilteredClinicalDataCounts = studyViewColumnarService.getClinicalDataCounts(partialFilter, attributeIds); - List filteredClinicalDataCounts = studyViewColumnarService.getClinicalDataCounts(studyViewFilter, attributeIds); - - // TODO ignoring conflictingPatientAttributeIds for now - List unfilteredClinicalData = convertCountsToData( - unfilteredClinicalDataCounts.stream().flatMap(c -> c.getCounts().stream()).toList() - ); - List filteredClinicalData = convertCountsToData( - filteredClinicalDataCounts.stream().flatMap(c -> c.getCounts().stream()).toList() - ); - - Map attributeDatatypeMap = studyViewColumnarService.getClinicalAttributeDatatypeMap(studyViewFilter); - - Map> unfilteredClinicalDataByAttributeId = - unfilteredClinicalData.stream().collect(Collectors.groupingBy(Binnable::getAttrId)); - - Map> filteredClinicalDataByAttributeId = - filteredClinicalData.stream().collect(Collectors.groupingBy(Binnable::getAttrId)); - - List clinicalDataBins = Collections.emptyList(); - - if (dataBinMethod == DataBinMethod.STATIC) { - if (!unfilteredClinicalData.isEmpty()) { - clinicalDataBins = NewClinicalDataBinUtil.calculateStaticDataBins( - dataBinner, - attributes, - attributeDatatypeMap, - unfilteredClinicalDataByAttributeId, - filteredClinicalDataByAttributeId - ); - } - } - else { // dataBinMethod == DataBinMethod.DYNAMIC - // TODO we should consider removing dynamic binning support - // we never use dynamic binning in the frontend because number of bins and the bin ranges can change - // each time there is a new filter which makes the frontend implementation complicated - if (!filteredClinicalData.isEmpty()) { - clinicalDataBins = NewClinicalDataBinUtil.calculateDynamicDataBins( - dataBinner, - attributes, - attributeDatatypeMap, - filteredClinicalDataByAttributeId - ); - } - } - - return clinicalDataBins; - } -} diff --git a/src/main/java/org/cbioportal/web/columnar/StudyViewColumnStoreController.java b/src/main/java/org/cbioportal/web/columnar/StudyViewColumnStoreController.java deleted file mode 100644 index 39fc7001b8b..00000000000 --- a/src/main/java/org/cbioportal/web/columnar/StudyViewColumnStoreController.java +++ /dev/null @@ -1,679 +0,0 @@ -package org.cbioportal.web.columnar; - -import io.swagger.v3.oas.annotations.Hidden; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.media.ArraySchema; -import io.swagger.v3.oas.annotations.media.Content; -import io.swagger.v3.oas.annotations.media.Schema; -import io.swagger.v3.oas.annotations.responses.ApiResponse; -import jakarta.validation.Valid; -import org.cbioportal.model.AlterationCountByGene; -import org.cbioportal.model.AlterationFilter; -import org.cbioportal.model.CaseListDataCount; -import org.cbioportal.model.ClinicalData; -import org.cbioportal.model.ClinicalDataBin; -import org.cbioportal.model.ClinicalDataCountItem; -import org.cbioportal.model.ClinicalEventKeyCode; -import org.cbioportal.model.ClinicalEventTypeCount; -import org.cbioportal.model.ClinicalViolinPlotData; -import org.cbioportal.model.CopyNumberCountByGene; -import org.cbioportal.model.DensityPlotData; -import org.cbioportal.model.GenericAssayDataBin; -import org.cbioportal.model.GenericAssayDataCountItem; -import org.cbioportal.model.GenomicDataBin; -import org.cbioportal.model.GenomicDataCount; -import org.cbioportal.model.PatientTreatmentReport; -import org.cbioportal.model.Sample; -import org.cbioportal.model.SampleTreatmentReport; -import org.cbioportal.service.ClinicalDataDensityPlotService; -import org.cbioportal.model.GenomicDataCountItem; -import org.cbioportal.service.CustomDataService; -import org.cbioportal.service.StudyViewColumnarService; -import org.cbioportal.service.ViolinPlotService; -import org.cbioportal.service.exception.StudyNotFoundException; -import org.cbioportal.service.util.CustomDataSession; -import org.cbioportal.utils.config.annotation.ConditionalOnProperty; -import org.cbioportal.web.columnar.util.CustomDataFilterUtil; -import org.cbioportal.web.columnar.util.NewStudyViewFilterUtil; -import org.cbioportal.web.config.annotation.InternalApi; -import org.cbioportal.web.parameter.ClinicalDataBinCountFilter; -import org.cbioportal.web.parameter.ClinicalDataCountFilter; -import org.cbioportal.web.parameter.ClinicalDataFilter; -import org.cbioportal.web.parameter.DataBinMethod; -import org.cbioportal.web.parameter.GenericAssayDataBinCountFilter; -import org.cbioportal.web.parameter.GenericAssayDataCountFilter; -import org.cbioportal.web.parameter.GenericAssayDataFilter; -import org.cbioportal.web.parameter.GenomicDataBinCountFilter; -import org.cbioportal.web.parameter.GenomicDataCountFilter; -import org.cbioportal.web.parameter.GenomicDataFilter; -import org.cbioportal.web.parameter.MutationOption; -import org.cbioportal.web.parameter.Projection; -import org.cbioportal.web.parameter.SampleIdentifier; -import org.cbioportal.web.parameter.StudyViewFilter; -import org.cbioportal.web.util.DensityPlotParameters; -import org.cbioportal.web.util.StudyViewFilterUtil; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.RequestAttribute; -import org.springframework.web.bind.annotation.RequestBody; -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.bind.annotation.RestController; - -import java.math.BigDecimal; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - -@InternalApi -@RestController() -@RequestMapping("/api") -@Validated -@ConditionalOnProperty(name = "clickhouse_mode", havingValue = "true") -public class StudyViewColumnStoreController { - - private final StudyViewColumnarService studyViewColumnarService; - private final ClinicalDataBinner clinicalDataBinner; - - private final BasicDataBinner basicDataBinner; - private final ClinicalDataDensityPlotService clinicalDataDensityPlotService; - private final ViolinPlotService violinPlotService; - private final CustomDataService customDataService; - private final StudyViewFilterUtil studyViewFilterUtil; - private final CustomDataFilterUtil customDataFilterUtil; - - @Autowired - public StudyViewColumnStoreController(StudyViewColumnarService studyViewColumnarService, - ClinicalDataBinner clinicalDataBinner, - BasicDataBinner basicDataBinner, - ClinicalDataDensityPlotService clinicalDataDensityPlotService, - ViolinPlotService violinPlotService, - CustomDataService customDataService, - StudyViewFilterUtil studyViewFilterUtil, - CustomDataFilterUtil customDataFilterUtil - ) { - this.studyViewColumnarService = studyViewColumnarService; - this.clinicalDataBinner = clinicalDataBinner; - this.basicDataBinner = basicDataBinner; - this.clinicalDataDensityPlotService = clinicalDataDensityPlotService; - this.violinPlotService = violinPlotService; - this.customDataService = customDataService; - this.studyViewFilterUtil = studyViewFilterUtil; - this.customDataFilterUtil = customDataFilterUtil; - } - - - @Hidden // should unhide when we remove legacy controller - @PreAuthorize("hasPermission(#involvedCancerStudies, 'Collection', T(org.cbioportal.utils.security.AccessLevel).READ)") - @RequestMapping(value = "/column-store/filtered-samples/fetch", - consumes = MediaType.APPLICATION_JSON_VALUE, method=RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE) - public ResponseEntity> fetchFilteredSamples( - @RequestParam(defaultValue = "false") Boolean negateFilters, - @RequestAttribute(required = false, value = "involvedCancerStudies") Collection involvedCancerStudies, - @RequestAttribute(required = false, value = "interceptedStudyViewFilter") StudyViewFilter interceptedStudyViewFilter, - @RequestBody(required = false) StudyViewFilter studyViewFilter) { - return new ResponseEntity<>( - studyViewColumnarService.getFilteredSamples(interceptedStudyViewFilter), - HttpStatus.OK - ); - } - - @Hidden // should unhide when we remove legacy controller - @PreAuthorize("hasPermission(#involvedCancerStudies, 'Collection', T(org.cbioportal.utils.security.AccessLevel).READ)") - @RequestMapping(value = "/column-store/mutated-genes/fetch", - consumes = MediaType.APPLICATION_JSON_VALUE, method=RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE) - public ResponseEntity> fetchMutatedGenes( - @RequestBody(required = false) StudyViewFilter studyViewFilter, - @RequestAttribute(required = false, value = "involvedCancerStudies") Collection involvedCancerStudies, - @RequestAttribute(required = false, value = "interceptedStudyViewFilter") StudyViewFilter interceptedStudyViewFilter - ) throws StudyNotFoundException { - AlterationFilter annotationFilters = interceptedStudyViewFilter.getAlterationFilter(); - return new ResponseEntity<>( - studyViewColumnarService.getMutatedGenes(interceptedStudyViewFilter), - HttpStatus.OK - ); - } - - @Hidden // should unhide when we remove legacy controller - @PreAuthorize("hasPermission(#involvedCancerStudies, 'Collection', T(org.cbioportal.utils.security.AccessLevel).READ)") - @RequestMapping(value = "/column-store/molecular-profile-sample-counts/fetch", method = RequestMethod.POST, - consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "Fetch sample counts by study view filter") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(array = @ArraySchema(schema = @Schema(implementation = GenomicDataCount.class)))) - public ResponseEntity> fetchMolecularProfileSampleCounts( - @Parameter(required = true, description = "Study view filter") - @Valid @RequestBody(required = false) StudyViewFilter studyViewFilter, - @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface - @RequestAttribute(required = false, value = "involvedCancerStudies") Collection involvedCancerStudies, - @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface. this attribute is needed for the @PreAuthorize tag above. - @Valid @RequestAttribute(required = false, value = "interceptedStudyViewFilter") StudyViewFilter interceptedStudyViewFilter - ) - { - return new ResponseEntity>( - studyViewColumnarService.getMolecularProfileSampleCounts(interceptedStudyViewFilter) - , HttpStatus.OK); - } - - @Hidden // should unhide when we remove legacy controller - @RequestMapping(value = "/column-store/cna-genes/fetch", - consumes = MediaType.APPLICATION_JSON_VALUE, method=RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE) - public ResponseEntity> fetchCnaGenes( - @RequestBody(required = false) StudyViewFilter studyViewFilter, - @RequestAttribute(required = false, value = "involvedCancerStudies") Collection involvedCancerStudies, - @RequestAttribute(required = false, value = "interceptedStudyViewFilter") StudyViewFilter interceptedStudyViewFilter - ) throws StudyNotFoundException { - return new ResponseEntity<>( - studyViewColumnarService.getCnaGenes(interceptedStudyViewFilter), - HttpStatus.OK - ); - } - - @Hidden // should unhide when we remove legacy controller - @RequestMapping(value = "/column-store/structuralvariant-genes/fetch", - consumes = MediaType.APPLICATION_JSON_VALUE, method=RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "Fetch structural variant genes by study view filter") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(array = @ArraySchema(schema = @Schema(implementation = AlterationCountByGene.class)))) - public ResponseEntity> fetchStructuralVariantGenes( - @Parameter(required = true, description = "Study view filter") - @Valid @RequestBody(required = false) StudyViewFilter studyViewFilter, - @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface. This attribute is needed for the @PreAuthorize tag above. - @RequestAttribute(required = false, value = "involvedCancerStudies") Collection involvedCancerStudies, - @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface. - @Valid @RequestAttribute(required = false, value = "interceptedStudyViewFilter") StudyViewFilter interceptedStudyViewFilter - ) throws StudyNotFoundException { - return new ResponseEntity<>(studyViewColumnarService.getStructuralVariantGenes(interceptedStudyViewFilter), HttpStatus.OK); - } - - @Hidden // should unhide when we remove legacy controller - @PreAuthorize("hasPermission(#involvedCancerStudies, 'Collection', T(org.cbioportal.utils.security.AccessLevel).READ)") - @RequestMapping(value = "/column-store/clinical-data-counts/fetch", - method=RequestMethod.POST, - consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) - public ResponseEntity> fetchClinicalDataCounts( - @RequestBody(required = false) ClinicalDataCountFilter clinicalDataCountFilter, - @RequestAttribute(required = false, value = "involvedCancerStudies") Collection involvedCancerStudies, - @RequestAttribute(required = false, value = "interceptedClinicalDataCountFilter") ClinicalDataCountFilter interceptedClinicalDataCountFilter) { - - List attributes = interceptedClinicalDataCountFilter.getAttributes(); - StudyViewFilter studyViewFilter = interceptedClinicalDataCountFilter.getStudyViewFilter(); - - if (attributes.size() == 1) { - NewStudyViewFilterUtil.removeClinicalDataFilter(attributes.getFirst().getAttributeId(), studyViewFilter.getClinicalDataFilters()); - } - List result = studyViewColumnarService.getClinicalDataCounts( - studyViewFilter, - attributes.stream().map(ClinicalDataFilter::getAttributeId).collect(Collectors.toList())); - return new ResponseEntity<>(result, HttpStatus.OK); - - } - - @Hidden // should unhide when we remove legacy controller - @PreAuthorize("hasPermission(#involvedCancerStudies, 'Collection', T(org.cbioportal.utils.security.AccessLevel).READ)") - @RequestMapping(value = "/column-store/sample-lists-counts/fetch", method = RequestMethod.POST, - consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "Fetch case list sample counts by study view filter") - public List fetchCaseListCounts( - @Parameter(required = true, description = "Study view filter") - @Valid @RequestBody(required = false) StudyViewFilter studyViewFilter, - @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface - @RequestAttribute(required = false, value = "involvedCancerStudies") Collection involvedCancerStudies, - @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface. this attribute is needed for the @PreAuthorize tag above. - @Valid @RequestAttribute(required = false, value = "interceptedStudyViewFilter") StudyViewFilter interceptedStudyViewFilter) { - - return studyViewColumnarService.getCaseListDataCounts(interceptedStudyViewFilter); - - } - - @Hidden // should unhide when we remove legacy controller - @PreAuthorize("hasPermission(#involvedCancerStudies, 'Collection', T(org.cbioportal.utils.security.AccessLevel).READ)") - @RequestMapping(value = "/column-store/clinical-data-bin-counts/fetch", method = RequestMethod.POST, - consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) - public ResponseEntity> fetchClinicalDataBinCounts( - @RequestParam(defaultValue = "DYNAMIC") DataBinMethod dataBinMethod, - @RequestBody(required = false) ClinicalDataBinCountFilter clinicalDataBinCountFilter, - @RequestAttribute(required = false, value = "involvedCancerStudies") Collection involvedCancerStudies, - @RequestAttribute(required = false, value = "interceptedClinicalDataBinCountFilter") ClinicalDataBinCountFilter interceptedClinicalDataBinCountFilter - ) { - List clinicalDataBins = clinicalDataBinner.fetchClinicalDataBinCounts( - dataBinMethod, - interceptedClinicalDataBinCountFilter, - true - ); - return new ResponseEntity<>(clinicalDataBins, HttpStatus.OK); - } - - @Hidden // should unhide when we remove legacy controller - @PreAuthorize("hasPermission(#involvedCancerStudies, 'Collection', T(org.cbioportal.utils.security.AccessLevel).READ)") - @RequestMapping(value = "/column-store/clinical-data-density-plot/fetch", - method = RequestMethod.POST, - consumes = MediaType.APPLICATION_JSON_VALUE, - produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "Fetch clinical data density plot bins by study view filter") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(schema = @Schema(implementation = DensityPlotData.class))) - @Validated - public ResponseEntity fetchClinicalDataDensityPlot( - @Parameter(required = true, description = "Clinical Attribute ID of the X axis") - @RequestParam String xAxisAttributeId, - @Parameter(description = "Number of the bins in X axis") - @RequestParam(defaultValue = "50") Integer xAxisBinCount, - @Parameter(description = "Starting point of the X axis, if different than smallest value") - @RequestParam(required = false) BigDecimal xAxisStart, - @Parameter(description = "Starting point of the X axis, if different than largest value") - @RequestParam(required = false) BigDecimal xAxisEnd, - @Parameter(required = true, description = "Clinical Attribute ID of the Y axis") - @RequestParam String yAxisAttributeId, - @Parameter(description = "Number of the bins in Y axis") - @RequestParam(defaultValue = "50") Integer yAxisBinCount, - @Parameter(description = "Starting point of the Y axis, if different than smallest value") - @RequestParam(required = false) BigDecimal yAxisStart, - @Parameter(description = "Starting point of the Y axis, if different than largest value") - @RequestParam(required = false) BigDecimal yAxisEnd, - @Parameter(description="Use log scale for X axis") - @RequestParam(required = false, defaultValue = "false") Boolean xAxisLogScale, - @Schema(defaultValue = "false") - @Parameter(description="Use log scale for Y axis") - @RequestParam(required = false, defaultValue = "false") Boolean yAxisLogScale, - @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface - @RequestAttribute(required = false, value = "involvedCancerStudies") Collection involvedCancerStudies, - @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface. this attribute is needed for the @PreAuthorize tag above. - @Valid @RequestAttribute(required = false, value = "interceptedStudyViewFilter") StudyViewFilter interceptedStudyViewFilter, - @Parameter(required = true, description = "Study view filter") - @RequestBody(required = false) StudyViewFilter studyViewFilter - ) { - DensityPlotParameters densityPlotParameters = - new DensityPlotParameters.Builder() - .xAxisAttributeId(xAxisAttributeId) - .yAxisAttributeId(yAxisAttributeId) - .xAxisBinCount(xAxisBinCount) - .yAxisBinCount(yAxisBinCount) - .xAxisStart(xAxisStart) - .yAxisStart(yAxisStart) - .xAxisEnd(xAxisEnd) - .yAxisEnd(yAxisEnd) - .xAxisLogScale(xAxisLogScale) - .yAxisLogScale(yAxisLogScale) - .build(); - - List combinedClinicalDataList = studyViewColumnarService.fetchClinicalDataForXyPlot( - interceptedStudyViewFilter, - List.of(xAxisAttributeId, yAxisAttributeId), - false - ); - - DensityPlotData result = clinicalDataDensityPlotService.getDensityPlotData( - combinedClinicalDataList, - densityPlotParameters, - interceptedStudyViewFilter - ); - - return new ResponseEntity<>(result, HttpStatus.OK); - } - - @Hidden // should unhide when we remove legacy controller - @PreAuthorize("hasPermission(#involvedCancerStudies, 'Collection', T(org.cbioportal.utils.security.AccessLevel).READ)") - @RequestMapping(value = "/column-store/clinical-data-violin-plots/fetch", - method = RequestMethod.POST, - consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "Fetch violin plot curves per categorical clinical data value, filtered by study view filter") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(schema = @Schema(implementation = ClinicalViolinPlotData.class))) - public ResponseEntity fetchClinicalDataViolinPlots( - @Parameter(required = true, description = "Clinical Attribute ID of the categorical attribute") - @RequestParam String categoricalAttributeId, - @Parameter(required = true, description = "Clinical Attribute ID of the numerical attribute") - @RequestParam String numericalAttributeId, - @Parameter(description = "Starting point of the violin plot axis, if different than smallest value") - @RequestParam(required = false) BigDecimal axisStart, - @Parameter(description = "Ending point of the violin plot axis, if different than largest value") - @RequestParam(required = false) BigDecimal axisEnd, - @Parameter(description = "Number of points in the curve") - @RequestParam(required = false, defaultValue = "100") BigDecimal numCurvePoints, - @Parameter(description="Use log scale for the numerical attribute") - @RequestParam(required = false, defaultValue = "false") Boolean logScale, - @Parameter(description="Sigma stepsize multiplier") - @RequestParam(required = false, defaultValue = "1") BigDecimal sigmaMultiplier, - @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface - @RequestAttribute(required = false, value = "involvedCancerStudies") Collection involvedCancerStudies, - @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface. this attribute is needed for the @PreAuthorize tag above. - @Valid @RequestAttribute(required = false, value = "interceptedStudyViewFilter") StudyViewFilter interceptedStudyViewFilter, - @Parameter(required = true, description = "Study view filter") - @Valid @RequestBody(required = false) StudyViewFilter studyViewFilter - ) { - // fetch the samples by using the provided study view filter - List filteredSamples = studyViewColumnarService.getFilteredSamples(interceptedStudyViewFilter); - - // remove the numerical clinical data filter from the study view filter. - // this new modified filter is used to fetch sample and patient clinical data. - // this is required to get the complete violin plot data. - // filteredSamples reflects only the original unmodified study view filter. - // we will need to fetch samples again to get the samples corresponding to this modified filter, - // otherwise patient to sample mapping may be incomplete. - if (interceptedStudyViewFilter.getClinicalDataFilters() != null) { - interceptedStudyViewFilter.getClinicalDataFilters().stream() - .filter(f->f.getAttributeId().equals(numericalAttributeId)) - .findAny() - .ifPresent(f->interceptedStudyViewFilter.getClinicalDataFilters().remove(f)); - } - - List combinedClinicalDataList = studyViewColumnarService.fetchClinicalDataForXyPlot( - interceptedStudyViewFilter, - List.of(numericalAttributeId, categoricalAttributeId), - true // filter out clinical data with empty attribute values due to Clickhouse migration - ); - - // Only mutation count can use log scale - boolean useLogScale = logScale && numericalAttributeId.equals("MUTATION_COUNT"); - - ClinicalViolinPlotData result = violinPlotService.getClinicalViolinPlotData( - combinedClinicalDataList, - filteredSamples, - axisStart, - axisEnd, - numCurvePoints, - useLogScale, - sigmaMultiplier, - interceptedStudyViewFilter - ); - - return new ResponseEntity<>(result, HttpStatus.OK); - } - - @Hidden // should unhide when we remove legacy controller - @PreAuthorize("hasPermission(#involvedCancerStudies, 'Collection', T(org.cbioportal.utils.security.AccessLevel).READ)") - @RequestMapping(value = "/column-store/genomic-data-counts/fetch", - method = RequestMethod.POST, - consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "Fetch genomic data counts by GenomicDataCountFilter") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(array = @ArraySchema(schema = @Schema(implementation = GenomicDataCountItem.class)))) - public ResponseEntity> fetchGenomicDataCounts( - @Parameter(required = true, description = "Genomic data count filter") @Valid @RequestBody(required = false) GenomicDataCountFilter genomicDataCountFilter, - @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface - @RequestAttribute(required = false, value = "involvedCancerStudies") Collection involvedCancerStudies, - @Parameter(required = true, description = "Intercepted Genomic Data Count Filter") - @Valid @RequestAttribute(required = false, value = "interceptedGenomicDataCountFilter") GenomicDataCountFilter interceptedGenomicDataCountFilter - ) throws StudyNotFoundException { - List genomicDataFilters = interceptedGenomicDataCountFilter.getGenomicDataFilters(); - StudyViewFilter studyViewFilter = interceptedGenomicDataCountFilter.getStudyViewFilter(); - // when there is only one filter, it means study view is doing a single chart filter operation - // remove filter from studyViewFilter to return all data counts - // the reason we do this is to make sure after chart get filtered, user can still see unselected portion of the chart - if (genomicDataFilters.size() == 1) { - studyViewFilterUtil.removeSelfFromGenomicDataFilter( - genomicDataFilters.get(0).getHugoGeneSymbol(), - genomicDataFilters.get(0).getProfileType(), - studyViewFilter); - } - - // This endpoint is CNA specific. The name choice of "genomic data" does not imply it support other genomic data types - List result = studyViewColumnarService.getCNACountsByGeneSpecific(studyViewFilter, genomicDataFilters); - - return new ResponseEntity<>(result, HttpStatus.OK); - } - - @Hidden // should unhide when we remove legacy controller - @PreAuthorize("hasPermission(#involvedCancerStudies, 'Collection', T(org.cbioportal.utils.security.AccessLevel).READ)") - @RequestMapping(value = "/column-store/generic-assay-data-counts/fetch", - method = RequestMethod.POST, - consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "Fetch generic assay data counts by study view filter") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(array = @ArraySchema(schema = @Schema(implementation = GenericAssayDataCountItem.class)))) - public ResponseEntity> fetchGenericAssayDataCounts( - @Parameter(required = true, description = "Generic assay data count filter") @Valid @RequestBody(required = false) GenericAssayDataCountFilter genericAssayDataCountFilter, - @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface - @RequestAttribute(required = false, value = "involvedCancerStudies") Collection involvedCancerStudies, - @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface. this - // attribute is needed for the @PreAuthorize tag above. - @Valid @RequestAttribute(required = false, value = "interceptedGenericAssayDataCountFilter") GenericAssayDataCountFilter interceptedGenericAssayDataCountFilter) { - - List gaFilters = interceptedGenericAssayDataCountFilter.getGenericAssayDataFilters(); - StudyViewFilter studyViewFilter = interceptedGenericAssayDataCountFilter.getStudyViewFilter(); - // when there is only one filter, it means study view is doing a single chart filter operation - // remove filter from studyViewFilter to return all data counts - // the reason we do this is to make sure after chart get filtered, user can still see unselected portion of the chart - - if (gaFilters.size() == 1) { - studyViewFilterUtil.removeSelfFromGenericAssayFilter(gaFilters.getFirst().getStableId(), studyViewFilter); - } - - return new ResponseEntity<>(studyViewColumnarService.getGenericAssayDataCounts(studyViewFilter, gaFilters), HttpStatus.OK); - } - - @Hidden // should unhide when we remove legacy controller - @PreAuthorize("hasPermission(#involvedCancerStudies, 'Collection', T(org.cbioportal.utils.security.AccessLevel).READ)") - @RequestMapping(value = "/column-store/mutation-data-counts/fetch", - method = RequestMethod.POST, - consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "Fetch mutation data counts by GenomicDataCountFilter") - public ResponseEntity> fetchMutationDataCounts( - @Parameter(description = "Level of detail of the response") - @RequestParam(defaultValue = "SUMMARY") Projection projection, - @Parameter(required = true, description = "Genomic data count filter") - @Valid @RequestBody(required = false) GenomicDataCountFilter genomicDataCountFilter, - @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface - @RequestAttribute(required = false, value = "involvedCancerStudies") Collection involvedCancerStudies, - @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface - @Valid @RequestAttribute(required = false, value = "interceptedGenomicDataCountFilter") GenomicDataCountFilter interceptedGenomicDataCountFilter - ) { - List genomicDataFilters = interceptedGenomicDataCountFilter.getGenomicDataFilters(); - StudyViewFilter studyViewFilter = interceptedGenomicDataCountFilter.getStudyViewFilter(); - // when there is only one filter, it means study view is doing a single chart filter operation - // remove filter from studyViewFilter to return all data counts - // the reason we do this is to make sure after chart get filtered, user can still see unselected portion of the chart - if (genomicDataFilters.size() == 1 && projection == Projection.SUMMARY) { - studyViewFilterUtil.removeSelfFromMutationDataFilter( - genomicDataFilters.get(0).getHugoGeneSymbol(), - genomicDataFilters.get(0).getProfileType(), - MutationOption.MUTATED, - studyViewFilter); - } - - List result = projection == Projection.SUMMARY ? - studyViewColumnarService.getMutationCountsByGeneSpecific(studyViewFilter, genomicDataFilters) : - studyViewColumnarService.getMutationTypeCountsByGeneSpecific(studyViewFilter, genomicDataFilters); - - return new ResponseEntity<>(result, HttpStatus.OK); - } - - @Hidden // should unhide when we remove legacy controller - @PreAuthorize("hasPermission(#involvedCancerStudies, 'Collection', T(org.cbioportal.utils.security.AccessLevel).READ)") - @RequestMapping(value = "/column-store/clinical-event-type-counts/fetch", - method = RequestMethod.POST, - consumes = MediaType.APPLICATION_JSON_VALUE, - produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "Get Counts of Clinical Event Types by Study View Filter") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(array = @ArraySchema(schema = @Schema(implementation = ClinicalEventTypeCount.class)))) - public ResponseEntity> getClinicalEventTypeCounts( - @Parameter(required = true, description = "Study view filter") - @Valid - @RequestBody(required = false) - StudyViewFilter studyViewFilter, - - @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface - @RequestAttribute(required = false, value = "involvedCancerStudies") - Collection involvedCancerStudies, - - @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface. this attribute is needed for the @PreAuthorize tag above. - @Valid - @RequestAttribute(required = false, value = "interceptedStudyViewFilter") - StudyViewFilter interceptedStudyViewFilter - ) { - return new ResponseEntity<>(studyViewColumnarService.getClinicalEventTypeCounts(interceptedStudyViewFilter), HttpStatus.OK); - } - - @PreAuthorize("hasPermission(#involvedCancerStudies, 'Collection', T(org.cbioportal.utils.security.AccessLevel).READ)") - @RequestMapping(value = "/column-store/treatments/patient-counts/fetch", - method = RequestMethod.POST, - produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "Get all patient level treatments") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(schema = @Schema(implementation = PatientTreatmentReport.class))) - public ResponseEntity fetchPatientTreatmentCounts( - @Parameter(required = false ) - @RequestParam(name = "tier", required = false, defaultValue = "Agent") - ClinicalEventKeyCode tier, - - @Parameter(required = true, description = "Study view filter") - @Valid - @RequestBody(required = false) - StudyViewFilter studyViewFilter, - - @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface - @RequestAttribute(required = false, value = "involvedCancerStudies") - Collection involvedCancerStudies, - - @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface. this attribute is needed for the @PreAuthorize tag above. - @Valid - @RequestAttribute(required = false, value = "interceptedStudyViewFilter") - StudyViewFilter interceptedStudyViewFilter - ) { - return new ResponseEntity<>(studyViewColumnarService.getPatientTreatmentReport(interceptedStudyViewFilter), - HttpStatus.OK); - } - - @PreAuthorize("hasPermission(#involvedCancerStudies, 'Collection', T(org.cbioportal.utils.security.AccessLevel).READ)") - @RequestMapping(value = "/column-store/treatments/sample-counts/fetch", - method = RequestMethod.POST, - produces = MediaType.APPLICATION_JSON_VALUE) - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(schema = @Schema(implementation = SampleTreatmentReport.class))) - public ResponseEntity fetchSampleTreatmentCounts( - @Parameter(required = false ) - @RequestParam(name = "tier", required = false, defaultValue = "Agent") - ClinicalEventKeyCode tier, - - @Parameter(required = true, description = "Study view filter") - @Valid - @RequestBody(required = false) - StudyViewFilter studyViewFilter, - - @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface - @RequestAttribute(required = false, value = "involvedCancerStudies") - Collection involvedCancerStudies, - - @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface. this attribute is needed for the @PreAuthorize tag above. - @Valid - @RequestAttribute(required = false, value = "interceptedStudyViewFilter") - StudyViewFilter interceptedStudyViewFilter - ) { - return new ResponseEntity<>(studyViewColumnarService.getSampleTreatmentReport(interceptedStudyViewFilter), - HttpStatus.OK); - } - - @Hidden // should unhide when we remove legacy controller - @PreAuthorize("hasPermission(#involvedCancerStudies, 'Collection', T(org.cbioportal.utils.security.AccessLevel).READ)") - @RequestMapping(value = "/column-store/custom-data-counts/fetch", - method=RequestMethod.POST, - consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "Fetch custom data counts by study view filter") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(array = @ArraySchema(schema = @Schema(implementation = ClinicalDataCountItem.class)))) - public ResponseEntity> fetchCustomDataCounts( - @Parameter(required = true, description = "Custom data count filter") @Valid @RequestBody(required = false) ClinicalDataCountFilter clinicalDataCountFilter, - @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui - // interface - @RequestAttribute(required = false, value = "involvedCancerStudies") Collection involvedCancerStudies, - @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui - // interface. this attribute is needed for the - // @PreAuthorize tag above. - @Valid @RequestAttribute(required = false, value = "interceptedClinicalDataCountFilter") ClinicalDataCountFilter interceptedClinicalDataCountFilter) { - - List attributes = interceptedClinicalDataCountFilter.getAttributes(); - StudyViewFilter studyViewFilter = interceptedClinicalDataCountFilter.getStudyViewFilter(); - if (attributes.size() == 1) { - NewStudyViewFilterUtil.removeClinicalDataFilter(attributes.getFirst().getAttributeId(), studyViewFilter.getCustomDataFilters()); - } - - List filteredSampleIdentifiers = studyViewColumnarService.getFilteredSamples(studyViewFilter).stream().map(sample -> studyViewFilterUtil.buildSampleIdentifier(sample.getCancerStudyIdentifier(), sample.getStableId())).toList(); - - if (filteredSampleIdentifiers.isEmpty()) { - return new ResponseEntity<>(new ArrayList<>(), HttpStatus.OK); - } - - final List attributeIds = attributes.stream().map(ClinicalDataFilter::getAttributeId).toList(); - Map customDataSessionsMap = customDataService.getCustomDataSessions(attributeIds); - - List result = customDataFilterUtil.getCustomDataCounts(filteredSampleIdentifiers, customDataSessionsMap); - - return new ResponseEntity<>(result, HttpStatus.OK); - } - - @Hidden // should unhide when we remove legacy controller - @PreAuthorize("hasPermission(#involvedCancerStudies, 'Collection', T(org.cbioportal.utils.security.AccessLevel).READ)") - @RequestMapping(value = "/column-store/custom-data-bin-counts/fetch", - consumes = MediaType.APPLICATION_JSON_VALUE, method= RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "Fetch custom data bin counts by study view filter") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(array = @ArraySchema(schema = @Schema(implementation = ClinicalDataBin.class)))) - public ResponseEntity> fetchCustomDataBinCounts( - @Parameter(description = "Method for data binning") - @RequestParam(defaultValue = "DYNAMIC") DataBinMethod dataBinMethod, - @Parameter(required = true, description = "Clinical data bin count filter") - @Valid @RequestBody(required = false) ClinicalDataBinCountFilter clinicalDataBinCountFilter, - @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface - @RequestAttribute(required = false, value = "involvedCancerStudies") Collection involvedCancerStudies, - @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface. this attribute is needed for the @PreAuthorize tag above. - @Valid @RequestAttribute(required = false, value = "interceptedClinicalDataBinCountFilter") ClinicalDataBinCountFilter interceptedClinicalDataBinCountFilter - ) { - List customDataBins = basicDataBinner.getDataBins( - dataBinMethod, - interceptedClinicalDataBinCountFilter, - true - ); - - return new ResponseEntity<>(customDataBins, HttpStatus.OK); - } - - @Hidden // should unhide when we remove legacy controller - @PreAuthorize("hasPermission(#involvedCancerStudies, 'Collection', T(org.cbioportal.utils.security.AccessLevel).READ)") - @RequestMapping(value = "/column-store/genomic-data-bin-counts/fetch", - consumes = MediaType.APPLICATION_JSON_VALUE, method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE) - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(array = @ArraySchema(schema = @Schema(implementation = GenomicDataBin.class)))) - public ResponseEntity> fetchGenomicDataBinCounts( - @RequestParam(defaultValue = "DYNAMIC") DataBinMethod dataBinMethod, - @RequestBody(required = false) GenomicDataBinCountFilter genomicDataBinCountFilter, - @RequestAttribute(required = false, value = "involvedCancerStudies") Collection involvedCancerStudies, - @RequestAttribute(required = false, value = "interceptedGenomicDataBinCountFilter") GenomicDataBinCountFilter interceptedGenomicDataBinCountFilter - ) { - List genomicDataBins = basicDataBinner.getDataBins( - dataBinMethod, - interceptedGenomicDataBinCountFilter, - true - ); - return new ResponseEntity<>(genomicDataBins, HttpStatus.OK); - } - - @Hidden // should unhide when we remove legacy controller - @PreAuthorize("hasPermission(#involvedCancerStudies, 'Collection', T(org.cbioportal.utils.security.AccessLevel).READ)") - @RequestMapping(value = "/column-store/generic-assay-data-bin-counts/fetch", - consumes = MediaType.APPLICATION_JSON_VALUE, method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE) - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(array = @ArraySchema(schema = @Schema(implementation = GenericAssayDataBin.class)))) - public ResponseEntity> fetchGenericAssayDataBinCounts( - @RequestParam(defaultValue = "DYNAMIC") DataBinMethod dataBinMethod, - @RequestBody(required = false) GenericAssayDataBinCountFilter genericAssayDataBinCountFilter, - @RequestAttribute(required = false, value = "involvedCancerStudies") Collection involvedCancerStudies, - @RequestAttribute(required = false, value = "interceptedGenericAssayDataBinCountFilter") GenericAssayDataBinCountFilter interceptedGenericAssayDataBinCountFilter - ) { - List genericAssayDataBins = basicDataBinner.getDataBins( - dataBinMethod, - interceptedGenericAssayDataBinCountFilter, - true - ); - return new ResponseEntity<>(genericAssayDataBins, HttpStatus.OK); - } -} diff --git a/src/main/java/org/cbioportal/web/columnar/util/ClinicalDataXyPlotUtil.java b/src/main/java/org/cbioportal/web/columnar/util/ClinicalDataXyPlotUtil.java deleted file mode 100644 index 58b2d1e9c4e..00000000000 --- a/src/main/java/org/cbioportal/web/columnar/util/ClinicalDataXyPlotUtil.java +++ /dev/null @@ -1,84 +0,0 @@ -package org.cbioportal.web.columnar.util; - -import org.cbioportal.model.ClinicalData; -import org.cbioportal.model.Sample; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -public class ClinicalDataXyPlotUtil { - public static List combineClinicalDataForXyPlot( - List sampleClinicalDataList, - List patientClinicalDataList, - List samples, - boolean shouldFilterNonEmptyClinicalData - ) { - List combinedClinicalDataList; - - if (shouldFilterNonEmptyClinicalData) { - sampleClinicalDataList = filterNonEmptyClinicalData(sampleClinicalDataList); - patientClinicalDataList = filterNonEmptyClinicalData(patientClinicalDataList); - } - - if (patientClinicalDataList.isEmpty()) { - combinedClinicalDataList = sampleClinicalDataList; - } else { - combinedClinicalDataList = Stream.concat( - sampleClinicalDataList.stream(), - convertPatientClinicalDataToSampleClinicalData(patientClinicalDataList, samples).stream() - ).toList(); - } - - return combinedClinicalDataList; - } - - public static List filterNonEmptyClinicalData(List clinicalData) { - return clinicalData - .stream() - .filter(data -> !data.getAttrValue().isEmpty()) - .toList(); - } - - public static List convertPatientClinicalDataToSampleClinicalData( - List patientClinicalDataList, - List samplesWithoutNumericalFilter - ) { - List sampleClinicalDataList = new ArrayList<>(); - - Map>> patientToSamples = samplesWithoutNumericalFilter - .stream() - .collect(Collectors.groupingBy( - Sample::getPatientStableId, - Collectors.groupingBy(Sample::getCancerStudyIdentifier) - )); - - // put all clinical data into sample form - for (ClinicalData d: patientClinicalDataList) { - List samplesForPatient = patientToSamples.get(d.getPatientId()).get(d.getStudyId()); - if (samplesForPatient != null) { - for (Sample s: samplesForPatient) { - ClinicalData newData = new ClinicalData(); - - newData.setInternalId(s.getInternalId()); - newData.setAttrId(d.getAttrId()); - newData.setPatientId(d.getPatientId()); - newData.setStudyId(d.getStudyId()); - newData.setAttrValue(d.getAttrValue()); - newData.setSampleId(s.getStableId()); - - sampleClinicalDataList.add(newData); - } - } else { - // TODO ignoring for now rather than throwing an error - // patient has no samples - this shouldn't happen and could affect the integrity - // of the data analysis - // return new ResponseEntity<>(null, HttpStatus.INTERNAL_SERVER_ERROR); - } - } - - return sampleClinicalDataList; - } -} diff --git a/src/main/java/org/cbioportal/web/columnar/util/CustomDataFilterUtil.java b/src/main/java/org/cbioportal/web/columnar/util/CustomDataFilterUtil.java deleted file mode 100644 index 9987bf510c1..00000000000 --- a/src/main/java/org/cbioportal/web/columnar/util/CustomDataFilterUtil.java +++ /dev/null @@ -1,378 +0,0 @@ -package org.cbioportal.web.columnar.util; - -import com.google.common.collect.Range; -import org.apache.commons.collections4.CollectionUtils; -import org.apache.commons.collections4.map.MultiKeyMap; -import org.cbioportal.model.ClinicalDataCountItem; -import org.cbioportal.model.Patient; -import org.cbioportal.service.CustomDataService; -import org.cbioportal.service.PatientService; -import org.cbioportal.service.util.CustomDataSession; -import org.cbioportal.web.parameter.*; -import org.cbioportal.web.util.CustomDatatype; -import org.cbioportal.web.util.DataBinHelper; -import org.cbioportal.web.util.StudyViewFilterUtil; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -import java.math.BigDecimal; -import java.util.*; -import java.util.function.Function; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -@Component -public class CustomDataFilterUtil { - private final StudyViewFilterUtil studyViewFilterUtil; - private final CustomDataService customDataService; - private final PatientService patientService; - - @Autowired - public CustomDataFilterUtil(StudyViewFilterUtil studyViewFilterUtil, CustomDataService customDataService, PatientService patientService) { - this.studyViewFilterUtil = studyViewFilterUtil; - this.customDataService = customDataService; - this.patientService = patientService; - } - - public List extractInvolvedCancerStudies(final StudyViewFilter studyViewFilter) { - List involvedCancerStudies; - - if (studyViewFilter.getStudyIds() != null && !studyViewFilter.getStudyIds().isEmpty()) { - involvedCancerStudies = studyViewFilter.getStudyIds(); - } else if (studyViewFilter.getSampleIdentifiers() != null && !studyViewFilter.getSampleIdentifiers().isEmpty()) { - Set studyIdSet = new HashSet<>(); - for (SampleIdentifier sampleIdentifier : studyViewFilter.getSampleIdentifiers()) { - studyIdSet.add(sampleIdentifier.getStudyId()); - } - involvedCancerStudies = studyIdSet.stream().toList(); - } - else { - involvedCancerStudies = Collections.emptyList(); - } - - return involvedCancerStudies; - } - public List extractCustomDataSamples(final StudyViewFilter studyViewFilter) { - if (studyViewFilter == null) { - return null; - } - - if (CollectionUtils.isEmpty(studyViewFilter.getCustomDataFilters())) { - return null; - } - - final List customSamplesFromProperty = studyViewFilter.getCustomDataFilters().stream() - .flatMap(filter -> { - List samples = filter.getSamples(); - return (samples != null) ? samples.stream() : Stream.empty(); - }) - .toList(); - - if (!customSamplesFromProperty.isEmpty()) { - return extractCustomDataSamplesWithoutSession(studyViewFilter, customSamplesFromProperty); - } - else { - return extractCustomDataSamplesWithSession(studyViewFilter); - } - } - - private List extractCustomDataSamplesWithSession(final StudyViewFilter studyViewFilter) { - List customSampleIdentifiers = new ArrayList<>(); - - final List attributeIds = studyViewFilter.getCustomDataFilters().stream() - .map(ClinicalDataFilter::getAttributeId) - .collect(Collectors.toList()); - - final Map customDataSessions = customDataService.getCustomDataSessions(attributeIds); - - Map customDataSessionById = customDataSessions - .values() - .stream() - .collect(Collectors.toMap( - CustomDataSession::getId, - Function.identity() - )); - - MultiKeyMap customDataByStudySampleSession = new MultiKeyMap<>(); - - customDataSessionById.values().forEach(customDataSession -> customDataSession - .getData() - .getData() - .forEach(datum -> { - String value = datum.getValue().toUpperCase(); - if (value.equals("NAN") || value.equals("N/A")) { - value = "NA"; - } - CustomSampleIdentifier customSampleIdentifier = new CustomSampleIdentifier(); - customSampleIdentifier.setStudyId(datum.getStudyId()); - customSampleIdentifier.setSampleId(datum.getSampleId()); - customSampleIdentifiers.add(customSampleIdentifier); - customDataByStudySampleSession.put(datum.getStudyId(), datum.getSampleId(), customDataSession.getId(), value); - }) - ); - - List equalityFilters = new ArrayList<>(); - List intervalFilters = new ArrayList<>(); - - studyViewFilter.getCustomDataFilters().forEach(filter -> { - String attributeId = filter.getAttributeId(); - if (!customDataSessionById.containsKey(attributeId)) { - return; - } - if (customDataSessionById - .get(attributeId) - .getData() - .getDatatype() - .equals(CustomDatatype.STRING.name()) - ) { - equalityFilters.add(filter); - } else { - intervalFilters.add(filter); - } - }); - - List filtered = new ArrayList<>(); - customSampleIdentifiers.forEach(customSampleIdentifier -> { - int equalityFilterCount = studyViewFilterUtil.getFilteredCountByDataEquality(equalityFilters, customDataByStudySampleSession, - customSampleIdentifier.getSampleId(), customSampleIdentifier.getStudyId(), false); - int intervalFilterCount = getFilteredCountByDataInterval(intervalFilters, customDataByStudySampleSession, - customSampleIdentifier.getSampleId(), customSampleIdentifier.getStudyId()); - if (equalityFilterCount == equalityFilters.size() - && intervalFilterCount == intervalFilters.size() - ) { - filtered.add(customSampleIdentifier); - } - else { - customSampleIdentifier.setIsFilteredOut(true); - filtered.add(customSampleIdentifier); - } - }); - - return filtered; - } - - private List extractCustomDataSamplesWithoutSession(final StudyViewFilter studyViewFilter, List customSamplesFromProperty) { - List customSampleIdentifiers = new ArrayList<>(customSamplesFromProperty); - - List equalityFilters = new ArrayList<>(); - List intervalFilters = new ArrayList<>(); - - studyViewFilter.getCustomDataFilters().forEach(filter -> { - if (filter.getDatatype() - .equals(CustomDatatype.STRING.name()) - ) { - equalityFilters.add(filter); - } else { - intervalFilters.add(filter); - } - }); - - MultiKeyMap customDataByStudySampleName = new MultiKeyMap<>(); - - studyViewFilter.getCustomDataFilters().stream().forEach(filter -> - filter.getSamples().forEach(datum -> { - String value = datum.getValue().toUpperCase(); - if (value.equals("NAN") || value.equals("N/A")) { - value = "NA"; - } - customDataByStudySampleName.put(datum.getStudyId(), datum.getSampleId(), filter.getDisplayName(), value); - }) - ); - - List filtered = new ArrayList<>(); - customSampleIdentifiers.forEach(customSampleIdentifier -> { - int equalityFilterCount = getFilteredCountByDataEqualityWithStudySampleNameMap(equalityFilters, customDataByStudySampleName, - customSampleIdentifier.getSampleId(), customSampleIdentifier.getStudyId(), false); - int intervalFilterCount = getFilteredCountByDataIntervalWithStudySampleNameMap(intervalFilters, customDataByStudySampleName, - customSampleIdentifier.getSampleId(), customSampleIdentifier.getStudyId()); - if (equalityFilterCount == equalityFilters.size() - && intervalFilterCount == intervalFilters.size() - ) { - filtered.add(customSampleIdentifier); - } - else { - customSampleIdentifier.setIsFilteredOut(true); - filtered.add(customSampleIdentifier); - } - }); - return filtered; - } - - private Integer getFilteredCountByDataEqualityWithStudySampleNameMap(List attributes, MultiKeyMap clinicalDataMap, - String entityId, String studyId, boolean negateFilters) { - Integer count = 0; - for (ClinicalDataFilter s : attributes) { - List filteredValues = s.getValues() - .stream() - .map(DataFilterValue::getValue) - .collect(Collectors.toList()); - filteredValues.replaceAll(String::toUpperCase); - if (clinicalDataMap.containsKey(studyId, entityId, s.getDisplayName())) { - String value = clinicalDataMap.get(studyId, entityId, s.getDisplayName()); - if (negateFilters ^ filteredValues.contains(value)) { - count++; - } - } else if (negateFilters ^ filteredValues.contains("NA")) { - count++; - } - } - return count; - } - - private Integer getFilteredCountByDataInterval(List attributes, MultiKeyMap clinicalDataMap, - String entityId, String studyId) { - int count = 0; - - for (ClinicalDataFilter filter : attributes) { - if (clinicalDataMap.containsKey(studyId, entityId, filter.getAttributeId())) { - String attrValue = (String) clinicalDataMap.get(studyId, entityId, filter.getAttributeId()); - Range rangeValue = calculateRangeValueForAttr(attrValue); - - // find range filters - List> ranges = filter.getValues().stream() - .map(this::calculateRangeValueForFilter) - .filter(Objects::nonNull) - .collect(Collectors.toList()); - - // find special value filters - List specialValues = filter.getValues().stream() - .filter(f -> f.getValue() != null) - .map(f -> f.getValue().toUpperCase()) - .collect(Collectors.toList()); - - if (rangeValue != null) { - if (ranges.stream().anyMatch(r -> r.encloses(rangeValue))) { - count++; - } - } - else if (specialValues.contains(attrValue.toUpperCase())) { - count++; - } - } else if (containsNA(filter)) { - count++; - } - } - - return count; - } - - private Integer getFilteredCountByDataIntervalWithStudySampleNameMap(List attributes, MultiKeyMap clinicalDataMap, - String entityId, String studyId) { - int count = 0; - - for (ClinicalDataFilter filter : attributes) { - if (clinicalDataMap.containsKey(studyId, entityId, filter.getDisplayName())) { - String attrValue = clinicalDataMap.get(studyId, entityId, filter.getDisplayName()); - Range rangeValue = calculateRangeValueForAttr(attrValue); - - // find range filters - List> ranges = filter.getValues().stream() - .map(this::calculateRangeValueForFilter) - .filter(Objects::nonNull) - .toList(); - - // find special value filters - List specialValues = filter.getValues().stream() - .filter(f -> f.getValue() != null) - .map(f -> f.getValue().toUpperCase()) - .toList(); - - if ((rangeValue != null && ranges.stream().anyMatch(r -> r.encloses(rangeValue))) || - (rangeValue == null && specialValues.contains(attrValue.toUpperCase()))) { - count++; - } - } else if (Boolean.TRUE.equals(containsNA(filter))) { - count++; - } - } - - return count; - } - - private Range calculateRangeValueForAttr(String attrValue) { - if (attrValue == null) { - return null; - } - - BigDecimal min = null; - BigDecimal max = null; - - String value = attrValue.trim(); - - String lte = "<="; - String lt = "<"; - String gte = ">="; - String gt = ">"; - - boolean startInclusive = true; - boolean endInclusive = true; - - try { - if (value.startsWith(lte)) { - max = new BigDecimal(value.substring(lte.length())); - } - else if (value.startsWith(lt)) { - max = new BigDecimal(value.substring(lt.length())); - endInclusive = false; - } - else if (value.startsWith(gte)) { - min = new BigDecimal(value.substring(gte.length())); - } - else if (value.startsWith(gt)) { - min = new BigDecimal(value.substring(gt.length())); - startInclusive = false; - } - else { - min = max = new BigDecimal(attrValue); - } - } catch (Exception e) { - // invalid range -- TODO: also support ranges like 20-30? - return null; - } - - return DataBinHelper.calcRange(min, startInclusive, max, endInclusive); - } - - private Range calculateRangeValueForFilter(DataFilterValue filterValue) { - BigDecimal start = filterValue.getStart(); - BigDecimal end = filterValue.getEnd(); - - // default: (start, end] - boolean startInclusive = false; - boolean endInclusive = true; - - // special case: end == start (both inclusive) - if (end != null && end.equals(start)) { - startInclusive = true; - } - - return DataBinHelper.calcRange(start, startInclusive, end, endInclusive); - } - - private Boolean containsNA(ClinicalDataFilter filter) { - return filter.getValues().stream().anyMatch( - r -> r.getValue() != null && r.getValue().toUpperCase().equals("NA")); - } - - public List getCustomDataCounts(List filteredSampleIdentifiers, Map customDataSessions) { - Map customSamplesMap = filteredSampleIdentifiers.stream() - .collect(Collectors.toMap(sampleIdentifier -> studyViewFilterUtil.getCaseUniqueKey( - sampleIdentifier.getStudyId(), - sampleIdentifier.getSampleId() - ), Function.identity())); - - List studyIds = new ArrayList<>(); - List sampleIds = new ArrayList<>(); - studyViewFilterUtil.extractStudyAndSampleIds(filteredSampleIdentifiers, studyIds, sampleIds); - - long patientCustomDataSessionsCount = customDataSessions.values().stream() - .filter(customDataSession -> customDataSession.getData().getPatientAttribute()).count(); - List patients = new ArrayList<>(); - if (patientCustomDataSessionsCount > 0) { - patients.addAll(patientService.getPatientsOfSamples(studyIds, sampleIds)); - } - - return studyViewFilterUtil.getClinicalDataCountsFromCustomData(customDataSessions.values(), - customSamplesMap, patients); - } -} diff --git a/src/main/java/org/cbioportal/web/columnar/util/NewClinicalDataBinUtil.java b/src/main/java/org/cbioportal/web/columnar/util/NewClinicalDataBinUtil.java deleted file mode 100644 index df1b9524c6e..00000000000 --- a/src/main/java/org/cbioportal/web/columnar/util/NewClinicalDataBinUtil.java +++ /dev/null @@ -1,167 +0,0 @@ -package org.cbioportal.web.columnar.util; - -import org.cbioportal.model.Binnable; -import org.cbioportal.model.ClinicalData; -import org.cbioportal.model.ClinicalDataBin; -import org.cbioportal.model.ClinicalDataCount; -import org.cbioportal.model.DataBin; -import org.cbioportal.service.util.CustomDataSession; -import org.cbioportal.web.parameter.ClinicalDataBinCountFilter; -import org.cbioportal.web.parameter.ClinicalDataBinFilter; -import org.cbioportal.web.parameter.ClinicalDataType; -import org.cbioportal.web.parameter.StudyViewFilter; -import org.cbioportal.web.util.DataBinner; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import static java.util.Collections.emptyList; - -public class NewClinicalDataBinUtil { - public static StudyViewFilter removeSelfFromFilter(ClinicalDataBinCountFilter dataBinCountFilter) { - List attributes = dataBinCountFilter.getAttributes(); - StudyViewFilter studyViewFilter = dataBinCountFilter.getStudyViewFilter(); - - if (attributes.size() == 1) { - NewStudyViewFilterUtil.removeClinicalDataFilter(attributes.getFirst().getAttributeId(), studyViewFilter.getClinicalDataFilters()); - } - - return studyViewFilter; - } - - public static StudyViewFilter removeSelfCustomDataFromFilter(ClinicalDataBinCountFilter dataBinCountFilter) { - List attributes = dataBinCountFilter.getAttributes(); - StudyViewFilter studyViewFilter = dataBinCountFilter.getStudyViewFilter(); - - if (attributes.size() == 1) { - NewStudyViewFilterUtil.removeClinicalDataFilter(attributes.getFirst().getAttributeId(), studyViewFilter.getCustomDataFilters()); - } - - return studyViewFilter; - } - - public static ClinicalDataBin dataBinToClinicalDataBin(ClinicalDataBinFilter attribute, DataBin dataBin) { - ClinicalDataBin clinicalDataBin = new ClinicalDataBin(); - clinicalDataBin.setAttributeId(attribute.getAttributeId()); - clinicalDataBin.setCount(dataBin.getCount()); - if (dataBin.getEnd() != null) { - clinicalDataBin.setEnd(dataBin.getEnd()); - } - if (dataBin.getSpecialValue() != null) { - clinicalDataBin.setSpecialValue(dataBin.getSpecialValue()); - } - if (dataBin.getStart() != null) { - clinicalDataBin.setStart(dataBin.getStart()); - } - return clinicalDataBin; - } - - public static Map toAttributeDatatypeMap( - List sampleAttributeIds, - List patientAttributeIds, - List conflictingPatientAttributeIds - ) { - Map attributeDatatypeMap = new HashMap<>(); - - sampleAttributeIds.forEach(attribute -> { - attributeDatatypeMap.put(attribute, ClinicalDataType.SAMPLE); - }); - patientAttributeIds.forEach(attribute -> { - attributeDatatypeMap.put(attribute, ClinicalDataType.PATIENT); - }); - conflictingPatientAttributeIds.forEach(attribute -> { - attributeDatatypeMap.put(attribute, ClinicalDataType.SAMPLE); - }); - - return attributeDatatypeMap; - } - - public static List calculateStaticDataBins( - DataBinner dataBinner, - List attributes, - Map attributeDatatypeMap, - Map> unfilteredClinicalDataByAttributeId, - Map> filteredClinicalDataByAttributeId - ) { - List clinicalDataBins = new ArrayList<>(); - - for (ClinicalDataBinFilter attribute : attributes) { - if (attributeDatatypeMap.containsKey(attribute.getAttributeId())) { - List dataBins = dataBinner - .calculateClinicalDataBins( - attribute, - filteredClinicalDataByAttributeId.getOrDefault(attribute.getAttributeId(), emptyList()), - unfilteredClinicalDataByAttributeId.getOrDefault(attribute.getAttributeId(), emptyList()) - ) - .stream() - .map(dataBin -> dataBinToClinicalDataBin(attribute, dataBin)) - .toList(); - - clinicalDataBins.addAll(dataBins); - } - } - - return clinicalDataBins; - } - - public static List calculateDynamicDataBins( - DataBinner dataBinner, - List attributes, - Map attributeDatatypeMap, - Map> filteredClinicalDataByAttributeId - ) { - List clinicalDataBins = new ArrayList<>(); - - for (ClinicalDataBinFilter attribute : attributes) { - - // if there is clinical data for requested attribute - if (attributeDatatypeMap.containsKey(attribute.getAttributeId())) { - List dataBins = dataBinner - .calculateDataBins( - attribute, - filteredClinicalDataByAttributeId.getOrDefault(attribute.getAttributeId(), emptyList()) - ) - .stream() - .map(dataBin -> dataBinToClinicalDataBin(attribute, dataBin)) - .toList(); - clinicalDataBins.addAll(dataBins); - } - } - - return clinicalDataBins; - } - - /** - * Generate a list of ClinicalData from the given data count instance. - * Size of the generated list is equal to 'dataCount.count', - * and each ClinicalData in the list contains the same value 'dataCount.value' - * - * This method improves the performance of the data binning because it allows us to fetch only - * the clinical data counts data which is a lot more compact and faster to generated than the actual clinical data. - * We only need the attribute id and the value of the clinical data to generate data bins. - * Constructing the clinical data in memory by using clinical data counts significantly improves the performance, - * and it also allows us to use the exact same SQL used by the clinical data counts endpoint. - * - * @param dataCount ClinicalDataCount instance containing the count and the value - * @return a list of ClinicalData with size 'dataCount.count' and value 'dataCount.value' - */ - public static List generateClinicalDataFromClinicalDataCount(ClinicalDataCount dataCount) - { - List data = new ArrayList<>(dataCount.getCount()); - - for (int i=0; i < dataCount.getCount(); i++) { - ClinicalData d = new ClinicalData(); - d.setAttrId(dataCount.getAttributeId()); - d.setAttrValue(dataCount.getValue()); - data.add(d); - } - - return data; - } - - public static ClinicalDataType getDataType(Map.Entry entry) { - return Boolean.TRUE.equals(entry.getValue().getData().getPatientAttribute()) ? ClinicalDataType.PATIENT : ClinicalDataType.SAMPLE; - } -} diff --git a/src/main/java/org/cbioportal/web/columnar/util/NewStudyViewFilterUtil.java b/src/main/java/org/cbioportal/web/columnar/util/NewStudyViewFilterUtil.java deleted file mode 100644 index 5363802afe2..00000000000 --- a/src/main/java/org/cbioportal/web/columnar/util/NewStudyViewFilterUtil.java +++ /dev/null @@ -1,15 +0,0 @@ -package org.cbioportal.web.columnar.util; - - -import org.cbioportal.web.parameter.ClinicalDataFilter; - -import java.util.List; - -public class NewStudyViewFilterUtil { - - public static void removeClinicalDataFilter(String attributeId, List dataFilterList ) { - if (dataFilterList != null) { - dataFilterList.removeIf(f -> f.getAttributeId().equals(attributeId)); - } - } -} diff --git a/src/main/java/org/cbioportal/web/config/CustomObjectMapper.java b/src/main/java/org/cbioportal/web/config/CustomObjectMapper.java deleted file mode 100644 index d5853d58218..00000000000 --- a/src/main/java/org/cbioportal/web/config/CustomObjectMapper.java +++ /dev/null @@ -1,155 +0,0 @@ -/* - * Copyright (c) 2016 Memorial Sloan-Kettering Cancer Center. - * - * This library is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS - * FOR A PARTICULAR PURPOSE. The software and documentation provided hereunder - * is on an "as is" basis, and Memorial Sloan-Kettering Cancer Center has no - * obligations to provide maintenance, support, updates, enhancements or - * modifications. In no event shall Memorial Sloan-Kettering Cancer Center be - * liable to any party for direct, indirect, special, incidental or - * consequential damages, including lost profits, arising out of the use of this - * software and its documentation, even if Memorial Sloan-Kettering Cancer - * Center has been advised of the possibility of such damage. - */ - -/* - * This file is part of cBioPortal. - * - * cBioPortal is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . -*/ - -package org.cbioportal.web.config; - -import com.fasterxml.jackson.annotation.JsonInclude; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.SerializationFeature; -import org.cbioportal.model.CancerStudy; -import org.cbioportal.model.ClinicalAttribute; -import org.cbioportal.model.ClinicalAttributeCount; -import org.cbioportal.model.ClinicalData; -import org.cbioportal.model.ClinicalDataCount; -import org.cbioportal.model.ClinicalEvent; -import org.cbioportal.model.ClinicalEventData; -import org.cbioportal.model.CopyNumberSeg; -import org.cbioportal.model.DataAccessToken; -import org.cbioportal.model.DiscreteCopyNumberData; -import org.cbioportal.model.Gene; -import org.cbioportal.model.GenePanel; -import org.cbioportal.model.GenePanelToGene; -import org.cbioportal.model.Geneset; -import org.cbioportal.model.GenesetCorrelation; -import org.cbioportal.model.GenesetMolecularData; -import org.cbioportal.model.Gistic; -import org.cbioportal.model.GisticToGene; -import org.cbioportal.model.MolecularProfile; -import org.cbioportal.model.MutSig; -import org.cbioportal.model.Mutation; -import org.cbioportal.model.MutationSpectrum; -import org.cbioportal.model.Patient; -import org.cbioportal.model.ResourceDefinition; -import org.cbioportal.model.Sample; -import org.cbioportal.model.SampleList; -import org.cbioportal.model.StructuralVariant; -import org.cbioportal.model.TypeOfCancer; -import org.cbioportal.service.util.CustomAttributeWithData; -import org.cbioportal.service.util.CustomDataSession; -import org.cbioportal.utils.removeme.Session; -import org.cbioportal.web.mixin.CancerStudyMixin; -import org.cbioportal.web.mixin.ClinicalAttributeCountMixin; -import org.cbioportal.web.mixin.ClinicalAttributeMixin; -import org.cbioportal.web.mixin.ClinicalDataCountMixin; -import org.cbioportal.web.mixin.ClinicalDataMixin; -import org.cbioportal.web.mixin.ClinicalEventDataMixin; -import org.cbioportal.web.mixin.ClinicalEventMixin; -import org.cbioportal.web.mixin.CopyNumberSegMixin; -import org.cbioportal.web.mixin.DataAccessTokenMixin; -import org.cbioportal.web.mixin.DiscreteCopyNumberDataMixin; -import org.cbioportal.web.mixin.GeneMixin; -import org.cbioportal.web.mixin.GenePanelMixin; -import org.cbioportal.web.mixin.GenePanelToGeneMixin; -import org.cbioportal.web.mixin.GenesetCorrelationMixin; -import org.cbioportal.web.mixin.GenesetMixin; -import org.cbioportal.web.mixin.GenesetMolecularDataMixin; -import org.cbioportal.web.mixin.GisticMixin; -import org.cbioportal.web.mixin.GisticToGeneMixin; -import org.cbioportal.web.mixin.MolecularProfileMixin; -import org.cbioportal.web.mixin.MutSigMixin; -import org.cbioportal.web.mixin.MutationMixin; -import org.cbioportal.web.mixin.MutationSpectrumMixin; -import org.cbioportal.web.mixin.PatientMixin; -import org.cbioportal.web.mixin.ResourceDefinitionMixin; -import org.cbioportal.web.mixin.SampleListMixin; -import org.cbioportal.web.mixin.SampleMixin; -import org.cbioportal.web.mixin.SessionDataMixin; -import org.cbioportal.web.mixin.SessionMixin; -import org.cbioportal.web.mixin.StructuralVariantMixin; -import org.cbioportal.web.mixin.TypeOfCancerMixin; -import org.cbioportal.web.parameter.PageSettings; -import org.cbioportal.web.parameter.PageSettingsData; -import org.cbioportal.web.parameter.StudyPageSettings; -import org.cbioportal.web.parameter.VirtualStudy; -import org.cbioportal.web.parameter.VirtualStudyData; - -import java.util.HashMap; -import java.util.Map; - -// This bean automatically registers with MappingJackson2HttpMessageConverter -// By marking it @Primary it will displace the default ObjectMapper -// See: https://www.baeldung.com/spring-boot-customize-jackson-objectmapper#1-objectmapper -public class CustomObjectMapper extends ObjectMapper { - - public CustomObjectMapper() { - super.setSerializationInclusion(JsonInclude.Include.NON_NULL); - super.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING); - Map, Class> mixinMap = new HashMap<>(); - mixinMap.put(CancerStudy.class, CancerStudyMixin.class); - mixinMap.put(ClinicalAttribute.class, ClinicalAttributeMixin.class); - mixinMap.put(ClinicalAttributeCount.class, ClinicalAttributeCountMixin.class); - mixinMap.put(ClinicalData.class, ClinicalDataMixin.class); - mixinMap.put(ClinicalDataCount.class, ClinicalDataCountMixin.class); - mixinMap.put(ClinicalEvent.class, ClinicalEventMixin.class); - mixinMap.put(ClinicalEventData.class, ClinicalEventDataMixin.class); - mixinMap.put(CopyNumberSeg.class, CopyNumberSegMixin.class); - mixinMap.put(DataAccessToken.class, DataAccessTokenMixin.class); - mixinMap.put(DiscreteCopyNumberData.class, DiscreteCopyNumberDataMixin.class); - mixinMap.put(StructuralVariant.class, StructuralVariantMixin.class); - mixinMap.put(Gene.class, GeneMixin.class); - mixinMap.put(GenePanel.class, GenePanelMixin.class); - mixinMap.put(GenePanelToGene.class, GenePanelToGeneMixin.class); - mixinMap.put(Geneset.class, GenesetMixin.class); - mixinMap.put(GenesetMolecularData.class, GenesetMolecularDataMixin.class); - mixinMap.put(GenesetCorrelation.class, GenesetCorrelationMixin.class); - mixinMap.put(MolecularProfile.class, MolecularProfileMixin.class); - mixinMap.put(Gistic.class, GisticMixin.class); - mixinMap.put(GisticToGene.class, GisticToGeneMixin.class); - mixinMap.put(Mutation.class, MutationMixin.class); - mixinMap.put(MutationSpectrum.class, MutationSpectrumMixin.class); - mixinMap.put(MutSig.class, MutSigMixin.class); - mixinMap.put(PageSettings.class, SessionMixin.class); - mixinMap.put(PageSettingsData.class, SessionDataMixin.class); - mixinMap.put(Patient.class, PatientMixin.class); - mixinMap.put(Sample.class, SampleMixin.class); - mixinMap.put(SampleList.class, SampleListMixin.class); - mixinMap.put(Session.class, SessionMixin.class); - mixinMap.put(StudyPageSettings.class, SessionDataMixin.class); - mixinMap.put(TypeOfCancer.class, TypeOfCancerMixin.class); - mixinMap.put(ResourceDefinition.class, ResourceDefinitionMixin.class); - mixinMap.put(VirtualStudy.class, SessionMixin.class); - mixinMap.put(VirtualStudyData.class, SessionDataMixin.class); - mixinMap.put(CustomAttributeWithData.class, SessionDataMixin.class); - mixinMap.put(CustomDataSession.class, SessionMixin.class); - super.setMixIns(mixinMap); - } -} diff --git a/src/main/java/org/cbioportal/web/config/InternalApiTags.java b/src/main/java/org/cbioportal/web/config/InternalApiTags.java deleted file mode 100644 index 810cbb21939..00000000000 --- a/src/main/java/org/cbioportal/web/config/InternalApiTags.java +++ /dev/null @@ -1,12 +0,0 @@ -package org.cbioportal.web.config; - -public class InternalApiTags { - public static final String CLINICAL_EVENTS = "Clinical Events"; - public static final String CLINICAL_ATTRIBUTES_COUNT = "Clinical Attributes Count"; - public static final String DISCRETE_COPY_NUMBER_ALTERATION_COUNTS = "Discrete Copy Number Alteration Counts"; - public static final String MUTATIONS_COUNT = "Mutations Count"; - public static final String REFERENCE_GENOME_GENES = "Reference Genome Genes"; - public static final String RESOURCE_DEFINITIONS = "Resource Definitions"; - public static final String RESOURCE_DATA = "Resource Data"; - public static final String STRUCTURAL_VARIANTS = "Structural Variants"; -} diff --git a/src/main/java/org/cbioportal/web/config/JacksonConfig.java b/src/main/java/org/cbioportal/web/config/JacksonConfig.java deleted file mode 100644 index 6e0c7a00247..00000000000 --- a/src/main/java/org/cbioportal/web/config/JacksonConfig.java +++ /dev/null @@ -1,15 +0,0 @@ -package org.cbioportal.web.config; - -import com.fasterxml.jackson.databind.ObjectMapper; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Primary; - -@Configuration -public class JacksonConfig { - @Bean - @Primary - public ObjectMapper objectMapper() { - return new CustomObjectMapper(); - } -} diff --git a/src/main/java/org/cbioportal/web/config/MethodValidationConfig.java b/src/main/java/org/cbioportal/web/config/MethodValidationConfig.java deleted file mode 100644 index 52ec3c80cfb..00000000000 --- a/src/main/java/org/cbioportal/web/config/MethodValidationConfig.java +++ /dev/null @@ -1,23 +0,0 @@ -package org.cbioportal.web.config; - -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean; -import org.springframework.validation.beanvalidation.MethodValidationPostProcessor; - -@Configuration -public class MethodValidationConfig { - - @Bean - public MethodValidationPostProcessor methodValidationPostProcessor() { - MethodValidationPostProcessor processor = new MethodValidationPostProcessor(); - processor.setValidator(validatorFactoryBean()); - return processor; - } - - @Bean - public LocalValidatorFactoryBean validatorFactoryBean() { - return new LocalValidatorFactoryBean(); - } - -} diff --git a/src/main/java/org/cbioportal/web/config/PublicApiTags.java b/src/main/java/org/cbioportal/web/config/PublicApiTags.java deleted file mode 100644 index 55952192cfa..00000000000 --- a/src/main/java/org/cbioportal/web/config/PublicApiTags.java +++ /dev/null @@ -1,22 +0,0 @@ -package org.cbioportal.web.config; - -public class PublicApiTags { - public static final String CANCER_TYPES = "Cancer Types"; - public static final String STUDIES = "Studies"; - public static final String PATIENTS = "Patients"; - public static final String SAMPLES = "Samples"; - public static final String SAMPLE_LISTS = "Sample Lists"; - public static final String CLINICAL_ATTRIBUTES = "Clinical Attributes"; - public static final String CLINICAL_DATA = "Clinical Data"; - public static final String MOLECULAR_DATA = "Molecular Data"; - public static final String MOLECULAR_PROFILES = "Molecular Profiles"; - public static final String MUTATIONS = "Mutations"; - public static final String DISCRETE_COPY_NUMBER_ALTERATIONS = "Discrete Copy Number Alterations"; - public static final String COPY_NUMBER_SEGMENTS = "Copy Number Segments"; - public static final String GENES = "Genes"; - public static final String GENE_PANELS = "Gene Panels"; - public static final String GENE_PANEL_DATA = "Gene Panel Data"; - public static final String GENERIC_ASSAYS = "Generic Assays"; - public static final String GENERIC_ASSAY_DATA = "Generic Assay Data"; - public static final String INFO = "Info"; -} \ No newline at end of file diff --git a/src/main/java/org/cbioportal/web/config/SwaggerConfig.java b/src/main/java/org/cbioportal/web/config/SwaggerConfig.java deleted file mode 100644 index 1c3b485865a..00000000000 --- a/src/main/java/org/cbioportal/web/config/SwaggerConfig.java +++ /dev/null @@ -1,86 +0,0 @@ -package org.cbioportal.web.config; - -import com.fasterxml.jackson.databind.ObjectMapper; -import io.swagger.v3.core.converter.ModelConverters; -import io.swagger.v3.core.jackson.ModelResolver; -import io.swagger.v3.oas.models.ExternalDocumentation; -import io.swagger.v3.oas.models.OpenAPI; -import io.swagger.v3.oas.models.info.Contact; -import io.swagger.v3.oas.models.info.Info; -import io.swagger.v3.oas.models.info.License; -import org.cbioportal.web.config.annotation.InternalApi; -import org.cbioportal.web.config.annotation.PublicApi; -import org.springdoc.core.customizers.OperationCustomizer; -import org.springdoc.core.models.GroupedOpenApi; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestMethod; -import org.springframework.web.method.HandlerMethod; - -import java.lang.annotation.Annotation; -import java.util.stream.Stream; - - -@Configuration -public class SwaggerConfig { - - @Bean - public GroupedOpenApi publicApi() { - return GroupedOpenApi.builder() - .group("public") - .addOpenApiMethodFilter(method -> method.getDeclaringClass().isAnnotationPresent(PublicApi.class)) - .addOperationCustomizer(customizeOperation()) - .pathsToMatch("/api/**") - .build(); - } - - @Bean - public GroupedOpenApi internalApi() { - return GroupedOpenApi.builder() - .group("internal") - .addOpenApiMethodFilter(method -> method.getDeclaringClass().isAnnotationPresent(InternalApi.class)) - .addOperationCustomizer(customizeOperation()) - .pathsToMatch("/api/**") - .build(); - } - - @Bean - public OpenAPI springShopOpenAPI(ObjectMapper customObjectMapper) { - ModelConverters.getInstance().addConverter(new ModelResolver(customObjectMapper)); - return new OpenAPI() - .info(new Info().title("cBioPortal web Public API [Alpha]") - .description("A web service for supplying JSON formatted data to cBioPortal clients. " + - "Please note that this API is currently in beta and subject to change.") - .version("1.0 (beta). Backwards compatibility will be maintained (after 1.0 release)") - .license(new License().name("License").url("https://github.com/cBioPortal/cbioportal/blob/master/LICENSE")) - .contact(new Contact().name("cbioportal").url("https://www.cbioportal.org").email("cbioportal@googlegroups.com"))) - .externalDocs(new ExternalDocumentation() - .description("SpringShop Wiki Documentation") - .url("https://springshop.wiki.github.org/docs")); - } - - @Bean - public OperationCustomizer customizeOperation() { - return (operation, handlerMethod) -> { - // TODO: Add HTTP Action to EndPoint should remove eventually - String httpMethod = extractHttpMethod(handlerMethod); - String originalOperationId = operation.getOperationId(); - String newOperationId = originalOperationId + "Using" + httpMethod; - - operation.setOperationId(newOperationId); - return operation; - }; - } - - private String extractHttpMethod(HandlerMethod handlerMethod) { - Annotation[] declaredAnnotations = handlerMethod.getMethod().getDeclaredAnnotations(); - for (var annotation : declaredAnnotations) { - if (annotation instanceof RequestMapping requestMapping) { - return Stream.of(requestMapping.method()).findFirst().map(RequestMethod::toString).orElse(""); - } - } - return ""; - } - -} diff --git a/src/main/java/org/cbioportal/web/config/WebServletContextListener.java b/src/main/java/org/cbioportal/web/config/WebServletContextListener.java deleted file mode 100644 index 8311df288df..00000000000 --- a/src/main/java/org/cbioportal/web/config/WebServletContextListener.java +++ /dev/null @@ -1,100 +0,0 @@ -package org.cbioportal.web.config; - -import jakarta.servlet.ServletContextEvent; -import jakarta.servlet.ServletContextListener; -import org.springframework.beans.factory.InitializingBean; - -import java.io.*; -import java.util.Properties; -import org.springframework.util.ObjectUtils; - -/** - * Created by Hongxin Zhang on 11/15/19. - */ -public class WebServletContextListener implements ServletContextListener, InitializingBean { - private Boolean showOncokb; - - private String oncokbToken; - - private String oncokbURL; - - private Properties properties; - - private static final String DEFAULT_ONCOKB_URL = "https://public.api.oncokb.org/api/v1"; - - @Override - public void contextDestroyed(ServletContextEvent arg0) { - System.out.println("ServletContextListener destroyed"); - } - - //Run this before web application is started - @Override - public void contextInitialized(ServletContextEvent arg0) { - this.properties = loadProperties(getResourceStream("application.properties")); - - this.showOncokb = Boolean.parseBoolean(getProperty("show.oncokb", "true")); - this.oncokbToken = getProperty("oncokb.token", ""); - this.oncokbURL = getProperty("oncokb.public_api.url", ""); - - if (this.showOncokb) { - checkOncokbInfo(); - } - } - - @Override - public void afterPropertiesSet() throws Exception { - } - - private void checkOncokbInfo() { - if(ObjectUtils.isEmpty(this.oncokbToken) && (ObjectUtils.isEmpty(this.oncokbURL) || this.oncokbURL.equalsIgnoreCase(DEFAULT_ONCOKB_URL))) { - System.out.println("----------------------------------------------------------------------------------------------------------------"); - // oncokb.org is deprecated, www.oncokb.org should be used - System.out.println("-- You are connecting to the OncoKB public instance which does not include any therapeutic information."); - System.out.println("-- Please consider obtaining a license to support future OncoKB development by following https://docs.cbioportal.org/2.4-integration-with-other-webservices/oncokb-data-access."); - System.out.println("-- Thank you."); - System.out.println("----------------------------------------------------------------------------------------------------------------"); - } - } - - private String getProperty(String key, String defaultValue) { - String propertyValue = this.properties.getProperty(key, defaultValue); - return System.getProperty(key, propertyValue); - } - - private InputStream getResourceStream(String propertiesFileName) - { - String resourceFilename = null; - InputStream resourceFIS = null; - - try { - String home = System.getenv("PORTAL_HOME"); - if (home != null) { - resourceFilename = - home + File.separator + propertiesFileName; - resourceFIS = new FileInputStream(resourceFilename); - } - } catch (FileNotFoundException e) { - } - - if (resourceFIS == null) { - resourceFIS = this.getClass().getClassLoader(). - getResourceAsStream(propertiesFileName); - } - - return resourceFIS; - } - private Properties loadProperties(InputStream resourceInputStream) - { - Properties properties = new Properties(); - - try { - properties.load(resourceInputStream); - resourceInputStream.close(); - } - catch (IOException e) { - System.out.println("Error loading properties file: " + e.getMessage()); - } - - return properties; - } -} diff --git a/src/main/java/org/cbioportal/web/config/annotation/InternalApi.java b/src/main/java/org/cbioportal/web/config/annotation/InternalApi.java deleted file mode 100644 index f9717fb0610..00000000000 --- a/src/main/java/org/cbioportal/web/config/annotation/InternalApi.java +++ /dev/null @@ -1,8 +0,0 @@ -package org.cbioportal.web.config.annotation; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; - -@Retention(RetentionPolicy.RUNTIME) -public @interface InternalApi { -} diff --git a/src/main/java/org/cbioportal/web/config/annotation/PublicApi.java b/src/main/java/org/cbioportal/web/config/annotation/PublicApi.java deleted file mode 100644 index 76dc021ee72..00000000000 --- a/src/main/java/org/cbioportal/web/config/annotation/PublicApi.java +++ /dev/null @@ -1,8 +0,0 @@ -package org.cbioportal.web.config.annotation; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; - -@Retention(RetentionPolicy.RUNTIME) -public @interface PublicApi { -} diff --git a/src/main/java/org/cbioportal/web/error/ErrorResponse.java b/src/main/java/org/cbioportal/web/error/ErrorResponse.java deleted file mode 100644 index cf37cafb850..00000000000 --- a/src/main/java/org/cbioportal/web/error/ErrorResponse.java +++ /dev/null @@ -1,18 +0,0 @@ -package org.cbioportal.web.error; - -public class ErrorResponse { - - private String message; - - public ErrorResponse(String message) { - this.message = message; - } - - public String getMessage() { - return message; - } - - public void setMessage(String message) { - this.message = message; - } -} diff --git a/src/main/java/org/cbioportal/web/error/GlobalExceptionHandler.java b/src/main/java/org/cbioportal/web/error/GlobalExceptionHandler.java deleted file mode 100644 index 1c24d60c431..00000000000 --- a/src/main/java/org/cbioportal/web/error/GlobalExceptionHandler.java +++ /dev/null @@ -1,216 +0,0 @@ -package org.cbioportal.web.error; - -import jakarta.validation.ConstraintViolation; -import jakarta.validation.ConstraintViolationException; -import jakarta.validation.ElementKind; -import jakarta.validation.Path; -import org.cbioportal.service.exception.*; -import org.springframework.beans.TypeMismatchException; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.http.converter.HttpMessageNotReadableException; -import org.springframework.jdbc.BadSqlGrammarException; -import org.springframework.security.access.AccessDeniedException; -import org.springframework.validation.FieldError; -import org.springframework.web.bind.MethodArgumentNotValidException; -import org.springframework.web.bind.MissingServletRequestParameterException; -import org.springframework.web.bind.annotation.ControllerAdvice; -import org.springframework.web.bind.annotation.ExceptionHandler; - -import java.util.Iterator; -import java.util.NoSuchElementException; - - -// TODO -// - consider extending extends ResponseEntityExceptionHandler -// - check controllers for not catching exceptions themselves -@ControllerAdvice("org.cbioportal.web") -public class GlobalExceptionHandler { - - @ExceptionHandler(UnsupportedOperationException.class) - public ResponseEntity handleUnsupportedOperation() { - return new ResponseEntity<>(new ErrorResponse("Requested API is not implemented yet"), - HttpStatus.NOT_IMPLEMENTED); - } - - @ExceptionHandler(StudyNotFoundException.class) - public ResponseEntity handleStudyNotFound(StudyNotFoundException ex) { - return new ResponseEntity<>(new ErrorResponse("Study not found: " + ex.getStudyId()), - HttpStatus.NOT_FOUND); - } - - @ExceptionHandler(PatientNotFoundException.class) - public ResponseEntity handlePatientNotFound(PatientNotFoundException ex) { - return new ResponseEntity<>(new ErrorResponse("Patient not found in study " + ex.getStudyId() + ": " + - ex.getPatientId()), HttpStatus.NOT_FOUND); - } - - @ExceptionHandler(CancerTypeNotFoundException.class) - public ResponseEntity handleCancerTypeNotFound(CancerTypeNotFoundException ex) { - return new ResponseEntity<>(new ErrorResponse("Cancer type not found: " + ex.getCancerTypeId()), - HttpStatus.NOT_FOUND); - } - - @ExceptionHandler(MolecularProfileNotFoundException.class) - public ResponseEntity handleMolecularProfileNotFound(MolecularProfileNotFoundException ex) { - return new ResponseEntity<>(new ErrorResponse("Molecular profile not found: " + ex.getMolecularProfileId()), - HttpStatus.NOT_FOUND); - } - - @ExceptionHandler(SampleNotFoundException.class) - public ResponseEntity handleSampleNotFound(SampleNotFoundException ex) { - return new ResponseEntity<>(new ErrorResponse("Sample not found in study " + ex.getStudyId() + ": " + - ex.getSampleId()), HttpStatus.NOT_FOUND); - } - - @ExceptionHandler(GeneNotFoundException.class) - public ResponseEntity handleGeneNotFound(GeneNotFoundException ex) { - return new ResponseEntity<>(new ErrorResponse("Gene not found: " + ex.getGeneId()), - HttpStatus.NOT_FOUND); - } - - @ExceptionHandler(GeneWithMultipleEntrezIdsException.class) - public ResponseEntity handleGeneWithMultipleEntrezIdsException( - GeneWithMultipleEntrezIdsException ex) { - return new ResponseEntity<>( - new ErrorResponse("Gene data error: multiple Entrez gene IDs for " + ex.getGeneId()), - HttpStatus.INTERNAL_SERVER_ERROR); - } - - @ExceptionHandler(GenesetNotFoundException.class) - public ResponseEntity handleGenesetNotFound(GenesetNotFoundException ex) { - return new ResponseEntity<>(new ErrorResponse("Gene set not found: " + ex.getGenesetId()), - HttpStatus.NOT_FOUND); - } - - @ExceptionHandler(SampleListNotFoundException.class) - public ResponseEntity handleSampleListNotFound(SampleListNotFoundException ex) { - return new ResponseEntity<>(new ErrorResponse("Sample list not found: " + ex.getSampleListId()), - HttpStatus.NOT_FOUND); - } - - @ExceptionHandler(ClinicalAttributeNotFoundException.class) - public ResponseEntity handleClinicalAttributeNotFound(ClinicalAttributeNotFoundException ex) { - return new ResponseEntity<>(new ErrorResponse("Clinical attribute not found in study " + ex.getStudyId() + - ": " + ex.getClinicalAttributeId()), HttpStatus.NOT_FOUND); - } - - @ExceptionHandler(GenePanelNotFoundException.class) - public ResponseEntity handleGenePanelNotFound(GenePanelNotFoundException ex) { - return new ResponseEntity<>(new ErrorResponse("Gene panel not found: " + ex.getGenePanelId()), - HttpStatus.NOT_FOUND); - } - - @ExceptionHandler(MissingServletRequestParameterException.class) - public ResponseEntity handleMissingServletRequestParameter( - MissingServletRequestParameterException ex) { - return new ResponseEntity<>(new ErrorResponse("Request parameter is missing: " + ex.getParameterName()), - HttpStatus.BAD_REQUEST); - } - - @ExceptionHandler(TypeMismatchException.class) - public ResponseEntity handleTypeMismatch(TypeMismatchException ex) { - return new ResponseEntity<>(new ErrorResponse("Request parameter type mismatch: " + ex.getMostSpecificCause()), - HttpStatus.BAD_REQUEST); - } - - @ExceptionHandler(HttpMessageNotReadableException.class) - public ResponseEntity handleHttpMessageNotReadable(HttpMessageNotReadableException ex) { - return new ResponseEntity<>(new ErrorResponse("There is an error in the JSON format of the request payload"), - HttpStatus.BAD_REQUEST); - } - - @ExceptionHandler(ConstraintViolationException.class) - public ResponseEntity handleConstraintViolation(ConstraintViolationException ex) { - ConstraintViolation constraintViolation = ex.getConstraintViolations().iterator().next(); - Iterator iterator = constraintViolation.getPropertyPath().iterator(); - String parameterName = null; - - while (iterator.hasNext()) { - Path.Node node = iterator.next(); - if (node.getKind() == ElementKind.PARAMETER) { - parameterName = node.getName(); - break; - } - } - return new ResponseEntity<>(new ErrorResponse(parameterName + " " + constraintViolation.getMessage()), - HttpStatus.BAD_REQUEST); - } - - @ExceptionHandler(MethodArgumentNotValidException.class) - public ResponseEntity handleMethodArgumentNotValid(MethodArgumentNotValidException ex) { - - FieldError fieldError = ex.getBindingResult().getFieldError(); - return new ResponseEntity<>(new ErrorResponse(fieldError.getField() + " " + fieldError.getDefaultMessage()), - HttpStatus.BAD_REQUEST); - } - - @ExceptionHandler(AccessDeniedException.class) - public ResponseEntity handleAccessDeniedException(AccessDeniedException ex) { - return new ResponseEntity<>(new ErrorResponse("Access to the specified resource has been forbidden"), - HttpStatus.FORBIDDEN); - } - - @ExceptionHandler(DataAccessTokenNoUserIdentityException.class) - public ResponseEntity handleDataAccessTokenNoUserIdentityException() { - ErrorResponse response = new ErrorResponse("No authenticated identity found while processing request"); - return new ResponseEntity<>(response, HttpStatus.UNAUTHORIZED); - } - - @ExceptionHandler(DataAccessTokenProhibitedUserException.class) - public ResponseEntity handleDataAccessTokenProhibitedUserException() { - ErrorResponse response = new ErrorResponse("You are prohibited from using Data Access Tokens"); - return new ResponseEntity<>(response, HttpStatus.UNAUTHORIZED); - } - - @ExceptionHandler(AccessForbiddenException.class) - public ResponseEntity handleAccessForbiddenException() { - ErrorResponse response = new ErrorResponse("The access is forbidden."); - return new ResponseEntity<>(response, HttpStatus.UNAUTHORIZED); - } - - @ExceptionHandler(TokenNotFoundException.class) - public ResponseEntity handleTokenNotFoundException() { - ErrorResponse response = new ErrorResponse("Specified token cannot be found"); - return new ResponseEntity<>(response, HttpStatus.NOT_FOUND); - } - - @ExceptionHandler(CacheNotFoundException.class) - public ResponseEntity handleCacheNotFoundException(CacheNotFoundException ex) { - return new ResponseEntity<>(new ErrorResponse("No cache found with name " + ex.getCacheName()), - HttpStatus.NOT_FOUND); - } - - @ExceptionHandler(CacheOperationException.class) - public ResponseEntity handleCacheOperationException(CacheNotFoundException ex) { - ErrorResponse response = new ErrorResponse("Error evicting caches. Please try again or validate correct operation of your configured caching implementation."); - return new ResponseEntity<>(response, HttpStatus.INTERNAL_SERVER_ERROR); - } - - @ExceptionHandler(GenericAssayNotFoundException.class) - public ResponseEntity handleGenericAssayNotFound(GenericAssayNotFoundException ex) { - - return new ResponseEntity<>(new ErrorResponse("stableId not found: " + ex.getStableId()), - HttpStatus.NOT_FOUND); - } - - @ExceptionHandler(ResourceDefinitionNotFoundException.class) - public ResponseEntity handleResourceDefinitionNotFound(ResourceDefinitionNotFoundException ex) { - return new ResponseEntity<>(new ErrorResponse("Resource not found: " + ex.getResourceId()), - HttpStatus.NOT_FOUND); - } - - @ExceptionHandler(BadSqlGrammarException.class) - public ResponseEntity handleBadSqlGrammar(BadSqlGrammarException ex) { - ex.printStackTrace(); // we still want this to show up in the logs - return new ResponseEntity<>( - new ErrorResponse("SQL exception. If you are a maintainer of this instance, see logs for details."), - HttpStatus.INTERNAL_SERVER_ERROR - ); - } - - @ExceptionHandler(NoSuchElementException.class) - public ResponseEntity handleNoSuchElementException(NoSuchElementException ex) { - return new ResponseEntity<>(new ErrorResponse(ex.getMessage()), HttpStatus.NOT_FOUND); - } -} diff --git a/src/main/java/org/cbioportal/web/interceptor/UniqueKeyInterceptor.java b/src/main/java/org/cbioportal/web/interceptor/UniqueKeyInterceptor.java deleted file mode 100644 index baba716ecef..00000000000 --- a/src/main/java/org/cbioportal/web/interceptor/UniqueKeyInterceptor.java +++ /dev/null @@ -1,101 +0,0 @@ -package org.cbioportal.web.interceptor; - -import org.cbioportal.model.Alteration; -import org.cbioportal.model.ClinicalData; -import org.cbioportal.model.ClinicalEvent; -import org.cbioportal.model.CopyNumberSeg; -import org.cbioportal.model.GenePanelData; -import org.cbioportal.model.MolecularData; -import org.cbioportal.model.MrnaPercentile; -import org.cbioportal.model.MutationSpectrum; -import org.cbioportal.model.NumericGeneMolecularData; -import org.cbioportal.model.Patient; -import org.cbioportal.model.ResourceData; -import org.cbioportal.model.Sample; -import org.cbioportal.model.StructuralVariant; -import org.springframework.core.MethodParameter; -import org.springframework.http.MediaType; -import org.springframework.http.converter.json.MappingJacksonValue; -import org.springframework.http.server.ServerHttpRequest; -import org.springframework.http.server.ServerHttpResponse; -import org.springframework.web.bind.annotation.ControllerAdvice; -import org.springframework.web.servlet.mvc.method.annotation.AbstractMappingJacksonResponseBodyAdvice; - -import java.util.List; - -import static org.cbioportal.utils.Encoder.calculateBase64; - -@ControllerAdvice("org.cbioportal.web") -public class UniqueKeyInterceptor extends AbstractMappingJacksonResponseBodyAdvice { - - @Override - protected void beforeBodyWriteInternal(MappingJacksonValue mappingJacksonValue, MediaType mediaType, - MethodParameter methodParameter, ServerHttpRequest serverHttpRequest, - ServerHttpResponse serverHttpResponse) { - Object value = mappingJacksonValue.getValue(); - if (value instanceof List) { - List list = (List) value; - for (Object object : list) { - if (object instanceof Alteration) { - Alteration alteration = (Alteration) object; - alteration.setUniqueSampleKey(calculateBase64(alteration.getSampleId(), alteration.getStudyId())); - alteration.setUniquePatientKey(calculateBase64(alteration.getPatientId(), alteration.getStudyId())); - } else if (object instanceof ClinicalData) { - ClinicalData clinicalData = (ClinicalData) object; - if (clinicalData.getSampleId() != null) { - clinicalData.setUniqueSampleKey(calculateBase64(clinicalData.getSampleId(), clinicalData.getStudyId())); - } - clinicalData.setUniquePatientKey(calculateBase64(clinicalData.getPatientId(), clinicalData.getStudyId())); - } else if (object instanceof ClinicalEvent) { - ClinicalEvent clinicalEvent = (ClinicalEvent) object; - clinicalEvent.setUniquePatientKey(calculateBase64(clinicalEvent.getPatientId(), clinicalEvent.getStudyId())); - } else if (object instanceof CopyNumberSeg) { - CopyNumberSeg copyNumberSeg = (CopyNumberSeg) object; - copyNumberSeg.setUniqueSampleKey(calculateBase64(copyNumberSeg.getSampleStableId(), copyNumberSeg.getCancerStudyIdentifier())); - copyNumberSeg.setUniquePatientKey(calculateBase64(copyNumberSeg.getPatientId(), copyNumberSeg.getCancerStudyIdentifier())); - } else if (object instanceof GenePanelData) { - GenePanelData genePanelData = (GenePanelData) object; - genePanelData.setUniqueSampleKey(calculateBase64(genePanelData.getSampleId(), genePanelData.getStudyId())); - genePanelData.setUniquePatientKey(calculateBase64(genePanelData.getPatientId(), genePanelData.getStudyId())); - } else if (object instanceof MolecularData) { - MolecularData molecularData = (MolecularData) object; - molecularData.setUniqueSampleKey(calculateBase64(molecularData.getSampleId(), molecularData.getStudyId())); - molecularData.setUniquePatientKey(calculateBase64(molecularData.getPatientId(), molecularData.getStudyId())); - } else if (object instanceof MrnaPercentile) { - MrnaPercentile mrnaPercentile = (MrnaPercentile) object; - mrnaPercentile.setUniqueSampleKey(calculateBase64(mrnaPercentile.getSampleId(), mrnaPercentile.getStudyId())); - mrnaPercentile.setUniquePatientKey(calculateBase64(mrnaPercentile.getPatientId(), mrnaPercentile.getStudyId())); - } else if (object instanceof MutationSpectrum) { - MutationSpectrum mutationSpectrum = (MutationSpectrum) object; - mutationSpectrum.setUniqueSampleKey(calculateBase64(mutationSpectrum.getSampleId(), mutationSpectrum.getStudyId())); - mutationSpectrum.setUniquePatientKey(calculateBase64(mutationSpectrum.getPatientId(), mutationSpectrum.getStudyId())); - } else if (object instanceof NumericGeneMolecularData) { - NumericGeneMolecularData numericGeneMolecularData = (NumericGeneMolecularData) object; - numericGeneMolecularData.setUniqueSampleKey(calculateBase64(numericGeneMolecularData.getSampleId(), numericGeneMolecularData.getStudyId())); - numericGeneMolecularData.setUniquePatientKey(calculateBase64(numericGeneMolecularData.getPatientId(), numericGeneMolecularData.getStudyId())); - } else if (object instanceof Patient) { - Patient patient = (Patient) object; - patient.setUniquePatientKey(calculateBase64(patient.getStableId(), patient.getCancerStudyIdentifier())); - } else if (object instanceof Sample) { - Sample sample = (Sample) object; - sample.setUniqueSampleKey(calculateBase64(sample.getStableId(), sample.getCancerStudyIdentifier())); - sample.setUniquePatientKey(calculateBase64(sample.getPatientStableId(), - sample.getCancerStudyIdentifier())); - } else if (object instanceof StructuralVariant) { - StructuralVariant structuralVariant = (StructuralVariant) object; - structuralVariant.setUniqueSampleKey(calculateBase64(structuralVariant.getSampleId(), structuralVariant.getStudyId())); - structuralVariant.setUniquePatientKey(calculateBase64(structuralVariant.getPatientId(), structuralVariant.getStudyId())); - } else if (object instanceof ResourceData) { - ResourceData resourceData = (ResourceData) object; - if (resourceData.getSampleId() != null) { - resourceData.setUniqueSampleKey(calculateBase64(resourceData.getSampleId(), resourceData.getStudyId())); - } - if (resourceData.getPatientId() != null) { - resourceData.setUniquePatientKey(calculateBase64(resourceData.getPatientId(), resourceData.getStudyId())); - } - } - } - } - } - -} diff --git a/src/main/java/org/cbioportal/web/mixin/CancerStudyMixin.java b/src/main/java/org/cbioportal/web/mixin/CancerStudyMixin.java deleted file mode 100644 index f8fc1045e66..00000000000 --- a/src/main/java/org/cbioportal/web/mixin/CancerStudyMixin.java +++ /dev/null @@ -1,24 +0,0 @@ -package org.cbioportal.web.mixin; - -import com.fasterxml.jackson.annotation.JsonFormat; -import com.fasterxml.jackson.annotation.JsonIgnore; -import com.fasterxml.jackson.annotation.JsonProperty; -import org.cbioportal.model.TypeOfCancer; - -import java.util.Date; - -public class CancerStudyMixin { - - @JsonIgnore - private Integer cancerStudyId; - @JsonProperty("studyId") - private String cancerStudyIdentifier; - @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss") - private Date importDate; - @JsonProperty("cancerTypeId") - private String typeOfCancerId; - @JsonProperty("cancerType") - private TypeOfCancer typeOfCancer; - @JsonProperty("referenceGenome") - private String referenceGenome; -} diff --git a/src/main/java/org/cbioportal/web/mixin/ClinicalAttributeCountMixin.java b/src/main/java/org/cbioportal/web/mixin/ClinicalAttributeCountMixin.java deleted file mode 100644 index 4510c009639..00000000000 --- a/src/main/java/org/cbioportal/web/mixin/ClinicalAttributeCountMixin.java +++ /dev/null @@ -1,9 +0,0 @@ -package org.cbioportal.web.mixin; - -import com.fasterxml.jackson.annotation.JsonProperty; - -public class ClinicalAttributeCountMixin { - - @JsonProperty("clinicalAttributeId") - private String attrId; -} diff --git a/src/main/java/org/cbioportal/web/mixin/ClinicalAttributeMixin.java b/src/main/java/org/cbioportal/web/mixin/ClinicalAttributeMixin.java deleted file mode 100644 index e5b23cbc539..00000000000 --- a/src/main/java/org/cbioportal/web/mixin/ClinicalAttributeMixin.java +++ /dev/null @@ -1,14 +0,0 @@ -package org.cbioportal.web.mixin; - -import com.fasterxml.jackson.annotation.JsonIgnore; -import com.fasterxml.jackson.annotation.JsonProperty; - -public class ClinicalAttributeMixin { - - @JsonProperty("clinicalAttributeId") - private String attrId; - @JsonIgnore - private Integer cancerStudyId; - @JsonProperty("studyId") - private String cancerStudyIdentifier; -} diff --git a/src/main/java/org/cbioportal/web/mixin/ClinicalDataCountMixin.java b/src/main/java/org/cbioportal/web/mixin/ClinicalDataCountMixin.java deleted file mode 100644 index 92c5c657ccb..00000000000 --- a/src/main/java/org/cbioportal/web/mixin/ClinicalDataCountMixin.java +++ /dev/null @@ -1,9 +0,0 @@ -package org.cbioportal.web.mixin; - -import com.fasterxml.jackson.annotation.JsonIgnore; - -public class ClinicalDataCountMixin { - - @JsonIgnore - private String attributeId; -} diff --git a/src/main/java/org/cbioportal/web/mixin/ClinicalDataMixin.java b/src/main/java/org/cbioportal/web/mixin/ClinicalDataMixin.java deleted file mode 100644 index 7f5e481fc4d..00000000000 --- a/src/main/java/org/cbioportal/web/mixin/ClinicalDataMixin.java +++ /dev/null @@ -1,14 +0,0 @@ -package org.cbioportal.web.mixin; - -import com.fasterxml.jackson.annotation.JsonIgnore; -import com.fasterxml.jackson.annotation.JsonProperty; - -public class ClinicalDataMixin { - - @JsonIgnore - private Integer internalId; - @JsonProperty("clinicalAttributeId") - private String attrId; - @JsonProperty("value") - private String attrValue; -} diff --git a/src/main/java/org/cbioportal/web/mixin/ClinicalEventDataMixin.java b/src/main/java/org/cbioportal/web/mixin/ClinicalEventDataMixin.java deleted file mode 100644 index c889e865a55..00000000000 --- a/src/main/java/org/cbioportal/web/mixin/ClinicalEventDataMixin.java +++ /dev/null @@ -1,9 +0,0 @@ -package org.cbioportal.web.mixin; - -import com.fasterxml.jackson.annotation.JsonIgnore; - -public class ClinicalEventDataMixin { - - @JsonIgnore - private Integer clinicalEventId; -} diff --git a/src/main/java/org/cbioportal/web/mixin/ClinicalEventMixin.java b/src/main/java/org/cbioportal/web/mixin/ClinicalEventMixin.java deleted file mode 100644 index 1b6c4fc4822..00000000000 --- a/src/main/java/org/cbioportal/web/mixin/ClinicalEventMixin.java +++ /dev/null @@ -1,14 +0,0 @@ -package org.cbioportal.web.mixin; - -import com.fasterxml.jackson.annotation.JsonIgnore; -import com.fasterxml.jackson.annotation.JsonProperty; - -public class ClinicalEventMixin { - - @JsonIgnore - private Integer clinicalEventId; - @JsonProperty("startNumberOfDaysSinceDiagnosis") - private Integer startDate; - @JsonProperty("endNumberOfDaysSinceDiagnosis") - private Integer stopDate; -} diff --git a/src/main/java/org/cbioportal/web/mixin/CopyNumberSegMixin.java b/src/main/java/org/cbioportal/web/mixin/CopyNumberSegMixin.java deleted file mode 100644 index 896c371400e..00000000000 --- a/src/main/java/org/cbioportal/web/mixin/CopyNumberSegMixin.java +++ /dev/null @@ -1,22 +0,0 @@ -package org.cbioportal.web.mixin; - -import com.fasterxml.jackson.annotation.JsonIgnore; -import com.fasterxml.jackson.annotation.JsonProperty; - -public class CopyNumberSegMixin { - - @JsonIgnore - private Long segId; - @JsonIgnore - private Integer cancerStudyId; - @JsonProperty("studyId") - private String cancerStudyIdentifier; - @JsonIgnore - private Integer sampleId; - @JsonProperty("sampleId") - private String sampleStableId; - @JsonProperty("numberOfProbes") - private Integer numProbes; - @JsonProperty("chromosome") - private String chr; -} diff --git a/src/main/java/org/cbioportal/web/mixin/DataAccessTokenMixin.java b/src/main/java/org/cbioportal/web/mixin/DataAccessTokenMixin.java deleted file mode 100644 index 119cae61c5a..00000000000 --- a/src/main/java/org/cbioportal/web/mixin/DataAccessTokenMixin.java +++ /dev/null @@ -1,13 +0,0 @@ -package org.cbioportal.web.mixin; - -import com.fasterxml.jackson.annotation.JsonFormat; - -import java.util.Date; - -public class DataAccessTokenMixin { - - @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss") - private Date expiration; - @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss") - private Date creation; -} diff --git a/src/main/java/org/cbioportal/web/mixin/DiscreteCopyNumberDataMixin.java b/src/main/java/org/cbioportal/web/mixin/DiscreteCopyNumberDataMixin.java deleted file mode 100644 index ef9a17f3871..00000000000 --- a/src/main/java/org/cbioportal/web/mixin/DiscreteCopyNumberDataMixin.java +++ /dev/null @@ -1,9 +0,0 @@ -package org.cbioportal.web.mixin; - -import com.fasterxml.jackson.annotation.JsonProperty; - -public class DiscreteCopyNumberDataMixin { - - @JsonProperty("namespaceColumns") - private Object annotationJson; -} \ No newline at end of file diff --git a/src/main/java/org/cbioportal/web/mixin/GeneMixin.java b/src/main/java/org/cbioportal/web/mixin/GeneMixin.java deleted file mode 100644 index fb4445cfcb2..00000000000 --- a/src/main/java/org/cbioportal/web/mixin/GeneMixin.java +++ /dev/null @@ -1,5 +0,0 @@ -package org.cbioportal.web.mixin; - -public class GeneMixin { - -} diff --git a/src/main/java/org/cbioportal/web/mixin/GenePanelMixin.java b/src/main/java/org/cbioportal/web/mixin/GenePanelMixin.java deleted file mode 100644 index 1ccbc6af9bd..00000000000 --- a/src/main/java/org/cbioportal/web/mixin/GenePanelMixin.java +++ /dev/null @@ -1,12 +0,0 @@ -package org.cbioportal.web.mixin; - -import com.fasterxml.jackson.annotation.JsonIgnore; -import com.fasterxml.jackson.annotation.JsonProperty; - -public class GenePanelMixin { - - @JsonIgnore - private Integer internalId; - @JsonProperty("genePanelId") - private String stableId; -} diff --git a/src/main/java/org/cbioportal/web/mixin/GenePanelToGeneMixin.java b/src/main/java/org/cbioportal/web/mixin/GenePanelToGeneMixin.java deleted file mode 100644 index aacf2d62ba2..00000000000 --- a/src/main/java/org/cbioportal/web/mixin/GenePanelToGeneMixin.java +++ /dev/null @@ -1,9 +0,0 @@ -package org.cbioportal.web.mixin; - -import com.fasterxml.jackson.annotation.JsonIgnore; - -public class GenePanelToGeneMixin { - - @JsonIgnore - private String genePanelId; -} diff --git a/src/main/java/org/cbioportal/web/mixin/GenesetCorrelationMixin.java b/src/main/java/org/cbioportal/web/mixin/GenesetCorrelationMixin.java deleted file mode 100644 index fa42833f5fe..00000000000 --- a/src/main/java/org/cbioportal/web/mixin/GenesetCorrelationMixin.java +++ /dev/null @@ -1,11 +0,0 @@ -package org.cbioportal.web.mixin; - -import com.fasterxml.jackson.annotation.JsonProperty; - -public class GenesetCorrelationMixin { - - @JsonProperty("expressionGeneticProfileId") - private String expressionMolecularProfileId; - @JsonProperty("zScoreGeneticProfileId") - private String zScoreMolecularProfileId; -} diff --git a/src/main/java/org/cbioportal/web/mixin/GenesetMixin.java b/src/main/java/org/cbioportal/web/mixin/GenesetMixin.java deleted file mode 100644 index a1a2adecc67..00000000000 --- a/src/main/java/org/cbioportal/web/mixin/GenesetMixin.java +++ /dev/null @@ -1,9 +0,0 @@ -package org.cbioportal.web.mixin; - -import com.fasterxml.jackson.annotation.JsonIgnore; - -public class GenesetMixin { - - @JsonIgnore - private Integer internalId; -} diff --git a/src/main/java/org/cbioportal/web/mixin/GenesetMolecularDataMixin.java b/src/main/java/org/cbioportal/web/mixin/GenesetMolecularDataMixin.java deleted file mode 100644 index ae836c19de1..00000000000 --- a/src/main/java/org/cbioportal/web/mixin/GenesetMolecularDataMixin.java +++ /dev/null @@ -1,9 +0,0 @@ -package org.cbioportal.web.mixin; - -import com.fasterxml.jackson.annotation.JsonProperty; - -public class GenesetMolecularDataMixin { - - @JsonProperty("geneticProfileId") - private String molecularProfileId; -} diff --git a/src/main/java/org/cbioportal/web/mixin/GisticMixin.java b/src/main/java/org/cbioportal/web/mixin/GisticMixin.java deleted file mode 100644 index 5913c07dbb5..00000000000 --- a/src/main/java/org/cbioportal/web/mixin/GisticMixin.java +++ /dev/null @@ -1,14 +0,0 @@ -package org.cbioportal.web.mixin; - -import com.fasterxml.jackson.annotation.JsonIgnore; -import com.fasterxml.jackson.annotation.JsonProperty; - -import java.math.BigDecimal; - -public class GisticMixin { - - @JsonIgnore - private Long gisticRoiId; - @JsonProperty("studyId") - private String cancerStudyId; -} diff --git a/src/main/java/org/cbioportal/web/mixin/GisticToGeneMixin.java b/src/main/java/org/cbioportal/web/mixin/GisticToGeneMixin.java deleted file mode 100644 index b43b1cebd75..00000000000 --- a/src/main/java/org/cbioportal/web/mixin/GisticToGeneMixin.java +++ /dev/null @@ -1,9 +0,0 @@ -package org.cbioportal.web.mixin; - -import com.fasterxml.jackson.annotation.JsonIgnore; - -public class GisticToGeneMixin { - - @JsonIgnore - private Long gisticRoiId; -} diff --git a/src/main/java/org/cbioportal/web/mixin/MolecularProfileMixin.java b/src/main/java/org/cbioportal/web/mixin/MolecularProfileMixin.java deleted file mode 100644 index 78f58c76163..00000000000 --- a/src/main/java/org/cbioportal/web/mixin/MolecularProfileMixin.java +++ /dev/null @@ -1,20 +0,0 @@ -package org.cbioportal.web.mixin; - -import com.fasterxml.jackson.annotation.JsonIgnore; -import com.fasterxml.jackson.annotation.JsonProperty; -import org.cbioportal.model.CancerStudy; - -public class MolecularProfileMixin { - - @JsonIgnore - private Integer molecularProfileId; - @JsonProperty("molecularProfileId") - private String stableId; - @JsonIgnore - private Integer cancerStudyId; - @JsonProperty("studyId") - private String cancerStudyIdentifier; - @JsonProperty("study") - private CancerStudy cancerStudy; - -} diff --git a/src/main/java/org/cbioportal/web/mixin/MutSigMixin.java b/src/main/java/org/cbioportal/web/mixin/MutSigMixin.java deleted file mode 100644 index f837ef99240..00000000000 --- a/src/main/java/org/cbioportal/web/mixin/MutSigMixin.java +++ /dev/null @@ -1,18 +0,0 @@ -package org.cbioportal.web.mixin; - -import com.fasterxml.jackson.annotation.JsonIgnore; -import com.fasterxml.jackson.annotation.JsonProperty; - -import java.math.BigDecimal; - -public class MutSigMixin { - - @JsonIgnore - private Integer cancerStudyId; - @JsonProperty("studyId") - private String cancerStudyIdentifier; - @JsonIgnore - private Integer numbasescovered; - @JsonProperty("numberOfMutations") - private Integer nummutations; -} diff --git a/src/main/java/org/cbioportal/web/mixin/MutationMixin.java b/src/main/java/org/cbioportal/web/mixin/MutationMixin.java deleted file mode 100644 index 36e59eaba4e..00000000000 --- a/src/main/java/org/cbioportal/web/mixin/MutationMixin.java +++ /dev/null @@ -1,23 +0,0 @@ -package org.cbioportal.web.mixin; - -import com.fasterxml.jackson.annotation.JsonProperty; -import com.fasterxml.jackson.annotation.JsonRawValue; -import io.swagger.v3.oas.annotations.media.Schema; - -public class MutationMixin { - - @JsonProperty("variantAllele") - private String tumorSeqAllele; - @JsonProperty("refseqMrnaId") - private String refseqMrnaId; - @JsonProperty("proteinPosStart") - private Integer proteinPosStart; - @JsonProperty("proteinPosEnd") - private Integer proteinPosEnd; - @JsonProperty("chr") - private String chr; - - @Schema(type = "java.util.Map") - @JsonProperty("namespaceColumns") - private Object annotationJSON; -} diff --git a/src/main/java/org/cbioportal/web/mixin/MutationSpectrumMixin.java b/src/main/java/org/cbioportal/web/mixin/MutationSpectrumMixin.java deleted file mode 100644 index b4ef6b1dbe6..00000000000 --- a/src/main/java/org/cbioportal/web/mixin/MutationSpectrumMixin.java +++ /dev/null @@ -1,19 +0,0 @@ -package org.cbioportal.web.mixin; - -import com.fasterxml.jackson.annotation.JsonProperty; - -public class MutationSpectrumMixin { - - @JsonProperty("CtoA") - private Integer ctoA; - @JsonProperty("CtoG") - private Integer ctoG; - @JsonProperty("CtoT") - private Integer ctoT; - @JsonProperty("TtoA") - private Integer ttoA; - @JsonProperty("TtoC") - private Integer ttoC; - @JsonProperty("TtoG") - private Integer ttoG; -} diff --git a/src/main/java/org/cbioportal/web/mixin/PatientMixin.java b/src/main/java/org/cbioportal/web/mixin/PatientMixin.java deleted file mode 100644 index 3e555424e4e..00000000000 --- a/src/main/java/org/cbioportal/web/mixin/PatientMixin.java +++ /dev/null @@ -1,16 +0,0 @@ -package org.cbioportal.web.mixin; - -import com.fasterxml.jackson.annotation.JsonIgnore; -import com.fasterxml.jackson.annotation.JsonProperty; - -public class PatientMixin { - - @JsonIgnore - private Integer internalId; - @JsonProperty("patientId") - private String stableId; - @JsonIgnore - private Integer cancerStudyId; - @JsonProperty("studyId") - private String cancerStudyIdentifier; -} diff --git a/src/main/java/org/cbioportal/web/mixin/ReferenceGenomeGeneMixin.java b/src/main/java/org/cbioportal/web/mixin/ReferenceGenomeGeneMixin.java deleted file mode 100644 index 0a333d11eb0..00000000000 --- a/src/main/java/org/cbioportal/web/mixin/ReferenceGenomeGeneMixin.java +++ /dev/null @@ -1,9 +0,0 @@ -package org.cbioportal.web.mixin; - -import com.fasterxml.jackson.annotation.JsonIgnore; -import com.fasterxml.jackson.annotation.JsonProperty; - -public class ReferenceGenomeGeneMixin { - @JsonIgnore - private Integer referenceGenomeId; -} diff --git a/src/main/java/org/cbioportal/web/mixin/ResourceDefinitionMixin.java b/src/main/java/org/cbioportal/web/mixin/ResourceDefinitionMixin.java deleted file mode 100644 index b1c60d06509..00000000000 --- a/src/main/java/org/cbioportal/web/mixin/ResourceDefinitionMixin.java +++ /dev/null @@ -1,9 +0,0 @@ -package org.cbioportal.web.mixin; - -import com.fasterxml.jackson.annotation.JsonProperty; - -public class ResourceDefinitionMixin { - - @JsonProperty("studyId") - private String cancerStudyIdentifier; -} diff --git a/src/main/java/org/cbioportal/web/mixin/SampleListMixin.java b/src/main/java/org/cbioportal/web/mixin/SampleListMixin.java deleted file mode 100644 index d6919ae56aa..00000000000 --- a/src/main/java/org/cbioportal/web/mixin/SampleListMixin.java +++ /dev/null @@ -1,19 +0,0 @@ -package org.cbioportal.web.mixin; - -import com.fasterxml.jackson.annotation.JsonIgnore; -import com.fasterxml.jackson.annotation.JsonProperty; -import org.cbioportal.model.CancerStudy; - -public class SampleListMixin { - - @JsonIgnore - private Integer listId; - @JsonProperty("sampleListId") - private String stableId; - @JsonIgnore - private Integer cancerStudyId; - @JsonProperty("studyId") - private String cancerStudyIdentifier; - @JsonIgnore - private CancerStudy cancerStudy; -} diff --git a/src/main/java/org/cbioportal/web/mixin/SampleMixin.java b/src/main/java/org/cbioportal/web/mixin/SampleMixin.java deleted file mode 100644 index 4242a9f5d10..00000000000 --- a/src/main/java/org/cbioportal/web/mixin/SampleMixin.java +++ /dev/null @@ -1,21 +0,0 @@ -package org.cbioportal.web.mixin; - -import com.fasterxml.jackson.annotation.JsonIgnore; -import com.fasterxml.jackson.annotation.JsonProperty; -import org.cbioportal.model.Patient; - -public class SampleMixin { - - @JsonIgnore - private Integer internalId; - @JsonProperty("sampleId") - private String stableId; - @JsonIgnore - private Integer patientId; - @JsonProperty("patientId") - private String patientStableId; - @JsonIgnore - private Patient patient; - @JsonProperty("studyId") - private String cancerStudyIdentifier; -} diff --git a/src/main/java/org/cbioportal/web/mixin/SessionDataMixin.java b/src/main/java/org/cbioportal/web/mixin/SessionDataMixin.java deleted file mode 100644 index 60b4351eb2a..00000000000 --- a/src/main/java/org/cbioportal/web/mixin/SessionDataMixin.java +++ /dev/null @@ -1,18 +0,0 @@ -package org.cbioportal.web.mixin; - -import java.util.Set; - -import com.fasterxml.jackson.annotation.JsonIgnore; - -public class SessionDataMixin { - @JsonIgnore - private String owner; - @JsonIgnore - private Long created; - @JsonIgnore - private Float version; - @JsonIgnore - private Set users; - @JsonIgnore - private Long lastUpdated; -} diff --git a/src/main/java/org/cbioportal/web/mixin/SessionMixin.java b/src/main/java/org/cbioportal/web/mixin/SessionMixin.java deleted file mode 100644 index 0d7e0a89d45..00000000000 --- a/src/main/java/org/cbioportal/web/mixin/SessionMixin.java +++ /dev/null @@ -1,14 +0,0 @@ -package org.cbioportal.web.mixin; - -import com.fasterxml.jackson.annotation.JsonIgnore; - -public class SessionMixin { - - @JsonIgnore - private String source; - @JsonIgnore - private String type; - @JsonIgnore - private String checksum; - -} diff --git a/src/main/java/org/cbioportal/web/mixin/StructuralVariantMixin.java b/src/main/java/org/cbioportal/web/mixin/StructuralVariantMixin.java deleted file mode 100644 index a0d840ed5ff..00000000000 --- a/src/main/java/org/cbioportal/web/mixin/StructuralVariantMixin.java +++ /dev/null @@ -1,9 +0,0 @@ -package org.cbioportal.web.mixin; - -import com.fasterxml.jackson.annotation.*; - -public class StructuralVariantMixin { - - @JsonProperty("namespaceColumns") - private Object annotationJson; -} \ No newline at end of file diff --git a/src/main/java/org/cbioportal/web/mixin/TypeOfCancerMixin.java b/src/main/java/org/cbioportal/web/mixin/TypeOfCancerMixin.java deleted file mode 100644 index 73f4d8a1520..00000000000 --- a/src/main/java/org/cbioportal/web/mixin/TypeOfCancerMixin.java +++ /dev/null @@ -1,9 +0,0 @@ -package org.cbioportal.web.mixin; - -import com.fasterxml.jackson.annotation.JsonProperty; - -public class TypeOfCancerMixin { - - @JsonProperty("cancerTypeId") - private String typeOfCancerId; -} diff --git a/src/main/java/org/cbioportal/web/parameter/BinsGeneratorConfig.java b/src/main/java/org/cbioportal/web/parameter/BinsGeneratorConfig.java deleted file mode 100644 index 78b0de399e4..00000000000 --- a/src/main/java/org/cbioportal/web/parameter/BinsGeneratorConfig.java +++ /dev/null @@ -1,26 +0,0 @@ -package org.cbioportal.web.parameter; - -import java.math.BigDecimal; - -public class BinsGeneratorConfig { - - private BigDecimal binSize; - private BigDecimal anchorValue; - - public BigDecimal getBinSize() { - return binSize; - } - - public void setBinSize(BigDecimal binSize) { - this.binSize = binSize; - } - - public BigDecimal getAnchorValue() { - return anchorValue; - } - - public void setAnchorValue(BigDecimal anchorValue) { - this.anchorValue = anchorValue; - } - -} diff --git a/src/main/java/org/cbioportal/web/parameter/CategorizedClinicalDataCountFilter.java b/src/main/java/org/cbioportal/web/parameter/CategorizedClinicalDataCountFilter.java deleted file mode 100644 index 22ce588453e..00000000000 --- a/src/main/java/org/cbioportal/web/parameter/CategorizedClinicalDataCountFilter.java +++ /dev/null @@ -1,71 +0,0 @@ -package org.cbioportal.web.parameter; - -import java.util.List; - -public final class CategorizedClinicalDataCountFilter { - - public static Builder getBuilder() { - return new Builder(); - } - private final List sampleNumericalClinicalDataFilters; - private final List sampleCategoricalClinicalDataFilters; - private final List patientNumericalClinicalDataFilters; - private final List patientCategoricalClinicalDataFilters; - - private CategorizedClinicalDataCountFilter(Builder builder) { - this.sampleCategoricalClinicalDataFilters = builder.sampleCategoricalClinicalDataFilters; - this.sampleNumericalClinicalDataFilters = builder.sampleNumericalClinicalDataFilters; - this.patientCategoricalClinicalDataFilters = builder.patientCategoricalClinicalDataFilters; - this.patientNumericalClinicalDataFilters = builder.patientNumericalClinicalDataFilters; - } - - public List getSampleNumericalClinicalDataFilters() { - return sampleNumericalClinicalDataFilters; - } - - public List getSampleCategoricalClinicalDataFilters() { - return sampleCategoricalClinicalDataFilters; - } - - public List getPatientNumericalClinicalDataFilters() { - return patientNumericalClinicalDataFilters; - } - - public List getPatientCategoricalClinicalDataFilters() { - return patientCategoricalClinicalDataFilters; - } - - public static class Builder { - private List sampleNumericalClinicalDataFilters; - private List sampleCategoricalClinicalDataFilters; - private List patientNumericalClinicalDataFilters; - private List patientCategoricalClinicalDataFilters; - - private Builder(){ - - } - public Builder setSampleCategoricalClinicalDataFilters(List sampleCategoricalClinicalDataFilters) { - this.sampleCategoricalClinicalDataFilters = sampleCategoricalClinicalDataFilters; - return this; - } - - public Builder setSampleNumericalClinicalDataFilters(List sampleNumericalClinicalDataFilters) { - this.sampleNumericalClinicalDataFilters = sampleNumericalClinicalDataFilters; - return this; - } - - public Builder setPatientCategoricalClinicalDataFilters(List patientCategoricalClinicalDataFilters) { - this.patientCategoricalClinicalDataFilters = patientCategoricalClinicalDataFilters; - return this; - } - - public Builder setPatientNumericalClinicalDataFilters(List patientNumericalClinicalDataFilters) { - this.patientNumericalClinicalDataFilters = patientNumericalClinicalDataFilters; - return this; - } - - public CategorizedClinicalDataCountFilter build() { - return new CategorizedClinicalDataCountFilter(this); - } - } -} diff --git a/src/main/java/org/cbioportal/web/parameter/CategorizedGenericAssayDataCountFilter.java b/src/main/java/org/cbioportal/web/parameter/CategorizedGenericAssayDataCountFilter.java deleted file mode 100644 index 3d9face92c8..00000000000 --- a/src/main/java/org/cbioportal/web/parameter/CategorizedGenericAssayDataCountFilter.java +++ /dev/null @@ -1,72 +0,0 @@ -package org.cbioportal.web.parameter; - -import java.util.List; - -public final class CategorizedGenericAssayDataCountFilter { - - public static Builder getBuilder() { - return new Builder(); - } - - private final List sampleNumericalGenericAssayDataFilters; - private final List sampleCategoricalGenericAssayDataFilters; - private final List patientNumericalGenericAssayDataFilters; - private final List patientCategoricalGenericAssayDataFilters; - private CategorizedGenericAssayDataCountFilter(Builder builder) { - this.sampleCategoricalGenericAssayDataFilters = builder.sampleCategoricalGenericAssayDataFilters; - this.sampleNumericalGenericAssayDataFilters = builder.sampleNumericalGenericAssayDataFilters; - this.patientCategoricalGenericAssayDataFilters = builder.patientCategoricalGenericAssayDataFilters; - this.patientNumericalGenericAssayDataFilters = builder.patientNumericalGenericAssayDataFilters; - } - - public List getSampleNumericalGenericAssayDataFilters() { - return sampleNumericalGenericAssayDataFilters; - } - - public List getSampleCategoricalGenericAssayDataFilters() { - return sampleCategoricalGenericAssayDataFilters; - } - - public List getPatientNumericalGenericAssayDataFilters() { - return patientNumericalGenericAssayDataFilters; - } - - public List getPatientCategoricalGenericAssayDataFilters() { - return patientCategoricalGenericAssayDataFilters; - } - - public static class Builder { - private List sampleNumericalGenericAssayDataFilters; - private List sampleCategoricalGenericAssayDataFilters; - private List patientNumericalGenericAssayDataFilters; - private List patientCategoricalGenericAssayDataFilters; - - private Builder(){ - - } - - public Builder setSampleCategoricalGenericAssayDataFilters(List sampleCategoricalGenericAssayDataFilters) { - this.sampleCategoricalGenericAssayDataFilters = sampleCategoricalGenericAssayDataFilters; - return this; - } - - public Builder setSampleNumericalGenericAssayDataFilters(List sampleNumericalGenericAssayDataFilters) { - this.sampleNumericalGenericAssayDataFilters = sampleNumericalGenericAssayDataFilters; - return this; - } - - public Builder setPatientCategoricalGenericAssayDataFilters(List patientCategoricalGenericAssayDataFilters) { - this.patientCategoricalGenericAssayDataFilters = patientCategoricalGenericAssayDataFilters; - return this; - } - - public Builder setPatientNumericalGenericAssayDataFilters(List patientNumericalGenericAssayDataFilters) { - this.patientNumericalGenericAssayDataFilters = patientNumericalGenericAssayDataFilters; - return this; - } - - public CategorizedGenericAssayDataCountFilter build() { - return new CategorizedGenericAssayDataCountFilter(this); - } - } -} diff --git a/src/main/java/org/cbioportal/web/parameter/ClinicalAttributeCountFilter.java b/src/main/java/org/cbioportal/web/parameter/ClinicalAttributeCountFilter.java deleted file mode 100644 index 63e59aa5944..00000000000 --- a/src/main/java/org/cbioportal/web/parameter/ClinicalAttributeCountFilter.java +++ /dev/null @@ -1,34 +0,0 @@ -package org.cbioportal.web.parameter; - -import jakarta.validation.constraints.AssertTrue; -import jakarta.validation.constraints.Size; -import java.util.List; -import java.io.Serializable; - -public class ClinicalAttributeCountFilter implements Serializable { - - @Size(min = 1, max = PagingConstants.MAX_PAGE_SIZE) - private List sampleIdentifiers; - private String sampleListId; - - @AssertTrue - private boolean isEitherSampleListIdOrSampleIdsPresent() { - return sampleListId != null ^ sampleIdentifiers != null; - } - - public List getSampleIdentifiers() { - return sampleIdentifiers; - } - - public void setSampleIdentifiers(List sampleIdentifiers) { - this.sampleIdentifiers = sampleIdentifiers; - } - - public String getSampleListId() { - return sampleListId; - } - - public void setSampleListId(String sampleListId) { - this.sampleListId = sampleListId; - } -} diff --git a/src/main/java/org/cbioportal/web/parameter/ClinicalDataBinCountFilter.java b/src/main/java/org/cbioportal/web/parameter/ClinicalDataBinCountFilter.java deleted file mode 100644 index 565b7286556..00000000000 --- a/src/main/java/org/cbioportal/web/parameter/ClinicalDataBinCountFilter.java +++ /dev/null @@ -1,18 +0,0 @@ -package org.cbioportal.web.parameter; - -import java.io.Serializable; -import java.util.List; - -public class ClinicalDataBinCountFilter extends DataBinCountFilter implements Serializable { - - private List attributes; - - public List getAttributes() { - return attributes; - } - - public void setAttributes(List attributes) { - this.attributes = attributes; - } - -} diff --git a/src/main/java/org/cbioportal/web/parameter/ClinicalDataBinFilter.java b/src/main/java/org/cbioportal/web/parameter/ClinicalDataBinFilter.java deleted file mode 100644 index 4df9e8add07..00000000000 --- a/src/main/java/org/cbioportal/web/parameter/ClinicalDataBinFilter.java +++ /dev/null @@ -1,20 +0,0 @@ -package org.cbioportal.web.parameter; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; - -import java.io.Serializable; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class ClinicalDataBinFilter extends DataBinFilter implements Serializable { - - private String attributeId; - - public String getAttributeId() { - return attributeId; - } - - public void setAttributeId(String attributeId) { - this.attributeId = attributeId; - } - -} diff --git a/src/main/java/org/cbioportal/web/parameter/ClinicalDataCountFilter.java b/src/main/java/org/cbioportal/web/parameter/ClinicalDataCountFilter.java deleted file mode 100644 index 66679896da5..00000000000 --- a/src/main/java/org/cbioportal/web/parameter/ClinicalDataCountFilter.java +++ /dev/null @@ -1,26 +0,0 @@ -package org.cbioportal.web.parameter; - -import java.io.Serializable; -import java.util.List; - -public class ClinicalDataCountFilter implements Serializable { - - private List attributes; - private StudyViewFilter studyViewFilter; - - public List getAttributes() { - return attributes; - } - - public void setAttributes(List attributes) { - this.attributes = attributes; - } - - public StudyViewFilter getStudyViewFilter() { - return studyViewFilter; - } - - public void setStudyViewFilter(StudyViewFilter studyViewFilter) { - this.studyViewFilter = studyViewFilter; - } -} diff --git a/src/main/java/org/cbioportal/web/parameter/ClinicalDataFilter.java b/src/main/java/org/cbioportal/web/parameter/ClinicalDataFilter.java deleted file mode 100644 index 1b406b31532..00000000000 --- a/src/main/java/org/cbioportal/web/parameter/ClinicalDataFilter.java +++ /dev/null @@ -1,51 +0,0 @@ -package org.cbioportal.web.parameter; - -import io.swagger.v3.oas.annotations.Hidden; - -import java.io.Serializable; -import java.util.List; - -public class ClinicalDataFilter extends DataFilter implements Serializable { - - private String attributeId; - - @Hidden - private List samples; - @Hidden - private String datatype; - @Hidden - private String displayName; - - public String getAttributeId() { - return attributeId; - } - - public void setAttributeId(String attributeId) { - this.attributeId = attributeId; - } - - public List getSamples() { - return samples; - } - - public void setSamples(List samples) { - this.samples = samples; - } - - public String getDatatype() { - return datatype; - } - - public void setDatatype(String datatype) { - this.datatype = datatype; - } - - public String getDisplayName() { - return displayName; - } - - public void setDisplayName(String displayName) { - this.displayName = displayName; - } - -} diff --git a/src/main/java/org/cbioportal/web/parameter/ClinicalDataIdentifier.java b/src/main/java/org/cbioportal/web/parameter/ClinicalDataIdentifier.java deleted file mode 100644 index 9b015f866b7..00000000000 --- a/src/main/java/org/cbioportal/web/parameter/ClinicalDataIdentifier.java +++ /dev/null @@ -1,25 +0,0 @@ -package org.cbioportal.web.parameter; - -import java.io.Serializable; - -public class ClinicalDataIdentifier implements Serializable { - - private String entityId; - private String studyId; - - public String getEntityId() { - return entityId; - } - - public void setEntityId(String entityId) { - this.entityId = entityId; - } - - public String getStudyId() { - return studyId; - } - - public void setStudyId(String studyId) { - this.studyId = studyId; - } -} diff --git a/src/main/java/org/cbioportal/web/parameter/ClinicalDataMultiStudyFilter.java b/src/main/java/org/cbioportal/web/parameter/ClinicalDataMultiStudyFilter.java deleted file mode 100644 index 784331533e7..00000000000 --- a/src/main/java/org/cbioportal/web/parameter/ClinicalDataMultiStudyFilter.java +++ /dev/null @@ -1,33 +0,0 @@ -package org.cbioportal.web.parameter; - -import org.cbioportal.web.ClinicalDataController; - -import jakarta.validation.constraints.Size; -import java.util.List; -import java.io.Serializable; - -import static org.cbioportal.web.parameter.PagingConstants.MAX_PAGE_SIZE; - -public class ClinicalDataMultiStudyFilter implements Serializable { - - @Size(min = 1, max = ClinicalDataController.CLINICAL_DATA_MAX_PAGE_SIZE) - private List identifiers; - @Size(min = 1, max = MAX_PAGE_SIZE) - private List attributeIds; - - public List getIdentifiers() { - return identifiers; - } - - public void setIdentifiers(List identifiers) { - this.identifiers = identifiers; - } - - public List getAttributeIds() { - return attributeIds; - } - - public void setAttributeIds(List attributeIds) { - this.attributeIds = attributeIds; - } -} diff --git a/src/main/java/org/cbioportal/web/parameter/ClinicalDataSingleStudyFilter.java b/src/main/java/org/cbioportal/web/parameter/ClinicalDataSingleStudyFilter.java deleted file mode 100644 index f76f9daf0b7..00000000000 --- a/src/main/java/org/cbioportal/web/parameter/ClinicalDataSingleStudyFilter.java +++ /dev/null @@ -1,32 +0,0 @@ -package org.cbioportal.web.parameter; - -import jakarta.validation.constraints.Size; -import org.cbioportal.web.ClinicalDataController; - -import java.util.List; - -import static org.cbioportal.web.parameter.PagingConstants.MAX_PAGE_SIZE; - -public class ClinicalDataSingleStudyFilter { - - @Size(min = 1, max = ClinicalDataController.CLINICAL_DATA_MAX_PAGE_SIZE) - private List ids; - @Size(min = 1, max = MAX_PAGE_SIZE) - private List attributeIds; - - public List getIds() { - return ids; - } - - public void setIds(List ids) { - this.ids = ids; - } - - public List getAttributeIds() { - return attributeIds; - } - - public void setAttributeIds(List attributeIds) { - this.attributeIds = attributeIds; - } -} diff --git a/src/main/java/org/cbioportal/web/parameter/ClinicalDataType.java b/src/main/java/org/cbioportal/web/parameter/ClinicalDataType.java deleted file mode 100644 index 6f7121c8fb2..00000000000 --- a/src/main/java/org/cbioportal/web/parameter/ClinicalDataType.java +++ /dev/null @@ -1,6 +0,0 @@ -package org.cbioportal.web.parameter; - -public enum ClinicalDataType { - SAMPLE, - PATIENT; -} diff --git a/src/main/java/org/cbioportal/web/parameter/ClinicalEventAttributeRequest.java b/src/main/java/org/cbioportal/web/parameter/ClinicalEventAttributeRequest.java deleted file mode 100644 index 4cc2d6f254e..00000000000 --- a/src/main/java/org/cbioportal/web/parameter/ClinicalEventAttributeRequest.java +++ /dev/null @@ -1,31 +0,0 @@ -package org.cbioportal.web.parameter; - -import jakarta.validation.constraints.Size; - -import java.io.Serializable; -import java.util.List; -import java.util.Set; - -public class ClinicalEventAttributeRequest implements Serializable { - - @Size(min = 1, max = PagingConstants.MAX_PAGE_SIZE) - private List patientIdentifiers; - - private Set clinicalEventRequests; - - public List getPatientIdentifiers() { - return patientIdentifiers; - } - - public void setPatientIdentifiers(List patientIdentifiers) { - this.patientIdentifiers = patientIdentifiers; - } - - public Set getClinicalEventRequests() { - return clinicalEventRequests; - } - - public void setClinicalEventRequests(Set clinicalEventRequests) { - this.clinicalEventRequests = clinicalEventRequests; - } -} \ No newline at end of file diff --git a/src/main/java/org/cbioportal/web/parameter/ClinicalEventRequest.java b/src/main/java/org/cbioportal/web/parameter/ClinicalEventRequest.java deleted file mode 100644 index 1397e0dcb85..00000000000 --- a/src/main/java/org/cbioportal/web/parameter/ClinicalEventRequest.java +++ /dev/null @@ -1,32 +0,0 @@ -package org.cbioportal.web.parameter; - -import org.cbioportal.model.ClinicalEventData; - -import jakarta.validation.constraints.NotNull; - -import java.io.Serializable; -import java.util.List; - -public class ClinicalEventRequest implements Serializable { - - @NotNull - private String eventType; - - private List attributes; - - public String getEventType() { - return eventType; - } - - public void setEventType(String eventType) { - this.eventType = eventType; - } - - public List getAttributes() { - return attributes; - } - - public void setAttributes(List attributes) { - this.attributes = attributes; - } -} diff --git a/src/main/java/org/cbioportal/web/parameter/ClinicalEventRequestIdentifier.java b/src/main/java/org/cbioportal/web/parameter/ClinicalEventRequestIdentifier.java deleted file mode 100644 index 2d38a85e91c..00000000000 --- a/src/main/java/org/cbioportal/web/parameter/ClinicalEventRequestIdentifier.java +++ /dev/null @@ -1,31 +0,0 @@ -package org.cbioportal.web.parameter; - - -import jakarta.validation.constraints.NotNull; -import jakarta.validation.constraints.Size; -import java.io.Serializable; -import java.util.Set; - -public class ClinicalEventRequestIdentifier implements Serializable { - - @Size(max = PagingConstants.MAX_PAGE_SIZE) - private Set clinicalEventRequests; - @NotNull - private OccurrencePosition position; - - public Set getClinicalEventRequests() { - return clinicalEventRequests; - } - - public void setClinicalEventRequests(Set clinicalEventRequests) { - this.clinicalEventRequests = clinicalEventRequests; - } - - public OccurrencePosition getPosition() { - return position; - } - - public void setPosition(OccurrencePosition position) { - this.position = position; - } -} diff --git a/src/main/java/org/cbioportal/web/parameter/ClinicalTrackConfig.java b/src/main/java/org/cbioportal/web/parameter/ClinicalTrackConfig.java deleted file mode 100644 index 9683a4b2fbe..00000000000 --- a/src/main/java/org/cbioportal/web/parameter/ClinicalTrackConfig.java +++ /dev/null @@ -1,36 +0,0 @@ -package org.cbioportal.web.parameter; - -import com.fasterxml.jackson.annotation.JsonInclude; - -import java.io.Serializable; - -@JsonInclude(JsonInclude.Include.ALWAYS) -class ClinicalTrackConfig implements Serializable { - private String stableId; - private String sortOrder; - private Boolean gapOn; - - public String getStableId() { - return stableId; - } - - public void setStableId(String stableId) { - this.stableId = stableId; - } - - public String getSortOrder() { - return sortOrder; - } - - public void setSortOrder(String sortOrder) { - this.sortOrder = sortOrder; - } - - public Boolean getGapOn() { - return gapOn; - } - - public void setGapOn(Boolean gapOn) { - this.gapOn = gapOn; - } -} diff --git a/src/main/java/org/cbioportal/web/parameter/CoExpressionFilter.java b/src/main/java/org/cbioportal/web/parameter/CoExpressionFilter.java deleted file mode 100644 index 0bc03751278..00000000000 --- a/src/main/java/org/cbioportal/web/parameter/CoExpressionFilter.java +++ /dev/null @@ -1,56 +0,0 @@ -package org.cbioportal.web.parameter; - -import jakarta.validation.constraints.AssertTrue; -import jakarta.validation.constraints.Size; -import java.util.List; - -public class CoExpressionFilter { - - @Size(min = 1, max = PagingConstants.MAX_PAGE_SIZE) - private List sampleIds; - private String sampleListId; - private Integer entrezGeneId; - private String genesetId; - - @AssertTrue - private boolean isEitherSampleListIdOrSampleIdsPresent() { - return sampleListId != null ^ sampleIds != null; - } - - @AssertTrue - private boolean isEitherEntrezGeneIdOrGenesetIdPresent() { - return entrezGeneId != null ^ genesetId != null; - } - - public List getSampleIds() { - return sampleIds; - } - - public void setSampleIds(List sampleIds) { - this.sampleIds = sampleIds; - } - - public String getSampleListId() { - return sampleListId; - } - - public void setSampleListId(String sampleListId) { - this.sampleListId = sampleListId; - } - - public Integer getEntrezGeneId() { - return entrezGeneId; - } - - public void setEntrezGeneId(Integer entrezGeneId) { - this.entrezGeneId = entrezGeneId; - } - - public String getGenesetId() { - return genesetId; - } - - public void setGenesetId(String genesetId) { - this.genesetId = genesetId; - } -} diff --git a/src/main/java/org/cbioportal/web/parameter/CopyNumberCountIdentifier.java b/src/main/java/org/cbioportal/web/parameter/CopyNumberCountIdentifier.java deleted file mode 100644 index 20d14894d2e..00000000000 --- a/src/main/java/org/cbioportal/web/parameter/CopyNumberCountIdentifier.java +++ /dev/null @@ -1,23 +0,0 @@ -package org.cbioportal.web.parameter; - -public class CopyNumberCountIdentifier { - - private Integer entrezGeneId; - private Integer alteration; - - public Integer getEntrezGeneId() { - return entrezGeneId; - } - - public void setEntrezGeneId(Integer entrezGeneId) { - this.entrezGeneId = entrezGeneId; - } - - public Integer getAlteration() { - return alteration; - } - - public void setAlteration(Integer alteration) { - this.alteration = alteration; - } -} diff --git a/src/main/java/org/cbioportal/web/parameter/CustomGeneList.java b/src/main/java/org/cbioportal/web/parameter/CustomGeneList.java deleted file mode 100644 index ae762277a51..00000000000 --- a/src/main/java/org/cbioportal/web/parameter/CustomGeneList.java +++ /dev/null @@ -1,45 +0,0 @@ -package org.cbioportal.web.parameter; - -import com.fasterxml.jackson.annotation.JsonIgnore; -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.databind.ObjectMapper; -import org.cbioportal.utils.removeme.Session; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.IOException; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class CustomGeneList extends Session { - - private final Logger LOG = LoggerFactory.getLogger(CustomGeneList.class); - private CustomGeneListData data; - - @Override - public void setData(Object data) { - ObjectMapper mapper = new ObjectMapper(); - try { - this.data = mapper.readValue(mapper.writeValueAsString(data), CustomGeneListData.class); - } catch (IOException e) { - LOG.error("Error occurred", e); - } - } - - @Override - public CustomGeneListData getData() { - return data; - } - - @JsonIgnore - @Override - public String getSource() { - return super.getSource(); - } - - @JsonIgnore - @Override - public SessionType getType() { - return super.getType(); - } - -} diff --git a/src/main/java/org/cbioportal/web/parameter/CustomGeneListData.java b/src/main/java/org/cbioportal/web/parameter/CustomGeneListData.java deleted file mode 100644 index 6e9f1c5d194..00000000000 --- a/src/main/java/org/cbioportal/web/parameter/CustomGeneListData.java +++ /dev/null @@ -1,47 +0,0 @@ -package org.cbioportal.web.parameter; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; - -import java.io.Serializable; -import java.util.HashSet; -import java.util.Set; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class CustomGeneListData implements Serializable { - - private String name; - private String description; - private Set geneList = new HashSet<>(); - private Set users = new HashSet<>(); - - public Set getUsers() { - return users; - } - - public void setUsers(Set users) { - this.users = users; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String getDescription() { - return description; - } - - public void setDescription(String description) { - this.description = description; - } - - public Set getGeneList() { - return geneList; - } - - public void setGeneList(Set geneList) { this.geneList = geneList; } - -} diff --git a/src/main/java/org/cbioportal/web/parameter/CustomSampleIdentifier.java b/src/main/java/org/cbioportal/web/parameter/CustomSampleIdentifier.java deleted file mode 100644 index 51692168fcb..00000000000 --- a/src/main/java/org/cbioportal/web/parameter/CustomSampleIdentifier.java +++ /dev/null @@ -1,36 +0,0 @@ -package org.cbioportal.web.parameter; - -import java.io.Serializable; - -public class CustomSampleIdentifier extends SampleIdentifier implements Serializable { - - private boolean isFilteredOut = false; - private String value; - private String uniqueSampleId; - - public boolean getIsFilteredOut() { - return isFilteredOut; - } - - public void setIsFilteredOut(boolean isFilteredOut) { - this.isFilteredOut = isFilteredOut; - } - - public String getValue() { - return value; - } - - public void setValue(String value) { - this.value = value; - } - - // Generating unique SampleId by concatenating studyId and sampleId - public String getUniqueSampleId() { - // Assuming studyId and sampleId are available in SampleIdentifier - // Concatenate with "_" in between if both values are not null - if (getStudyId() != null && getSampleId() != null) { - return getStudyId() + "_" + getSampleId(); - } - return null; // or return null if either studyId or sampleId is null - } -} diff --git a/src/main/java/org/cbioportal/web/parameter/DataBinCountFilter.java b/src/main/java/org/cbioportal/web/parameter/DataBinCountFilter.java deleted file mode 100644 index 4ed75c840d7..00000000000 --- a/src/main/java/org/cbioportal/web/parameter/DataBinCountFilter.java +++ /dev/null @@ -1,16 +0,0 @@ -package org.cbioportal.web.parameter; - -import java.io.Serializable; - -public class DataBinCountFilter implements Serializable { - - private StudyViewFilter studyViewFilter; - - public StudyViewFilter getStudyViewFilter() { - return studyViewFilter; - } - - public void setStudyViewFilter(StudyViewFilter studyViewFilter) { - this.studyViewFilter = studyViewFilter; - } -} diff --git a/src/main/java/org/cbioportal/web/parameter/DataBinFilter.java b/src/main/java/org/cbioportal/web/parameter/DataBinFilter.java deleted file mode 100644 index 4011b5547a4..00000000000 --- a/src/main/java/org/cbioportal/web/parameter/DataBinFilter.java +++ /dev/null @@ -1,101 +0,0 @@ -package org.cbioportal.web.parameter; - -import java.io.Serializable; -import java.math.BigDecimal; -import java.util.List; - -import jakarta.validation.constraints.AssertTrue; -import org.springframework.validation.annotation.Validated; - -@Validated -public class DataBinFilter implements Serializable { - - public enum BinMethod { - MEDIAN, - QUARTILE, - CUSTOM, - GENERATE; - } - - private Boolean disableLogScale = false; - private List customBins; // needed for 'Custom bins' frontend option - - // FIXME: Code added for backwards compatibility. - // Replace by commented out line after merge of PR: - // https://github.com/cBioPortal/cbioportal-frontend/pull/4102 - private BinMethod binMethod = BinMethod.CUSTOM; - //private BinMethod binMethod; // needed for 'Median split' and 'Quartile' frontend options - - private BinsGeneratorConfig binsGeneratorConfig; // needed for 'Generate Bins' frontend option - private BigDecimal start; - private BigDecimal end; - - public Boolean getDisableLogScale() { - return disableLogScale; - } - - public void setDisableLogScale(Boolean disableLogScale) { - this.disableLogScale = disableLogScale; - } - - public List getCustomBins() { - return customBins; - } - - public void setCustomBins(List customBins) { - this.customBins = customBins; - } - - public BigDecimal getStart() { - return start; - } - - public void setStart(BigDecimal start) { - this.start = start; - } - - public BigDecimal getEnd() { - return end; - } - - public void setEnd(BigDecimal end) { - this.end = end; - } - - public BinMethod getBinMethod() { - return binMethod; - } - - public void setBinMethod(BinMethod binMethod) { - this.binMethod = binMethod; - } - - public BinsGeneratorConfig getBinsGeneratorConfig() { - return binsGeneratorConfig; - } - - public void setBinsGeneratorConfig( - BinsGeneratorConfig binsGeneratorConfig) { - this.binsGeneratorConfig = binsGeneratorConfig; - } - - // TODO: make this work - @AssertTrue - private boolean rangeIsCoveringCustomBins() { - if (this.customBins != null && (start != null || end != null)) { - boolean valid = true; - for (BigDecimal bin : this.customBins) { - if (start != null && start.compareTo(bin) > 0) { - valid = false; - break; - } - if (end != null && end.compareTo(bin) < 0) { - valid = false; - break; - } - } - return valid; - } - return true; - } -} diff --git a/src/main/java/org/cbioportal/web/parameter/DataBinMethod.java b/src/main/java/org/cbioportal/web/parameter/DataBinMethod.java deleted file mode 100644 index c63dda3c48c..00000000000 --- a/src/main/java/org/cbioportal/web/parameter/DataBinMethod.java +++ /dev/null @@ -1,19 +0,0 @@ -package org.cbioportal.web.parameter; - -/** - * STATIC and DYNAMIC binning relate to the way bin boundaries are derived from numerical data of a sample cohort - * defined by a Study View Filter (SVF). - * - * When binning in STATIC mode, the binning ignores any filter in the SVF on the attribute that is the subject of - * binning. In effect, it bins all values of the cohort. This mode is important to drive frontend behavior where - * histograms show bins related to the entire data range, but highlight the currently selected/filtered data in blue - * (non-selected data bins in grey). In effect, this way the non-selected data influences the boundaries of the data - * bins, irrespective of the selected attribute range. - * - * When binning in DYNAMIC mode, only the attribute data is binned that is defined by the SVF. The non-selected - * rest of the data does not influence the bin boundaries. - */ -public enum DataBinMethod { - STATIC, - DYNAMIC -} diff --git a/src/main/java/org/cbioportal/web/parameter/DataFilter.java b/src/main/java/org/cbioportal/web/parameter/DataFilter.java deleted file mode 100644 index 05d9c52c8b7..00000000000 --- a/src/main/java/org/cbioportal/web/parameter/DataFilter.java +++ /dev/null @@ -1,18 +0,0 @@ -package org.cbioportal.web.parameter; - -import java.io.Serializable; -import java.util.List; - -public class DataFilter implements Serializable { - - private List values; - - public List getValues() { - return values; - } - - public void setValues(List values) { - this.values = values; - } - -} diff --git a/src/main/java/org/cbioportal/web/parameter/DataFilterValue.java b/src/main/java/org/cbioportal/web/parameter/DataFilterValue.java deleted file mode 100644 index 47fdb0937e9..00000000000 --- a/src/main/java/org/cbioportal/web/parameter/DataFilterValue.java +++ /dev/null @@ -1,46 +0,0 @@ -package org.cbioportal.web.parameter; - -import java.io.Serializable; -import java.math.BigDecimal; - -public class DataFilterValue implements Serializable { - - private BigDecimal start; - private BigDecimal end; - private String value; - - public DataFilterValue() {} - - public DataFilterValue(BigDecimal start, BigDecimal end) { - this.start = start; - this.end = end; - } - - public DataFilterValue(String value) { - this.value = value; - } - - public BigDecimal getStart() { - return start; - } - - public void setStart(BigDecimal start) { - this.start = start; - } - - public BigDecimal getEnd() { - return end; - } - - public void setEnd(BigDecimal end) { - this.end = end; - } - - public String getValue() { - return value; - } - - public void setValue(String value) { - this.value = value; - } -} diff --git a/src/main/java/org/cbioportal/web/parameter/Direction.java b/src/main/java/org/cbioportal/web/parameter/Direction.java deleted file mode 100644 index 1453d856420..00000000000 --- a/src/main/java/org/cbioportal/web/parameter/Direction.java +++ /dev/null @@ -1,7 +0,0 @@ -package org.cbioportal.web.parameter; - -public enum Direction { - - ASC, - DESC -} diff --git a/src/main/java/org/cbioportal/web/parameter/DiscreteCopyNumberEventType.java b/src/main/java/org/cbioportal/web/parameter/DiscreteCopyNumberEventType.java deleted file mode 100644 index 520c58f98bb..00000000000 --- a/src/main/java/org/cbioportal/web/parameter/DiscreteCopyNumberEventType.java +++ /dev/null @@ -1,25 +0,0 @@ -package org.cbioportal.web.parameter; - -import java.util.Arrays; -import java.util.List; - -public enum DiscreteCopyNumberEventType { - - HOMDEL_AND_AMP(-2, 2), - HOMDEL(-2), - AMP(2), - GAIN(1), - HETLOSS(-1), - DIPLOID(0), - ALL(-2, -1, 0, 1, 2); - - private List alterationTypes; - - DiscreteCopyNumberEventType(Integer... alterationTypes) { - this.alterationTypes = Arrays.asList(alterationTypes); - } - - public List getAlterationTypes() { - return alterationTypes; - } -} diff --git a/src/main/java/org/cbioportal/web/parameter/DiscreteCopyNumberFilter.java b/src/main/java/org/cbioportal/web/parameter/DiscreteCopyNumberFilter.java deleted file mode 100644 index 859575119c4..00000000000 --- a/src/main/java/org/cbioportal/web/parameter/DiscreteCopyNumberFilter.java +++ /dev/null @@ -1,44 +0,0 @@ -package org.cbioportal.web.parameter; - -import jakarta.validation.constraints.AssertTrue; -import jakarta.validation.constraints.Size; -import java.util.List; - -public class DiscreteCopyNumberFilter { - - private static final int DISCRETE_COPY_NUMBER_MAX_PAGE_SIZE = 50000; - @Size(min = 1, max = PagingConstants.MAX_PAGE_SIZE) - private List sampleIds; - private String sampleListId; - @Size(min = 1, max = DISCRETE_COPY_NUMBER_MAX_PAGE_SIZE) - private List entrezGeneIds; - - @AssertTrue - private boolean isEitherSampleListIdOrSampleIdsPresent() { - return sampleListId != null ^ sampleIds != null; - } - - public List getSampleIds() { - return sampleIds; - } - - public void setSampleIds(List sampleIds) { - this.sampleIds = sampleIds; - } - - public String getSampleListId() { - return sampleListId; - } - - public void setSampleListId(String sampleListId) { - this.sampleListId = sampleListId; - } - - public List getEntrezGeneIds() { - return entrezGeneIds; - } - - public void setEntrezGeneIds(List entrezGeneIds) { - this.entrezGeneIds = entrezGeneIds; - } -} diff --git a/src/main/java/org/cbioportal/web/parameter/EnrichmentFilter.java b/src/main/java/org/cbioportal/web/parameter/EnrichmentFilter.java deleted file mode 100644 index 571f086a951..00000000000 --- a/src/main/java/org/cbioportal/web/parameter/EnrichmentFilter.java +++ /dev/null @@ -1,32 +0,0 @@ -package org.cbioportal.web.parameter; - -import jakarta.validation.constraints.NotNull; -import jakarta.validation.constraints.Size; - -import java.util.List; - -public class EnrichmentFilter { - - @NotNull - @Size(min = 1) - private List alteredIds; - @NotNull - @Size(min = 1) - private List unalteredIds; - - public List getAlteredIds() { - return alteredIds; - } - - public void setAlteredIds(List alteredIds) { - this.alteredIds = alteredIds; - } - - public List getUnalteredIds() { - return unalteredIds; - } - - public void setUnalteredIds(List unalteredIds) { - this.unalteredIds = unalteredIds; - } -} diff --git a/src/main/java/org/cbioportal/web/parameter/GeneFilter.java b/src/main/java/org/cbioportal/web/parameter/GeneFilter.java deleted file mode 100644 index a956f5a63c7..00000000000 --- a/src/main/java/org/cbioportal/web/parameter/GeneFilter.java +++ /dev/null @@ -1,101 +0,0 @@ -package org.cbioportal.web.parameter; - -import java.io.Serializable; -import java.util.*; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import java.util.stream.Collectors; - -import jakarta.validation.constraints.AssertTrue; -import org.apache.commons.collections4.CollectionUtils; -import org.cbioportal.model.CNA; -import com.fasterxml.jackson.annotation.JsonIgnore; - -public class GeneFilter implements Serializable { - - private Set molecularProfileIds; - private List> geneQueries; - - private final String GENE_QUERY_PATTERN = "^(\\w+)[\\s]*?(?:\\:(?:[\\s]*(?:(AMP)|(GAIN)|(DIPLOID)|(HETLOSS)|(HOMDEL))\\b)+)?$"; - - public class SingleGeneQuery implements Serializable { - private String hugoGeneSymbol; - private List alterations; - - public String getHugoGeneSymbol() { - return hugoGeneSymbol; - } - - public void setHugoGeneSymbol(String hugoGeneSymbol) { - this.hugoGeneSymbol = hugoGeneSymbol; - } - - public List getAlterations() { - return alterations; - } - - public void setAlterations(List alterations) { - this.alterations = alterations; - } - } - - @AssertTrue - private boolean isValid() { - if (!CollectionUtils.isEmpty(geneQueries) && !CollectionUtils.isEmpty(molecularProfileIds)) { - return geneQueries.stream().flatMap(geneQuery -> geneQuery.stream().map(query -> { - Pattern pattern = Pattern.compile(GENE_QUERY_PATTERN); - Matcher matcher = pattern.matcher(query.trim()); - return matcher.matches(); - })).reduce(Boolean.TRUE, Boolean::logicalAnd); - } - return false; - } - - public Set getMolecularProfileIds() { - return molecularProfileIds; - } - - public void setMolecularProfileIds(Set molecularProfileIds) { - this.molecularProfileIds = molecularProfileIds; - } - - public List> getGeneQueries() { - return geneQueries; - } - - public void setGeneQueries(List> geneQueries) { - this.geneQueries = geneQueries; - } - - @JsonIgnore - public List> getSingleGeneQueries() { - - return geneQueries.stream().map(geneQuery -> { - - List singleGeneQueries = new ArrayList(); - - geneQuery.stream().forEach(query -> { - Pattern pattern = Pattern.compile(GENE_QUERY_PATTERN); - Matcher matcher = pattern.matcher(query.trim()); - - if (matcher.find()) { - - String hugoGeneSymbol = matcher.group(1); - Set alterations = new HashSet<>(); - for (int count = 2; count <= matcher.groupCount(); count++) { - if (matcher.group(count) != null) { - alterations.add(CNA.valueOf(matcher.group(count))); - } - } - SingleGeneQuery singleGeneQuery = new SingleGeneQuery(); - singleGeneQuery.setHugoGeneSymbol(hugoGeneSymbol); - singleGeneQuery.setAlterations(new ArrayList<>(alterations)); - singleGeneQueries.add(singleGeneQuery); - } - }); - - return singleGeneQueries; - }).collect(Collectors.toList()); - } - -} \ No newline at end of file diff --git a/src/main/java/org/cbioportal/web/parameter/GeneIdType.java b/src/main/java/org/cbioportal/web/parameter/GeneIdType.java deleted file mode 100644 index a46435d1cdb..00000000000 --- a/src/main/java/org/cbioportal/web/parameter/GeneIdType.java +++ /dev/null @@ -1,7 +0,0 @@ -package org.cbioportal.web.parameter; - -public enum GeneIdType { - - ENTREZ_GENE_ID, - HUGO_GENE_SYMBOL -} diff --git a/src/main/java/org/cbioportal/web/parameter/GenePanelDataFilter.java b/src/main/java/org/cbioportal/web/parameter/GenePanelDataFilter.java deleted file mode 100644 index 9b28bf8c510..00000000000 --- a/src/main/java/org/cbioportal/web/parameter/GenePanelDataFilter.java +++ /dev/null @@ -1,32 +0,0 @@ -package org.cbioportal.web.parameter; - -import jakarta.validation.constraints.AssertTrue; -import jakarta.validation.constraints.Size; -import java.util.List; - -public class GenePanelDataFilter { - @Size(min = 1, max = PagingConstants.MAX_PAGE_SIZE) - private List sampleIds; - private String sampleListId; - - @AssertTrue - private boolean isEitherSampleListIdOrSampleIdsPresent() { - return sampleListId != null ^ sampleIds != null; - } - - public List getSampleIds() { - return sampleIds; - } - - public void setSampleIds(List sampleIds) { - this.sampleIds = sampleIds; - } - - public String getSampleListId() { - return sampleListId; - } - - public void setSampleListId(String sampleListId) { - this.sampleListId = sampleListId; - } -} diff --git a/src/main/java/org/cbioportal/web/parameter/GenePanelDataMultipleStudyFilter.java b/src/main/java/org/cbioportal/web/parameter/GenePanelDataMultipleStudyFilter.java deleted file mode 100644 index f4e70978c6b..00000000000 --- a/src/main/java/org/cbioportal/web/parameter/GenePanelDataMultipleStudyFilter.java +++ /dev/null @@ -1,35 +0,0 @@ -package org.cbioportal.web.parameter; - -import jakarta.validation.constraints.AssertTrue; -import jakarta.validation.constraints.Size; -import java.util.List; -import java.io.Serializable; - -public class GenePanelDataMultipleStudyFilter implements Serializable { - - @Size(min = 1, max = PagingConstants.MAX_PAGE_SIZE) - private List sampleMolecularIdentifiers; - @Size(min = 1, max = PagingConstants.MAX_PAGE_SIZE) - private List molecularProfileIds; - - @AssertTrue - private boolean isEitherMolecularProfileIdsOrSampleMolecularIdentifiersPresent() { - return molecularProfileIds != null ^ sampleMolecularIdentifiers != null; - } - - public List getSampleMolecularIdentifiers() { - return sampleMolecularIdentifiers; - } - - public void setSampleMolecularIdentifiers(List sampleMolecularIdentifiers) { - this.sampleMolecularIdentifiers = sampleMolecularIdentifiers; - } - - public List getMolecularProfileIds() { - return molecularProfileIds; - } - - public void setMolecularProfileIds(List molecularProfileIds) { - this.molecularProfileIds = molecularProfileIds; - } -} diff --git a/src/main/java/org/cbioportal/web/parameter/GenericAssayDataBinCountFilter.java b/src/main/java/org/cbioportal/web/parameter/GenericAssayDataBinCountFilter.java deleted file mode 100644 index eb088eb6faa..00000000000 --- a/src/main/java/org/cbioportal/web/parameter/GenericAssayDataBinCountFilter.java +++ /dev/null @@ -1,18 +0,0 @@ -package org.cbioportal.web.parameter; - -import java.io.Serializable; -import java.util.List; - -public class GenericAssayDataBinCountFilter extends DataBinCountFilter implements Serializable { - - private List genericAssayDataBinFilters; - - public List getGenericAssayDataBinFilters() { - return genericAssayDataBinFilters; - } - - public void setGenericAssayDataBinFilters(List genericAssayDataBinFilters) { - this.genericAssayDataBinFilters = genericAssayDataBinFilters; - } - -} diff --git a/src/main/java/org/cbioportal/web/parameter/GenericAssayDataBinFilter.java b/src/main/java/org/cbioportal/web/parameter/GenericAssayDataBinFilter.java deleted file mode 100644 index 0d30f34b7c0..00000000000 --- a/src/main/java/org/cbioportal/web/parameter/GenericAssayDataBinFilter.java +++ /dev/null @@ -1,25 +0,0 @@ -package org.cbioportal.web.parameter; - -import java.io.Serializable; - -public class GenericAssayDataBinFilter extends DataBinFilter implements Serializable { - private String stableId; - private String profileType; - - public String getStableId() { - return stableId; - } - - public void setStableId(String stableId) { - this.stableId = stableId; - } - - public String getProfileType() { - return profileType; - } - - public void setProfileType(String profileType) { - this.profileType = profileType; - } - -} diff --git a/src/main/java/org/cbioportal/web/parameter/GenericAssayDataCountFilter.java b/src/main/java/org/cbioportal/web/parameter/GenericAssayDataCountFilter.java deleted file mode 100644 index b4e60373894..00000000000 --- a/src/main/java/org/cbioportal/web/parameter/GenericAssayDataCountFilter.java +++ /dev/null @@ -1,26 +0,0 @@ -package org.cbioportal.web.parameter; - -import java.io.Serializable; -import java.util.List; - -public class GenericAssayDataCountFilter implements Serializable { - - private List genericAssayDataFilters; - private StudyViewFilter studyViewFilter; - - public List getGenericAssayDataFilters() { - return genericAssayDataFilters; - } - - public void setGenericAssayDataFilters(List genericAssayDataFilters) { - this.genericAssayDataFilters = genericAssayDataFilters; - } - - public StudyViewFilter getStudyViewFilter() { - return studyViewFilter; - } - - public void setStudyViewFilter(StudyViewFilter studyViewFilter) { - this.studyViewFilter = studyViewFilter; - } -} diff --git a/src/main/java/org/cbioportal/web/parameter/GenericAssayDataFilter.java b/src/main/java/org/cbioportal/web/parameter/GenericAssayDataFilter.java deleted file mode 100644 index 14dfbf0a46d..00000000000 --- a/src/main/java/org/cbioportal/web/parameter/GenericAssayDataFilter.java +++ /dev/null @@ -1,32 +0,0 @@ -package org.cbioportal.web.parameter; - -import java.io.Serializable; - -public class GenericAssayDataFilter extends DataFilter implements Serializable { - private String stableId; - private String profileType; - - public GenericAssayDataFilter() {} - - public GenericAssayDataFilter(String stableId, String profileType) { - this.stableId = stableId; - this.profileType = profileType; - } - - public String getStableId() { - return stableId; - } - - public void setStableId(String stableId) { - this.stableId = stableId; - } - - public String getProfileType() { - return profileType; - } - - public void setProfileType(String profileType) { - this.profileType = profileType; - } - -} diff --git a/src/main/java/org/cbioportal/web/parameter/GenericAssayDataMultipleStudyFilter.java b/src/main/java/org/cbioportal/web/parameter/GenericAssayDataMultipleStudyFilter.java deleted file mode 100644 index 35a1afb390f..00000000000 --- a/src/main/java/org/cbioportal/web/parameter/GenericAssayDataMultipleStudyFilter.java +++ /dev/null @@ -1,45 +0,0 @@ -package org.cbioportal.web.parameter; - -import jakarta.validation.constraints.AssertTrue; -import jakarta.validation.constraints.Size; -import java.util.List; -import java.io.Serializable; - -public class GenericAssayDataMultipleStudyFilter implements Serializable { - - @Size(min = 1, max = PagingConstants.MAX_PAGE_SIZE) - private List sampleMolecularIdentifiers; - @Size(min = 1, max = PagingConstants.MAX_PAGE_SIZE) - private List molecularProfileIds; - @Size(min = 1, max = PagingConstants.MAX_PAGE_SIZE) - private List genericAssayStableIds; - - @AssertTrue - private boolean isEitherMolecularProfileIdsOrSampleMolecularIdentifiersPresent() { - return molecularProfileIds != null ^ sampleMolecularIdentifiers != null; - } - - public List getSampleMolecularIdentifiers() { - return sampleMolecularIdentifiers; - } - - public void setSampleMolecularIdentifiers(List sampleMolecularIdentifiers) { - this.sampleMolecularIdentifiers = sampleMolecularIdentifiers; - } - - public List getMolecularProfileIds() { - return molecularProfileIds; - } - - public void setMolecularProfileIds(List molecularProfileIds) { - this.molecularProfileIds = molecularProfileIds; - } - - public List getGenericAssayStableIds() { - return genericAssayStableIds; - } - - public void setGenericAssayStableIds(List genericAssayStableIds) { - this.genericAssayStableIds = genericAssayStableIds; - } -} diff --git a/src/main/java/org/cbioportal/web/parameter/GenericAssayFilter.java b/src/main/java/org/cbioportal/web/parameter/GenericAssayFilter.java deleted file mode 100644 index c0f4a75998c..00000000000 --- a/src/main/java/org/cbioportal/web/parameter/GenericAssayFilter.java +++ /dev/null @@ -1,43 +0,0 @@ -package org.cbioportal.web.parameter; - -import jakarta.validation.constraints.AssertTrue; -import jakarta.validation.constraints.Size; -import java.util.List; - -public class GenericAssayFilter { - - @Size(min = 1, max = PagingConstants.MAX_PAGE_SIZE) - private List sampleIds; - private String sampleListId; - @Size(min = 1, max = PagingConstants.MAX_PAGE_SIZE) - private List genericAssayStableId; - - @AssertTrue - private boolean isEitherSampleListIdOrSampleIdsPresent() { - return sampleListId != null ^ sampleIds != null; - } - - public List getSampleIds() { - return sampleIds; - } - - public void setSampleIds(List sampleIds) { - this.sampleIds = sampleIds; - } - - public String getSampleListId() { - return sampleListId; - } - - public void setSampleListId(String sampleListId) { - this.sampleListId = sampleListId; - } - - public List getGenericAssayStableIds() { - return genericAssayStableId; - } - - public void setGenericAssayStableIds(List genericAssayStableId) { - this.genericAssayStableId = genericAssayStableId; - } -} diff --git a/src/main/java/org/cbioportal/web/parameter/GenericAssayMetaFilter.java b/src/main/java/org/cbioportal/web/parameter/GenericAssayMetaFilter.java deleted file mode 100644 index f877912b2a2..00000000000 --- a/src/main/java/org/cbioportal/web/parameter/GenericAssayMetaFilter.java +++ /dev/null @@ -1,29 +0,0 @@ -package org.cbioportal.web.parameter; - -import jakarta.validation.constraints.Size; -import java.util.List; -import java.io.Serializable; - -public class GenericAssayMetaFilter implements Serializable { - - @Size(min = 1, max = PagingConstants.MAX_PAGE_SIZE) - private List molecularProfileIds; - @Size(min = 1, max = PagingConstants.MAX_PAGE_SIZE) - private List genericAssayStableIds; - - public List getMolecularProfileIds() { - return molecularProfileIds; - } - - public void setMolecularProfileIds(List molecularProfileIds) { - this.molecularProfileIds = molecularProfileIds; - } - - public List getGenericAssayStableIds() { - return genericAssayStableIds; - } - - public void setGenericAssayStableIds(List genericAssayStableIds) { - this.genericAssayStableIds = genericAssayStableIds; - } -} \ No newline at end of file diff --git a/src/main/java/org/cbioportal/web/parameter/GenesetDataFilterCriteria.java b/src/main/java/org/cbioportal/web/parameter/GenesetDataFilterCriteria.java deleted file mode 100644 index f0c9c3397f9..00000000000 --- a/src/main/java/org/cbioportal/web/parameter/GenesetDataFilterCriteria.java +++ /dev/null @@ -1,44 +0,0 @@ -package org.cbioportal.web.parameter; - -import java.util.List; - -/** - * Wrapper class for specifying filter criteria for GeneticData items - * in the GeneticDataController services. - * - * @author pieter - * - */ -public class GenesetDataFilterCriteria { - - //The list of identifiers for the gene sets of interest. - private List genesetIds; - //Identifier of pre-defined sample list with samples to query. E.g. brca_tcga_all - private String sampleListId; - //Full list of samples or patients to query, E.g. list with TCGA-AR-A1AR-01, TCGA-BH-A1EO-01... - private List sampleIds; - - public List getGenesetIds() { - return genesetIds; - } - - public void setGenesetIds(List genesetIds) { - this.genesetIds = genesetIds; - } - - public String getSampleListId() { - return sampleListId; - } - - public void setSampleListId(String sampleListId) { - this.sampleListId = sampleListId; - } - - public List getSampleIds() { - return sampleIds; - } - - public void setSampleIds(List sampleIds) { - this.sampleIds = sampleIds; - } -} diff --git a/src/main/java/org/cbioportal/web/parameter/GenomicDataBinCountFilter.java b/src/main/java/org/cbioportal/web/parameter/GenomicDataBinCountFilter.java deleted file mode 100644 index b2e9ad1734a..00000000000 --- a/src/main/java/org/cbioportal/web/parameter/GenomicDataBinCountFilter.java +++ /dev/null @@ -1,18 +0,0 @@ -package org.cbioportal.web.parameter; - -import java.io.Serializable; -import java.util.List; - -public class GenomicDataBinCountFilter extends DataBinCountFilter implements Serializable { - - private List genomicDataBinFilters; - - public List getGenomicDataBinFilters() { - return genomicDataBinFilters; - } - - public void setGenomicDataBinFilters(List genomicDataBinFilters) { - this.genomicDataBinFilters = genomicDataBinFilters; - } - -} diff --git a/src/main/java/org/cbioportal/web/parameter/GenomicDataBinFilter.java b/src/main/java/org/cbioportal/web/parameter/GenomicDataBinFilter.java deleted file mode 100644 index 5629c027ec8..00000000000 --- a/src/main/java/org/cbioportal/web/parameter/GenomicDataBinFilter.java +++ /dev/null @@ -1,25 +0,0 @@ -package org.cbioportal.web.parameter; - -import java.io.Serializable; - -public class GenomicDataBinFilter extends DataBinFilter implements Serializable { - private String hugoGeneSymbol; - private String profileType; - - public String getHugoGeneSymbol() { - return hugoGeneSymbol; - } - - public void setHugoGeneSymbol(String hugoGeneSymbol) { - this.hugoGeneSymbol = hugoGeneSymbol; - } - - public String getProfileType() { - return profileType; - } - - public void setProfileType(String profileType) { - this.profileType = profileType; - } - -} diff --git a/src/main/java/org/cbioportal/web/parameter/GenomicDataCountFilter.java b/src/main/java/org/cbioportal/web/parameter/GenomicDataCountFilter.java deleted file mode 100644 index c01ec7696c1..00000000000 --- a/src/main/java/org/cbioportal/web/parameter/GenomicDataCountFilter.java +++ /dev/null @@ -1,26 +0,0 @@ -package org.cbioportal.web.parameter; - -import java.io.Serializable; -import java.util.List; - -public class GenomicDataCountFilter implements Serializable { - - private List genomicDataFilters; - private StudyViewFilter studyViewFilter; - - public List getGenomicDataFilters() { - return genomicDataFilters; - } - - public void setGenomicDataFilters(List genomicDataFilters) { - this.genomicDataFilters = genomicDataFilters; - } - - public StudyViewFilter getStudyViewFilter() { - return studyViewFilter; - } - - public void setStudyViewFilter(StudyViewFilter studyViewFilter) { - this.studyViewFilter = studyViewFilter; - } -} diff --git a/src/main/java/org/cbioportal/web/parameter/GenomicDataFilter.java b/src/main/java/org/cbioportal/web/parameter/GenomicDataFilter.java deleted file mode 100644 index 34aca9c0894..00000000000 --- a/src/main/java/org/cbioportal/web/parameter/GenomicDataFilter.java +++ /dev/null @@ -1,39 +0,0 @@ -package org.cbioportal.web.parameter; - -import java.io.Serializable; -import java.util.List; - -public class GenomicDataFilter extends DataFilter implements Serializable { - private String hugoGeneSymbol; - private String profileType; - - public GenomicDataFilter() {} - - public GenomicDataFilter(String hugoGeneSymbol, String profileType) { - this.hugoGeneSymbol = hugoGeneSymbol; - this.profileType = profileType; - } - - public GenomicDataFilter(String hugoGeneSymbol, String profileType, List values) { - this.hugoGeneSymbol = hugoGeneSymbol; - this.profileType = profileType; - this.setValues(values); - } - - public String getHugoGeneSymbol() { - return hugoGeneSymbol; - } - - public void setHugoGeneSymbol(String hugoGeneSymbol) { - this.hugoGeneSymbol = hugoGeneSymbol; - } - - public String getProfileType() { - return profileType; - } - - public void setProfileType(String profileType) { - this.profileType = profileType; - } - -} diff --git a/src/main/java/org/cbioportal/web/parameter/Group.java b/src/main/java/org/cbioportal/web/parameter/Group.java deleted file mode 100644 index ae9e8c184e9..00000000000 --- a/src/main/java/org/cbioportal/web/parameter/Group.java +++ /dev/null @@ -1,31 +0,0 @@ -package org.cbioportal.web.parameter; - -import jakarta.validation.constraints.Size; - -import java.io.Serializable; -import java.util.List; - - -public class Group implements Serializable { - - @Size(min = 1, max = PagingConstants.MAX_PAGE_SIZE) - private List sampleIdentifiers; - private String name; - - public List getSampleIdentifiers() { - return sampleIdentifiers; - } - - public void setSampleIdentifiers(List sampleIdentifiers) { - this.sampleIdentifiers = sampleIdentifiers; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - -} diff --git a/src/main/java/org/cbioportal/web/parameter/GroupFilter.java b/src/main/java/org/cbioportal/web/parameter/GroupFilter.java deleted file mode 100644 index 8cfcba4859b..00000000000 --- a/src/main/java/org/cbioportal/web/parameter/GroupFilter.java +++ /dev/null @@ -1,23 +0,0 @@ -package org.cbioportal.web.parameter; - -import jakarta.validation.Valid; -import jakarta.validation.constraints.Size; - -import java.io.Serializable; -import java.util.List; - - -public class GroupFilter implements Serializable { - - @Size(min = 2) - @Valid - private List groups; - - public List getGroups() { - return groups; - } - - public void setGroups(List groups) { - this.groups = groups; - } -} diff --git a/src/main/java/org/cbioportal/web/parameter/HeaderKeyConstants.java b/src/main/java/org/cbioportal/web/parameter/HeaderKeyConstants.java deleted file mode 100644 index 89a51ea7e13..00000000000 --- a/src/main/java/org/cbioportal/web/parameter/HeaderKeyConstants.java +++ /dev/null @@ -1,9 +0,0 @@ -package org.cbioportal.web.parameter; - -/* When changing these edit them in portal/src/main/webapp/WEB-INF/web.xml as - * well to expose the CORS headers */ -public class HeaderKeyConstants { - - public static final String TOTAL_COUNT = "total-count"; - public static final String SAMPLE_COUNT = "sample-count"; -} diff --git a/src/main/java/org/cbioportal/web/parameter/MolecularDataFilter.java b/src/main/java/org/cbioportal/web/parameter/MolecularDataFilter.java deleted file mode 100644 index d8765076905..00000000000 --- a/src/main/java/org/cbioportal/web/parameter/MolecularDataFilter.java +++ /dev/null @@ -1,44 +0,0 @@ -package org.cbioportal.web.parameter; - -import jakarta.validation.constraints.AssertTrue; -import jakarta.validation.constraints.Size; - -import java.util.List; - -public class MolecularDataFilter { - - @Size(min = 1, max = PagingConstants.MAX_PAGE_SIZE) - private List sampleIds; - private String sampleListId; - @Size(min = 1, max = PagingConstants.MAX_PAGE_SIZE) - private List entrezGeneIds; - - @AssertTrue - private boolean isEitherSampleListIdOrSampleIdsPresent() { - return sampleListId != null ^ sampleIds != null; - } - - public List getSampleIds() { - return sampleIds; - } - - public void setSampleIds(List sampleIds) { - this.sampleIds = sampleIds; - } - - public String getSampleListId() { - return sampleListId; - } - - public void setSampleListId(String sampleListId) { - this.sampleListId = sampleListId; - } - - public List getEntrezGeneIds() { - return entrezGeneIds; - } - - public void setEntrezGeneIds(List entrezGeneIds) { - this.entrezGeneIds = entrezGeneIds; - } -} diff --git a/src/main/java/org/cbioportal/web/parameter/MolecularDataMultipleStudyFilter.java b/src/main/java/org/cbioportal/web/parameter/MolecularDataMultipleStudyFilter.java deleted file mode 100644 index 3527ca674c1..00000000000 --- a/src/main/java/org/cbioportal/web/parameter/MolecularDataMultipleStudyFilter.java +++ /dev/null @@ -1,45 +0,0 @@ -package org.cbioportal.web.parameter; - -import jakarta.validation.constraints.AssertTrue; -import jakarta.validation.constraints.Size; -import java.util.List; -import java.io.Serializable; - -public class MolecularDataMultipleStudyFilter implements Serializable { - - @Size(min = 1, max = PagingConstants.MAX_PAGE_SIZE) - private List sampleMolecularIdentifiers; - @Size(min = 1, max = PagingConstants.MAX_PAGE_SIZE) - private List molecularProfileIds; - @Size(min = 1, max = PagingConstants.MAX_PAGE_SIZE) - private List entrezGeneIds; - - @AssertTrue - private boolean isEitherMolecularProfileIdsOrSampleMolecularIdentifiersPresent() { - return molecularProfileIds != null ^ sampleMolecularIdentifiers != null; - } - - public List getSampleMolecularIdentifiers() { - return sampleMolecularIdentifiers; - } - - public void setSampleMolecularIdentifiers(List sampleMolecularIdentifiers) { - this.sampleMolecularIdentifiers = sampleMolecularIdentifiers; - } - - public List getMolecularProfileIds() { - return molecularProfileIds; - } - - public void setMolecularProfileIds(List molecularProfileIds) { - this.molecularProfileIds = molecularProfileIds; - } - - public List getEntrezGeneIds() { - return entrezGeneIds; - } - - public void setEntrezGeneIds(List entrezGeneIds) { - this.entrezGeneIds = entrezGeneIds; - } -} diff --git a/src/main/java/org/cbioportal/web/parameter/MolecularProfileCasesGroupAndAlterationTypeFilter.java b/src/main/java/org/cbioportal/web/parameter/MolecularProfileCasesGroupAndAlterationTypeFilter.java deleted file mode 100644 index a8d991ca95e..00000000000 --- a/src/main/java/org/cbioportal/web/parameter/MolecularProfileCasesGroupAndAlterationTypeFilter.java +++ /dev/null @@ -1,35 +0,0 @@ -package org.cbioportal.web.parameter; - -import io.swagger.v3.oas.annotations.media.Schema; -import org.cbioportal.model.AlterationFilter; - -import java.util.List; - -import jakarta.validation.constraints.Size; - -public class MolecularProfileCasesGroupAndAlterationTypeFilter { - - - private AlterationFilter alterationEventTypes; - @Size(min = 1, max = PagingConstants.MAX_PAGE_SIZE) - @Schema - private List molecularProfileCasesGroupFilter; - - - public List getMolecularProfileCasesGroupFilter() { - return this.molecularProfileCasesGroupFilter; - } - - public void setMolecularProfileCasesGroupFilter( - List molecularProfileCasesGroupFilter) { - this.molecularProfileCasesGroupFilter = molecularProfileCasesGroupFilter; - } - - public AlterationFilter getAlterationEventTypes() { - return this.alterationEventTypes; - } - - public void setAlterationEventTypes(AlterationFilter alterationEventTypes) { - this.alterationEventTypes = alterationEventTypes; - } -} diff --git a/src/main/java/org/cbioportal/web/parameter/MolecularProfileCasesGroupFilter.java b/src/main/java/org/cbioportal/web/parameter/MolecularProfileCasesGroupFilter.java deleted file mode 100644 index decdc4748e5..00000000000 --- a/src/main/java/org/cbioportal/web/parameter/MolecularProfileCasesGroupFilter.java +++ /dev/null @@ -1,36 +0,0 @@ -package org.cbioportal.web.parameter; - -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; - - -import jakarta.validation.constraints.Size; -import org.cbioportal.model.MolecularProfileCaseIdentifier; - -public class MolecularProfileCasesGroupFilter { - - @Size(min = 1, max = PagingConstants.MAX_PAGE_SIZE) - private List MolecularProfileCaseIdentifiers; - private String name; - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public List getMolecularProfileCaseIdentifiers() { - return MolecularProfileCaseIdentifiers; - } - - public void setMolecularProfileCaseIdentifiers( - List molecularProfileCaseIdentifiers) { - - MolecularProfileCaseIdentifiers = new ArrayList<>( - new HashSet<>(molecularProfileCaseIdentifiers)); - } - -} diff --git a/src/main/java/org/cbioportal/web/parameter/MolecularProfileFilter.java b/src/main/java/org/cbioportal/web/parameter/MolecularProfileFilter.java deleted file mode 100644 index bc5a460dc9b..00000000000 --- a/src/main/java/org/cbioportal/web/parameter/MolecularProfileFilter.java +++ /dev/null @@ -1,36 +0,0 @@ -package org.cbioportal.web.parameter; - -import jakarta.validation.constraints.AssertTrue; -import jakarta.validation.constraints.Size; -import java.util.List; -import java.io.Serializable; -import java.util.Set; - -public class MolecularProfileFilter implements Serializable { - - @Size(min = 1, max = PagingConstants.MAX_PAGE_SIZE) - private List studyIds; - @Size(min = 1, max = PagingConstants.MAX_PAGE_SIZE) - private Set molecularProfileIds; - - @AssertTrue - private boolean isEitherStudyIdsOrMolecularProfileIdsPresent() { - return studyIds != null ^ molecularProfileIds != null; - } - - public List getStudyIds() { - return studyIds; - } - - public void setStudyIds(List studyIds) { - this.studyIds = studyIds; - } - - public Set getMolecularProfileIds() { - return molecularProfileIds; - } - - public void setMolecularProfileIds(Set molecularProfileIds) { - this.molecularProfileIds = molecularProfileIds; - } -} diff --git a/src/main/java/org/cbioportal/web/parameter/MutationDataFilter.java b/src/main/java/org/cbioportal/web/parameter/MutationDataFilter.java deleted file mode 100644 index cb5401aaac6..00000000000 --- a/src/main/java/org/cbioportal/web/parameter/MutationDataFilter.java +++ /dev/null @@ -1,55 +0,0 @@ -package org.cbioportal.web.parameter; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonInclude; - -import jakarta.validation.constraints.NotNull; - -import java.io.Serializable; -import java.util.List; - -import static com.fasterxml.jackson.annotation.JsonInclude.Include.NON_NULL; - -@JsonIgnoreProperties(ignoreUnknown = true) -@JsonInclude(NON_NULL) -public class MutationDataFilter implements Serializable { - private String hugoGeneSymbol; - private String profileType; - @NotNull - private MutationOption categorization; // filter by either having mutations or by mutation types - - private List> values; - - public String getHugoGeneSymbol() { - return hugoGeneSymbol; - } - - public void setHugoGeneSymbol(String hugoGeneSymbol) { - this.hugoGeneSymbol = hugoGeneSymbol; - } - - public String getProfileType() { - return profileType; - } - - public void setProfileType(String profileType) { - this.profileType = profileType; - } - - public MutationOption getCategorization() { - return categorization; - } - - public void setCategorization(MutationOption categorization) { - this.categorization = categorization; - } - - public List> getValues() { - return values; - } - - public void setValues(List> values) { - this.values = values; - } -} - diff --git a/src/main/java/org/cbioportal/web/parameter/MutationFilter.java b/src/main/java/org/cbioportal/web/parameter/MutationFilter.java deleted file mode 100644 index f9d10a3fccd..00000000000 --- a/src/main/java/org/cbioportal/web/parameter/MutationFilter.java +++ /dev/null @@ -1,43 +0,0 @@ -package org.cbioportal.web.parameter; - -import jakarta.validation.constraints.AssertTrue; -import jakarta.validation.constraints.Size; -import java.util.List; - -public class MutationFilter { - - @Size(min = 1, max = PagingConstants.MAX_PAGE_SIZE) - private List sampleIds; - private String sampleListId; - @Size(min = 1, max = PagingConstants.MAX_PAGE_SIZE) - private List entrezGeneIds; - - @AssertTrue - private boolean isEitherSampleListIdOrSampleIdsPresent() { - return sampleListId != null ^ sampleIds != null; - } - - public List getSampleIds() { - return sampleIds; - } - - public void setSampleIds(List sampleIds) { - this.sampleIds = sampleIds; - } - - public String getSampleListId() { - return sampleListId; - } - - public void setSampleListId(String sampleListId) { - this.sampleListId = sampleListId; - } - - public List getEntrezGeneIds() { - return entrezGeneIds; - } - - public void setEntrezGeneIds(List entrezGeneIds) { - this.entrezGeneIds = entrezGeneIds; - } -} diff --git a/src/main/java/org/cbioportal/web/parameter/MutationMultipleStudyFilter.java b/src/main/java/org/cbioportal/web/parameter/MutationMultipleStudyFilter.java deleted file mode 100644 index c487cf754fa..00000000000 --- a/src/main/java/org/cbioportal/web/parameter/MutationMultipleStudyFilter.java +++ /dev/null @@ -1,45 +0,0 @@ -package org.cbioportal.web.parameter; - -import jakarta.validation.constraints.AssertTrue; -import jakarta.validation.constraints.Size; - -import java.util.List; -import java.io.Serializable; - -public class MutationMultipleStudyFilter implements Serializable { - - @Size(min = 1, max = PagingConstants.MAX_PAGE_SIZE) - private List sampleMolecularIdentifiers; - private List molecularProfileIds; - @Size(min = 1, max = PagingConstants.MAX_PAGE_SIZE) - private List entrezGeneIds; - - @AssertTrue - private boolean isEitherMolecularProfileIdsOrSampleMolecularIdentifiersPresent() { - return molecularProfileIds != null ^ sampleMolecularIdentifiers != null; - } - - public List getSampleMolecularIdentifiers() { - return sampleMolecularIdentifiers; - } - - public void setSampleMolecularIdentifiers(List sampleMolecularIdentifiers) { - this.sampleMolecularIdentifiers = sampleMolecularIdentifiers; - } - - public List getMolecularProfileIds() { - return molecularProfileIds; - } - - public void setMolecularProfileIds(List molecularProfileIds) { - this.molecularProfileIds = molecularProfileIds; - } - - public List getEntrezGeneIds() { - return entrezGeneIds; - } - - public void setEntrezGeneIds(List entrezGeneIds) { - this.entrezGeneIds = entrezGeneIds; - } -} diff --git a/src/main/java/org/cbioportal/web/parameter/MutationOption.java b/src/main/java/org/cbioportal/web/parameter/MutationOption.java deleted file mode 100644 index 32d98555dce..00000000000 --- a/src/main/java/org/cbioportal/web/parameter/MutationOption.java +++ /dev/null @@ -1,6 +0,0 @@ -package org.cbioportal.web.parameter; - -public enum MutationOption { - MUTATED, // fetch mutation data with MUTATED, NOT_MUTATED, NOT_PROFILED in MutationFilterOption - MUTATION_TYPE // fetch mutation data with mutation types -} diff --git a/src/main/java/org/cbioportal/web/parameter/MutationPositionIdentifier.java b/src/main/java/org/cbioportal/web/parameter/MutationPositionIdentifier.java deleted file mode 100644 index a54854ecec9..00000000000 --- a/src/main/java/org/cbioportal/web/parameter/MutationPositionIdentifier.java +++ /dev/null @@ -1,32 +0,0 @@ -package org.cbioportal.web.parameter; - -public class MutationPositionIdentifier { - - private Integer entrezGeneId; - private Integer proteinPosStart; - private Integer proteinPosEnd; - - public Integer getEntrezGeneId() { - return entrezGeneId; - } - - public void setEntrezGeneId(Integer entrezGeneId) { - this.entrezGeneId = entrezGeneId; - } - - public Integer getProteinPosStart() { - return proteinPosStart; - } - - public void setProteinPosStart(Integer proteinPosStart) { - this.proteinPosStart = proteinPosStart; - } - - public Integer getProteinPosEnd() { - return proteinPosEnd; - } - - public void setProteinPosEnd(Integer proteinPosEnd) { - this.proteinPosEnd = proteinPosEnd; - } -} diff --git a/src/main/java/org/cbioportal/web/parameter/MutationSpectrumFilter.java b/src/main/java/org/cbioportal/web/parameter/MutationSpectrumFilter.java deleted file mode 100644 index 8d97f0b85f8..00000000000 --- a/src/main/java/org/cbioportal/web/parameter/MutationSpectrumFilter.java +++ /dev/null @@ -1,33 +0,0 @@ -package org.cbioportal.web.parameter; - -import jakarta.validation.constraints.AssertTrue; -import jakarta.validation.constraints.Size; -import java.util.List; - -public class MutationSpectrumFilter { - - @Size(min = 1, max = PagingConstants.MAX_PAGE_SIZE) - private List sampleIds; - private String sampleListId; - - @AssertTrue - private boolean isEitherSampleListIdOrSampleIdsPresent() { - return sampleListId != null ^ sampleIds != null; - } - - public List getSampleIds() { - return sampleIds; - } - - public void setSampleIds(List sampleIds) { - this.sampleIds = sampleIds; - } - - public String getSampleListId() { - return sampleListId; - } - - public void setSampleListId(String sampleListId) { - this.sampleListId = sampleListId; - } -} diff --git a/src/main/java/org/cbioportal/web/parameter/OccurrencePosition.java b/src/main/java/org/cbioportal/web/parameter/OccurrencePosition.java deleted file mode 100644 index b9a5dbc9aad..00000000000 --- a/src/main/java/org/cbioportal/web/parameter/OccurrencePosition.java +++ /dev/null @@ -1,6 +0,0 @@ -package org.cbioportal.web.parameter; - -public enum OccurrencePosition { - FIRST, - LAST -} diff --git a/src/main/java/org/cbioportal/web/parameter/PageSettings.java b/src/main/java/org/cbioportal/web/parameter/PageSettings.java deleted file mode 100644 index 0d9c32dfe00..00000000000 --- a/src/main/java/org/cbioportal/web/parameter/PageSettings.java +++ /dev/null @@ -1,46 +0,0 @@ -package org.cbioportal.web.parameter; - -import java.io.IOException; - -import org.cbioportal.utils.removeme.Session; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.fasterxml.jackson.annotation.JsonIgnore; -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.databind.ObjectMapper; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class PageSettings extends Session { - - private final Logger LOG = LoggerFactory.getLogger(PageSettings.class); - private PageSettingsData data; - - @Override - public void setData(Object data) { - ObjectMapper mapper = new ObjectMapper(); - try { - this.data = mapper.readValue(mapper.writeValueAsString(data), PageSettingsData.class); - } catch (IOException e) { - LOG.error("Error occurred", e); - } - } - - @Override - public PageSettingsData getData() { - return data; - } - - @JsonIgnore - @Override - public String getSource() { - return super.getSource(); - } - - @JsonIgnore - @Override - public SessionType getType() { - return super.getType(); - } - -} diff --git a/src/main/java/org/cbioportal/web/parameter/PageSettingsData.java b/src/main/java/org/cbioportal/web/parameter/PageSettingsData.java deleted file mode 100644 index 2a22e333bf8..00000000000 --- a/src/main/java/org/cbioportal/web/parameter/PageSettingsData.java +++ /dev/null @@ -1,71 +0,0 @@ -package org.cbioportal.web.parameter; - -import java.io.Serializable; -import java.util.Set; - -import jakarta.validation.constraints.NotNull; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonInclude; -import com.fasterxml.jackson.annotation.JsonInclude.Include; -import com.fasterxml.jackson.annotation.JsonSubTypes; -import com.fasterxml.jackson.annotation.JsonTypeInfo; - -@JsonIgnoreProperties(ignoreUnknown = true) -@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.EXISTING_PROPERTY, property = "page", visible = true) -@JsonSubTypes({ - @JsonSubTypes.Type(value = ResultsPageSettings.class, name = "results_view"), - @JsonSubTypes.Type(value = StudyPageSettings.class, name = "study_view") -}) -@JsonInclude(Include.NON_NULL) -public abstract class PageSettingsData implements Serializable { - - @NotNull - private SessionPage page; - private String owner = "anonymous"; - @NotNull - private Set origin; - private Long created = System.currentTimeMillis(); - private Long lastUpdated = System.currentTimeMillis(); - - public SessionPage getPage() { - return page; - } - - public void setPage(SessionPage page) { - this.page = page; - } - - public String getOwner() { - return owner; - } - - public void setOwner(String owner) { - this.owner = owner; - } - - public void setOrigin(Set origin) { - this.origin = origin; - } - - public Long getCreated() { - return created; - } - - public void setCreated(Long created) { - this.created = created; - } - - public Long getLastUpdated() { - return lastUpdated; - } - - public void setLastUpdated(Long lastUpdated) { - this.lastUpdated = lastUpdated; - } - - public Set getOrigin() { - return this.origin; - } - -} diff --git a/src/main/java/org/cbioportal/web/parameter/PageSettingsIdentifier.java b/src/main/java/org/cbioportal/web/parameter/PageSettingsIdentifier.java deleted file mode 100644 index 6dbd479e2ad..00000000000 --- a/src/main/java/org/cbioportal/web/parameter/PageSettingsIdentifier.java +++ /dev/null @@ -1,33 +0,0 @@ -package org.cbioportal.web.parameter; - -import java.io.Serializable; -import java.util.Set; - -import jakarta.validation.constraints.NotNull; -import jakarta.validation.constraints.Size; - -public class PageSettingsIdentifier implements Serializable { - - @NotNull - private SessionPage page; - @Size(min = 1, max = PagingConstants.MAX_PAGE_SIZE) - // type of it should be similar to PageSettingsData -> origin - Set origin; - - public SessionPage getPage() { - return page; - } - - public void setPage(SessionPage page) { - this.page = page; - } - - public Set getOrigin() { - return origin; - } - - public void setOrigin(Set origin) { - this.origin = origin; - } - -} diff --git a/src/main/java/org/cbioportal/web/parameter/PagingConstants.java b/src/main/java/org/cbioportal/web/parameter/PagingConstants.java deleted file mode 100644 index 0c26098758c..00000000000 --- a/src/main/java/org/cbioportal/web/parameter/PagingConstants.java +++ /dev/null @@ -1,14 +0,0 @@ -package org.cbioportal.web.parameter; - -public class PagingConstants { - - public static final String DEFAULT_PAGE_SIZE = "10000000"; - public static final int MAX_PAGE_SIZE = 10000000; - public static final int MIN_PAGE_SIZE = 1; - - public static final String DEFAULT_NO_PAGING_PAGE_SIZE = "0"; - public static final int NO_PAGING_PAGE_SIZE = 0; - - public static final String DEFAULT_PAGE_NUMBER = "0"; - public static final int MIN_PAGE_NUMBER = 0; -} diff --git a/src/main/java/org/cbioportal/web/parameter/PatientFilter.java b/src/main/java/org/cbioportal/web/parameter/PatientFilter.java deleted file mode 100644 index 7f69fb048de..00000000000 --- a/src/main/java/org/cbioportal/web/parameter/PatientFilter.java +++ /dev/null @@ -1,35 +0,0 @@ -package org.cbioportal.web.parameter; - -import java.io.Serializable; -import java.util.List; -import jakarta.validation.constraints.AssertTrue; -import jakarta.validation.constraints.Size; - -public class PatientFilter implements Serializable { - - @Size(min = 1, max = PagingConstants.MAX_PAGE_SIZE) - private List patientIdentifiers; - @Size(min = 1, max = PagingConstants.MAX_PAGE_SIZE) - private List uniquePatientKeys; - - @AssertTrue - private boolean isEitherPatientIdentifiersOrUniquePatientKeysPresent() { - return patientIdentifiers != null ^ uniquePatientKeys != null; - } - - public List getPatientIdentifiers() { - return patientIdentifiers; - } - - public void setPatientIdentifiers(List patientIdentifiers) { - this.patientIdentifiers = patientIdentifiers; - } - - public List getUniquePatientKeys() { - return uniquePatientKeys; - } - - public void setUniquePatientKeys(List uniquePatientKeys) { - this.uniquePatientKeys = uniquePatientKeys; - } -} diff --git a/src/main/java/org/cbioportal/web/parameter/PatientIdentifier.java b/src/main/java/org/cbioportal/web/parameter/PatientIdentifier.java deleted file mode 100644 index b7a9117a031..00000000000 --- a/src/main/java/org/cbioportal/web/parameter/PatientIdentifier.java +++ /dev/null @@ -1,25 +0,0 @@ -package org.cbioportal.web.parameter; - -import java.io.Serializable; - -public class PatientIdentifier implements Serializable { - - private String patientId; - private String studyId; - - public String getPatientId() { - return patientId; - } - - public void setPatientId(String patientId) { - this.patientId = patientId; - } - - public String getStudyId() { - return studyId; - } - - public void setStudyId(String studyId) { - this.studyId = studyId; - } -} diff --git a/src/main/java/org/cbioportal/web/parameter/Projection.java b/src/main/java/org/cbioportal/web/parameter/Projection.java deleted file mode 100644 index d17103c18ba..00000000000 --- a/src/main/java/org/cbioportal/web/parameter/Projection.java +++ /dev/null @@ -1,9 +0,0 @@ -package org.cbioportal.web.parameter; - -public enum Projection { - - ID, - SUMMARY, - DETAILED, - META -} diff --git a/src/main/java/org/cbioportal/web/parameter/ResultsPageSettings.java b/src/main/java/org/cbioportal/web/parameter/ResultsPageSettings.java deleted file mode 100644 index b549ed25c51..00000000000 --- a/src/main/java/org/cbioportal/web/parameter/ResultsPageSettings.java +++ /dev/null @@ -1,29 +0,0 @@ -package org.cbioportal.web.parameter; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonInclude; -import com.fasterxml.jackson.annotation.JsonInclude.Include; - -import java.io.Serializable; -import java.util.ArrayList; -import java.util.List; - -@JsonIgnoreProperties(ignoreUnknown = true) -@JsonInclude(Include.ALWAYS) -public class ResultsPageSettings extends PageSettingsData implements Serializable { - - /** - * Configuration of clinical tracks - * Use lowercase instead of camelCase to be compatible with url query param - */ - private List clinicallist = new ArrayList<>(); - - public List getClinicallist() { - return clinicallist; - } - - public void setClinicallist(List clinicallist) { - this.clinicallist = clinicallist; - } -} - diff --git a/src/main/java/org/cbioportal/web/parameter/SampleFilter.java b/src/main/java/org/cbioportal/web/parameter/SampleFilter.java deleted file mode 100644 index 701dc6181ac..00000000000 --- a/src/main/java/org/cbioportal/web/parameter/SampleFilter.java +++ /dev/null @@ -1,47 +0,0 @@ -package org.cbioportal.web.parameter; - -import jakarta.validation.constraints.AssertTrue; -import jakarta.validation.constraints.Size; -import org.cbioportal.web.SampleController; - -import java.util.List; -import java.io.Serializable; - -public class SampleFilter implements Serializable { - - @Size(min = 1, max = SampleController.SAMPLE_MAX_PAGE_SIZE) - private List sampleIdentifiers; - @Size(min = 1, max = PagingConstants.MAX_PAGE_SIZE) - private List sampleListIds; - @Size(min = 1, max = SampleController.SAMPLE_MAX_PAGE_SIZE) - private List uniqueSampleKeys; - - @AssertTrue - private boolean isOnlyOneTypeOfFilterPresent() { - return sampleIdentifiers != null ^ sampleListIds != null ^ uniqueSampleKeys != null; - } - - public List getSampleIdentifiers() { - return sampleIdentifiers; - } - - public void setSampleIdentifiers(List sampleIdentifiers) { - this.sampleIdentifiers = sampleIdentifiers; - } - - public List getSampleListIds() { - return sampleListIds; - } - - public void setSampleListIds(List sampleListIds) { - this.sampleListIds = sampleListIds; - } - - public List getUniqueSampleKeys() { - return uniqueSampleKeys; - } - - public void setUniqueSampleKeys(List uniqueSampleKeys) { - this.uniqueSampleKeys = uniqueSampleKeys; - } -} diff --git a/src/main/java/org/cbioportal/web/parameter/SampleIdentifier.java b/src/main/java/org/cbioportal/web/parameter/SampleIdentifier.java deleted file mode 100644 index 95b78e36763..00000000000 --- a/src/main/java/org/cbioportal/web/parameter/SampleIdentifier.java +++ /dev/null @@ -1,46 +0,0 @@ -package org.cbioportal.web.parameter; - -import java.io.Serializable; -import java.util.Objects; - -public class SampleIdentifier implements Serializable { - - private String sampleId; - private String studyId; - - public String getSampleId() { - return sampleId; - } - - public void setSampleId(String sampleId) { - this.sampleId = sampleId; - } - - public String getStudyId() { - return studyId; - } - - public void setStudyId(String studyId) { - this.studyId = studyId; - } - - @Override - public String toString() { - return getSampleId() + getStudyId(); - } - - @Override - public boolean equals(Object o) { - if (o == this) return true; - if (!(o instanceof SampleIdentifier)) { - return false; - } - SampleIdentifier user = (SampleIdentifier) o; - return Objects.equals(sampleId, user.sampleId) && Objects.equals(studyId, user.studyId); - } - - @Override - public int hashCode() { - return Objects.hash(sampleId, studyId); - } -} diff --git a/src/main/java/org/cbioportal/web/parameter/SampleMolecularIdentifier.java b/src/main/java/org/cbioportal/web/parameter/SampleMolecularIdentifier.java deleted file mode 100644 index 12103116941..00000000000 --- a/src/main/java/org/cbioportal/web/parameter/SampleMolecularIdentifier.java +++ /dev/null @@ -1,25 +0,0 @@ -package org.cbioportal.web.parameter; - -import java.io.Serializable; - -public class SampleMolecularIdentifier implements Serializable { - - private String sampleId; - private String molecularProfileId; - - public String getSampleId() { - return sampleId; - } - - public void setSampleId(String sampleId) { - this.sampleId = sampleId; - } - - public String getMolecularProfileId() { - return molecularProfileId; - } - - public void setMolecularProfileId(String molecularProfileId) { - this.molecularProfileId = molecularProfileId; - } -} diff --git a/src/main/java/org/cbioportal/web/parameter/SessionPage.java b/src/main/java/org/cbioportal/web/parameter/SessionPage.java deleted file mode 100644 index bdffd95307f..00000000000 --- a/src/main/java/org/cbioportal/web/parameter/SessionPage.java +++ /dev/null @@ -1,6 +0,0 @@ -package org.cbioportal.web.parameter; - -public enum SessionPage { - results_view, - study_view; -} diff --git a/src/main/java/org/cbioportal/web/parameter/StructuralVariantFilter.java b/src/main/java/org/cbioportal/web/parameter/StructuralVariantFilter.java deleted file mode 100644 index 7d3c831196c..00000000000 --- a/src/main/java/org/cbioportal/web/parameter/StructuralVariantFilter.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (c) 2018 The Hyve B.V. - * This code is licensed under the GNU Affero General Public License (AGPL), - * version 3, or (at your option) any later version. - */ - -/* - * This file is part of cBioPortal. - * - * cBioPortal is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -package org.cbioportal.web.parameter; - -import jakarta.validation.Valid; -import jakarta.validation.constraints.AssertTrue; -import jakarta.validation.constraints.Size; -import org.apache.commons.collections4.CollectionUtils; -import org.cbioportal.model.StructuralVariantQuery; - -import java.io.Serializable; -import java.util.List; - -public class StructuralVariantFilter implements Serializable { - - @Size(max = PagingConstants.MAX_PAGE_SIZE) - private List sampleMolecularIdentifiers; - @Size(max = PagingConstants.MAX_PAGE_SIZE) - private List molecularProfileIds; - @Size(max = PagingConstants.MAX_PAGE_SIZE) - private List entrezGeneIds; - @Valid - @Size(max = PagingConstants.MAX_PAGE_SIZE) - private List structuralVariantQueries; - - @AssertTrue - private boolean isEitherMolecularProfileIdsOrSampleMolecularIdentifiersPresent() { - return !CollectionUtils.isEmpty(molecularProfileIds) ^ !CollectionUtils.isEmpty(sampleMolecularIdentifiers); - } - - public List getMolecularProfileIds() { - return molecularProfileIds; - } - - public void setMolecularProfileIds(List molecularProfileIds) { - this.molecularProfileIds = molecularProfileIds; - } - - public List getEntrezGeneIds(){ - return entrezGeneIds; - } - - public void setEntrezGeneIds(List entrezGeneIds) { - this.entrezGeneIds = entrezGeneIds; - } - - public List getSampleMolecularIdentifiers(){ - return sampleMolecularIdentifiers; - } - - public void setSampleMolecularIdentifiers(List sampleMolecularIdentifiers) { - this.sampleMolecularIdentifiers = sampleMolecularIdentifiers; - } - - public List getStructuralVariantQueries() { - return structuralVariantQueries; - } - - public void setStructuralVariantQueries(List structuralVariantQueries) { - this.structuralVariantQueries = structuralVariantQueries; - } -} diff --git a/src/main/java/org/cbioportal/web/parameter/StudyPageSettings.java b/src/main/java/org/cbioportal/web/parameter/StudyPageSettings.java deleted file mode 100644 index 5dcbc8b3887..00000000000 --- a/src/main/java/org/cbioportal/web/parameter/StudyPageSettings.java +++ /dev/null @@ -1,38 +0,0 @@ -package org.cbioportal.web.parameter; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonInclude; -import com.fasterxml.jackson.annotation.JsonInclude.Include; - -import java.io.Serializable; -import java.util.Map; - -/** - * @author kalletlak - * - */ - -@JsonIgnoreProperties(ignoreUnknown = true) -@JsonInclude(Include.NON_NULL) -public class StudyPageSettings extends PageSettingsData implements Serializable { - - private Object chartSettings; - private Map groupColors; - - public Object getChartSettings() { - return chartSettings; - } - - public void setChartSettings(Object chartSettings) { - this.chartSettings = chartSettings; - } - - public Map getGroupColors() { - return groupColors; - } - - public void setGroupColors(Map groupColors) { - this.groupColors = groupColors; - } - -} diff --git a/src/main/java/org/cbioportal/web/parameter/StudyViewFilter.java b/src/main/java/org/cbioportal/web/parameter/StudyViewFilter.java deleted file mode 100644 index 738d3632a70..00000000000 --- a/src/main/java/org/cbioportal/web/parameter/StudyViewFilter.java +++ /dev/null @@ -1,233 +0,0 @@ -package org.cbioportal.web.parameter; - -import java.io.Serializable; -import java.util.List; -import java.util.Objects; - -import com.fasterxml.jackson.annotation.JsonInclude; -import com.fasterxml.jackson.annotation.JsonInclude.Include; -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import jakarta.validation.Valid; -import jakarta.validation.constraints.AssertTrue; -import jakarta.validation.constraints.Size; -import org.cbioportal.model.AlterationFilter; -import org.cbioportal.model.GeneFilter; -import org.cbioportal.model.StudyViewStructuralVariantFilter; -import org.cbioportal.web.parameter.filter.*; - -@JsonIgnoreProperties(ignoreUnknown = true) -@JsonInclude(Include.NON_NULL) -public class StudyViewFilter implements Serializable { - - @Size(min = 1) - private List sampleIdentifiers; - @Size(min = 1) - private List studyIds; - private List clinicalDataFilters; - private List geneFilters; - @Valid - private List structuralVariantFilters; - private AndedSampleTreatmentFilters sampleTreatmentFilters; - private AndedSampleTreatmentFilters sampleTreatmentGroupFilters; - private AndedSampleTreatmentFilters sampleTreatmentTargetFilters; - private AndedPatientTreatmentFilters patientTreatmentFilters; - private AndedPatientTreatmentFilters patientTreatmentGroupFilters; - private AndedPatientTreatmentFilters patientTreatmentTargetFilters; - private List> genomicProfiles; - private List genomicDataFilters; - private List genericAssayDataFilters; - private List> caseLists; - private List customDataFilters; - private AlterationFilter alterationFilter; - private List clinicalEventFilters; - private List mutationDataFilters; - - @AssertTrue - private boolean isEitherSampleIdentifiersOrStudyIdsPresent() { - return sampleIdentifiers != null ^ studyIds != null; - } - - @AssertTrue - private boolean isEitherValueOrRangePresentInClinicalDataIntervalFilters() { - return validateDataFilters(clinicalDataFilters); - } - - @AssertTrue - private boolean isEitherValueOrRangePresentInGenomicDataIntervalFilters() { - return validateDataFilters(genomicDataFilters); - } - - @AssertTrue - private boolean isEitherValueOrRangePresentInGenericAssayDataIntervalFilters() { - return validateDataFilters(genericAssayDataFilters); - } - - @AssertTrue - private boolean isEitherValueOrRangePresentInCustomDataFilters() { - return validateDataFilters(customDataFilters); - } - - private boolean validateDataFilters(List dataFilters) { - long invalidCount = 0; - - if (dataFilters != null) { - invalidCount = dataFilters.stream() - .flatMap(f -> f.getValues().stream()) - .filter(Objects::nonNull) - .filter(v -> v.getValue() != null == (v.getStart() != null || v.getEnd() != null)) - .count(); - } - - return invalidCount == 0; - } - - public List getSampleIdentifiers() { - return sampleIdentifiers; - } - - public void setSampleIdentifiers(List sampleIdentifiers) { - this.sampleIdentifiers = sampleIdentifiers; - } - - public List getStudyIds() { - return studyIds; - } - - public void setStudyIds(List studyIds) { - this.studyIds = studyIds; - } - - public List getClinicalDataFilters() { - return clinicalDataFilters; - } - - public void setClinicalDataFilters(List clinicalDataFilters) { - this.clinicalDataFilters = clinicalDataFilters; - } - - public List getGeneFilters() { - return geneFilters; - } - - public void setGeneFilters(List geneFilters) { - this.geneFilters = geneFilters; - } - - public List getStructuralVariantFilters() { - return structuralVariantFilters; - } - - public void setStructuralVariantFilters(List structuralVariantFilters) { - this.structuralVariantFilters = structuralVariantFilters; - } - - public List> getGenomicProfiles() { - return genomicProfiles; - } - - public void setGenomicProfiles(List> genomicProfiles) { - this.genomicProfiles = genomicProfiles; - } - - public List getGenomicDataFilters() { - return genomicDataFilters; - } - - public void setGenomicDataFilters(List genomicDataFilters) { - this.genomicDataFilters = genomicDataFilters; - } - - public AndedSampleTreatmentFilters getSampleTreatmentFilters() { - return sampleTreatmentFilters; - } - - public void setSampleTreatmentFilters(AndedSampleTreatmentFilters sampleTreatmentFilters) { - this.sampleTreatmentFilters = sampleTreatmentFilters; - } - - public AndedPatientTreatmentFilters getPatientTreatmentFilters() { - return patientTreatmentFilters; - } - - public void setPatientTreatmentFilters(AndedPatientTreatmentFilters patientTreatmentFilters) { - this.patientTreatmentFilters = patientTreatmentFilters; - } - - public List> getCaseLists() { - return caseLists; - } - - public void setCaseLists(List> caseLists) { - this.caseLists = caseLists; - } - - public List getGenericAssayDataFilters() { - return genericAssayDataFilters; - } - - public void setGenericAssayDataFilters(List genericAssayDataFilters) { - this.genericAssayDataFilters = genericAssayDataFilters; - } - - public List getCustomDataFilters() { - return customDataFilters; - } - - public void setCustomDataFilters(List customDataFilters) { - this.customDataFilters = customDataFilters; - } - - public AlterationFilter getAlterationFilter() { - return alterationFilter; - } - - public void setAlterationFilter(AlterationFilter alterationFilter) { - this.alterationFilter = alterationFilter; - } - - public AndedSampleTreatmentFilters getSampleTreatmentGroupFilters() { - return sampleTreatmentGroupFilters; - } - - public void setSampleTreatmentGroupFilters(AndedSampleTreatmentFilters sampleTreatmentGroupFilters) { - this.sampleTreatmentGroupFilters = sampleTreatmentGroupFilters; - } - - public AndedPatientTreatmentFilters getPatientTreatmentGroupFilters() { - return patientTreatmentGroupFilters; - } - - public void setPatientTreatmentGroupFilters(AndedPatientTreatmentFilters patientTreatmentGroupFilters) { - this.patientTreatmentGroupFilters = patientTreatmentGroupFilters; - } - - public AndedSampleTreatmentFilters getSampleTreatmentTargetFilters() { - return sampleTreatmentTargetFilters; - } - - public void setSampleTreatmentTargetFilters(AndedSampleTreatmentFilters sampleTreatmentTargetFilters) { - this.sampleTreatmentTargetFilters = sampleTreatmentTargetFilters; - } - - public AndedPatientTreatmentFilters getPatientTreatmentTargetFilters() { - return patientTreatmentTargetFilters; - } - - public void setPatientTreatmentTargetFilters(AndedPatientTreatmentFilters patientTreatmentTagetFilters) { - this.patientTreatmentTargetFilters = patientTreatmentTagetFilters; - } - - public List getClinicalEventFilters() { - return clinicalEventFilters; - } - - public void setClinicalEventFilters(List clinicalEventFilters) { - this.clinicalEventFilters = clinicalEventFilters; - } - - public List getMutationDataFilters() { return mutationDataFilters; } - - public void setMutationDataFilters(List mutationDataFilters) { - this.mutationDataFilters = mutationDataFilters; - } -} diff --git a/src/main/java/org/cbioportal/web/parameter/SurvivalRequest.java b/src/main/java/org/cbioportal/web/parameter/SurvivalRequest.java deleted file mode 100644 index 7f770d9cd42..00000000000 --- a/src/main/java/org/cbioportal/web/parameter/SurvivalRequest.java +++ /dev/null @@ -1,65 +0,0 @@ -package org.cbioportal.web.parameter; - -import jakarta.validation.Valid; -import jakarta.validation.constraints.NotNull; -import jakarta.validation.constraints.Size; -import java.io.Serializable; -import java.util.List; - -public class SurvivalRequest implements Serializable { - - @Size(min = 1, max = PagingConstants.MAX_PAGE_SIZE) - private List patientIdentifiers; - - @NotNull - private String attributeIdPrefix; - - @Valid - private ClinicalEventRequestIdentifier startEventRequestIdentifier; - - @Valid - private ClinicalEventRequestIdentifier endEventRequestIdentifier; - - @Valid - private ClinicalEventRequestIdentifier censoredEventRequestIdentifier; - - public List getPatientIdentifiers() { - return patientIdentifiers; - } - - public void setPatientIdentifiers(List patientIdentifiers) { - this.patientIdentifiers = patientIdentifiers; - } - - public String getAttributeIdPrefix() { - return attributeIdPrefix; - } - - public void setAttributeIdPrefix(String attributeIdPrefix) { - this.attributeIdPrefix = attributeIdPrefix; - } - - public ClinicalEventRequestIdentifier getStartEventRequestIdentifier() { - return startEventRequestIdentifier; - } - - public void setStartEventRequestIdentifier(ClinicalEventRequestIdentifier startEventRequestIdentifier) { - this.startEventRequestIdentifier = startEventRequestIdentifier; - } - - public ClinicalEventRequestIdentifier getEndEventRequestIdentifier() { - return endEventRequestIdentifier; - } - - public void setEndEventRequestIdentifier(ClinicalEventRequestIdentifier endEventRequestIdentifier) { - this.endEventRequestIdentifier = endEventRequestIdentifier; - } - - public ClinicalEventRequestIdentifier getCensoredEventRequestIdentifier() { - return censoredEventRequestIdentifier; - } - - public void setCensoredEventRequestIdentifier(ClinicalEventRequestIdentifier censoredEventRequestIdentifier) { - this.censoredEventRequestIdentifier = censoredEventRequestIdentifier; - } -} diff --git a/src/main/java/org/cbioportal/web/parameter/VariantCountIdentifier.java b/src/main/java/org/cbioportal/web/parameter/VariantCountIdentifier.java deleted file mode 100644 index 1b6ace73404..00000000000 --- a/src/main/java/org/cbioportal/web/parameter/VariantCountIdentifier.java +++ /dev/null @@ -1,23 +0,0 @@ -package org.cbioportal.web.parameter; - -public class VariantCountIdentifier { - - private Integer entrezGeneId; - private String keyword; - - public Integer getEntrezGeneId() { - return entrezGeneId; - } - - public void setEntrezGeneId(Integer entrezGeneId) { - this.entrezGeneId = entrezGeneId; - } - - public String getKeyword() { - return keyword; - } - - public void setKeyword(String keyword) { - this.keyword = keyword; - } -} diff --git a/src/main/java/org/cbioportal/web/parameter/VirtualStudy.java b/src/main/java/org/cbioportal/web/parameter/VirtualStudy.java deleted file mode 100644 index d5613860982..00000000000 --- a/src/main/java/org/cbioportal/web/parameter/VirtualStudy.java +++ /dev/null @@ -1,46 +0,0 @@ -package org.cbioportal.web.parameter; - -import java.io.IOException; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.fasterxml.jackson.annotation.JsonIgnore; -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.databind.ObjectMapper; -import org.cbioportal.utils.removeme.Session; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class VirtualStudy extends Session { - - private final Logger LOG = LoggerFactory.getLogger(VirtualStudy.class); - private VirtualStudyData data; - - @Override - public void setData(Object data) { - ObjectMapper mapper = new ObjectMapper(); - try { - this.data = mapper.readValue(mapper.writeValueAsString(data), VirtualStudyData.class); - } catch (IOException e) { - LOG.error("Error occurred", e); - } - } - - @Override - public VirtualStudyData getData() { - return data; - } - - @JsonIgnore - @Override - public String getSource() { - return super.getSource(); - } - - @JsonIgnore - @Override - public SessionType getType() { - return super.getType(); - } - -} diff --git a/src/main/java/org/cbioportal/web/parameter/VirtualStudyData.java b/src/main/java/org/cbioportal/web/parameter/VirtualStudyData.java deleted file mode 100644 index f3f60dfb360..00000000000 --- a/src/main/java/org/cbioportal/web/parameter/VirtualStudyData.java +++ /dev/null @@ -1,135 +0,0 @@ -package org.cbioportal.web.parameter; - -import java.io.Serializable; -import java.util.HashSet; -import java.util.Set; -import java.util.stream.Collectors; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class VirtualStudyData implements Serializable { - - private String name; - private String description; - private Set studies; - private StudyViewFilter studyViewFilter; - private Float version = 1.0f; - private String owner = "anonymous"; - private Set origin = new HashSet<>(); - private Long created = System.currentTimeMillis(); - private Long lastUpdated = System.currentTimeMillis(); - private Set users = new HashSet<>(); - - private String typeOfCancerId; - private String pmid; - - private Boolean dynamic; - - public String getOwner() { - return owner; - } - - public void setOwner(String owner) { - this.owner = owner; - } - - public void setOrigin(Set origin) { - this.origin = origin; - } - - public Long getCreated() { - return created; - } - - public void setCreated(Long created) { - this.created = created; - } - - public Long getLastUpdated() { - return lastUpdated; - } - - public void setLastUpdated(Long lastUpdated) { - this.lastUpdated = lastUpdated; - } - - public Set getUsers() { - return users; - } - - public void setUsers(Set users) { - this.users = users; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String getDescription() { - return description; - } - - public void setDescription(String description) { - this.description = description; - } - - public Set getStudies() { - return studies; - } - - public void setStudies(Set studies) { - this.studies = studies; - } - - public Set getOrigin() { - if (this.origin == null || this.origin.size() == 0) { - return studies.stream().map(map -> map.getId()).collect(Collectors.toSet()); - } - return this.origin; - } - - public Float getVersion() { - return version; - } - - public void setVersion(Float version) { - this.version = version; - } - - public StudyViewFilter getStudyViewFilter() { - return studyViewFilter; - } - - public void setStudyViewFilter(StudyViewFilter studyViewFilter) { - this.studyViewFilter = studyViewFilter; - } - - public String getTypeOfCancerId() { - return typeOfCancerId; - } - - public void setTypeOfCancerId(String typeOfCancerId) { - this.typeOfCancerId = typeOfCancerId; - } - - public String getPmid() { - return pmid; - } - - public void setPmid(String pmid) { - this.pmid = pmid; - } - - public Boolean getDynamic() { - return dynamic; - } - - public void setDynamic(Boolean dynamic) { - this.dynamic = dynamic; - } -} diff --git a/src/main/java/org/cbioportal/web/parameter/VirtualStudySamples.java b/src/main/java/org/cbioportal/web/parameter/VirtualStudySamples.java deleted file mode 100644 index 5cfb36afa3b..00000000000 --- a/src/main/java/org/cbioportal/web/parameter/VirtualStudySamples.java +++ /dev/null @@ -1,26 +0,0 @@ -package org.cbioportal.web.parameter; - -import java.util.Set; - -public class VirtualStudySamples { - - private String id; - private Set samples; - - public String getId() { - return id; - } - - public void setId(String id) { - this.id = id; - } - - public Set getSamples() { - return samples; - } - - public void setSamples(Set samples) { - this.samples = samples; - } - -} diff --git a/src/main/java/org/cbioportal/web/parameter/filter/AndedPatientTreatmentFilters.java b/src/main/java/org/cbioportal/web/parameter/filter/AndedPatientTreatmentFilters.java deleted file mode 100644 index eaf81744f5c..00000000000 --- a/src/main/java/org/cbioportal/web/parameter/filter/AndedPatientTreatmentFilters.java +++ /dev/null @@ -1,31 +0,0 @@ -package org.cbioportal.web.parameter.filter; - -import org.cbioportal.model.ClinicalEventSample; -import org.cbioportal.model.PatientTreatmentRow; -import org.cbioportal.web.parameter.SampleIdentifier; - -import java.io.Serializable; -import java.util.List; -import java.util.Map; -import java.util.Set; - -public class AndedPatientTreatmentFilters implements Serializable { - private List filters; - - public boolean filter(SampleIdentifier sampleId, Map> treatments) { - if (filters == null || filters.isEmpty()) { - return true; - } - - return filters.stream() - .allMatch(f -> f.filter(sampleId, treatments)); - } - - public List getFilters() { - return filters; - } - - public void setFilters(List filters) { - this.filters = filters; - } -} diff --git a/src/main/java/org/cbioportal/web/parameter/filter/AndedSampleTreatmentFilters.java b/src/main/java/org/cbioportal/web/parameter/filter/AndedSampleTreatmentFilters.java deleted file mode 100644 index 93960cc7541..00000000000 --- a/src/main/java/org/cbioportal/web/parameter/filter/AndedSampleTreatmentFilters.java +++ /dev/null @@ -1,31 +0,0 @@ -package org.cbioportal.web.parameter.filter; - -import org.cbioportal.model.PatientTreatmentRow; -import org.cbioportal.model.SampleTreatmentRow; -import org.cbioportal.web.parameter.SampleIdentifier; - -import java.io.Serializable; -import java.util.List; -import java.util.Map; -import java.util.Set; - -public class AndedSampleTreatmentFilters implements Serializable { - private List filters; - - public boolean filter(SampleIdentifier sampleId, Map> treatments) { - if (filters == null || filters.isEmpty()) { - return true; - } - - return filters.stream() - .allMatch(f -> f.filter(sampleId, treatments)); - } - - public List getFilters() { - return filters; - } - - public void setFilters(List filters) { - this.filters = filters; - } -} diff --git a/src/main/java/org/cbioportal/web/parameter/filter/OredPatientTreatmentFilters.java b/src/main/java/org/cbioportal/web/parameter/filter/OredPatientTreatmentFilters.java deleted file mode 100644 index 57ae0d3797e..00000000000 --- a/src/main/java/org/cbioportal/web/parameter/filter/OredPatientTreatmentFilters.java +++ /dev/null @@ -1,31 +0,0 @@ -package org.cbioportal.web.parameter.filter; - -import org.cbioportal.model.ClinicalEventSample; -import org.cbioportal.model.PatientTreatmentRow; -import org.cbioportal.web.parameter.SampleIdentifier; - -import java.io.Serializable; -import java.util.List; -import java.util.Map; -import java.util.Set; - -public class OredPatientTreatmentFilters implements Serializable { - private List filters; - - public boolean filter(SampleIdentifier sampleId, Map> treatments) { - if (filters == null || filters.isEmpty()) { - return true; - } - - return filters.stream() - .anyMatch(f -> f.filter(sampleId, treatments)); - } - - public List getFilters() { - return filters; - } - - public void setFilters(List filters) { - this.filters = filters; - } -} diff --git a/src/main/java/org/cbioportal/web/parameter/filter/OredSampleTreatmentFilters.java b/src/main/java/org/cbioportal/web/parameter/filter/OredSampleTreatmentFilters.java deleted file mode 100644 index 388ab0113a4..00000000000 --- a/src/main/java/org/cbioportal/web/parameter/filter/OredSampleTreatmentFilters.java +++ /dev/null @@ -1,30 +0,0 @@ -package org.cbioportal.web.parameter.filter; - -import org.cbioportal.model.SampleTreatmentRow; -import org.cbioportal.web.parameter.SampleIdentifier; - -import java.io.Serializable; -import java.util.List; -import java.util.Map; -import java.util.Set; - -public class OredSampleTreatmentFilters implements Serializable { - private List filters; // ored - - public boolean filter(SampleIdentifier sampleId, Map> treatments) { - if (filters == null || filters.isEmpty()) { - return true; - } - - return filters.stream() - .anyMatch(f -> f.filter(sampleId, treatments)); - } - - public List getFilters() { - return filters; - } - - public void setFilters(List filters) { - this.filters = filters; - } -} diff --git a/src/main/java/org/cbioportal/web/parameter/filter/PatientTreatmentFilter.java b/src/main/java/org/cbioportal/web/parameter/filter/PatientTreatmentFilter.java deleted file mode 100644 index fb4d8095ce9..00000000000 --- a/src/main/java/org/cbioportal/web/parameter/filter/PatientTreatmentFilter.java +++ /dev/null @@ -1,30 +0,0 @@ -package org.cbioportal.web.parameter.filter; - -import java.io.Serializable; -import java.util.Map; -import java.util.Set; - -import org.cbioportal.web.parameter.SampleIdentifier; - -public class PatientTreatmentFilter implements Serializable { - private String treatment; - - /** - * A sampleId should be included if the treatment row that corresponds - * to the treatment and time in this filter contains that sampleId. - * @param sampleId sample.STABLE_ID - * @param treatments key is PatientTreatmentRow::calculateKey - */ - public boolean filter(SampleIdentifier sampleId, Map> treatments) { - Set row = treatments.get(treatment); - return row != null && row.contains(sampleId.toString()); - } - - public String getTreatment() { - return treatment; - } - - public void setTreatment(String treatment) { - this.treatment = treatment; - } -} diff --git a/src/main/java/org/cbioportal/web/parameter/filter/SampleTreatmentFilter.java b/src/main/java/org/cbioportal/web/parameter/filter/SampleTreatmentFilter.java deleted file mode 100644 index f4c2dcf1027..00000000000 --- a/src/main/java/org/cbioportal/web/parameter/filter/SampleTreatmentFilter.java +++ /dev/null @@ -1,42 +0,0 @@ -package org.cbioportal.web.parameter.filter; - -import org.cbioportal.model.TemporalRelation; -import org.cbioportal.model.SampleTreatmentRow; -import org.cbioportal.web.parameter.SampleIdentifier; - -import java.io.Serializable; -import java.util.Map; -import java.util.Set; - -public class SampleTreatmentFilter implements Serializable { - private String treatment; - private TemporalRelation time; - - /** - * A sample should be included if the treatment row that corresponds - * to the treatment and time in this filter contains that sample. - * @param sampleId sample.STABLE_ID - * @param treatments key is SampleTreatmentRow::calculateKey - */ - public boolean filter(SampleIdentifier sampleId, Map> treatments) { - Set row = treatments.get(treatment + time.name()); - return row != null && row.contains(sampleId.toString()); - } - - public String getTreatment() { - return treatment; - } - - public void setTreatment(String treatment) { - this.treatment = treatment; - } - - public TemporalRelation getTime() { - return time; - } - - public void setTime(TemporalRelation time) { - this.time = time; - } - -} diff --git a/src/main/java/org/cbioportal/web/parameter/sort/CancerTypeSortBy.java b/src/main/java/org/cbioportal/web/parameter/sort/CancerTypeSortBy.java deleted file mode 100644 index 31305e393bd..00000000000 --- a/src/main/java/org/cbioportal/web/parameter/sort/CancerTypeSortBy.java +++ /dev/null @@ -1,20 +0,0 @@ -package org.cbioportal.web.parameter.sort; - -public enum CancerTypeSortBy { - - cancerTypeId("typeOfCancerId"), - name("name"), - dedicatedColor("dedicatedColor"), - shortName("shortName"), - parent("parent"); - - private String originalValue; - - CancerTypeSortBy(String originalValue) { - this.originalValue = originalValue; - } - - public String getOriginalValue() { - return originalValue; - } -} diff --git a/src/main/java/org/cbioportal/web/parameter/sort/ClinicalAttributeSortBy.java b/src/main/java/org/cbioportal/web/parameter/sort/ClinicalAttributeSortBy.java deleted file mode 100644 index 5b6ef9c8021..00000000000 --- a/src/main/java/org/cbioportal/web/parameter/sort/ClinicalAttributeSortBy.java +++ /dev/null @@ -1,22 +0,0 @@ -package org.cbioportal.web.parameter.sort; - -public enum ClinicalAttributeSortBy { - - clinicalAttributeId("attrId"), - displayName("displayName"), - description("description"), - datatype("datatype"), - patientAttribute("patientAttribute"), - priority("priority"), - studyId("cancerStudyIdentifier"); - - private String originalValue; - - ClinicalAttributeSortBy(String originalValue) { - this.originalValue = originalValue; - } - - public String getOriginalValue() { - return originalValue; - } -} diff --git a/src/main/java/org/cbioportal/web/parameter/sort/ClinicalDataSortBy.java b/src/main/java/org/cbioportal/web/parameter/sort/ClinicalDataSortBy.java deleted file mode 100644 index 9da6465c5af..00000000000 --- a/src/main/java/org/cbioportal/web/parameter/sort/ClinicalDataSortBy.java +++ /dev/null @@ -1,17 +0,0 @@ -package org.cbioportal.web.parameter.sort; - -public enum ClinicalDataSortBy { - - clinicalAttributeId("attrId"), - value("attrValue"); - - private String originalValue; - - ClinicalDataSortBy(String originalValue) { - this.originalValue = originalValue; - } - - public String getOriginalValue() { - return originalValue; - } -} diff --git a/src/main/java/org/cbioportal/web/parameter/sort/ClinicalEventSortBy.java b/src/main/java/org/cbioportal/web/parameter/sort/ClinicalEventSortBy.java deleted file mode 100644 index 44508aba81f..00000000000 --- a/src/main/java/org/cbioportal/web/parameter/sort/ClinicalEventSortBy.java +++ /dev/null @@ -1,18 +0,0 @@ -package org.cbioportal.web.parameter.sort; - -public enum ClinicalEventSortBy { - - eventType("eventType"), - startNumberOfDaysSinceDiagnosis("startDate"), - endNumberOfDaysSinceDiagnosis("stopDate"); - - private String originalValue; - - ClinicalEventSortBy(String originalValue) { - this.originalValue = originalValue; - } - - public String getOriginalValue() { - return originalValue; - } -} diff --git a/src/main/java/org/cbioportal/web/parameter/sort/CopyNumberSegmentSortBy.java b/src/main/java/org/cbioportal/web/parameter/sort/CopyNumberSegmentSortBy.java deleted file mode 100644 index 2d662dbd005..00000000000 --- a/src/main/java/org/cbioportal/web/parameter/sort/CopyNumberSegmentSortBy.java +++ /dev/null @@ -1,20 +0,0 @@ -package org.cbioportal.web.parameter.sort; - -public enum CopyNumberSegmentSortBy { - - chromosome("chr"), - start("start"), - end("end"), - numberOfProbes("numProbes"), - segmentMean("segmentMean"); - - private String originalValue; - - CopyNumberSegmentSortBy(String originalValue) { - this.originalValue = originalValue; - } - - public String getOriginalValue() { - return originalValue; - } -} diff --git a/src/main/java/org/cbioportal/web/parameter/sort/DiscreteCopyNumberSortBy.java b/src/main/java/org/cbioportal/web/parameter/sort/DiscreteCopyNumberSortBy.java deleted file mode 100644 index 41e4128c4a9..00000000000 --- a/src/main/java/org/cbioportal/web/parameter/sort/DiscreteCopyNumberSortBy.java +++ /dev/null @@ -1,17 +0,0 @@ -package org.cbioportal.web.parameter.sort; - -public enum DiscreteCopyNumberSortBy { - - entrezGeneId("entrezGeneId"), - alteration("alteration"); - - private String originalValue; - - DiscreteCopyNumberSortBy(String originalValue) { - this.originalValue = originalValue; - } - - public String getOriginalValue() { - return originalValue; - } -} diff --git a/src/main/java/org/cbioportal/web/parameter/sort/GenePanelSortBy.java b/src/main/java/org/cbioportal/web/parameter/sort/GenePanelSortBy.java deleted file mode 100644 index 1b2750f9386..00000000000 --- a/src/main/java/org/cbioportal/web/parameter/sort/GenePanelSortBy.java +++ /dev/null @@ -1,17 +0,0 @@ -package org.cbioportal.web.parameter.sort; - -public enum GenePanelSortBy { - - genePanelId("stableId"), - description("description"); - - private String originalValue; - - GenePanelSortBy(String originalValue) { - this.originalValue = originalValue; - } - - public String getOriginalValue() { - return originalValue; - } -} diff --git a/src/main/java/org/cbioportal/web/parameter/sort/GeneSortBy.java b/src/main/java/org/cbioportal/web/parameter/sort/GeneSortBy.java deleted file mode 100644 index 233f92864b5..00000000000 --- a/src/main/java/org/cbioportal/web/parameter/sort/GeneSortBy.java +++ /dev/null @@ -1,20 +0,0 @@ -package org.cbioportal.web.parameter.sort; - -public enum GeneSortBy { - - entrezGeneId("entrezGeneId"), - hugoGeneSymbol("hugoGeneSymbol"), - type("type"), - cytoband("cytoband"), - length("length"); - - private String originalValue; - - GeneSortBy(String originalValue) { - this.originalValue = originalValue; - } - - public String getOriginalValue() { - return originalValue; - } -} diff --git a/src/main/java/org/cbioportal/web/parameter/sort/MolecularProfileSortBy.java b/src/main/java/org/cbioportal/web/parameter/sort/MolecularProfileSortBy.java deleted file mode 100644 index c089ee90fea..00000000000 --- a/src/main/java/org/cbioportal/web/parameter/sort/MolecularProfileSortBy.java +++ /dev/null @@ -1,21 +0,0 @@ -package org.cbioportal.web.parameter.sort; - -public enum MolecularProfileSortBy { - - molecularProfileId("stableId"), - molecularAlterationType("geneticAlterationType"), - datatype("datatype"), - name("name"), - description("description"), - showProfileInAnalysisTab("showProfileInAnalysisTab"); - - private String originalValue; - - MolecularProfileSortBy(String originalValue) { - this.originalValue = originalValue; - } - - public String getOriginalValue() { - return originalValue; - } -} diff --git a/src/main/java/org/cbioportal/web/parameter/sort/MutationSortBy.java b/src/main/java/org/cbioportal/web/parameter/sort/MutationSortBy.java deleted file mode 100644 index ce2caf51cdb..00000000000 --- a/src/main/java/org/cbioportal/web/parameter/sort/MutationSortBy.java +++ /dev/null @@ -1,36 +0,0 @@ -package org.cbioportal.web.parameter.sort; - -public enum MutationSortBy { - - entrezGeneId("entrezGeneId"), - center("center"), - mutationStatus("mutationStatus"), - validationStatus("validationStatus"), - tumorAltCount("tumorAltCount"), - tumorRefCount("tumorRefCount"), - normalAltCount("normalAltCount"), - normalRefCount("normalRefCount"), - aminoAcidChange("aminoAcidChange"), - startPosition("startPosition"), - endPosition("endPosition"), - referenceAllele("referenceAllele"), - variantAllele("tumorSeqAllele"), - proteinChange("proteinChange"), - mutationType("mutationType"), - ncbiBuild("ncbiBuild"), - variantType("variantType"), - refseqMrnaId("refseqMrnaId"), - proteinPosStart("proteinPosStart"), - proteinPosEnd("proteinPosEnd"), - keyword("keyword"); - - private String originalValue; - - MutationSortBy(String originalValue) { - this.originalValue = originalValue; - } - - public String getOriginalValue() { - return originalValue; - } -} diff --git a/src/main/java/org/cbioportal/web/parameter/sort/PatientSortBy.java b/src/main/java/org/cbioportal/web/parameter/sort/PatientSortBy.java deleted file mode 100644 index eca583a6e6e..00000000000 --- a/src/main/java/org/cbioportal/web/parameter/sort/PatientSortBy.java +++ /dev/null @@ -1,16 +0,0 @@ -package org.cbioportal.web.parameter.sort; - -public enum PatientSortBy { - - patientId("stableId"); - - private String originalValue; - - PatientSortBy(String originalValue) { - this.originalValue = originalValue; - } - - public String getOriginalValue() { - return originalValue; - } -} diff --git a/src/main/java/org/cbioportal/web/parameter/sort/ResourceDataSortBy.java b/src/main/java/org/cbioportal/web/parameter/sort/ResourceDataSortBy.java deleted file mode 100644 index aa0d097020a..00000000000 --- a/src/main/java/org/cbioportal/web/parameter/sort/ResourceDataSortBy.java +++ /dev/null @@ -1,17 +0,0 @@ -package org.cbioportal.web.parameter.sort; - -public enum ResourceDataSortBy { - - ResourceId("resourceId"), - url("url"); - - private String originalValue; - - ResourceDataSortBy(String originalValue) { - this.originalValue = originalValue; - } - - public String getOriginalValue() { - return originalValue; - } -} diff --git a/src/main/java/org/cbioportal/web/parameter/sort/ResourceDefinitionSortBy.java b/src/main/java/org/cbioportal/web/parameter/sort/ResourceDefinitionSortBy.java deleted file mode 100644 index 92163a2350b..00000000000 --- a/src/main/java/org/cbioportal/web/parameter/sort/ResourceDefinitionSortBy.java +++ /dev/null @@ -1,22 +0,0 @@ -package org.cbioportal.web.parameter.sort; - -public enum ResourceDefinitionSortBy { - - resourceId("resourceId"), - displayName("displayName"), - description("description"), - resourceType("resourceType"), - priority("priority"), - openByDefault("openByDefault"), - studyId("cancerStudyIdentifier"); - - private String originalValue; - - ResourceDefinitionSortBy(String originalValue) { - this.originalValue = originalValue; - } - - public String getOriginalValue() { - return originalValue; - } -} diff --git a/src/main/java/org/cbioportal/web/parameter/sort/SampleListSortBy.java b/src/main/java/org/cbioportal/web/parameter/sort/SampleListSortBy.java deleted file mode 100644 index 924ca559177..00000000000 --- a/src/main/java/org/cbioportal/web/parameter/sort/SampleListSortBy.java +++ /dev/null @@ -1,20 +0,0 @@ -package org.cbioportal.web.parameter.sort; - -public enum SampleListSortBy { - - sampleListId("stableId"), - category("category"), - studyId("cancerStudyIdentifier"), - name("name"), - description("description"); - - private String originalValue; - - SampleListSortBy(String originalValue) { - this.originalValue = originalValue; - } - - public String getOriginalValue() { - return originalValue; - } -} diff --git a/src/main/java/org/cbioportal/web/parameter/sort/SampleSortBy.java b/src/main/java/org/cbioportal/web/parameter/sort/SampleSortBy.java deleted file mode 100644 index d42dc7b7f53..00000000000 --- a/src/main/java/org/cbioportal/web/parameter/sort/SampleSortBy.java +++ /dev/null @@ -1,17 +0,0 @@ -package org.cbioportal.web.parameter.sort; - -public enum SampleSortBy { - - sampleId("stableId"), - sampleType("sampleType"); - - private String originalValue; - - SampleSortBy(String originalValue) { - this.originalValue = originalValue; - } - - public String getOriginalValue() { - return originalValue; - } -} diff --git a/src/main/java/org/cbioportal/web/parameter/sort/SignificantCopyNumberRegionSortBy.java b/src/main/java/org/cbioportal/web/parameter/sort/SignificantCopyNumberRegionSortBy.java deleted file mode 100644 index 8003d56a9ef..00000000000 --- a/src/main/java/org/cbioportal/web/parameter/sort/SignificantCopyNumberRegionSortBy.java +++ /dev/null @@ -1,22 +0,0 @@ -package org.cbioportal.web.parameter.sort; - -public enum SignificantCopyNumberRegionSortBy { - - chromosome("chromosome"), - cytoband("cytoband"), - widePeakStart("widePeakStart"), - widePeakEnd("widePeakEnd"), - qValue("qValue"), - amp("amp"); - - private String originalValue; - - SignificantCopyNumberRegionSortBy(String originalValue) { - this.originalValue = originalValue; - } - - public String getOriginalValue() { - return originalValue; - } - -} diff --git a/src/main/java/org/cbioportal/web/parameter/sort/SignificantlyMutatedGeneSortBy.java b/src/main/java/org/cbioportal/web/parameter/sort/SignificantlyMutatedGeneSortBy.java deleted file mode 100644 index eb2a9003756..00000000000 --- a/src/main/java/org/cbioportal/web/parameter/sort/SignificantlyMutatedGeneSortBy.java +++ /dev/null @@ -1,21 +0,0 @@ -package org.cbioportal.web.parameter.sort; - -public enum SignificantlyMutatedGeneSortBy { - - entrezGeneId("entrezGeneId"), - hugoGeneSymbol("hugoGeneSymbol"), - rank("rank"), - numberOfMutations("nummutations"), - pValue("pValue"), - qValue("qValue"); - - private String originalValue; - - SignificantlyMutatedGeneSortBy(String originalValue) { - this.originalValue = originalValue; - } - - public String getOriginalValue() { - return originalValue; - } -} diff --git a/src/main/java/org/cbioportal/web/parameter/sort/StudySortBy.java b/src/main/java/org/cbioportal/web/parameter/sort/StudySortBy.java deleted file mode 100644 index d13a09d9535..00000000000 --- a/src/main/java/org/cbioportal/web/parameter/sort/StudySortBy.java +++ /dev/null @@ -1,25 +0,0 @@ -package org.cbioportal.web.parameter.sort; - -public enum StudySortBy { - - studyId("cancerStudyIdentifier"), - cancerTypeId("typeOfCancerId"), - name("name"), - description("description"), - publicStudy("public"), - pmid("pmid"), - citation("citation"), - groups("groups"), - status("status"), - importDate("importDate"); - - private String originalValue; - - StudySortBy(String originalValue) { - this.originalValue = originalValue; - } - - public String getOriginalValue() { - return originalValue; - } -} diff --git a/src/main/java/org/cbioportal/web/studyview/CustomDataController.java b/src/main/java/org/cbioportal/web/studyview/CustomDataController.java deleted file mode 100644 index 9df5f7acf14..00000000000 --- a/src/main/java/org/cbioportal/web/studyview/CustomDataController.java +++ /dev/null @@ -1,111 +0,0 @@ -package org.cbioportal.web.studyview; - - -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.media.ArraySchema; -import io.swagger.v3.oas.annotations.media.Content; -import io.swagger.v3.oas.annotations.media.Schema; -import io.swagger.v3.oas.annotations.responses.ApiResponse; -import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.validation.Valid; -import org.cbioportal.model.ClinicalDataCountItem; -import org.cbioportal.model.Patient; -import org.cbioportal.service.CustomDataService; -import org.cbioportal.service.PatientService; -import org.cbioportal.service.util.CustomDataSession; -import org.cbioportal.web.config.annotation.InternalApi; -import org.cbioportal.web.parameter.ClinicalDataCountFilter; -import org.cbioportal.web.parameter.ClinicalDataFilter; -import org.cbioportal.web.parameter.SampleIdentifier; -import org.cbioportal.web.parameter.StudyViewFilter; -import org.cbioportal.web.util.StudyViewFilterApplier; -import org.cbioportal.web.util.StudyViewFilterUtil; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.RequestAttribute; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestMethod; -import org.springframework.web.bind.annotation.RestController; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.Map; -import java.util.function.Function; -import java.util.stream.Collectors; - -@InternalApi -@RestController() -@RequestMapping("/api") -@Validated -@Tag(name = "Study View", description = " ") -public class CustomDataController { - - @Autowired - private StudyViewFilterApplier studyViewFilterApplier; - @Autowired - private StudyViewFilterUtil studyViewFilterUtil; - @Autowired - private CustomDataService customDataService; - @Autowired - private PatientService patientService; - - @PreAuthorize("hasPermission(#involvedCancerStudies, 'Collection', T(org.cbioportal.utils.security.AccessLevel).READ)") - @RequestMapping(value = "/custom-data-counts/fetch", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(description = "Fetch custom data counts by study view filter") - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(array = @ArraySchema(schema = @Schema(implementation = ClinicalDataCountItem.class)))) - public ResponseEntity> fetchCustomDataCounts( - @Parameter(required = true, description = "Custom data count filter") @Valid @RequestBody(required = false) ClinicalDataCountFilter clinicalDataCountFilter, - @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui - // interface - @RequestAttribute(required = false, value = "involvedCancerStudies") Collection involvedCancerStudies, - @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui - // interface. this attribute is needed for the - // @PreAuthorize tag above. - @Valid @RequestAttribute(required = false, value = "interceptedClinicalDataCountFilter") ClinicalDataCountFilter interceptedClinicalDataCountFilter) { - - List attributes = interceptedClinicalDataCountFilter.getAttributes(); - StudyViewFilter studyViewFilter = interceptedClinicalDataCountFilter.getStudyViewFilter(); - if (attributes.size() == 1) { - studyViewFilterUtil.removeSelfCustomDataFromFilter(attributes.get(0).getAttributeId(), studyViewFilter); - } - List filteredSampleIdentifiers = studyViewFilterApplier.apply(studyViewFilter); - - if (filteredSampleIdentifiers.isEmpty()) { - return new ResponseEntity<>(new ArrayList<>(), HttpStatus.OK); - } - - final List attributeIds = attributes.stream().map(ClinicalDataFilter::getAttributeId).collect(Collectors.toList()); - Map customDataSessionsMap = customDataService.getCustomDataSessions(attributeIds); - - Map filteredSamplesMap = filteredSampleIdentifiers.stream() - .collect(Collectors.toMap(sampleIdentifier -> studyViewFilterUtil.getCaseUniqueKey( - sampleIdentifier.getStudyId(), - sampleIdentifier.getSampleId() - ), Function.identity())); - - List studyIds = new ArrayList<>(); - List sampleIds = new ArrayList<>(); - studyViewFilterUtil.extractStudyAndSampleIds(filteredSampleIdentifiers, studyIds, sampleIds); - - long patientCustomDataSessionsCount = customDataSessionsMap.values().stream() - .filter(customDataSession -> customDataSession.getData().getPatientAttribute()).count(); - List patients = new ArrayList<>(); - if (patientCustomDataSessionsCount > 0) { - patients.addAll(patientService.getPatientsOfSamples(studyIds, sampleIds)); - } - - List result = studyViewFilterUtil.getClinicalDataCountsFromCustomData(customDataSessionsMap.values(), - filteredSamplesMap, patients); - - return new ResponseEntity<>(result, HttpStatus.OK); - } - -} diff --git a/src/main/java/org/cbioportal/web/util/BinningData.java b/src/main/java/org/cbioportal/web/util/BinningData.java deleted file mode 100644 index 82edafd1edd..00000000000 --- a/src/main/java/org/cbioportal/web/util/BinningData.java +++ /dev/null @@ -1,39 +0,0 @@ -package org.cbioportal.web.util; - -import com.google.common.collect.ImmutableList; -import org.cbioportal.model.Binnable; -import org.cbioportal.model.ClinicalData; - -import java.util.Collection; -import java.util.List; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -import static java.util.Collections.unmodifiableList; - -public class BinningData { - public final List samples; - public final List patients; - public final List conflictingPatientAttributes; - private final List allData; - - public BinningData( - List samples, - List patients, - List conflictingPatientAttributes - ) { - this.samples = unmodifiableList(samples); - this.patients = unmodifiableList(patients); - this.conflictingPatientAttributes = unmodifiableList(conflictingPatientAttributes); - this.allData = Stream.of( - this.samples, - this.patients, - this.conflictingPatientAttributes - ).flatMap(Collection::stream).collect(Collectors.toList()); - } - - public List getAllData() { - return allData; - } - -} \ No newline at end of file diff --git a/src/main/java/org/cbioportal/web/util/BinningIds.java b/src/main/java/org/cbioportal/web/util/BinningIds.java deleted file mode 100644 index 6d19d79051b..00000000000 --- a/src/main/java/org/cbioportal/web/util/BinningIds.java +++ /dev/null @@ -1,75 +0,0 @@ -package org.cbioportal.web.util; - -import java.util.ArrayList; -import java.util.List; - -import static java.util.Collections.unmodifiableList; - -/** - * All IDs relevant for binning of clinical (and custom clinical) data - */ -public class BinningIds { - private List studyIds = new ArrayList<>(); - private List sampleIds = new ArrayList<>(); - private List patientIds = new ArrayList<>(); - private List studyIdsOfPatients = new ArrayList<>(); - private List uniqueSampleKeys = new ArrayList<>(); - private List uniquePatientKeys = new ArrayList<>(); - private List sampleAttributeIds = new ArrayList<>(); - private List patientAttributeIds = new ArrayList<>(); - private List conflictingPatientAttributeIds = new ArrayList<>(); - - public BinningIds() {} - - /** - * Create shallow clone - */ - public BinningIds(BinningIds toClone) { - this(); - this.studyIds = new ArrayList<>(toClone.getStudyIds()); - this.sampleIds = new ArrayList<>(toClone.getSampleIds()); - this.patientIds = new ArrayList<>(toClone.getPatientIds()); - this.studyIdsOfPatients = new ArrayList<>(toClone.getStudyIdsOfPatients()); - this.uniqueSampleKeys = new ArrayList<>(toClone.getUniqueSampleKeys()); - this.uniquePatientKeys = new ArrayList<>(toClone.getUniquePatientKeys()); - this.sampleAttributeIds = new ArrayList<>(toClone.getSampleAttributeIds()); - this.patientAttributeIds = new ArrayList<>(toClone.getPatientAttributeIds()); - this.conflictingPatientAttributeIds = new ArrayList<>(toClone.getConflictingPatientAttributeIds()); - } - - public List getStudyIds() { - return studyIds; - } - - public List getSampleIds() { - return sampleIds; - } - - public List getPatientIds() { - return patientIds; - } - - public List getStudyIdsOfPatients() { - return studyIdsOfPatients; - } - - public List getUniqueSampleKeys() { - return uniqueSampleKeys; - } - - public List getUniquePatientKeys() { - return uniquePatientKeys; - } - - public List getSampleAttributeIds() { - return sampleAttributeIds; - } - - public List getPatientAttributeIds() { - return patientAttributeIds; - } - - public List getConflictingPatientAttributeIds() { - return conflictingPatientAttributeIds; - } -} \ No newline at end of file diff --git a/src/main/java/org/cbioportal/web/util/ClinicalDataBinUtil.java b/src/main/java/org/cbioportal/web/util/ClinicalDataBinUtil.java deleted file mode 100644 index bf90b2de08b..00000000000 --- a/src/main/java/org/cbioportal/web/util/ClinicalDataBinUtil.java +++ /dev/null @@ -1,434 +0,0 @@ -package org.cbioportal.web.util; - -import org.cbioportal.model.Binnable; -import org.cbioportal.model.ClinicalAttribute; -import org.cbioportal.model.ClinicalData; -import org.cbioportal.model.ClinicalDataBin; -import org.cbioportal.service.AttributeByStudyService; -import org.cbioportal.service.CustomDataService; -import org.cbioportal.service.util.BinnableCustomDataValue; -import org.cbioportal.service.util.CustomAttributeWithData; -import org.cbioportal.service.util.CustomDataSession; -import org.cbioportal.service.util.CustomDataValue; -import org.cbioportal.web.columnar.util.NewClinicalDataBinUtil; -import org.cbioportal.web.parameter.*; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -import java.util.*; -import java.util.function.Function; -import java.util.stream.Collectors; - -import static java.util.Collections.emptyList; -import static java.util.stream.Collectors.toList; -import static java.util.stream.Collectors.toMap; - -@Component -public class ClinicalDataBinUtil { - - @Autowired - private AttributeByStudyService clinicalAttributeService; - @Autowired - private StudyViewFilterApplier studyViewFilterApplier; - @Autowired - private ClinicalDataFetcher clinicalDataFetcher; - @Autowired - private DataBinner dataBinner; - @Autowired - private StudyViewFilterUtil studyViewFilterUtil; - @Autowired - private CustomDataService customDataService; - @Autowired - private IdPopulator idPopulator; - - public StudyViewFilter removeSelfFromFilter(ClinicalDataBinCountFilter dataBinCountFilter) { - return NewClinicalDataBinUtil.removeSelfFromFilter(dataBinCountFilter); - } - - public List fetchClinicalDataBinCounts( - DataBinMethod dataBinMethod, - ClinicalDataBinCountFilter dataBinCountFilter - ) { - return this.fetchClinicalDataBinCounts( - dataBinMethod, - dataBinCountFilter, - // by default call the method to remove self from filter - true - ); - } - - public List fetchClinicalDataBinCounts( - DataBinMethod dataBinMethod, - ClinicalDataBinCountFilter dataBinCountFilter, - boolean shouldRemoveSelfFromFilter - ) { - StudyViewFilter studyViewFilter = toStudyViewFilter(dataBinCountFilter, shouldRemoveSelfFromFilter); - List unfilteredSamples = filterByStudyAndSample(studyViewFilter); - List attributeIds = toAttributeIds(dataBinCountFilter.getAttributes()); - List clinicalAttributes = fetchClinicalAttributes(attributeIds, unfilteredSamples); - BinningIds binningIds = idPopulator.populateIdLists(unfilteredSamples, clinicalAttributes); - Map attributeByDatatype = toAttributeDatatypeMap(binningIds); - BinningData unfilteredData = (BinningData) (BinningData) fetchBinningData(binningIds); - return createBins( - dataBinMethod, - dataBinCountFilter, - studyViewFilter, - attributeByDatatype, - clinicalAttributes, - binningIds, - unfilteredSamples, - unfilteredData - ); - } - - public List fetchCustomDataBinCounts( - DataBinMethod dataBinMethod, - ClinicalDataBinCountFilter dataBinCountFilter, - boolean shouldRemoveSelfFromFilter - ) { - List attributeIds = toAttributeIds(dataBinCountFilter.getAttributes()); - Map customDataSessions = customDataService.getCustomDataSessions(attributeIds); - Map> customDataByAttributeId = createCustomDataByAttributeId(customDataSessions); - Map customAttributeByDatatype = createCustomAttributeDatatypeMap(customDataSessions); - - StudyViewFilter studyViewFilter = toStudyViewFilter(dataBinCountFilter, shouldRemoveSelfFromFilter); - List unfilteredSamples = filterByStudyAndSample(studyViewFilter); - List customDataAttributes = toCustomAttributes(customDataSessions); - - BinningIds unfilteredIds = idPopulator.populateIdLists(unfilteredSamples, customDataAttributes); - BinningData unfilteredData = fetchCustomBinningData(customDataByAttributeId, unfilteredIds); - - return createBins( - dataBinMethod, - dataBinCountFilter, - studyViewFilter, - customAttributeByDatatype, - customDataAttributes, - unfilteredIds, - unfilteredSamples, - unfilteredData - ); - } - - private List createBins( - DataBinMethod dataBinMethod, - ClinicalDataBinCountFilter dataBinCountFilter, - StudyViewFilter studyViewFilter, - Map clinicalDataAttributeDatatypeMap, - List clinicalAttributes, - BinningIds unfilteredIds, - List unfilteredSampleIds, - BinningData unfilteredData - ) { - List filteredSampleIds = filterSampleIds(studyViewFilter, unfilteredSampleIds); - - BinningIds filteredIds; - List filteredClinicalData; - if (filteredSampleIds.equals(unfilteredSampleIds)) { - // if filtered and unfiltered samples are exactly the same, no need to fetch clinical data again: - filteredIds = new BinningIds(unfilteredIds); - filteredClinicalData = unfilteredData.getAllData(); - } else { - filteredIds = idPopulator.populateIdLists(filteredSampleIds, clinicalAttributes); - filteredClinicalData = filterClinicalData(unfilteredData, filteredIds); - } - - List attributes = dataBinCountFilter.getAttributes(); - if (dataBinMethod == DataBinMethod.STATIC) { - if (unfilteredSampleIds.isEmpty() || unfilteredData.getAllData().isEmpty()) { - return emptyList(); - } - return calculateStaticDataBins( - attributes, - clinicalDataAttributeDatatypeMap, - toClinicalDataByAttributeId(unfilteredData.getAllData()), - toClinicalDataByAttributeId(filteredClinicalData), - unfilteredIds.getUniqueSampleKeys(), - unfilteredIds.getUniquePatientKeys(), - filteredIds.getUniqueSampleKeys(), - filteredIds.getUniquePatientKeys() - ); - } else { // dataBinMethod == DataBinMethod.DYNAMIC - if (filteredClinicalData.isEmpty()) { - return emptyList(); - } - return calculateDynamicDataBins( - attributes, - clinicalDataAttributeDatatypeMap, - toClinicalDataByAttributeId(filteredClinicalData), - filteredIds.getUniqueSampleKeys(), - filteredIds.getUniquePatientKeys() - ); - } - } - - private List toCustomAttributes( - Map customDataSessions - ) { - return customDataSessions - .entrySet() - .stream() - .map(e -> toClinicalAttribute(e.getKey(), e.getValue().getData())) - .collect(toList()); - } - - private ClinicalAttribute toClinicalAttribute(String key, CustomAttributeWithData data) { - ClinicalAttribute result = new ClinicalAttribute(); - result.setPatientAttribute(data.getPatientAttribute()); - result.setAttrId(key); - result.setDatatype(data.getDatatype()); - return result; - } - - private Map> toClinicalDataByAttributeId(List unfilteredData) { - return unfilteredData.stream().collect(Collectors.groupingBy(Binnable::getAttrId)); - } - - private List filterClinicalData( - BinningData unfilteredData, - BinningIds filteredIds - ) { - return studyViewFilterUtil.filterClinicalData( - unfilteredData.samples, - unfilteredData.patients, - unfilteredData.conflictingPatientAttributes, - filteredIds.getStudyIds(), - filteredIds.getSampleIds(), - filteredIds.getStudyIdsOfPatients(), - filteredIds.getPatientIds(), - filteredIds.getSampleAttributeIds(), - filteredIds.getPatientAttributeIds(), - filteredIds.getConflictingPatientAttributeIds() - ); - } - - private List filterSampleIds(StudyViewFilter studyViewFilter, List unfilteredSampleIds) { - return studyViewFilterUtil.shouldSkipFilterForClinicalDataBins(studyViewFilter) - ? unfilteredSampleIds - : studyViewFilterApplier.apply(studyViewFilter); - } - - private List toAttributeIds(List dataBinCountFilter) { - return dataBinCountFilter.stream() - .map(ClinicalDataBinFilter::getAttributeId).collect(toList()); - } - - private StudyViewFilter toStudyViewFilter(ClinicalDataBinCountFilter dataBinCountFilter, boolean shouldRemoveSelfFromFilter) { - StudyViewFilter studyViewFilter = dataBinCountFilter.getStudyViewFilter(); - - if (shouldRemoveSelfFromFilter) { - studyViewFilter = removeSelfFromFilter(dataBinCountFilter); - } - return studyViewFilter; - } - - private Map> createCustomDataByAttributeId(Map customDataSessions) { - return customDataSessions.entrySet().stream() - .collect(toMap( - Map.Entry::getKey, - entry -> entry - .getValue() - .getData() - .getData() - .stream() - .map(mapCustomToBinnable(entry)) - .collect(toList()) - )); - } - - private BinningData fetchBinningData(BinningIds binningIds) { - List samples = clinicalDataFetcher.fetchClinicalDataForSamples( - binningIds.getStudyIds(), - binningIds.getSampleIds(), - binningIds.getSampleAttributeIds() - ); - - List patients = clinicalDataFetcher.fetchClinicalDataForPatients( - binningIds.getStudyIdsOfPatients(), - binningIds.getPatientIds(), - binningIds.getPatientAttributeIds() - ); - - List conflictingPatientAttributes = clinicalDataFetcher.fetchClinicalDataForConflictingPatientAttributes( - binningIds.getStudyIdsOfPatients(), - binningIds.getPatientIds(), - binningIds.getConflictingPatientAttributeIds() - ); - return new BinningData<>(samples, patients, conflictingPatientAttributes); - } - - private BinningData fetchCustomBinningData( - Map> clinicalDataByAttributeId, - BinningIds binningIds - ) { - List clinicalDataForPatients = clinicalDataByAttributeId - .values() - .stream() - .filter(e -> e.get(0).isPatientAttribute()) - .flatMap(List::stream) - .collect(toList()); - - List clinicalDataForSamples = clinicalDataByAttributeId - .values() - .stream() - .filter(e -> !e.get(0).isPatientAttribute()) - .flatMap(List::stream) - .collect(toList()); - - List unfilteredClinicalDataForConflictingPatientAttributes = clinicalDataFetcher.fetchClinicalDataForConflictingPatientAttributes( - binningIds.getStudyIdsOfPatients(), - binningIds.getPatientIds(), - binningIds.getConflictingPatientAttributeIds() - ); - return new BinningData<>( - clinicalDataForSamples, - clinicalDataForPatients, - (List) (List) unfilteredClinicalDataForConflictingPatientAttributes - ); - } - - - private Function mapCustomToBinnable(Map.Entry entry) { - return customDataValue -> { - final String attributeId = entry.getKey(); - final Boolean patientAttribute = entry.getValue().getData().getPatientAttribute(); - return new BinnableCustomDataValue( - customDataValue, - attributeId, - patientAttribute - ); - }; - } - - public List calculateStaticDataBins( - List attributes, - Map attributeDatatypeMap, - Map> unfilteredClinicalDataByAttributeId, - Map> filteredClinicalDataByAttributeId, - List unfilteredUniqueSampleKeys, - List unfilteredUniquePatientKeys, - List filteredUniqueSampleKeys, - List filteredUniquePatientKeys - ) { - List clinicalDataBins = new ArrayList<>(); - - for (ClinicalDataBinFilter attribute : attributes) { - if (attributeDatatypeMap.containsKey(attribute.getAttributeId())) { - ClinicalDataType clinicalDataType = attributeDatatypeMap.get(attribute.getAttributeId()); - List filteredIds = clinicalDataType == ClinicalDataType.PATIENT ? filteredUniquePatientKeys - : filteredUniqueSampleKeys; - List unfilteredIds = clinicalDataType == ClinicalDataType.PATIENT - ? unfilteredUniquePatientKeys - : unfilteredUniqueSampleKeys; - - List dataBins = dataBinner - .calculateClinicalDataBins(attribute, clinicalDataType, - filteredClinicalDataByAttributeId.getOrDefault(attribute.getAttributeId(), - emptyList()), - unfilteredClinicalDataByAttributeId.getOrDefault(attribute.getAttributeId(), - emptyList()), - filteredIds, unfilteredIds) - .stream() - .map(dataBin -> NewClinicalDataBinUtil.dataBinToClinicalDataBin(attribute, dataBin)) - .toList(); - - clinicalDataBins.addAll(dataBins); - } - } - - return clinicalDataBins; - } - - public List calculateDynamicDataBins( - List attributes, - Map attributeDatatypeMap, - Map> filteredClinicalDataByAttributeId, - List filteredUniqueSampleKeys, - List filteredUniquePatientKeys - ) { - List clinicalDataBins = new ArrayList<>(); - - for (ClinicalDataBinFilter attribute : attributes) { - - // if there is clinical data for requested attribute - if (attributeDatatypeMap.containsKey(attribute.getAttributeId())) { - ClinicalDataType clinicalDataType = attributeDatatypeMap.get(attribute.getAttributeId()); - List filteredIds = clinicalDataType == ClinicalDataType.PATIENT - ? filteredUniquePatientKeys - : filteredUniqueSampleKeys; - - List dataBins = dataBinner - .calculateDataBins(attribute, clinicalDataType, - filteredClinicalDataByAttributeId.getOrDefault(attribute.getAttributeId(), - emptyList()), - filteredIds) - .stream() - .map(dataBin -> NewClinicalDataBinUtil.dataBinToClinicalDataBin(attribute, dataBin)) - .toList(); - clinicalDataBins.addAll(dataBins); - } - } - - return clinicalDataBins; - } - private Map toAttributeDatatypeMap(BinningIds binningIds) { - return toAttributeDatatypeMap( - binningIds.getSampleAttributeIds(), - binningIds.getPatientAttributeIds(), - binningIds.getConflictingPatientAttributeIds() - ); - } - public Map toAttributeDatatypeMap( - List sampleAttributeIds, - List patientAttributeIds, - List conflictingPatientAttributeIds - ) { - return NewClinicalDataBinUtil.toAttributeDatatypeMap( - sampleAttributeIds, - patientAttributeIds, - conflictingPatientAttributeIds - ); - } - - private Map createCustomAttributeDatatypeMap( - Map customDataSessions - ) { - return customDataSessions.entrySet().stream().collect(toMap( - Map.Entry::getKey, - ClinicalDataBinUtil::getDataType - )); - } - - public List filterByStudyAndSample( - StudyViewFilter studyViewFilter - ) { - StudyViewFilter filter = null; - - // only filter by study id and sample identifiers - if (studyViewFilter != null) { - filter = new StudyViewFilter(); - filter.setStudyIds(studyViewFilter.getStudyIds()); - filter.setSampleIdentifiers(studyViewFilter.getSampleIdentifiers()); - } - - return studyViewFilterApplier.apply(filter); - } - - private static ClinicalDataType getDataType(Map.Entry entry) { - return entry.getValue().getData().getPatientAttribute() ? ClinicalDataType.PATIENT : ClinicalDataType.SAMPLE; - } - - private List fetchClinicalAttributes(List attributeIds, List unfilteredSamples) { - - List studyIds = new ArrayList<>(); - List sampleIds = new ArrayList<>(); - studyViewFilterUtil.extractStudyAndSampleIds( - unfilteredSamples, - studyIds, - sampleIds - ); - - return clinicalAttributeService.getClinicalAttributesByStudyIdsAndAttributeIds(studyIds, attributeIds); - } - -} diff --git a/src/main/java/org/cbioportal/web/util/ClinicalDataEnrichmentUtil.java b/src/main/java/org/cbioportal/web/util/ClinicalDataEnrichmentUtil.java deleted file mode 100644 index 50ab61aafa1..00000000000 --- a/src/main/java/org/cbioportal/web/util/ClinicalDataEnrichmentUtil.java +++ /dev/null @@ -1,276 +0,0 @@ -package org.cbioportal.web.util; - -import java.math.BigDecimal; -import java.util.*; -import java.util.function.Supplier; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -import org.apache.commons.lang3.math.NumberUtils; -import org.cbioportal.model.ClinicalAttribute; -import org.cbioportal.model.ClinicalData; -import org.cbioportal.model.ClinicalDataCount; -import org.cbioportal.model.ClinicalDataCountItem; -import org.cbioportal.model.ClinicalDataEnrichment; -import org.cbioportal.model.Sample; -import org.cbioportal.service.ClinicalDataService; -import org.cbioportal.service.util.ClinicalAttributeUtil; -import org.cbioportal.web.parameter.ClinicalDataType; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.stereotype.Component; - -import com.datumbox.framework.common.dataobjects.AssociativeArray; -import com.datumbox.framework.common.dataobjects.DataTable2D; -import com.datumbox.framework.common.dataobjects.FlatDataCollection; -import com.datumbox.framework.common.dataobjects.TransposeDataCollection; -import com.datumbox.framework.core.statistics.distributions.ContinuousDistributions; -import com.datumbox.framework.core.statistics.nonparametrics.independentsamples.Chisquare; -import com.datumbox.framework.core.statistics.nonparametrics.independentsamples.KruskalWallis; - -/** - * @author kalletlak - * - */ -@Component -public class ClinicalDataEnrichmentUtil { - - @Autowired - private ClinicalDataService clinicalDataService; - @Autowired - private ClinicalAttributeUtil clinicalAttributeUtil; - - @Value("${comparison.categorical_na_values:NA}") - private String ComparisonCategoricalNaValuesString; - - public List createEnrichmentsForNumericData(List attributes, - List> groupedSamples) { - List clinicalEnrichments = new ArrayList(); - - List filteredAttributes = attributes.stream() - .filter(attribute -> attribute.getDatatype().equals("NUMBER")) - .collect(Collectors.toList()); - - List sampleAttributeIds = new ArrayList<>(); - List patientAttributeIds = new ArrayList<>(); - List conflictingPatientAttributeIds = new ArrayList<>(); - - clinicalAttributeUtil.extractCategorizedClinicalAttributes(filteredAttributes, - sampleAttributeIds, - patientAttributeIds, - conflictingPatientAttributeIds); - String testName = groupedSamples.size() == 2 ? "Wilcoxon Test" : "Kruskal Wallis Test"; - - // list of values for all NUMBER datatype attributes and for all sample groups - List>> dataByGroupAndByAttribute = groupedSamples.stream() - .map(groupSamples -> getNumericClinicalData(new ArrayList<>(sampleAttributeIds), - new ArrayList<>(patientAttributeIds), new ArrayList<>(conflictingPatientAttributeIds), - groupSamples)) - .collect(Collectors.toList()); - - filteredAttributes.forEach(clinicalAttribute -> { - - String attributeId = clinicalAttribute.getAttrId(); - TransposeDataCollection transposeDataCollection = new TransposeDataCollection(); - int index = 0; - for (Map> entry : dataByGroupAndByAttribute) { - if (entry.containsKey(attributeId)) { - Collection values = entry.get(attributeId).stream().collect(Collectors.toList()); - // add only groups having values - if (values.size() > 0) { - transposeDataCollection.put(index++, new FlatDataCollection(values)); - } - } - } - - Supplier> valuesStreamSupplier = () -> transposeDataCollection - .values() - .stream() - .flatMap(Collection::stream) - .map(x -> (Double) x); - - List distinctValues = valuesStreamSupplier.get().distinct().collect(Collectors.toList()); - - // perform test only if there are more than one group and - // there are atleast two distinct values - if (transposeDataCollection.keySet().size() > 1 && distinctValues.size() > 1) { - double pValue = KruskalWallis.getPvalue(transposeDataCollection); - if (!Double.isNaN(pValue)) { // this happens when all the values are zero - ClinicalDataEnrichment clinicalEnrichment = new ClinicalDataEnrichment(); - clinicalEnrichment.setClinicalAttribute(clinicalAttribute); - clinicalEnrichment.setpValue(BigDecimal.valueOf(pValue)); - clinicalEnrichment.setScore(BigDecimal.valueOf(ContinuousDistributions.chisquareInverseCdf(pValue, - transposeDataCollection.keySet().size() - 1))); - clinicalEnrichment.setMethod(testName); - clinicalEnrichments.add(clinicalEnrichment); - } - } - }); - return clinicalEnrichments; - } - - public List createEnrichmentsForCategoricalData(List attributes, - List> groupedSamples) { - List clinicalEnrichments = new ArrayList(); - - List filteredAttributes = attributes.stream() - .filter(attribute -> attribute.getDatatype().equals("STRING")) - .collect(Collectors.toList()); - - List filteredAttributeIds = filteredAttributes.stream().map(ClinicalAttribute::getAttrId).collect(Collectors.toList()); - - // ClinicalDataCountItem for all STRING datatype attributes and for all sample groups - List> dataCountsByGroupAndByAttribute = groupedSamples.stream() - .map(groupSamples -> getClinicalDataCounts(filteredAttributeIds, groupSamples)).collect(Collectors.toList()); - - filteredAttributes.forEach(clinicalAttribute -> { - - String attributeId = clinicalAttribute.getAttrId(); - - // get counts for all categories in all group for a given attribute - List> categoryCountsByGroup = dataCountsByGroupAndByAttribute.stream().map(e -> { - if (e.containsKey(attributeId)) { - return e.get(attributeId).getCounts().stream() - .collect(Collectors.toMap(ClinicalDataCount::getValue, ClinicalDataCount::getCount)); - } - return new HashMap(); - }).collect(Collectors.toList()); - - Set allPossibleCategories = categoryCountsByGroup.stream().flatMap(x -> x.keySet().stream()) - .collect(Collectors.toSet()); - - if (allPossibleCategories.size() > 1) { - DataTable2D dataTable = new DataTable2D(); - int groupIndex = 0; - for (Map groupCategoryCounts : categoryCountsByGroup) { - Map allCategoryCounts = allPossibleCategories.stream() - .collect(Collectors.toMap(category -> category, category -> { - return groupCategoryCounts.containsKey(category) ? groupCategoryCounts.get(category) - : 0; - })); - - // filter group if all the categories values are 0 - if (isValidGroupdData(new ArrayList<>(allCategoryCounts.values()))) { - AssociativeArray categoryCounts = new AssociativeArray(); - categoryCounts.putAll(allCategoryCounts); - dataTable.put(groupIndex++, categoryCounts); - } - } - - if (dataTable.size() > 1 && dataTable.isValid()) { - double pValue = Chisquare.getPvalue(dataTable); - ClinicalDataEnrichment clinicalEnrichment = new ClinicalDataEnrichment(); - clinicalEnrichment.setClinicalAttribute(clinicalAttribute); - clinicalEnrichment.setpValue(BigDecimal.valueOf(pValue)); - clinicalEnrichment.setScore(BigDecimal.valueOf((Double) Chisquare.getScoreValue(dataTable))); - clinicalEnrichment.setMethod("Chi-squared Test"); - clinicalEnrichments.add(clinicalEnrichment); - } - - } - }); - - return clinicalEnrichments; - } - - /** - * get data for all NUMBER datatype attributes for given samples - * - * @param attributes - * @param samples - * @return - */ - private Map> getNumericClinicalData(List sampleAttributeIds, - List patientAttributeIds, - List conflictingPatientAttributeIds, - List samples) { - - List studyIds = new ArrayList<>(); - List sampleIds = new ArrayList<>(); - List patientIds = new ArrayList<>(); - for (Sample sample : samples) { - studyIds.add(sample.getCancerStudyIdentifier()); - sampleIds.add(sample.getStableId()); - patientIds.add(sample.getPatientStableId()); - } - - Map> dataByAttribute = new HashMap<>(); - - List clinicalDatas = new ArrayList(); - if (!sampleAttributeIds.isEmpty()) { - clinicalDatas.addAll(clinicalDataService - .fetchClinicalData(studyIds, sampleIds, sampleAttributeIds, ClinicalDataType.SAMPLE.name(), "SUMMARY")); - } - - if (!patientAttributeIds.isEmpty()) { - clinicalDatas.addAll(clinicalDataService - .fetchClinicalData(studyIds, patientIds, patientAttributeIds, ClinicalDataType.PATIENT.name(), "SUMMARY")); - } - - if (!conflictingPatientAttributeIds.isEmpty()) { - clinicalDatas.addAll(clinicalDataService - .getPatientClinicalDataDetailedToSample(studyIds, patientIds, conflictingPatientAttributeIds)); - } - - dataByAttribute = clinicalDatas.stream() - // filter are non numeric data to fix - // https://github.com/cBioPortal/cbioportal/issues/6228 - .filter(x -> NumberUtils.isCreatable(x.getAttrValue())) - .collect(Collectors.groupingBy(x -> x.getAttrId(), - Collectors.mapping(x -> Double.valueOf(x.getAttrValue()), Collectors.toList()))); - - return dataByAttribute; - } - - /** - * get data category counts for all STRING datatype attributes for given samples - * - * @param attributes - * @param samples - * @return - */ - private Map getClinicalDataCounts(List attributeIds, List samples) { - - List studyIds = new ArrayList<>(); - List sampleIds = new ArrayList<>(); - for (Sample sample : samples) { - studyIds.add(sample.getCancerStudyIdentifier()); - sampleIds.add(sample.getStableId()); - } - - List clinicalDataCountItems = clinicalDataService.fetchClinicalDataCounts(studyIds, - sampleIds, attributeIds); - - return clinicalDataCountItems.stream() - // Exclude NA category - .map(clinicalDataCountItem -> { - List filteredClinicalDataCount = clinicalDataCountItem.getCounts() - .stream() - .filter(clinicalDataCount -> { - if (ComparisonCategoricalNaValuesString != null) { - String[] ComparisonCategoricalNaValues = ComparisonCategoricalNaValuesString.split("\\|"); - for (String naValue : ComparisonCategoricalNaValues) { - if (clinicalDataCount.getValue().equalsIgnoreCase(naValue)) { - return false; - } - } - } - return true; - } - ) - .collect(Collectors.toList()); - clinicalDataCountItem.setCounts(filteredClinicalDataCount); - return clinicalDataCountItem; - }) - .collect(Collectors.toMap(clinicalDataCountItem -> clinicalDataCountItem.getAttributeId(), - clinicalDataCountItem -> clinicalDataCountItem)); - - } - - // For categorical values, group data is valid if all the values are not 0 - private boolean isValidGroupdData(List values) { - return values.stream().map(value -> (value == 0 ? false : true)).reduce(false, - (value1, value2) -> value1 || value2); - } - -} diff --git a/src/main/java/org/cbioportal/web/util/ClinicalDataEqualityFilterApplier.java b/src/main/java/org/cbioportal/web/util/ClinicalDataEqualityFilterApplier.java deleted file mode 100644 index 251b9f96e56..00000000000 --- a/src/main/java/org/cbioportal/web/util/ClinicalDataEqualityFilterApplier.java +++ /dev/null @@ -1,50 +0,0 @@ -package org.cbioportal.web.util; - -import org.apache.commons.collections4.map.MultiKeyMap; -import org.cbioportal.model.ClinicalData; -import org.cbioportal.service.ClinicalDataService; -import org.cbioportal.service.PatientService; -import org.cbioportal.web.parameter.ClinicalDataFilter; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -import java.util.ArrayList; -import java.util.List; - -@Component -public class ClinicalDataEqualityFilterApplier extends ClinicalDataFilterApplier { - @Autowired - public ClinicalDataEqualityFilterApplier(PatientService patientService, - ClinicalDataService clinicalDataService, - StudyViewFilterUtil studyViewFilterUtil) { - super(patientService, clinicalDataService, studyViewFilterUtil); - } - - @Autowired - private StudyViewFilterUtil studyViewFilterUtil; - - @Override - public Integer apply(List attributes, - MultiKeyMap clinicalDataMap, - String entityId, - String studyId, - boolean negateFilters - ) { - return studyViewFilterUtil.getFilteredCountByDataEquality(attributes, clinicalDataMap, entityId, studyId, negateFilters); - } - - public static MultiKeyMap> buildClinicalDataMap(List clinicalDatas) { - MultiKeyMap> clinicalDataMap = new MultiKeyMap<>(); - - clinicalDatas.forEach(clinicalData -> { - if (!clinicalDataMap.containsKey(clinicalData.getStudyId(), clinicalData.getSampleId(), clinicalData.getAttrId())) { - clinicalDataMap.put(clinicalData.getStudyId(), clinicalData.getSampleId(), clinicalData.getAttrId(), new ArrayList<>()); - } - clinicalDataMap - .get(clinicalData.getStudyId(), clinicalData.getSampleId(), clinicalData.getAttrId()) - .add(clinicalData.getAttrValue()); - }); - - return clinicalDataMap; - } -} diff --git a/src/main/java/org/cbioportal/web/util/ClinicalDataFetcher.java b/src/main/java/org/cbioportal/web/util/ClinicalDataFetcher.java deleted file mode 100644 index 56dcbef0573..00000000000 --- a/src/main/java/org/cbioportal/web/util/ClinicalDataFetcher.java +++ /dev/null @@ -1,114 +0,0 @@ -package org.cbioportal.web.util; - -import org.apache.commons.collections4.CollectionUtils; -import org.cbioportal.model.ClinicalData; -import org.cbioportal.service.ClinicalDataService; -import org.cbioportal.web.parameter.ClinicalDataType; -import org.cbioportal.web.parameter.Projection; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -@Component -public class ClinicalDataFetcher { - - @Autowired - private ClinicalDataService clinicalDataService; - - public List fetchClinicalDataForSamples( - List studyIds, - List sampleIds, - List sampleAttributeIds - ) { - List filteredClinicalDataForSamples = Collections.emptyList(); - - if (CollectionUtils.isNotEmpty(sampleAttributeIds)) { - filteredClinicalDataForSamples = clinicalDataService.fetchClinicalData( - studyIds, - sampleIds, - sampleAttributeIds, - ClinicalDataType.SAMPLE.name(), - Projection.SUMMARY.name() - ); - } - - return filteredClinicalDataForSamples; - } - - public List fetchClinicalDataForPatients( - List studyIdsOfPatients, - List patientIds, - List patientAttributeIds - ) { - List filteredClinicalDataForPatients = Collections.emptyList(); - - if (CollectionUtils.isNotEmpty(patientAttributeIds)) { - filteredClinicalDataForPatients = clinicalDataService.fetchClinicalData( - studyIdsOfPatients, - patientIds, - patientAttributeIds, - ClinicalDataType.PATIENT.name(), - Projection.SUMMARY.name() - ); - } - - return filteredClinicalDataForPatients; - } - - public List fetchClinicalDataForConflictingPatientAttributes( - List studyIdsOfPatients, - List patientIds, - List conflictingPatientAttributes - ) { - List filteredClinicalDataForPatients = Collections.emptyList(); - - if (CollectionUtils.isNotEmpty(conflictingPatientAttributes)) { - filteredClinicalDataForPatients = clinicalDataService.getPatientClinicalDataDetailedToSample( - studyIdsOfPatients, - patientIds, - conflictingPatientAttributes - ); - } - - return filteredClinicalDataForPatients; - } - - public List fetchClinicalData( - List studyIds, - List sampleIds, - List patientIds, - List studyIdsOfPatients, - List sampleAttributeIds, - List patientAttributeIds, - List conflictingPatientAttributes - ) { - List unfilteredClinicalDataForSamples = fetchClinicalDataForSamples( - studyIds, - sampleIds, - sampleAttributeIds - ); - - List unfilteredClinicalDataForPatients = fetchClinicalDataForPatients( - studyIdsOfPatients, - patientIds, - patientAttributeIds - ); - - List unfilteredClinicalDataForConflictingPatientAttributes = fetchClinicalDataForConflictingPatientAttributes( - studyIdsOfPatients, - patientIds, - conflictingPatientAttributes - ); - - return Stream.of( - unfilteredClinicalDataForSamples, - unfilteredClinicalDataForPatients, - unfilteredClinicalDataForConflictingPatientAttributes - ).flatMap(Collection::stream).collect(Collectors.toList()); - } -} diff --git a/src/main/java/org/cbioportal/web/util/ClinicalDataFilterApplier.java b/src/main/java/org/cbioportal/web/util/ClinicalDataFilterApplier.java deleted file mode 100644 index 5a46baca9c2..00000000000 --- a/src/main/java/org/cbioportal/web/util/ClinicalDataFilterApplier.java +++ /dev/null @@ -1,90 +0,0 @@ -package org.cbioportal.web.util; - -import java.util.ArrayList; -import java.util.List; -import java.util.stream.Collectors; - -import org.apache.commons.collections4.map.MultiKeyMap; -import org.cbioportal.model.ClinicalData; -import org.cbioportal.model.Patient; -import org.cbioportal.service.ClinicalDataService; -import org.cbioportal.service.PatientService; -import org.cbioportal.web.parameter.ClinicalDataFilter; -import org.cbioportal.web.parameter.Projection; -import org.cbioportal.web.parameter.SampleIdentifier; - -public abstract class ClinicalDataFilterApplier implements DataFilterApplier { - private PatientService patientService; - private ClinicalDataService clinicalDataService; - protected StudyViewFilterUtil studyViewFilterUtil; - - public ClinicalDataFilterApplier( - PatientService patientService, - ClinicalDataService clinicalDataService, - StudyViewFilterUtil studyViewFilterUtil - ) { - this.patientService = patientService; - this.clinicalDataService = clinicalDataService; - this.studyViewFilterUtil = studyViewFilterUtil; - } - - @Override - public List apply( - List sampleIdentifiers, - List clinicalDataFilters, - boolean negateFilters - ) { - if (!clinicalDataFilters.isEmpty() && !sampleIdentifiers.isEmpty()) { - List studyIds = new ArrayList<>(); - List sampleIds = new ArrayList<>(); - - studyViewFilterUtil.extractStudyAndSampleIds(sampleIdentifiers, studyIds, sampleIds); - - List patients = patientService.getPatientsOfSamples(studyIds, sampleIds); - List patientIds = patients.stream().map(Patient::getStableId).collect(Collectors.toList()); - List studyIdsOfPatients = patients.stream().map(Patient::getCancerStudyIdentifier).collect(Collectors.toList()); - - List attributeIds = clinicalDataFilters.stream().map(ClinicalDataFilter::getAttributeId) - .collect(Collectors.toList()); - - List clinicalDataList = new ArrayList(); - - List sampleClinicalDataList = clinicalDataService.fetchClinicalData(studyIds, sampleIds, - attributeIds, "SAMPLE", Projection.SUMMARY.name()); - clinicalDataList.addAll(sampleClinicalDataList); - - List patientClinicalDataList = clinicalDataService - .getPatientClinicalDataDetailedToSample(studyIdsOfPatients, patientIds, attributeIds); - clinicalDataList.addAll(patientClinicalDataList); - - clinicalDataList.forEach(c -> { - c.setAttrValue(c.getAttrValue().toUpperCase()); - if (c.getAttrValue().equals("NAN") || c.getAttrValue().equals("N/A")) { - c.setAttrValue("NA"); - } - }); - - MultiKeyMap clinicalDataMap = new MultiKeyMap(); - for (ClinicalData clinicalData : clinicalDataList) { - clinicalDataMap.put(clinicalData.getStudyId(), clinicalData.getSampleId(), clinicalData.getAttrId(), - clinicalData.getAttrValue()); - } - - List newSampleIdentifiers = new ArrayList<>(); - sampleIdentifiers.forEach(sampleIdentifier -> { - int count = apply(clinicalDataFilters, clinicalDataMap, sampleIdentifier.getSampleId(), - sampleIdentifier.getStudyId(), negateFilters); - - if (count == clinicalDataFilters.size()) { - newSampleIdentifiers.add(sampleIdentifier); - } - }); - - return newSampleIdentifiers; - } - return sampleIdentifiers; - } - - // Must be overridden by child classes - protected abstract Integer apply(List attributes, MultiKeyMap clinicalDataMap, String entityId, String studyId, boolean negateFilters); -} diff --git a/src/main/java/org/cbioportal/web/util/ClinicalDataIntervalFilterApplier.java b/src/main/java/org/cbioportal/web/util/ClinicalDataIntervalFilterApplier.java deleted file mode 100644 index 66d310a2511..00000000000 --- a/src/main/java/org/cbioportal/web/util/ClinicalDataIntervalFilterApplier.java +++ /dev/null @@ -1,144 +0,0 @@ -package org.cbioportal.web.util; - -import com.google.common.collect.Range; -import org.apache.commons.collections4.map.MultiKeyMap; -import org.cbioportal.model.ClinicalData; -import org.cbioportal.service.ClinicalDataService; -import org.cbioportal.service.PatientService; -import org.cbioportal.web.parameter.ClinicalDataFilter; -import org.cbioportal.web.parameter.DataFilterValue; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -import java.math.BigDecimal; -import java.util.List; -import java.util.Objects; -import java.util.stream.Collectors; - -@Component -public class ClinicalDataIntervalFilterApplier extends ClinicalDataFilterApplier { - - @Autowired - public ClinicalDataIntervalFilterApplier(PatientService patientService, - ClinicalDataService clinicalDataService, - StudyViewFilterUtil studyViewFilterUtil) { - super(patientService, clinicalDataService, studyViewFilterUtil); - } - - @Override - public Integer apply(List attributes, - MultiKeyMap clinicalDataMap, - String entityId, - String studyId, - boolean negateFilters) { - int count = 0; - - for (ClinicalDataFilter filter : attributes) { - if (clinicalDataMap.containsKey(studyId, entityId, filter.getAttributeId())) { - String attrValue = (String) clinicalDataMap.get(studyId, entityId, filter.getAttributeId()); - Range rangeValue = calculateRangeValueForAttr(attrValue); - - // find range filters - List> ranges = filter.getValues().stream() - .map(this::calculateRangeValueForFilter) - .filter(Objects::nonNull) - .collect(Collectors.toList()); - - // find special value filters - List specialValues = filter.getValues().stream() - .filter(f -> f.getValue() != null) - .map(f -> f.getValue().toUpperCase()) - .collect(Collectors.toList()); - - if (rangeValue != null) { - if (negateFilters ^ ranges.stream().anyMatch(r -> r.encloses(rangeValue))) { - count++; - } - } - else if (negateFilters ^ specialValues.contains(attrValue.toUpperCase())) { - count++; - } - } else if (negateFilters ^ containsNA(filter)) { - count++; - } - } - - return count; - } - - private Range calculateRangeValueForAttr(String attrValue) { - if (attrValue == null) { - return null; - } - - BigDecimal min = null; - BigDecimal max = null; - - String value = attrValue.trim(); - - String lte = "<="; - String lt = "<"; - String gte = ">="; - String gt = ">"; - - boolean startInclusive = true; - boolean endInclusive = true; - - try { - if (value.startsWith(lte)) { - max = new BigDecimal(value.substring(lte.length())); - } - else if (value.startsWith(lt)) { - max = new BigDecimal(value.substring(lt.length())); - endInclusive = false; - } - else if (value.startsWith(gte)) { - min = new BigDecimal(value.substring(gte.length())); - } - else if (value.startsWith(gt)) { - min = new BigDecimal(value.substring(gt.length())); - startInclusive = false; - } - else { - min = max = new BigDecimal(attrValue); - } - } catch (Exception e) { - // invalid range -- TODO: also support ranges like 20-30? - return null; - } - - return DataBinHelper.calcRange(min, startInclusive, max, endInclusive); - } - - private Range calculateRangeValueForFilter(DataFilterValue filterValue) { - BigDecimal start = filterValue.getStart(); - BigDecimal end = filterValue.getEnd(); - - // default: (start, end] - boolean startInclusive = false; - boolean endInclusive = true; - - // special case: end == start (both inclusive) - if (end != null && end.equals(start)) { - startInclusive = true; - } - - return DataBinHelper.calcRange(start, startInclusive, end, endInclusive); - } - - private Boolean containsNA(ClinicalDataFilter filter) { - return filter.getValues().stream().anyMatch( - r -> r.getValue() != null && r.getValue().toUpperCase().equals("NA")); - } - - public static MultiKeyMap buildClinicalDataMap(List clinicalDatas) { - MultiKeyMap clinicalDataMap = new MultiKeyMap<>(); - - clinicalDatas.forEach(clinicalData -> - clinicalDataMap.put(clinicalData.getStudyId(), clinicalData.getSampleId(), clinicalData.getAttrId(), - clinicalData.getAttrValue()) - ); - - return clinicalDataMap; - } -} diff --git a/src/main/java/org/cbioportal/web/util/CustomDataFilterApplier.java b/src/main/java/org/cbioportal/web/util/CustomDataFilterApplier.java deleted file mode 100644 index ed37c9a13a4..00000000000 --- a/src/main/java/org/cbioportal/web/util/CustomDataFilterApplier.java +++ /dev/null @@ -1,132 +0,0 @@ -package org.cbioportal.web.util; - -import org.apache.commons.collections4.map.MultiKeyMap; -import org.cbioportal.service.CustomDataService; -import org.cbioportal.service.util.CustomDataSession; -import org.cbioportal.web.parameter.ClinicalDataFilter; -import org.cbioportal.web.parameter.SampleIdentifier; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.function.Function; -import java.util.stream.Collectors; - -@Component -public class CustomDataFilterApplier implements DataFilterApplier { - - private CustomDataService customDataService; - - private ClinicalDataEqualityFilterApplier equalityFilterApplier; - private ClinicalDataIntervalFilterApplier intervalFilterApplier; - - @Autowired - public CustomDataFilterApplier( - CustomDataService customDataService, - ClinicalDataEqualityFilterApplier equalityFilterApplier, - ClinicalDataIntervalFilterApplier intervalFilterApplier - ) { - this.customDataService = customDataService; - this.equalityFilterApplier = equalityFilterApplier; - this.intervalFilterApplier = intervalFilterApplier; - } - - @Override - public List apply( - List sampleIdentifiers, - List dataFilters, - boolean negateFilters - ) { - if (dataFilters.isEmpty() || sampleIdentifiers.isEmpty()) { - return sampleIdentifiers; - } - - final List attributeIds = dataFilters.stream() - .map(ClinicalDataFilter::getAttributeId) - .collect(Collectors.toList()); - - final Map customDataSessions = customDataService.getCustomDataSessions(attributeIds); - - Map customDataSessionById = customDataSessions - .values() - .stream() - .collect(Collectors.toMap( - CustomDataSession::getId, - Function.identity() - )); - - /* - Custom data entry with: - - key1: studyId; - - key2: sampleId; - - key3: sessionId. - */ - MultiKeyMap customDataByStudySampleSession = new MultiKeyMap<>(); - - customDataSessionById.values().forEach(customDataSession -> customDataSession - .getData() - .getData() - .forEach(datum -> { - String value = datum.getValue().toUpperCase(); - if (value.equals("NAN") || value.equals("N/A")) { - value = "NA"; - } - customDataByStudySampleSession.put(datum.getStudyId(), datum.getSampleId(), customDataSession.getId(), value); - }) - ); - - return filterCustomData( - dataFilters, - negateFilters, - sampleIdentifiers, - customDataSessionById, - customDataByStudySampleSession - ); - } - - private List filterCustomData( - List customDataFilters, - boolean negateFilters, - List sampleIdentifiers, - Map customDataSessionById, - MultiKeyMap clinicalDataMap - ) { - List equalityFilters = new ArrayList<>(); - List intervalFilters = new ArrayList<>(); - - customDataFilters.forEach(filter -> { - String attributeId = filter.getAttributeId(); - if (!customDataSessionById.containsKey(attributeId)) { - return; - } - if (customDataSessionById - .get(attributeId) - .getData() - .getDatatype() - .equals(CustomDatatype.STRING.name()) - ) { - equalityFilters.add(filter); - } else { - intervalFilters.add(filter); - } - }); - - List filtered = new ArrayList<>(); - sampleIdentifiers.forEach(sampleIdentifier -> { - int equalityFilterCount = equalityFilterApplier.apply(equalityFilters, clinicalDataMap, - sampleIdentifier.getSampleId(), sampleIdentifier.getStudyId(), negateFilters); - int intervalFilterCount = intervalFilterApplier.apply(intervalFilters, clinicalDataMap, - sampleIdentifier.getSampleId(), sampleIdentifier.getStudyId(), negateFilters); - if (equalityFilterCount == equalityFilters.size() - && intervalFilterCount == intervalFilters.size() - ) { - filtered.add(sampleIdentifier); - } - }); - - return filtered; - } - -} diff --git a/src/main/java/org/cbioportal/web/util/CustomDatatype.java b/src/main/java/org/cbioportal/web/util/CustomDatatype.java deleted file mode 100644 index 9aaac0ebd15..00000000000 --- a/src/main/java/org/cbioportal/web/util/CustomDatatype.java +++ /dev/null @@ -1,13 +0,0 @@ -package org.cbioportal.web.util; - -public enum CustomDatatype { - /** - * Categorical data - */ - STRING, - - /** - * Numerical data - */ - NUMBER -} \ No newline at end of file diff --git a/src/main/java/org/cbioportal/web/util/DataBinHelper.java b/src/main/java/org/cbioportal/web/util/DataBinHelper.java deleted file mode 100644 index 9138aef2572..00000000000 --- a/src/main/java/org/cbioportal/web/util/DataBinHelper.java +++ /dev/null @@ -1,511 +0,0 @@ -package org.cbioportal.web.util; - -import org.cbioportal.model.DataBin; -import com.google.common.collect.Range; -import java.math.BigDecimal; -import java.math.RoundingMode; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.ListIterator; -import java.util.Map; -import java.util.Set; -import java.util.stream.Collectors; -import org.springframework.util.Assert; - -public class DataBinHelper { - - public static DataBin calcUpperOutlierBin(List gteValues, List gtValues) { - BigDecimal gteMin = gteValues.size() > 0 ? Collections.min(gteValues) : null; - BigDecimal gtMin = gtValues.size() > 0 ? Collections.min(gtValues) : null; - BigDecimal min; - String value; - - if (gtMin == null && gteMin == null) { - // no special outlier - min = null; - value = ">"; - } else if (gtMin == null || (gteMin != null && gteMin.compareTo(gtMin) < 0)) { - min = gteMin; - value = ">="; - } else { - min = gtMin; - value = ">"; - } - - DataBin dataBin = new DataBin(); - - dataBin.setCount(gteValues.size() + gtValues.size()); - dataBin.setSpecialValue(value); - dataBin.setStart(min); - - return dataBin; - } - - public static DataBin calcLowerOutlierBin(List lteValues, List ltValues) { - BigDecimal lteMax = lteValues.size() > 0 ? Collections.max(lteValues) : null; - BigDecimal ltMax = ltValues.size() > 0 ? Collections.max(ltValues) : null; - BigDecimal max; - String specialValue; - - if (ltMax == null && lteMax == null) { - max = null; - specialValue = "<="; - } else if (lteMax == null || (ltMax != null && lteMax.compareTo(ltMax) < 0)) { - max = ltMax; - specialValue = "<"; - } else { - max = lteMax; - specialValue = "<="; - } - - DataBin dataBin = new DataBin(); - - dataBin.setCount(lteValues.size() + ltValues.size()); - dataBin.setSpecialValue(specialValue); - dataBin.setEnd(max); - - return dataBin; - } - - public static List calcQuartileBoundaries(List sortedValues) { - // Edge case: some of Q1, Q2, and Q3 are the same value. - // Solution: reduce bins to represent unique values only. - // Note: cannot use stream.distinct() because BigDecimal does - // not play nice with this (e.g., "2.5E+2" is not identical to "250" - // when using Object.equals()) - final BigDecimal q1 = calcQ1(sortedValues); - final BigDecimal q2 = calcMedian(sortedValues); - final BigDecimal q3 = calcQ3(sortedValues); - List boundaries = new ArrayList<>(); - boundaries.add(q1); - // Check Q1 smaller than Q2 - if (q1.compareTo(q2) < 0) { - boundaries.add(q2); - } - // Check Q2 smaller than Q3 - if (q2.compareTo(q3) < 0) { - boundaries.add(q3); - } - return boundaries; - } - - public static Range calcBoxRange(List sortedValues) { - if (sortedValues == null || sortedValues.size() == 0) { - return null; - } - - // Find a generous IQR. This is generous because if (values.length / 4) - // is not an int, then really you should average the two elements on either - // side to find q1 and q3. - Range interquartileRange = calcInterquartileRangeApproximation(sortedValues); - - BigDecimal q1 = interquartileRange.lowerEndpoint(); - BigDecimal q3 = interquartileRange.upperEndpoint(); - BigDecimal iqr = q3.subtract(q1); - BigDecimal iqrOneAndHalf = iqr.multiply(new BigDecimal("1.5")); - BigDecimal q1LowerBoundry = q1.subtract(iqrOneAndHalf); - BigDecimal q3upperBoundry = q3.add(iqrOneAndHalf); - - - // Then find min and max values - BigDecimal maxValue; - BigDecimal minValue; - - if (sortedValues.get(0).compareTo(sortedValues.get(sortedValues.size() - 1)) == 0) { - // if the first and last values are the same, no need to do any other calculation - // we simply set min and max to the same value - minValue = sortedValues.get(0); - maxValue = minValue; - } else if (q3.compareTo(new BigDecimal("0.001")) != -1 && q3.compareTo(new BigDecimal("1")) < 0) { - //maxValue = Number((q3 + iqr * 1.5).toFixed(3)); - //minValue = Number((q1 - iqr * 1.5).toFixed(3)); - maxValue = q3upperBoundry.setScale(3, BigDecimal.ROUND_HALF_UP); - minValue = q1LowerBoundry.setScale(3, BigDecimal.ROUND_HALF_UP); - } else if (q3.compareTo(BigDecimal.valueOf(0.001)) < 0) { - // get IQR for very small number(<0.001) - maxValue = q3upperBoundry; - minValue = q1LowerBoundry; - } else { - maxValue = q3upperBoundry.setScale(1, RoundingMode.CEILING); - minValue = q1LowerBoundry.setScale(1, RoundingMode.FLOOR); - } - - if (minValue.compareTo(sortedValues.get(0)) < 0) { - minValue = sortedValues.get(0); - } - - if (maxValue.compareTo(sortedValues.get(sortedValues.size() - 1)) > 0) { - maxValue = sortedValues.get(sortedValues.size() - 1); - } - - return Range.closed(minValue, maxValue); - } - - public static Range calcInterquartileRangeApproximation(List sortedValues) { - Range iqr = null; - - if (sortedValues.size() > 0) { - BigDecimal q1 = valueCloseToQ1(sortedValues); - BigDecimal q3 = valueCloseToQ3(sortedValues); - BigDecimal max = sortedValues.get(sortedValues.size() - 1); - - // if iqr == 0 AND max == q3 then recursively try finding a non-zero iqr approximation. - if (q1.compareTo(q3) == 0 && max.compareTo(q3) == 0) { - // filter out max and try again - iqr = calcInterquartileRangeApproximation( - sortedValues.stream().filter(d -> d.compareTo(max) < 0).collect(Collectors.toList())); - } - - // if range is still empty use the original q1 and q3 values - if (iqr == null || iqr.isEmpty()) { - iqr = Range.closedOpen(q1, q3); - } - } - - return iqr; - } - - public static BigDecimal calcQ1(List sortedValues) { - if (sortedValues == null || sortedValues.isEmpty()) { - return null; - } - // Stop is one position before the median array index. - int stopIndex = (int) (sortedValues.size() * 0.5) - 1; - return calcMedian(sortedValues, 0, stopIndex); - } - - public static BigDecimal calcMedian(List sortedValues) { - return (sortedValues == null || sortedValues.isEmpty()) ? null - : calcMedian(sortedValues, 0, sortedValues.size() - 1); - } - - public static BigDecimal calcQ3(List sortedValues) { - if (sortedValues == null || sortedValues.isEmpty()) { - return null; - } - // Start one position after the median array index. - int startIndex = (int) (sortedValues.size() * 0.5); - if (sortedValues.size() % 2 != 0) { - startIndex += 1; - } - return calcMedian(sortedValues, startIndex, sortedValues.size() - 1); - } - - private static BigDecimal calcMedian(List sortedValues, int start, int stop) { - if (sortedValues == null || sortedValues.isEmpty()) { - return null; - } - final List values = sortedValues.subList(start, stop + 1); - double index = values.size() * 0.5; - BigDecimal value = values.get((int) index); - if (values.size() % 2 != 0) { - return value; - } else { - BigDecimal valueBelow = values.get((int) index - 1); - return value.add(valueBelow).divide(new BigDecimal("2.0")); - } - } - - public static BigDecimal valueCloseToQ1(List sortedValues) { - return (sortedValues == null || sortedValues.isEmpty()) ? - null : sortedValues.get((int) (sortedValues.size() * 0.25)); - } - - public static BigDecimal valueCloseToQ3(List sortedValues) { - return (sortedValues == null || sortedValues.isEmpty()) ? - null : sortedValues.get((int) (sortedValues.size() * 0.75)); - } - - public static List filterIntervals(List intervals, BigDecimal lowerOutlier, BigDecimal upperOutlier) { - // remove values that fall outside the lower and upper outlier limits - return intervals.stream() - .filter(d -> (lowerOutlier == null || d.compareTo(lowerOutlier) > 0 ) && (upperOutlier == null || d.compareTo(upperOutlier) < 0)) - .collect(Collectors.toList()); - } - - public static List initDataBins(List values, - List intervals, - BigDecimal lowerOutlier, - BigDecimal upperOutlier) { - return initDataBins(values, - filterIntervals(intervals, lowerOutlier, upperOutlier)); - } - - public static List initDataBins(List values, - List intervals) { - List dataBins = initDataBins(intervals); - - calcCounts(dataBins, values); - - return dataBins; - } - - public static List initDataBins(List intervalValues) { - List dataBins = new ArrayList<>(); - - for (int i = 0; i < intervalValues.size() - 1; i++) { - DataBin dataBin = new DataBin(); - - dataBin.setCount(0); - dataBin.setStart(intervalValues.get(i)); - dataBin.setEnd(intervalValues.get(i+1)); - - dataBins.add(dataBin); - } - - return dataBins; - } - - public static List trim(List dataBins) { - List toRemove = new ArrayList<>(); - - // find out leading empty bins - for (DataBin dataBin : dataBins) { - if (dataBin.getCount() == null || dataBin.getCount() <= 0) { - toRemove.add(dataBin); - } else { - break; - } - } - - // find out trailing empty bins - ListIterator iterator = dataBins.listIterator(dataBins.size()); - - while (iterator.hasPrevious()) { - DataBin dataBin = iterator.previous(); - - if (dataBin.getCount() == null || dataBin.getCount() <= 0) { - toRemove.add(dataBin); - } else { - break; - } - } - - List trimmed = new ArrayList<>(dataBins); - trimmed.removeAll(toRemove); - - return trimmed; - } - - public static void calcCounts(List dataBins, List values) { - Map, DataBin> rangeMap = dataBins.stream().collect(Collectors.toMap(DataBinHelper::calcRange, b -> b)); - - // TODO complexity here is O(n x m), find a better way to do this - for (Range range : rangeMap.keySet()) { - for (BigDecimal value: values) { - // check if the value falls within the data bin range - if (range != null && range.contains(value)) { - DataBin dataBin = rangeMap.get(range); - dataBin.setCount(dataBin.getCount() + 1); - } - } - } - } - - public static Range calcRange(DataBin dataBin) { - boolean startInclusive = ">=".equals(dataBin.getSpecialValue()); - boolean endInclusive = !"<".equals(dataBin.getSpecialValue()); - - // special condition (start == end) - if (dataBin.getStart() != null && dataBin.getEnd() != null && dataBin.getStart().compareTo(dataBin.getEnd())==0) { - startInclusive = endInclusive = true; - } - - return calcRange(dataBin.getStart(), startInclusive, dataBin.getEnd(), endInclusive); - } - - public static Range calcRange(String operator, BigDecimal value) { - boolean startInclusive = ">=".equals(operator); - BigDecimal start = operator.contains(">") ? value : null; - boolean endInclusive = !"<".equals(operator); - BigDecimal end = operator.contains("<") ? value : null; - - return calcRange(start, startInclusive, end, endInclusive); - } - - public static boolean isNA(String value) { - return value.equalsIgnoreCase("NA") || - value.equalsIgnoreCase("NAN") || - value.equalsIgnoreCase("N/A"); - } - - public static boolean isSmallData(List sortedValues) { - BigDecimal median = sortedValues.get((int) Math.ceil((sortedValues.size() * (1.0 / 2.0)))); - - return median.compareTo(new BigDecimal("0.001")) < 0 && median.compareTo(new BigDecimal("-0.001")) > 0 && median.compareTo(new BigDecimal("0")) != 0; - } - - public static String extractOperator(String value) { - int length = 0; - - if (value.trim().startsWith(">=") || value.trim().startsWith("<=")) { - length = 2; - } else if (value.trim().startsWith(">") || value.trim().startsWith("<")) { - length = 1; - } - - return value.trim().substring(0, length); - } - - public static Integer calcExponent(BigDecimal value) { - return value.precision() - value.scale() - 1; - } - - public static String stripOperator(String value) { - int length = 0; - - if (value.trim().startsWith(">=") || value.trim().startsWith("<=")) { - length = 2; - } else if (value.trim().startsWith(">") || value.trim().startsWith("<")) { - length = 1; - } - - return value.trim().substring(length); - } - - public static boolean isAgeAttribute(String attributeId) { - return attributeId != null && attributeId.matches("(^AGE$)|(^AGE_.*)|(.*_AGE_.*)|(.*_AGE&)"); - } - - public static Range calcRange(BigDecimal start, boolean startInclusive, BigDecimal end, boolean endInclusive) { - // check for invalid filter (no start or end provided) - if (start == null && end == null) { - return null; - } else if (start == null) { - if (endInclusive) { - return Range.atMost(end); - } else { - return Range.lessThan(end); - } - } else if (end == null) { - if (startInclusive) { - return Range.atLeast(start); - } else { - return Range.greaterThan(start); - } - } else if (startInclusive) { - if (endInclusive) { - return Range.closed(start, end); - } else { - return Range.closedOpen(start, end); - } - } else { - if (endInclusive) { - return Range.openClosed(start, end); - } else { - return Range.open(start, end); - } - } - } - - public static Set findDistinctValues(DataBin numericalBin, List numericalValues) { - Range range = calcRange(numericalBin); - - return numericalValues.stream().filter(range::contains).collect(Collectors.toSet()); - } - - public static Set> findDistinctSpecialRanges(DataBin numericalBin, List> rangeValues) { - Range range = calcRange(numericalBin); - - return rangeValues.stream().filter(range::encloses).collect(Collectors.toSet()); - } - - public static List convertToDistinctBins( - List dataBins, - List numericalValues, - List> rangeValues - ) { - List distinctBins = new ArrayList<>(); - - for (DataBin bin: dataBins) { - Set distinctValues = findDistinctValues(bin, numericalValues); - Set> distinctRanges = findDistinctSpecialRanges(bin, rangeValues); - - // if the bin contains only one distinct value and no range value then create a distinct bin - if (distinctRanges.size() == 0 && distinctValues.size() == 1 && areAllIntegers(distinctValues)) { - BigDecimal distinctValue = distinctValues.iterator().next(); - - DataBin distinctBin = new DataBin(); - distinctBin.setCount(bin.getCount()); - distinctBin.setStart(distinctValue); - distinctBin.setEnd(distinctValue); - - distinctBins.add(distinctBin); - } - // else keep the bin as is - else { - distinctBins.add(bin); - } - } - - // all bins except the outlier bins has to be distinct, - // otherwise return the original input bins (no conversion) - if (areAllDistinctExceptOutliers(distinctBins)) { - return distinctBins; - } - else { - return dataBins; - } - } - - public static Boolean areAllDistinctExceptOutliers(List dataBins) { - return dataBins - .stream() - .filter(b -> b.getStart() != null && b.getEnd() != null) - .map(b -> b.getStart().equals(b.getEnd())) - .reduce((a, b) -> a && b) - .orElse(false); - } - - public static Boolean areAllIntegers(Set uniqueValues) { - return uniqueValues - .stream() - .map(value -> value.stripTrailingZeros().scale() <= 0) - .reduce((a, b) -> a && b) - .orElse(false); - } - - public static List generateBins(List sortedNumericalValues, BigDecimal binSize, BigDecimal anchorValue) { - - Assert.notNull(sortedNumericalValues, "sortedNumerical values is null!"); - Assert.notNull(binSize, "binSize values is null!"); - Assert.notNull(anchorValue, "anchorValue values is null!"); - - if (sortedNumericalValues.isEmpty()) { - return null; - } - - // Assumes that elements are sorted in ascending order - BigDecimal minValue = sortedNumericalValues.get(0); - BigDecimal maxValue = sortedNumericalValues.get(sortedNumericalValues.size()-1); - Assert.isTrue(minValue.compareTo(maxValue) < 1, "minValue larger than maxValue. Input is not sorted in ascending order!"); - - List bins = new ArrayList<>(); - - // Calculate the lower boundary. - BigDecimal deltaL = anchorValue.subtract(minValue); - BigDecimal remainderL = deltaL.remainder(binSize); - // remainder() is not modulo; correct for this. - if (remainderL.compareTo(new BigDecimal(0)) < 0) { - remainderL = remainderL.add(binSize); - } - BigDecimal lowerBound = minValue.add(remainderL); - - // While the bound smaller than the maxValue keep adding boundaries. - while (lowerBound.compareTo(maxValue) < 0) { - bins.add(lowerBound); - lowerBound = lowerBound.add(binSize); - } - - return bins; - } - - private BigDecimal min(List numericalValues) { - return numericalValues.size() > 0 ? Collections.min(numericalValues) : null; - } - - private BigDecimal max(List numericalValues) { - return numericalValues.size() > 0 ? Collections.max(numericalValues) : null; - } -} diff --git a/src/main/java/org/cbioportal/web/util/DataBinner.java b/src/main/java/org/cbioportal/web/util/DataBinner.java deleted file mode 100644 index 85e21f2e69c..00000000000 --- a/src/main/java/org/cbioportal/web/util/DataBinner.java +++ /dev/null @@ -1,700 +0,0 @@ -package org.cbioportal.web.util; - -import com.google.common.collect.Range; -import org.apache.commons.lang3.math.NumberUtils; -import org.cbioportal.model.Binnable; -import org.cbioportal.model.DataBin; -import org.cbioportal.web.parameter.BinsGeneratorConfig; -import org.cbioportal.web.parameter.ClinicalDataBinFilter; -import org.cbioportal.web.parameter.ClinicalDataType; -import org.cbioportal.web.parameter.DataBinFilter; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -import java.math.BigDecimal; -import java.util.*; -import java.util.function.Predicate; -import java.util.stream.Collectors; - -@Component -public class DataBinner { - private static final Integer DEFAULT_DISTINCT_VALUE_THRESHOLD = 10; - - @Autowired - private DiscreteDataBinner discreteDataBinner; - @Autowired - private LinearDataBinner linearDataBinner; - @Autowired - private ScientificSmallDataBinner scientificSmallDataBinner; - @Autowired - private LogScaleDataBinner logScaleDataBinner; - - /** - * This method should only be invoked by legacy endpoints because it requires sample/patient ids. - * - * @deprecated - */ - @Deprecated - public List calculateClinicalDataBins( - T dataBinFilter, - ClinicalDataType clinicalDataType, - List filteredClinicalData, - List unfilteredClinicalData, - List filteredIds, - List unfilteredIds - ) { - // calculate data bins for unfiltered clinical data - List dataBins = calculateDataBins( - dataBinFilter, clinicalDataType, unfilteredClinicalData, unfilteredIds); - - // recount - return recalcBinCount(dataBins, clinicalDataType, filteredClinicalData, filteredIds); - } - - public List calculateClinicalDataBins( - T dataBinFilter, - List filteredClinicalData, - List unfilteredClinicalData - ) { - // calculate data bins for unfiltered clinical data - // we need this additional calculation to know the bins generated for the initial state. - // this allows us to keep the number of bins and bin ranges consistent. - // we only want to update the counts for each bin, we don't want to regenerate the bins for the filtered data. - List dataBins = calculateDataBins( - dataBinFilter, - unfilteredClinicalData - ); - - // recount - return recalcBinCount( - dataBins, - filteredClinicalData, - countNAs(filteredClinicalData) - ); - } - - /** - * This method should only be invoked by legacy endpoints because it requires sample/patient ids. - * - * @deprecated - */ - @Deprecated - public List recalcBinCount( - List dataBins, - ClinicalDataType clinicalDataType, - List clinicalData, - List caseIds - ) { - return recalcBinCount( - dataBins, - clinicalData, - countNAs(clinicalData, clinicalDataType, caseIds) - ); - } - - public List recalcBinCount( - List dataBins, - List clinicalData, - Long naCount - ) { - List numericalValues = clinicalData == null ? - Collections.emptyList() : filterNumericalValues(clinicalData); - List nonNumericalValues = clinicalData == null ? - Collections.emptyList() : filterNonNumericalValues(clinicalData); - List> ranges = clinicalData == null ? - Collections.emptyList() : filterSpecialRanges(clinicalData); - - for (DataBin dataBin : dataBins) { - // reset count - dataBin.setCount(0); - - // calculate range - Range range = DataBinHelper.calcRange(dataBin); - - if (range != null) { - for (BigDecimal value : numericalValues) { - if (range.contains(value)) { - dataBin.setCount(dataBin.getCount() + 1); - } - } - - for (Range r : ranges) { - if (range.encloses(r)) { - dataBin.setCount(dataBin.getCount() + 1); - } - } - } else { // if no range then it means non numerical data bin - for (String value : nonNumericalValues) { - if (value.equalsIgnoreCase(dataBin.getSpecialValue())) { - dataBin.setCount(dataBin.getCount() + 1); - } - } - } - if ("NA".equalsIgnoreCase(dataBin.getSpecialValue())) { - dataBin.setCount(naCount.intValue()); - } - } - - return dataBins; - } - - /** - * This method should only be invoked by legacy endpoints because it requires sample/patient ids. - * - * @deprecated - */ - @Deprecated - public List calculateDataBins( - T dataBinFilter, - ClinicalDataType clinicalDataType, - List clinicalData, - List caseIds - ) { - return calculateDataBins( - dataBinFilter, - clinicalDataType, - clinicalData, - caseIds, - DEFAULT_DISTINCT_VALUE_THRESHOLD - ); - } - - public List calculateDataBins( - T dataBinFilter, - List clinicalData - ) { - return calculateDataBins( - dataBinFilter, - clinicalData, - DEFAULT_DISTINCT_VALUE_THRESHOLD - ); - } - - public List calculateDataBins( - T dataBinFilter, - List clinicalData, - Integer distinctValueThreshold - ) { - DataBin naDataBin = calcNaDataBin(clinicalData); - - return calculateDataBins(dataBinFilter, clinicalData, naDataBin, distinctValueThreshold); - } - - /** - * This method should only be invoked by legacy endpoints because it requires sample/patient ids. - * - * @deprecated - */ - @Deprecated - public List calculateDataBins( - T dataBinFilter, - ClinicalDataType clinicalDataType, - List clinicalData, - List caseIds, - Integer distinctValueThreshold - ) { - DataBin naDataBin = calcNaDataBin(clinicalData, clinicalDataType, caseIds); - - return calculateDataBins(dataBinFilter, clinicalData, naDataBin, distinctValueThreshold); - } - - public List calculateDataBins( - T dataBinFilter, - List clinicalData, - DataBin naDataBin, - Integer distinctValueThreshold - ) { - boolean numericalOnly = false; - - Range range = dataBinFilter.getStart() == null && dataBinFilter.getEnd() == null ? - Range.all() : DataBinHelper.calcRange(dataBinFilter.getStart(), true, dataBinFilter.getEnd(), true); - - if (range.hasUpperBound()) { - clinicalData = filterSmallerThanUpperBound(clinicalData, range.upperEndpoint()); - numericalOnly = true; - } - - if (range.hasLowerBound()) { - clinicalData = filterBiggerThanLowerBound(clinicalData, range.lowerEndpoint()); - numericalOnly = true; - } - - DataBin upperOutlierBin = calcUpperOutlierBin(clinicalData); - DataBin lowerOutlierBin = calcLowerOutlierBin(clinicalData); - Collection numericalBins = calcNumericalClinicalDataBins( - dataBinFilter, - clinicalData, - dataBinFilter.getCustomBins(), - dataBinFilter.getBinMethod(), - dataBinFilter.getBinsGeneratorConfig(), - lowerOutlierBin, - upperOutlierBin, - dataBinFilter.getDisableLogScale(), - distinctValueThreshold - ); - - List dataBins = new ArrayList<>(); - - if (!lowerOutlierBin.getCount().equals(0)) { - dataBins.add(lowerOutlierBin); - } - - dataBins.addAll(numericalBins); - - if (!upperOutlierBin.getCount().equals(0)) { - dataBins.add(upperOutlierBin); - } - - // remove leading and trailing empty bins before adding non numerical ones - dataBins = DataBinHelper.trim(dataBins); - - // in some cases every numerical bin actually contains only a single discrete value - // convert interval bins to distinct (single value) bins in these cases - dataBins = DataBinHelper.convertToDistinctBins( - dataBins, filterNumericalValues(clinicalData), filterSpecialRanges(clinicalData) - ); - - if (!numericalOnly) { - // add non numerical and NA data bins - - dataBins.addAll(calcNonNumericalClinicalDataBins(clinicalData)); - - if (!naDataBin.getCount().equals(0)) { - dataBins.add(naDataBin); - } - } - - return dataBins; - } - - public List> filterSpecialRanges(List clinicalData) { - return clinicalData.stream() - .map(Binnable::getAttrValue) - .filter(s -> (s.contains(">") || s.contains("<")) && - // ignore any invalid values such as >10PY, <20%, etc. - NumberUtils.isCreatable(DataBinHelper.stripOperator(s))) - .map(v -> DataBinHelper.calcRange( - // only use "<" or ">" to make sure that we only generate open ranges - DataBinHelper.extractOperator(v).substring(0, 1), - new BigDecimal(DataBinHelper.stripOperator(v)))) - .collect(Collectors.toList()); - } - - public Collection calcNonNumericalClinicalDataBins(List clinicalData) { - return calcNonNumericalDataBins(filterNonNumericalValues(clinicalData)); - } - - public List filterNonNumericalValues(List clinicalData) { - // filter out numerical values and 'NA's - return clinicalData.stream() - .map(Binnable::getAttrValue) - .filter(s -> !NumberUtils.isCreatable(DataBinHelper.stripOperator(s)) && !DataBinHelper.isNA(s)) - .collect(Collectors.toList()); - } - - public Collection calcNonNumericalDataBins(List nonNumericalValues) { - Map map = new LinkedHashMap<>(); - - for (String value : nonNumericalValues) { - DataBin dataBin = map.computeIfAbsent(value.trim().toUpperCase(), key -> { - DataBin bin = new DataBin(); - bin.setSpecialValue(value.trim()); - bin.setCount(0); - return bin; - }); - - dataBin.setCount(dataBin.getCount() + 1); - } - - return map.values(); - } - - public Collection calcNumericalClinicalDataBins( - DataBinFilter dataBinFilter, - List clinicalData, - List customBins, - DataBinFilter.BinMethod binMethod, - BinsGeneratorConfig binsGeneratorConfig, - DataBin lowerOutlierBin, - DataBin upperOutlierBin, - Boolean disableLogScale, - Integer distinctValueThreshold - ) { - return calcNumericalDataBins( - dataBinFilter, - filterNumericalValues(clinicalData), - customBins, - binMethod, - binsGeneratorConfig, - lowerOutlierBin, - upperOutlierBin, - disableLogScale, - distinctValueThreshold - ); - } - - public List filterNumericalValues(List clinicalData) { - // filter out invalid values - return clinicalData.stream() - .filter(c -> NumberUtils.isCreatable(c.getAttrValue())) - .map(c -> new BigDecimal(c.getAttrValue())) - .collect(Collectors.toList()); - } - - public Collection calcNumericalDataBins( - DataBinFilter dataBinFilter, - List numericalValues, - List customBins, - DataBinFilter.BinMethod binMethod, - BinsGeneratorConfig binsGeneratorConfig, - DataBin lowerOutlierBin, - DataBin upperOutlierBin, - Boolean disableLogScale, - Integer distinctValueThreshold - ) { - - Predicate isLowerOutlier = d -> ( - lowerOutlierBin != null && - lowerOutlierBin.getEnd() != null && - (lowerOutlierBin.getSpecialValue() != null && lowerOutlierBin.getSpecialValue().contains("=") ? - d.compareTo(lowerOutlierBin.getEnd()) != 1 : d.compareTo(lowerOutlierBin.getEnd()) == -1) - ); - - Predicate isUpperOutlier = d -> ( - upperOutlierBin != null && - upperOutlierBin.getStart() != null && - (upperOutlierBin.getSpecialValue() != null && upperOutlierBin.getSpecialValue().contains("=") ? - d.compareTo(upperOutlierBin.getStart()) != -1 : d.compareTo(upperOutlierBin.getStart()) == 1) - ); - - Predicate isNotOutlier = - d -> !isUpperOutlier.test(d) && !isLowerOutlier.test(d); - - List sortedNumericalValues = new ArrayList<>(numericalValues); - Collections.sort(sortedNumericalValues); - - Range boxRange = DataBinHelper.calcBoxRange(sortedNumericalValues); - - // remove initial outliers - List withoutOutliers = sortedNumericalValues.stream().filter(isNotOutlier).collect(Collectors.toList()); - - // calculate data bins for the rest of the values - List dataBins = null; - - Set uniqueValues = new LinkedHashSet<>(withoutOutliers); - - if (0 < uniqueValues.size() && uniqueValues.size() <= distinctValueThreshold) { - // No data intervals when the number of distinct values less than or equal to the threshold. - // In this case, number of bins = number of distinct data values - dataBins = discreteDataBinner.calculateDataBins(withoutOutliers, uniqueValues); - } else if (!withoutOutliers.isEmpty()) { - - if (DataBinFilter.BinMethod.CUSTOM == binMethod && customBins != null) { - // adjust custom bins w.r.t. outliers (if any) - customBins = this.adjustCustomBins(customBins, lowerOutlierBin, upperOutlierBin); - dataBins = linearDataBinner.calculateDataBins(customBins, numericalValues); - } else if (DataBinFilter.BinMethod.GENERATE == binMethod && binsGeneratorConfig != null) { - List bins = DataBinHelper.generateBins(sortedNumericalValues, binsGeneratorConfig.getBinSize(), binsGeneratorConfig.getAnchorValue()); - dataBins = linearDataBinner.calculateDataBins(bins, numericalValues); - } else if (DataBinFilter.BinMethod.MEDIAN == binMethod) { - // NOOP - handled later - } else if (DataBinFilter.BinMethod.QUARTILE == binMethod) { - List boundaries = DataBinHelper.calcQuartileBoundaries(sortedNumericalValues); - dataBins = linearDataBinner.calculateDataBins(boundaries, numericalValues); - } else if (boxRange.upperEndpoint().subtract(boxRange.lowerEndpoint()).compareTo(new BigDecimal(1000)) == 1 && - (disableLogScale == null || !disableLogScale)) { - dataBins = logScaleDataBinner.calculateDataBins( - boxRange, - withoutOutliers, - lowerOutlierBin.getEnd(), - upperOutlierBin.getStart()); - } else if (DataBinHelper.isSmallData(sortedNumericalValues)) { - dataBins = scientificSmallDataBinner.calculateDataBins( - sortedNumericalValues, - withoutOutliers, - lowerOutlierBin.getEnd(), - upperOutlierBin.getStart()); - - // override box range with data bin min & max values (ignoring actual box range for now) - if (!dataBins.isEmpty()) { - boxRange = Range.closed(dataBins.get(0).getStart(), dataBins.get(dataBins.size() - 1).getEnd()); - } - } else { - Boolean areAllIntegers = DataBinHelper.areAllIntegers(uniqueValues); - - if (areAllIntegers) { - boxRange = Range.closed( - new BigDecimal(boxRange.lowerEndpoint().longValue()), - new BigDecimal(boxRange.upperEndpoint().longValue()) - ); - } - - BigDecimal lowerOutlier = lowerOutlierBin.getEnd() == null ? boxRange.lowerEndpoint() - : boxRange.lowerEndpoint().max(lowerOutlierBin.getEnd()); - BigDecimal upperOutlier = upperOutlierBin.getStart() == null ? boxRange.upperEndpoint() - : boxRange.upperEndpoint().min(upperOutlierBin.getStart()); - - Optional attributeId = dataBinFilter instanceof ClinicalDataBinFilter - ? Optional.of(((ClinicalDataBinFilter) dataBinFilter).getAttributeId()) - : Optional.empty(); - - dataBins = linearDataBinner.calculateDataBins(areAllIntegers, boxRange, withoutOutliers, lowerOutlier, - upperOutlier, attributeId); - } - - if (DataBinFilter.BinMethod.MEDIAN == binMethod - // In edge cases all quartile values can be identical (all - // values are in the outlier bins). - || (DataBinFilter.BinMethod.QUARTILE == binMethod && dataBins.size() == 0)) { - BigDecimal median = DataBinHelper.calcMedian(sortedNumericalValues); - lowerOutlierBin.setEnd(median); - upperOutlierBin.setStart(median); - // Covers the situation where there is a single custom boundary (i.e. there are only outlier bins). - } else if (DataBinFilter.BinMethod.CUSTOM == binMethod && customBins != null && - customBins.size() == 1) { - lowerOutlierBin.setEnd(customBins.get(0)); - upperOutlierBin.setStart(customBins.get(0)); - } - - // adjust the outlier limits: - // - // - when there is no special outlier values within the original data (like "<=20", ">80") - // then prioritize dataBin values over box range values - // - // - when there is special outlier values within the original data, - // then prioritize special outlier values over dataBin values - - if (lowerOutlierBin.getEnd() == null) { - - BigDecimal end = dataBins != null && !dataBins.isEmpty() ? dataBins.get(0).getStart() : - boxRange.lowerEndpoint(); - - lowerOutlierBin.setEnd(end); - } else if (dataBins != null && !dataBins.isEmpty()) { - if (dataBins.get(0).getStart().compareTo(lowerOutlierBin.getEnd()) == 1) { - lowerOutlierBin.setEnd(dataBins.get(0).getStart()); - } else { - dataBins.get(0).setStart(lowerOutlierBin.getEnd()); - } - } - - if (upperOutlierBin.getStart() == null) { - BigDecimal start = dataBins != null && !dataBins.isEmpty() ? dataBins.get(dataBins.size() - 1).getEnd() : - boxRange.upperEndpoint(); - - upperOutlierBin.setStart(start); - } else if (dataBins != null && !dataBins.isEmpty()) { - if (dataBins.get(dataBins.size() - 1).getEnd().compareTo(upperOutlierBin.getStart()) == -1) { - upperOutlierBin.setStart(dataBins.get(dataBins.size() - 1).getEnd()); - } else { - dataBins.get(dataBins.size() - 1).setEnd(upperOutlierBin.getStart()); - } - } - } - - // update upper and lower outlier counts - List upperOutliers = sortedNumericalValues.stream().filter(isUpperOutlier).collect(Collectors.toList()); - List lowerOutliers = sortedNumericalValues.stream().filter(isLowerOutlier).collect(Collectors.toList()); - - if (upperOutliers.size() > 0) { - upperOutlierBin.setCount(upperOutlierBin.getCount() + upperOutliers.size()); - } - - if (lowerOutliers.size() > 0) { - lowerOutlierBin.setCount(lowerOutlierBin.getCount() + lowerOutliers.size()); - } - - if (dataBins == null) { - dataBins = Collections.emptyList(); - } - - return dataBins; - } - - public List doubleValuesForSpecialOutliers(List clinicalData, String operator) { - return ( - // find the ones starting with the operator - clinicalData.stream().filter(c -> c.getAttrValue().trim().startsWith(operator)) - // strip the operator - .map(c -> c.getAttrValue().trim().substring(operator.length())) - // filter out invalid values - .filter(NumberUtils::isCreatable) - // parse the numerical value as a BigDecimal instance - .map(integer -> new BigDecimal(integer)) - // collect as list - .collect(Collectors.toList()) - ); - } - - public List filterSmallerThanUpperBound(List clinicalData, BigDecimal value) { - return ( - clinicalData.stream() - .filter(c -> NumberUtils.isCreatable(c.getAttrValue()) && new BigDecimal(c.getAttrValue()).compareTo(value) != 1) - .collect(Collectors.toList()) - ); - } - - public List filterBiggerThanLowerBound(List clinicalData, BigDecimal value) { - return ( - clinicalData.stream() - .filter(c -> NumberUtils.isCreatable(c.getAttrValue()) && new BigDecimal(c.getAttrValue()).compareTo(value) != -1) - // collect as list - .collect(Collectors.toList()) - ); - } - - public DataBin calcUpperOutlierBin(List clinicalData) { - DataBin dataBin = DataBinHelper.calcUpperOutlierBin( - doubleValuesForSpecialOutliers(clinicalData, ">="), - doubleValuesForSpecialOutliers(clinicalData, ">")); - - // for consistency always set operator to ">" - dataBin.setSpecialValue(">"); - - return dataBin; - } - - public DataBin calcLowerOutlierBin(List clinicalData) { - DataBin dataBin = DataBinHelper.calcLowerOutlierBin( - doubleValuesForSpecialOutliers(clinicalData, "<="), - doubleValuesForSpecialOutliers(clinicalData, "<")); - - // for consistency always set operator to "<=" - dataBin.setSpecialValue("<="); - - return dataBin; - } - - /** - * We cannot do an exact calculation for values below/above the special outlier values. - * We need to adjust custom bins for those cases. - * - * example: assume we have special values <18 and >90 in our dataset - * custom bins => [10, 15, 40, 70, 95, 100] - * adjusted custom bins => [18, 40, 70, 90] - */ - public List adjustCustomBins( - List customBins, - DataBin lowerOutlierBin, - DataBin upperOutlierBin - ) { - BigDecimal lowerBound = lowerOutlierBin.getEnd(); - BigDecimal upperBound = upperOutlierBin.getStart(); - - // filter out values less than lower bound and greater than the upper bound - List binsWithinBounds = customBins - .stream() - .filter(bin -> lowerBound == null || bin.compareTo(lowerBound) != -1) - .filter(bin -> upperBound == null || bin.compareTo(upperBound) != 1) - .collect(Collectors.toList()); - - // we need to add back lower bound if we removed values below the lower bound from the original bin list - if (customBins.stream().anyMatch(bin -> lowerBound != null && bin.compareTo(lowerBound) == -1)) { - binsWithinBounds.add(0, lowerBound); - } - - // we need to add back upper bound if we removed values above the upper bound from the original bin list - if (customBins.stream().anyMatch(bin -> upperBound != null && bin.compareTo(upperBound) == 1)) { - binsWithinBounds.add(upperBound); - } - - return binsWithinBounds; - } - - /** - * NA count is: Number of clinical data marked actually as "NA" + Number of patients/samples without clinical data. - * Assuming that clinical data is for a single attribute. - * - * This method should only be invoked by legacy endpoints because it requires sample/patient ids. - * - * @param clinicalData clinical data list for a single attribute - * @param caseIds sample/patient ids - * - * @return 'NA' clinical data count as a DataBin instance - * @deprecated - */ - @Deprecated - public DataBin calcNaDataBin( - List clinicalData, - ClinicalDataType clinicalDataType, - List caseIds - ) { - DataBin bin = initNaDataBin(); - bin.setCount(countNAs(clinicalData, clinicalDataType, caseIds).intValue()); - - return bin; - } - - /** - * This function assumes that all the NA values are already in the provided clinical data list. - * - * @param clinicalData clinical data list for a single attribute - * - * @return 'NA' clinical data count as a DataBin instance - */ - public DataBin calcNaDataBin( - List clinicalData - ) { - DataBin bin = initNaDataBin(); - bin.setCount(countNAs(clinicalData).intValue()); - - return bin; - } - - public DataBin initNaDataBin() { - DataBin bin = new DataBin(); - bin.setSpecialValue("NA"); - return bin; - } - - /** - * This method should only be invoked by legacy endpoints because it requires sample/patient ids - * - * @deprecated - */ - @Deprecated - public Long countNAs(List clinicalData, ClinicalDataType clinicalDataType, List caseIds) { - // Calculate the number of clinical data marked actually as "NA", "NAN", or "N/A" - - Long count = countNAs(clinicalData); - - // Calculate number of patients/samples without clinical data - - Set uniqueClinicalDataIds; - - if (clinicalData != null) { - uniqueClinicalDataIds = clinicalData - .stream() - .filter(Objects::nonNull) - .map(datum -> computeUniqueCaseId(datum, clinicalDataType)) - .collect(Collectors.toSet()); - } else { - uniqueClinicalDataIds = Collections.emptySet(); - } - - Set uniqueInputIds = new HashSet<>(caseIds); - - // remove the ids with existing clinical data, - // size of the difference (of two sets) is the count we need - uniqueInputIds.removeAll(uniqueClinicalDataIds); - count += uniqueInputIds.size(); - - return count; - } - - /** - * Calculate number of clinical data marked actually as "NA", "NAN", or "N/A" - */ - public Long countNAs(List clinicalData) { - return clinicalData == null ? 0 : - clinicalData.stream() - .filter(c -> DataBinHelper.isNA(c.getAttrValue())) - .count(); - } - - private String computeUniqueCaseId(Binnable clinicalData, ClinicalDataType clinicalDataType) { - return clinicalData.getStudyId() + (clinicalDataType == ClinicalDataType.PATIENT - ? clinicalData.getPatientId() - : clinicalData.getSampleId()); - } -} diff --git a/src/main/java/org/cbioportal/web/util/DataFilterApplier.java b/src/main/java/org/cbioportal/web/util/DataFilterApplier.java deleted file mode 100644 index ad5d6521658..00000000000 --- a/src/main/java/org/cbioportal/web/util/DataFilterApplier.java +++ /dev/null @@ -1,15 +0,0 @@ -package org.cbioportal.web.util; - -import org.cbioportal.web.parameter.DataFilter; -import org.cbioportal.web.parameter.SampleIdentifier; - -import java.util.List; - -public interface DataFilterApplier { - - List apply( - List sampleIdentifiers, - List dataFilters, - boolean negateFilters - ); -} diff --git a/src/main/java/org/cbioportal/web/util/DensityPlotParameters.java b/src/main/java/org/cbioportal/web/util/DensityPlotParameters.java deleted file mode 100644 index 47e65543680..00000000000 --- a/src/main/java/org/cbioportal/web/util/DensityPlotParameters.java +++ /dev/null @@ -1,118 +0,0 @@ -package org.cbioportal.web.util; - -import java.math.BigDecimal; - -public class DensityPlotParameters { - private final Integer xAxisBinCount; - private final Integer yAxisBinCount; - private final BigDecimal xAxisStart; - private final BigDecimal xAxisEnd; - private final BigDecimal yAxisStart; - private final BigDecimal yAxisEnd; - private final Boolean xAxisLogScale; - private final Boolean yAxisLogScale; - private final String xAxisAttributeId; - private final String yAxisAttributeId; - - DensityPlotParameters(Builder builder) { - this.xAxisBinCount = builder.xAxisBinCount; - this.yAxisBinCount = builder.yAxisBinCount; - this.xAxisStart = builder.xAxisStart; - this.xAxisEnd = builder.xAxisEnd; - this.yAxisStart = builder.yAxisStart; - this.yAxisEnd = builder.yAxisEnd; - this.xAxisAttributeId = builder.xAxisAttributeId; - this.yAxisAttributeId = builder.yAxisAttributeId; - this.xAxisLogScale = builder.xAxisLogScale; - this.yAxisLogScale = builder.yAxisLogScale; - } - - public Integer getXAxisBinCount() { - return xAxisBinCount; - } - public Integer getYAxisBinCount() { - return yAxisBinCount; - } - public BigDecimal getXAxisStart() { - return xAxisStart; - } - public BigDecimal getXAxisEnd() { - return xAxisEnd; - } - public BigDecimal getYAxisStart() { - return yAxisStart; - } - public BigDecimal getYAxisEnd() { - return yAxisEnd; - } - public Boolean getXAxisLogScale() { - return xAxisLogScale; - } - public Boolean getYAxisLogScale() { - return yAxisLogScale; - } - public String getXAxisAttributeId() { - return xAxisAttributeId; - } - public String getYAxisAttributeId() { - return yAxisAttributeId; - } - - public static class Builder { - private Integer xAxisBinCount; - private Integer yAxisBinCount; - private BigDecimal xAxisStart; - private BigDecimal xAxisEnd; - private BigDecimal yAxisStart; - private BigDecimal yAxisEnd; - private Boolean xAxisLogScale; - private Boolean yAxisLogScale; - private String xAxisAttributeId; - private String yAxisAttributeId; - - public Builder xAxisBinCount(Integer xAxisBinCount) { - this.xAxisBinCount = xAxisBinCount; - return this; - } - public Builder yAxisBinCount(Integer yAxisBinCount) { - this.yAxisBinCount = yAxisBinCount; - return this; - } - public Builder xAxisStart(BigDecimal xAxisStart) { - this.xAxisStart = xAxisStart; - return this; - } - public Builder xAxisEnd(BigDecimal xAxisEnd) { - this.xAxisEnd = xAxisEnd; - return this; - } - public Builder yAxisStart(BigDecimal yAxisStart) { - this.yAxisStart = yAxisStart; - return this; - } - public Builder yAxisEnd(BigDecimal yAxisEnd) { - this.yAxisEnd = yAxisEnd; - return this; - } - public Builder xAxisLogScale(Boolean xAxisLogScale) { - this.xAxisLogScale = xAxisLogScale; - return this; - } - public Builder yAxisLogScale(Boolean yAxisLogScale) { - this.yAxisLogScale = yAxisLogScale; - return this; - } - public Builder xAxisAttributeId(String xAxisAttributeId) { - this.xAxisAttributeId = xAxisAttributeId; - return this; - } - public Builder yAxisAttributeId(String yAxisAttributeId) { - this.yAxisAttributeId = yAxisAttributeId; - return this; - } - public DensityPlotParameters build() { - return new DensityPlotParameters(this); - - } - } -} diff --git a/src/main/java/org/cbioportal/web/util/DiscreteDataBinner.java b/src/main/java/org/cbioportal/web/util/DiscreteDataBinner.java deleted file mode 100644 index d6eaf334f82..00000000000 --- a/src/main/java/org/cbioportal/web/util/DiscreteDataBinner.java +++ /dev/null @@ -1,38 +0,0 @@ -package org.cbioportal.web.util; - -import org.cbioportal.model.DataBin; -import org.springframework.stereotype.Component; - -import java.math.BigDecimal; -import java.util.List; -import java.util.Set; -import java.util.stream.Collectors; - -@Component -public class DiscreteDataBinner { - - public List calculateDataBins(List values, - Set uniqueValues) { - List dataBins = initDataBins(uniqueValues); - - DataBinHelper.calcCounts(dataBins, values); - - return dataBins; - } - - public List initDataBins(Set uniqueValues) { - return uniqueValues.stream() - .map(d -> { - DataBin dataBin = new DataBin(); - - dataBin.setCount(0); - - // set both start and end to the same value - dataBin.setStart(d); - dataBin.setEnd(d); - - return dataBin; - }) - .collect(Collectors.toList()); - } -} diff --git a/src/main/java/org/cbioportal/web/util/GoogleAnalyticsInterceptor.java b/src/main/java/org/cbioportal/web/util/GoogleAnalyticsInterceptor.java deleted file mode 100644 index 540e8f2ab79..00000000000 --- a/src/main/java/org/cbioportal/web/util/GoogleAnalyticsInterceptor.java +++ /dev/null @@ -1,117 +0,0 @@ -package org.cbioportal.web.util; - -import java.util.Arrays; -import java.util.concurrent.CompletableFuture; - -import jakarta.annotation.PostConstruct; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; -import org.springframework.http.*; -import org.springframework.stereotype.Component; -import org.springframework.util.LinkedMultiValueMap; -import org.springframework.web.client.RestClientException; -import org.springframework.web.client.RestTemplate; -import org.springframework.web.servlet.HandlerInterceptor; - -// TODO: Double check, needed to convert HandlerInterceptorAdapter to HandlerInterceptor -@Component -@ConditionalOnExpression("!'${google.analytics.tracking.code.api:}'.isEmpty() || !'${google.analytics.application.client.id:}'.isEmpty()") -public class GoogleAnalyticsInterceptor implements HandlerInterceptor { - - private static final Logger LOG = LoggerFactory.getLogger(GoogleAnalyticsInterceptor.class); - - @Value("${google.analytics.tracking.code.api:}") - private String trackingId; - - @Value("${google.analytics.application.client.id:}") - private String clientId; - - private static HttpHeaders defaultHeaders; - private static LinkedMultiValueMap globalURIVariables; - private boolean missingGoogleAnalyticsCredentials; - - @PostConstruct - private void initializeDefaultParams() { - - missingGoogleAnalyticsCredentials = trackingId.isEmpty() || clientId.isEmpty(); - if (missingGoogleAnalyticsCredentials) { - if (LOG.isInfoEnabled()) { - LOG.info("@PostContruct:"); - LOG.info("Google Analytics tracking id: {}", trackingId); - LOG.info("Google Analytics client id: {}", clientId); - } - return; - } - - defaultHeaders = new HttpHeaders(); - defaultHeaders.setAccept(Arrays.asList(MediaType.ALL)); - defaultHeaders.setContentType(MediaType.APPLICATION_FORM_URLENCODED); - defaultHeaders.set(HttpHeaders.USER_AGENT, "cBioPortal API Reporting/1.0 via org.cbioportal.web.util.GoogleAnalyticsInterceptor"); - - globalURIVariables = new LinkedMultiValueMap<>(); - globalURIVariables.add("v", "1"); - globalURIVariables.add("dt", "request logged by GoogleAnalyticsInterceptor"); - globalURIVariables.add("t", "pageview"); - globalURIVariables.add("tid", trackingId); - globalURIVariables.add("cid", clientId); - globalURIVariables.add("dh", "cbioportal.org"); - } - - @Override - public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) { - - if (invalidAfterCompletionArgs(response)) { - return; - } - - CompletableFuture.runAsync(() -> { - LinkedMultiValueMap thisTasksURIVariables = new LinkedMultiValueMap<>(); - thisTasksURIVariables.putAll(globalURIVariables); - thisTasksURIVariables.add("dp", request.getRequestURI()); - HttpEntity> requestEntity = - new HttpEntity<>(thisTasksURIVariables, defaultHeaders); - try { - RestTemplate restTemplate = new RestTemplate(); - ResponseEntity responseEntity = - restTemplate.exchange("https://www.google-analytics.com/collect", HttpMethod.POST, requestEntity, String.class); - HttpStatusCode responseStatus = responseEntity.getStatusCode(); - if (responseStatus.is2xxSuccessful()) { - if (LOG.isInfoEnabled()) { - LOG.info("CompletableFuture.runAsync(): POST request successfully sent to Google Analytics: "); - LOG.info(requestEntity.toString()); - } - } - else { - if (LOG.isInfoEnabled()) { - LOG.info("CompletableFuture.runAsync(): POST request to Google Analytics failed. HTTP status code: " - + Integer.toString(responseStatus.value())); - } - } - } - catch(RestClientException e) { - e.printStackTrace(); - } - }); - } - - // TODO I think this bean should not be created when no Google analytics are configured. - private boolean invalidAfterCompletionArgs(HttpServletResponse response) { - if (missingGoogleAnalyticsCredentials || response.getHeader("referer") != null) { - if (LOG.isInfoEnabled()) { - LOG.info("afterCompletion() cannot be completed:"); - if (missingGoogleAnalyticsCredentials) { - LOG.info("Invalid Google Analytics credentials (see @PostConstruct log entry)"); - } - else { - LOG.info("Response referer is not null"); - } - } - return true; - } - return false; - } -} diff --git a/src/main/java/org/cbioportal/web/util/GzippedInputStreamRequestWrapper.java b/src/main/java/org/cbioportal/web/util/GzippedInputStreamRequestWrapper.java deleted file mode 100644 index 2d8b4bc9b90..00000000000 --- a/src/main/java/org/cbioportal/web/util/GzippedInputStreamRequestWrapper.java +++ /dev/null @@ -1,100 +0,0 @@ -package org.cbioportal.web.util; - -import jakarta.servlet.ReadListener; -import jakarta.servlet.ServletInputStream; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletRequestWrapper; - -import java.io.*; -import java.util.zip.GZIPInputStream; - -public class GzippedInputStreamRequestWrapper extends HttpServletRequestWrapper { - public static final int BUFFER_SIZE = 1024; - private final ByteArrayInputStream inputStream; - - GzippedInputStreamRequestWrapper(final HttpServletRequest request, int maxInflatedRequestBodySize) throws IOException { - super(request); - inputStream = inflate(request.getInputStream(), maxInflatedRequestBodySize); - } - - @Override - public ServletInputStream getInputStream() throws IOException { - return new ServletInputStream() { - @Override - public int read() { - return inputStream.read(); - } - - @Override - public int readLine(byte[] b, int off, int len) throws IOException { - return super.readLine(b, off, len); - } - - @Override - public boolean isFinished() { - return true; - } - - @Override - public boolean isReady() { - return false; - } - - @Override - public void setReadListener(ReadListener readListener) { - - } - - @Override - public int read(byte[] bytes) throws IOException { - return super.read(bytes); - } - - @Override - public int read(byte[] bytes, int i, int i1) throws IOException { - return super.read(bytes, i, i1); - } - - @Override - public void close() throws IOException { - super.close(); - inputStream.close(); - } - }; - } - - @Override - public BufferedReader getReader() throws IOException { - return new BufferedReader(new InputStreamReader(getInputStream())); - } - - /** - * Inflates the compressed input stream all at once. Previously, we wrapped the compressed ServletInputStream - * stream with a GZIPInputStream, and read from that gradually. For some reason, that approach resulted in - * very long inflation times. By reading out everything from the GZIPInputStream here in the constructor, we - * managed to get down to the sub second performance you would expect with gzipping. - */ - private ByteArrayInputStream inflate(ServletInputStream requestStream, int maxInflatedRequestBodySize) throws IOException { - GZIPInputStream gzipInputStream = new GZIPInputStream(requestStream, BUFFER_SIZE); - ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); - byte[] buffer = new byte[BUFFER_SIZE]; - int len; - long byteCount = 0; - - while((len = gzipInputStream.read(buffer)) > 0) { - outputStream.write(buffer, 0, len); - byteCount += BUFFER_SIZE; - - if (byteCount > maxInflatedRequestBodySize) { - throw new IOException( - "Inflated request body too large (> " - + maxInflatedRequestBodySize - + " bytes)" - ); - } - } - - return new ByteArrayInputStream(outputStream.toByteArray()); - } - -} \ No newline at end of file diff --git a/src/main/java/org/cbioportal/web/util/HttpRequestUtils.java b/src/main/java/org/cbioportal/web/util/HttpRequestUtils.java deleted file mode 100644 index 325a5cf35bf..00000000000 --- a/src/main/java/org/cbioportal/web/util/HttpRequestUtils.java +++ /dev/null @@ -1,33 +0,0 @@ -package org.cbioportal.web.util; - -import java.util.Enumeration; - -import jakarta.servlet.http.HttpServletRequest; -import org.json.simple.JSONObject; -import org.springframework.stereotype.Component; - -@Component -public class HttpRequestUtils { - - public JSONObject getPostData(HttpServletRequest request) { - // To support posted query data (when data would exceed URL length), - // write all post params to json on page where it can be consumed. - JSONObject paramsJson = new JSONObject(); - if (request.getMethod().equals("POST")) { - Enumeration parameterNames = request.getParameterNames(); - while (parameterNames.hasMoreElements()) { - String parameterName = parameterNames.nextElement(); - paramsJson.put(parameterName, request.getParameter(parameterName)); - } - } - return paramsJson; - } - - public String getBaseUrl(HttpServletRequest request) { - String currentUrl = request.getRequestURL().toString(); - String contextPath = request.getContextPath(); - String baseURL = currentUrl.substring(0, currentUrl.length() - request.getRequestURI().length()) + contextPath; - return baseURL.replaceAll("https?://", ""); - } - -} diff --git a/src/main/java/org/cbioportal/web/util/IdPopulator.java b/src/main/java/org/cbioportal/web/util/IdPopulator.java deleted file mode 100644 index e7c02227bdf..00000000000 --- a/src/main/java/org/cbioportal/web/util/IdPopulator.java +++ /dev/null @@ -1,66 +0,0 @@ -package org.cbioportal.web.util; - -import org.cbioportal.model.ClinicalAttribute; -import org.cbioportal.service.PatientService; -import org.cbioportal.service.util.ClinicalAttributeUtil; -import org.cbioportal.web.parameter.SampleIdentifier; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -import java.util.List; - -@Component -public class IdPopulator { - - @Autowired - private ClinicalAttributeUtil clinicalAttributeUtil; - @Autowired - private StudyViewFilterApplier studyViewFilterApplier; - @Autowired - private StudyViewFilterUtil studyViewFilterUtil; - @Autowired - private PatientService patientService; - - public IdPopulator() {} - - public BinningIds populateIdLists( - List samples, - List clinicalAttributes - ) { - BinningIds binningIds = new BinningIds(); - List studyIds = binningIds.getStudyIds(); - List sampleIds = binningIds.getSampleIds(); - List patientIds = binningIds.getPatientIds(); - List studyIdsOfPatients = binningIds.getStudyIdsOfPatients(); - List uniqueSampleKeys = binningIds.getUniqueSampleKeys(); - List uniquePatientKeys = binningIds.getUniquePatientKeys(); - List sampleAttributeIds = binningIds.getSampleAttributeIds(); - List patientAttributeIds = binningIds.getPatientAttributeIds(); - List conflictingPatientAttributeIds = binningIds.getConflictingPatientAttributeIds(); - - studyViewFilterUtil.extractStudyAndSampleIds( - samples, - studyIds, - sampleIds - ); - - patientService.getPatientsOfSamples(studyIds, sampleIds).forEach(patient -> { - patientIds.add(patient.getStableId()); - studyIdsOfPatients.add(patient.getCancerStudyIdentifier()); - }); - - uniqueSampleKeys.addAll(studyViewFilterApplier.getUniqkeyKeys(studyIds, sampleIds)); - uniquePatientKeys.addAll(studyViewFilterApplier.getUniqkeyKeys(studyIdsOfPatients, patientIds)); - - if (clinicalAttributes != null && !clinicalAttributes.isEmpty()) { - clinicalAttributeUtil.extractCategorizedClinicalAttributes( - clinicalAttributes, - sampleAttributeIds, - patientAttributeIds, - conflictingPatientAttributeIds - ); - } - return binningIds; - } - -} diff --git a/src/main/java/org/cbioportal/web/util/InvolvedCancerStudyExtractorInterceptor.java b/src/main/java/org/cbioportal/web/util/InvolvedCancerStudyExtractorInterceptor.java deleted file mode 100644 index e0ee3961f71..00000000000 --- a/src/main/java/org/cbioportal/web/util/InvolvedCancerStudyExtractorInterceptor.java +++ /dev/null @@ -1,888 +0,0 @@ -/* - * Copyright (c) 2019 Memorial Sloan-Kettering Cancer Center. - * - * This library is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS - * FOR A PARTICULAR PURPOSE. The software and documentation provided hereunder - * is on an "as is" basis, and Memorial Sloan-Kettering Cancer Center has no - * obligations to provide maintenance, support, updates, enhancements or - * modifications. In no event shall Memorial Sloan-Kettering Cancer Center be - * liable to any party for direct, indirect, special, incidental or - * consequential damages, including lost profits, arising out of the use of this - * software and its documentation, even if Memorial Sloan-Kettering Cancer - * Center has been advised of the possibility of such damage. - */ - -/* - * This file is part of cBioPortal. - * - * cBioPortal is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -package org.cbioportal.web.util; - -import com.fasterxml.jackson.databind.ObjectMapper; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; -import org.apache.commons.lang3.StringUtils; -import org.cbioportal.model.AlterationFilter; -import org.cbioportal.model.MolecularProfile; -import org.cbioportal.model.MolecularProfileCaseIdentifier; -import org.cbioportal.model.SampleList; -import org.cbioportal.persistence.cachemaputil.CacheMapUtil; -import org.cbioportal.web.parameter.ClinicalAttributeCountFilter; -import org.cbioportal.web.parameter.ClinicalDataBinCountFilter; -import org.cbioportal.web.parameter.ClinicalDataCountFilter; -import org.cbioportal.web.parameter.ClinicalDataIdentifier; -import org.cbioportal.web.parameter.ClinicalDataMultiStudyFilter; -import org.cbioportal.web.parameter.ClinicalEventAttributeRequest; -import org.cbioportal.web.parameter.GenePanelDataMultipleStudyFilter; -import org.cbioportal.web.parameter.GenericAssayDataBinCountFilter; -import org.cbioportal.web.parameter.GenericAssayDataCountFilter; -import org.cbioportal.web.parameter.GenericAssayDataMultipleStudyFilter; -import org.cbioportal.web.parameter.GenomicDataBinCountFilter; -import org.cbioportal.web.parameter.GenomicDataCountFilter; -import org.cbioportal.web.parameter.GroupFilter; -import org.cbioportal.web.parameter.MolecularDataMultipleStudyFilter; -import org.cbioportal.web.parameter.MolecularProfileCasesGroupAndAlterationTypeFilter; -import org.cbioportal.web.parameter.MolecularProfileCasesGroupFilter; -import org.cbioportal.web.parameter.MolecularProfileFilter; -import org.cbioportal.web.parameter.MutationMultipleStudyFilter; -import org.cbioportal.web.parameter.PatientFilter; -import org.cbioportal.web.parameter.PatientIdentifier; -import org.cbioportal.web.parameter.SampleFilter; -import org.cbioportal.web.parameter.SampleIdentifier; -import org.cbioportal.web.parameter.SampleMolecularIdentifier; -import org.cbioportal.web.parameter.StructuralVariantFilter; -import org.cbioportal.web.parameter.StudyViewFilter; -import org.cbioportal.web.parameter.SurvivalRequest; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.web.servlet.HandlerInterceptor; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import java.util.stream.Collectors; - -public class InvolvedCancerStudyExtractorInterceptor implements HandlerInterceptor { - - private ObjectMapper objectMapper = new ObjectMapper(); - - @Autowired - private CacheMapUtil cacheMapUtil; - - private static final Logger LOG = LoggerFactory.getLogger(InvolvedCancerStudyExtractorInterceptor.class); - public static final String PATIENT_FETCH_PATH = "/patients/fetch"; - public static final String SAMPLE_FETCH_PATH = "/samples/fetch"; - public static final String MOLECULAR_PROFILE_FETCH_PATH = "/molecular-profiles/fetch"; - public static final String CLINICAL_ATTRIBUTE_COUNT_FETCH_PATH = "/clinical-attributes/counts/fetch"; - public static final String CLINICAL_DATA_FETCH_PATH = "/clinical-data/fetch"; - public static final String GENE_PANEL_DATA_FETCH_PATH = "/gene-panel-data/fetch"; - public static final String MOLECULAR_DATA_MULTIPLE_STUDY_FETCH_PATH = "/molecular-data/fetch"; - public static final String MUTATION_MULTIPLE_STUDY_FETCH_PATH = "/mutations/fetch"; - public static final String COPY_NUMBER_SEG_FETCH_PATH = "/copy-number-segments/fetch"; - public static final String STUDY_VIEW_CLINICAL_DATA_BIN_COUNTS_PATH = "/clinical-data-bin-counts/fetch"; - public static final String STUDY_VIEW_CUSTOM_DATA_BIN_COUNTS_PATH = "/custom-data-bin-counts/fetch"; - public static final String STUDY_VIEW_GENOMICL_DATA_BIN_COUNTS_PATH = "/genomic-data-bin-counts/fetch"; - public static final String STUDY_VIEW_GENOMICL_DATA_COUNTS_PATH = "/genomic-data-counts/fetch"; - public static final String STUDY_VIEW_MUTATION_DATA_COUNTS_PATH = "/mutation-data-counts/fetch"; - public static final String STUDY_VIEW_GENERIC_ASSAY_DATA_BIN_COUNTS_PATH = "/generic-assay-data-bin-counts/fetch"; - public static final String STUDY_VIEW_GENERIC_ASSAY_DATA_COUNTS_PATH = "/generic-assay-data-counts/fetch"; - public static final String STUDY_VIEW_CLINICAL_DATA_COUNTS_PATH = "/clinical-data-counts/fetch"; - public static final String STUDY_VIEW_CUSTOM_DATA_COUNTS_PATH = "/custom-data-counts/fetch"; - public static final String STUDY_VIEW_CLINICAL_DATA_DENSITY_PATH = "/clinical-data-density-plot/fetch"; - public static final String STUDY_VIEW_CLINICAL_DATA_VIOLIN_PATH = "/clinical-data-violin-plots/fetch"; - public static final String STUDY_VIEW_CNA_GENES = "/cna-genes/fetch"; - public static final String STUDY_VIEW_FILTERED_SAMPLES = "/filtered-samples/fetch"; - public static final String STUDY_VIEW_MUTATED_GENES = "/mutated-genes/fetch"; - public static final String STUDY_VIEW_STRUCTURAL_VARIANT_GENES = "/structuralvariant-genes/fetch"; - public static final String STUDY_VIEW_STRUCTURAL_VARIANT_COUNTS = "/structuralvariant-counts/fetch"; - public static final String STUDY_VIEW_SAMPLE_COUNTS = "/sample-counts/fetch"; - public static final String STUDY_VIEW_SAMPLE_LIST_COUNTS_PATH = "/sample-lists-counts/fetch"; - public static final String STUDY_VIEW_CLINICAL_TABLE_DATA_FETCH_PATH = "/clinical-data-table/fetch"; - public static final String STUDY_VIEW_PROFILE_SAMPLE_COUNTS_PATH = "/molecular-profile-sample-counts/fetch"; - public static final String CLINICAL_DATA_ENRICHMENT_FETCH_PATH = "/clinical-data-enrichments/fetch"; - public static final String MUTATION_ENRICHMENT_FETCH_PATH = "/mutation-enrichments/fetch"; - public static final String COPY_NUMBER_ENRICHMENT_FETCH_PATH = "/copy-number-enrichments/fetch"; - public static final String EXPRESSION_ENRICHMENT_FETCH_PATH = "/expression-enrichments/fetch"; - public static final String ALTERATION_ENRICHMENT_FETCH_PATH = "/alteration-enrichments/fetch"; - public static final String TREATMENT_FETCH_PATH = "/treatments/fetch"; - public static final String STRUCTURAL_VARIANT_FETCH_PATH = "/structural-variant/fetch"; - public static final String GENERIC_ASSAY_DATA_MULTIPLE_STUDY_FETCH_PATH = "/generic_assay_data/fetch"; - public static final String TREATMENTS_PATIENT_PATH = "/treatments/patient"; - public static final String TREATMENTS_SAMPLE_PATH = "/treatments/sample"; - public static final String GENERIC_ASSAY_ENRICHMENT_FETCH_PATH = "/generic-assay-enrichments/fetch"; - public static final String GENERIC_ASSAY_CATEGORICAL_ENRICHMENT_FETCH_PATH = "/generic-assay-categorical-enrichments/fetch"; - public static final String GENERIC_ASSAY_BINARY_ENRICHMENT_FETCH_PATH = "/generic-assay-binary-enrichments/fetch"; - public static final String CLINICAL_EVENT_TYPE_COUNT_FETCH_PATH = "/clinical-event-type-counts/fetch"; - public static final String SURVIVAL_DATA_FETCH_PATH = "/survival-data/fetch"; - public static final String CLINICAL_EVENT_META_FETCH_PATH = "/clinical-events-meta/fetch"; - public static final String TREATMENTS_PATIENT_COUNT_FETCH_PATH = "/treatments/patient-counts/fetch"; - public static final String TREATMENTS_SAMPLE_COUNT_FETCH_PATH = "/treatments/sample-counts/fetch"; - - @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) { - if (!request.getMethod().equals("POST")) { - return true; // no attribute extraction needed because all user supplied filter objects are in POST requests - } - // TODO when reimplemeting different dispatcherservlets with different context roots - // reset this to 'String requestPathInfo = request.getPathInfo();' - String requestPathInfo = request.getPathInfo() == null? request.getServletPath() : request.getPathInfo(); - requestPathInfo = requestPathInfo.replaceFirst("^/api", ""); - requestPathInfo = StringUtils.removeStart(requestPathInfo, "/column-store"); - if (requestPathInfo.equals(PATIENT_FETCH_PATH)) { - return extractAttributesFromPatientFilter(request); - } else if (requestPathInfo.equals(SAMPLE_FETCH_PATH)) { - return extractAttributesFromSampleFilter(request); - } else if (requestPathInfo.equals(MOLECULAR_PROFILE_FETCH_PATH)) { - return extractAttributesFromMolecularProfileFilter(request); - } else if (requestPathInfo.equals(CLINICAL_ATTRIBUTE_COUNT_FETCH_PATH)) { - return extractAttributesFromClinicalAttributeCountFilter(request); - } else if (requestPathInfo.equals(CLINICAL_DATA_FETCH_PATH)) { - return extractAttributesFromClinicalDataMultiStudyFilter(request); - } else if (requestPathInfo.equals(GENE_PANEL_DATA_FETCH_PATH)) { - return extractAttributesFromGenePanelDataMultipleStudyFilter(request); - } else if (requestPathInfo.equals(MOLECULAR_DATA_MULTIPLE_STUDY_FETCH_PATH)) { - return extractAttributesFromMolecularDataMultipleStudyFilter(request); - } else if (requestPathInfo.equals(MUTATION_MULTIPLE_STUDY_FETCH_PATH)) { - return extractAttributesFromMutationMultipleStudyFilter(request); - } else if (requestPathInfo.equals(COPY_NUMBER_SEG_FETCH_PATH)) { - return extractAttributesFromSampleIdentifiers(request); - } else if (Arrays.asList(STUDY_VIEW_CLINICAL_DATA_BIN_COUNTS_PATH, STUDY_VIEW_CUSTOM_DATA_BIN_COUNTS_PATH).contains(requestPathInfo)) { - return extractAttributesFromClinicalDataBinCountFilter(request); - } else if (requestPathInfo.equals(STUDY_VIEW_GENOMICL_DATA_BIN_COUNTS_PATH)) { - return extractAttributesFromGenomicDataBinCountFilter(request); - } else if (Arrays.asList(STUDY_VIEW_GENOMICL_DATA_COUNTS_PATH, STUDY_VIEW_MUTATION_DATA_COUNTS_PATH).contains(requestPathInfo)) { - return extractAttributesFromGenomicDataCountFilter(request); - } else if (requestPathInfo.equals(STUDY_VIEW_GENERIC_ASSAY_DATA_BIN_COUNTS_PATH)) { - return extractAttributesFromGenericAssayDataBinCountFilter(request); - } else if (requestPathInfo.equals(STUDY_VIEW_GENERIC_ASSAY_DATA_COUNTS_PATH)) { - return extractAttributesFromGenericAssayDataCountFilter(request); - } else if (Arrays.asList(STUDY_VIEW_CLINICAL_DATA_COUNTS_PATH, STUDY_VIEW_CUSTOM_DATA_COUNTS_PATH) - .contains(requestPathInfo)) { - return extractAttributesFromClinicalDataCountFilter(request); - } else if (Arrays.asList(STUDY_VIEW_CLINICAL_DATA_DENSITY_PATH, STUDY_VIEW_CLINICAL_DATA_VIOLIN_PATH, STUDY_VIEW_CNA_GENES, - STUDY_VIEW_FILTERED_SAMPLES, STUDY_VIEW_MUTATED_GENES, STUDY_VIEW_STRUCTURAL_VARIANT_GENES, - STUDY_VIEW_STRUCTURAL_VARIANT_COUNTS, STUDY_VIEW_SAMPLE_COUNTS, STUDY_VIEW_SAMPLE_LIST_COUNTS_PATH, STUDY_VIEW_CLINICAL_TABLE_DATA_FETCH_PATH, - TREATMENTS_PATIENT_PATH, TREATMENTS_SAMPLE_PATH, STUDY_VIEW_PROFILE_SAMPLE_COUNTS_PATH, CLINICAL_EVENT_TYPE_COUNT_FETCH_PATH, - TREATMENTS_PATIENT_COUNT_FETCH_PATH, TREATMENTS_SAMPLE_COUNT_FETCH_PATH - ).contains(requestPathInfo)) { - return extractAttributesFromStudyViewFilter(request); - } else if (requestPathInfo.equals(CLINICAL_DATA_ENRICHMENT_FETCH_PATH)) { - return extractAttributesFromGroupFilter(request); - } else if (requestPathInfo.equals(MUTATION_ENRICHMENT_FETCH_PATH) || - requestPathInfo.equals(COPY_NUMBER_ENRICHMENT_FETCH_PATH) || - requestPathInfo.equals(EXPRESSION_ENRICHMENT_FETCH_PATH) || - requestPathInfo.equals(GENERIC_ASSAY_ENRICHMENT_FETCH_PATH) || - requestPathInfo.equals(GENERIC_ASSAY_CATEGORICAL_ENRICHMENT_FETCH_PATH) || - requestPathInfo.equals(GENERIC_ASSAY_BINARY_ENRICHMENT_FETCH_PATH)) { - return extractAttributesFromMolecularProfileCasesGroups(request); - } else if (requestPathInfo.equals(ALTERATION_ENRICHMENT_FETCH_PATH)) { - return extractAttributesFromMolecularProfileCasesGroupsAndAlterationTypes(request); - } else if (requestPathInfo.equals(STRUCTURAL_VARIANT_FETCH_PATH)) { - return extractAttributesFromStructuralVariantFilter(request); - } else if (requestPathInfo.equals(GENERIC_ASSAY_DATA_MULTIPLE_STUDY_FETCH_PATH)) { - return extractAttributesFromGenericAssayDataMultipleStudyFilter(request); - } else if (requestPathInfo.equals(SURVIVAL_DATA_FETCH_PATH)) { - return extractCancerStudyIdsFromSurvivalRequest(request); - } else if (requestPathInfo.equals(CLINICAL_EVENT_META_FETCH_PATH)) { - return extractCancerStudyIdsFromClinicalEventAttributeRequest(request); - } - return true; - } - - private boolean extractAttributesFromPatientFilter(HttpServletRequest request) { - try { - PatientFilter patientFilter = objectMapper.readValue(request.getInputStream(), PatientFilter.class); - LOG.debug("extracted patientFilter: {}", patientFilter); - LOG.debug("setting interceptedPatientFilter to {}", patientFilter); - request.setAttribute("interceptedPatientFilter", patientFilter); - if (cacheMapUtil.hasCacheEnabled()) { - Collection cancerStudyIdCollection = extractCancerStudyIdsFromPatientFilter(patientFilter); - LOG.debug("setting involvedCancerStudies to {}", cancerStudyIdCollection); - request.setAttribute("involvedCancerStudies", cancerStudyIdCollection); - } - } catch (Exception e) { - LOG.error("exception thrown during extraction of patientFilter: {}", e.getMessage()); - return false; - } - return true; - } - - private Collection extractCancerStudyIdsFromPatientFilter(PatientFilter patientFilter) { - // use hashset as the study list in the patientFilter will usually be populated with many duplicate values - Set studyIdSet = new HashSet<>(); - if (patientFilter.getPatientIdentifiers() != null) { - for (PatientIdentifier patientIdentifier : patientFilter.getPatientIdentifiers()) { - studyIdSet.add(patientIdentifier.getStudyId()); - } - } else { - UniqueKeyExtractor.extractUniqueKeys(patientFilter.getUniquePatientKeys(), studyIdSet); - } - return studyIdSet; - } - - private boolean extractAttributesFromSampleFilter(HttpServletRequest request) { - try { - SampleFilter sampleFilter = objectMapper.readValue(request.getInputStream(), SampleFilter.class); - LOG.debug("extracted sampleFilter: {}", sampleFilter); - LOG.debug("setting interceptedSampleFilter to {}", sampleFilter); - request.setAttribute("interceptedSampleFilter", sampleFilter); - if (cacheMapUtil.hasCacheEnabled()) { - Collection cancerStudyIdCollection = extractCancerStudyIdsFromSampleFilter(sampleFilter); - LOG.debug("setting involvedCancerStudies to {}", cancerStudyIdCollection); - request.setAttribute("involvedCancerStudies", cancerStudyIdCollection); - } - } catch (Exception e) { - LOG.error("exception thrown during extraction of sampleFilter: {}", e.getMessage()); - return false; - } - return true; - } - - private Collection extractCancerStudyIdsFromSampleFilter(SampleFilter sampleFilter) { - // use hashset as the study list in the sampleFilter will usually be populated with many duplicate values - Set studyIdSet = new HashSet<>(); - if (sampleFilter.getSampleListIds() != null) { - extractCancerStudyIdsFromSampleListIds(sampleFilter.getSampleListIds(), studyIdSet); - } else if (sampleFilter.getSampleIdentifiers() != null) { - extractCancerStudyIdsFromSampleIdentifiers(sampleFilter.getSampleIdentifiers(), studyIdSet); - } else { - UniqueKeyExtractor.extractUniqueKeys(sampleFilter.getUniqueSampleKeys(), studyIdSet); - } - return studyIdSet; - } - - private boolean extractAttributesFromMolecularProfileFilter(HttpServletRequest request) { - try { - MolecularProfileFilter molecularProfileFilter = objectMapper.readValue(request.getInputStream(), MolecularProfileFilter.class); - LOG.debug("extracted molecularProfileFilter: {}", molecularProfileFilter); - LOG.debug("setting interceptedMolecularProfileFilter to {}", molecularProfileFilter); - request.setAttribute("interceptedMolecularProfileFilter", molecularProfileFilter); - if (cacheMapUtil.hasCacheEnabled()) { - Collection cancerStudyIdCollection = extractCancerStudyIdsFromMolecularProfileFilter(molecularProfileFilter); - LOG.debug("setting involvedCancerStudies to {}", cancerStudyIdCollection); - request.setAttribute("involvedCancerStudies", cancerStudyIdCollection); - } - } catch (Exception e) { - LOG.error("exception thrown during extraction of molecularProfileFilter: {}", e.getMessage()); - return false; - } - return true; - } - - private Collection extractCancerStudyIdsFromMolecularProfileFilter(MolecularProfileFilter molecularProfileFilter) { - // use hashset as the study list in the molecularProfileFilter may be populated with many duplicate values - Set studyIdSet = new HashSet<>(); - if (molecularProfileFilter.getStudyIds() != null) { - studyIdSet.addAll(molecularProfileFilter.getStudyIds()); - } else { - extractCancerStudyIdsFromMolecularProfileIds(molecularProfileFilter.getMolecularProfileIds(), studyIdSet); - } - return studyIdSet; - } - - private boolean extractAttributesFromClinicalAttributeCountFilter(HttpServletRequest request) { - try { - ClinicalAttributeCountFilter clinicalAttributeCountFilter = objectMapper.readValue(request.getInputStream(), ClinicalAttributeCountFilter.class); - LOG.debug("extracted clinicalAttributeCountFilter: {}", clinicalAttributeCountFilter); - LOG.debug("setting interceptedClinicalAttributeCountFilter to {}", clinicalAttributeCountFilter); - request.setAttribute("interceptedClinicalAttributeCountFilter", clinicalAttributeCountFilter); - if (cacheMapUtil.hasCacheEnabled()) { - Collection cancerStudyIdCollection = extractCancerStudyIdsFromClinicalAttributeCountFilter(clinicalAttributeCountFilter); - LOG.debug("setting involvedCancerStudies to {}", cancerStudyIdCollection); - request.setAttribute("involvedCancerStudies", cancerStudyIdCollection); - } - } catch (Exception e) { - LOG.error("exception thrown during extraction of clinicalAttributeCountFilter: {}", e.getMessage()); - return false; - } - return true; - } - - private Collection extractCancerStudyIdsFromClinicalAttributeCountFilter(ClinicalAttributeCountFilter clinicalAttributeCountFilter) { - // use hashset as the study list in the clinicalAttributeCountFilter may be populated with many duplicate values - Set studyIdSet = new HashSet<>(); - if (clinicalAttributeCountFilter.getSampleListId() != null) { - extractCancerStudyIdsFromSampleListIds(Collections.singletonList(clinicalAttributeCountFilter.getSampleListId()), studyIdSet); - } else { - extractCancerStudyIdsFromSampleIdentifiers(clinicalAttributeCountFilter.getSampleIdentifiers(), studyIdSet); - } - return studyIdSet; - } - - private boolean extractAttributesFromClinicalDataMultiStudyFilter(HttpServletRequest request) { - try { - ClinicalDataMultiStudyFilter clinicalDataMultiStudyFilter = objectMapper.readValue(request.getInputStream(), ClinicalDataMultiStudyFilter.class); - LOG.debug("extracted clinicalDataMultiStudyFilter: {}", clinicalDataMultiStudyFilter); - LOG.debug("setting interceptedClinicalDataMultiStudyFilter to {}", clinicalDataMultiStudyFilter); - request.setAttribute("interceptedClinicalDataMultiStudyFilter", clinicalDataMultiStudyFilter); - if (cacheMapUtil.hasCacheEnabled()) { - Collection cancerStudyIdCollection = extractCancerStudyIdsFromClinicalDataMultiStudyFilter(clinicalDataMultiStudyFilter); - LOG.debug("setting involvedCancerStudies to {}", cancerStudyIdCollection); - request.setAttribute("involvedCancerStudies", cancerStudyIdCollection); - } - } catch (Exception e) { - LOG.error("exception thrown during extraction of clinicalDataMultiStudyFilter: {}", e.getMessage()); - return false; - } - return true; - } - - private Collection extractCancerStudyIdsFromClinicalDataMultiStudyFilter(ClinicalDataMultiStudyFilter clinicalDataMultiStudyFilter) { - // use hashset as the study list in the clinicalDataMultiStudyFilter may be populated with many duplicate values - Set studyIdSet = new HashSet<>(); - for(ClinicalDataIdentifier clinicalDataIdentifier : clinicalDataMultiStudyFilter.getIdentifiers()) { - studyIdSet.add(clinicalDataIdentifier.getStudyId()); - } - return studyIdSet; - } - - private boolean extractAttributesFromGenePanelDataMultipleStudyFilter(HttpServletRequest request) { - try { - GenePanelDataMultipleStudyFilter genePanelDataMultipleStudyFilter = objectMapper.readValue(request.getInputStream(), GenePanelDataMultipleStudyFilter.class); - LOG.debug("extracted genePanelDataMultipleStudyFilter: {}", genePanelDataMultipleStudyFilter); - LOG.debug("setting interceptedGenePanelDataMultipleStudyFilter to {}", genePanelDataMultipleStudyFilter); - request.setAttribute("interceptedGenePanelDataMultipleStudyFilter", genePanelDataMultipleStudyFilter); - if (cacheMapUtil.hasCacheEnabled()) { - Collection cancerStudyIdCollection = extractCancerStudyIdsFromGenePanelDataMultipleStudyFilter(genePanelDataMultipleStudyFilter); - LOG.debug("setting involvedCancerStudies to {}", cancerStudyIdCollection); - request.setAttribute("involvedCancerStudies", cancerStudyIdCollection); - } - } catch (Exception e) { - LOG.error("exception thrown during extraction of genePanelSampleMolecularIdentifiers: {}", e.getMessage()); - return false; - } - return true; - } - - private Collection extractCancerStudyIdsFromGenePanelDataMultipleStudyFilter(GenePanelDataMultipleStudyFilter genePanelDataMultipleStudyFilter) { - Set studyIdSet = new HashSet<>(); - if (genePanelDataMultipleStudyFilter.getMolecularProfileIds() != null) { - extractCancerStudyIdsFromMolecularProfileIds(genePanelDataMultipleStudyFilter.getMolecularProfileIds(), studyIdSet); - } else { - extractCancerStudyIdsFromSampleMolecularIdentifiers(genePanelDataMultipleStudyFilter.getSampleMolecularIdentifiers(), studyIdSet); - } - return studyIdSet; - } - - private boolean extractAttributesFromMolecularDataMultipleStudyFilter(HttpServletRequest request) { - try { - MolecularDataMultipleStudyFilter molecularDataMultipleStudyFilter = objectMapper.readValue(request.getInputStream(), MolecularDataMultipleStudyFilter.class); - LOG.debug("extracted molecularDataMultipleStudyFilter: {}", molecularDataMultipleStudyFilter); - LOG.debug("setting interceptedMolecularDataMultipleStudyFilter to {}", molecularDataMultipleStudyFilter); - request.setAttribute("interceptedMolecularDataMultipleStudyFilter", molecularDataMultipleStudyFilter); - if (cacheMapUtil.hasCacheEnabled()) { - Collection cancerStudyIdCollection = extractCancerStudyIdsFromMolecularDataMultipleStudyFilter(molecularDataMultipleStudyFilter); - LOG.debug("setting involvedCancerStudies to {}", cancerStudyIdCollection); - request.setAttribute("involvedCancerStudies", cancerStudyIdCollection); - } - } catch (Exception e) { - LOG.error("exception thrown during extraction of molecularDataMultipleStudyFilter: {}", e.getMessage()); - return false; - } - return true; - } - - private Collection extractCancerStudyIdsFromMolecularDataMultipleStudyFilter(MolecularDataMultipleStudyFilter molecularDataMultipleStudyFilter) { - Set studyIdSet = new HashSet<>(); - if (molecularDataMultipleStudyFilter.getMolecularProfileIds() != null) { - extractCancerStudyIdsFromMolecularProfileIds(molecularDataMultipleStudyFilter.getMolecularProfileIds(), studyIdSet); - } else { - extractCancerStudyIdsFromSampleMolecularIdentifiers(molecularDataMultipleStudyFilter.getSampleMolecularIdentifiers(), studyIdSet); - } - return studyIdSet; - } - - private boolean extractAttributesFromGenericAssayDataMultipleStudyFilter(HttpServletRequest request) { - try { - GenericAssayDataMultipleStudyFilter genericAssayDataMultipleStudyFilter = objectMapper.readValue(request.getInputStream(), GenericAssayDataMultipleStudyFilter.class); - LOG.debug("extracted genericAssayDataMultipleStudyFilter: {}", genericAssayDataMultipleStudyFilter); - LOG.debug("setting interceptedGenericAssayDataMultipleStudyFilter to {}", genericAssayDataMultipleStudyFilter); - request.setAttribute("interceptedGenericAssayDataMultipleStudyFilter", genericAssayDataMultipleStudyFilter); - if (cacheMapUtil.hasCacheEnabled()) { - Collection cancerStudyIdCollection = extractCancerStudyIdsFromGenericAssayDataMultipleStudyFilter(genericAssayDataMultipleStudyFilter); - LOG.debug("setting involvedCancerStudies to {}", cancerStudyIdCollection); - request.setAttribute("involvedCancerStudies", cancerStudyIdCollection); - } - } catch (Exception e) { - LOG.error("exception thrown during extraction of genericAssayDataMultipleStudyFilter: {}", e.getMessage()); - return false; - } - return true; - } - - private Collection extractCancerStudyIdsFromGenericAssayDataMultipleStudyFilter(GenericAssayDataMultipleStudyFilter genericAssayDataMultipleStudyFilter) { - Set studyIdSet = new HashSet<>(); - if (genericAssayDataMultipleStudyFilter.getMolecularProfileIds() != null) { - extractCancerStudyIdsFromMolecularProfileIds(genericAssayDataMultipleStudyFilter.getMolecularProfileIds(), studyIdSet); - } else { - extractCancerStudyIdsFromSampleMolecularIdentifiers(genericAssayDataMultipleStudyFilter.getSampleMolecularIdentifiers(), studyIdSet); - } - return studyIdSet; - } - - private boolean extractAttributesFromMutationMultipleStudyFilter(HttpServletRequest request) { - try { - MutationMultipleStudyFilter mutationMultipleStudyFilter = objectMapper.readValue(request.getInputStream(), MutationMultipleStudyFilter.class); - LOG.debug("extracted mutationMultipleStudyFilter: {}", mutationMultipleStudyFilter); - LOG.debug("setting interceptedMutationMultipleStudyFilter to {}", mutationMultipleStudyFilter); - request.setAttribute("interceptedMutationMultipleStudyFilter", mutationMultipleStudyFilter); - if (cacheMapUtil.hasCacheEnabled()) { - Collection cancerStudyIdCollection = extractCancerStudyIdsFromMutationMultipleStudyFilter(mutationMultipleStudyFilter); - LOG.debug("setting involvedCancerStudies to {}", cancerStudyIdCollection); - request.setAttribute("involvedCancerStudies", cancerStudyIdCollection); - } - } catch (Exception e) { - LOG.error("exception thrown during extraction of mutationMultipleStudyFilter: {}", e.getMessage()); - return false; - } - return true; - } - - private Set extractCancerStudyIdsFromMutationMultipleStudyFilter(MutationMultipleStudyFilter mutationMultipleStudyFilter) { - Set studyIdSet = new HashSet<>(); - if (mutationMultipleStudyFilter.getMolecularProfileIds() != null) { - extractCancerStudyIdsFromMolecularProfileIds(mutationMultipleStudyFilter.getMolecularProfileIds(), studyIdSet); - } else { - extractCancerStudyIdsFromSampleMolecularIdentifiers(mutationMultipleStudyFilter.getSampleMolecularIdentifiers(), studyIdSet); - } - return studyIdSet; - } - - private boolean extractAttributesFromSampleIdentifiers(HttpServletRequest request) { - try { - List sampleIdentifiers = Arrays.asList(objectMapper.readValue(request.getInputStream(), SampleIdentifier[].class)); - LOG.debug("extracted sampleIdentifiers: {}", sampleIdentifiers); - LOG.debug("setting interceptedSampleIdentifiers to {}", sampleIdentifiers); - request.setAttribute("interceptedSampleIdentifiers", sampleIdentifiers); - if (cacheMapUtil.hasCacheEnabled()) { - Collection cancerStudyIdCollection = extractCancerStudyIdsFromSampleIdentifiers(sampleIdentifiers); - LOG.debug("setting involvedCancerStudies to {}", cancerStudyIdCollection); - request.setAttribute("involvedCancerStudies", cancerStudyIdCollection); - } - } catch (Exception e) { - LOG.error("exception thrown during extraction of sampleIdentifiers: {}", e.getMessage()); - return false; - } - return true; - } - - private boolean extractAttributesFromClinicalDataBinCountFilter(HttpServletRequest request) { - try { - ClinicalDataBinCountFilter clinicalDataBinCountFilter = objectMapper.readValue(request.getInputStream(), - ClinicalDataBinCountFilter.class); - LOG.debug("extracted clinicalDataBinCountFilter: {}", clinicalDataBinCountFilter); - LOG.debug("setting interceptedClinicalDataBinCountFilter to {}", clinicalDataBinCountFilter); - request.setAttribute("interceptedClinicalDataBinCountFilter", clinicalDataBinCountFilter); - if (cacheMapUtil.hasCacheEnabled()) { - Collection cancerStudyIdCollection = extractCancerStudyIdsFromClinicalDataBinCountFilter( - clinicalDataBinCountFilter); - LOG.debug("setting involvedCancerStudies to {}", cancerStudyIdCollection); - request.setAttribute("involvedCancerStudies", cancerStudyIdCollection); - } - } catch (Exception e) { - LOG.error("exception thrown during extraction of clinicalDataBinCountFilter: {}", e.getMessage()); - return false; - } - return true; - } - - private boolean extractAttributesFromGenomicDataBinCountFilter(HttpServletRequest request) { - try { - GenomicDataBinCountFilter genomicDataBinCountFilter = objectMapper.readValue(request.getInputStream(), - GenomicDataBinCountFilter.class); - LOG.debug("extracted genomicDataBinCountFilter: {}", genomicDataBinCountFilter); - LOG.debug("setting interceptedGenomicDataBinCountFilter to {}", genomicDataBinCountFilter); - request.setAttribute("interceptedGenomicDataBinCountFilter", genomicDataBinCountFilter); - if (cacheMapUtil.hasCacheEnabled()) { - Collection cancerStudyIdCollection = extractCancerStudyIdsFromGenomicDataBinCountFilter( - genomicDataBinCountFilter); - LOG.debug("setting involvedCancerStudies to {}", cancerStudyIdCollection); - request.setAttribute("involvedCancerStudies", cancerStudyIdCollection); - } - } catch (Exception e) { - LOG.error("exception thrown during extraction of genomicDataBinCountFilter: {}", e.getMessage()); - return false; - } - return true; - } - - private boolean extractAttributesFromGenomicDataCountFilter(HttpServletRequest request) { - try { - GenomicDataCountFilter genomicDataCountFilter = objectMapper.readValue(request.getInputStream(), - GenomicDataCountFilter.class); - LOG.debug("extracted genomicDataCountFilter: {}", genomicDataCountFilter); - LOG.debug("setting interceptedGenomicDataCountFilter to {}", genomicDataCountFilter); - request.setAttribute("interceptedGenomicDataCountFilter", genomicDataCountFilter); - if (cacheMapUtil.hasCacheEnabled()) { - Collection cancerStudyIdCollection = extractCancerStudyIdsFromGenomicDataCountFilter( - genomicDataCountFilter); - LOG.debug("setting involvedCancerStudies to {}", cancerStudyIdCollection); - request.setAttribute("involvedCancerStudies", cancerStudyIdCollection); - } - } catch (Exception e) { - LOG.error("exception thrown during extraction of genomicDataCountFilter: {}", e.getMessage()); - return false; - } - return true; - } - - private boolean extractAttributesFromGenericAssayDataBinCountFilter(HttpServletRequest request) { - try { - GenericAssayDataBinCountFilter genericAssayDataBinCountFilter = objectMapper - .readValue(request.getInputStream(), GenericAssayDataBinCountFilter.class); - LOG.debug("extracted genericAssayDataBinCountFilter: {}", genericAssayDataBinCountFilter); - LOG.debug("setting interceptedGenericAssayDataBinCountFilter to {}", genericAssayDataBinCountFilter); - request.setAttribute("interceptedGenericAssayDataBinCountFilter", genericAssayDataBinCountFilter); - if (cacheMapUtil.hasCacheEnabled()) { - Collection cancerStudyIdCollection = extractCancerStudyIdsFromGenericAssayDataBinCountFilter( - genericAssayDataBinCountFilter); - LOG.debug("setting involvedCancerStudies to {}", cancerStudyIdCollection); - request.setAttribute("involvedCancerStudies", cancerStudyIdCollection); - } - } catch (Exception e) { - LOG.error("exception thrown during extraction of genericAssayDataBinCountFilter: {}", e.getMessage()); - return false; - } - return true; - } - - private boolean extractAttributesFromGenericAssayDataCountFilter(HttpServletRequest request) { - try { - GenericAssayDataCountFilter genericAssayDataCountFilter = objectMapper - .readValue(request.getInputStream(), GenericAssayDataCountFilter.class); - LOG.debug("extracted genericAssayDataCountFilter: {}", genericAssayDataCountFilter); - LOG.debug("setting interceptedGenericAssayDataCountFilter to {}", genericAssayDataCountFilter); - request.setAttribute("interceptedGenericAssayDataCountFilter", genericAssayDataCountFilter); - if (cacheMapUtil.hasCacheEnabled()) { - Collection cancerStudyIdCollection = extractCancerStudyIdsFromGenericAssayDataCountFilter( - genericAssayDataCountFilter); - LOG.debug("setting involvedCancerStudies to {}", cancerStudyIdCollection); - request.setAttribute("involvedCancerStudies", cancerStudyIdCollection); - } - } catch (Exception e) { - LOG.error("exception thrown during extraction of genericAssayDataCountFilter: {}", e.getMessage()); - return false; - } - return true; - } - - private boolean extractAttributesFromClinicalDataCountFilter(HttpServletRequest request) { - try { - ClinicalDataCountFilter clinicalDataCountFilter = objectMapper.readValue(request.getInputStream(), - ClinicalDataCountFilter.class); - LOG.debug("extracted clinicalDataBinCountFilter: {}", clinicalDataCountFilter); - LOG.debug("setting interceptedClinicalDataCountFilter to {}", clinicalDataCountFilter); - request.setAttribute("interceptedClinicalDataCountFilter", clinicalDataCountFilter); - if (cacheMapUtil.hasCacheEnabled()) { - Collection cancerStudyIdCollection = extractCancerStudyIdsFromClinicalDataCountFilter( - clinicalDataCountFilter); - LOG.debug("setting involvedCancerStudies to {}", cancerStudyIdCollection); - request.setAttribute("involvedCancerStudies", cancerStudyIdCollection); - } - } catch (Exception e) { - LOG.error("exception thrown during extraction of clinicalDataBinCountFilter: {}", e.getMessage()); - return false; - } - return true; - } - - private boolean extractAttributesFromGroupFilter(HttpServletRequest request) { - try { - GroupFilter groupFilter = objectMapper.readValue(request.getInputStream(), - GroupFilter.class); - LOG.debug("extracted groupFilter: {}", groupFilter); - LOG.debug("setting interceptedGroupFilter to {}", groupFilter); - request.setAttribute("interceptedGroupFilter", groupFilter); - if (cacheMapUtil.hasCacheEnabled()) { - List sampleIdentifiers = groupFilter.getGroups().stream() - .flatMap(group -> group.getSampleIdentifiers().stream()).collect(Collectors.toList()); - Collection cancerStudyIdCollection = extractCancerStudyIdsFromSampleIdentifiers(sampleIdentifiers); - LOG.debug("setting involvedCancerStudies to {}", cancerStudyIdCollection); - request.setAttribute("involvedCancerStudies", cancerStudyIdCollection); - } - } catch (Exception e) { - LOG.error("exception thrown during extraction of groupFilter: {}", e.getMessage()); - return false; - } - return true; - } - - private boolean extractAttributesFromStudyViewFilter(HttpServletRequest request) { - try { - StudyViewFilter studyViewFilter = objectMapper.readValue(request.getInputStream(), StudyViewFilter.class); - if (studyViewFilter.getAlterationFilter() == null) { - // For backwards compatibility an inactive filter is set - // when the AlterationFilter is not part of the request. - studyViewFilter.setAlterationFilter(new AlterationFilter()); - } - if (studyViewFilter.getStructuralVariantFilters() == null) { - // For backwards compatibility an inactive filter is set - // when the StructuralVariantFilters are not part of the request. - studyViewFilter.setStructuralVariantFilters(new ArrayList<>()); - } - LOG.debug("extracted studyViewFilter: {}", studyViewFilter); - LOG.debug("setting interceptedStudyViewFilter to {}", studyViewFilter); - request.setAttribute("interceptedStudyViewFilter", studyViewFilter); - if (cacheMapUtil.hasCacheEnabled()) { - Collection cancerStudyIdCollection = extractCancerStudyIdsFromStudyViewFilter(studyViewFilter); - LOG.debug("setting involvedCancerStudies to {}", cancerStudyIdCollection); - request.setAttribute("involvedCancerStudies", cancerStudyIdCollection); - } - } catch (Exception e) { - LOG.error("exception thrown during extraction of studyViewFilter: {}", e.getMessage()); - return false; - } - return true; - } - - private boolean extractAttributesFromMolecularProfileCasesGroups(HttpServletRequest request) { - try { - List molecularProfileCasesGroupFilters = Arrays - .asList(objectMapper.readValue(request.getInputStream(), MolecularProfileCasesGroupFilter[].class)); - LOG.debug("extracted molecularProfileCasesGroupFilters: {}", molecularProfileCasesGroupFilters); - LOG.debug("setting interceptedMolecularProfileCasesGroupFilters to {}", molecularProfileCasesGroupFilters); - request.setAttribute("interceptedMolecularProfileCasesGroupFilters", molecularProfileCasesGroupFilters); - if (cacheMapUtil.hasCacheEnabled()) { - Collection cancerStudyIdCollection = extractCancerStudyIdsFromMolecularProfileCasesGroups( - molecularProfileCasesGroupFilters); - LOG.debug("setting involvedCancerStudies to {}", cancerStudyIdCollection); - request.setAttribute("involvedCancerStudies", cancerStudyIdCollection); - } - } catch (Exception e) { - LOG.error("exception thrown during extraction of molecularProfileCasesGroupFilters: {}", e.getMessage()); - return false; - } - return true; - } - - private boolean extractAttributesFromMolecularProfileCasesGroupsAndAlterationTypes(HttpServletRequest request) { - try { - MolecularProfileCasesGroupAndAlterationTypeFilter molecularProfileCasesAndAlterationTypesGroupFilters = objectMapper.readValue(request.getInputStream(), MolecularProfileCasesGroupAndAlterationTypeFilter.class); - List molecularProfileCasesGroupFilters = molecularProfileCasesAndAlterationTypesGroupFilters.getMolecularProfileCasesGroupFilter(); - LOG.debug("extracted molecularProfileCasesGroupFilters: {}", molecularProfileCasesGroupFilters); - LOG.debug("setting interceptedMolecularProfileCasesGroupFilters to {}", molecularProfileCasesGroupFilters); - request.setAttribute("interceptedMolecularProfileCasesGroupFilters", molecularProfileCasesGroupFilters); - if (molecularProfileCasesAndAlterationTypesGroupFilters.getAlterationEventTypes() != null) { - AlterationFilter alterationEnrichmentEventTypes = molecularProfileCasesAndAlterationTypesGroupFilters.getAlterationEventTypes(); - LOG.debug("extracted alterationEventTypes: {}", alterationEnrichmentEventTypes); - LOG.debug("setting alterationEventTypes to {}", alterationEnrichmentEventTypes); - request.setAttribute("alterationEventTypes", alterationEnrichmentEventTypes); - } - if (cacheMapUtil.hasCacheEnabled()) { - Collection cancerStudyIdCollection = extractCancerStudyIdsFromMolecularProfileCasesGroups( - molecularProfileCasesGroupFilters); - LOG.debug("setting involvedCancerStudies to {}", cancerStudyIdCollection); - request.setAttribute("involvedCancerStudies", cancerStudyIdCollection); - } - } catch (Exception e) { - LOG.error("exception thrown during extraction of molecularProfileCasesGroupFilters: {}", e.getMessage()); - return false; - } - return true; - } - - private boolean extractAttributesFromStructuralVariantFilter(HttpServletRequest request) { - try { - StructuralVariantFilter structuralVariantFilter = objectMapper.readValue(request.getInputStream(), - StructuralVariantFilter.class); - LOG.debug("extracted structuralVariantFilter: {}", structuralVariantFilter); - if (structuralVariantFilter.getStructuralVariantQueries() == null) { - // For backwards compatibility an empty set of queries is inferred - // when the StructuralVariantFilter is not part of the request. - structuralVariantFilter.setStructuralVariantQueries(new ArrayList<>()); - } - LOG.debug("setting interceptedStructuralVariantFilter to {}", structuralVariantFilter); - request.setAttribute("interceptedStructuralVariantFilter", structuralVariantFilter); - if (cacheMapUtil.hasCacheEnabled()) { - Collection cancerStudyIdCollection = extractCancerStudyIdsFromStructuralVariantFilter( - structuralVariantFilter); - LOG.debug("setting involvedCancerStudies to {}", cancerStudyIdCollection); - request.setAttribute("involvedCancerStudies", cancerStudyIdCollection); - } - } catch (Exception e) { - LOG.error("exception thrown during extraction of structuralVariantFilter: {}", e.getMessage()); - return false; - } - return true; - } - - private Collection extractCancerStudyIdsFromStructuralVariantFilter(StructuralVariantFilter structuralVariantFilter) { - Set studyIdSet = new HashSet<>(); - if (structuralVariantFilter.getSampleMolecularIdentifiers() != null) { - // controller handler will preferentially use SampleMolecularIdentifiers if they are present in the filter - extractCancerStudyIdsFromSampleMolecularIdentifiers(structuralVariantFilter.getSampleMolecularIdentifiers(), studyIdSet); - } else { - // otherwise, handler will use the list of MolecularProfileIds in the filter - if (structuralVariantFilter.getMolecularProfileIds() != null) { - extractCancerStudyIdsFromMolecularProfileIds(structuralVariantFilter.getMolecularProfileIds(), studyIdSet); - } - } - return studyIdSet; - } - - private Set extractCancerStudyIdsFromSampleIdentifiers(Collection sampleIdentifiers) { - Set studyIdSet = new HashSet<>(); - extractCancerStudyIdsFromSampleIdentifiers(sampleIdentifiers, studyIdSet); - return studyIdSet; - } - - private void extractCancerStudyIdsFromSampleIdentifiers(Collection sampleIdentifiers, Set studyIdSet) { - for (SampleIdentifier sampleIdentifier : sampleIdentifiers) { - studyIdSet.add(sampleIdentifier.getStudyId()); - } - } - - private void extractCancerStudyIdsFromSampleListIds(List sampleListIds, Set studyIdSet) { - for (String sampleListId : sampleListIds) { - SampleList sampleList = cacheMapUtil.getSampleListMap().get(sampleListId); - studyIdSet.add(sampleList.getCancerStudyIdentifier()); - } - } - - private void extractCancerStudyIdsFromMolecularProfileIds(Collection molecularProfileIds, Set studyIdSet) { - for (String molecularProfileId : molecularProfileIds) { - MolecularProfile molecularProfile = cacheMapUtil.getMolecularProfileMap().get(molecularProfileId); - studyIdSet.add(molecularProfile.getCancerStudyIdentifier()); - } - } - - private void extractCancerStudyIdsFromSampleMolecularIdentifiers(List sampleMolecularIdentifiers, Set studyIdSet) { - // use hashset as the study list in sampleMolecularIdentifiers may be populated with duplicate values - Set molecularProfileIds = new HashSet<>(); - for (SampleMolecularIdentifier sampleMolecularIdentifier: sampleMolecularIdentifiers) { - molecularProfileIds.add(sampleMolecularIdentifier.getMolecularProfileId()); - } - extractCancerStudyIdsFromMolecularProfileIds(molecularProfileIds, studyIdSet); - } - - private Set extractCancerStudyIdsFromClinicalDataBinCountFilter( - ClinicalDataBinCountFilter clinicalDataBinCountFilter) { - if (clinicalDataBinCountFilter.getStudyViewFilter() != null) { - return extractCancerStudyIdsFromStudyViewFilter(clinicalDataBinCountFilter.getStudyViewFilter()); - } - return new HashSet<>(); - } - - private Set extractCancerStudyIdsFromGenomicDataBinCountFilter( - GenomicDataBinCountFilter genomicDataBinCountFilter) { - if (genomicDataBinCountFilter.getStudyViewFilter() != null) { - return extractCancerStudyIdsFromStudyViewFilter(genomicDataBinCountFilter.getStudyViewFilter()); - } - return new HashSet<>(); - } - - private Set extractCancerStudyIdsFromGenomicDataCountFilter( - GenomicDataCountFilter genomicDataCountFilter) { - if (genomicDataCountFilter.getStudyViewFilter() != null) { - return extractCancerStudyIdsFromStudyViewFilter(genomicDataCountFilter.getStudyViewFilter()); - } - return new HashSet(); - } - - private Set extractCancerStudyIdsFromGenericAssayDataBinCountFilter( - GenericAssayDataBinCountFilter genericAssayDataBinCountFilter) { - if (genericAssayDataBinCountFilter.getStudyViewFilter() != null) { - return extractCancerStudyIdsFromStudyViewFilter(genericAssayDataBinCountFilter.getStudyViewFilter()); - } - return new HashSet<>(); - } - - private Set extractCancerStudyIdsFromGenericAssayDataCountFilter( - GenericAssayDataCountFilter genericAssayDataCountFilter) { - if (genericAssayDataCountFilter.getStudyViewFilter() != null) { - return extractCancerStudyIdsFromStudyViewFilter(genericAssayDataCountFilter.getStudyViewFilter()); - } - return new HashSet<>(); - } - - private Set extractCancerStudyIdsFromClinicalDataCountFilter( - ClinicalDataCountFilter clinicalDataCountFilter) { - if (clinicalDataCountFilter.getStudyViewFilter() != null) { - return extractCancerStudyIdsFromStudyViewFilter(clinicalDataCountFilter.getStudyViewFilter()); - } - return new HashSet<>(); - } - - private Set extractCancerStudyIdsFromStudyViewFilter(StudyViewFilter studyViewFilter) { - Set studyIdSet = new HashSet<>(); - if (studyViewFilter.getSampleIdentifiers() != null && !studyViewFilter.getSampleIdentifiers().isEmpty()) { - extractCancerStudyIdsFromSampleIdentifiers(studyViewFilter.getSampleIdentifiers(), studyIdSet); - } else { - studyIdSet.addAll(studyViewFilter.getStudyIds()); - } - return studyIdSet; - } - - private Set extractCancerStudyIdsFromMolecularProfileCasesGroups(Collection molecularProfileCasesGroupFilters) { - Set molecularProfileIds = molecularProfileCasesGroupFilters.stream().flatMap(group -> { - return group.getMolecularProfileCaseIdentifiers().stream() - .map(MolecularProfileCaseIdentifier::getMolecularProfileId); - }).collect(Collectors.toSet()); - Set studyIdSet = new HashSet<>(); - extractCancerStudyIdsFromMolecularProfileIds(molecularProfileIds, studyIdSet); - return studyIdSet; - } - - private boolean extractCancerStudyIdsFromSurvivalRequest(HttpServletRequest request) { - try { - SurvivalRequest survivalRequest = objectMapper.readValue(request.getInputStream(), SurvivalRequest.class); - LOG.debug("extracted survivalRequest: {}", survivalRequest); - LOG.debug("setting interceptedSurvivalRequest to {}", survivalRequest); - request.setAttribute("interceptedSurvivalRequest", survivalRequest); - if (cacheMapUtil.hasCacheEnabled()) { - Collection cancerStudyIdCollection = survivalRequest - .getPatientIdentifiers() - .stream() - .map(PatientIdentifier::getStudyId) - .collect(Collectors.toSet()); - LOG.debug("setting involvedCancerStudies to {}", cancerStudyIdCollection); - request.setAttribute("involvedCancerStudies", cancerStudyIdCollection); - } - } catch (Exception e) { - LOG.error("exception thrown during extraction of survivalRequest: {}", e.getMessage()); - return false; - } - return true; - } - - private boolean extractCancerStudyIdsFromClinicalEventAttributeRequest(HttpServletRequest request) { - try { - ClinicalEventAttributeRequest clinicalEventAttributeRequest = objectMapper.readValue(request.getInputStream(), ClinicalEventAttributeRequest.class); - LOG.debug("extracted clinicalEventAttributeRequest: {}", clinicalEventAttributeRequest); - LOG.debug("setting interceptedClinicalEventAttributeRequest to {}", clinicalEventAttributeRequest); - request.setAttribute("interceptedClinicalEventAttributeRequest", clinicalEventAttributeRequest); - if (cacheMapUtil.hasCacheEnabled()) { - Collection cancerStudyIdCollection = clinicalEventAttributeRequest - .getPatientIdentifiers() - .stream() - .map(PatientIdentifier::getStudyId) - .collect(Collectors.toSet()); - LOG.debug("setting involvedCancerStudies to {}", cancerStudyIdCollection); - request.setAttribute("involvedCancerStudies", cancerStudyIdCollection); - } - } catch (Exception e) { - LOG.error("exception thrown during extraction of clinicalEventAttributeRequest: {}", e.getMessage()); - return false; - } - return true; - } - -} diff --git a/src/main/java/org/cbioportal/web/util/LinearDataBinner.java b/src/main/java/org/cbioportal/web/util/LinearDataBinner.java deleted file mode 100644 index 34bea85d9e4..00000000000 --- a/src/main/java/org/cbioportal/web/util/LinearDataBinner.java +++ /dev/null @@ -1,138 +0,0 @@ -package org.cbioportal.web.util; - -import com.google.common.collect.Range; -import org.cbioportal.model.DataBin; -import org.springframework.stereotype.Component; - -import java.math.BigDecimal; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.Optional; -import java.util.stream.Collectors; - -@Component -public class LinearDataBinner { - public static final Double[] POSSIBLE_INTERVALS = { - 0.001, 0.002, 0.0025, 0.005, 0.01, - 0.02, 0.025, 0.05, 0.1, - 0.2, 0.25, 0.5, 1.0, - 2.0, 5.0, 10.0, - 20.0, 25.0, 50.0, 100.0, - 200.0, 250.0, 500.0, 1000.0, - 2000.0, 2500.0, 5000.0, 10000.0 - }; - - public static final Double[] POSSIBLE_DISCRETE_INTERVALS = { - 1.0, 2.0, 5.0, 10.0, - 20.0, 25.0, 50.0, 100.0, - 200.0, 250.0, 500.0, 1000.0, - 2000.0, 2500.0, 5000.0, 10000.0 - }; - - public static final Integer DEFAULT_INTERVAL_COUNT = 20; - - public List calculateDataBins(boolean areAllIntegers, - Range boxRange, - List values, - BigDecimal lowerOutlier, - BigDecimal upperOutlier, - Optional attributeId) { - BigDecimal min = lowerOutlier == null ? Collections.min(values) : Collections.min(values).max(lowerOutlier); - BigDecimal max = upperOutlier == null ? Collections.max(values) : Collections.max(values).min(upperOutlier); - - List dataBins = initDataBins(areAllIntegers, min, max, lowerOutlier, upperOutlier); - - // special case for "AGE" attributes - if (attributeId.isPresent() && - DataBinHelper.isAgeAttribute(attributeId.get()) && - min.doubleValue() < 18 && - boxRange.upperEndpoint().subtract(boxRange.lowerEndpoint()).divide(BigDecimal.valueOf(2)).compareTo(BigDecimal.valueOf(18)) == 1 && - dataBins.get(0).getEnd().compareTo(BigDecimal.valueOf(18)) == 1) { - // force first bin to start from 18 - dataBins.get(0).setStart(BigDecimal.valueOf(18)); - } - - DataBinHelper.calcCounts(dataBins, values); - - return dataBins; - } - - public List calculateDataBins(List customBins, - List values) { - List dataBins = initDataBins(customBins); - DataBinHelper.calcCounts(dataBins, values); - return dataBins; - } - - // Add boundaries that have a defined start and end value. - // Ignore boundaries for lower (<=) and upper (>) limits. - public List initDataBins(List boundaries) { - List dataBins = new ArrayList<>(); - for (int i = 0; i < boundaries.size() - 1; i++) { - DataBin dataBin = new DataBin(); - dataBin.setStart(boundaries.get(i)); - dataBin.setEnd(boundaries.get(i + 1)); - dataBin.setCount(0); - dataBins.add(dataBin); - } - return dataBins; - } - - public List initDataBins(boolean areAllIntegers, - BigDecimal min, - BigDecimal max, - BigDecimal lowerOutlier, - BigDecimal upperOutlier) { - List dataBins = new ArrayList<>(); - - List possibleIntervals = Arrays - .asList(areAllIntegers ? POSSIBLE_DISCRETE_INTERVALS : POSSIBLE_INTERVALS) - .stream() - .map(val -> BigDecimal.valueOf(val)) - .collect(Collectors.toList()); - - BigDecimal interval = calcBinInterval(possibleIntervals, max.subtract(min), DEFAULT_INTERVAL_COUNT); - - BigDecimal start = min.add(interval).subtract(min.remainder(interval)); - - // check lowerOutlier too for better tuning of start - if (lowerOutlier == null || start.subtract(interval).compareTo(lowerOutlier) == 1) { - start = start.subtract(interval); - } - - // check upperOutlier too for better tuning of end - BigDecimal end = upperOutlier == null || max.add(interval).compareTo(upperOutlier) == -1 ? max: max.subtract(interval); - - for (BigDecimal d = start; d.compareTo(end) != 1; ) { - DataBin dataBin = new DataBin(); - BigDecimal newEnd = d.add(interval); - - dataBin.setStart(d); - dataBin.setEnd(newEnd); - dataBin.setCount(0); - - dataBins.add(dataBin); - - d = newEnd; - } - - return dataBins; - } - - public BigDecimal calcBinInterval(List possibleIntervals, BigDecimal totalRange, Integer maxIntervalCount) { - BigDecimal interval = new BigDecimal("-1.0"); - - for (int i = 0; i < possibleIntervals.size(); i++) { - interval = possibleIntervals.get(i); - BigDecimal count = totalRange.divide(interval); - - if (count.doubleValue() < maxIntervalCount) { - break; - } - } - - return interval; - } -} diff --git a/src/main/java/org/cbioportal/web/util/LogScaleDataBinner.java b/src/main/java/org/cbioportal/web/util/LogScaleDataBinner.java deleted file mode 100644 index febeb34ebb8..00000000000 --- a/src/main/java/org/cbioportal/web/util/LogScaleDataBinner.java +++ /dev/null @@ -1,76 +0,0 @@ -package org.cbioportal.web.util; - -import com.google.common.collect.Range; -import org.cbioportal.model.DataBin; -import org.springframework.stereotype.Component; - -import java.math.BigDecimal; -import java.util.ArrayList; -import java.util.List; - -@Component -public class LogScaleDataBinner { - - public List calculateDataBins(Range boxRange, - List values, - BigDecimal lowerOutlier, - BigDecimal upperOutlier) { - List intervals = new ArrayList<>(); - BigDecimal start = new BigDecimal("0"); - - if (boxRange.lowerEndpoint().compareTo(new BigDecimal("0")) != 0) { - double absLogValue = Math.log10(boxRange.lowerEndpoint().abs().doubleValue()); - start = BigDecimal.valueOf(boxRange.lowerEndpoint().compareTo(new BigDecimal("0")) == -1 ? - -Math.ceil(absLogValue) : Math.floor(absLogValue)); - } - - if (lowerOutlier != null) { - intervals.add(lowerOutlier); - } - - for (BigDecimal exponent = start; ; exponent = exponent.add(new BigDecimal("0.5"))) { - BigDecimal value = calcIntervalValue(exponent); - - if ((lowerOutlier == null || value.compareTo(lowerOutlier) == 1) && - (upperOutlier == null || value.compareTo(upperOutlier) != 1)) { - intervals.add(value); - } - - if (value.compareTo(boxRange.upperEndpoint()) == 1) { - exponent = exponent.add(new BigDecimal("0.5")); - - if (!addOutlierInterval(intervals, exponent, upperOutlier)) { - intervals.add(upperOutlier); - } - - // we don't want to end with non-integer exponent, - // add one more interval value if possible - if (exponent.stripTrailingZeros().scale() > 0) { - exponent = exponent.add(new BigDecimal("0.5")); - addOutlierInterval(intervals, exponent, upperOutlier); - } - - break; - } - } - - return DataBinHelper.initDataBins(values, intervals); - } - - public BigDecimal calcIntervalValue(BigDecimal exponent) { - return BigDecimal.valueOf(exponent.signum() * Math.floor(Math.pow(10, exponent.abs().doubleValue()))); - } - - private boolean addOutlierInterval(List intervals, - BigDecimal exponent, - BigDecimal upperOutlier) - { - BigDecimal value = calcIntervalValue(exponent); - - if (upperOutlier == null || value.compareTo(upperOutlier) != 1) { - return intervals.add(value); - } - - return false; - } -} diff --git a/src/main/java/org/cbioportal/web/util/RequestBodyGZipFilter.java b/src/main/java/org/cbioportal/web/util/RequestBodyGZipFilter.java deleted file mode 100644 index 7c68698c38c..00000000000 --- a/src/main/java/org/cbioportal/web/util/RequestBodyGZipFilter.java +++ /dev/null @@ -1,79 +0,0 @@ -package org.cbioportal.web.util; - -import jakarta.servlet.*; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.http.HttpHeaders; -import org.springframework.stereotype.Component; - -import java.io.IOException; - -@Component("requestBodyGZipFilter") -public class RequestBodyGZipFilter implements Filter { - /** - * We need to limit the size of the gzipped request bodies to avoid denial of memory attacks. - * Because gzip can achieve text compression rates of around 1000x, without a common sense limit for - * request body size, it would be very easy to send a request body that, when inflated, consumes the - * entirety of a server's memory. - */ - @Value("${request_gzip_body_size_bytes:80000000}") - private int maxInflatedRequestBodySize; - - @Value("${enable_request_body_gzip_compression:false}") - private boolean enabled; - - @Override - public void init(FilterConfig filterConfig) throws ServletException { - // Nothing to init (Sonar asks you to comment if you leave a method empty) - } - - /** - * Analyzes servlet request for possible gzipped body. - * When Content-Encoding header has "gzip" value and request method is POST, we read all the - * gzipped stream and if it has any data unzip it. In case when gzip Content-Encoding header - * specified but body is not actually in gzip format we will throw ZipException. - * - * @param servletRequest servlet request - * @param servletResponse servlet response - * @param chain filter chain - * @throws IOException throws when fails - * @throws ServletException thrown when fails - */ - @Override - public final void doFilter( - final ServletRequest servletRequest, - final ServletResponse servletResponse, - final FilterChain chain - ) throws IOException, ServletException { - HttpServletRequest request = (HttpServletRequest) servletRequest; - HttpServletResponse response = (HttpServletResponse) servletResponse; - boolean isGzipped = request.getHeader(HttpHeaders.CONTENT_ENCODING) != null - && request.getHeader(HttpHeaders.CONTENT_ENCODING).contains("gzip"); - boolean requestTypeSupported = "POST".equals(request.getMethod()); - - if (isGzipped) { - if (!enabled) { - throw new IllegalStateException( - "Received gzipped request body, but enable_request_body_gzip_compression is not set or is false" - ); - } - if (!requestTypeSupported) { - throw new IllegalStateException( - "Received request with a Content-Encoding: gzip header and a request method of: " + - request.getMethod() - + " Only POST requests are supported." - ); - } - - request = new GzippedInputStreamRequestWrapper((HttpServletRequest) servletRequest, maxInflatedRequestBodySize); - } - - chain.doFilter(request, response); - } - - @Override - public final void destroy() { - // Nothing to destroy (Sonar asks you to comment if you leave a method empty) - } -} \ No newline at end of file diff --git a/src/main/java/org/cbioportal/web/util/ResettableHttpServletRequestFilter.java b/src/main/java/org/cbioportal/web/util/ResettableHttpServletRequestFilter.java deleted file mode 100644 index b34fe2eaaab..00000000000 --- a/src/main/java/org/cbioportal/web/util/ResettableHttpServletRequestFilter.java +++ /dev/null @@ -1,41 +0,0 @@ -package org.cbioportal.web.util; - -import java.io.IOException; - -import jakarta.servlet.*; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; -import org.slf4j.LoggerFactory; -import org.slf4j.Logger; -import org.springframework.stereotype.Component; -import org.springframework.web.util.ContentCachingRequestWrapper; -import org.springframework.web.util.ContentCachingResponseWrapper; - - -/** - * - * @author ochoaa - * - */ -@Component -public class ResettableHttpServletRequestFilter implements Filter { - private Logger LOG = LoggerFactory.getLogger(ResettableHttpServletRequestFilter.class); - - @Override - public void init(FilterConfig aChain) throws ServletException { - // do nothing - } - - @Override - public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException { - ContentCachingRequestWrapper wrappedRequest = new ContentCachingRequestWrapper((HttpServletRequest) request); - ContentCachingResponseWrapper wrappedResponse = new ContentCachingResponseWrapper((HttpServletResponse) response); - filterChain.doFilter(wrappedRequest, wrappedResponse); - wrappedResponse.copyBodyToResponse(); - } - - @Override - public void destroy() { - // do nothing - } -} diff --git a/src/main/java/org/cbioportal/web/util/ScientificSmallDataBinner.java b/src/main/java/org/cbioportal/web/util/ScientificSmallDataBinner.java deleted file mode 100644 index f3766164ef8..00000000000 --- a/src/main/java/org/cbioportal/web/util/ScientificSmallDataBinner.java +++ /dev/null @@ -1,73 +0,0 @@ -package org.cbioportal.web.util; - -import com.google.common.collect.Range; -import org.cbioportal.model.DataBin; -import org.springframework.stereotype.Component; - -import java.math.BigDecimal; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.stream.Collectors; - -@Component -public class ScientificSmallDataBinner { - - public List calculateDataBins(List sortedNumericalValues, - List valuesWithoutOutliers, - BigDecimal lowerOutlier, - BigDecimal upperOutlier) { - List exponents = sortedNumericalValues - .stream() - .map(d -> BigDecimal.valueOf(DataBinHelper.calcExponent(d))) - .filter(d -> d.compareTo(new BigDecimal("0")) != 0) - .collect(Collectors.toList()); - - Collections.sort(exponents); - - Range exponentBoxRange = DataBinHelper.calcBoxRange(exponents); - - List intervals = new ArrayList<>(); - - BigDecimal exponentRange = exponentBoxRange == null ? - null : exponentBoxRange.upperEndpoint().subtract(exponentBoxRange.lowerEndpoint()); - - if (exponentRange == null) { - // data set is not compatible with the scientific small data binner, - // just set one interval for the entire set - intervals.add(sortedNumericalValues.get(0)); - intervals.add(sortedNumericalValues.get(sortedNumericalValues.size() - 1)); - } else if (exponentRange.compareTo(new BigDecimal("1")) == 1) { - Integer interval = Math.round(exponentRange.floatValue() / 4); - - for (int i = exponentBoxRange.lowerEndpoint().intValue() - interval; - i <= exponentBoxRange.upperEndpoint().intValue(); - i += interval) - { - intervals.add(BigDecimal.valueOf(Math.pow(10, i))); - } - } else if (exponentRange.compareTo(new BigDecimal("1")) == 0) { - intervals.add(BigDecimal.valueOf(Math.pow(10, exponentBoxRange.lowerEndpoint().doubleValue()) / 3)); - - for (int i = exponentBoxRange.lowerEndpoint().intValue(); - i <= exponentBoxRange.upperEndpoint().intValue() + 1; - i++) - { - BigDecimal powerTen = BigDecimal.valueOf(Math.pow(10, i)); - intervals.add(powerTen); - intervals.add(powerTen.multiply(new BigDecimal("3"))); - } - } else { // exponentRange == 0 - BigDecimal interval = BigDecimal.valueOf(2 * Math.pow(10, exponentBoxRange.lowerEndpoint().doubleValue())); - - for (BigDecimal d = BigDecimal.valueOf(Math.pow(10, exponentBoxRange.lowerEndpoint().intValue())); - d.doubleValue() <= Math.pow(10, exponentBoxRange.upperEndpoint().doubleValue() + 1); - d=d.add(interval)) - { - intervals.add(d); - } - } - - return DataBinHelper.initDataBins(valuesWithoutOutliers, intervals, lowerOutlier, upperOutlier); - } -} diff --git a/src/main/java/org/cbioportal/web/util/StudyViewFilterApplier.java b/src/main/java/org/cbioportal/web/util/StudyViewFilterApplier.java deleted file mode 100644 index 43980c99f90..00000000000 --- a/src/main/java/org/cbioportal/web/util/StudyViewFilterApplier.java +++ /dev/null @@ -1,1307 +0,0 @@ -package org.cbioportal.web.util; - -import org.apache.commons.collections4.CollectionUtils; -import org.apache.commons.collections4.map.MultiKeyMap; -import org.cbioportal.model.Binnable; -import org.cbioportal.model.ClinicalAttribute; -import org.cbioportal.model.ClinicalData; -import org.cbioportal.model.DataBin; -import org.cbioportal.model.DiscreteCopyNumberData; -import org.cbioportal.model.Gene; -import org.cbioportal.model.GeneFilter; -import org.cbioportal.model.GeneFilterQuery; -import org.cbioportal.model.GenePanel; -import org.cbioportal.model.GenePanelData; -import org.cbioportal.model.GenePanelToGene; -import org.cbioportal.model.GenericAssayDataBin; -import org.cbioportal.model.GenomicDataBin; -import org.cbioportal.model.MolecularData; -import org.cbioportal.model.MolecularProfile; -import org.cbioportal.model.MolecularProfile.MolecularAlterationType; -import org.cbioportal.model.MolecularProfileCaseIdentifier; -import org.cbioportal.model.Mutation; -import org.cbioportal.model.MutationFilterOption; -import org.cbioportal.model.Sample; -import org.cbioportal.model.SampleList; -import org.cbioportal.model.UniqueKeyBase; -import org.cbioportal.service.ClinicalAttributeService; -import org.cbioportal.service.DiscreteCopyNumberService; -import org.cbioportal.service.GenePanelService; -import org.cbioportal.service.GeneService; -import org.cbioportal.service.GenericAssayService; -import org.cbioportal.service.MolecularDataService; -import org.cbioportal.service.MolecularProfileService; -import org.cbioportal.service.MutationService; -import org.cbioportal.service.SampleListService; -import org.cbioportal.service.SampleService; -import org.cbioportal.service.StructuralVariantService; -import org.cbioportal.service.exception.MolecularProfileNotFoundException; -import org.cbioportal.service.util.MolecularProfileUtil; -import org.cbioportal.web.parameter.ClinicalDataFilter; -import org.cbioportal.web.parameter.ClinicalDataType; -import org.cbioportal.web.parameter.DataBinCountFilter; -import org.cbioportal.web.parameter.DataBinFilter; -import org.cbioportal.web.parameter.DataBinMethod; -import org.cbioportal.web.parameter.DataFilter; -import org.cbioportal.web.parameter.DataFilterValue; -import org.cbioportal.web.parameter.DiscreteCopyNumberEventType; -import org.cbioportal.web.parameter.GeneIdType; -import org.cbioportal.web.parameter.GenericAssayDataBinCountFilter; -import org.cbioportal.web.parameter.GenericAssayDataBinFilter; -import org.cbioportal.web.parameter.GenericAssayDataFilter; -import org.cbioportal.web.parameter.GenomicDataBinCountFilter; -import org.cbioportal.web.parameter.GenomicDataBinFilter; -import org.cbioportal.web.parameter.GenomicDataFilter; -import org.cbioportal.web.parameter.MutationDataFilter; -import org.cbioportal.web.parameter.MutationOption; -import org.cbioportal.web.parameter.Projection; -import org.cbioportal.web.parameter.SampleIdentifier; -import org.cbioportal.web.parameter.StudyViewFilter; -import org.cbioportal.web.util.appliers.StudyViewSubFilterApplier; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.cache.annotation.Cacheable; -import org.springframework.context.ApplicationContext; -import org.springframework.stereotype.Component; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Set; -import java.util.function.Function; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -@Component -public class StudyViewFilterApplier { - @Autowired - private ApplicationContext applicationContext; - - private StudyViewFilterApplier instance; - - // This gets initialized and overwritten. We do this because Spring's unit tests - // don't know how to autowire this, even though production Spring does. If we - // don't give this an initial value, we get NPEs. - @Autowired - private final List subFilterAppliers = new ArrayList<>(); - - @Autowired - private SampleService sampleService; - @Autowired - private MutationService mutationService; - @Autowired - private DiscreteCopyNumberService discreteCopyNumberService; - @Autowired - private MolecularProfileService molecularProfileService; - @Autowired - private GenePanelService genePanelService; - @Autowired - private ClinicalDataEqualityFilterApplier clinicalDataEqualityFilterApplier; - @Autowired - private ClinicalDataIntervalFilterApplier clinicalDataIntervalFilterApplier; - @Autowired - private CustomDataFilterApplier customDataFilterApplier; - @Autowired - private StudyViewFilterUtil studyViewFilterUtil; - @Autowired - private GeneService geneService; - @Autowired - private ClinicalAttributeService clinicalAttributeService; - @Autowired - private SampleListService sampleListService; - @Autowired - private MolecularDataService molecularDataService; - @Autowired - private GenericAssayService genericAssayService; - @Autowired - private DataBinner dataBinner; - @Autowired - private StructuralVariantService structuralVariantService; - @Autowired - private MolecularProfileUtil molecularProfileUtil; - - - private StudyViewFilterApplier getInstance() { - if (Objects.isNull(instance)) { - instance = applicationContext.getBean(StudyViewFilterApplier.class); - } - return instance; - } - - Function sampleToSampleIdentifier = new Function() { - - public SampleIdentifier apply(Sample sample) { - return studyViewFilterUtil.buildSampleIdentifier(sample.getCancerStudyIdentifier(), sample.getStableId()); - } - }; - - public List apply(StudyViewFilter studyViewFilter) { - return this.getInstance().cachedApply(studyViewFilter); - } - - @Cacheable( - cacheResolver = "generalRepositoryCacheResolver", - condition = "@cacheEnabledConfig.getEnabled()" - ) - public List cachedApply(StudyViewFilter studyViewFilter) { - return this.apply(studyViewFilter, false); - } - - public List apply(StudyViewFilter studyViewFilter, boolean negateFilters) { - - List sampleIdentifiers = new ArrayList<>(); - if (studyViewFilter == null) { - return sampleIdentifiers; - } - - if (studyViewFilter != null && studyViewFilter.getSampleIdentifiers() != null && !studyViewFilter.getSampleIdentifiers().isEmpty()) { - List studyIds = new ArrayList<>(); - List sampleIds = new ArrayList<>(); - studyViewFilterUtil.extractStudyAndSampleIds(studyViewFilter.getSampleIdentifiers(), studyIds, sampleIds); - sampleIdentifiers = sampleService.fetchSamples(studyIds, sampleIds, Projection.ID.name()).stream() - .map(sampleToSampleIdentifier).collect(Collectors.toList()); - } else { - sampleIdentifiers = sampleService.getAllSamplesInStudies(studyViewFilter.getStudyIds(), Projection.ID.name(), - null, null, null, null).stream().map(sampleToSampleIdentifier).collect(Collectors.toList()); - } - - List studyIds = sampleIdentifiers.stream().map(SampleIdentifier::getStudyId).distinct() - .collect(Collectors.toList()); - - List clinicalDataEqualityFilters = new ArrayList<>(); - List clinicalDataIntervalFilters = new ArrayList<>(); - - List clinicalDataFilters = studyViewFilter.getClinicalDataFilters(); - - if (!CollectionUtils.isEmpty(clinicalDataFilters)) { - List attributeIds = clinicalDataFilters.stream().map(ClinicalDataFilter::getAttributeId) - .collect(Collectors.toList()); - List clinicalAttributes = clinicalAttributeService - .getClinicalAttributesByStudyIdsAndAttributeIds(studyIds, attributeIds); - - Map clinicalAttributeMap = clinicalAttributes.stream() - .collect(Collectors.toMap(ClinicalAttribute::getAttrId, Function.identity(), (a, b) -> { - return a.getDatatype().equals("STRING") ? a : b; - })); - - clinicalDataFilters.forEach(clinicalDataFilter -> { - String attributeId = clinicalDataFilter.getAttributeId(); - if (clinicalAttributeMap.containsKey(attributeId)) { - if (clinicalAttributeMap.get(attributeId).getDatatype().equals("STRING")) { - clinicalDataEqualityFilters.add(clinicalDataFilter); - } else { - clinicalDataIntervalFilters.add(clinicalDataFilter); - } - } - }); - } - - if (!CollectionUtils.isEmpty(clinicalDataEqualityFilters)) { - sampleIdentifiers = equalityFilterClinicalData(sampleIdentifiers, clinicalDataEqualityFilters, negateFilters); - } - - if (!CollectionUtils.isEmpty(clinicalDataIntervalFilters)) { - sampleIdentifiers = intervalFilterClinicalData(sampleIdentifiers, clinicalDataIntervalFilters, negateFilters); - } - - if (!CollectionUtils.isEmpty(studyViewFilter.getCustomDataFilters())) { - sampleIdentifiers = customDataFilterApplier.apply(sampleIdentifiers, studyViewFilter.getCustomDataFilters(), - negateFilters); - } - - List molecularProfiles = null; - if (!CollectionUtils.isEmpty(studyViewFilter.getGeneFilters()) - || !CollectionUtils.isEmpty(studyViewFilter.getMutationDataFilters()) - || !CollectionUtils.isEmpty(studyViewFilter.getGenomicDataFilters()) - || !CollectionUtils.isEmpty(studyViewFilter.getGenericAssayDataFilters()) - || !CollectionUtils.isEmpty(studyViewFilter.getGenomicProfiles())) { - - molecularProfiles = molecularProfileService.getMolecularProfilesInStudies(studyIds, "SUMMARY"); - } - - List genomicDataEqualityFilters = new ArrayList<>(); - List genomicDataIntervalFilters = new ArrayList<>(); - - List genomicDataFilters = studyViewFilter.getGenomicDataFilters(); - - if (!CollectionUtils.isEmpty(genomicDataFilters)) { - Map molecularProfileMapByType = molecularProfileUtil - .categorizeMolecularProfilesByStableIdSuffixes(molecularProfiles) - .entrySet() - .stream() - .collect(Collectors.toMap(Map.Entry::getKey, e -> e.getValue().get(0))); - - genomicDataFilters.forEach(genomicDataFilter -> { - String profileType = genomicDataFilter.getProfileType(); - if (molecularProfileMapByType.containsKey(profileType)) { - if (molecularProfileMapByType.get(profileType).getDatatype().equals("DISCRETE")) { - genomicDataEqualityFilters.add(genomicDataFilter); - } else { - genomicDataIntervalFilters.add(genomicDataFilter); - } - } - }); - } - - if (!CollectionUtils.isEmpty(genomicDataEqualityFilters)) { - sampleIdentifiers = equalityFilterExpressionData(sampleIdentifiers, molecularProfiles, - genomicDataEqualityFilters, negateFilters); - } - - if (!CollectionUtils.isEmpty(genomicDataIntervalFilters)) { - sampleIdentifiers = intervalFilterExpressionData(sampleIdentifiers, molecularProfiles, - genomicDataIntervalFilters, negateFilters); - } - - sampleIdentifiers = intervalFilterExpressionData(sampleIdentifiers, molecularProfiles, - studyViewFilter.getGenericAssayDataFilters(), negateFilters); - - if (!CollectionUtils.isEmpty(studyViewFilter.getGeneFilters())) { - Map molecularProfileMap = molecularProfiles.stream() - .collect(Collectors.toMap(MolecularProfile::getStableId, Function.identity())); - List mutatedGeneFilters = new ArrayList(); - List structuralVariantGeneFilters = new ArrayList(); - List cnaGeneFilters = new ArrayList(); - - splitGeneFiltersByMolecularAlterationType(studyViewFilter.getGeneFilters(), molecularProfileMap, - mutatedGeneFilters, structuralVariantGeneFilters, cnaGeneFilters); - - if ((mutatedGeneFilters.size() + structuralVariantGeneFilters.size() + cnaGeneFilters.size()) == studyViewFilter - .getGeneFilters().size()) { - if (!mutatedGeneFilters.isEmpty()) { - sampleIdentifiers = filterMutatedGenes(mutatedGeneFilters, molecularProfileMap, sampleIdentifiers); - } - if (!structuralVariantGeneFilters.isEmpty()) { - sampleIdentifiers = filterStructuralVariantGenes(structuralVariantGeneFilters, molecularProfileMap, - sampleIdentifiers); - } - if (!cnaGeneFilters.isEmpty()) { - sampleIdentifiers = filterCNAGenes(cnaGeneFilters, molecularProfileMap, sampleIdentifiers); - } - - } else { - return new ArrayList<>(); - } - } - - if (!CollectionUtils.isEmpty(studyViewFilter.getGenomicProfiles())) { - Map> groupStudySampleIdentifiers = sampleIdentifiers.stream() - .collect(Collectors.groupingBy(SampleIdentifier::getStudyId)); - - Map> molecularProfileSet = molecularProfileUtil - .categorizeMolecularProfilesByStableIdSuffixes(molecularProfiles); - - List molecularProfileSampleIdentifiers = new ArrayList<>(); - - studyViewFilter.getGenomicProfiles().stream().forEach(profileValues -> { - profileValues.stream().forEach(profileValue -> { - molecularProfileSet.getOrDefault(profileValue, new ArrayList<>()).stream().forEach(profile -> { - groupStudySampleIdentifiers.getOrDefault(profile.getCancerStudyIdentifier(), new ArrayList<>()) - .forEach(sampleIdentifier -> { - MolecularProfileCaseIdentifier profileCaseIdentifier = new MolecularProfileCaseIdentifier(); - profileCaseIdentifier.setMolecularProfileId(profile.getStableId()); - profileCaseIdentifier.setCaseId(sampleIdentifier.getSampleId()); - molecularProfileSampleIdentifiers.add(profileCaseIdentifier); - }); - }); - - }); - }); - - - List genePanelData = genePanelService - .fetchGenePanelDataInMultipleMolecularProfiles(molecularProfileSampleIdentifiers); - - // gene panel data is { profileId, sampleId, isProfiled } - // it tells us whether a particular sample is profiled by a given molecularprofile - // we can use the gene panel to find out what genes were profiled - for (List profileValues : studyViewFilter.getGenomicProfiles()) { - - // using the profileIds from the filter we get a map, stableId to profile entity - Map profileMap = profileValues.stream().flatMap( - profileValue -> molecularProfileSet.getOrDefault(profileValue, new ArrayList<>()).stream()) - .collect(Collectors.toMap(MolecularProfile::getStableId, Function.identity())); - - Set filteredSampleIdentifiers = new HashSet<>(); - - // for each sample/profile combo, we need to find out whether - // the profileMap contains that profile id - genePanelData.forEach(datum -> { - if (datum.getProfiled() && profileMap.containsKey(datum.getMolecularProfileId())) { - SampleIdentifier sampleIdentifier = - studyViewFilterUtil.buildSampleIdentifier(datum.getStudyId(), datum.getSampleId()); - filteredSampleIdentifiers.add(sampleIdentifier); - } - }); - sampleIdentifiers.retainAll(filteredSampleIdentifiers); - } - } - - if (!CollectionUtils.isEmpty(studyViewFilter.getCaseLists())) { - List sampleLists = sampleListService.getAllSampleListsInStudies(studyIds, - Projection.DETAILED.name()); - Map> groupedSampleListByListType = studyViewFilterUtil - .categorizeSampleLists(sampleLists); - - for (List sampleListTypes : studyViewFilter.getCaseLists()) { - List filteredSampleIdentifiers = sampleListTypes.stream() - .flatMap(sampleListType -> groupedSampleListByListType - .getOrDefault(sampleListType, new ArrayList<>()).stream().flatMap(sampleList -> { - return sampleList.getSampleIds().stream().map(sampleId -> - studyViewFilterUtil.buildSampleIdentifier( - sampleList.getCancerStudyIdentifier(), - sampleId)); - })) - .toList(); - - sampleIdentifiers.retainAll(filteredSampleIdentifiers); - } - } - - List mutationOptionDataFilters = new ArrayList<>(); - List mutationTypeDataFilters = new ArrayList<>(); - - List mutationDataFilters = studyViewFilter.getMutationDataFilters(); - - if (!CollectionUtils.isEmpty(mutationDataFilters)) { - mutationDataFilters.forEach(mutationDataFilter -> { - if (mutationDataFilter.getCategorization() == MutationOption.MUTATED) { - mutationOptionDataFilters.add(mutationDataFilter); - } else { - mutationTypeDataFilters.add(mutationDataFilter); - } - }); - } - - if (!CollectionUtils.isEmpty(mutationOptionDataFilters)) { - sampleIdentifiers = filterMutationData(sampleIdentifiers, molecularProfiles, - mutationOptionDataFilters, negateFilters, clinicalDataEqualityFilterApplier); - } - - if (!CollectionUtils.isEmpty(mutationTypeDataFilters)) { - sampleIdentifiers = filterMutationData(sampleIdentifiers, molecularProfiles, - mutationTypeDataFilters, negateFilters, clinicalDataEqualityFilterApplier); - } - - return chainSubFilters(studyViewFilter, sampleIdentifiers); - } - - private List chainSubFilters(StudyViewFilter studyViewFilter, List sampleIdentifiers) { - for (StudyViewSubFilterApplier subFilterApplier : subFilterAppliers) { - if (!sampleIdentifiers.isEmpty() && subFilterApplier.shouldApplyFilter(studyViewFilter)) { - sampleIdentifiers = subFilterApplier.filter(sampleIdentifiers, studyViewFilter); - } - } - - return sampleIdentifiers; - } - - private List intervalFilterClinicalData(List sampleIdentifiers, - List clinicalDataIntervalFilters, - boolean negateFilters) { - return clinicalDataIntervalFilterApplier.apply(sampleIdentifiers, clinicalDataIntervalFilters, negateFilters); - } - - private List equalityFilterClinicalData(List sampleIdentifiers, - List clinicalDataEqualityFilters, - boolean negateFilters) { - return clinicalDataEqualityFilterApplier.apply(sampleIdentifiers, clinicalDataEqualityFilters, negateFilters); - } - - private List filterMutatedGenes(List mutatedGenefilters, - Map molecularProfileMap, List sampleIdentifiers) { - - if (sampleIdentifiers == null || sampleIdentifiers.isEmpty()) { - return new ArrayList<>(); - } - - for (GeneFilter genefilter : mutatedGenefilters) { - - List filteredMolecularProfiles = genefilter - .getMolecularProfileIds() - .stream() - .map(molecularProfileMap::get) - .toList(); - - Map> mapByStudyId = filteredMolecularProfiles - .stream() - .collect(Collectors.groupingBy(MolecularProfile::getCancerStudyIdentifier)); - - for (List geneQueries : genefilter.getGeneQueries()) { - List studyIds = new ArrayList<>(); - List sampleIds = new ArrayList<>(); - - List hugoGeneSymbols = geneQueries - .stream() - .map(GeneFilterQuery::getHugoGeneSymbol) - .toList(); - - Map symbolToEntrezGeneId = geneService - .fetchGenes(new ArrayList<>(hugoGeneSymbols), - GeneIdType.HUGO_GENE_SYMBOL.name(), Projection.SUMMARY.name()) - .stream() - .collect(Collectors.toMap(Gene::getHugoGeneSymbol, Gene::getEntrezGeneId)); - - geneQueries.removeIf( - q -> !symbolToEntrezGeneId.containsKey(q.getHugoGeneSymbol()) - ); - - geneQueries.stream().forEach( - q -> q.setEntrezGeneId(symbolToEntrezGeneId.get(q.getHugoGeneSymbol())) - ); - studyViewFilterUtil.extractStudyAndSampleIds(sampleIdentifiers, studyIds, sampleIds); - - List molecularProfileIds = new ArrayList<>(); - int removedSampleCount = 0; - for (int i = 0; i < studyIds.size(); i++) { - String studyId = studyIds.get(i); - if (mapByStudyId.containsKey(studyId)) { - molecularProfileIds.add(mapByStudyId.get(studyId).get(0).getStableId()); - } else { - sampleIds.remove(i - removedSampleCount); - removedSampleCount++; - } - } - - sampleIdentifiers = mutationService - .getMutationsInMultipleMolecularProfilesByGeneQueries(molecularProfileIds, sampleIds, geneQueries, - Projection.ID.name(), null, null, null, null) - .stream() - .map(m -> studyViewFilterUtil.buildSampleIdentifier(m.getStudyId(), m.getSampleId())) - .distinct() - .collect(Collectors.toList()); - } - - } - return sampleIdentifiers; - } - - private List filterStructuralVariantGenes(List svGenefilters, - Map molecularProfileMap, List sampleIdentifiers) { - - if (sampleIdentifiers == null || sampleIdentifiers.isEmpty()) { - return new ArrayList<>(); - } - - for (GeneFilter genefilter : svGenefilters) { - - List filteredMolecularProfiles = genefilter - .getMolecularProfileIds() - .stream() - .map(molecularProfileMap::get) - .toList(); - - Map> mapByStudyId = filteredMolecularProfiles - .stream() - .collect(Collectors.groupingBy(MolecularProfile::getCancerStudyIdentifier)); - - for (List geneQueries : genefilter.getGeneQueries()) { - List studyIds = new ArrayList<>(); - List sampleIds = new ArrayList<>(); - - List hugoGeneSymbols = geneQueries - .stream() - .map(GeneFilterQuery::getHugoGeneSymbol) - .toList(); - - Map symbolToEntrezGeneId = geneService - .fetchGenes(new ArrayList<>(hugoGeneSymbols), - GeneIdType.HUGO_GENE_SYMBOL.name(), Projection.SUMMARY.name()) - .stream() - .collect(Collectors.toMap(Gene::getHugoGeneSymbol, Gene::getEntrezGeneId)); - - geneQueries.removeIf( - q -> !symbolToEntrezGeneId.containsKey(q.getHugoGeneSymbol()) - ); - - geneQueries.stream().forEach( - q -> q.setEntrezGeneId(symbolToEntrezGeneId.get(q.getHugoGeneSymbol())) - ); - - studyViewFilterUtil.extractStudyAndSampleIds(sampleIdentifiers, studyIds, sampleIds); - - List molecularProfileIds = new ArrayList<>(); - int removedSampleCount = 0; - for (int i = 0; i < studyIds.size(); i++) { - String studyId = studyIds.get(i); - if (mapByStudyId.containsKey(studyId)) { - molecularProfileIds.add(mapByStudyId.get(studyId).get(0).getStableId()); - } else { - sampleIds.remove(i - removedSampleCount); - removedSampleCount++; - } - } - - sampleIdentifiers = structuralVariantService - .fetchStructuralVariantsByGeneQueries(molecularProfileIds, sampleIds, geneQueries) - .stream() - .map(m -> studyViewFilterUtil.buildSampleIdentifier(m.getStudyId(), m.getSampleId())) - .distinct() - .collect(Collectors.toList()); - } - - } - return sampleIdentifiers; - } - - private List filterCNAGenes(List cnaGeneFilters, - Map molecularProfileMap, List sampleIdentifiers) { - - if (sampleIdentifiers == null || sampleIdentifiers.isEmpty()) { - return new ArrayList<>(); - } - - for (GeneFilter geneFilter : cnaGeneFilters) { - - List filteredMolecularProfiles = geneFilter.getMolecularProfileIds().stream() - .map(molecularProfileMap::get) - .toList(); - - for (List geneQueries : geneFilter.getGeneQueries()) { - - List studyIds = new ArrayList<>(); - List sampleIds = new ArrayList<>(); - studyViewFilterUtil.extractStudyAndSampleIds(sampleIdentifiers, studyIds, sampleIds); - - List molecularProfileIds = new ArrayList<>(); - Map> mapByStudyId = filteredMolecularProfiles.stream() - .collect(Collectors.groupingBy(MolecularProfile::getCancerStudyIdentifier)); - int removedSampleCount = 0; - for (int i = 0; i < studyIds.size(); i++) { - String studyId = studyIds.get(i); - if (mapByStudyId.containsKey(studyId)) { - molecularProfileIds.add(mapByStudyId.get(studyId).get(0).getStableId()); - } else { - sampleIds.remove(i - removedSampleCount); - removedSampleCount++; - } - } - - List resultList = DiscreteCopyNumberEventType.ALL - .getAlterationTypes().stream().flatMap(alterationType -> { - - List filteredGeneQueries = geneQueries.stream() - .filter(geneQuery -> geneQuery.getAlterations().stream().anyMatch(alteration -> alteration.getCode() == alterationType)) - .collect(Collectors.toList()); - - List hugoGeneSymbols = filteredGeneQueries.stream() - .map(GeneFilterQuery::getHugoGeneSymbol).toList(); - - Map symbolToEntrezGeneId = geneService - .fetchGenes(new ArrayList<>(hugoGeneSymbols), - GeneIdType.HUGO_GENE_SYMBOL.name(), Projection.SUMMARY.name()) - .stream().collect(Collectors.toMap(Gene::getHugoGeneSymbol, Gene::getEntrezGeneId)); - - filteredGeneQueries.removeIf( - q -> !symbolToEntrezGeneId.containsKey(q.getHugoGeneSymbol()) - ); - - filteredGeneQueries.forEach( - q -> q.setEntrezGeneId(symbolToEntrezGeneId.get(q.getHugoGeneSymbol())) - ); - - List copyNumberDatas = new ArrayList<>(); - if (!filteredGeneQueries.isEmpty()) { - copyNumberDatas = discreteCopyNumberService - .getDiscreteCopyNumbersInMultipleMolecularProfilesByGeneQueries( - molecularProfileIds, - sampleIds, - filteredGeneQueries, - Projection.ID.name()); - } - return copyNumberDatas.stream(); - }).toList(); - - sampleIdentifiers = resultList.stream().map( - d -> studyViewFilterUtil.buildSampleIdentifier(d.getStudyId(), d.getSampleId()) - ).distinct().collect(Collectors.toList()); - } - } - - return sampleIdentifiers; - } - - private List filterMutationData(List sampleIdentifiers, - List molecularProfiles, List mutationDataFilters, - boolean negateFilters, ClinicalDataFilterApplier clinicalDataFilterApplier) { - if (CollectionUtils.isNotEmpty(mutationDataFilters) && CollectionUtils.isNotEmpty(sampleIdentifiers)) { - List clinicalDatas = - fetchMutationDataAndTransformToClinicalDataList(sampleIdentifiers, molecularProfiles, mutationDataFilters); - - - MultiKeyMap clinicalDataMap; - if (clinicalDataFilterApplier instanceof ClinicalDataEqualityFilterApplier) { - clinicalDataMap = ClinicalDataEqualityFilterApplier.buildClinicalDataMap(clinicalDatas); - } else { - clinicalDataMap = ClinicalDataIntervalFilterApplier.buildClinicalDataMap(clinicalDatas); - } - - List newSampleIdentifiers = new ArrayList<>(); - - // loop through each mutationDataFilter and filter data - for (MutationDataFilter mutationDataFilter : mutationDataFilters) { - // loop through each list of DataFilterValue and do union or intersection selections - for (List values : mutationDataFilter.getValues()) { - ClinicalDataFilter clinicalDataFilter = new ClinicalDataFilter(); - clinicalDataFilter.setAttributeId(mutationDataFilter.getHugoGeneSymbol() + mutationDataFilter.getProfileType()); - clinicalDataFilter.setValues(values); - - List attributes = Collections.singletonList(clinicalDataFilter); - - // union selection: filter all samples that have at least one value from a list of DataFilterValue, e.g. Missense_Mutation, In_Shift_Del, ... - List filteredSampleIdentifiers = filterSampleIdentifiers( - sampleIdentifiers, attributes, clinicalDataMap, clinicalDataFilterApplier, negateFilters - ); - - if (newSampleIdentifiers.isEmpty()) { - newSampleIdentifiers = filteredSampleIdentifiers; - } else { - // intersection selection: retain shared samples from each selection for all mutationDataFilter - newSampleIdentifiers.retainAll(filteredSampleIdentifiers); - } - } - } - - return newSampleIdentifiers.stream().distinct().toList(); - } - - return sampleIdentifiers; - } - - private void splitGeneFiltersByMolecularAlterationType(List genefilters, - Map molecularProfileMap, List mutatedGeneFilters, - List structuralVariantGeneFilters, List cnaGeneFilters) { - - for (GeneFilter genefilter : genefilters) { - - List filteredMolecularProfiles = genefilter.getMolecularProfileIds().stream() - // need this filter criteria since profile id might be present - // in filter but the study might already been filtered out - .filter(molecularProfileMap::containsKey) - .map(molecularProfileMap::get) - .toList(); - - Set alterationTypes = filteredMolecularProfiles.stream() - .map(MolecularProfile::getMolecularAlterationType) - .collect(Collectors.toSet()); - - Set dataTypes = filteredMolecularProfiles.stream().map(MolecularProfile::getDatatype) - .collect(Collectors.toSet()); - - Set filteredMolecularProfileIds = filteredMolecularProfiles - .stream() - .map(MolecularProfile::getStableId) - .collect(Collectors.toSet()); - genefilter.setMolecularProfileIds(filteredMolecularProfileIds); - - if (alterationTypes.size() == 1) { - MolecularAlterationType alterationType = alterationTypes.iterator().next(); - - if (alterationType.equals(MolecularAlterationType.STRUCTURAL_VARIANT)) { - structuralVariantGeneFilters.add(genefilter); - } else if (alterationType == MolecularAlterationType.MUTATION_EXTENDED) { - mutatedGeneFilters.add(genefilter); - } else if (alterationType == MolecularAlterationType.COPY_NUMBER_ALTERATION - && dataTypes.size() == 1 && dataTypes.iterator().next().equals("DISCRETE")) { - cnaGeneFilters.add(genefilter); - } - } - } - } - - public List getUniqkeyKeys(List studyIds, List caseIds) { - List uniqkeyKeys = new ArrayList(); - for (int i = 0; i < caseIds.size(); i++) { - uniqkeyKeys.add(studyViewFilterUtil.getCaseUniqueKey(studyIds.get(i), caseIds.get(i))); - } - return uniqkeyKeys; - } - - public List getDataBins( - DataBinMethod dataBinMethod, T dataBinCountFilter) { - List dataBinFilters = fetchDataBinFilters(dataBinCountFilter); - StudyViewFilter studyViewFilter = dataBinCountFilter.getStudyViewFilter(); - - if (dataBinFilters.size() == 1) { - removeSelfFromFilter(dataBinFilters.get(0), studyViewFilter); - } - - List resultDataBins; - List filteredSampleIds = new ArrayList<>(); - List filteredStudyIds = new ArrayList<>(); - - List filteredData = fetchData(dataBinCountFilter, studyViewFilter, filteredSampleIds, - filteredStudyIds); - - List filteredUniqueSampleKeys = getUniqkeyKeys(filteredStudyIds, filteredSampleIds); - - Map> filteredClinicalDataByAttributeId = filteredData.stream() - .collect(Collectors.groupingBy(Binnable::getAttrId)); - - if (dataBinMethod == DataBinMethod.STATIC) { - - StudyViewFilter filter = studyViewFilter == null ? null : new StudyViewFilter(); - if (filter != null) { - filter.setStudyIds(studyViewFilter.getStudyIds()); - filter.setSampleIdentifiers(studyViewFilter.getSampleIdentifiers()); - } - - List unfilteredSampleIds = new ArrayList<>(); - List unfilteredStudyIds = new ArrayList<>(); - List unfilteredData = fetchData(dataBinCountFilter, filter, unfilteredSampleIds, - unfilteredStudyIds); - - List unFilteredUniqueSampleKeys = getUniqkeyKeys(unfilteredSampleIds, unfilteredStudyIds); - - Map> unfilteredDataByAttributeId = unfilteredData.stream() - .collect(Collectors.groupingBy(Binnable::getAttrId)); - - resultDataBins = dataBinFilters.stream().flatMap(dataBinFilter -> { - String attributeId = studyViewFilterUtil.getDataBinFilterUniqueKey(dataBinFilter); - return dataBinner - .calculateClinicalDataBins(dataBinFilter, ClinicalDataType.SAMPLE, - filteredClinicalDataByAttributeId.getOrDefault(attributeId, Collections.emptyList()), - unfilteredDataByAttributeId.getOrDefault(attributeId, Collections.emptyList()), - filteredUniqueSampleKeys, unFilteredUniqueSampleKeys) - .stream().map(dataBin -> (U) transform(dataBinFilter, dataBin)); - - }).collect(Collectors.toList()); - - } else { // dataBinMethod == DataBinMethod.DYNAMIC - resultDataBins = dataBinFilters.stream().flatMap(dataBinFilter -> - dataBinner - .calculateDataBins(dataBinFilter, ClinicalDataType.SAMPLE, - filteredClinicalDataByAttributeId.getOrDefault(studyViewFilterUtil.getDataBinFilterUniqueKey(dataBinFilter), - Collections.emptyList()), - filteredUniqueSampleKeys) - .stream().map(dataBin -> (U) transform(dataBinFilter, dataBin)) - ).collect(Collectors.toList()); - } - - return resultDataBins; - } - - private List fetchData( - S dataBinCountFilter, - StudyViewFilter studyViewFilter, - List sampleIds, - List studyIds - ) { - - List filteredSampleIdentifiers = apply(studyViewFilter); - studyViewFilterUtil.extractStudyAndSampleIds(filteredSampleIdentifiers, studyIds, sampleIds); - - List molecularProfiles = molecularProfileService.getMolecularProfilesInStudies(studyIds, - Projection.SUMMARY.name()); - - Map> molecularProfileMap = molecularProfileUtil - .categorizeMolecularProfilesByStableIdSuffixes(molecularProfiles); - - if (dataBinCountFilter instanceof GenomicDataBinCountFilter genomicDataBinCountFilter) { - List genomicDataBinFilters = genomicDataBinCountFilter.getGenomicDataBinFilters(); - - Set hugoGeneSymbols = genomicDataBinFilters.stream().map(GenomicDataBinFilter::getHugoGeneSymbol) - .collect(Collectors.toSet()); - - Map geneSymbolIdMap = geneService - .fetchGenes(new ArrayList<>(hugoGeneSymbols), GeneIdType.HUGO_GENE_SYMBOL.name(), - Projection.SUMMARY.name()) - .stream().collect(Collectors.toMap(Gene::getHugoGeneSymbol, Gene::getEntrezGeneId)); - - return genomicDataBinFilters.stream().flatMap(genomicDataBinFilter -> { - - Map studyIdToMolecularProfileIdMap = molecularProfileMap - .getOrDefault(genomicDataBinFilter.getProfileType(), new ArrayList<>()).stream() - .collect(Collectors.toMap(MolecularProfile::getCancerStudyIdentifier, - MolecularProfile::getStableId)); - - return invokeDataFunc(sampleIds, studyIds, - List.of(geneSymbolIdMap.get(genomicDataBinFilter.getHugoGeneSymbol()).toString()), - studyIdToMolecularProfileIdMap, studyViewFilterUtil.getDataBinFilterUniqueKey(genomicDataBinFilter), - fetchMolecularData); - }).collect(Collectors.toList()); - } else if (dataBinCountFilter instanceof GenericAssayDataBinCountFilter genomicDataBinCountFilter) { - - List genericAssayDataBinFilters = genomicDataBinCountFilter - .getGenericAssayDataBinFilters(); - - return genericAssayDataBinFilters.stream().flatMap(genericAssayDataBinFilter -> { - - Map studyIdToMolecularProfileIdMap = molecularProfileMap - .getOrDefault(genericAssayDataBinFilter.getProfileType(), new ArrayList<>()) - .stream().collect(Collectors.toMap(MolecularProfile::getCancerStudyIdentifier, - MolecularProfile::getStableId)); - - return invokeDataFunc(sampleIds, studyIds, Collections.singletonList(genericAssayDataBinFilter.getStableId()), - studyIdToMolecularProfileIdMap, studyViewFilterUtil.getDataBinFilterUniqueKey(genericAssayDataBinFilter), - fetchGenericAssayData); - - }).collect(Collectors.toList()); - - } - - return new ArrayList<>(); - } - - private Stream invokeDataFunc(List sampleIds, List studyIds, - List stableIds, Map studyIdToMolecularProfileIdMap, String attributeId, - FourParameterFunction, List, List, String, List> dataFunc) { - - List mappedSampleIds = new ArrayList<>(); - List mappedProfileIds = new ArrayList<>(); - - for (int i = 0; i < sampleIds.size(); i++) { - String studyId = studyIds.get(i); - if (studyIdToMolecularProfileIdMap.containsKey(studyId)) { - mappedSampleIds.add(sampleIds.get(i)); - mappedProfileIds.add(studyIdToMolecularProfileIdMap.get(studyId)); - } - } - - if (mappedSampleIds.isEmpty()) { - return Stream.of(); - } - return dataFunc.apply(mappedProfileIds, mappedSampleIds, stableIds, attributeId) - .stream(); - } - - @FunctionalInterface - private interface FourParameterFunction { - R apply(T t, U u, V v, W w); - } - - FourParameterFunction, List, List, String, List> fetchMolecularData = ( - mappedProfileIds, mappedSampleIds, stableIds, attributeId) -> - molecularDataService.getMolecularDataInMultipleMolecularProfiles(mappedProfileIds, mappedSampleIds, - stableIds.stream().map(Integer::parseInt).toList(), Projection.SUMMARY.name()) - .stream().map(geneMolecularData -> - transformDataToClinicalData(geneMolecularData, attributeId, geneMolecularData.getValue())) - .collect(Collectors.toList()); - - FourParameterFunction, List, List, String, List> fetchGenericAssayData = ( - mappedProfileIds, mappedSampleIds, stableIds, attributeId) -> { - - try { - return genericAssayService - .fetchGenericAssayData(mappedProfileIds, mappedSampleIds, stableIds, Projection.SUMMARY.name()) - .stream().map(genericAssayData -> - transformDataToClinicalData(genericAssayData, attributeId, genericAssayData.getValue()) - ).collect(Collectors.toList()); - } catch (MolecularProfileNotFoundException e) { - return new ArrayList<>(); - } - }; - - FourParameterFunction, List, List, String, List> fetchMutationData = ( - mappedProfileIds, mappedSampleIds, stableIds, attributeId) -> - mutationService.getMutationsInMultipleMolecularProfiles(mappedProfileIds, mappedSampleIds, - stableIds.stream().map(Integer::parseInt).toList(), Projection.DETAILED.name(), - null, null, null, null) - .stream().map(mutationData -> transformDataToClinicalData(mutationData, attributeId, mutationData.getMutationType().toUpperCase()) - ).collect(Collectors.toList()); - - FourParameterFunction, List, List, String, List> fetchMutatedData = ( - mappedProfileIds, mappedSampleIds, stableIds, attributeId) -> - mutationService.getMutationsInMultipleMolecularProfiles(mappedProfileIds, mappedSampleIds, - stableIds.stream().map(Integer::parseInt).toList(), Projection.DETAILED.name(), - null, null, null, null) - .stream().map(mutationData -> transformDataToClinicalData(mutationData, attributeId, MutationFilterOption.MUTATED.name()) - ).collect(Collectors.toList()); - - private List fetchDataBinFilters(T dataBinCountFilter) { - if (dataBinCountFilter instanceof GenomicDataBinCountFilter) { - return (List) ((GenomicDataBinCountFilter) dataBinCountFilter).getGenomicDataBinFilters(); - } else if (dataBinCountFilter instanceof GenericAssayDataBinCountFilter) { - return (List) ((GenericAssayDataBinCountFilter) dataBinCountFilter).getGenericAssayDataBinFilters(); - } - return new ArrayList<>(); - } - - private void removeSelfFromFilter(S dataBinFilter, StudyViewFilter studyViewFilter) { - if (studyViewFilter != null) { - if (dataBinFilter instanceof GenomicDataBinFilter genomicDataBinFilter && - studyViewFilter.getGenomicDataFilters() != null) { - studyViewFilter.getGenomicDataFilters().removeIf(f -> - f.getHugoGeneSymbol().equals(genomicDataBinFilter.getHugoGeneSymbol()) - && f.getProfileType().equals(genomicDataBinFilter.getProfileType()) - ); - } else if (dataBinFilter instanceof GenericAssayDataBinFilter genericAssayDataBinFilter && - studyViewFilter.getGenericAssayDataFilters() != null) { - studyViewFilter.getGenericAssayDataFilters().removeIf(f -> - f.getStableId().equals(genericAssayDataBinFilter.getStableId()) - && f.getProfileType().equals(genericAssayDataBinFilter.getProfileType()) - ); - } - } - } - - private T transform(S dataBinFilter, DataBin dataBin) { - if (dataBinFilter instanceof GenomicDataBinFilter genomicDataBinFilter) { - return (T) dataBintoGenomicDataBin(genomicDataBinFilter, dataBin); - } else if (dataBinFilter instanceof GenericAssayDataBinFilter genericAssayDataBinFilter) { - return (T) dataBintoGenericAssayDataBin(genericAssayDataBinFilter, dataBin); - } - return null; - } - - private GenomicDataBin dataBintoGenomicDataBin(GenomicDataBinFilter genomicDataBinFilter, DataBin dataBin) { - GenomicDataBin genomicDataBin = new GenomicDataBin(); - genomicDataBin.setCount(dataBin.getCount()); - genomicDataBin.setHugoGeneSymbol(genomicDataBinFilter.getHugoGeneSymbol()); - genomicDataBin.setProfileType(genomicDataBinFilter.getProfileType()); - if (dataBin.getSpecialValue() != null) { - genomicDataBin.setSpecialValue(dataBin.getSpecialValue()); - } - if (dataBin.getStart() != null) { - genomicDataBin.setStart(dataBin.getStart()); - } - if (dataBin.getEnd() != null) { - genomicDataBin.setEnd(dataBin.getEnd()); - } - return genomicDataBin; - } - - private GenericAssayDataBin dataBintoGenericAssayDataBin(GenericAssayDataBinFilter genericAssayDataBinFilter, - DataBin dataBin) { - GenericAssayDataBin genericAssayDataBin = new GenericAssayDataBin(); - genericAssayDataBin.setCount(dataBin.getCount()); - genericAssayDataBin.setStableId(genericAssayDataBinFilter.getStableId()); - genericAssayDataBin.setProfileType(genericAssayDataBinFilter.getProfileType()); - if (dataBin.getSpecialValue() != null) { - genericAssayDataBin.setSpecialValue(dataBin.getSpecialValue()); - } - if (dataBin.getStart() != null) { - genericAssayDataBin.setStart(dataBin.getStart()); - } - if (dataBin.getEnd() != null) { - genericAssayDataBin.setEnd(dataBin.getEnd()); - } - return genericAssayDataBin; - } - - public List intervalFilterExpressionData( - List sampleIdentifiers, List molecularProfiles, List dataFilters, - boolean negateFilters) { - - return filterExpressionData(sampleIdentifiers, molecularProfiles, dataFilters, negateFilters, clinicalDataIntervalFilterApplier); - } - - public List equalityFilterExpressionData( - List sampleIdentifiers, List molecularProfiles, List dataFilters, - boolean negateFilters) { - - return filterExpressionData(sampleIdentifiers, molecularProfiles, dataFilters, negateFilters, clinicalDataEqualityFilterApplier); - } - - - public List filterExpressionData( - List sampleIdentifiers, List molecularProfiles, List dataFilters, - boolean negateFilters, ClinicalDataFilterApplier clinicalDataFilterApplier) { - if (!CollectionUtils.isEmpty(dataFilters) && !CollectionUtils.isEmpty(sampleIdentifiers)) { - List clinicalDatas = - fetchDataAndTransformToClinicalDataList(sampleIdentifiers, molecularProfiles, dataFilters); - List attributes = transformToClinicalDataFilter(dataFilters); - - MultiKeyMap clinicalDataMap; - if (clinicalDataFilterApplier instanceof ClinicalDataEqualityFilterApplier) { - clinicalDataMap = ClinicalDataEqualityFilterApplier.buildClinicalDataMap(clinicalDatas); - } else { - clinicalDataMap = ClinicalDataIntervalFilterApplier.buildClinicalDataMap(clinicalDatas); - } - - return filterSampleIdentifiers(sampleIdentifiers, attributes, clinicalDataMap, clinicalDataFilterApplier, negateFilters).stream().distinct().toList(); - } - - return sampleIdentifiers; - } - - private List fetchDataAndTransformToClinicalDataList( - List sampleIdentifiers, List molecularProfiles, List dataFilters) { - Map> molecularProfileMap = molecularProfileUtil - .categorizeMolecularProfilesByStableIdSuffixes(molecularProfiles); - - List studyIds = new ArrayList<>(); - List sampleIds = new ArrayList<>(); - studyViewFilterUtil.extractStudyAndSampleIds(sampleIdentifiers, studyIds, sampleIds); - - if (dataFilters.getFirst() instanceof GenomicDataFilter) { - List genomicDataIntervalFilters = (List) dataFilters; - Set hugoGeneSymbols = genomicDataIntervalFilters.stream() - .map(GenomicDataFilter::getHugoGeneSymbol).collect(Collectors.toSet()); - Map geneNameIdMap = geneService - .fetchGenes(new ArrayList<>(hugoGeneSymbols), GeneIdType.HUGO_GENE_SYMBOL.name(), - Projection.SUMMARY.name()) - .stream().collect(Collectors.toMap(Gene::getHugoGeneSymbol, Gene::getEntrezGeneId)); - - return genomicDataIntervalFilters.stream().flatMap(genomicDataFilter -> { - - List subMolecularProfiles = molecularProfileMap - .getOrDefault(genomicDataFilter.getProfileType(), new ArrayList<>()); - Map studyIdToMolecularProfileIdMap = subMolecularProfiles - .stream().collect(Collectors.toMap(MolecularProfile::getCancerStudyIdentifier, - MolecularProfile::getStableId)); - - return invokeDataFunc(sampleIds, studyIds, - Collections.singletonList(geneNameIdMap.get(genomicDataFilter.getHugoGeneSymbol()).toString()), - studyIdToMolecularProfileIdMap, studyViewFilterUtil.getDataFilterUniqueKey(genomicDataFilter), - fetchMolecularData); - }).collect(Collectors.toList()); - - } else { - return ((List) dataFilters).stream().flatMap(genericAssayDataFilter -> { - - Map studyIdToMolecularProfileIdMap = molecularProfileMap - .getOrDefault(genericAssayDataFilter.getProfileType(), new ArrayList()) - .stream().collect(Collectors.toMap(MolecularProfile::getCancerStudyIdentifier, - MolecularProfile::getStableId)); - - // get original data stream from invokeDataFunc - Stream dataStream = invokeDataFunc(sampleIds, studyIds, Collections.singletonList(genericAssayDataFilter.getStableId()), - studyIdToMolecularProfileIdMap, studyViewFilterUtil.getDataFilterUniqueKey(genericAssayDataFilter), fetchGenericAssayData); - // For patient level generic assay profile, only keep the one sample per patient - List profiles = molecularProfileMap.getOrDefault(genericAssayDataFilter.getProfileType(), new ArrayList<>()); - if (profiles.size() > 0 && profiles.get(0).getPatientLevel()) { - dataStream = dataStream.collect(Collectors.groupingBy(ClinicalData::getPatientId)).values().stream() - .flatMap(d -> d.stream().limit(1)); - } - // don't change anything for non patient level data - return dataStream; - }).collect(Collectors.toList()); - } - } - - private List fetchMutationDataAndTransformToClinicalDataList( - List sampleIdentifiers, List molecularProfiles, List mutationDataFilters - ) { - Map> molecularProfileMap = molecularProfileUtil - .categorizeMolecularProfilesByStableIdSuffixes(molecularProfiles); - - List studyIds = new ArrayList<>(); - List sampleIds = new ArrayList<>(); - studyViewFilterUtil.extractStudyAndSampleIds(sampleIdentifiers, studyIds, sampleIds); - - Set hugoGeneSymbols = mutationDataFilters.stream() - .map(MutationDataFilter::getHugoGeneSymbol).collect(Collectors.toSet()); - Map geneNameIdMap = geneService - .fetchGenes(new ArrayList<>(hugoGeneSymbols), GeneIdType.HUGO_GENE_SYMBOL.name(), - Projection.SUMMARY.name()) - .stream().collect(Collectors.toMap(Gene::getHugoGeneSymbol, Gene::getEntrezGeneId)); - - return mutationDataFilters.stream().flatMap(mutationDataFilter -> { - List subMolecularProfiles = molecularProfileMap - .getOrDefault(mutationDataFilter.getProfileType(), new ArrayList<>()); - Map studyIdToMolecularProfileIdMap = subMolecularProfiles - .stream().collect(Collectors.toMap(MolecularProfile::getCancerStudyIdentifier, - MolecularProfile::getStableId)); - - if (mutationDataFilter.getCategorization() == MutationOption.MUTATED) { - return fetchMutatedAndWildTypeData( - sampleIdentifiers, geneNameIdMap, mutationDataFilter, - studyIdToMolecularProfileIdMap); - } else { - // fetch mutation type data - return invokeDataFunc(sampleIds, studyIds, Collections.singletonList( - geneNameIdMap.get(mutationDataFilter.getHugoGeneSymbol()).toString()), - studyIdToMolecularProfileIdMap, - studyViewFilterUtil.getMutationDataFilterUniqueKey(mutationDataFilter), - fetchMutationData); - } - }).collect(Collectors.toList()); - } - - private List transformToClinicalDataFilter(List dataFilters) { - List attributes; - attributes = dataFilters.stream().map(dataFilter -> { - ClinicalDataFilter clinicalDataFilter = new ClinicalDataFilter(); - clinicalDataFilter.setAttributeId(studyViewFilterUtil.getDataFilterUniqueKey(dataFilter)); - clinicalDataFilter.setValues(dataFilter.getValues()); - return clinicalDataFilter; - }).collect(Collectors.toList()); - return attributes; - } - - private List fetchProfiledMutationDataByGene(List studyIds, List sampleIds, Integer entrezGeneId) { - List molecularProfileCaseIdentifiers = - molecularProfileService.getMutationProfileCaseIdentifiers(studyIds, sampleIds); - - List genePanelDataList = genePanelService - .fetchGenePanelDataInMultipleMolecularProfiles(molecularProfileCaseIdentifiers); - - Function sampleIdentifierBuilder = sample -> - studyViewFilterUtil.buildSampleIdentifier(sample.getStudyId(), sample.getSampleId()); - - Map> casesWithDataInGenePanel = new HashMap<>(); - // loop through all membership records -- ignore any where g.getGenePanelId == null - for (GenePanelData genePanelDataRecord : genePanelDataList) { - String associatedGenePanel = genePanelDataRecord.getGenePanelId(); - if (associatedGenePanel != null) { - casesWithDataInGenePanel.putIfAbsent(associatedGenePanel, new HashSet<>()); - Set casesForThisGenePanel = casesWithDataInGenePanel.get(associatedGenePanel); - casesForThisGenePanel.add(sampleIdentifierBuilder.apply(genePanelDataRecord)); - } - } - - List genePanels = new ArrayList<>(); - if (!casesWithDataInGenePanel.isEmpty()) { - genePanels = genePanelService.fetchGenePanels(new ArrayList<>(casesWithDataInGenePanel.keySet()), Projection.DETAILED.name()); - } - - List genePanelData = genePanelDataList - .stream() - .filter(GenePanelData::getProfiled) - .toList(); - - Set profiledCases = genePanelData - .stream() - // there can be duplicate patient or sample id, append study id - .map(sampleIdentifierBuilder) - .collect(Collectors.toSet()); - - // here we look for cases where none of the profiles have gene panel ids - // a case with at least one profile with gene panel id is considered as a case with gene panel data - // so a case is considered without panel data only if none of the profiles has a gene panel id - - // first identify cases with gene panel data - Set casesWithPanelData = genePanelData - .stream() - .filter(g -> g.getGenePanelId() != null) - // there can be duplicate patient or sample id, append study id - .map(sampleIdentifierBuilder) - .collect(Collectors.toSet()); - - // find all unique cases - Set casesWithoutPanelData = genePanelData - .stream() - // there can be duplicate patient or sample id, append study id - .map(sampleIdentifierBuilder) - .collect(Collectors.toSet()); - - // removing cases with panel data from all unique cases gives us the cases without panel data - casesWithoutPanelData.removeAll(casesWithPanelData); - - List genePanelIds = genePanels.stream().flatMap(genePanel -> { - List genePanelToGenes = genePanel.getGenes(); - return genePanelToGenes - .stream() - .filter(genePanelToGene -> genePanelToGene.getEntrezGeneId().equals(entrezGeneId)) - .map(GenePanelToGene::getGenePanelId); - }).toList(); - - List newSampleIdentifiers = new ArrayList<>(); - // different calculations depending on if gene is linked to gene panels - if (CollectionUtils.isNotEmpty(genePanelIds)) { - // for every gene panel associated containing the gene, use the sum of unique cases - // as well as cases without panel data - for (String genePanelId : genePanelIds) { - newSampleIdentifiers.addAll(casesWithDataInGenePanel.get(genePanelId)); - } - newSampleIdentifiers.addAll(casesWithoutPanelData); - } else { - // we use profiledCasesCount instead of casesWithoutPanelData to - // prevent a divide by zero error which can happen for targeted studies - // in which certain genes have events that are not captured by the panel. - newSampleIdentifiers.addAll(profiledCases); - } - - return newSampleIdentifiers; - } - - private Stream fetchMutatedAndWildTypeData( - List sampleIdentifiers, Map geneNameIdMap, MutationDataFilter mutationDataFilter, - Map studyIdToMolecularProfileIdMap) { - List studyIds = new ArrayList<>(); - List sampleIds = new ArrayList<>(); - studyViewFilterUtil.extractStudyAndSampleIds(sampleIdentifiers, studyIds, sampleIds); - - // mutated - List mutatedClinicalDatas = invokeDataFunc(sampleIds, studyIds, - Collections.singletonList(geneNameIdMap.get(mutationDataFilter.getHugoGeneSymbol()).toString()), - studyIdToMolecularProfileIdMap, studyViewFilterUtil.getMutationDataFilterUniqueKey(mutationDataFilter), - fetchMutatedData).toList(); - - List mutatedSampleIdentifiers = mutatedClinicalDatas - .stream() - .map(datum -> studyViewFilterUtil.buildSampleIdentifier(datum.getStudyId(), datum.getSampleId()) - ).toList(); - - List clinicalDatas = new ArrayList<>(mutatedClinicalDatas); - - // not profiled - List profiledSampleIdentifiers = fetchProfiledMutationDataByGene( - studyIds, sampleIds, geneNameIdMap.get(mutationDataFilter.getHugoGeneSymbol())); - - List notProfiledSampleIdentifiers = sampleIdentifiers - .stream() - .filter(s -> profiledSampleIdentifiers.stream().noneMatch(p -> p.equals(s))) - .toList(); - - List notProfiledClinicalDatas = studyViewFilterUtil.transformSampleIdentifiersToClinicalData( - notProfiledSampleIdentifiers, - studyViewFilterUtil.getMutationDataFilterUniqueKey(mutationDataFilter), - MutationFilterOption.NOT_PROFILED.name() - ); - - clinicalDatas.addAll(notProfiledClinicalDatas); - - // not mutated - List notMutatedSampleIdentifiers = profiledSampleIdentifiers - .stream() - .filter(p -> mutatedSampleIdentifiers.stream().noneMatch(m -> m.equals(p))) - .toList(); - - List notMutatedClinicalDatas = studyViewFilterUtil.transformSampleIdentifiersToClinicalData( - notMutatedSampleIdentifiers, - studyViewFilterUtil.getMutationDataFilterUniqueKey(mutationDataFilter), - MutationFilterOption.NOT_MUTATED.name() - ); - - clinicalDatas.addAll(notMutatedClinicalDatas); - - return clinicalDatas.stream(); - } - - private ClinicalData transformDataToClinicalData(S data, String attributeId, String attributeValue) { - ClinicalData clinicalData = new ClinicalData(); - - if (data instanceof MolecularData molecularData) { - clinicalData.setPatientId(molecularData.getPatientId()); - clinicalData.setSampleId(molecularData.getSampleId()); - clinicalData.setStudyId(molecularData.getStudyId()); - } else if (data instanceof Mutation mutationData) { - clinicalData.setPatientId(mutationData.getPatientId()); - clinicalData.setSampleId(mutationData.getSampleId()); - clinicalData.setStudyId(mutationData.getStudyId()); - } else { - return clinicalData; - } - - clinicalData.setAttrValue(attributeValue); - clinicalData.setAttrId(attributeId); - - return clinicalData; - } - - private List filterSampleIdentifiers( - List sampleIdentifiers, - List attributes, - MultiKeyMap clinicalDataMap, - ClinicalDataFilterApplier clinicalDataFilterApplier, - boolean negateFilters - ) { - return sampleIdentifiers.stream() - .filter(sampleIdentifier -> { - int count = clinicalDataFilterApplier.apply( - attributes, - clinicalDataMap, - sampleIdentifier.getSampleId(), - sampleIdentifier.getStudyId(), - negateFilters - ); - return count == attributes.size(); - }) - .collect(Collectors.toList()); - } -} diff --git a/src/main/java/org/cbioportal/web/util/StudyViewFilterUtil.java b/src/main/java/org/cbioportal/web/util/StudyViewFilterUtil.java deleted file mode 100644 index b44b8bd8a63..00000000000 --- a/src/main/java/org/cbioportal/web/util/StudyViewFilterUtil.java +++ /dev/null @@ -1,433 +0,0 @@ -package org.cbioportal.web.util; - -import org.apache.commons.collections4.CollectionUtils; -import org.apache.commons.collections4.map.MultiKeyMap; -import org.cbioportal.model.Binnable; -import org.cbioportal.model.ClinicalData; -import org.cbioportal.model.ClinicalDataCount; -import org.cbioportal.model.ClinicalDataCountItem; -import org.cbioportal.model.Gene; -import org.cbioportal.model.Patient; -import org.cbioportal.model.SampleList; -import org.cbioportal.model.StructuralVariantFilterQuery; -import org.cbioportal.model.StructuralVariantSpecialValue; -import org.cbioportal.service.GeneService; -import org.cbioportal.service.util.CustomDataSession; -import org.cbioportal.service.util.CustomDataValue; -import org.cbioportal.web.parameter.*; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -@Component -public class StudyViewFilterUtil { - - private final GeneService geneService; - - @Autowired - public StudyViewFilterUtil(GeneService geneService) { - this.geneService = geneService; - } - - public StudyViewFilterUtil() { - geneService = null; - } - - public void extractStudyAndSampleIds( - List sampleIdentifiers, - List studyIds, - List sampleIds - ) { - for (SampleIdentifier sampleIdentifier : sampleIdentifiers) { - studyIds.add(sampleIdentifier.getStudyId()); - sampleIds.add(sampleIdentifier.getSampleId()); - } - } - - public void removeSelfFromFilter(String attributeId, StudyViewFilter studyViewFilter) { - if (studyViewFilter != null && studyViewFilter.getClinicalDataFilters() != null) { - studyViewFilter.getClinicalDataFilters().removeIf(f -> f.getAttributeId().equals(attributeId)); - } - } - - public void removeSelfFromGenomicDataFilter(String hugoGeneSymbol, String profileType, StudyViewFilter studyViewFilter) { - if (studyViewFilter != null && studyViewFilter.getGenomicDataFilters() != null) { - studyViewFilter.getGenomicDataFilters().removeIf(f -> - f.getHugoGeneSymbol().equals(hugoGeneSymbol) && f.getProfileType().equals(profileType) - ); - } - } - - public void removeSelfFromMutationDataFilter(String hugoGeneSymbol, String profileType, MutationOption categorization, StudyViewFilter studyViewFilter) { - if (studyViewFilter != null && studyViewFilter.getMutationDataFilters() != null) { - studyViewFilter.getMutationDataFilters().removeIf(f -> - f.getHugoGeneSymbol().equals(hugoGeneSymbol) && - f.getProfileType().equals(profileType) && - f.getCategorization().equals(categorization) - ); - } - } - - public void removeSelfFromGenericAssayFilter(String stableId, StudyViewFilter studyViewFilter) { - if (studyViewFilter != null && studyViewFilter.getGenericAssayDataFilters() != null) { - studyViewFilter.getGenericAssayDataFilters().removeIf(f -> f.getStableId().equals(stableId)); - } - } - - public void removeSelfCustomDataFromFilter(String attributeId, StudyViewFilter studyViewFilter) { - if (studyViewFilter != null && studyViewFilter.getCustomDataFilters() != null) { - studyViewFilter.getCustomDataFilters().removeIf(f -> f.getAttributeId().equals(attributeId)); - } - } - - public String getCaseUniqueKey(String studyId, String caseId) { - return studyId + caseId; - } - - public String getDataFilterUniqueKey(S dataFilter) { - if (dataFilter instanceof GenomicDataFilter genomicDataFilter) { - return genomicDataFilter.getHugoGeneSymbol() + genomicDataFilter.getProfileType(); - } else if (dataFilter instanceof GenericAssayDataFilter genericAssayDataFilter) { - return genericAssayDataFilter.getStableId() + genericAssayDataFilter.getProfileType(); - } - return null; - } - - public String getMutationDataFilterUniqueKey(MutationDataFilter mutationDataFilter) { - return mutationDataFilter.getHugoGeneSymbol() + mutationDataFilter.getProfileType(); - } - - public String getDataBinFilterUniqueKey(S dataBinFilter) { - if (dataBinFilter instanceof GenomicDataBinFilter genomicDataBinFilter) { - return genomicDataBinFilter.getHugoGeneSymbol() + genomicDataBinFilter.getProfileType(); - } else if (dataBinFilter instanceof GenericAssayDataBinFilter genericAssayDataBinFilter) { - return genericAssayDataBinFilter.getStableId() + genericAssayDataBinFilter.getProfileType(); - } - return null; - } - - public Map> categorizeSampleLists(List sampleLists) { - return sampleLists.stream().collect(Collectors.groupingBy(sampleList -> { - return sampleList.getStableId().replace(sampleList.getCancerStudyIdentifier() + "_", ""); - })); - } - - public Integer getFilteredCountByDataEquality(List attributes, MultiKeyMap clinicalDataMap, - String entityId, String studyId, boolean negateFilters) { - Integer count = 0; - for (ClinicalDataFilter s : attributes) { - List filteredValues = s.getValues() - .stream() - .map(DataFilterValue::getValue) - .collect(Collectors.toList()); - filteredValues.replaceAll(String::toUpperCase); - if (clinicalDataMap.containsKey(studyId, entityId, s.getAttributeId())) { - S value = clinicalDataMap.get(studyId, entityId, s.getAttributeId()); - if (value instanceof String) { - if (negateFilters ^ filteredValues.contains(value)) { - count++; - } - } else if (value instanceof List && - negateFilters ^ filteredValues.stream().anyMatch(((List) value)::contains)) { - count++; - } - } else if (negateFilters ^ filteredValues.contains("NA")) { - count++; - } - } - return count; - } - - public List getClinicalDataCountsFromCustomData(Collection customDataSessions, - Map filteredSamplesMap, List patients) { - int totalSamplesCount = filteredSamplesMap.keySet().size(); - int totalPatientsCount = patients.size(); - - return customDataSessions.stream().map(customDataSession -> { - - Map> groupedDatabyValue = customDataSession.getData().getData().stream() - .filter(datum -> filteredSamplesMap - .containsKey(getCaseUniqueKey(datum.getStudyId(), datum.getSampleId())) - ).collect(Collectors.groupingBy(CustomDataValue::getValue)); - - ClinicalDataCountItem clinicalDataCountItem = new ClinicalDataCountItem(); - clinicalDataCountItem.setAttributeId(customDataSession.getId()); - - List clinicalDataCounts = groupedDatabyValue.entrySet().stream() - .map(entry -> { - long count = entry.getValue().stream().map(datum -> { - return getCaseUniqueKey(datum.getStudyId(), - customDataSession.getData().getPatientAttribute() - ? datum.getPatientId() - : datum.getSampleId()); - - }).distinct().count(); - ClinicalDataCount dataCount = new ClinicalDataCount(); - dataCount.setAttributeId(customDataSession.getId()); - dataCount.setValue(entry.getKey()); - dataCount.setCount(Math.toIntExact(count)); - return dataCount; - }) - .filter(c -> !c.getValue().equalsIgnoreCase("NA") && !c.getValue().equalsIgnoreCase("NAN") - && !c.getValue().equalsIgnoreCase("N/A")) - .collect(Collectors.toList()); - - int totalCount = clinicalDataCounts.stream().mapToInt(ClinicalDataCount::getCount).sum(); - int naCount = 0; - if (customDataSession.getData().getPatientAttribute()) { - naCount = totalPatientsCount - totalCount; - } else { - naCount = totalSamplesCount - totalCount; - } - if (naCount > 0) { - ClinicalDataCount clinicalDataCount = new ClinicalDataCount(); - clinicalDataCount.setAttributeId(customDataSession.getId()); - clinicalDataCount.setValue("NA"); - clinicalDataCount.setCount(naCount); - clinicalDataCounts.add(clinicalDataCount); - } - - clinicalDataCountItem.setCounts(clinicalDataCounts); - return clinicalDataCountItem; - }).collect(Collectors.toList()); - } - - public boolean isSingleStudyUnfiltered(StudyViewFilter filter) { - return isSingleStudy(filter) && isUnfilteredQuery(filter); - } - - public boolean isSingleStudy(StudyViewFilter filter) { - return filter.getStudyIds() != null && - filter.getStudyIds().size() == 1; - } - - public boolean isUnfilteredQuery(StudyViewFilter filter) { - return filter.getStudyIds() != null && - (filter.getClinicalDataFilters() == null || filter.getClinicalDataFilters().isEmpty()) && - (filter.getGeneFilters() == null || filter.getGeneFilters().isEmpty()) && - (filter.getSampleTreatmentFilters() == null || filter.getSampleTreatmentFilters().getFilters().isEmpty()) && - (filter.getPatientTreatmentFilters() == null || filter.getPatientTreatmentFilters().getFilters().isEmpty()) && - (filter.getGenomicProfiles() == null || filter.getGenomicProfiles().isEmpty()) && - (filter.getGenomicDataFilters() == null || filter.getGenomicDataFilters().isEmpty()) && - (filter.getGenericAssayDataFilters() == null || filter.getGenericAssayDataFilters().isEmpty()) && - (filter.getCaseLists() == null || filter.getCaseLists().isEmpty()) && - (filter.getCustomDataFilters() == null || filter.getCustomDataFilters().isEmpty()) && - (filter.getMutationDataFilters() == null || filter.getMutationDataFilters().isEmpty()); - } - - public boolean shouldSkipFilterForClinicalDataBins(StudyViewFilter filter) { - // if everything other than study ids and sample identifiers is null, - // we can skip the filter for data bin calculation - return ( - filter != null && - filter.getClinicalDataFilters() == null && - filter.getClinicalEventFilters() == null && - filter.getMutationDataFilters() == null && - filter.getStructuralVariantFilters() == null && - filter.getGeneFilters() == null && - filter.getSampleTreatmentFilters() == null && - filter.getPatientTreatmentFilters() == null && - filter.getPatientTreatmentGroupFilters() == null && - filter.getSampleTreatmentGroupFilters() == null && - filter.getPatientTreatmentTargetFilters() == null && - filter.getSampleTreatmentTargetFilters() == null && - filter.getGenomicProfiles() == null && - filter.getGenomicDataFilters() == null && - filter.getGenericAssayDataFilters() == null && - filter.getCaseLists() == null && - filter.getCustomDataFilters() == null - ); - } - - public List filterClinicalData( - List unfilteredClinicalDataForSamples, - List unfilteredClinicalDataForPatients, - List unfilteredClinicalDataForConflictingPatientAttributes, - List studyIds, - List sampleIds, - List studyIdsOfPatients, - List patientIds, - List sampleAttributeIds, - List patientAttributeIds, - List conflictingPatientAttributes - ) { - List combinedResult = new ArrayList<>(); - - Map patientIdToStudyId = null; - - if (CollectionUtils.isNotEmpty(sampleAttributeIds)) { - // create lookups for faster filtering - Map sampleIdToStudyId = mapCaseToStudy(sampleIds, studyIds); - Map sampleAttributeIdLookup = listToMap(sampleAttributeIds); - - combinedResult.addAll( - filterClinicalDataByStudyAndSampleAndAttribute( - unfilteredClinicalDataForSamples, - sampleIdToStudyId, - sampleAttributeIdLookup - ) - ); - } - - if (CollectionUtils.isNotEmpty(patientAttributeIds)) { - // create lookups for faster filtering - Map patientAttributeIdLookup = listToMap(patientAttributeIds); - patientIdToStudyId = mapCaseToStudy(patientIds, studyIdsOfPatients); - - combinedResult.addAll( - filterClinicalDataByStudyAndPatientAndAttribute( - unfilteredClinicalDataForPatients, - patientIdToStudyId, - patientAttributeIdLookup - ) - ); - } - - if (CollectionUtils.isNotEmpty(conflictingPatientAttributes)) { - // create lookups for faster filtering - Map conflictingPatientAttributeIdLookup = listToMap(conflictingPatientAttributes); - if (patientIdToStudyId == null) { - patientIdToStudyId = mapCaseToStudy(patientIds, studyIdsOfPatients); - } - - combinedResult.addAll( - filterClinicalDataByStudyAndPatientAndAttribute( - unfilteredClinicalDataForConflictingPatientAttributes, - patientIdToStudyId, - conflictingPatientAttributeIdLookup - ) - ); - } - - return combinedResult; - } - - - - private Map getStringIntegerMap(List hugoGeneSymbols) { - Map symbolToEntrezGeneId = geneService - .fetchGenes(new ArrayList<>(hugoGeneSymbols), - GeneIdType.HUGO_GENE_SYMBOL.name(), Projection.SUMMARY.name()) - .stream() - .collect(Collectors.toMap(Gene::getHugoGeneSymbol, Gene::getEntrezGeneId)); - return symbolToEntrezGeneId; - } - - public List resolveEntrezGeneIds(List structVarQueries) { - - List hugoGeneSymbols = structVarQueries - .stream() - .flatMap(q -> Stream.of(q.getGene1Query(), q.getGene2Query())) - .filter(structVarIdentifier -> structVarIdentifier.getHugoSymbol() != null) - .map(structVarIdentifier -> structVarIdentifier.getHugoSymbol()) - .collect(Collectors.toList()); - - Map symbolToEntrezGeneId = getStringIntegerMap(hugoGeneSymbols); - - // Add Entrez gene ids to the queries. - structVarQueries.forEach(structVarQuery -> { - structVarQuery.getGene1Query().setEntrezId( - symbolToEntrezGeneId.getOrDefault(structVarQuery.getGene1Query().getHugoSymbol(), null) - ); - structVarQuery.getGene2Query().setEntrezId( - symbolToEntrezGeneId.getOrDefault(structVarQuery.getGene2Query().getHugoSymbol(), null) - ); - }); - - // Remove any genes where the Entrez gene id is needed, but translation failed. - structVarQueries.removeIf( - q -> (q.getGene1Query().getSpecialValue() != StructuralVariantSpecialValue.NO_GENE - && q.getGene1Query().getSpecialValue() != StructuralVariantSpecialValue.ANY_GENE - && q.getGene1Query().getEntrezId() == null) - || (q.getGene2Query().getSpecialValue() != StructuralVariantSpecialValue.NO_GENE - && q.getGene2Query().getSpecialValue() != StructuralVariantSpecialValue.ANY_GENE - && q.getGene2Query().getEntrezId() == null) - ); - - return structVarQueries; - } - - private List filterClinicalDataByStudyAndSampleAndAttribute( - List clinicalData, - Map sampleToStudyId, - Map attributeIdLookup - ) { - return clinicalData - .stream() - .filter(d -> - sampleToStudyId.getOrDefault(generateSampleToStudyKey(d), "").equals(d.getStudyId()) && - attributeIdLookup.getOrDefault(d.getAttrId(), false) - ) - .collect(Collectors.toList()); - } - - private List filterClinicalDataByStudyAndPatientAndAttribute( - List clinicalData, - Map patientToStudyId, - Map attributeIdLookup - ) { - return clinicalData - .stream() - .filter(d -> - patientToStudyId.getOrDefault(generatePatientToStudyKey(d), "").equals(d.getStudyId()) && - attributeIdLookup.getOrDefault(d.getAttrId(), false) - ) - .collect(Collectors.toList()); - } - - private Map listToMap(List list) { - return list.stream().collect(Collectors.toMap(s -> s, s -> true, (s1, s2) -> s1)); - } - - private Map mapCaseToStudy(List caseIds, List studyIds) { - Map caseToStudy = new HashMap<>(); - - for (int i = 0; i < caseIds.size(); i++) { - String studyId = studyIds.get(i); - String caseId = caseIds.get(i); - String key = generateCaseToStudyKey(studyId, caseId); - caseToStudy.put(key, studyId); - } - - return caseToStudy; - } - - private String generateSampleToStudyKey(Binnable clinicalData) { - return generateCaseToStudyKey(clinicalData.getStudyId(), clinicalData.getSampleId()); - } - - private String generatePatientToStudyKey(Binnable clinicalData) { - return generateCaseToStudyKey(clinicalData.getStudyId(), clinicalData.getPatientId()); - } - - private String generateCaseToStudyKey(String studyId, String caseId) { - return studyId + ":" + caseId; - } - - public SampleIdentifier buildSampleIdentifier(String studyId, String sampleId) { - SampleIdentifier sampleIdentifier = new SampleIdentifier(); - sampleIdentifier.setStudyId(studyId); - sampleIdentifier.setSampleId(sampleId); - return sampleIdentifier; - } - - public List transformSampleIdentifiersToClinicalData(List sampleIdentifiers, String attributeId, String attributeValue) { - return sampleIdentifiers - .stream() - .map(sampleIdentifier -> { - ClinicalData clinicalData = new ClinicalData(); - clinicalData.setAttrId(attributeId); - clinicalData.setAttrValue(attributeValue); - clinicalData.setSampleId(sampleIdentifier.getSampleId()); - clinicalData.setStudyId(sampleIdentifier.getStudyId()); - return clinicalData; - }).collect(Collectors.toList()); - } -} diff --git a/src/main/java/org/cbioportal/web/util/UniqueKeyExtractor.java b/src/main/java/org/cbioportal/web/util/UniqueKeyExtractor.java deleted file mode 100644 index 90d99dfe0a0..00000000000 --- a/src/main/java/org/cbioportal/web/util/UniqueKeyExtractor.java +++ /dev/null @@ -1,27 +0,0 @@ -package org.cbioportal.web.util; - -import org.cbioportal.utils.Encoder; -import java.util.List; -import java.util.Collection; - -public class UniqueKeyExtractor { - - private UniqueKeyExtractor() {} - - public static void extractUniqueKeys(List uniqueKeys, Collection studyIdsToReturn) { - extractUniqueKeys(uniqueKeys, studyIdsToReturn, null); - } - - public static void extractUniqueKeys(List uniqueKeys, Collection studyIdsToReturn, Collection patientOrSampleIdsToReturn) { - for (String uniqueKey : uniqueKeys) { - String uniqueId = Encoder.decodeBase64(uniqueKey); - String[] patientOrSampleAndStudyId = uniqueId.split(Encoder.DELIMITER); - if (patientOrSampleAndStudyId.length == 2) { - if (patientOrSampleIdsToReturn != null) { - patientOrSampleIdsToReturn.add(patientOrSampleAndStudyId[0]); - } - studyIdsToReturn.add(patientOrSampleAndStudyId[1]); - } - } - } -} diff --git a/src/main/java/org/cbioportal/web/util/appliers/AbstractPatientTreatmentFilter.java b/src/main/java/org/cbioportal/web/util/appliers/AbstractPatientTreatmentFilter.java deleted file mode 100644 index 30d507d297a..00000000000 --- a/src/main/java/org/cbioportal/web/util/appliers/AbstractPatientTreatmentFilter.java +++ /dev/null @@ -1,62 +0,0 @@ -package org.cbioportal.web.util.appliers; - -import org.cbioportal.model.ClinicalEventKeyCode; -import org.cbioportal.model.PatientTreatmentRow; -import org.cbioportal.service.TreatmentService; -import org.cbioportal.web.parameter.SampleIdentifier; -import org.cbioportal.web.parameter.StudyViewFilter; -import org.cbioportal.web.parameter.filter.AndedPatientTreatmentFilters; -import org.springframework.beans.factory.annotation.Autowired; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.stream.Collectors; - -public abstract class AbstractPatientTreatmentFilter implements StudyViewSubFilterApplier { - @Autowired - TreatmentService treatmentService; - - @Autowired - TreatmentRowExtractor treatmentRowExtractor; - - @Override - public List filter( - List identifiers, - StudyViewFilter filter - ) { - - if (identifiers == null || identifiers.isEmpty()) { - return new ArrayList<>(); - } - - AndedPatientTreatmentFilters filters = getFilters(filter); - - List sampleIds = identifiers.stream() - .map(SampleIdentifier::getSampleId) - .collect(Collectors.toList()); - - List studyIds = identifiers.stream() - .map(SampleIdentifier::getStudyId) - .collect(Collectors.toList()); - - Map> rows = - treatmentService.getAllPatientTreatmentRows(sampleIds, studyIds, getCode()) - .stream() - .collect(Collectors.toMap(PatientTreatmentRow::getTreatment, treatmentRowExtractor::extractSamples)); - - return identifiers.stream() - .filter(i -> filters.filter(i, rows)) - .collect(Collectors.toList()); - } - - protected abstract AndedPatientTreatmentFilters getFilters(StudyViewFilter filter); - - protected abstract ClinicalEventKeyCode getCode(); - - @Override - public boolean shouldApplyFilter(StudyViewFilter studyViewFilter) { - return getFilters(studyViewFilter) != null && !getFilters(studyViewFilter).getFilters().isEmpty(); - } -} diff --git a/src/main/java/org/cbioportal/web/util/appliers/AbstractSampleTreatmentFilter.java b/src/main/java/org/cbioportal/web/util/appliers/AbstractSampleTreatmentFilter.java deleted file mode 100644 index c28dcefbcbd..00000000000 --- a/src/main/java/org/cbioportal/web/util/appliers/AbstractSampleTreatmentFilter.java +++ /dev/null @@ -1,61 +0,0 @@ -package org.cbioportal.web.util.appliers; - -import org.cbioportal.model.ClinicalEventKeyCode; -import org.cbioportal.model.SampleTreatmentRow; -import org.cbioportal.service.TreatmentService; -import org.cbioportal.web.parameter.SampleIdentifier; -import org.cbioportal.web.parameter.StudyViewFilter; -import org.cbioportal.web.parameter.filter.AndedSampleTreatmentFilters; -import org.springframework.beans.factory.annotation.Autowired; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.stream.Collectors; - -public abstract class AbstractSampleTreatmentFilter implements StudyViewSubFilterApplier { - @Autowired - TreatmentService treatmentService; - - @Autowired - TreatmentRowExtractor treatmentRowExtractor; - - @Override - public List filter ( - List identifiers, - StudyViewFilter filter - ) { - - if (identifiers == null || identifiers.isEmpty()) { - return new ArrayList<>(); - } - - AndedSampleTreatmentFilters filters = getFilters(filter); - - List sampleIds = identifiers.stream() - .map(SampleIdentifier::getSampleId) - .collect(Collectors.toList()); - List studyIds = identifiers.stream() - .map(SampleIdentifier::getStudyId) - .collect(Collectors.toList()); - - Map> rows = - treatmentService.getAllSampleTreatmentRows(sampleIds, studyIds, getCode()) - .stream() - .collect(Collectors.toMap(SampleTreatmentRow::key, treatmentRowExtractor::extractSamples)); - - return identifiers.stream() - .filter(id -> filters.filter(id, rows)) - .collect(Collectors.toList()); - } - - protected abstract AndedSampleTreatmentFilters getFilters(StudyViewFilter filter); - - protected abstract ClinicalEventKeyCode getCode(); - - @Override - public boolean shouldApplyFilter(StudyViewFilter studyViewFilter) { - return getFilters(studyViewFilter) != null && !getFilters(studyViewFilter).getFilters().isEmpty(); - } -} diff --git a/src/main/java/org/cbioportal/web/util/appliers/ClinicalEventFilterApplier.java b/src/main/java/org/cbioportal/web/util/appliers/ClinicalEventFilterApplier.java deleted file mode 100644 index adf70d4a782..00000000000 --- a/src/main/java/org/cbioportal/web/util/appliers/ClinicalEventFilterApplier.java +++ /dev/null @@ -1,88 +0,0 @@ -package org.cbioportal.web.util.appliers; - -import org.cbioportal.service.ClinicalEventService; -import org.cbioportal.web.parameter.DataFilter; -import org.cbioportal.web.parameter.DataFilterValue; -import org.cbioportal.web.parameter.SampleIdentifier; -import org.cbioportal.web.parameter.StudyViewFilter; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.lang.NonNull; -import org.springframework.stereotype.Component; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Set; -import java.util.stream.Collectors; - - -@Component -public final class ClinicalEventFilterApplier implements StudyViewSubFilterApplier { - - @Autowired - private ClinicalEventService clinicalEventService; - - @Override - public List filter(@NonNull List toFilter, @NonNull StudyViewFilter filters) { - - if (toFilter == null || toFilter.isEmpty()) { - return new ArrayList<>(); - } - - List studyIds = toFilter.stream() - .map(SampleIdentifier::getStudyId) - .collect(Collectors.toList()); - - List sampleIds = toFilter.stream() - .map(SampleIdentifier::getSampleId) - .collect(Collectors.toList()); - - Map> samplesPerEventType = clinicalEventService.getPatientsSamplesPerClinicalEventType(studyIds, sampleIds); - - List clinicalEventFilters = filters.getClinicalEventFilters().stream() - .map(ClinicalEventFilter::new) - .collect(Collectors.toList()); - - return toFilter.stream() - .filter(i -> applyClinicalEventFilter(i, clinicalEventFilters, samplesPerEventType)) - .collect(Collectors.toList()); - } - - boolean applyClinicalEventFilter(SampleIdentifier sampleIdentifier, List eventFilters, Map> samplesPerEventType) { - for(ClinicalEventFilter eventFilter : eventFilters) { - if(!eventFilter.filter(sampleIdentifier, samplesPerEventType)){ - return false; - } - } - return true; - } - @Override - public boolean shouldApplyFilter(@NonNull StudyViewFilter studyViewFilter) { - return studyViewFilter.getClinicalEventFilters() != null && !studyViewFilter.getClinicalEventFilters().isEmpty(); - } - - private static class ClinicalEventFilter { - private final List filters; - ClinicalEventFilter(DataFilter filters) { - this.filters = filters.getValues(); - } - - public boolean filter(SampleIdentifier s, Map> samplesPerEventType) { - if(Objects.isNull(filters) || filters.isEmpty()) { - return true; - } - - for(DataFilterValue filter : filters) { - Collection samples = samplesPerEventType.get(filter.getValue()); - - if(!Objects.isNull(samples) && samples.contains(s.getSampleId())) { - return true; - } - } - - return false; - } - } -} diff --git a/src/main/java/org/cbioportal/web/util/appliers/PatientTreatmentFilterApplier.java b/src/main/java/org/cbioportal/web/util/appliers/PatientTreatmentFilterApplier.java deleted file mode 100644 index c97c313ec8b..00000000000 --- a/src/main/java/org/cbioportal/web/util/appliers/PatientTreatmentFilterApplier.java +++ /dev/null @@ -1,20 +0,0 @@ -package org.cbioportal.web.util.appliers; - -import org.cbioportal.model.ClinicalEventKeyCode; -import org.cbioportal.web.parameter.StudyViewFilter; -import org.cbioportal.web.parameter.filter.AndedPatientTreatmentFilters; -import org.springframework.stereotype.Component; - -@Component -public class PatientTreatmentFilterApplier extends AbstractPatientTreatmentFilter { - - @Override - protected AndedPatientTreatmentFilters getFilters(StudyViewFilter filter) { - return filter.getPatientTreatmentFilters(); - } - - @Override - protected ClinicalEventKeyCode getCode() { - return ClinicalEventKeyCode.Agent; - } -} diff --git a/src/main/java/org/cbioportal/web/util/appliers/PatientTreatmentGroupFilterApplier.java b/src/main/java/org/cbioportal/web/util/appliers/PatientTreatmentGroupFilterApplier.java deleted file mode 100644 index 6110d4aa8e3..00000000000 --- a/src/main/java/org/cbioportal/web/util/appliers/PatientTreatmentGroupFilterApplier.java +++ /dev/null @@ -1,20 +0,0 @@ -package org.cbioportal.web.util.appliers; - -import org.cbioportal.model.ClinicalEventKeyCode; -import org.cbioportal.web.parameter.StudyViewFilter; -import org.cbioportal.web.parameter.filter.AndedPatientTreatmentFilters; -import org.springframework.stereotype.Component; - -@Component -public class PatientTreatmentGroupFilterApplier extends AbstractPatientTreatmentFilter { - - @Override - protected AndedPatientTreatmentFilters getFilters(StudyViewFilter filter) { - return filter.getPatientTreatmentGroupFilters(); - } - - @Override - protected ClinicalEventKeyCode getCode() { - return ClinicalEventKeyCode.AgentClass; - } -} diff --git a/src/main/java/org/cbioportal/web/util/appliers/PatientTreatmentTargetFilterApplier.java b/src/main/java/org/cbioportal/web/util/appliers/PatientTreatmentTargetFilterApplier.java deleted file mode 100644 index 87c69ea8fbc..00000000000 --- a/src/main/java/org/cbioportal/web/util/appliers/PatientTreatmentTargetFilterApplier.java +++ /dev/null @@ -1,20 +0,0 @@ -package org.cbioportal.web.util.appliers; - -import org.cbioportal.model.ClinicalEventKeyCode; -import org.cbioportal.web.parameter.StudyViewFilter; -import org.cbioportal.web.parameter.filter.AndedPatientTreatmentFilters; -import org.springframework.stereotype.Component; - -@Component -public class PatientTreatmentTargetFilterApplier extends AbstractPatientTreatmentFilter { - - @Override - protected AndedPatientTreatmentFilters getFilters(StudyViewFilter filter) { - return filter.getPatientTreatmentTargetFilters(); - } - - @Override - protected ClinicalEventKeyCode getCode() { - return ClinicalEventKeyCode.AgentTarget; - } -} diff --git a/src/main/java/org/cbioportal/web/util/appliers/SampleTreatmentFilterApplier.java b/src/main/java/org/cbioportal/web/util/appliers/SampleTreatmentFilterApplier.java deleted file mode 100644 index 83e6bd7301a..00000000000 --- a/src/main/java/org/cbioportal/web/util/appliers/SampleTreatmentFilterApplier.java +++ /dev/null @@ -1,20 +0,0 @@ -package org.cbioportal.web.util.appliers; - -import org.cbioportal.model.ClinicalEventKeyCode; -import org.cbioportal.web.parameter.StudyViewFilter; -import org.cbioportal.web.parameter.filter.AndedSampleTreatmentFilters; -import org.springframework.stereotype.Component; - -@Component -public class SampleTreatmentFilterApplier extends AbstractSampleTreatmentFilter { - - @Override - protected AndedSampleTreatmentFilters getFilters(StudyViewFilter filter) { - return filter.getSampleTreatmentFilters(); - } - - @Override - protected ClinicalEventKeyCode getCode() { - return ClinicalEventKeyCode.Agent; - } -} diff --git a/src/main/java/org/cbioportal/web/util/appliers/SampleTreatmentGroupFilterApplier.java b/src/main/java/org/cbioportal/web/util/appliers/SampleTreatmentGroupFilterApplier.java deleted file mode 100644 index 9f0e3aa0b31..00000000000 --- a/src/main/java/org/cbioportal/web/util/appliers/SampleTreatmentGroupFilterApplier.java +++ /dev/null @@ -1,19 +0,0 @@ -package org.cbioportal.web.util.appliers; - -import org.cbioportal.model.ClinicalEventKeyCode; -import org.cbioportal.web.parameter.StudyViewFilter; -import org.cbioportal.web.parameter.filter.AndedSampleTreatmentFilters; -import org.springframework.stereotype.Component; - -@Component -public class SampleTreatmentGroupFilterApplier extends AbstractSampleTreatmentFilter { - @Override - protected AndedSampleTreatmentFilters getFilters(StudyViewFilter filter) { - return filter.getSampleTreatmentGroupFilters(); - } - - @Override - protected ClinicalEventKeyCode getCode() { - return ClinicalEventKeyCode.AgentClass; - } -} diff --git a/src/main/java/org/cbioportal/web/util/appliers/SampleTreatmentTargetFilterApplier.java b/src/main/java/org/cbioportal/web/util/appliers/SampleTreatmentTargetFilterApplier.java deleted file mode 100644 index d7d6c37b449..00000000000 --- a/src/main/java/org/cbioportal/web/util/appliers/SampleTreatmentTargetFilterApplier.java +++ /dev/null @@ -1,20 +0,0 @@ -package org.cbioportal.web.util.appliers; - -import org.cbioportal.model.ClinicalEventKeyCode; -import org.cbioportal.web.parameter.StudyViewFilter; -import org.cbioportal.web.parameter.filter.AndedSampleTreatmentFilters; -import org.springframework.stereotype.Component; - -@Component -public class SampleTreatmentTargetFilterApplier extends AbstractSampleTreatmentFilter { - - @Override - protected AndedSampleTreatmentFilters getFilters(StudyViewFilter filter) { - return filter.getSampleTreatmentTargetFilters(); - } - - @Override - protected ClinicalEventKeyCode getCode() { - return ClinicalEventKeyCode.AgentTarget; - } -} diff --git a/src/main/java/org/cbioportal/web/util/appliers/StructuralVariantSubFilterApplier.java b/src/main/java/org/cbioportal/web/util/appliers/StructuralVariantSubFilterApplier.java deleted file mode 100644 index 9367c54884b..00000000000 --- a/src/main/java/org/cbioportal/web/util/appliers/StructuralVariantSubFilterApplier.java +++ /dev/null @@ -1,112 +0,0 @@ -package org.cbioportal.web.util.appliers; - -import org.cbioportal.model.MolecularProfile; -import org.cbioportal.model.StructuralVariantFilterQuery; -import org.cbioportal.model.StudyViewStructuralVariantFilter; -import org.cbioportal.service.MolecularProfileService; -import org.cbioportal.service.StructuralVariantService; -import org.cbioportal.web.parameter.SampleIdentifier; -import org.cbioportal.web.parameter.StudyViewFilter; -import org.cbioportal.web.util.StudyViewFilterUtil; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.function.Function; -import java.util.stream.Collectors; - -@Component -public class StructuralVariantSubFilterApplier implements StudyViewSubFilterApplier { - - @Autowired - private MolecularProfileService molecularProfileService; - - @Autowired - private StructuralVariantService structuralVariantService; - - @Autowired - private StudyViewFilterUtil studyViewFilterUtil; - - @Override - public List filter(List toFilter, StudyViewFilter filters) { - - final List structVarFilters = getStructVarFilters(filters); - - List includedStudyIds = toFilter.stream() - .map(SampleIdentifier::getStudyId) - .distinct() - .collect(Collectors.toList()); - - List molecularProfiles = molecularProfileService.getMolecularProfilesInStudies(includedStudyIds, "SUMMARY"); - - Map molecularProfileMap = molecularProfiles.stream() - .collect(Collectors.toMap(MolecularProfile::getStableId, Function.identity())); - - List remainingSampleIdentifiers = toFilter; - - for (StudyViewStructuralVariantFilter structuralVariantFilter : structVarFilters) { - - // Collect molecular profiles referenced in gene filter. - List filteredMolecularProfiles = structuralVariantFilter - .getMolecularProfileIds() - .stream() - .map(molecularProfileId -> molecularProfileMap.get(molecularProfileId)) - .collect(Collectors.toList()); - - Map> mapByStudyId = filteredMolecularProfiles - .stream() - .collect(Collectors.groupingBy(MolecularProfile::getCancerStudyIdentifier)); - - for (List structVarQueries: structuralVariantFilter.getStructVarQueries()) { - - // Remove samples in remainingSampleIdentifiers that belong to a study that is not accessible to the current user - // (do not appear in the molecularProfileMap argument). - final List filteredSampleIdentifiers = remainingSampleIdentifiers.stream() - .filter(i -> mapByStudyId.containsKey(i.getStudyId())).collect(Collectors.toList()); - - final List molecularProfileIds = filteredSampleIdentifiers.stream() - .map(i -> mapByStudyId.get(i.getStudyId()).get(0).getStableId()) - .distinct() - .collect(Collectors.toList()); - - final List sampleIds = filteredSampleIdentifiers.stream() - .map(SampleIdentifier::getSampleId) - .collect(Collectors.toList()); - - final List entrezIdEnhancedSvQueries = studyViewFilterUtil.resolveEntrezGeneIds(structVarQueries); - remainingSampleIdentifiers = structuralVariantService - .fetchStructuralVariantsByStructVarQueries(molecularProfileIds, sampleIds, entrezIdEnhancedSvQueries) - .stream() - .map(m -> { - SampleIdentifier sampleIdentifier = new SampleIdentifier(); - sampleIdentifier.setSampleId(m.getSampleId()); - sampleIdentifier.setStudyId(m.getStudyId()); - return sampleIdentifier; - }) - .distinct() - .collect(Collectors.toList()); - } - - } - return remainingSampleIdentifiers; - } - - @Override - public boolean shouldApplyFilter(StudyViewFilter studyViewFilter) { - return !getStructVarFilters(studyViewFilter).isEmpty(); - } - - private static List getStructVarFilters(StudyViewFilter filters) { - final List structuralVariantFilters = filters.getStructuralVariantFilters(); - if (structuralVariantFilters == null || structuralVariantFilters.isEmpty()) { - return new ArrayList<>(); - } - final List structVarFilters = structuralVariantFilters.stream() - .filter(structuralVariantFilter -> !structuralVariantFilter.getStructVarQueries().isEmpty()) - .collect(Collectors.toList()); - return structVarFilters; - } - -} diff --git a/src/main/java/org/cbioportal/web/util/appliers/StudyViewSubFilterApplier.java b/src/main/java/org/cbioportal/web/util/appliers/StudyViewSubFilterApplier.java deleted file mode 100644 index 8ba7dc037ef..00000000000 --- a/src/main/java/org/cbioportal/web/util/appliers/StudyViewSubFilterApplier.java +++ /dev/null @@ -1,12 +0,0 @@ -package org.cbioportal.web.util.appliers; - -import org.cbioportal.web.parameter.SampleIdentifier; -import org.cbioportal.web.parameter.StudyViewFilter; - -import java.util.List; - -public interface StudyViewSubFilterApplier { - List filter(List toFilter, StudyViewFilter filters); - - boolean shouldApplyFilter(StudyViewFilter studyViewFilter); -} diff --git a/src/main/java/org/cbioportal/web/util/appliers/TreatmentRowExtractor.java b/src/main/java/org/cbioportal/web/util/appliers/TreatmentRowExtractor.java deleted file mode 100644 index f260304356a..00000000000 --- a/src/main/java/org/cbioportal/web/util/appliers/TreatmentRowExtractor.java +++ /dev/null @@ -1,17 +0,0 @@ -package org.cbioportal.web.util.appliers; - -import org.cbioportal.model.ClinicalEventSample; -import org.cbioportal.model.TreatmentRow; -import org.springframework.stereotype.Service; - -import java.util.Set; -import java.util.stream.Collectors; - -@Service -public class TreatmentRowExtractor { - public Set extractSamples(TreatmentRow row) { - return row.getSamples().stream() - .map(ClinicalEventSample::key) - .collect(Collectors.toSet()); - } -} diff --git a/src/main/resources/application.properties.EXAMPLE b/src/main/resources/application.properties.EXAMPLE index e3cd32283e6..b7b2fb178f6 100644 --- a/src/main/resources/application.properties.EXAMPLE +++ b/src/main/resources/application.properties.EXAMPLE @@ -136,9 +136,6 @@ skin.study_view.link_text=To build your own case set, try out our enhanced Study ## setting controlling whether Download tabs and download/copy-to-clipboard controls should be shown # skin.hide_download_controls=false -## setting controlling which name should be used to display the authenticated user (email, or username) -# skin.user_display_name=email - ## enable and set this property to specify a study group to be used to identify public studies for which no specific authorization entries are needed in the `authorities` table # always_show_study_group= @@ -239,7 +236,9 @@ pathway_commons.url=http://www.pathwaycommons.org/pc2 bitly.access.token= # google analytics -google_analytics_profile_id= +# Note: use one or the other of these properties, not both +# google_analytics_profile_id= +# google_tag_manager_id= # genomespace linking genomespace=true diff --git a/src/main/resources/db-scripts/cgds.sql b/src/main/resources/db-scripts/cgds.sql index 2971b3d1be6..6ccd9828c70 100644 --- a/src/main/resources/db-scripts/cgds.sql +++ b/src/main/resources/db-scripts/cgds.sql @@ -1,5 +1,5 @@ -- --- Copyright (c) 2016 - 2022 Memorial Sloan Kettering Cancer Center. +-- Copyright (c) 2016 - 2025 Memorial Sloan Kettering Cancer Center. -- -- This library is distributed in the hope that it will be useful, but WITHOUT -- ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS @@ -41,12 +41,16 @@ -- tables are created before referring tables. -- DROP TABLE statements are here in the reverse order. -- -------------------------------------------------------- - +DROP TABLE IF EXISTS `resource_study`; +DROP TABLE IF EXISTS `resource_patient`; +DROP TABLE IF EXISTS `resource_sample`; +DROP TABLE IF EXISTS `resource_definition`; DROP TABLE IF EXISTS `info`; +DROP TABLE IF EXISTS `allele_specific_copy_number`; +DROP TABLE IF EXISTS `data_access_tokens`; +DROP TABLE IF EXISTS `reference_genome_gene`; DROP TABLE IF EXISTS `clinical_event_data`; DROP TABLE IF EXISTS `clinical_event`; -DROP TABLE IF EXISTS `pdb_uniprot_residue_mapping`; -DROP TABLE IF EXISTS `pdb_uniprot_alignment`; DROP TABLE IF EXISTS `cosmic_mutation`; DROP TABLE IF EXISTS `copy_number_seg_file`; DROP TABLE IF EXISTS `copy_number_seg`; @@ -58,14 +62,10 @@ DROP TABLE IF EXISTS `mut_sig`; DROP TABLE IF EXISTS `clinical_attribute_meta`; DROP TABLE IF EXISTS `clinical_sample`; DROP TABLE IF EXISTS `clinical_patient`; -DROP TABLE IF EXISTS `resource_definition`; -DROP TABLE IF EXISTS `resource_sample`; -DROP TABLE IF EXISTS `resource_patient`; -DROP TABLE IF EXISTS `resource_study`; DROP TABLE IF EXISTS `mutation_count_by_keyword`; -DROP TABLE IF EXISTS `allele_specific_copy_number`; DROP TABLE IF EXISTS `mutation`; DROP TABLE IF EXISTS `mutation_event`; +DROP TABLE IF EXISTS `alteration_driver_annotation`; DROP TABLE IF EXISTS `structural_variant`; DROP TABLE IF EXISTS `sample_profile`; DROP TABLE IF EXISTS `gene_panel_list`; @@ -73,30 +73,33 @@ DROP TABLE IF EXISTS `gene_panel`; DROP TABLE IF EXISTS `genetic_profile_samples`; DROP TABLE IF EXISTS `genetic_alteration`; DROP TABLE IF EXISTS `genetic_profile_link`; -DROP TABLE IF EXISTS `alteration_driver_annotation`; DROP TABLE IF EXISTS `genetic_profile`; -DROP TABLE IF EXISTS `gene_alias`; +DROP TABLE IF EXISTS `generic_entity_properties`; +DROP TABLE IF EXISTS `geneset_hierarchy_leaf`; +DROP TABLE IF EXISTS `geneset_hierarchy_node`; DROP TABLE IF EXISTS `geneset_gene`; -DROP TABLE IF EXISTS `reference_genome_gene`; +DROP TABLE IF EXISTS `geneset`; +DROP TABLE IF EXISTS `gene_alias`; DROP TABLE IF EXISTS `gene`; +DROP TABLE IF EXISTS `genetic_entity`; DROP TABLE IF EXISTS `sample_list_list`; DROP TABLE IF EXISTS `sample_list`; DROP TABLE IF EXISTS `sample`; DROP TABLE IF EXISTS `patient`; DROP TABLE IF EXISTS `authorities`; -DROP TABLE IF EXISTS `data_access_tokens`; DROP TABLE IF EXISTS `users`; DROP TABLE IF EXISTS `cancer_study_tags`; DROP TABLE IF EXISTS `cancer_study`; -DROP TABLE IF EXISTS `type_of_cancer`; -DROP TABLE IF EXISTS `geneset_hierarchy_leaf`; -DROP TABLE IF EXISTS `geneset_hierarchy_node`; -DROP TABLE IF EXISTS `geneset`; -DROP TABLE IF EXISTS `generic_entity_properties`; -DROP TABLE IF EXISTS `genetic_entity`; DROP TABLE IF EXISTS `reference_genome`; - +DROP TABLE IF EXISTS `type_of_cancer`; -- -------------------------------------------------------- +-- Reminder : Do not simply append to the drop list above. +-- If you added a new table at the END of the +-- create list, you should add a matching DROP +-- statement at the BEGINNING of the drop list. +-- See the comment above. +-- -------------------------------------------------------- + CREATE TABLE `type_of_cancer` ( `TYPE_OF_CANCER_ID` varchar(63) NOT NULL, `NAME` varchar(255) NOT NULL, @@ -108,15 +111,15 @@ CREATE TABLE `type_of_cancer` ( -- -------------------------------------------------------- CREATE TABLE `reference_genome` ( - `REFERENCE_GENOME_ID` int(4) NOT NULL AUTO_INCREMENT, - `SPECIES` varchar(64) NOT NULL, - `NAME` varchar(64) NOT NULL, - `BUILD_NAME` varchar(64) NOT NULL, - `GENOME_SIZE` bigint(20) NULL, - `URL` varchar(256) NOT NULL, - `RELEASE_DATE` datetime DEFAULT NULL, - PRIMARY KEY (`REFERENCE_GENOME_ID`), - UNIQUE INDEX `BUILD_NAME_UNIQUE` (`BUILD_NAME` ASC) + `REFERENCE_GENOME_ID` int(4) NOT NULL AUTO_INCREMENT, + `SPECIES` varchar(64) NOT NULL, + `NAME` varchar(64) NOT NULL, + `BUILD_NAME` varchar(64) NOT NULL, + `GENOME_SIZE` bigint(20) NULL, + `URL` varchar(256) NOT NULL, + `RELEASE_DATE` datetime DEFAULT NULL, + PRIMARY KEY (`REFERENCE_GENOME_ID`), + UNIQUE INDEX `BUILD_NAME_UNIQUE` (`BUILD_NAME` ASC) ); -- -------------------------------------------------------- @@ -202,7 +205,6 @@ CREATE TABLE `sample_list_list` ( ); -- -------------------------------------------------------- - CREATE TABLE `genetic_entity` ( `ID` int(11) NOT NULL AUTO_INCREMENT, `ENTITY_TYPE` varchar(45) NOT NULL, @@ -249,7 +251,7 @@ CREATE TABLE `geneset` ( CREATE TABLE `geneset_gene` ( `GENESET_ID` INT(11) NOT NULL, `ENTREZ_GENE_ID` INT(11) NOT NULL, - PRIMARY KEY (`GENESET_ID`, `ENTREZ_GENE_ID`), + PRIMARY KEY (`GENESET_ID`,`ENTREZ_GENE_ID`), FOREIGN KEY (`ENTREZ_GENE_ID`) REFERENCES `gene` (`ENTREZ_GENE_ID`) ON DELETE CASCADE, FOREIGN KEY (`GENESET_ID`) REFERENCES `geneset` (`ID`) ON DELETE CASCADE ); @@ -267,7 +269,7 @@ CREATE TABLE `geneset_hierarchy_node` ( CREATE TABLE `geneset_hierarchy_leaf` ( `NODE_ID` BIGINT NOT NULL, `GENESET_ID` INT NOT NULL, - PRIMARY KEY (`NODE_ID`, `GENESET_ID`), + PRIMARY KEY (`NODE_ID`,`GENESET_ID`), FOREIGN KEY (`NODE_ID`) REFERENCES `geneset_hierarchy_node` (`NODE_ID`) ON DELETE CASCADE, FOREIGN KEY (`GENESET_ID`) REFERENCES `geneset` (`ID`) ON DELETE CASCADE ); @@ -278,7 +280,7 @@ CREATE TABLE `generic_entity_properties` ( `GENETIC_ENTITY_ID` INT NOT NULL, `NAME` varchar(255) NOT NULL, `VALUE` varchar(5000) NOT NULL, - UNIQUE (`GENETIC_ENTITY_ID`, `NAME`), + UNIQUE (`GENETIC_ENTITY_ID`,`NAME`), PRIMARY KEY (`ID`), FOREIGN KEY (`GENETIC_ENTITY_ID`) REFERENCES `genetic_entity` (`ID`) ON DELETE CASCADE ); @@ -307,9 +309,9 @@ CREATE TABLE `genetic_profile_link` ( `REFERRING_GENETIC_PROFILE_ID` INT NOT NULL, `REFERRED_GENETIC_PROFILE_ID` INT NOT NULL, `REFERENCE_TYPE` VARCHAR(45) NULL, -- COMMENT 'Values: AGGREGATION (e.g. for GSVA) or STATISTIC (e.g. for Z-SCORES) - PRIMARY KEY (`REFERRING_GENETIC_PROFILE_ID`, `REFERRED_GENETIC_PROFILE_ID`), - FOREIGN KEY (`REFERRING_GENETIC_PROFILE_ID` ) REFERENCES `genetic_profile` (`GENETIC_PROFILE_ID`) ON DELETE CASCADE, - FOREIGN KEY (`REFERRED_GENETIC_PROFILE_ID` ) REFERENCES `genetic_profile` (`GENETIC_PROFILE_ID`) ON DELETE NO ACTION ON UPDATE NO ACTION + PRIMARY KEY (`REFERRING_GENETIC_PROFILE_ID`,`REFERRED_GENETIC_PROFILE_ID`), + FOREIGN KEY (`REFERRING_GENETIC_PROFILE_ID`) REFERENCES `genetic_profile` (`GENETIC_PROFILE_ID`) ON DELETE CASCADE, + FOREIGN KEY (`REFERRED_GENETIC_PROFILE_ID`) REFERENCES `genetic_profile` (`GENETIC_PROFILE_ID`) ON DELETE NO ACTION ON UPDATE NO ACTION ); -- -------------------------------------------------------- @@ -343,7 +345,7 @@ CREATE TABLE `gene_panel` ( CREATE TABLE `gene_panel_list` ( `INTERNAL_ID` int(11) NOT NULL, `GENE_ID` int(11) NOT NULL, - PRIMARY KEY (`INTERNAL_ID`, `GENE_ID`), + PRIMARY KEY (`INTERNAL_ID`,`GENE_ID`), FOREIGN KEY (`INTERNAL_ID`) REFERENCES `gene_panel` (`INTERNAL_ID`) ON DELETE CASCADE, FOREIGN KEY (`GENE_ID`) REFERENCES `gene` (`ENTREZ_GENE_ID`) ON DELETE CASCADE ); @@ -418,7 +420,7 @@ CREATE TABLE `alteration_driver_annotation` ( `DRIVER_FILTER_ANNOTATION` VARCHAR(80), `DRIVER_TIERS_FILTER` VARCHAR(50), `DRIVER_TIERS_FILTER_ANNOTATION` VARCHAR(80), - PRIMARY KEY (`ALTERATION_EVENT_ID`, `GENETIC_PROFILE_ID`, `SAMPLE_ID`), + PRIMARY KEY (`ALTERATION_EVENT_ID`,`GENETIC_PROFILE_ID`,`SAMPLE_ID`), FOREIGN KEY (`GENETIC_PROFILE_ID`) REFERENCES `genetic_profile` (`GENETIC_PROFILE_ID`) ON DELETE CASCADE, FOREIGN KEY (`SAMPLE_ID`) REFERENCES `sample` (`INTERNAL_ID`) ON DELETE CASCADE, INDEX (`DRIVER_FILTER`), @@ -450,7 +452,7 @@ CREATE TABLE `mutation_event` ( `KEYWORD` varchar(255) DEFAULT NULL COMMENT 'e.g. truncating, V200 Missense, E338del, ', KEY (`KEYWORD`), PRIMARY KEY (`MUTATION_EVENT_ID`), - KEY `KEY_MUTATION_EVENT_DETAILS` (`CHR`, `START_POSITION`, `END_POSITION`, `TUMOR_SEQ_ALLELE`(240), `ENTREZ_GENE_ID`, `PROTEIN_CHANGE`, `MUTATION_TYPE`), + KEY `KEY_MUTATION_EVENT_DETAILS` (`CHR`,`START_POSITION`,`END_POSITION`,`TUMOR_SEQ_ALLELE`(240),`ENTREZ_GENE_ID`,`PROTEIN_CHANGE`,`MUTATION_TYPE`), FOREIGN KEY (`ENTREZ_GENE_ID`) REFERENCES `gene` (`ENTREZ_GENE_ID`), INDEX (`MUTATION_TYPE`) ) COMMENT='Mutation Data'; @@ -501,14 +503,14 @@ CREATE TABLE `mutation` ( -- -------------------------------------------------------- CREATE TABLE `mutation_count_by_keyword` ( - `GENETIC_PROFILE_ID` int(11) NOT NULL, - `KEYWORD` varchar(255) DEFAULT NULL, - `ENTREZ_GENE_ID` int(11) NOT NULL, - `KEYWORD_COUNT` int NOT NULL, - `GENE_COUNT` int NOT NULL, - KEY (`GENETIC_PROFILE_ID`,`KEYWORD`), - FOREIGN KEY (`GENETIC_PROFILE_ID`) REFERENCES `genetic_profile` (`GENETIC_PROFILE_ID`) ON DELETE CASCADE, - FOREIGN KEY (`ENTREZ_GENE_ID`) REFERENCES `gene` (`ENTREZ_GENE_ID`) ON DELETE CASCADE + `GENETIC_PROFILE_ID` int(11) NOT NULL, + `KEYWORD` varchar(255) DEFAULT NULL, + `ENTREZ_GENE_ID` int(11) NOT NULL, + `KEYWORD_COUNT` int NOT NULL, + `GENE_COUNT` int NOT NULL, + KEY (`GENETIC_PROFILE_ID`,`KEYWORD`), + FOREIGN KEY (`GENETIC_PROFILE_ID`) REFERENCES `genetic_profile` (`GENETIC_PROFILE_ID`) ON DELETE CASCADE, + FOREIGN KEY (`ENTREZ_GENE_ID`) REFERENCES `gene` (`ENTREZ_GENE_ID`) ON DELETE CASCADE ); -- -------------------------------------------------------- @@ -516,7 +518,7 @@ CREATE TABLE `clinical_patient` ( `INTERNAL_ID` int(11) NOT NULL, `ATTR_ID` varchar(255) NOT NULL, `ATTR_VALUE` varchar(255) NOT NULL, - PRIMARY KEY (`INTERNAL_ID`, `ATTR_ID`), + PRIMARY KEY (`INTERNAL_ID`,`ATTR_ID`), FOREIGN KEY (`INTERNAL_ID`) REFERENCES `patient` (`INTERNAL_ID`) ON DELETE CASCADE ); @@ -551,7 +553,7 @@ CREATE TABLE `mut_sig` ( `NumMutations` int(11) NOT NULL, `P_VALUE` float NOT NULL, `Q_VALUE` float NOT NULL, - PRIMARY KEY (`CANCER_STUDY_ID`, `ENTREZ_GENE_ID`), + PRIMARY KEY (`CANCER_STUDY_ID`,`ENTREZ_GENE_ID`), FOREIGN KEY (`CANCER_STUDY_ID`) REFERENCES `cancer_study` (`CANCER_STUDY_ID`) ON DELETE CASCADE, FOREIGN KEY (`ENTREZ_GENE_ID`) REFERENCES `gene` (`ENTREZ_GENE_ID`) ); @@ -574,7 +576,7 @@ CREATE TABLE `gistic` ( CREATE TABLE `gistic_to_gene` ( `GISTIC_ROI_ID` bigint(20) NOT NULL, `ENTREZ_GENE_ID` int(11) NOT NULL, - PRIMARY KEY(`GISTIC_ROI_ID`, `ENTREZ_GENE_ID`), + PRIMARY KEY(`GISTIC_ROI_ID`,`ENTREZ_GENE_ID`), FOREIGN KEY (`ENTREZ_GENE_ID`) REFERENCES `gene` (`ENTREZ_GENE_ID`), FOREIGN KEY (`GISTIC_ROI_ID`) REFERENCES `gistic` (`GISTIC_ROI_ID`) ON DELETE CASCADE ); @@ -585,7 +587,7 @@ CREATE TABLE `cna_event` ( `ENTREZ_GENE_ID` int(11) NOT NULL, `ALTERATION` tinyint NOT NULL, PRIMARY KEY (`CNA_EVENT_ID`), - UNIQUE (`ENTREZ_GENE_ID`, `ALTERATION`), + UNIQUE (`ENTREZ_GENE_ID`,`ALTERATION`), FOREIGN KEY (`ENTREZ_GENE_ID`) REFERENCES `gene` (`ENTREZ_GENE_ID`), INDEX (`ALTERATION`) ); @@ -597,7 +599,7 @@ CREATE TABLE `sample_cna_event` ( `GENETIC_PROFILE_ID` int(11) NOT NULL, `ANNOTATION_JSON` JSON, KEY (`GENETIC_PROFILE_ID`,`SAMPLE_ID`), - PRIMARY KEY (`CNA_EVENT_ID`, `SAMPLE_ID`, `GENETIC_PROFILE_ID`), + PRIMARY KEY (`CNA_EVENT_ID`,`SAMPLE_ID`,`GENETIC_PROFILE_ID`), FOREIGN KEY (`CNA_EVENT_ID`) REFERENCES `cna_event` (`CNA_EVENT_ID`), FOREIGN KEY (`GENETIC_PROFILE_ID`) REFERENCES `genetic_profile` (`GENETIC_PROFILE_ID`) ON DELETE CASCADE, FOREIGN KEY (`SAMPLE_ID`) REFERENCES `sample` (`INTERNAL_ID`) ON DELETE CASCADE @@ -650,19 +652,19 @@ CREATE TABLE `cosmic_mutation` ( -- -------------------------------------------------------- CREATE TABLE `clinical_event` ( - `CLINICAL_EVENT_ID` int NOT NULL auto_increment, - `PATIENT_ID` int(11) NOT NULL, + `CLINICAL_EVENT_ID` BIGINT NOT NULL auto_increment, + `PATIENT_ID` int(11) NOT NULL, `START_DATE` int NOT NULL, `STOP_DATE` int, `EVENT_TYPE` varchar(20) NOT NULL, PRIMARY KEY (`CLINICAL_EVENT_ID`), - KEY (`PATIENT_ID`, `EVENT_TYPE`), + KEY (`PATIENT_ID`,`EVENT_TYPE`), FOREIGN KEY (`PATIENT_ID`) REFERENCES `patient` (`INTERNAL_ID`) ON DELETE CASCADE ); -- -------------------------------------------------------- CREATE TABLE `clinical_event_data` ( - `CLINICAL_EVENT_ID` int(255) NOT NULL, + `CLINICAL_EVENT_ID` BIGINT NOT NULL, `KEY` varchar(255) NOT NULL, `VALUE` varchar(5000) NOT NULL, FOREIGN KEY (`CLINICAL_EVENT_ID`) REFERENCES `clinical_event` (`CLINICAL_EVENT_ID`) ON DELETE CASCADE @@ -670,48 +672,51 @@ CREATE TABLE `clinical_event_data` ( -- -------------------------------------------------------- CREATE TABLE `reference_genome_gene` ( - `ENTREZ_GENE_ID` int(11) NOT NULL, - `REFERENCE_GENOME_ID` int(4) NOT NULL, - `CHR` varchar(5) DEFAULT NULL, - `CYTOBAND` varchar(64) DEFAULT NULL, - `START` bigint(20) DEFAULT NULL, - `END` bigint(20) DEFAULT NULL, - PRIMARY KEY (`ENTREZ_GENE_ID`,`REFERENCE_GENOME_ID`), - FOREIGN KEY (`REFERENCE_GENOME_ID`) REFERENCES `reference_genome` (`REFERENCE_GENOME_ID`) ON DELETE CASCADE, - FOREIGN KEY (`ENTREZ_GENE_ID`) REFERENCES `gene` (`ENTREZ_GENE_ID`) ON DELETE CASCADE + `ENTREZ_GENE_ID` int(11) NOT NULL, + `REFERENCE_GENOME_ID` int(4) NOT NULL, + `CHR` varchar(5) DEFAULT NULL, + `CYTOBAND` varchar(64) DEFAULT NULL, + `START` bigint(20) DEFAULT NULL, + `END` bigint(20) DEFAULT NULL, + PRIMARY KEY (`ENTREZ_GENE_ID`,`REFERENCE_GENOME_ID`), + FOREIGN KEY (`REFERENCE_GENOME_ID`) REFERENCES `reference_genome` (`REFERENCE_GENOME_ID`) ON DELETE CASCADE, + FOREIGN KEY (`ENTREZ_GENE_ID`) REFERENCES `gene` (`ENTREZ_GENE_ID`) ON DELETE CASCADE ); -- -------------------------------------------------------- CREATE TABLE `data_access_tokens` ( - `TOKEN` varchar(50) NOT NULL, - `USERNAME` varchar(128) NOT NULL, - `EXPIRATION` datetime NOT NULL, - `CREATION` datetime NOT NULL, - PRIMARY KEY (`TOKEN`), - FOREIGN KEY (`USERNAME`) REFERENCES `users` (`EMAIL`) ON DELETE CASCADE + `TOKEN` varchar(50) NOT NULL, + `USERNAME` varchar(128) NOT NULL, + `EXPIRATION` datetime NOT NULL, + `CREATION` datetime NOT NULL, + PRIMARY KEY (`TOKEN`), + FOREIGN KEY (`USERNAME`) REFERENCES `users` (`EMAIL`) ON DELETE CASCADE ); + -- -------------------------------------------------------- CREATE TABLE `allele_specific_copy_number` ( - `MUTATION_EVENT_ID` int(255) NOT NULL, - `GENETIC_PROFILE_ID` int(11) NOT NULL, - `SAMPLE_ID` int(11) NOT NULL, - `ASCN_INTEGER_COPY_NUMBER` int DEFAULT NULL, - `ASCN_METHOD` varchar(24) NOT NULL, - `CCF_EXPECTED_COPIES_UPPER` float DEFAULT NULL, - `CCF_EXPECTED_COPIES` float DEFAULT NULL, - `CLONAL` varchar(16) DEFAULT NULL, - `MINOR_COPY_NUMBER` int DEFAULT NULL, - `EXPECTED_ALT_COPIES` int DEFAULT NULL, - `TOTAL_COPY_NUMBER` int DEFAULT NULL, - UNIQUE KEY `UQ_ASCN_MUTATION_EVENT_ID_GENETIC_PROFILE_ID_SAMPLE_ID` (`MUTATION_EVENT_ID`,`GENETIC_PROFILE_ID`,`SAMPLE_ID`), -- Constraint to block duplicated mutation entries - FOREIGN KEY (`MUTATION_EVENT_ID`) REFERENCES `mutation_event` (`MUTATION_EVENT_ID`), - FOREIGN KEY (`GENETIC_PROFILE_ID`) REFERENCES `genetic_profile` (`GENETIC_PROFILE_ID`) ON DELETE CASCADE, - FOREIGN KEY (`SAMPLE_ID`) REFERENCES `sample` (`INTERNAL_ID`) ON DELETE CASCADE + `MUTATION_EVENT_ID` int(255) NOT NULL, + `GENETIC_PROFILE_ID` int(11) NOT NULL, + `SAMPLE_ID` int(11) NOT NULL, + `ASCN_INTEGER_COPY_NUMBER` int DEFAULT NULL, + `ASCN_METHOD` varchar(24) NOT NULL, + `CCF_EXPECTED_COPIES_UPPER` float DEFAULT NULL, + `CCF_EXPECTED_COPIES` float DEFAULT NULL, + `CLONAL` varchar(16) DEFAULT NULL, + `MINOR_COPY_NUMBER` int DEFAULT NULL, + `EXPECTED_ALT_COPIES` int DEFAULT NULL, + `TOTAL_COPY_NUMBER` int DEFAULT NULL, + UNIQUE KEY `UQ_ASCN_MUTATION_EVENT_ID_GENETIC_PROFILE_ID_SAMPLE_ID` (`MUTATION_EVENT_ID`,`GENETIC_PROFILE_ID`,`SAMPLE_ID`), -- Constraint to block duplicated mutation entries + FOREIGN KEY (`MUTATION_EVENT_ID`) REFERENCES `mutation_event` (`MUTATION_EVENT_ID`), + FOREIGN KEY (`GENETIC_PROFILE_ID`) REFERENCES `genetic_profile` (`GENETIC_PROFILE_ID`) ON DELETE CASCADE, + FOREIGN KEY (`SAMPLE_ID`) REFERENCES `sample` (`INTERNAL_ID`) ON DELETE CASCADE ); + -- -------------------------------------------------------- CREATE TABLE `info` ( `DB_SCHEMA_VERSION` varchar(24), - `GENESET_VERSION` varchar(24) + `GENESET_VERSION` varchar(24), + `DERIVED_TABLE_SCHEMA_VERSION` varchar(24) ); -- -------------------------------------------------------- @@ -719,10 +724,11 @@ CREATE TABLE `resource_definition` ( `RESOURCE_ID` varchar(255) NOT NULL, `DISPLAY_NAME` varchar(255) NOT NULL, `DESCRIPTION` varchar(2048) DEFAULT NULL, - `RESOURCE_TYPE` ENUM('STUDY', 'PATIENT', 'SAMPLE') NOT NULL, + `RESOURCE_TYPE` ENUM('STUDY','PATIENT','SAMPLE') NOT NULL, `OPEN_BY_DEFAULT` BOOLEAN DEFAULT 0, `PRIORITY` int(11) NOT NULL, `CANCER_STUDY_ID` int(11) NOT NULL, + `CUSTOM_METADATA` JSON, PRIMARY KEY (`RESOURCE_ID`,`CANCER_STUDY_ID`), FOREIGN KEY (`CANCER_STUDY_ID`) REFERENCES `cancer_study` (`CANCER_STUDY_ID`) ON DELETE CASCADE ); @@ -732,7 +738,7 @@ CREATE TABLE `resource_sample` ( `INTERNAL_ID` int(11) NOT NULL, `RESOURCE_ID` varchar(255) NOT NULL, `URL` varchar(255) NOT NULL, - PRIMARY KEY (`INTERNAL_ID`, `RESOURCE_ID`, `URL`), + PRIMARY KEY (`INTERNAL_ID`,`RESOURCE_ID`,`URL`), FOREIGN KEY (`INTERNAL_ID`) REFERENCES `sample` (`INTERNAL_ID`) ON DELETE CASCADE ); @@ -741,7 +747,7 @@ CREATE TABLE `resource_patient` ( `INTERNAL_ID` int(11) NOT NULL, `RESOURCE_ID` varchar(255) NOT NULL, `URL` varchar(255) NOT NULL, - PRIMARY KEY (`INTERNAL_ID`, `RESOURCE_ID`, `URL`), + PRIMARY KEY (`INTERNAL_ID`,`RESOURCE_ID`,`URL`), FOREIGN KEY (`INTERNAL_ID`) REFERENCES `patient` (`INTERNAL_ID`) ON DELETE CASCADE ); @@ -750,10 +756,10 @@ CREATE TABLE `resource_study` ( `INTERNAL_ID` int(11) NOT NULL, `RESOURCE_ID` varchar(255) NOT NULL, `URL` varchar(255) NOT NULL, - PRIMARY KEY (`INTERNAL_ID`, `RESOURCE_ID`, `URL`), + PRIMARY KEY (`INTERNAL_ID`,`RESOURCE_ID`,`URL`), FOREIGN KEY (`INTERNAL_ID`) REFERENCES `cancer_study` (`CANCER_STUDY_ID`) ON DELETE CASCADE ); --- THIS MUST BE KEPT IN SYNC WITH db.version PROPERTY IN pom.xml -INSERT INTO info VALUES ('2.13.1', NULL); - +-- DB_SCHEMA_VERSION AND DERIVED_TABLE_SCHEMA_VERSION MUST BE KEPT IN SYNC WITH THE db.version AND derived_table.version PROPERTIES IN pom.xml +INSERT INTO `info` (`DB_SCHEMA_VERSION`, `GENESET_VERSION`, `DERIVED_TABLE_SCHEMA_VERSION`) + VALUES ('2.14.2', NULL, '1.0.2'); diff --git a/src/main/resources/db-scripts/clickhouse/clickhouse.sql b/src/main/resources/db-scripts/clickhouse/clickhouse.sql index db311282190..24614f792dc 100644 --- a/src/main/resources/db-scripts/clickhouse/clickhouse.sql +++ b/src/main/resources/db-scripts/clickhouse/clickhouse.sql @@ -1,3 +1,8 @@ +-- version 1.0.2 of derived table schema and data definition +-- when making updates: +-- increment the version number here +-- update pom.xml with the new version number + DROP TABLE IF EXISTS sample_to_gene_panel_derived; DROP TABLE IF EXISTS gene_panel_to_gene_derived; DROP TABLE IF EXISTS sample_derived; @@ -7,6 +12,44 @@ DROP TABLE IF EXISTS clinical_event_derived; DROP TABLE IF EXISTS genetic_alteration_derived; DROP TABLE IF EXISTS generic_assay_data_derived; +-- the following query "fixes" the sample_profile table by adding entries for "missing" samples -- those which appear in mutated case list but not in the MySQL sample_profile table +-- this problem was handled in java at run time in legacy codebase +-- this MUST BE RUN prior to creation of any derived table which relies on sample_profile table +INSERT INTO sample_profile (sample_id, genetic_profile_id, panel_id) +WITH missing_samples AS ( + -- Select all members of lists of type '_sequenced' (mutation) which do NOT appear in sample_profile table for profiles of type mutation + SELECT + sample_id, + cs.cancer_study_identifier AS cancer_study_identifier, + CONCAT(cancer_study_identifier, '_mutations') as stable_id + FROM + sample_list_list sll + JOIN sample_list sl ON sl.list_id = sll.list_id + JOIN cancer_study cs ON cs.cancer_study_id = sl.cancer_study_id + WHERE + sl.stable_id LIKE '%_sequenced' + AND CONCAT(sll.sample_id,'-',cs.cancer_study_id) NOT IN ( + SELECT + CONCAT(sp.sample_id,'-',cs.cancer_study_id) + FROM + sample_profile sp + JOIN genetic_profile gp ON gp.genetic_profile_id = sp.genetic_profile_id + JOIN cancer_study cs ON cs.cancer_study_id = gp.cancer_study_id + WHERE + gp.genetic_alteration_type = 'MUTATION_EXTENDED' + ) +) +-- These are the missing items for the sample_profile table. They are missing because they were not included in matrix file +-- perhaps because they have no associated mutations (even though they WERE profiled for mutation as indicated by presence in the case list file +SELECT + ms.sample_id as sample_id, + gp.genetic_profile_id AS genetic_profile_id, + NULL AS panel_id +FROM + missing_samples ms + JOIN genetic_profile gp ON ms.stable_id=gp.stable_id + JOIN cancer_study cs ON cs.cancer_study_id=gp.cancer_study_id; + CREATE TABLE sample_to_gene_panel_derived ( sample_unique_id String, @@ -50,23 +93,48 @@ SELECT 'WES' AS gene_panel_id, gene.hugo_gene_symbol AS gene FROM gene -WHERE gene.entrez_gene_id > 0 AND gene.type = 'protein-coding'; +WHERE gene.entrez_gene_id > 0; CREATE TABLE sample_derived ( - sample_unique_id String, - sample_unique_id_base64 String, - sample_stable_id String, - patient_unique_id String, - patient_unique_id_base64 String, - patient_stable_id String, - cancer_study_identifier LowCardinality(String), - internal_id Int + sample_unique_id String, + sample_unique_id_base64 String, + sample_stable_id String, + patient_unique_id String, + patient_unique_id_base64 String, + patient_stable_id String, + cancer_study_identifier LowCardinality(String), + internal_id Int, + -- fields below are needed for the SUMMARY projection + patient_internal_id Int, + sample_type String, + -- fields below are needed for the DETAILED projection + sequenced Int, + copy_number_segment_present Int ) ENGINE = MergeTree ORDER BY (cancer_study_identifier, sample_unique_id); INSERT INTO sample_derived +WITH + sequenced_samples AS ( + SELECT + sample.stable_id + FROM sample_list_list + INNER JOIN sample_list ON sample_list_list.list_id = sample_list.list_id + INNER JOIN sample ON sample_list_list.sample_id = sample.internal_id + INNER JOIN patient ON sample.patient_id = patient.internal_id + INNER JOIN cancer_study ON patient.cancer_study_id = cancer_study.cancer_study_id + WHERE sample_list.stable_id = concat(cancer_study.cancer_study_identifier, '_sequenced') + ), + cn_segment_samples AS ( + SELECT + concat(cancer_study.cancer_study_identifier, '_', sample.stable_id) as segment_unique_id + FROM copy_number_seg + INNER JOIN cancer_study ON copy_number_seg.cancer_study_id = cancer_study.cancer_study_id + INNER JOIN sample ON copy_number_seg.sample_id = sample.internal_id + INNER JOIN patient ON sample.patient_id = patient.internal_id + ) SELECT concat(cs.cancer_study_identifier, '_', sample.stable_id) AS sample_unique_id, base64Encode(sample.stable_id) AS sample_unique_id_base64, sample.stable_id AS sample_stable_id, @@ -74,7 +142,13 @@ SELECT concat(cs.cancer_study_identifier, '_', sample.stable_id) AS sample_uniqu base64Encode(p.stable_id) AS patient_unique_id_base64, p.stable_id AS patient_stable_id, cs.cancer_study_identifier AS cancer_study_identifier, - sample.internal_id AS internal_id + sample.internal_id AS internal_id, + -- fields below are needed for the SUMMARY projection + sample.patient_id AS patient_internal_id, + sample.sample_type AS sample_type, + -- fields below are needed for the DETAILED projection + if (sample.stable_id IN sequenced_samples, 1, 0) AS sequenced, + if (sample_unique_id IN cn_segment_samples, 1, 0) AS copy_number_segment_present FROM sample INNER JOIN patient AS p ON sample.patient_id = p.internal_id INNER JOIN cancer_study AS cs ON p.cancer_study_id = cs.cancer_study_id; @@ -96,9 +170,10 @@ CREATE TABLE IF NOT EXISTS genomic_event_derived cna_alteration Nullable(Int8), cna_cytoband String, sv_event_info String, - patient_unique_id String + patient_unique_id String, + off_panel Boolean DEFAULT FALSE ) ENGINE = MergeTree - ORDER BY ( variant_type, entrez_gene_id, hugo_gene_symbol, genetic_profile_stable_id, sample_unique_id); + ORDER BY (variant_type, entrez_gene_id, hugo_gene_symbol, genetic_profile_stable_id, sample_unique_id); INSERT INTO genomic_event_derived -- Insert Mutations @@ -117,7 +192,11 @@ SELECT concat(cs.cancer_study_identifier, '_', sample.stable_id) AS sample_uniqu NULL AS cna_alteration, '' AS cna_cytoband, '' AS sv_event_info, - concat(cs.cancer_study_identifier, '_', patient.stable_id) AS patient_unique_id + concat(cs.cancer_study_identifier, '_', patient.stable_id) AS patient_unique_id, + (gene_panel_stable_id, hugo_gene_symbol) NOT IN ( + SELECT gene_panel_id, gene + FROM gene_panel_to_gene_derived + ) AS off_panel FROM mutation INNER JOIN mutation_event AS me ON mutation.mutation_event_id = me.mutation_event_id INNER JOIN sample_profile sp @@ -145,7 +224,11 @@ SELECT concat(cs.cancer_study_identifier, '_', sample.stable_id) AS sample_uniqu ce.alteration AS cna_alteration, rgg.cytoband AS cna_cytoband, '' AS sv_event_info, - concat(cs.cancer_study_identifier, '_', patient.stable_id) AS patient_unique_id + concat(cs.cancer_study_identifier, '_', patient.stable_id) AS patient_unique_id, + (gene_panel_stable_id, hugo_gene_symbol) NOT IN ( + SELECT gene_panel_id, gene + FROM gene_panel_to_gene_derived + ) AS off_panel FROM cna_event ce INNER JOIN sample_cna_event sce ON ce.cna_event_id = sce.cna_event_id INNER JOIN sample_profile sp ON sce.sample_id = sp.sample_id AND sce.genetic_profile_id = sp.genetic_profile_id @@ -173,7 +256,11 @@ SELECT concat(cs.cancer_study_identifier, '_', s.stable_id) AS sample_unique_id, NULL AS cna_alteration, '' AS cna_cytoband, event_info AS sv_event_info, - concat(cs.cancer_study_identifier, '_', patient.stable_id) AS patient_unique_id + concat(cs.cancer_study_identifier, '_', patient.stable_id) AS patient_unique_id, + (gene_panel_stable_id, hugo_gene_symbol) NOT IN ( + SELECT gene_panel_id, gene + FROM gene_panel_to_gene_derived + ) AS off_panel FROM structural_variant sv INNER JOIN genetic_profile gp ON sv.genetic_profile_id = gp.genetic_profile_id INNER JOIN sample s ON sv.sample_id = s.internal_id @@ -199,7 +286,11 @@ SELECT concat(cs.cancer_study_identifier, '_', s.stable_id) AS sample_unique_id, NULL AS cna_alteration, '' AS cna_cytoband, event_info AS sv_event_info, - concat(cs.cancer_study_identifier, '_', patient.stable_id) AS patient_unique_id + concat(cs.cancer_study_identifier, '_', patient.stable_id) AS patient_unique_id, + (gene_panel_stable_id, hugo_gene_symbol) NOT IN ( + SELECT gene_panel_id, gene + FROM gene_panel_to_gene_derived + ) AS off_panel FROM structural_variant sv INNER JOIN genetic_profile gp ON sv.genetic_profile_id = gp.genetic_profile_id INNER JOIN sample s ON sv.sample_id = s.internal_id @@ -318,12 +409,12 @@ FROM arrayMap(x -> (x = '' ? NULL : x), splitByString(',', assumeNotNull(substring(ga.values, 1, -1)))) AS alteration_value, arrayMap(x -> (x = '' ? NULL : toInt32(x)), splitByString(',', assumeNotNull(substring(gps.ordered_sample_list, 1, -1)))) AS sample_id FROM - genetic_profile gp + genetic_alteration ga + JOIN genetic_profile gp ON ga.genetic_profile_id=gp.genetic_profile_id JOIN genetic_profile_samples gps ON gp.genetic_profile_id = gps.genetic_profile_id - JOIN genetic_alteration ga ON gp.genetic_profile_id = ga.genetic_profile_id JOIN gene g ON ga.genetic_entity_id = g.genetic_entity_id WHERE - gp.genetic_alteration_type NOT IN ('GENERIC_ASSAY', 'MUTATION_EXTENDED', 'STRUCTURAL_VARIANT')) + gp.genetic_alteration_type NOT IN ('GENERIC_ASSAY', 'MUTATION_EXTENDED', 'MUTATION_UNCALLED', 'STRUCTURAL_VARIANT')) ARRAY JOIN alteration_value, sample_id WHERE alteration_value != 'NA') AS subquery JOIN sample_derived sd ON sd.internal_id = subquery.sample_id; @@ -381,9 +472,11 @@ FROM gp.patient_level as patient_level, arrayMap(x -> (x = '' ? NULL : x), splitByString(',', assumeNotNull(substring(ga.values, 1, -1)))) AS value, arrayMap(x -> (x = '' ? NULL : toInt64(x)), splitByString(',', assumeNotNull(substring(gps.ordered_sample_list, 1, -1)))) AS sample_id - FROM genetic_profile gp + FROM + + genetic_alteration ga + JOIN genetic_profile gp ON ga.genetic_profile_id=gp.genetic_profile_id JOIN genetic_profile_samples gps ON gp.genetic_profile_id = gps.genetic_profile_id - JOIN genetic_alteration ga ON gp.genetic_profile_id = ga.genetic_profile_id JOIN genetic_entity ge on ga.genetic_entity_id = ge.id WHERE gp.generic_assay_type IS NOT NULL diff --git a/src/main/resources/db-scripts/migration.sql b/src/main/resources/db-scripts/migration.sql index 78c0d25ea14..35bccece2ba 100644 --- a/src/main/resources/db-scripts/migration.sql +++ b/src/main/resources/db-scripts/migration.sql @@ -294,7 +294,6 @@ INSERT INTO mutation_count_by_keyword GROUP BY g2.`GENETIC_PROFILE_ID` , mutation_event.`KEYWORD` , m2.`ENTREZ_GENE_ID`; UPDATE info SET DB_SCHEMA_VERSION="2.2.0"; - ##version: 2.3.0 -- ========================== new geneset related tables ============================================= @@ -419,9 +418,9 @@ CREATE TABLE `reference_genome_gene` ( INSERT INTO reference_genome_gene (ENTREZ_GENE_ID, CYTOBAND, EXONIC_LENGTH, CHR, REFERENCE_GENOME_ID) (SELECT - ENTREZ_GENE_ID, - CYTOBAND, - LENGTH, + ENTREZ_GENE_ID, + CYTOBAND, + LENGTH, SUBSTRING_INDEX( SUBSTRING_INDEX( SUBSTRING_INDEX( @@ -429,7 +428,7 @@ INSERT INTO reference_genome_gene (ENTREZ_GENE_ID, CYTOBAND, EXONIC_LENGTH, CHR, 'q', 1), 'cen', 1), ' ', 1), - 1 + 1 FROM `gene`); UPDATE info SET DB_SCHEMA_VERSION="2.4.1"; @@ -854,16 +853,16 @@ UPDATE `info` SET `DB_SCHEMA_VERSION`="2.12.4"; ##version: 2.12.5 -- survival data migration -- create temporary table to store survival attributes -CREATE TEMPORARY TABLE IF NOT EXISTS survival_attributes AS - (SELECT DISTINCT Concat(Substr(ATTR_ID, 1, Char_length(ATTR_ID) - 7), - "_STATUS") AS ATTR_ID - FROM clinical_attribute_meta - WHERE ATTR_ID LIKE "%_STATUS" - AND Substr(ATTR_ID, 1, Char_length(ATTR_ID) - 7)IN (SELECT DISTINCT - Substr(ATTR_ID, 1, Char_length(ATTR_ID) - 7) AS - SurvivalDataStatusPrefix - FROM clinical_attribute_meta - WHERE ATTR_ID LIKE "%_MONTHS")); +CREATE TEMPORARY TABLE IF NOT EXISTS survival_attributes AS + (SELECT DISTINCT Concat(Substr(ATTR_ID, 1, Char_length(ATTR_ID) - 7), + "_STATUS") AS ATTR_ID + FROM clinical_attribute_meta + WHERE ATTR_ID LIKE "%_STATUS" + AND Substr(ATTR_ID, 1, Char_length(ATTR_ID) - 7)IN (SELECT DISTINCT + Substr(ATTR_ID, 1, Char_length(ATTR_ID) - 7) AS + SurvivalDataStatusPrefix + FROM clinical_attribute_meta + WHERE ATTR_ID LIKE "%_MONTHS")); -- mapping to 0/1 UPDATE clinical_patient SET ATTR_VALUE = CONCAT("1:",ATTR_VALUE) WHERE ATTR_ID in (SELECT ATTR_ID FROM survival_attributes) AND ATTR_VALUE in ('DECEASED','Recurred/Progressed','Recurred','Progressed','Yes','yes','1','PROGRESSION','Event','DEAD OF MELANOMA','DEAD WITH TUMOR','Metastatic Relapse','Localized Relapse'); @@ -932,7 +931,7 @@ UPDATE `info` SET `DB_SCHEMA_VERSION`="2.12.7"; ##version: 2.12.8 CREATE INDEX idx_mutation_type ON mutation_event (`MUTATION_TYPE`); -CREATE INDEX idx_cna_type ON cna_event (`ALTERATION`); +CREATE INDEX idx_cna_type ON cna_event (`ALTERATION`); CREATE INDEX idx_driver_filter ON alteration_driver_annotation (`DRIVER_FILTER`); CREATE INDEX idx_driver_tiers_filter ON alteration_driver_annotation (`DRIVER_TIERS_FILTER`); UPDATE `info` SET `DB_SCHEMA_VERSION`="2.12.8"; @@ -978,8 +977,6 @@ UPDATE `info` SET `DB_SCHEMA_VERSION`="2.12.12"; ALTER TABLE `sample` MODIFY COLUMN `STABLE_ID` VARCHAR(63) NOT NULL; UPDATE `info` SET `DB_SCHEMA_VERSION`="2.12.13"; - - ##version: 2.12.14 ALTER TABLE `structural_variant` MODIFY COLUMN `SITE1_ENTREZ_GENE_ID` int(11); ALTER TABLE `structural_variant` ADD COLUMN `SITE1_REGION` varchar(25) AFTER `SITE1_CHROMOSOME`; @@ -1021,10 +1018,59 @@ ALTER TABLE `mutation_event` CHANGE COLUMN `ONCOTATOR_PROTEIN_POS_START` `PROTEI ALTER TABLE `mutation_event` CHANGE COLUMN `ONCOTATOR_PROTEIN_POS_END` `PROTEIN_POS_END` int(11); UPDATE `info` SET `DB_SCHEMA_VERSION`="2.13.0"; - ##version: 2.13.1 ALTER TABLE `clinical_event_data` MODIFY COLUMN `VALUE` varchar(3000) NOT NULL; CREATE INDEX idx_clinical_event_key ON clinical_event_data (`KEY`); CREATE INDEX idx_clinical_event_value ON clinical_event_data (`VALUE`); CREATE INDEX idx_sample_stable_id ON sample (`STABLE_ID`); -UPDATE `info` SET `DB_SCHEMA_VERSION`="2.13.1"; \ No newline at end of file +UPDATE `info` SET `DB_SCHEMA_VERSION`="2.13.1"; + +##version: 2.14.0 + +-- Step 1: Drop foreign key + +-- CREATE PROCEDURE DROP_FOREIGN_KEY_IF_EXISTS(IN tableName VARCHAR(64), IN constraintName VARCHAR(64)) +-- BEGIN +-- IF EXISTS( +-- SELECT * FROM information_schema.table_constraints +-- WHERE +-- table_schema = DATABASE() AND +-- table_name = tableName AND +-- constraint_name = constraintName AND +-- constraint_type = 'FOREIGN KEY') +-- THEN +-- SET @query = CONCAT('ALTER TABLE ', tableName, ' DROP FOREIGN KEY ', constraintName, ';'); +-- PREPARE stmt FROM @query; +-- EXECUTE stmt; +-- DEALLOCATE PREPARE stmt; +-- END IF; +-- END + +DROP PROCEDURE IF EXISTS DROP_FOREIGN_KEY_IF_EXISTS; +-- This all has to be on a single line for the migrate_db script to parse it correctly +CREATE PROCEDURE DROP_FOREIGN_KEY_IF_EXISTS(IN tableName VARCHAR(64), IN constraintName VARCHAR(64)) BEGIN IF EXISTS (SELECT 1 FROM information_schema.table_constraints WHERE table_schema = DATABASE() AND table_name = tableName AND constraint_name = constraintName AND constraint_type = 'FOREIGN KEY') THEN SET @query = CONCAT('ALTER TABLE ', tableName, ' DROP FOREIGN KEY ', constraintName); PREPARE stmt FROM @query; EXECUTE stmt; DEALLOCATE PREPARE stmt; END IF; END; + +CALL DROP_FOREIGN_KEY_IF_EXISTS('clinical_event_data', 'clinical_event_data_ibfk_1'); + +DROP PROCEDURE IF EXISTS DROP_FOREIGN_KEY_IF_EXISTS; + +-- Step 2: Change datatype of primary key +ALTER TABLE `clinical_event` MODIFY COLUMN `CLINICAL_EVENT_ID` BIGINT NOT NULL AUTO_INCREMENT; + +-- Step 3: Change datatype of foreign key +ALTER TABLE `clinical_event_data` MODIFY COLUMN `CLINICAL_EVENT_ID` BIGINT NOT NULL; + +-- Step 4: Re-add foreign key constraint +ALTER TABLE `clinical_event_data` ADD CONSTRAINT FOREIGN KEY (`CLINICAL_EVENT_ID`) REFERENCES `clinical_event` (`CLINICAL_EVENT_ID`) ON DELETE CASCADE; + +UPDATE `info` SET `DB_SCHEMA_VERSION`="2.14.0"; + +##version: 2.14.1 +ALTER TABLE `info` ADD COLUMN `DERIVED_TABLE_SCHEMA_VERSION` varchar(24); +UPDATE `info` SET `DERIVED_TABLE_SCHEMA_VERSION`="1.0.0"; +UPDATE `info` SET `DB_SCHEMA_VERSION`="2.14.1"; + +##version: 2.14.2 +ALTER TABLE `resource_definition` ADD COLUMN `CUSTOM_METADATA` JSON; +UPDATE `info` SET `DERIVED_TABLE_SCHEMA_VERSION`="1.0.2"; +UPDATE `info` SET `DB_SCHEMA_VERSION`="2.14.2"; diff --git a/src/main/resources/mappers/clickhouse/alteration/ClickhouseAlterationFilterMapper.xml b/src/main/resources/mappers/clickhouse/alteration/ClickhouseAlterationFilterMapper.xml new file mode 100644 index 00000000000..253a8e23a7d --- /dev/null +++ b/src/main/resources/mappers/clickhouse/alteration/ClickhouseAlterationFilterMapper.xml @@ -0,0 +1,128 @@ + + + + + + + + AND genomic_event_derived.mutation_type = 'NA' + + + AND + lower(genomic_event_derived.mutation_type) + + + NOT IN + + + IN + + + + + lower(#{type}) + + , 'na') + + + + + + + + + + AND genomic_event_derived.cna_alteration is NULL + + + + AND + (genomic_event_derived.cna_alteration IN + + #{type} + + OR genomic_event_derived.cna_alteration is NULL) + + + + + + + + + + + OR + lower(genomic_event_derived.mutation_status) LIKE '%germline%' + + + OR + lower(genomic_event_derived.mutation_status) = 'somatic' + + + OR + lower(genomic_event_derived.mutation_status) != 'somatic' AND lower(genomic_event_derived.mutation_status) NOT LIKE '%germline%' + + + + + AND genomic_event_derived.mutation_status = 'NA' + + + + + + + + + + + + + OR lower(driver_filter) = 'putative_driver' + + + OR lower(driver_filter) = 'putative_passenger' + + + OR driver_filter IS NULL + OR lower(driver_filter) IN ('unknown', 'na', '') + + + + + AND driver_filter = 'NA' + + + + + + + + + + + + + + OR driver_tiers_filter IN + + #{item} + + + + OR driver_tiers_filter IS NULL + OR lower(driver_tiers_filter) IN ('', 'na', 'unknown') + + + + + AND NULL + + + + + + + \ No newline at end of file diff --git a/src/main/resources/mappers/clickhouse/alteration/ClickhouseAlterationMapper.xml b/src/main/resources/mappers/clickhouse/alteration/ClickhouseAlterationMapper.xml new file mode 100644 index 00000000000..2429d7337f6 --- /dev/null +++ b/src/main/resources/mappers/clickhouse/alteration/ClickhouseAlterationMapper.xml @@ -0,0 +1,270 @@ + + + + + + + + + + + + + + + + + + + + + + + (WITH profiled_count_by_genes AS ( + SELECT gptg.gene as hugoGeneSymbol, + COUNT(DISTINCT stgp.${unique_id}) as profiled_count + FROM sample_to_gene_panel_derived stgp + INNER JOIN gene_panel_to_gene_derived gptg on stgp.gene_panel_id = gptg.gene_panel_id + + + stgp.genetic_profile_id IN (#{molecularProfiles,typeHandler=org.apache.ibatis.type.ArrayTypeHandler}) + + + AND stgp.sample_unique_id IN (#{samples,typeHandler=org.apache.ibatis.type.ArrayTypeHandler}) + + + GROUP BY gptg.gene), + total_count_by_genes AS ( + SELECT ged.hugo_gene_symbol AS hugoGeneSymbol, + ged.entrez_gene_id as entrezGeneId, + COUNT(DISTINCT ${unique_id}) as numberOfAlteredCases, + COUNT(DISTINCT CASE WHEN off_panel = 0 THEN ${unique_id} END) as numberOfAlteredCasesOnPanel + FROM genomic_event_derived ged + + ged.mutation_status != 'UNCALLED' + + AND ged.genetic_profile_stable_id IN (#{molecularProfiles,typeHandler=org.apache.ibatis.type.ArrayTypeHandler}) + + + AND ged.sample_unique_id IN (#{samples,typeHandler=org.apache.ibatis.type.ArrayTypeHandler}) + + + + + + + + + AND ged.variant_type != 'structural_variant' + + + GROUP BY ged.entrez_gene_id, ged.hugo_gene_symbol + ) + + SELECT + pgb.hugoGeneSymbol AS hugoGeneSymbol, + ifNull(tcg.entrezGeneId, 0) AS entrezGeneId, + tcg.numberOfAlteredCases as numberOfAlteredCases, + tcg.numberOfAlteredCasesOnPanel as numberOfAlteredCasesOnPanel, + pgb.profiled_count as numberOfProfiledCases + FROM total_count_by_genes tcg + RIGHT JOIN profiled_count_by_genes pgb ON tcg.hugoGeneSymbol = pgb.hugoGeneSymbol + ) + + + + + + + + + + diff --git a/src/main/resources/mappers/clickhouse/cancerstudy/CancerStudyMapper.xml b/src/main/resources/mappers/clickhouse/cancerstudy/CancerStudyMapper.xml new file mode 100644 index 00000000000..970196a7443 --- /dev/null +++ b/src/main/resources/mappers/clickhouse/cancerstudy/CancerStudyMapper.xml @@ -0,0 +1,208 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/mappers/clickhouse/clinical_attributes/ClickhouseClinicalAttributesMapper.xml b/src/main/resources/mappers/clickhouse/clinical_attributes/ClickhouseClinicalAttributesMapper.xml new file mode 100644 index 00000000000..7d1df775ed5 --- /dev/null +++ b/src/main/resources/mappers/clickhouse/clinical_attributes/ClickhouseClinicalAttributesMapper.xml @@ -0,0 +1,33 @@ + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/mappers/clickhouse/clinical_data/ClickhouseClinicalDataMapper.xml b/src/main/resources/mappers/clickhouse/clinical_data/ClickhouseClinicalDataMapper.xml new file mode 100644 index 00000000000..d4aa6b46be7 --- /dev/null +++ b/src/main/resources/mappers/clickhouse/clinical_data/ClickhouseClinicalDataMapper.xml @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + ( + WITH clinical_data_query AS ( + SELECT + attribute_name AS attributeId, + attribute_value AS value, + cast(count(*) AS INTEGER) as count + FROM clinical_data_derived + + type='${type}' + AND + + + + != 'NA' + AND + + + + + + + + + AND attribute_name IN + + #{attributeId} + + + GROUP BY attribute_name, value ), + clinical_data_sum AS (SELECT attributeId, sum(count) AS sum FROM clinical_data_query GROUP BY attributeId) + + SELECT * FROM clinical_data_query + UNION ALL + SELECT attributeId, + 'NA' AS value, + (( + + + + + + + + + ) - clinical_data_sum.sum) AS count + FROM clinical_data_sum + + count > 0 + + ) + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/mappers/clickhouse/clinical_event/ClickhouseClinicalEventMapper.xml b/src/main/resources/mappers/clickhouse/clinical_event/ClickhouseClinicalEventMapper.xml new file mode 100644 index 00000000000..b3df3a75def --- /dev/null +++ b/src/main/resources/mappers/clickhouse/clinical_event/ClickhouseClinicalEventMapper.xml @@ -0,0 +1,17 @@ + + + + + + + \ No newline at end of file diff --git a/src/main/resources/mappers/clickhouse/generic_assay/GenericAssayMapper.xml b/src/main/resources/mappers/clickhouse/generic_assay/GenericAssayMapper.xml new file mode 100644 index 00000000000..e82fa21273e --- /dev/null +++ b/src/main/resources/mappers/clickhouse/generic_assay/GenericAssayMapper.xml @@ -0,0 +1,157 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/mappers/clickhouse/genomic_data/ClickhouseGenomicDataMapper.xml b/src/main/resources/mappers/clickhouse/genomic_data/ClickhouseGenomicDataMapper.xml new file mode 100644 index 00000000000..9b257688c23 --- /dev/null +++ b/src/main/resources/mappers/clickhouse/genomic_data/ClickhouseGenomicDataMapper.xml @@ -0,0 +1,190 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/mappers/clickhouse/patient/ClickhousePatientMapper.xml b/src/main/resources/mappers/clickhouse/patient/ClickhousePatientMapper.xml new file mode 100644 index 00000000000..7486f242023 --- /dev/null +++ b/src/main/resources/mappers/clickhouse/patient/ClickhousePatientMapper.xml @@ -0,0 +1,34 @@ + + + + + + + SELECT count(distinct patient_unique_id) as count + FROM sample_derived + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/mappers/clickhouse/sample/ClickhouseSampleMapper.xml b/src/main/resources/mappers/clickhouse/sample/ClickhouseSampleMapper.xml new file mode 100644 index 00000000000..8c8477d35d1 --- /dev/null +++ b/src/main/resources/mappers/clickhouse/sample/ClickhouseSampleMapper.xml @@ -0,0 +1,289 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + SELECT count(distinct sample_unique_id) as count + FROM sample_derived + + + + + + + + + + + + + + + + + + + + + + + + + sample_derived.internal_id as internalId, + sample_stable_id as stableId, + patient_stable_id as patientStableId, + sample_derived.cancer_study_identifier as cancerStudyIdentifier, + sample_unique_id_base64 as uniqueSampleKey, + patient_unique_id_base64 as uniquePatientKey + + + + , + sample_type as sampleType, + patient_internal_id as patientId + + + + , + sequenced as sequenced, + copy_number_segment_present as copyNumberSegmentPresent, + patient_internal_id as "patient.internalId", + patient_stable_id as "patient.stableId", + cs.cancer_study_id as "patient.cancerStudyId", + cs.cancer_study_identifier as "patient.cancerStudyIdentifier", + cs.cancer_study_id as "patient.cancerStudy.cancerStudyId", + cs.cancer_study_identifier as "patient.cancerStudy.cancerStudyIdentifier", + cs.type_of_cancer_id as "patient.cancerStudy.typeOfCancerId", + cs.name as "patient.cancerStudy.name", + cs.description as "patient.cancerStudy.description", + cs.public as "patient.cancerStudy.publicStudy", + cs.pmid as "patient.cancerStudy.pmid", + cs.citation as "patient.cancerStudy.citation", + cs.groups as "patient.cancerStudy.groups", + cs.status as "patient.cancerStudy.status", + cs.import_date as "patient.cancerStudy.importDate", + rg.name as "patient.cancerStudy.referenceGenome" + + + + FROM sample_derived + INNER JOIN patient AS p ON patient_internal_id = p.internal_id + INNER JOIN cancer_study AS cs ON p.cancer_study_id = cs.cancer_study_id + INNER JOIN reference_genome AS rg ON cs.reference_genome_id = rg.reference_genome_id + + + + + + + + sample_derived.cancer_study_identifier IN + + (NULL) + + + (#{studyIdsArray, typeHandler=org.apache.ibatis.type.ArrayTypeHandler}) + + + + + sample_derived.cancer_study_identifier = #{studyIds[0]} + AND + sample_stable_id IN (#{sampleIdsArray, typeHandler=org.apache.ibatis.type.ArrayTypeHandler}) + + + + concat(sample_derived.cancer_study_identifier, '_', sample_stable_id) IN + (#{studyAndSampleTuples, typeHandler=org.apache.ibatis.type.ArrayTypeHandler}) + + + + AND patient_stable_id = #{patientId} + + + AND + + sample_stable_id ILIKE concat('%', #{item}, '%') + + + + + + + WHERE sample_stable_id = #{sampleId} AND sample_derived.cancer_study_identifier = #{studyId} + + + + + WHERE sample_derived.internal_id IN + ( + SELECT + sample_list_list.sample_id + FROM sample_list_list + INNER JOIN sample_list ON sample_list_list.list_id = sample_list.list_id + WHERE sample_list.stable_id IN + (#{sampleListIdsArray, typeHandler=org.apache.ibatis.type.ArrayTypeHandler}) + ) + + + + + ORDER BY "${sortBy}" ${direction} + + + ORDER BY sample_stable_id ASC + + + ORDER BY if(sample_stable_id ILIKE concat(#{keyword}, '%'), 0, 1), sample_stable_id + + + LIMIT #{limit} OFFSET #{offset} + + + \ No newline at end of file diff --git a/src/main/resources/mappers/clickhouse/studyview/ClickhouseStudyViewFilterMapper.xml b/src/main/resources/mappers/clickhouse/studyview/ClickhouseStudyViewFilterMapper.xml new file mode 100644 index 00000000000..9028134e052 --- /dev/null +++ b/src/main/resources/mappers/clickhouse/studyview/ClickhouseStudyViewFilterMapper.xml @@ -0,0 +1,806 @@ + + + + + + + + INTERSECT + SELECT sample_unique_id + FROM sample_derived + WHERE cancer_study_identifier IN + + #{studyId} + + + + + INTERSECT + -- case list filtering allows both UNION (OR) and INTERSECTION (AND) LOGIC + -- caseLists is an array of arrays wherein the top level is INTERSECTION + -- AND THE INTERNAL ARRAYS ARE UNION (OR) + SELECT * FROM ( + + SELECT sample_unique_id + FROM sample_list_list sll + LEFT JOIN sample_derived s ON sll.sample_id=s.internal_id + LEFT JOIN sample_list sl on sll.list_id=sl.list_id + WHERE + + sl.stable_id LIKE concat('%_', #{list}) + + + ) + + + + INTERSECT + SELECT * FROM ( + + SELECT sample_derived.sample_unique_id + FROM sample_profile GYMP + JOIN genetic_profile gp ON sample_profile.genetic_profile_id = gp.genetic_profile_id + JOIN cancer_study cs ON gp.cancer_study_id = cs.cancer_study_id + JOIN sample_derived on sample_profile.sample_id = sample_derived.internal_id + + + sample_derived.cancer_study_identifier IN + + #{studyId} + + AND + + + gp.stable_id=concat(#{studyId}, '_', #{genomicProfileId}) + + + + + + ) + + + + + INTERSECT + SELECT sample_unique_id + FROM sample_derived + WHERE sample_unique_id IN + ( + #{filteredSampleIdentifiers, typeHandler=org.apache.ibatis.type.ArrayTypeHandler} + ) + + + INTERSECT + SELECT sample_unique_id + FROM sample_derived + WHERE + + + + AND + ( + + + + sample_unique_id IN ( + '', + + + #{sampleIdentifier.uniqueSampleId} + + + ) + + + + + OR + sample_unique_id NOT IN ( + '', + + + #{sampleIdentifier.uniqueSampleId} + + + ) + + + ) + + + + + + + SELECT sample_unique_id + FROM genomic_event_derived + + genetic_profile_stable_id IN + + #{molecularProfileId} + + + + hugo_gene_symbol = #{geneFilterQuery.hugoGeneSymbol} + + + cna_alteration = #{alteration.code} + + + + + + + + + + + + + + + + + + + + ( + + + + + + + + + ) + + + + + + + + + + + + + + + + + + + + + + + + + + SELECT concat(ced.cancer_study_identifier, '_', ced.sample_id) AS sample_unique_id + FROM ( + + SELECT + ced.value AS sample_id, + ced.patient_unique_id AS patient_unique_id, + min(ced.start_date) AS time_taken, + ced.cancer_study_identifier AS cancer_study_identifier + FROM clinical_event_derived ced + + key = 'SAMPLE_ID' + AND (event_type ILIKE 'Sample Acquisition' OR event_type ILIKE 'SPECIMEN') + + GROUP BY patient_unique_id, ced.value, cancer_study_identifier + ) ced + INNER JOIN ( + + SELECT + patient_unique_id, + value AS treatment, + argMin(start_date, start_date) AS treatment_time_taken + FROM clinical_event_derived + WHERE lower(event_type) = 'treatment' + AND key = 'AGENT' + GROUP BY patient_unique_id, value + ) ced_inner ON ced_inner.patient_unique_id = ced.patient_unique_id + + + ced_inner.treatment = #{sampleTreatmentFilter.treatment} + + + AND ced.time_taken <= ced_inner.treatment_time_taken + + + AND ced.time_taken > ced_inner.treatment_time_taken + + + + + GROUP BY patient_unique_id, ced.sample_id, ced.time_taken, ced.cancer_study_identifier, ced_inner.treatment, ced_inner.treatment_time_taken + + + + + + SELECT sample_unique_id + FROM sample_derived + WHERE patient_unique_id in ( + SELECT patient_unique_id + FROM clinical_event_derived + + + event_type = #{dataFilterValue.value} + + + ) + + + + + + SELECT sample_unique_id + FROM sample_derived + WHERE patient_unique_id in ( + SELECT patient_unique_id + FROM clinical_event_derived + + lower(event_type) = 'treatment' + AND key = 'AGENT' + AND value = #{patientTreatmentFilter.treatment} + + + ) + + + + + + + + + AND + + + + + + + AND + ${attribute_value} ILIKE #{dataFilterValue.value} + + + + AND match(${attribute_value}, '^>?=?[-+]?[0-9]*[.,]?[0-9]+$') + + + AND match(${attribute_value}, '^<?=?[-+]?[0-9]*[.,]?[0-9]+$') + + + AND match(${attribute_value}, '^[-+]?[0-9]*[.,]?[0-9]+$') + + + + + + AND abs( + minus( + + + , + cast(#{dataFilterValue.start} as float) + ) + ) < exp(-11) + + + + AND + + + > cast(#{dataFilterValue.start} as float) + + + AND + + + <= cast(#{dataFilterValue.end} as float) + + + + + + + + + + + + ( + + + + + + + + + + + + + + + + + + UNION DISTINCT + SELECT sample_unique_id + FROM sample_derived + WHERE patient_unique_id in ( + + + + + + + + + + + + + + + + + ) + ) + + + + + + + + + + + + + + + + + + + ( + + + SELECT DISTINCT ${unique_id} + FROM sample_derived sd + LEFT JOIN () AS categorical_clinical_data + ON + + + sd.sample_unique_id = categorical_clinical_data.sample_unique_id + + + sd.patient_unique_id = categorical_clinical_data.patient_unique_id + + + WHERE empty(attribute_value) + AND EXISTS () + + + + + UNION ALL + + + + + SELECT ${unique_id} + FROM ${table_name} + WHERE attribute_name = #{clinicalDataFilter.attributeId} AND + type='${type}' + AND + + + + + + ) + + + + SELECT sample_unique_id, patient_unique_id, attribute_value + FROM clinical_data_derived + WHERE attribute_name = #{clinicalDataFilter.attributeId} AND type='${type}' + + AND cancer_study_identifier IN + + #{studyId} + + + + + + ( + SELECT ${unique_id} + FROM sample_derived sd + LEFT JOIN () AS categorical_clinical_data + ON + + + sd.sample_unique_id = categorical_clinical_data.sample_unique_id + + + sd.patient_unique_id = categorical_clinical_data.patient_unique_id + + + WHERE + + + + empty(attribute_value) + OR + + + = 'NA' + + + attribute_value ILIKE #{dataFilterValue.value} + + + + AND EXISTS () + ) + + + + + + + + + + + + + + + + + + + SELECT DISTINCT sd.sample_unique_id + FROM sample_derived sd + LEFT JOIN () AS genomic_numerical_query ON sd.sample_unique_id = genomic_numerical_query.sample_unique_id + WHERE alteration_value IS null + + + + UNION ALL + + + + SELECT DISTINCT sample_unique_id + FROM () AS genomic_numerical_query + WHERE + + + + + + + + + SELECT sample_unique_id, alteration_value + FROM genetic_alteration_derived + WHERE profile_type = #{genomicDataFilter.profileType} + AND hugo_gene_symbol = #{genomicDataFilter.hugoGeneSymbol} + + AND cancer_study_identifier IN + + #{studyId} + + + + + + + + ( + + + + ) + + + + + ( + + + + ) + + + -- patient level profile only have categorical for now + + + ( + + + + ) + + + + + + SELECT sample_unique_id, patient_unique_id, value, datatype + FROM generic_assay_data_derived + WHERE profile_type = #{genericAssayDataFilter.profileType} + AND entity_stable_id = #{genericAssayDataFilter.stableId} + + + + + + + + + + + + + + + + + + + + SELECT DISTINCT sd.sample_unique_id + FROM sample_derived sd + LEFT JOIN () AS generic_numerical_query ON sd.sample_unique_id = generic_numerical_query.sample_unique_id + WHERE datatype = 'LIMIT-VALUE' + AND value IS null OR + + + = 'NA' + + + + UNION ALL + + + + SELECT DISTINCT sample_unique_id + FROM () AS generic_numerical_query + WHERE + datatype = 'LIMIT-VALUE' + AND + + + != 'NA' + AND + + + + + + + + + SELECT sample_unique_id + FROM sample_derived sd + LEFT JOIN () AS generic_assay_query + ON + + + sd.sample_unique_id = generic_assay_query.sample_unique_id + + + sd.patient_unique_id = generic_assay_query.patient_unique_id + + + + datatype != 'LIMIT-VALUE' + + + + value IS null OR + + + = 'NA' + + + value ILIKE #{dataFilterValue.value} + + + + + + + + + + WITH all_samples AS ( + SELECT sample_unique_id + FROM sample_derived + WHERE cancer_study_identifier IN + + + #{studyId} + + + ), + profiled_samples AS ( + SELECT DISTINCT sgp.sample_unique_id + FROM sample_to_gene_panel_derived sgp + JOIN gene_panel_to_gene_derived gpg ON sgp.gene_panel_id = gpg.gene_panel_id + WHERE + + cancer_study_identifier IN + + #{studyId} + + AND + + gpg.gene = #{mutationDataFilter.hugoGeneSymbol} + AND sgp.alteration_type = 'MUTATION_EXTENDED' + ), + mutated_samples AS ( + SELECT DISTINCT sample_unique_id + FROM genomic_event_derived + WHERE + + cancer_study_identifier IN + + #{studyId} + + AND + + hugo_gene_symbol = #{mutationDataFilter.hugoGeneSymbol} + AND variant_type = 'mutation' + ) + SELECT DISTINCT sample_unique_id + FROM + + + + SELECT sample_unique_id FROM mutated_samples + + + SELECT sample_unique_id FROM profiled_samples + WHERE sample_unique_id NOT IN (SELECT sample_unique_id FROM mutated_samples) + + + SELECT sample_unique_id FROM all_samples + WHERE sample_unique_id NOT IN (SELECT sample_unique_id FROM profiled_samples) + + + + + + + + SELECT DISTINCT sample_unique_id + FROM genomic_event_derived + WHERE hugo_gene_symbol = #{mutationDataFilter.hugoGeneSymbol} + AND variant_type = 'mutation' + AND mutation_type IN + + #{dataFilterValue.value} + + + + + + + + WITH cna_query AS ( + SELECT sample_unique_id as sampleUniqueId, alteration_value + FROM genetic_alteration_derived + WHERE profile_type = #{genomicDataFilter.profileType} + AND hugo_gene_symbol = #{genomicDataFilter.hugoGeneSymbol} + + AND cancer_study_identifier IN + + #{studyId} + + + ) + SELECT DISTINCT sd.sample_unique_id + + FROM sample_derived sd + LEFT JOIN cna_query ON sd.sample_unique_id = cna_query.sampleUniqueId + WHERE + + cancer_study_identifier IN + + #{studyId} + + AND + + + + + alteration_value IS null + + alteration_value == #{dataFilterValue.value} + + + + + + + multiIf( + -- This condition is to prevent casting non numerical values to float + NOT match(${attribute_value}, '^[><]?=?[-+]?[0-9]*[.,]?[0-9]+$'), + NULL, + (startsWith(${attribute_value}, '<=') OR startsWith(${attribute_value}, '>=')), + cast(substr(${attribute_value}, 3) as float), + startsWith(${attribute_value}, '<'), + cast(substr(${attribute_value}, 2) as float) - exp(-10), + startsWith(${attribute_value}, '>'), + cast(substr(${attribute_value}, 2) as float) + exp(-10), + cast(${attribute_value} as float) + ) + + + + + ${attribute_value}='' + OR upperUTF8(${attribute_value})='NA' + OR upperUTF8(${attribute_value})='NAN' + OR upperUTF8(${attribute_value})='N/A' + + + + multiIf( + + + , + 'NA', + ${attribute_value} + ) + + + + patient_unique_id in ( + SELECT patient_unique_id + FROM sample_derived + + sample_unique_id IN () + + ) + + + + sample_unique_id IN () + + \ No newline at end of file diff --git a/src/main/resources/mappers/clickhouse/treatment/ClickhouseTreatmentMapper.xml b/src/main/resources/mappers/clickhouse/treatment/ClickhouseTreatmentMapper.xml new file mode 100644 index 00000000000..4f3ba5a1421 --- /dev/null +++ b/src/main/resources/mappers/clickhouse/treatment/ClickhouseTreatmentMapper.xml @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/maven.properties b/src/main/resources/maven.properties index 24e2bf7fc5a..e621748320b 100644 --- a/src/main/resources/maven.properties +++ b/src/main/resources/maven.properties @@ -1,4 +1,6 @@ app.version=@maven.build.timestamp@ portal.version=@project.version@ # this is the *expected* DB version (expected by the code). Don't set it manually, it is filled by maven: -db.version=@db.version@ \ No newline at end of file +db.version=@db.version@ +# this is the *expected* derived_table version (expected by the code). Don't set it manually, it is filled by maven: +derived_table.version=@derived_table.version@ diff --git a/src/main/resources/org/cbioportal/persistence/mybatis/AlterationCountsMapper.xml b/src/main/resources/org/cbioportal/legacy/persistence/mybatis/AlterationCountsMapper.xml similarity index 98% rename from src/main/resources/org/cbioportal/persistence/mybatis/AlterationCountsMapper.xml rename to src/main/resources/org/cbioportal/legacy/persistence/mybatis/AlterationCountsMapper.xml index f9e53a35b08..c2bc086ada4 100644 --- a/src/main/resources/org/cbioportal/persistence/mybatis/AlterationCountsMapper.xml +++ b/src/main/resources/org/cbioportal/legacy/persistence/mybatis/AlterationCountsMapper.xml @@ -1,9 +1,9 @@ - + - SELECT ENTREZ_GENE_ID AS "entrezGeneId", HUGO_GENE_SYMBOL AS "hugoGeneSymbol", @@ -37,7 +37,7 @@ GROUP BY ENTREZ_GENE_ID, HUGO_GENE_SYMBOL; - SELECT ENTREZ_GENE_ID AS entrezGeneId, HUGO_GENE_SYMBOL AS hugoGeneSymbol, @@ -71,7 +71,7 @@ GROUP BY ENTREZ_GENE_ID, HUGO_GENE_SYMBOL; - SELECT cna_event.ENTREZ_GENE_ID AS entrezGeneId, gene.HUGO_GENE_SYMBOL AS hugoGeneSymbol, @@ -111,7 +111,7 @@ GROUP BY cna_event.ENTREZ_GENE_ID, cna_event.ALTERATION, reference_genome_gene.CYTOBAND, gene.HUGO_GENE_SYMBOL - SELECT cna_event.ENTREZ_GENE_ID AS entrezGeneId, gene.HUGO_GENE_SYMBOL AS hugoGeneSymbol, @@ -148,7 +148,7 @@ GROUP BY cna_event.ENTREZ_GENE_ID, cna_event.ALTERATION, gene.HUGO_GENE_SYMBOL - SELECT gene1.ENTREZ_GENE_ID AS gene1EntrezGeneId, gene1.HUGO_GENE_SYMBOL AS gene1HugoGeneSymbol, @@ -176,7 +176,7 @@ GROUP BY gene1.ENTREZ_GENE_ID, gene2.ENTREZ_GENE_ID - SELECT gene1.ENTREZ_GENE_ID AS gene1EntrezGeneId, gene1.HUGO_GENE_SYMBOL AS gene1HugoGeneSymbol, @@ -579,7 +579,7 @@ caseUniqueId - SELECT genetic_profile.GENETIC_PROFILE_ID AS molecularProfileId, diff --git a/src/main/resources/org/cbioportal/persistence/mybatis/AlterationDriverAnnotationMapper.xml b/src/main/resources/org/cbioportal/legacy/persistence/mybatis/AlterationDriverAnnotationMapper.xml similarity index 90% rename from src/main/resources/org/cbioportal/persistence/mybatis/AlterationDriverAnnotationMapper.xml rename to src/main/resources/org/cbioportal/legacy/persistence/mybatis/AlterationDriverAnnotationMapper.xml index 6d133f365d7..85e9d73a9e6 100644 --- a/src/main/resources/org/cbioportal/persistence/mybatis/AlterationDriverAnnotationMapper.xml +++ b/src/main/resources/org/cbioportal/legacy/persistence/mybatis/AlterationDriverAnnotationMapper.xml @@ -1,9 +1,9 @@ - + - SELECT alteration_driver_annotation.ALTERATION_EVENT_ID as alterationEventId, alteration_driver_annotation.GENETIC_PROFILE_ID as geneticProfileId, diff --git a/src/main/resources/org/cbioportal/persistence/mybatis/CancerTypeMapper.xml b/src/main/resources/org/cbioportal/legacy/persistence/mybatis/CancerTypeMapper.xml similarity index 80% rename from src/main/resources/org/cbioportal/persistence/mybatis/CancerTypeMapper.xml rename to src/main/resources/org/cbioportal/legacy/persistence/mybatis/CancerTypeMapper.xml index 138ae3932bc..f1a93ec450a 100644 --- a/src/main/resources/org/cbioportal/persistence/mybatis/CancerTypeMapper.xml +++ b/src/main/resources/org/cbioportal/legacy/persistence/mybatis/CancerTypeMapper.xml @@ -1,7 +1,7 @@ - + type_of_cancer.TYPE_OF_CANCER_ID AS "${prefix}typeOfCancerId" @@ -14,7 +14,7 @@ - SELECT @@ -31,13 +31,13 @@ - SELECT COUNT(*) AS "totalCount" FROM type_of_cancer - SELECT diff --git a/src/main/resources/org/cbioportal/persistence/mybatis/ClinicalAttributeMapper.xml b/src/main/resources/org/cbioportal/legacy/persistence/mybatis/ClinicalAttributeMapper.xml similarity index 95% rename from src/main/resources/org/cbioportal/persistence/mybatis/ClinicalAttributeMapper.xml rename to src/main/resources/org/cbioportal/legacy/persistence/mybatis/ClinicalAttributeMapper.xml index 8dbdbc9a942..a552a83ffa2 100644 --- a/src/main/resources/org/cbioportal/persistence/mybatis/ClinicalAttributeMapper.xml +++ b/src/main/resources/org/cbioportal/legacy/persistence/mybatis/ClinicalAttributeMapper.xml @@ -1,7 +1,7 @@ - + clinical_attribute_meta.ATTR_ID AS "${prefix}attrId", @@ -64,7 +64,7 @@ - SELECT @@ -90,7 +90,7 @@ - SELECT COUNT(*) AS "totalCount" FROM clinical_attribute_meta @@ -105,7 +105,7 @@ - SELECT @@ -116,7 +116,7 @@ AND cancer_study.CANCER_STUDY_IDENTIFIER = #{studyId} - SELECT count(*) as "count", clinical_sample.ATTR_ID as "attrId" FROM clinical_sample @@ -134,7 +134,7 @@ GROUP BY clinical_patient.ATTR_ID - SELECT count(*) as "count", clinical_sample.ATTR_ID as "attrId" FROM clinical_sample @@ -152,7 +152,7 @@ GROUP BY clinical_patient.ATTR_ID - SELECT clinical_attribute_meta.ATTR_ID AS "attrId", cancer_study.CANCER_STUDY_IDENTIFIER AS "cancerStudyIdentifier", diff --git a/src/main/resources/org/cbioportal/persistence/mybatis/ClinicalDataMapper.xml b/src/main/resources/org/cbioportal/legacy/persistence/mybatis/ClinicalDataMapper.xml similarity index 96% rename from src/main/resources/org/cbioportal/persistence/mybatis/ClinicalDataMapper.xml rename to src/main/resources/org/cbioportal/legacy/persistence/mybatis/ClinicalDataMapper.xml index bfe06321aff..129fdce9494 100644 --- a/src/main/resources/org/cbioportal/persistence/mybatis/ClinicalDataMapper.xml +++ b/src/main/resources/org/cbioportal/legacy/persistence/mybatis/ClinicalDataMapper.xml @@ -1,7 +1,7 @@ - + clinical_sample.INTERNAL_ID AS "${prefix}internalId", @@ -15,7 +15,7 @@ , - + @@ -33,7 +33,7 @@ , - + @@ -115,7 +115,7 @@ - SELECT sample.INTERNAL_ID internalId, sample.STABLE_ID sampleId, patient.STABLE_ID patientId, cancer_study.CANCER_STUDY_IDENTIFIER studyId, clinical_patient.ATTR_ID attrId, clinical_patient.ATTR_VALUE attrValue FROM clinical_patient @@ -128,7 +128,7 @@ - SELECT sample.INTERNAL_ID internalId, sample.STABLE_ID sampleId, patient.STABLE_ID patientId, cancer_study.CANCER_STUDY_IDENTIFIER studyId, clinical_sample.ATTR_ID attrId, clinical_sample.ATTR_VALUE attrValue FROM clinical_sample @@ -141,7 +141,7 @@ - SELECT @@ -164,14 +164,14 @@ - SELECT COUNT(*) AS "totalCount" - SELECT @@ -194,7 +194,7 @@ - SELECT @@ -219,14 +219,14 @@ - SELECT COUNT(*) AS "totalCount" - SELECT count(*) as count, clinical_sample.ATTR_ID as attributeId, clinical_sample.ATTR_VALUE as value @@ -235,7 +235,7 @@ GROUP BY clinical_sample.ATTR_ID, clinical_sample.ATTR_VALUE - SELECT count(*) as count, clinical_patient.ATTR_ID as attributeId, clinical_patient.ATTR_VALUE as value diff --git a/src/main/resources/org/cbioportal/persistence/mybatis/ClinicalEventMapper.xml b/src/main/resources/org/cbioportal/legacy/persistence/mybatis/ClinicalEventMapper.xml similarity index 96% rename from src/main/resources/org/cbioportal/persistence/mybatis/ClinicalEventMapper.xml rename to src/main/resources/org/cbioportal/legacy/persistence/mybatis/ClinicalEventMapper.xml index 48e446aeccb..badc8b79702 100644 --- a/src/main/resources/org/cbioportal/persistence/mybatis/ClinicalEventMapper.xml +++ b/src/main/resources/org/cbioportal/legacy/persistence/mybatis/ClinicalEventMapper.xml @@ -1,7 +1,7 @@ - + clinical_event.CLINICAL_EVENT_ID AS "clinicalEventId", @@ -34,7 +34,7 @@ - SELECT @@ -50,14 +50,14 @@ - SELECT COUNT(*) AS totalCount - SELECT clinical_event_data.CLINICAL_EVENT_ID AS clinicalEventId, clinical_event_data.KEY AS "key", @@ -73,7 +73,7 @@ - SELECT @@ -89,14 +89,14 @@ - SELECT COUNT(*) AS totalCount - SELECT clinical_event.CLINICAL_EVENT_ID as clinicalEventId, clinical_event.EVENT_TYPE as eventType, @@ -140,7 +140,7 @@ - SELECT @@ -184,7 +184,7 @@ Group by clinical_event.EVENT_TYPE, patient.INTERNAL_ID - SELECT patient.STABLE_ID AS patientId, cancer_study.CANCER_STUDY_IDENTIFIER AS studyId, @@ -240,9 +240,9 @@ clinical_event.PATIENT_ID, cancer_study.CANCER_STUDY_IDENTIFIER; - + - + diff --git a/src/main/resources/org/cbioportal/persistence/mybatis/CopyNumberSegmentMapper.xml b/src/main/resources/org/cbioportal/legacy/persistence/mybatis/CopyNumberSegmentMapper.xml similarity index 94% rename from src/main/resources/org/cbioportal/persistence/mybatis/CopyNumberSegmentMapper.xml rename to src/main/resources/org/cbioportal/legacy/persistence/mybatis/CopyNumberSegmentMapper.xml index 58e2a37da07..0d3503c6fd5 100644 --- a/src/main/resources/org/cbioportal/persistence/mybatis/CopyNumberSegmentMapper.xml +++ b/src/main/resources/org/cbioportal/legacy/persistence/mybatis/CopyNumberSegmentMapper.xml @@ -1,7 +1,7 @@ - + copy_number_seg.SEG_ID AS "segId", @@ -50,7 +50,7 @@ - SELECT @@ -69,7 +69,7 @@ - SELECT COUNT(*) AS totalCount @@ -79,7 +79,7 @@ - SELECT diff --git a/src/main/resources/org/cbioportal/persistence/mybatis/CosmicCountMapper.xml b/src/main/resources/org/cbioportal/legacy/persistence/mybatis/CosmicCountMapper.xml similarity index 87% rename from src/main/resources/org/cbioportal/persistence/mybatis/CosmicCountMapper.xml rename to src/main/resources/org/cbioportal/legacy/persistence/mybatis/CosmicCountMapper.xml index df0fe7e0fe3..5541cb31f7b 100644 --- a/src/main/resources/org/cbioportal/persistence/mybatis/CosmicCountMapper.xml +++ b/src/main/resources/org/cbioportal/legacy/persistence/mybatis/CosmicCountMapper.xml @@ -1,9 +1,9 @@ - + - SELECT cosmic_mutation.COSMIC_MUTATION_ID AS "cosmicMutationId", cosmic_mutation.PROTEIN_CHANGE AS "proteinChange", diff --git a/src/main/resources/org/cbioportal/persistence/mybatis/DataAccessTokenMapper.xml b/src/main/resources/org/cbioportal/legacy/persistence/mybatis/DataAccessTokenMapper.xml similarity index 85% rename from src/main/resources/org/cbioportal/persistence/mybatis/DataAccessTokenMapper.xml rename to src/main/resources/org/cbioportal/legacy/persistence/mybatis/DataAccessTokenMapper.xml index f6aea8ca139..9aa8776df70 100644 --- a/src/main/resources/org/cbioportal/persistence/mybatis/DataAccessTokenMapper.xml +++ b/src/main/resources/org/cbioportal/legacy/persistence/mybatis/DataAccessTokenMapper.xml @@ -1,7 +1,7 @@ - + data_access_tokens.TOKEN AS "${prefix}token", @@ -10,7 +10,7 @@ data_access_tokens.CREATION AS "${prefix}creation" - SELECT @@ -20,7 +20,7 @@ ORDER BY data_access_tokens.EXPIRATION ASC - SELECT @@ -41,7 +41,7 @@ WHERE USERNAME = #{username} - + INSERT INTO data_access_tokens(TOKEN, USERNAME, EXPIRATION, CREATION) VALUES (#{token}, #{username}, #{expiration}, #{creation}) diff --git a/src/main/resources/org/cbioportal/persistence/mybatis/DiscreteCopyNumberMapper.xml b/src/main/resources/org/cbioportal/legacy/persistence/mybatis/DiscreteCopyNumberMapper.xml similarity index 95% rename from src/main/resources/org/cbioportal/persistence/mybatis/DiscreteCopyNumberMapper.xml rename to src/main/resources/org/cbioportal/legacy/persistence/mybatis/DiscreteCopyNumberMapper.xml index 3060a8a389e..338347d24ef 100644 --- a/src/main/resources/org/cbioportal/persistence/mybatis/DiscreteCopyNumberMapper.xml +++ b/src/main/resources/org/cbioportal/legacy/persistence/mybatis/DiscreteCopyNumberMapper.xml @@ -1,7 +1,7 @@ - + cna_event.ENTREZ_GENE_ID as entrezGeneId, @@ -17,7 +17,7 @@ alteration_driver_annotation.DRIVER_TIERS_FILTER_ANNOTATION AS "driverTiersFilterAnnotation" , - + @@ -193,7 +193,7 @@ - SELECT @@ -203,14 +203,14 @@ - SELECT COUNT(*) AS "totalCount" - SELECT @@ -220,7 +220,7 @@ - SELECT @@ -230,7 +230,7 @@ - SELECT @@ -240,14 +240,14 @@ - SELECT COUNT(*) AS "totalCount" - SELECT cna_event.ENTREZ_GENE_ID AS "entrezGeneId", gene.HUGO_GENE_SYMBOL AS "hugoGeneSymbol", diff --git a/src/main/resources/org/cbioportal/persistence/mybatis/GeneMapper.xml b/src/main/resources/org/cbioportal/legacy/persistence/mybatis/GeneMapper.xml similarity index 91% rename from src/main/resources/org/cbioportal/persistence/mybatis/GeneMapper.xml rename to src/main/resources/org/cbioportal/legacy/persistence/mybatis/GeneMapper.xml index eb9bbf1f24a..eab4878cfb3 100644 --- a/src/main/resources/org/cbioportal/persistence/mybatis/GeneMapper.xml +++ b/src/main/resources/org/cbioportal/legacy/persistence/mybatis/GeneMapper.xml @@ -1,7 +1,7 @@ - + gene.ENTREZ_GENE_ID AS "${prefix}entrezGeneId", @@ -32,7 +32,7 @@ - SELECT @@ -53,14 +53,14 @@ - SELECT COUNT(*) AS "totalCount" - SELECT @@ -69,7 +69,7 @@ WHERE gene.GENETIC_ENTITY_ID = #{geneticEntityId} - SELECT @@ -78,7 +78,7 @@ WHERE gene.ENTREZ_GENE_ID = #{entrezGeneId} - SELECT @@ -100,14 +100,14 @@ WHERE gene.HUGO_GENE_SYMBOL = #{hugoGeneSymbol} - SELECT gene_alias.ENTREZ_GENE_ID AS "entrezGeneId", LOWER(gene_alias.GENE_ALIAS) AS "geneAlias" FROM gene_alias - SELECT @@ -126,7 +126,7 @@ - SELECT COUNT(*) AS "totalCount" FROM gene @@ -143,7 +143,7 @@ - SELECT @@ -162,7 +162,7 @@ - SELECT COUNT(*) AS totalCount FROM gene diff --git a/src/main/resources/org/cbioportal/persistence/mybatis/GenePanelMapper.xml b/src/main/resources/org/cbioportal/legacy/persistence/mybatis/GenePanelMapper.xml similarity index 90% rename from src/main/resources/org/cbioportal/persistence/mybatis/GenePanelMapper.xml rename to src/main/resources/org/cbioportal/legacy/persistence/mybatis/GenePanelMapper.xml index 96a1d434c15..289f4df0127 100644 --- a/src/main/resources/org/cbioportal/persistence/mybatis/GenePanelMapper.xml +++ b/src/main/resources/org/cbioportal/legacy/persistence/mybatis/GenePanelMapper.xml @@ -1,7 +1,7 @@ - + gene_panel.INTERNAL_ID AS "internalId", @@ -30,7 +30,7 @@ LEFT JOIN gene_panel ON sample_profile.PANEL_ID = gene_panel.INTERNAL_ID - SELECT FROM gene_panel @@ -45,20 +45,20 @@ - SELECT COUNT(*) AS totalCount FROM gene_panel - SELECT FROM gene_panel WHERE gene_panel.STABLE_ID = #{genePanelId} - SELECT FROM gene_panel @@ -72,7 +72,7 @@ - SELECT gene_panel.STABLE_ID AS genePanelId, gene_panel_list.GENE_ID AS entrezGeneId, @@ -91,7 +91,7 @@ ORDER BY hugoGeneSymbol ASC - SELECT @@ -102,7 +102,7 @@ AND sample_list_query.STABLE_ID = #{sampleListId} - SELECT @@ -116,7 +116,7 @@ - SELECT @@ -127,7 +127,7 @@ - SELECT @@ -157,7 +157,7 @@ - SELECT diff --git a/src/main/resources/org/cbioportal/legacy/persistence/mybatis/GenericAssayMapper.xml b/src/main/resources/org/cbioportal/legacy/persistence/mybatis/GenericAssayMapper.xml new file mode 100644 index 00000000000..461d855ef02 --- /dev/null +++ b/src/main/resources/org/cbioportal/legacy/persistence/mybatis/GenericAssayMapper.xml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/org/cbioportal/persistence/mybatis/GenesetHierarchyMapper.xml b/src/main/resources/org/cbioportal/legacy/persistence/mybatis/GenesetHierarchyMapper.xml similarity index 87% rename from src/main/resources/org/cbioportal/persistence/mybatis/GenesetHierarchyMapper.xml rename to src/main/resources/org/cbioportal/legacy/persistence/mybatis/GenesetHierarchyMapper.xml index 6ed4252ada4..f8e105e4e64 100644 --- a/src/main/resources/org/cbioportal/persistence/mybatis/GenesetHierarchyMapper.xml +++ b/src/main/resources/org/cbioportal/legacy/persistence/mybatis/GenesetHierarchyMapper.xml @@ -1,7 +1,7 @@ - + a.NODE_ID AS nodeId, @@ -10,7 +10,7 @@ b.NODE_NAME AS parentNodeName - SELECT FROM geneset_hierarchy_node as a left join geneset_hierarchy_node as b ON a.PARENT_ID = b.NODE_ID @@ -27,7 +27,7 @@ ORDER BY b.NODE_NAME, a.NODE_NAME - SELECT FROM geneset_hierarchy_node as a LEFT join geneset_hierarchy_node as b ON a.PARENT_ID = b.NODE_ID @@ -44,9 +44,9 @@ ORDER BY b.NODE_NAME, a.NODE_NAME - SELECT - + FROM geneset diff --git a/src/main/resources/org/cbioportal/persistence/mybatis/GenesetMapper.xml b/src/main/resources/org/cbioportal/legacy/persistence/mybatis/GenesetMapper.xml similarity index 82% rename from src/main/resources/org/cbioportal/persistence/mybatis/GenesetMapper.xml rename to src/main/resources/org/cbioportal/legacy/persistence/mybatis/GenesetMapper.xml index 8c1fe553431..5a6674a2be4 100644 --- a/src/main/resources/org/cbioportal/persistence/mybatis/GenesetMapper.xml +++ b/src/main/resources/org/cbioportal/legacy/persistence/mybatis/GenesetMapper.xml @@ -1,7 +1,7 @@ - + geneset.ID AS "${prefix}internalId", @@ -11,7 +11,7 @@ geneset.REF_LINK as "${prefix}refLink" - SELECT @@ -28,13 +28,13 @@ - SELECT COUNT(*) AS totalCount FROM geneset - SELECT @@ -43,7 +43,7 @@ WHERE geneset.EXTERNAL_ID = #{genesetId} - SELECT @@ -56,9 +56,9 @@ ORDER BY geneset.EXTERNAL_ID ASC - SELECT - + FROM gene diff --git a/src/main/resources/org/cbioportal/persistence/mybatis/MolecularDataMapper.xml b/src/main/resources/org/cbioportal/legacy/persistence/mybatis/MolecularDataMapper.xml similarity index 91% rename from src/main/resources/org/cbioportal/persistence/mybatis/MolecularDataMapper.xml rename to src/main/resources/org/cbioportal/legacy/persistence/mybatis/MolecularDataMapper.xml index 45a1e222e63..e6f22dcdf63 100644 --- a/src/main/resources/org/cbioportal/persistence/mybatis/MolecularDataMapper.xml +++ b/src/main/resources/org/cbioportal/legacy/persistence/mybatis/MolecularDataMapper.xml @@ -1,7 +1,7 @@ - + @@ -20,7 +20,7 @@ - SELECT genetic_profile.STABLE_ID AS "molecularProfileId", genetic_profile_samples.ORDERED_SAMPLE_LIST AS "commaSeparatedSampleIds" @@ -37,13 +37,13 @@ - SELECT gene.ENTREZ_GENE_ID AS "entrezGeneId", genetic_alteration.`VALUES` AS "values" , - + @@ -67,13 +67,13 @@ (Attempts where made to share getGeneMolecularAlterations between methods in MolecularDataMapper.java all of which have failed). --> - SELECT gene.ENTREZ_GENE_ID AS "entrezGeneId", genetic_alteration.`VALUES` AS "values" , - + @@ -92,7 +92,7 @@ - SELECT gene.ENTREZ_GENE_ID AS "entrezGeneId", genetic_alteration.`VALUES` AS "values" @@ -104,14 +104,14 @@ - SELECT gene.ENTREZ_GENE_ID AS "entrezGeneId", genetic_alteration.`VALUES` AS "values", genetic_profile.STABLE_ID AS "molecularProfileId" , - + @@ -121,7 +121,7 @@ - SELECT geneset.EXTERNAL_ID AS genesetId, @@ -145,7 +145,7 @@ - SELECT genetic_entity.STABLE_ID AS genericAssayStableId, genetic_profile.STABLE_ID AS molecularProfileId, @@ -175,7 +175,7 @@ (Attempts where made to share getGenericAssayMolecularAlterations between methods in MolecularDataMapper.java all of which have failed). --> - SELECT genetic_entity.STABLE_ID AS genericAssayStableId, genetic_profile.STABLE_ID AS molecularProfileId, diff --git a/src/main/resources/org/cbioportal/persistence/mybatis/MolecularProfileMapper.xml b/src/main/resources/org/cbioportal/legacy/persistence/mybatis/MolecularProfileMapper.xml similarity index 93% rename from src/main/resources/org/cbioportal/persistence/mybatis/MolecularProfileMapper.xml rename to src/main/resources/org/cbioportal/legacy/persistence/mybatis/MolecularProfileMapper.xml index b51a2f9b5ab..bf59ea76beb 100644 --- a/src/main/resources/org/cbioportal/persistence/mybatis/MolecularProfileMapper.xml +++ b/src/main/resources/org/cbioportal/legacy/persistence/mybatis/MolecularProfileMapper.xml @@ -1,7 +1,7 @@ - + genetic_profile.GENETIC_PROFILE_ID AS "${prefix}molecularProfileId", @@ -22,13 +22,13 @@ , - + - SELECT @@ -58,7 +58,7 @@ - SELECT COUNT(*) AS totalCount FROM genetic_profile @@ -72,7 +72,7 @@ - SELECT @@ -83,7 +83,7 @@ WHERE genetic_profile.STABLE_ID = #{molecularProfileId} - SELECT @@ -101,7 +101,7 @@ - SELECT COUNT(*) AS totalCount FROM genetic_profile @@ -115,7 +115,7 @@ - SELECT @@ -133,7 +133,7 @@ ) - SELECT diff --git a/src/main/resources/org/cbioportal/persistence/mybatis/MutationMapper.xml b/src/main/resources/org/cbioportal/legacy/persistence/mybatis/MutationMapper.xml similarity index 96% rename from src/main/resources/org/cbioportal/persistence/mybatis/MutationMapper.xml rename to src/main/resources/org/cbioportal/legacy/persistence/mybatis/MutationMapper.xml index de6a18dc104..eb82f54b0e0 100644 --- a/src/main/resources/org/cbioportal/persistence/mybatis/MutationMapper.xml +++ b/src/main/resources/org/cbioportal/legacy/persistence/mybatis/MutationMapper.xml @@ -1,7 +1,7 @@ - + genetic_profile.STABLE_ID AS "molecularProfileId", @@ -40,7 +40,7 @@ , - + , @@ -275,13 +275,13 @@ AND mutation.SAMPLE_ID = allele_specific_copy_number.SAMPLE_ID - + - + - + @@ -289,7 +289,7 @@ - SELECT @@ -310,7 +310,7 @@ - SELECT COUNT(*) AS "totalCount", COUNT(DISTINCT(mutation.SAMPLE_ID)) AS "sampleCount" @@ -319,7 +319,7 @@ - SELECT @@ -332,7 +332,7 @@ - SELECT @@ -345,7 +345,7 @@ - SELECT COUNT(*) AS "totalCount", COUNT(DISTINCT(mutation.SAMPLE_ID)) AS "sampleCount" @@ -354,7 +354,7 @@ - SELECT COUNT(*) AS "totalCount", COUNT(DISTINCT(mutation.SAMPLE_ID)) AS "sampleCount" @@ -363,7 +363,7 @@ - SELECT mutation.ENTREZ_GENE_ID AS "entrezGeneId", gene.HUGO_GENE_SYMBOL AS "hugoGeneSymbol", @@ -378,7 +378,7 @@ GROUP BY mutation.ENTREZ_GENE_ID - SELECT #{entrezGeneId} AS "entrezGeneId", #{proteinPosStart} AS "proteinPosStart", diff --git a/src/main/resources/org/cbioportal/legacy/persistence/mybatis/NamespaceMapper.xml b/src/main/resources/org/cbioportal/legacy/persistence/mybatis/NamespaceMapper.xml new file mode 100644 index 00000000000..ac7f9de75d8 --- /dev/null +++ b/src/main/resources/org/cbioportal/legacy/persistence/mybatis/NamespaceMapper.xml @@ -0,0 +1,240 @@ + + + + + + + INNER JOIN sample ON mutation.SAMPLE_ID = sample.INTERNAL_ID + INNER JOIN patient ON sample.PATIENT_ID = patient.INTERNAL_ID + INNER JOIN cancer_study ON patient.CANCER_STUDY_ID = cancer_study.CANCER_STUDY_ID + + + + INNER JOIN sample ON structural_variant.SAMPLE_ID = sample.INTERNAL_ID + INNER JOIN patient ON sample.PATIENT_ID = patient.INTERNAL_ID + INNER JOIN cancer_study ON patient.CANCER_STUDY_ID = cancer_study.CANCER_STUDY_ID + + + + INNER JOIN sample ON sample_cna_event.SAMPLE_ID = sample.INTERNAL_ID + INNER JOIN patient ON sample.PATIENT_ID = patient.INTERNAL_ID + INNER JOIN cancer_study ON patient.CANCER_STUDY_ID = cancer_study.CANCER_STUDY_ID + + + + + + cancer_study.CANCER_STUDY_IDENTIFIER = #{studyIds[0]} + + + + cancer_study.CANCER_STUDY_IDENTIFIER = #{studyIds[0]} AND + sample.STABLE_ID IN + + #{item} + + + + (cancer_study.CANCER_STUDY_IDENTIFIER, sample.STABLE_ID) IN + + (#{studyIds[${i}]}, #{sampleIds[${i}]}) + + + + + + + + + (SELECT ANNOTATION_JSON + FROM mutation + + WHERE cancer_study.CANCER_STUDY_IDENTIFIER = #{studyId} + LIMIT 1) + UNION ALL + (SELECT ANNOTATION_JSON + FROM structural_variant + + WHERE cancer_study.CANCER_STUDY_IDENTIFIER = #{studyId} + LIMIT 1) + UNION ALL + (SELECT ANNOTATION_JSON + FROM sample_cna_event + + WHERE cancer_study.CANCER_STUDY_IDENTIFIER = #{studyId} + LIMIT 1) + + + + + + + + + + + + + + + diff --git a/src/main/resources/org/cbioportal/persistence/mybatis/PatientMapper.xml b/src/main/resources/org/cbioportal/legacy/persistence/mybatis/PatientMapper.xml similarity index 91% rename from src/main/resources/org/cbioportal/persistence/mybatis/PatientMapper.xml rename to src/main/resources/org/cbioportal/legacy/persistence/mybatis/PatientMapper.xml index 3b396bdfa6a..009a363d46f 100644 --- a/src/main/resources/org/cbioportal/persistence/mybatis/PatientMapper.xml +++ b/src/main/resources/org/cbioportal/legacy/persistence/mybatis/PatientMapper.xml @@ -1,7 +1,7 @@ - + patient.INTERNAL_ID AS "${prefix}internalId", @@ -10,7 +10,7 @@ cancer_study.CANCER_STUDY_IDENTIFIER AS "${prefix}cancerStudyIdentifier" , - + @@ -45,7 +45,7 @@ - SELECT @@ -69,7 +69,7 @@ - SELECT COUNT(*) AS totalCount @@ -79,7 +79,7 @@ - SELECT @@ -89,7 +89,7 @@ AND cancer_study.CANCER_STUDY_IDENTIFIER = #{studyId} - SELECT DISTINCT(patient.STABLE_ID) AS stableId, cancer_study.CANCER_STUDY_IDENTIFIER AS cancerStudyIdentifier FROM sample diff --git a/src/main/resources/org/cbioportal/persistence/mybatis/ReferenceGenomeGeneMapper.xml b/src/main/resources/org/cbioportal/legacy/persistence/mybatis/ReferenceGenomeGeneMapper.xml similarity index 93% rename from src/main/resources/org/cbioportal/persistence/mybatis/ReferenceGenomeGeneMapper.xml rename to src/main/resources/org/cbioportal/legacy/persistence/mybatis/ReferenceGenomeGeneMapper.xml index 0888d5d06be..0e2cbc981bd 100644 --- a/src/main/resources/org/cbioportal/persistence/mybatis/ReferenceGenomeGeneMapper.xml +++ b/src/main/resources/org/cbioportal/legacy/persistence/mybatis/ReferenceGenomeGeneMapper.xml @@ -1,7 +1,7 @@ - + @@ -18,7 +18,7 @@ - SELECT @@ -31,7 +31,7 @@ - SELECT @@ -53,7 +53,7 @@ - SELECT @@ -75,7 +75,7 @@ - SELECT @@ -89,7 +89,7 @@ - SELECT diff --git a/src/main/resources/org/cbioportal/persistence/mybatis/ResourceDataMapper.xml b/src/main/resources/org/cbioportal/legacy/persistence/mybatis/ResourceDataMapper.xml similarity index 92% rename from src/main/resources/org/cbioportal/persistence/mybatis/ResourceDataMapper.xml rename to src/main/resources/org/cbioportal/legacy/persistence/mybatis/ResourceDataMapper.xml index 051634e0e86..cfba5e33523 100644 --- a/src/main/resources/org/cbioportal/persistence/mybatis/ResourceDataMapper.xml +++ b/src/main/resources/org/cbioportal/legacy/persistence/mybatis/ResourceDataMapper.xml @@ -1,7 +1,7 @@ - + sample.STABLE_ID AS "${prefix}sampleId", @@ -13,7 +13,7 @@ , - + @@ -28,7 +28,7 @@ , - + @@ -42,7 +42,7 @@ , - + @@ -105,7 +105,7 @@ - SELECT @@ -127,7 +127,7 @@ - SELECT @@ -149,7 +149,7 @@ - SELECT @@ -171,7 +171,7 @@ - SELECT @@ -188,7 +188,7 @@ - SELECT diff --git a/src/main/resources/org/cbioportal/persistence/mybatis/ResourceDefinitionMapper.xml b/src/main/resources/org/cbioportal/legacy/persistence/mybatis/ResourceDefinitionMapper.xml similarity index 89% rename from src/main/resources/org/cbioportal/persistence/mybatis/ResourceDefinitionMapper.xml rename to src/main/resources/org/cbioportal/legacy/persistence/mybatis/ResourceDefinitionMapper.xml index a10818544ec..6612d86078d 100644 --- a/src/main/resources/org/cbioportal/persistence/mybatis/ResourceDefinitionMapper.xml +++ b/src/main/resources/org/cbioportal/legacy/persistence/mybatis/ResourceDefinitionMapper.xml @@ -1,7 +1,7 @@ - + resource_definition.RESOURCE_ID AS "${prefix}resourceId", @@ -13,11 +13,12 @@ resource_definition.OPEN_BY_DEFAULT AS "${prefix}openByDefault", resource_definition.DESCRIPTION AS "${prefix}description", resource_definition.RESOURCE_TYPE AS "${prefix}resourceType", - resource_definition.PRIORITY AS "${prefix}priority" + resource_definition.PRIORITY AS "${prefix}priority", + resource_definition.CUSTOM_METADATA AS "${prefix}customMetaData" - SELECT @@ -48,7 +49,7 @@ - SELECT diff --git a/src/main/resources/org/cbioportal/persistence/mybatis/SampleListMapper.xml b/src/main/resources/org/cbioportal/legacy/persistence/mybatis/SampleListMapper.xml similarity index 88% rename from src/main/resources/org/cbioportal/persistence/mybatis/SampleListMapper.xml rename to src/main/resources/org/cbioportal/legacy/persistence/mybatis/SampleListMapper.xml index ffb47f850f5..3cbce6bf85c 100644 --- a/src/main/resources/org/cbioportal/persistence/mybatis/SampleListMapper.xml +++ b/src/main/resources/org/cbioportal/legacy/persistence/mybatis/SampleListMapper.xml @@ -1,7 +1,7 @@ - + sample_list.LIST_ID AS "${prefix}listId", @@ -16,13 +16,13 @@ , - + - SELECT @@ -53,7 +53,7 @@ - SELECT COUNT(*) AS totalCount FROM sample_list @@ -63,7 +63,7 @@ - SELECT @@ -74,7 +74,7 @@ WHERE sample_list.STABLE_ID = #{sampleListId} - SELECT @@ -101,7 +101,7 @@ WHERE sample_list.STABLE_ID = #{sampleListId} - SELECT sample_list_list.LIST_ID as sampleListId, sample.STABLE_ID as sampleId diff --git a/src/main/resources/org/cbioportal/persistence/mybatis/SampleMapper.xml b/src/main/resources/org/cbioportal/legacy/persistence/mybatis/SampleMapper.xml similarity index 92% rename from src/main/resources/org/cbioportal/persistence/mybatis/SampleMapper.xml rename to src/main/resources/org/cbioportal/legacy/persistence/mybatis/SampleMapper.xml index 21f4e86da37..291946fe0ed 100644 --- a/src/main/resources/org/cbioportal/persistence/mybatis/SampleMapper.xml +++ b/src/main/resources/org/cbioportal/legacy/persistence/mybatis/SampleMapper.xml @@ -1,7 +1,7 @@ - + sample.INTERNAL_ID AS "${prefix}internalId", @@ -15,7 +15,7 @@ , - + @@ -68,7 +68,7 @@ - SELECT @@ -89,7 +89,7 @@ - SELECT @@ -107,14 +107,14 @@ ) - SELECT COUNT(*) AS "totalCount" - SELECT COUNT(*) AS "totalCount" @@ -130,7 +130,7 @@ ) - SELECT @@ -140,7 +140,7 @@ AND cancer_study.CANCER_STUDY_IDENTIFIER = #{studyId} - SELECT @@ -149,7 +149,7 @@ WHERE sample.INTERNAL_ID = #{internalId} - SELECT @@ -165,7 +165,7 @@ - SELECT @@ -181,7 +181,7 @@ - SELECT diff --git a/src/main/resources/org/cbioportal/persistence/mybatis/SecurityMapper.xml b/src/main/resources/org/cbioportal/legacy/persistence/mybatis/SecurityMapper.xml similarity index 88% rename from src/main/resources/org/cbioportal/persistence/mybatis/SecurityMapper.xml rename to src/main/resources/org/cbioportal/legacy/persistence/mybatis/SecurityMapper.xml index 77eb4a73004..8c2c7694833 100644 --- a/src/main/resources/org/cbioportal/persistence/mybatis/SecurityMapper.xml +++ b/src/main/resources/org/cbioportal/legacy/persistence/mybatis/SecurityMapper.xml @@ -1,18 +1,18 @@ - + - + - SELECT LOWER(email) AS email, name, diff --git a/src/main/resources/org/cbioportal/persistence/mybatis/SignificantCopyNumberRegionMapper.xml b/src/main/resources/org/cbioportal/legacy/persistence/mybatis/SignificantCopyNumberRegionMapper.xml similarity index 88% rename from src/main/resources/org/cbioportal/persistence/mybatis/SignificantCopyNumberRegionMapper.xml rename to src/main/resources/org/cbioportal/legacy/persistence/mybatis/SignificantCopyNumberRegionMapper.xml index eeea7c87f8c..c4cbfb34809 100644 --- a/src/main/resources/org/cbioportal/persistence/mybatis/SignificantCopyNumberRegionMapper.xml +++ b/src/main/resources/org/cbioportal/legacy/persistence/mybatis/SignificantCopyNumberRegionMapper.xml @@ -1,7 +1,7 @@ - + gistic.GISTIC_ROI_ID AS "gisticRoiId", @@ -25,7 +25,7 @@ - SELECT @@ -41,14 +41,14 @@ - SELECT COUNT(*) AS totalCount - SELECT gistic_to_gene.GISTIC_ROI_ID AS gisticRoiId, gistic_to_gene.ENTREZ_GENE_ID AS entrezGeneId, diff --git a/src/main/resources/org/cbioportal/persistence/mybatis/SignificantlyMutatedGeneMapper.xml b/src/main/resources/org/cbioportal/legacy/persistence/mybatis/SignificantlyMutatedGeneMapper.xml similarity index 90% rename from src/main/resources/org/cbioportal/persistence/mybatis/SignificantlyMutatedGeneMapper.xml rename to src/main/resources/org/cbioportal/legacy/persistence/mybatis/SignificantlyMutatedGeneMapper.xml index 51d26473570..a3b4a463011 100644 --- a/src/main/resources/org/cbioportal/persistence/mybatis/SignificantlyMutatedGeneMapper.xml +++ b/src/main/resources/org/cbioportal/legacy/persistence/mybatis/SignificantlyMutatedGeneMapper.xml @@ -1,7 +1,7 @@ - + mut_sig.ENTREZ_GENE_ID AS "entrezGeneId", @@ -26,7 +26,7 @@ - SELECT @@ -43,7 +43,7 @@ - SELECT COUNT(*) AS totalCount diff --git a/src/main/resources/org/cbioportal/persistence/mybatis/StaticDataTimestampMapper.xml b/src/main/resources/org/cbioportal/legacy/persistence/mybatis/StaticDataTimestampMapper.xml similarity index 80% rename from src/main/resources/org/cbioportal/persistence/mybatis/StaticDataTimestampMapper.xml rename to src/main/resources/org/cbioportal/legacy/persistence/mybatis/StaticDataTimestampMapper.xml index d1e69e5d8b7..fd058d34c0d 100644 --- a/src/main/resources/org/cbioportal/persistence/mybatis/StaticDataTimestampMapper.xml +++ b/src/main/resources/org/cbioportal/legacy/persistence/mybatis/StaticDataTimestampMapper.xml @@ -1,9 +1,9 @@ - + - SELECT TABLE_NAME AS "tableName", diff --git a/src/main/resources/org/cbioportal/persistence/mybatis/StructuralVariantMapper.xml b/src/main/resources/org/cbioportal/legacy/persistence/mybatis/StructuralVariantMapper.xml similarity index 96% rename from src/main/resources/org/cbioportal/persistence/mybatis/StructuralVariantMapper.xml rename to src/main/resources/org/cbioportal/legacy/persistence/mybatis/StructuralVariantMapper.xml index 0fe8bbe8955..45ea024fca7 100644 --- a/src/main/resources/org/cbioportal/persistence/mybatis/StructuralVariantMapper.xml +++ b/src/main/resources/org/cbioportal/legacy/persistence/mybatis/StructuralVariantMapper.xml @@ -1,7 +1,7 @@ - + genetic_profile.STABLE_ID AS "${prefix}molecularProfileId", @@ -92,20 +92,20 @@ - + AND structural_variant.SITE1_ENTREZ_GENE_ID IS NULL - + AND structural_variant.SITE1_ENTREZ_GENE_ID = ${geneFilterQuery.getGene1Query().getEntrezId()} - + AND structural_variant.SITE2_ENTREZ_GENE_ID IS NULL - + AND structural_variant.SITE2_ENTREZ_GENE_ID = ${geneFilterQuery.getGene2Query().getEntrezId()} @@ -243,7 +243,7 @@ - SELECT @@ -269,7 +269,7 @@ ORDER BY gene1.HUGO_GENE_SYMBOL, gene2.HUGO_GENE_SYMBOL - SELECT @@ -295,7 +295,7 @@ ORDER BY gene1.HUGO_GENE_SYMBOL, gene2.HUGO_GENE_SYMBOL - SELECT diff --git a/src/main/resources/org/cbioportal/persistence/mybatis/StudyMapper.xml b/src/main/resources/org/cbioportal/legacy/persistence/mybatis/StudyMapper.xml similarity index 95% rename from src/main/resources/org/cbioportal/persistence/mybatis/StudyMapper.xml rename to src/main/resources/org/cbioportal/legacy/persistence/mybatis/StudyMapper.xml index 9b580a23507..eff6ccbd3b5 100644 --- a/src/main/resources/org/cbioportal/persistence/mybatis/StudyMapper.xml +++ b/src/main/resources/org/cbioportal/legacy/persistence/mybatis/StudyMapper.xml @@ -1,7 +1,7 @@ - + cancer_study.CANCER_STUDY_ID AS "${prefix}cancerStudyId", @@ -95,7 +95,7 @@ - SELECT @@ -125,7 +125,7 @@ - SELECT COUNT(*) AS totalCount FROM cancer_study @@ -135,7 +135,7 @@ - SELECT @@ -152,7 +152,7 @@ GROUP BY cancer_study.CANCER_STUDY_ID - SELECT cancer_study_tags.CANCER_STUDY_ID AS cancerStudyId, cancer_study_tags.TAGS AS tags @@ -161,7 +161,7 @@ WHERE cancer_study.CANCER_STUDY_IDENTIFIER = #{studyId} - SELECT cancer_study_tags.CANCER_STUDY_ID AS cancerStudyId, cancer_study_tags.TAGS AS tags, diff --git a/src/main/resources/org/cbioportal/persistence/mybatis/TreatmentMapper.xml b/src/main/resources/org/cbioportal/legacy/persistence/mybatis/TreatmentMapper.xml similarity index 95% rename from src/main/resources/org/cbioportal/persistence/mybatis/TreatmentMapper.xml rename to src/main/resources/org/cbioportal/legacy/persistence/mybatis/TreatmentMapper.xml index 58c93613077..91037a138f4 100644 --- a/src/main/resources/org/cbioportal/persistence/mybatis/TreatmentMapper.xml +++ b/src/main/resources/org/cbioportal/legacy/persistence/mybatis/TreatmentMapper.xml @@ -1,9 +1,9 @@ - + - SELECT clinical_event_data.VALUE as treatment, patient.STABLE_ID as patientId, @@ -21,7 +21,7 @@ AND clinical_event_data.KEY = #{key} - SELECT sample.STABLE_ID as sampleId, patient.STABLE_ID as patientId, @@ -38,7 +38,7 @@ AND (clinical_event.EVENT_TYPE LIKE 'Sample Acquisition' OR clinical_event.EVENT_TYPE LIKE 'SPECIMEN') - SELECT sample.STABLE_ID as sampleId, patient.STABLE_ID as patientId, diff --git a/src/main/resources/org/cbioportal/persistence/mybatis/VariantCountMapper.xml b/src/main/resources/org/cbioportal/legacy/persistence/mybatis/VariantCountMapper.xml similarity index 89% rename from src/main/resources/org/cbioportal/persistence/mybatis/VariantCountMapper.xml rename to src/main/resources/org/cbioportal/legacy/persistence/mybatis/VariantCountMapper.xml index 92dcfc2788b..35376d31c39 100644 --- a/src/main/resources/org/cbioportal/persistence/mybatis/VariantCountMapper.xml +++ b/src/main/resources/org/cbioportal/legacy/persistence/mybatis/VariantCountMapper.xml @@ -1,9 +1,9 @@ - + - SELECT genetic_profile.STABLE_ID AS molecularProfileId, mutation_count_by_keyword.KEYWORD AS keyword, diff --git a/src/main/resources/org/cbioportal/persistence/mybatis/GenericAssayMapper.xml b/src/main/resources/org/cbioportal/persistence/mybatis/GenericAssayMapper.xml deleted file mode 100644 index 5b767fb93b3..00000000000 --- a/src/main/resources/org/cbioportal/persistence/mybatis/GenericAssayMapper.xml +++ /dev/null @@ -1,72 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/src/main/resources/org/cbioportal/persistence/mybatisclickhouse/StudyViewAlterationFilterMapper.xml b/src/main/resources/org/cbioportal/persistence/mybatisclickhouse/StudyViewAlterationFilterMapper.xml index 7f003505381..ead231b0236 100644 --- a/src/main/resources/org/cbioportal/persistence/mybatisclickhouse/StudyViewAlterationFilterMapper.xml +++ b/src/main/resources/org/cbioportal/persistence/mybatisclickhouse/StudyViewAlterationFilterMapper.xml @@ -1,7 +1,7 @@ - + NULL diff --git a/src/main/resources/org/cbioportal/persistence/mybatisclickhouse/StudyViewFilterMapper.xml b/src/main/resources/org/cbioportal/persistence/mybatisclickhouse/StudyViewFilterMapper.xml index 74eca303a81..96d572c12b1 100644 --- a/src/main/resources/org/cbioportal/persistence/mybatisclickhouse/StudyViewFilterMapper.xml +++ b/src/main/resources/org/cbioportal/persistence/mybatisclickhouse/StudyViewFilterMapper.xml @@ -1,7 +1,7 @@ - + @@ -645,7 +645,7 @@ - + WITH all_samples AS ( SELECT sample_unique_id FROM sample_derived @@ -704,7 +704,8 @@ - + SELECT DISTINCT sample_unique_id FROM genomic_event_derived diff --git a/src/main/resources/org/cbioportal/persistence/mybatisclickhouse/StudyViewMapper.xml b/src/main/resources/org/cbioportal/persistence/mybatisclickhouse/StudyViewMapper.xml index ce2fd9bf6ed..60ce0f90dce 100644 --- a/src/main/resources/org/cbioportal/persistence/mybatisclickhouse/StudyViewMapper.xml +++ b/src/main/resources/org/cbioportal/persistence/mybatisclickhouse/StudyViewMapper.xml @@ -1,10 +1,10 @@ - + - SELECT internal_id as internalId, patient_stable_id as patientStableId, @@ -33,7 +33,7 @@ - SELECT hugo_gene_symbol as hugoGeneSymbol, entrez_gene_id as entrezGeneId, @@ -55,7 +55,7 @@ - SELECT hugo_gene_symbol as hugoGeneSymbol, entrez_gene_id as entrezGeneId, @@ -76,7 +76,7 @@ GROUP BY entrez_gene_id, hugo_gene_symbol, alteration, cytoband - SELECT hugo_gene_symbol as hugoGeneSymbol, entrez_gene_id as entrezGeneId, @@ -92,7 +92,7 @@ GROUP BY entrez_gene_id, hugo_gene_symbol - SELECT internal_id as internalId, replaceOne(sample_unique_id, concat(cancer_study_identifier, '_'), '') as sampleId, @@ -115,7 +115,7 @@ AND type = 'sample' - SELECT internal_id as internalId, replaceOne(patient_unique_id, concat(cancer_study_identifier, '_'), '') as patientId, @@ -149,7 +149,7 @@ - --we need to derive the alteration type from the stable_id by removing cancer study id --this should probaby be refactored at some point but we need to maintain api interface SELECT replaceOne(genetic_profile.stable_id, @@ -168,7 +168,7 @@ - SELECT name AS label, REPLACE(stable_id, CONCAT(cancer_study_identifier, '_'), '') AS value, @@ -415,10 +415,10 @@ hugo_gene_symbol - + - + @@ -426,17 +426,17 @@ - + - + - + - + @@ -451,7 +451,7 @@ - SELECT attr_id as attrId, datatype as dataType, @@ -461,7 +461,7 @@ JOIN cancer_study cs on cs.cancer_study_id = cam.cancer_study_id - SELECT attr_id as attrId, datatype as dataType, @@ -486,7 +486,7 @@ We compute the WES counts by using the query getSampleProfileCountWithoutPanelData and adding this value to the totalProfiled Count per gene in java. --> - SELECT gene as hugoGeneSymbol, COUNT(*) as numberOfProfiledCases @@ -546,7 +546,7 @@ - SELECT gene as hugoGeneSymbol, gene_panel_id as genePanelId @@ -567,7 +567,7 @@ GROUP BY gene, gene_panel_id - SELECT event_type as eventType, count(DISTINCT patient_unique_id) as count @@ -601,7 +601,7 @@ - + @@ -649,7 +649,7 @@ - + @@ -699,7 +699,7 @@ GROUP BY treatments.treatment - WITH genomic_numerical_query AS ( @@ -742,7 +742,7 @@ cast(((SELECT * FROM ()) - coalesce((SELECT genomic_numerical_count FROM genomic_numerical_sum LIMIT 1), 0)) as INTEGER) as count - WITH generic_assay_query AS ( @@ -785,7 +785,7 @@ cast(((SELECT * FROM ()) - coalesce((SELECT generic_assay_count FROM generic_assay_sum LIMIT 1), 0)) as INTEGER) as count - SELECT genetic_profile.genetic_profile_id AS "molecularProfileId", genetic_profile.stable_id AS "stableId", @@ -806,7 +806,7 @@ WHERE genetic_profile.genetic_alteration_type = 'GENERIC_ASSAY' - WITH unique_study_ids AS ( SELECT DISTINCT cancer_study_identifier diff --git a/src/main/resources/templates/index.html b/src/main/resources/templates/index.html index 3b828ef82bd..5a39ef4ff45 100644 --- a/src/main/resources/templates/index.html +++ b/src/main/resources/templates/index.html @@ -1,6 +1,15 @@ - + + + + @@ -70,6 +79,12 @@ + + + diff --git a/src/main/resources/templates/tracking_include.html b/src/main/resources/templates/tracking_include.html index 6c0f1070639..bdcb02f7a0f 100644 --- a/src/main/resources/templates/tracking_include.html +++ b/src/main/resources/templates/tracking_include.html @@ -1,6 +1,9 @@ - diff --git a/src/test/java/org/cbioportal/application/security/util/ClaimRoleExtractorUtilTest.java b/src/test/java/org/cbioportal/application/security/util/ClaimRoleExtractorUtilTest.java new file mode 100644 index 00000000000..1f15a1ac9a5 --- /dev/null +++ b/src/test/java/org/cbioportal/application/security/util/ClaimRoleExtractorUtilTest.java @@ -0,0 +1,90 @@ +package org.cbioportal.application.security.util; + +import static org.junit.jupiter.api.Assertions.*; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ObjectNode; +import java.time.Instant; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import org.junit.jupiter.api.Test; +import org.junit.runner.RunWith; +import org.mockito.junit.MockitoJUnitRunner; + +@RunWith(MockitoJUnitRunner.class) +class ClaimRoleExtractorUtilTest { + + @Test + void shouldExtractRolesFromSerializedClaims() { + String claims = + """ + { + "roles": ["role1", "role2"] + } + """; + String jwtRolesPath = "roles"; + var result = ClaimRoleExtractorUtil.extractClientRoles(claims, jwtRolesPath); + assertNotNull(result); + assertEquals(2, result.size()); + assertTrue(result.contains("role1")); + assertTrue(result.contains("role2")); + } + + @Test + void shouldExtractRolesFromJsonNodeClaims() { + ObjectMapper objectMapper = new ObjectMapper(); + String roleString = + """ + ["role1","role2","role3"] + """; + ObjectNode root = objectMapper.createObjectNode(); + root.put("roles", roleString); + String jwtRolesPath = "roles"; + + var result = ClaimRoleExtractorUtil.extractClientRoles(root, jwtRolesPath); + + assertNotNull(result); + assertEquals(3, result.size()); + assertTrue(result.contains("role1")); + assertTrue(result.contains("role2")); + assertTrue(result.contains("role3")); + } + + @Test + void shouldExtractRolesFromString() { + ObjectMapper objectMapper = new ObjectMapper(); + String groupString = + """ + ["GROUP_A","GROUP_B","GROUP_C"] + """; + ObjectNode root = objectMapper.createObjectNode(); + root.put("groups", groupString); + String jwtRolesPath = "groups"; + + var result = ClaimRoleExtractorUtil.extractClientRoles(root, jwtRolesPath); + + assertNotNull(result); + assertEquals(3, result.size()); + assertTrue(result.contains("GROUP_A")); + assertTrue(result.contains("GROUP_B")); + assertTrue(result.contains("GROUP_C")); + } + + @Test + void shouldExtractRolesFormIdToken() { + + Map claims = new HashMap<>(); + claims.put("aud", "my-app-client-id"); + claims.put("exp", Instant.now()); + claims.put("iat", Instant.now()); + claims.put("groups", List.of("GROUP_X", "GROUP_Y")); + + String jwtRolesPath = "groups"; + var result = ClaimRoleExtractorUtil.extractClientRoles(claims, jwtRolesPath); + assertNotNull(result); + assertEquals(2, result.size()); + assertTrue(result.contains("GROUP_X")); + assertTrue(result.contains("GROUP_Y")); + } +} diff --git a/src/test/java/org/cbioportal/cancerstudy/usecase/GetCancerStudyMetadataUseCaseTest.java b/src/test/java/org/cbioportal/cancerstudy/usecase/GetCancerStudyMetadataUseCaseTest.java new file mode 100644 index 00000000000..b80137fda0f --- /dev/null +++ b/src/test/java/org/cbioportal/cancerstudy/usecase/GetCancerStudyMetadataUseCaseTest.java @@ -0,0 +1,45 @@ +package org.cbioportal.cancerstudy.usecase; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.verify; + +import org.cbioportal.domain.cancerstudy.repository.CancerStudyRepository; +import org.cbioportal.domain.cancerstudy.usecase.GetCancerStudyMetadataUseCase; +import org.cbioportal.shared.SortAndSearchCriteria; +import org.cbioportal.shared.enums.ProjectionType; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnitRunner; + +@RunWith(MockitoJUnitRunner.class) +public class GetCancerStudyMetadataUseCaseTest { + + @InjectMocks private GetCancerStudyMetadataUseCase getCancerStudyMetadataUseCase; + + @Mock CancerStudyRepository cancerStudyRepository; + + @Test + public void testExecuteWithProjectionTypeSummary() { + getCancerStudyMetadataUseCase.execute( + ProjectionType.SUMMARY, new SortAndSearchCriteria("", "", "")); + verify(cancerStudyRepository).getCancerStudiesMetadataSummary(any(SortAndSearchCriteria.class)); + } + + @Test + public void testExecuteWithProjectionTypeDetailed() { + getCancerStudyMetadataUseCase.execute( + ProjectionType.DETAILED, new SortAndSearchCriteria("", "", "")); + verify(cancerStudyRepository).getCancerStudiesMetadata(any(SortAndSearchCriteria.class)); + } + + @Test + public void testExecuteWithProjectionTypeDefault() { + Assert.assertTrue( + getCancerStudyMetadataUseCase + .execute(ProjectionType.META, new SortAndSearchCriteria("", "", "")) + .isEmpty()); + } +} diff --git a/src/test/java/org/cbioportal/domain/alteration/util/AlterationEnrichmentScoreUtilTest.java b/src/test/java/org/cbioportal/domain/alteration/util/AlterationEnrichmentScoreUtilTest.java new file mode 100644 index 00000000000..122a5a17932 --- /dev/null +++ b/src/test/java/org/cbioportal/domain/alteration/util/AlterationEnrichmentScoreUtilTest.java @@ -0,0 +1,50 @@ +package org.cbioportal.domain.alteration.util; + +import static org.junit.Assert.*; + +import java.util.ArrayList; +import java.util.List; +import org.cbioportal.legacy.model.AlterationEnrichment; +import org.cbioportal.legacy.model.CountSummary; +import org.junit.Test; + +public class AlterationEnrichmentScoreUtilTest { + + @Test + public void calculateEnrichmentScore() { + // create molecularProfileCaseSet1, molecularProfileCaseSet2 list of entities + + AlterationEnrichment alterationEnrichment = new AlterationEnrichment(); + + List countSummaries = new ArrayList<>(); + CountSummary countSummary1 = new CountSummary(); + CountSummary countSummary2 = new CountSummary(); + CountSummary countSummary3 = new CountSummary(); + CountSummary countSummary4 = new CountSummary(); + countSummary1.setAlteredCount(0); + countSummary1.setProfiledCount(943); + countSummary1.setName("groupD"); + + countSummary2.setAlteredCount(1); + countSummary2.setProfiledCount(2103); + countSummary2.setName("groupB"); + + countSummary3.setAlteredCount(0); + countSummary3.setProfiledCount(680); + countSummary3.setName("groupC"); + + countSummary4.setAlteredCount(0); + countSummary4.setProfiledCount(6144); + countSummary4.setName("groupD"); + + countSummaries.add(countSummary1); + countSummaries.add(countSummary2); + countSummaries.add(countSummary3); + countSummaries.add(countSummary4); + alterationEnrichment.setEntrezGeneId(2); + alterationEnrichment.setCounts(countSummaries); + + var pValue = AlterationEnrichmentScoreUtil.calculateEnrichmentScore(alterationEnrichment); + assertEquals(0.2964987551514857, pValue.doubleValue(), 1e-10); + } +} diff --git a/src/test/java/org/cbioportal/infrastructure/repository/clickhouse/AbstractTestcontainers.java b/src/test/java/org/cbioportal/infrastructure/repository/clickhouse/AbstractTestcontainers.java new file mode 100644 index 00000000000..7e9c88ddb4f --- /dev/null +++ b/src/test/java/org/cbioportal/infrastructure/repository/clickhouse/AbstractTestcontainers.java @@ -0,0 +1,44 @@ +package org.cbioportal.infrastructure.repository.clickhouse; + +import org.junit.BeforeClass; +import org.junit.ClassRule; +import org.springframework.boot.test.util.TestPropertyValues; +import org.springframework.context.ApplicationContextInitializer; +import org.springframework.context.ConfigurableApplicationContext; +import org.testcontainers.clickhouse.ClickHouseContainer; +import org.testcontainers.containers.BindMode; + +public abstract class AbstractTestcontainers { + @BeforeClass + public static void beforeAll() {} + + @ClassRule + public static final ClickHouseContainer clickhouseContainer = + new ClickHouseContainer("clickhouse/clickhouse-server:24.5") + .withUsername("cbio_user") + .withPassword("P@ssword1") + .withClasspathResourceMapping( + "clickhouse_cgds.sql", "/docker-entrypoint-initdb.d/a_schema.sql", BindMode.READ_ONLY) + .withClasspathResourceMapping( + "clickhouse_data.sql", "/docker-entrypoint-initdb.d/b_schema.sql", BindMode.READ_ONLY) + .withClasspathResourceMapping( + "clickhouse/clickhouse.sql", + "/docker-entrypoint-initdb.d/c_schema.sql", + BindMode.READ_ONLY); + + public static class Initializer + implements ApplicationContextInitializer { + + @Override + public void initialize(ConfigurableApplicationContext configurableApplicationContext) { + clickhouseContainer.start(); + TestPropertyValues values = + TestPropertyValues.of( + "spring.datasource.clickhouse.url=" + clickhouseContainer.getJdbcUrl(), + "spring.datasource.clickhouse.password=" + clickhouseContainer.getPassword(), + "spring.datasource.clickhouse.username=" + clickhouseContainer.getUsername(), + "spring.datasource.clickhouse.driver-class-name=com.clickhouse.jdbc.ClickHouseDriver"); + values.applyTo(configurableApplicationContext); + } + } +} diff --git a/src/test/java/org/cbioportal/infrastructure/repository/clickhouse/alteration/ClickhouseAlterationMapperTest.java b/src/test/java/org/cbioportal/infrastructure/repository/clickhouse/alteration/ClickhouseAlterationMapperTest.java new file mode 100644 index 00000000000..24a6a6a541f --- /dev/null +++ b/src/test/java/org/cbioportal/infrastructure/repository/clickhouse/alteration/ClickhouseAlterationMapperTest.java @@ -0,0 +1,420 @@ +package org.cbioportal.infrastructure.repository.clickhouse.alteration; + +import static org.junit.Assert.*; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import org.cbioportal.domain.studyview.StudyViewFilterFactory; +import org.cbioportal.infrastructure.repository.clickhouse.AbstractTestcontainers; +import org.cbioportal.infrastructure.repository.clickhouse.config.MyBatisConfig; +import org.cbioportal.legacy.model.AlterationFilter; +import org.cbioportal.legacy.model.CNA; +import org.cbioportal.legacy.model.MutationEventType; +import org.cbioportal.legacy.persistence.helper.AlterationFilterHelper; +import org.cbioportal.legacy.web.parameter.StudyViewFilter; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase; +import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; +import org.springframework.context.annotation.Import; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@Import(MyBatisConfig.class) +@DataJpaTest +@DirtiesContext +@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE) +@ContextConfiguration(initializers = AbstractTestcontainers.Initializer.class) +public class ClickhouseAlterationMapperTest { + private static final String STUDY_TCGA_PUB = "study_tcga_pub"; + private static final String STUDY_ACC_TCGA = "acc_tcga"; + private static final String STUDY_GENIE_PUB = "study_genie_pub"; + + @Autowired private ClickhouseAlterationMapper mapper; + + @Test + public void getMutatedGenes() { + StudyViewFilter studyViewFilter = new StudyViewFilter(); + studyViewFilter.setStudyIds(List.of(STUDY_TCGA_PUB)); + var alterationCountByGenes = + mapper.getMutatedGenes( + StudyViewFilterFactory.make(studyViewFilter, null, studyViewFilter.getStudyIds(), null), + AlterationFilterHelper.build(studyViewFilter.getAlterationFilter())); + assertEquals(3, alterationCountByGenes.size()); + + var testBrca1AlterationCount = + alterationCountByGenes.stream() + .filter(a -> Objects.equals(a.getHugoGeneSymbol(), "BRCA1")) + .findFirst(); + assert (testBrca1AlterationCount.isPresent()); + assertEquals(Integer.valueOf(5), testBrca1AlterationCount.get().getTotalCount()); + } + + @Test + public void getMutatedGenesWithAlterationFilter() { + StudyViewFilter studyViewFilter = new StudyViewFilter(); + studyViewFilter.setStudyIds(List.of(STUDY_TCGA_PUB)); + + // Create AlterationFilter + AlterationFilter alterationFilter = new AlterationFilter(); + Map mutationEventTypeFilterMap = new HashMap<>(); + mutationEventTypeFilterMap.put(MutationEventType.nonsense_mutation, Boolean.TRUE); + mutationEventTypeFilterMap.put(MutationEventType.other, Boolean.FALSE); + alterationFilter.setMutationEventTypes(mutationEventTypeFilterMap); + + var alterationCountByGenes = + mapper.getMutatedGenes( + StudyViewFilterFactory.make(studyViewFilter, null, studyViewFilter.getStudyIds(), null), + AlterationFilterHelper.build(alterationFilter)); + assertEquals(2, alterationCountByGenes.size()); + + AlterationFilter onlyMutationStatusFilter = new AlterationFilter(); + onlyMutationStatusFilter.setMutationEventTypes(new HashMap<>()); + onlyMutationStatusFilter.setIncludeGermline(false); + onlyMutationStatusFilter.setIncludeSomatic(false); + onlyMutationStatusFilter.setIncludeUnknownStatus(true); + + var alterationCountByGenes1 = + mapper.getMutatedGenes( + StudyViewFilterFactory.make(studyViewFilter, null, studyViewFilter.getStudyIds(), null), + AlterationFilterHelper.build(onlyMutationStatusFilter)); + assertEquals(1, alterationCountByGenes1.size()); + + AlterationFilter mutationTypeAndStatusFilter = new AlterationFilter(); + mutationTypeAndStatusFilter.setMutationEventTypes(mutationEventTypeFilterMap); + mutationTypeAndStatusFilter.setMutationEventTypes(new HashMap<>()); + mutationTypeAndStatusFilter.setIncludeGermline(false); + mutationTypeAndStatusFilter.setIncludeSomatic(false); + mutationTypeAndStatusFilter.setIncludeUnknownStatus(true); + + var alterationCountByGenes2 = + mapper.getMutatedGenes( + StudyViewFilterFactory.make(studyViewFilter, null, studyViewFilter.getStudyIds(), null), + AlterationFilterHelper.build(onlyMutationStatusFilter)); + assertEquals(1, alterationCountByGenes2.size()); + } + + @Test + public void getCnaGenes() { + StudyViewFilter studyViewFilter = new StudyViewFilter(); + studyViewFilter.setStudyIds(List.of(STUDY_TCGA_PUB)); + var alterationCountByGenes = + mapper.getCnaGenes( + StudyViewFilterFactory.make(studyViewFilter, null, studyViewFilter.getStudyIds(), null), + AlterationFilterHelper.build(studyViewFilter.getAlterationFilter())); + assertEquals(3, alterationCountByGenes.size()); + + // Test cna count for akt1 + var testAKT1AlterationCount = + alterationCountByGenes.stream() + .filter(a -> Objects.equals(a.getHugoGeneSymbol(), "AKT1")) + .mapToInt(c -> c.getTotalCount().intValue()) + .sum(); + assertEquals(3, testAKT1AlterationCount); + } + + @Test + public void getCnaGenesWithAlterationFilter() { + StudyViewFilter studyViewFilter = new StudyViewFilter(); + studyViewFilter.setStudyIds(List.of(STUDY_TCGA_PUB)); + + // Create AlterationFilter + AlterationFilter alterationFilter = new AlterationFilter(); + Map cnaEventTypeFilterMap = new HashMap<>(); + cnaEventTypeFilterMap.put(CNA.HOMDEL, false); + cnaEventTypeFilterMap.put(CNA.AMP, true); + alterationFilter.setCopyNumberAlterationEventTypes(cnaEventTypeFilterMap); + + var alterationCountByGenes = + mapper.getCnaGenes( + StudyViewFilterFactory.make(studyViewFilter, null, studyViewFilter.getStudyIds(), null), + AlterationFilterHelper.build(alterationFilter)); + assertEquals(2, alterationCountByGenes.size()); + + // Test cna count for akt1 filtering for AMP + var testAKT1AlterationCount = + alterationCountByGenes.stream() + .filter(a -> Objects.equals(a.getHugoGeneSymbol(), "AKT1")) + .mapToInt(c -> c.getTotalCount().intValue()) + .sum(); + assertEquals(2, testAKT1AlterationCount); + } + + @Test + public void getStructuralVariantGenes() { + StudyViewFilter studyViewFilter = new StudyViewFilter(); + studyViewFilter.setStudyIds(List.of(STUDY_TCGA_PUB, STUDY_ACC_TCGA)); + var alterationCountByGenes = + mapper.getStructuralVariantGenes( + StudyViewFilterFactory.make(studyViewFilter, null, studyViewFilter.getStudyIds(), null), + AlterationFilterHelper.build(studyViewFilter.getAlterationFilter())); + assertEquals(8, alterationCountByGenes.size()); + + // Test sv count for eml4 which is in one study + var testeml4AlterationCount = + alterationCountByGenes.stream() + .filter(a -> Objects.equals(a.getHugoGeneSymbol(), "eml4")) + .mapToInt(c -> c.getTotalCount().intValue()) + .sum(); + assertEquals(1, testeml4AlterationCount); + + // Test sv count for ncoa4 which is in both studies + var testncoa4AlterationCount = + alterationCountByGenes.stream() + .filter(a -> Objects.equals(a.getHugoGeneSymbol(), "ncoa4")) + .mapToInt(c -> c.getTotalCount().intValue()) + .sum(); + assertEquals(3, testncoa4AlterationCount); + } + + @Test + public void getTotalProfiledCountsByGene() { + StudyViewFilter studyViewFilter = new StudyViewFilter(); + studyViewFilter.setStudyIds(List.of(STUDY_TCGA_PUB)); + + // Testing profiled counts on samples with gene panel data and WES for one study + var totalProfiledCountsForMutationsMap = + mapper.getTotalProfiledCounts( + StudyViewFilterFactory.make(studyViewFilter, null, studyViewFilter.getStudyIds(), null), + "MUTATION_EXTENDED", + List.of()); + var totalProfiledCountsForCnaMap = + mapper.getTotalProfiledCounts( + StudyViewFilterFactory.make(studyViewFilter, null, studyViewFilter.getStudyIds(), null), + "COPY_NUMBER_ALTERATION", + List.of()); + var sampleProfiledCountsForMutationsWithoutPanelDataMap = + mapper.getSampleProfileCountWithoutPanelData( + StudyViewFilterFactory.make(studyViewFilter, null, studyViewFilter.getStudyIds(), null), + "MUTATION_EXTENDED"); + var sampleProfiledCountsForCnaWithoutPanelDataMap = + mapper.getSampleProfileCountWithoutPanelData( + StudyViewFilterFactory.make(studyViewFilter, null, studyViewFilter.getStudyIds(), null), + "COPY_NUMBER_ALTERATION"); + + // Assert the count of genes with profiled cases for mutations + assertEquals(5, totalProfiledCountsForMutationsMap.size()); + // Assert the count of genes with profiled cases for CNA + assertEquals(5, totalProfiledCountsForCnaMap.size()); + // Assert the profiled counts for mutations without panel data (WES) + assertEquals(6, sampleProfiledCountsForMutationsWithoutPanelDataMap); + // Assert the profiled counts for CNA without panel data (WES) + assertEquals(11, sampleProfiledCountsForCnaWithoutPanelDataMap); + + // Assert the profiled counts for AKT2 mutations + // AKT2 is on testpanel2 in STUDY_TCGA_PUB + var akt2TotalProfiledCountsForMutations = + totalProfiledCountsForMutationsMap.stream() + .filter(c -> c.getHugoGeneSymbol().equals("AKT2")) + .findFirst(); + assertTrue(akt2TotalProfiledCountsForMutations.isPresent()); + assertEquals( + 4, akt2TotalProfiledCountsForMutations.get().getNumberOfProfiledCases().intValue()); + // Assert the profiled counts for BRCA1 mutations + // BRCA1 is on testpanel1 in STUDY_TCGA_PUB + var brca1TotalProfiledCountsForMutations = + totalProfiledCountsForMutationsMap.stream() + .filter(c -> c.getHugoGeneSymbol().equals("BRCA1")) + .findFirst(); + assertTrue(brca1TotalProfiledCountsForMutations.isPresent()); + assertEquals( + 1, brca1TotalProfiledCountsForMutations.get().getNumberOfProfiledCases().intValue()); + // Assert the profiled counts for AKT1 mutations + // AKT1 is on both testpanel1 and testpanel2 in STUDY_TCGA_PUB + var akt1TotalProfiledCountsForMutations = + totalProfiledCountsForMutationsMap.stream() + .filter(c -> c.getHugoGeneSymbol().equals("AKT1")) + .findFirst(); + assertTrue(akt1TotalProfiledCountsForMutations.isPresent()); + assertEquals( + 5, akt1TotalProfiledCountsForMutations.get().getNumberOfProfiledCases().intValue()); + + // Assert the profiled counts for AKT2 CNA + // AKT2 is on testpanel2 in STUDY_TCGA_PUB + var akt2TotalProfiledCountsForCna = + totalProfiledCountsForCnaMap.stream() + .filter(c -> c.getHugoGeneSymbol().equals("AKT2")) + .findFirst(); + assertTrue(akt2TotalProfiledCountsForCna.isPresent()); + assertEquals(6, akt2TotalProfiledCountsForCna.get().getNumberOfProfiledCases().intValue()); + // Assert the profiled counts for BRCA1 CNA + // BRCA1 is on testpanel1 in STUDY_TCGA_PUB + var brca1TotalProfiledCountsForCna = + totalProfiledCountsForCnaMap.stream() + .filter(c -> c.getHugoGeneSymbol().equals("BRCA1")) + .findFirst(); + assertTrue(brca1TotalProfiledCountsForCna.isPresent()); + assertEquals(2, brca1TotalProfiledCountsForCna.get().getNumberOfProfiledCases().intValue()); + // Assert the profiled counts for AKT1 CNA + // AKT1 is on both testpanel1 and testpanel2 in STUDY_TCGA_PUB + var akt1TotalProfiledCountsForCna = + totalProfiledCountsForCnaMap.stream() + .filter(c -> c.getHugoGeneSymbol().equals("AKT1")) + .findFirst(); + assertTrue(akt1TotalProfiledCountsForCna.isPresent()); + assertEquals(8, akt1TotalProfiledCountsForCna.get().getNumberOfProfiledCases().intValue()); + + // Testing profiled counts on combined studies + studyViewFilter.setStudyIds(List.of(STUDY_TCGA_PUB, STUDY_GENIE_PUB)); + + // Testing profiled counts on samples with gene panel data and WES for a combined study + var totalProfiledCountsForMutationsMap1 = + mapper.getTotalProfiledCounts( + StudyViewFilterFactory.make(studyViewFilter, null, studyViewFilter.getStudyIds(), null), + "MUTATION_EXTENDED", + List.of()); + var totalProfiledCountsForCnaMap1 = + mapper.getTotalProfiledCounts( + StudyViewFilterFactory.make(studyViewFilter, null, studyViewFilter.getStudyIds(), null), + "COPY_NUMBER_ALTERATION", + List.of()); + var sampleProfiledCountsForMutationsWithoutPanelDataMap1 = + mapper.getSampleProfileCountWithoutPanelData( + StudyViewFilterFactory.make(studyViewFilter, null, studyViewFilter.getStudyIds(), null), + "MUTATION_EXTENDED"); + var sampleProfiledCountsForCnaWithoutPanelDataMap1 = + mapper.getSampleProfileCountWithoutPanelData( + StudyViewFilterFactory.make(studyViewFilter, null, studyViewFilter.getStudyIds(), null), + "COPY_NUMBER_ALTERATION"); + + // Assert the count of genes with profiled cases for mutations in a combined study + assertEquals(8, totalProfiledCountsForMutationsMap1.size()); + // Assert the count of genes with profiled cases for CNA in a combined study + assertEquals(8, totalProfiledCountsForCnaMap1.size()); + // Assert the profiled counts for mutations without panel data (WES) in a combined study + assertEquals(8, sampleProfiledCountsForMutationsWithoutPanelDataMap1); + // Assert the profiled counts for CNA without panel data (WES) in a combined study + assertEquals(12, sampleProfiledCountsForCnaWithoutPanelDataMap1); + + // Assert the profiled counts for BRCA1 mutations + // BRCA1 is on testpanel1 in STUDY_TCGA_PUB + var brca1TotalProfiledCountsForMutations1 = + totalProfiledCountsForMutationsMap1.stream() + .filter(c -> c.getHugoGeneSymbol().equals("BRCA1")) + .findFirst(); + assertTrue(brca1TotalProfiledCountsForMutations1.isPresent()); + assertEquals( + 1, brca1TotalProfiledCountsForMutations1.get().getNumberOfProfiledCases().intValue()); + // Assert the profiled counts for BRCA2 mutations + // BRCA2 is on testpanel3 and testpanel4 in STUDY_GENIE_PUB + var brca2TotalProfiledCountsForMutations1 = + totalProfiledCountsForMutationsMap1.stream() + .filter(c -> c.getHugoGeneSymbol().equals("BRCA2")) + .findFirst(); + assertTrue(brca2TotalProfiledCountsForMutations1.isPresent()); + assertEquals( + 2, brca2TotalProfiledCountsForMutations1.get().getNumberOfProfiledCases().intValue()); + // Assert the profiled counts for AKT2 mutations + // AKT2 is on testpanel2 in STUDY_TCGA_PUB and testpanel4 in STUDY_GENIE_PUB + var akt2TotalProfiledCountsForMutations1 = + totalProfiledCountsForMutationsMap1.stream() + .filter(c -> c.getHugoGeneSymbol().equals("AKT2")) + .findFirst(); + assertTrue(akt2TotalProfiledCountsForMutations1.isPresent()); + assertEquals( + 4, akt2TotalProfiledCountsForMutations1.get().getNumberOfProfiledCases().intValue()); + + // Assert the profiled counts for BRCA1 CNA + // BRCA1 is on testpanel1 in STUDY_TCGA_PUB + var brca1TotalProfiledCountsForCna1 = + totalProfiledCountsForCnaMap1.stream() + .filter(c -> c.getHugoGeneSymbol().equals("BRCA1")) + .findFirst(); + assertTrue(brca1TotalProfiledCountsForCna1.isPresent()); + assertEquals(2, brca1TotalProfiledCountsForCna1.get().getNumberOfProfiledCases().intValue()); + // Assert the profiled counts for BRCA2 CNA + // BRCA2 is on testpanel3 and testpanel4 in STUDY_GENIE_PUB + var brca2TotalProfiledCountsForCna1 = + totalProfiledCountsForCnaMap1.stream() + .filter(c -> c.getHugoGeneSymbol().equals("BRCA2")) + .findFirst(); + assertTrue(brca2TotalProfiledCountsForCna1.isPresent()); + assertEquals(3, brca2TotalProfiledCountsForCna1.get().getNumberOfProfiledCases().intValue()); + // Assert the profiled counts for AKT2 CNA + // AKT2 is on testpanel2 in STUDY_TCGA_PUB and testpanel4 in STUDY_GENIE_PUB + var akt2TotalProfiledCountsForCna1 = + totalProfiledCountsForCnaMap1.stream() + .filter(c -> c.getHugoGeneSymbol().equals("AKT2")) + .findFirst(); + assertTrue(akt2TotalProfiledCountsForCna1.isPresent()); + assertEquals(7, akt2TotalProfiledCountsForCna1.get().getNumberOfProfiledCases().intValue()); + } + + @Test + public void testMutatedGenesOnPanelCount() { + StudyViewFilter studyViewFilter = new StudyViewFilter(); + studyViewFilter.setStudyIds(List.of(STUDY_TCGA_PUB)); + var alterationCountByGenes = + mapper.getMutatedGenes( + StudyViewFilterFactory.make(studyViewFilter, null, studyViewFilter.getStudyIds(), null), + AlterationFilterHelper.build(studyViewFilter.getAlterationFilter())); + + // Test BRCA1: 4 total samples, 3 on-panel (samples 7,12,13 use WES), 1 off-panel (sample 6 uses + // testpanel2) + var brca1 = + alterationCountByGenes.stream() + .filter(a -> Objects.equals(a.getHugoGeneSymbol(), "BRCA1")) + .findFirst() + .orElse(null); + + assertNotNull("BRCA1 should be present", brca1); + assertEquals("BRCA1 total altered cases", Integer.valueOf(4), brca1.getNumberOfAlteredCases()); + assertEquals( + "BRCA1 on-panel altered cases", Integer.valueOf(3), brca1.getNumberOfAlteredCasesOnPanel()); + // totalCount = 5: sample 6 has 2 mutation events, samples 7,12,13 each have 1 (including sample + // 7's 'na' status which passes mutation_status != 'UNCALLED' filter) + assertEquals("BRCA1 total count", Integer.valueOf(5), brca1.getTotalCount()); + } + + @Test + public void testCnaGenesOnPanelCount() { + StudyViewFilter studyViewFilter = new StudyViewFilter(); + studyViewFilter.setStudyIds(List.of(STUDY_TCGA_PUB)); + var alterationCountByGenes = + mapper.getCnaGenes( + StudyViewFilterFactory.make(studyViewFilter, null, studyViewFilter.getStudyIds(), null), + AlterationFilterHelper.build(studyViewFilter.getAlterationFilter())); + + // Test AKT2: 1 total sample, 0 on-panel (sample 1 uses testpanel1 which doesn't contain AKT2) + var akt2 = + alterationCountByGenes.stream() + .filter(a -> Objects.equals(a.getHugoGeneSymbol(), "AKT2")) + .findFirst() + .orElse(null); + + assertNotNull("AKT2 should be present", akt2); + assertEquals("AKT2 total altered cases", Integer.valueOf(1), akt2.getNumberOfAlteredCases()); + assertEquals( + "AKT2 on-panel altered cases", Integer.valueOf(0), akt2.getNumberOfAlteredCasesOnPanel()); + assertEquals("AKT2 total count", Integer.valueOf(1), akt2.getTotalCount()); + } + + @Test + public void testStructuralVariantGenesOnPanelCount() { + StudyViewFilter studyViewFilter = new StudyViewFilter(); + studyViewFilter.setStudyIds(List.of(STUDY_TCGA_PUB, STUDY_ACC_TCGA)); + var alterationCountByGenes = + mapper.getStructuralVariantGenes( + StudyViewFilterFactory.make(studyViewFilter, null, studyViewFilter.getStudyIds(), null), + AlterationFilterHelper.build(studyViewFilter.getAlterationFilter())); + + // Test ncoa4: 2 total altered cases, 2 on-panel (both samples 1 and 15 use WES which contains + // all genes) + var ncoa4 = + alterationCountByGenes.stream() + .filter(a -> Objects.equals(a.getHugoGeneSymbol(), "ncoa4")) + .findFirst() + .orElse(null); + + assertNotNull("ncoa4 should be present", ncoa4); + assertEquals("ncoa4 total altered cases", Integer.valueOf(2), ncoa4.getNumberOfAlteredCases()); + assertEquals( + "ncoa4 on-panel altered cases", Integer.valueOf(2), ncoa4.getNumberOfAlteredCasesOnPanel()); + assertEquals("ncoa4 total count", Integer.valueOf(3), ncoa4.getTotalCount()); + } +} diff --git a/src/test/java/org/cbioportal/infrastructure/repository/clickhouse/clinical_data/ClickhouseClinicalDataMapperTest.java b/src/test/java/org/cbioportal/infrastructure/repository/clickhouse/clinical_data/ClickhouseClinicalDataMapperTest.java new file mode 100644 index 00000000000..b0605d84e69 --- /dev/null +++ b/src/test/java/org/cbioportal/infrastructure/repository/clickhouse/clinical_data/ClickhouseClinicalDataMapperTest.java @@ -0,0 +1,326 @@ +package org.cbioportal.infrastructure.repository.clickhouse.clinical_data; + +import static org.junit.Assert.*; + +import java.math.BigDecimal; +import java.util.Collections; +import java.util.List; +import org.cbioportal.domain.studyview.StudyViewFilterFactory; +import org.cbioportal.infrastructure.repository.clickhouse.AbstractTestcontainers; +import org.cbioportal.infrastructure.repository.clickhouse.config.MyBatisConfig; +import org.cbioportal.legacy.model.ClinicalDataCount; +import org.cbioportal.legacy.web.parameter.ClinicalDataFilter; +import org.cbioportal.legacy.web.parameter.DataFilterValue; +import org.cbioportal.legacy.web.parameter.StudyViewFilter; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase; +import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; +import org.springframework.context.annotation.Import; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@Import(MyBatisConfig.class) +@DataJpaTest +@DirtiesContext +@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE) +@ContextConfiguration(initializers = AbstractTestcontainers.Initializer.class) +public class ClickhouseClinicalDataMapperTest { + private static final String STUDY_ACC_TCGA = "acc_tcga"; + private static final String STUDY_GENIE_PUB = "study_genie_pub"; + + @Autowired private ClickhouseClinicalDataMapper mapper; + + @Test + public void getMutationCounts() { + StudyViewFilter studyViewFilter = new StudyViewFilter(); + studyViewFilter.setStudyIds(List.of(STUDY_GENIE_PUB)); + + var clinicalDataCountItems = + mapper.getClinicalDataCounts( + StudyViewFilterFactory.make(studyViewFilter, null, studyViewFilter.getStudyIds(), null), + List.of("mutation_count"), + Collections.emptyList()); + + var mutationsCountsOptional = + clinicalDataCountItems.stream() + .filter(c -> c.getAttributeId().equals("mutation_count")) + .findFirst(); + + assertTrue(mutationsCountsOptional.isPresent()); + var mutationsCounts = mutationsCountsOptional.get().getCounts(); + + assertEquals(6, mutationsCounts.size()); + assertEquals(1, findClinicaDataCount(mutationsCounts, "11")); + assertEquals(1, findClinicaDataCount(mutationsCounts, "6")); + assertEquals(2, findClinicaDataCount(mutationsCounts, "4")); + assertEquals(4, findClinicaDataCount(mutationsCounts, "2")); + assertEquals(2, findClinicaDataCount(mutationsCounts, "1")); + // 1 empty string + 1 'NAN' + 15 samples with no data + assertEquals(17, findClinicaDataCount(mutationsCounts, "NA")); + } + + @Test + public void getCenterCounts() { + StudyViewFilter studyViewFilter = new StudyViewFilter(); + studyViewFilter.setStudyIds(List.of(STUDY_GENIE_PUB)); + + var clinicalDataCounts = + mapper.getClinicalDataCounts( + StudyViewFilterFactory.make(studyViewFilter, null, studyViewFilter.getStudyIds(), null), + List.of("center"), + Collections.emptyList()); + + var categoricalClinicalDataCountsOptional = + clinicalDataCounts.stream().filter(c -> c.getAttributeId().equals("center")).findFirst(); + + assertTrue(categoricalClinicalDataCountsOptional.isPresent()); + var categoricalClinicalDataCounts = categoricalClinicalDataCountsOptional.get().getCounts(); + + assertEquals(7, categoricalClinicalDataCounts.size()); + assertEquals(3, findClinicaDataCount(categoricalClinicalDataCounts, "msk")); + assertEquals(2, findClinicaDataCount(categoricalClinicalDataCounts, "dfci")); + assertEquals(2, findClinicaDataCount(categoricalClinicalDataCounts, "chop")); + assertEquals(1, findClinicaDataCount(categoricalClinicalDataCounts, "mda")); + assertEquals(1, findClinicaDataCount(categoricalClinicalDataCounts, "ohsu")); + assertEquals(1, findClinicaDataCount(categoricalClinicalDataCounts, "ucsf")); + // 1 empty string + 1 'NA' + 12 samples with no data + assertEquals(14, findClinicaDataCount(categoricalClinicalDataCounts, "NA")); + } + + @Test + public void getDeadCounts() { + StudyViewFilter studyViewFilter = new StudyViewFilter(); + studyViewFilter.setStudyIds(List.of(STUDY_GENIE_PUB)); + + var clinicalDataCounts = + mapper.getClinicalDataCounts( + StudyViewFilterFactory.make(studyViewFilter, null, studyViewFilter.getStudyIds(), null), + List.of("dead"), + Collections.emptyList()); + + var categoricalClinicalDataCountsOptional = + clinicalDataCounts.stream().filter(c -> c.getAttributeId().equals("dead")).findFirst(); + + assertTrue(categoricalClinicalDataCountsOptional.isPresent()); + var categoricalClinicalDataCounts = categoricalClinicalDataCountsOptional.get().getCounts(); + + assertEquals(10, categoricalClinicalDataCounts.size()); + assertEquals(1, findClinicaDataCount(categoricalClinicalDataCounts, "True")); + assertEquals(1, findClinicaDataCount(categoricalClinicalDataCounts, "TRUE")); + assertEquals(1, findClinicaDataCount(categoricalClinicalDataCounts, "true")); + assertEquals(1, findClinicaDataCount(categoricalClinicalDataCounts, "False")); + assertEquals(2, findClinicaDataCount(categoricalClinicalDataCounts, "FALSE")); + assertEquals(1, findClinicaDataCount(categoricalClinicalDataCounts, "false")); + assertEquals(1, findClinicaDataCount(categoricalClinicalDataCounts, "Not Released")); + assertEquals(1, findClinicaDataCount(categoricalClinicalDataCounts, "Not Collected")); + assertEquals(1, findClinicaDataCount(categoricalClinicalDataCounts, "Unknown")); + // 1 empty string + 1 'N/A' + 12 samples with no data + assertEquals(14, findClinicaDataCount(categoricalClinicalDataCounts, "NA")); + } + + @Test + public void getMutationAndCenterCounts() { + StudyViewFilter studyViewFilter = new StudyViewFilter(); + studyViewFilter.setStudyIds(List.of(STUDY_GENIE_PUB)); + + var combinedClinicalDataCounts = + mapper.getClinicalDataCounts( + StudyViewFilterFactory.make(studyViewFilter, null, studyViewFilter.getStudyIds(), null), + List.of("mutation_count", "center"), + Collections.emptyList()); + + assertEquals(2, combinedClinicalDataCounts.size()); + } + + @Test + public void getAgeCounts() { + StudyViewFilter studyViewFilter = new StudyViewFilter(); + studyViewFilter.setStudyIds(List.of(STUDY_GENIE_PUB)); + + var clinicalDataCountItems = + mapper.getClinicalDataCounts( + StudyViewFilterFactory.make(studyViewFilter, null, studyViewFilter.getStudyIds(), null), + List.of("age"), + Collections.emptyList()); + + var ageCountsOptional = + clinicalDataCountItems.stream().filter(c -> c.getAttributeId().equals("age")).findFirst(); + + assertTrue(ageCountsOptional.isPresent()); + var ageCounts = ageCountsOptional.get().getCounts(); + + assertAgeCounts(ageCounts); + + // 1 empty string + 1 'NAN' + 1 'N/A' + 1 patient without data + assertEquals(4, findClinicaDataCount(ageCounts, "NA")); + } + + @Test + public void getAgeCountsForMultipleStudies() { + StudyViewFilter studyViewFilter = new StudyViewFilter(); + studyViewFilter.setStudyIds(List.of(STUDY_GENIE_PUB, STUDY_ACC_TCGA)); + + var clinicalDataCountItems = + mapper.getClinicalDataCounts( + StudyViewFilterFactory.make(studyViewFilter, null, studyViewFilter.getStudyIds(), null), + List.of("age"), + Collections.emptyList()); + + var ageCountsOptional = + clinicalDataCountItems.stream().filter(c -> c.getAttributeId().equals("age")).findFirst(); + + assertTrue(ageCountsOptional.isPresent()); + var ageCounts = ageCountsOptional.get().getCounts(); + + // everything should be exactly the same as single study (STUDY_GENIE_PUB) filter + // except NA counts + assertAgeCounts(ageCounts); + + // 1 empty string + 1 'NAN' + 1 'N/A' + 1 GENIE_PUB patient without data + 4 ACC_TCGA data + // without data + assertEquals(8, findClinicaDataCount(ageCounts, "NA")); + } + + private void assertAgeCounts(List ageCounts) { + assertEquals(15, ageCounts.size()); + + assertEquals(3, findClinicaDataCount(ageCounts, "<18")); + assertEquals(1, findClinicaDataCount(ageCounts, "18")); + assertEquals(1, findClinicaDataCount(ageCounts, "22")); + assertEquals(2, findClinicaDataCount(ageCounts, "42")); + assertEquals(1, findClinicaDataCount(ageCounts, "66")); + assertEquals(1, findClinicaDataCount(ageCounts, "66")); + assertEquals(1, findClinicaDataCount(ageCounts, "68")); + assertEquals(1, findClinicaDataCount(ageCounts, "77")); + assertEquals(1, findClinicaDataCount(ageCounts, "78")); + assertEquals(1, findClinicaDataCount(ageCounts, "79")); + assertEquals(2, findClinicaDataCount(ageCounts, "80")); + assertEquals(2, findClinicaDataCount(ageCounts, "82")); + assertEquals(1, findClinicaDataCount(ageCounts, "89")); + assertEquals(2, findClinicaDataCount(ageCounts, ">89")); + assertEquals(1, findClinicaDataCount(ageCounts, "UNKNOWN")); + } + + @Test + public void getMutationCountsFilteredByAge() { + StudyViewFilter studyViewFilter = new StudyViewFilter(); + studyViewFilter.setStudyIds(List.of(STUDY_GENIE_PUB)); + + // filter patients with age between 20 and 70 + // (there are 5 patients within this range, which are 307..311) + ClinicalDataFilter filter = buildClinicalDataFilter("age", 20, 70); + studyViewFilter.setClinicalDataFilters(List.of(filter)); + + var clinicalDataCountItems = + mapper.getClinicalDataCounts( + StudyViewFilterFactory.make(studyViewFilter, null, studyViewFilter.getStudyIds(), null), + List.of("mutation_count"), + Collections.emptyList()); + + var mutationsCountsOptional = + clinicalDataCountItems.stream() + .filter(c -> c.getAttributeId().equals("mutation_count")) + .findFirst(); + + assertTrue(mutationsCountsOptional.isPresent()); + var mutationCountsFiltered = mutationsCountsOptional.get().getCounts(); + + assertEquals(3, mutationCountsFiltered.size()); + assertEquals(2, findClinicaDataCount(mutationCountsFiltered, "2")); + assertEquals(2, findClinicaDataCount(mutationCountsFiltered, "1")); + assertEquals(1, findClinicaDataCount(mutationCountsFiltered, "NA")); + } + + @Test + public void getMutationCountsFilteredByAgeWithOpenStartValues() { + StudyViewFilter studyViewFilter = new StudyViewFilter(); + studyViewFilter.setStudyIds(List.of(STUDY_GENIE_PUB)); + + // filter patients with age less than 20 + // (there are 4 patients within this range, which are 301, 302, 303, and 306) + ClinicalDataFilter filter = buildClinicalDataFilter("age", null, 20); + studyViewFilter.setClinicalDataFilters(List.of(filter)); + + var clinicalDataCountItems = + mapper.getClinicalDataCounts( + StudyViewFilterFactory.make(studyViewFilter, null, studyViewFilter.getStudyIds(), null), + List.of("mutation_count"), + Collections.emptyList()); + + var mutationsCountsOptional = + clinicalDataCountItems.stream() + .filter(c -> c.getAttributeId().equals("mutation_count")) + .findFirst(); + + assertTrue(mutationsCountsOptional.isPresent()); + var mutationCountsFiltered = mutationsCountsOptional.get().getCounts(); + + assertEquals(4, mutationCountsFiltered.size()); + assertEquals(1, findClinicaDataCount(mutationCountsFiltered, "11")); // patient 301 + assertEquals(1, findClinicaDataCount(mutationCountsFiltered, "6")); // patient 302 + assertEquals(1, findClinicaDataCount(mutationCountsFiltered, "4")); // patient 303 + assertEquals(1, findClinicaDataCount(mutationCountsFiltered, "2")); // patient 306 + + // no patients/samples with NA + assertEquals(0, findClinicaDataCount(mutationCountsFiltered, "NA")); + } + + @Test + public void getMutationCountsFilteredByAgeWithOpenEndValues() { + StudyViewFilter studyViewFilter = new StudyViewFilter(); + studyViewFilter.setStudyIds(List.of(STUDY_GENIE_PUB)); + + // filter patients with age greater than 80 + // (there are 4 patients within this range, which are 317, 318, 319, 304, and 305) + ClinicalDataFilter filter = buildClinicalDataFilter("age", 80, null); + studyViewFilter.setClinicalDataFilters(List.of(filter)); + + var clinicalDataCountItems = + mapper.getClinicalDataCounts( + StudyViewFilterFactory.make(studyViewFilter, null, studyViewFilter.getStudyIds(), null), + List.of("mutation_count"), + Collections.emptyList()); + + var mutationsCountsOptional = + clinicalDataCountItems.stream() + .filter(c -> c.getAttributeId().equals("mutation_count")) + .findFirst(); + + assertTrue(mutationsCountsOptional.isPresent()); + var mutationCountsFiltered = mutationsCountsOptional.get().getCounts(); + + assertEquals(3, mutationCountsFiltered.size()); + assertEquals(1, findClinicaDataCount(mutationCountsFiltered, "4")); // patient 304 + assertEquals(1, findClinicaDataCount(mutationCountsFiltered, "2")); // patient 305 + + // patients/samples with NA data: 317, 318, and 319 + assertEquals(3, findClinicaDataCount(mutationCountsFiltered, "NA")); + } + + private ClinicalDataFilter buildClinicalDataFilter( + String attributeId, Integer start, Integer end) { + DataFilterValue value = new DataFilterValue(); + if (start != null) { + value.setStart(BigDecimal.valueOf(start)); + } + if (end != null) { + value.setEnd(BigDecimal.valueOf(end)); + } + + ClinicalDataFilter filter = new ClinicalDataFilter(); + filter.setAttributeId(attributeId); + filter.setValues(List.of(value)); + + return filter; + } + + private int findClinicaDataCount(List counts, String attrValue) { + var count = counts.stream().filter(c -> c.getValue().equals(attrValue)).findAny().orElse(null); + + return count == null ? 0 : count.getCount(); + } +} diff --git a/src/test/java/org/cbioportal/infrastructure/repository/clickhouse/clinical_event/ClickhouseClinicalEventMapperTest.java b/src/test/java/org/cbioportal/infrastructure/repository/clickhouse/clinical_event/ClickhouseClinicalEventMapperTest.java new file mode 100644 index 00000000000..7f94a393f78 --- /dev/null +++ b/src/test/java/org/cbioportal/infrastructure/repository/clickhouse/clinical_event/ClickhouseClinicalEventMapperTest.java @@ -0,0 +1,74 @@ +package org.cbioportal.infrastructure.repository.clickhouse.clinical_event; + +import static org.junit.Assert.*; + +import java.util.List; +import org.cbioportal.domain.studyview.StudyViewFilterContext; +import org.cbioportal.domain.studyview.StudyViewFilterFactory; +import org.cbioportal.infrastructure.repository.clickhouse.AbstractTestcontainers; +import org.cbioportal.infrastructure.repository.clickhouse.config.MyBatisConfig; +import org.cbioportal.legacy.web.parameter.DataFilter; +import org.cbioportal.legacy.web.parameter.DataFilterValue; +import org.cbioportal.legacy.web.parameter.StudyViewFilter; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase; +import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; +import org.springframework.context.annotation.Import; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@Import(MyBatisConfig.class) +@DataJpaTest +@DirtiesContext +@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE) +@ContextConfiguration(initializers = AbstractTestcontainers.Initializer.class) +public class ClickhouseClinicalEventMapperTest { + private static final String STUDY_TCGA_PUB = "study_tcga_pub"; + + @Autowired private ClickhouseClinicalEventMapper mapper; + + @Test + public void getClinicalEventTypeCounts() { + StudyViewFilter studyViewFilter = new StudyViewFilter(); + studyViewFilter.setStudyIds(List.of(STUDY_TCGA_PUB)); + + StudyViewFilterContext studyViewFilterContext = + StudyViewFilterFactory.make(studyViewFilter, null, studyViewFilter.getStudyIds(), null); + + var clinicalEventTypeCounts = mapper.getClinicalEventTypeCounts(studyViewFilterContext); + + assertEquals(4, clinicalEventTypeCounts.size()); + + var clinicalEventTypeCountOptional = + clinicalEventTypeCounts.stream() + .filter(ce -> ce.getEventType().equals("Treatment")) + .findFirst(); + + assertTrue(clinicalEventTypeCountOptional.isPresent()); + assertEquals(1, clinicalEventTypeCountOptional.get().getCount().intValue()); + + DataFilter dataFilter = new DataFilter(); + DataFilterValue dataFilterValue = new DataFilterValue(); + dataFilterValue.setValue("Treatment"); + dataFilter.setValues(List.of(dataFilterValue)); + studyViewFilter.setClinicalEventFilters(List.of(dataFilter)); + + clinicalEventTypeCounts = + mapper.getClinicalEventTypeCounts( + StudyViewFilterFactory.make( + studyViewFilter, null, studyViewFilter.getStudyIds(), null)); + + assertEquals(3, clinicalEventTypeCounts.size()); + + clinicalEventTypeCountOptional = + clinicalEventTypeCounts.stream() + .filter(ce -> ce.getEventType().equals("status")) + .findFirst(); + + assertFalse(clinicalEventTypeCountOptional.isPresent()); + } +} diff --git a/src/test/java/org/cbioportal/infrastructure/repository/clickhouse/config/MyBatisConfig.java b/src/test/java/org/cbioportal/infrastructure/repository/clickhouse/config/MyBatisConfig.java new file mode 100644 index 00000000000..f63bc4f873a --- /dev/null +++ b/src/test/java/org/cbioportal/infrastructure/repository/clickhouse/config/MyBatisConfig.java @@ -0,0 +1,39 @@ +package org.cbioportal.infrastructure.repository.clickhouse.config; + +import java.io.IOException; +import javax.sql.DataSource; +import org.mybatis.spring.SqlSessionFactoryBean; +import org.mybatis.spring.annotation.MapperScan; +import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.boot.test.context.TestConfiguration; +import org.springframework.context.ApplicationContext; +import org.springframework.context.annotation.Bean; +import org.springframework.core.io.ResourceLoader; + +@TestConfiguration +@MapperScan(value = "org.cbioportal.infrastructure.repository.clickhouse") +public class MyBatisConfig { + + @Bean + @ConfigurationProperties("spring.datasource.clickhouse") + public DataSourceProperties clickhouseDatSourceProperties() { + return new DataSourceProperties(); + } + + @Bean + public DataSource dataSource() { + return clickhouseDatSourceProperties().initializeDataSourceBuilder().build(); + } + + @Bean + public SqlSessionFactoryBean sqlColumnarSessionFactory( + ResourceLoader resourceLoader, DataSource dataSource, ApplicationContext context) + throws IOException { + SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean(); + sessionFactory.setDataSource(dataSource); + sessionFactory.addMapperLocations( + context.getResources("classpath:mappers/clickhouse/**/*.xml")); + return sessionFactory; + } +} diff --git a/src/test/java/org/cbioportal/infrastructure/repository/clickhouse/generic_assay/ClickhouseGenericAssayMapperTest.java b/src/test/java/org/cbioportal/infrastructure/repository/clickhouse/generic_assay/ClickhouseGenericAssayMapperTest.java new file mode 100644 index 00000000000..a7f55f2d431 --- /dev/null +++ b/src/test/java/org/cbioportal/infrastructure/repository/clickhouse/generic_assay/ClickhouseGenericAssayMapperTest.java @@ -0,0 +1,90 @@ +package org.cbioportal.infrastructure.repository.clickhouse.generic_assay; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.List; +import org.cbioportal.domain.studyview.StudyViewFilterFactory; +import org.cbioportal.infrastructure.repository.clickhouse.AbstractTestcontainers; +import org.cbioportal.infrastructure.repository.clickhouse.config.MyBatisConfig; +import org.cbioportal.legacy.model.GenericAssayDataCount; +import org.cbioportal.legacy.model.GenericAssayDataCountItem; +import org.cbioportal.legacy.web.parameter.GenericAssayDataFilter; +import org.cbioportal.legacy.web.parameter.StudyViewFilter; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase; +import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; +import org.springframework.context.annotation.Import; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@Import(MyBatisConfig.class) +@DataJpaTest +@DirtiesContext +@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE) +@ContextConfiguration(initializers = AbstractTestcontainers.Initializer.class) +public class ClickhouseGenericAssayMapperTest { + + private static final String ACC_TCGA = "acc_tcga"; + private static final String STUDY_GENIE_PUB = "study_genie_pub"; + + @Autowired private ClickhouseGenericAssayMapper mapper; + + @Test + public void getSampleCategoricalGenericAssayDataCounts() { + StudyViewFilter studyViewFilter = new StudyViewFilter(); + studyViewFilter.setStudyIds(List.of(ACC_TCGA)); + + GenericAssayDataFilter genericAssayDataFilter = + new GenericAssayDataFilter("1p_status", "armlevel_cna"); + List actualCounts = + mapper.getGenericAssayDataCounts( + StudyViewFilterFactory.make(studyViewFilter, null, studyViewFilter.getStudyIds(), null), + List.of(genericAssayDataFilter)); + + List expectedCounts = + List.of( + new GenericAssayDataCountItem( + "1p_status", + List.of( + new GenericAssayDataCount("Loss", 1), + new GenericAssayDataCount("Gain", 1), + new GenericAssayDataCount("Unchanged", 1), + new GenericAssayDataCount("NA", 1)))); + + assertThat(actualCounts) + .usingRecursiveComparison() + .ignoringCollectionOrder() + .isEqualTo(expectedCounts); + } + + @Test + public void getPatientCategoricalGenericAssayDataCounts() { + StudyViewFilter studyViewFilter = new StudyViewFilter(); + studyViewFilter.setStudyIds(List.of(STUDY_GENIE_PUB)); + + GenericAssayDataFilter genericAssayDataFilter = + new GenericAssayDataFilter("DMETS_DX_ADRENAL", "distant_mets"); + List actualCounts = + mapper.getGenericAssayDataCounts( + StudyViewFilterFactory.make(studyViewFilter, null, studyViewFilter.getStudyIds(), null), + List.of(genericAssayDataFilter)); + + List expectedCounts = + List.of( + new GenericAssayDataCountItem( + "DMETS_DX_ADRENAL", + List.of( + new GenericAssayDataCount("No", 9), + new GenericAssayDataCount("Yes", 1), + new GenericAssayDataCount("NA", 14)))); + + assertThat(actualCounts) + .usingRecursiveComparison() + .ignoringCollectionOrder() + .isEqualTo(expectedCounts); + } +} diff --git a/src/test/java/org/cbioportal/infrastructure/repository/clickhouse/genomic_data/ClickhouseGenomicDataMapperTest.java b/src/test/java/org/cbioportal/infrastructure/repository/clickhouse/genomic_data/ClickhouseGenomicDataMapperTest.java new file mode 100644 index 00000000000..9fb9893de8f --- /dev/null +++ b/src/test/java/org/cbioportal/infrastructure/repository/clickhouse/genomic_data/ClickhouseGenomicDataMapperTest.java @@ -0,0 +1,311 @@ +package org.cbioportal.infrastructure.repository.clickhouse.genomic_data; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.Assert.assertEquals; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import org.cbioportal.domain.studyview.StudyViewFilterFactory; +import org.cbioportal.infrastructure.repository.clickhouse.AbstractTestcontainers; +import org.cbioportal.infrastructure.repository.clickhouse.config.MyBatisConfig; +import org.cbioportal.legacy.model.ClinicalDataCount; +import org.cbioportal.legacy.model.GenomicDataCount; +import org.cbioportal.legacy.model.GenomicDataCountItem; +import org.cbioportal.legacy.web.parameter.DataFilterValue; +import org.cbioportal.legacy.web.parameter.GenomicDataBinFilter; +import org.cbioportal.legacy.web.parameter.GenomicDataFilter; +import org.cbioportal.legacy.web.parameter.StudyViewFilter; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase; +import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; +import org.springframework.context.annotation.Import; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@Import(MyBatisConfig.class) +@DataJpaTest +@DirtiesContext +@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE) +@ContextConfiguration(initializers = AbstractTestcontainers.Initializer.class) +public class ClickhouseGenomicDataMapperTest { + private static final String STUDY_TCGA_PUB = "study_tcga_pub"; + private static final String STUDY_ACC_TCGA = "acc_tcga"; + + @Autowired private ClickhouseGenomicDataMapper mapper; + + @Test + public void getCNACounts() { + StudyViewFilter studyViewFilter = new StudyViewFilter(); + studyViewFilter.setStudyIds(List.of(STUDY_TCGA_PUB)); + + GenomicDataFilter genomicDataFilterCNA = new GenomicDataFilter("AKT1", "cna"); + List actualCountsCNA = + mapper.getCNACounts( + StudyViewFilterFactory.make(studyViewFilter, null, studyViewFilter.getStudyIds(), null), + List.of(genomicDataFilterCNA)); + List expectedCountsCNA = + List.of( + new GenomicDataCountItem( + "AKT1", + "cna", + List.of( + new GenomicDataCount("Homozygously deleted", "-2", 2), + new GenomicDataCount("Heterozygously deleted", "-1", 2), + new GenomicDataCount("Diploid", "0", 2), + new GenomicDataCount("Gained", "1", 2), + new GenomicDataCount("Amplified", "2", 2), + new GenomicDataCount("NA", "NA", 5)))); + assertThat(actualCountsCNA) + .usingRecursiveComparison() + .ignoringCollectionOrder() + .isEqualTo(expectedCountsCNA); + + GenomicDataFilter genomicDataFilterGISTIC = new GenomicDataFilter("AKT1", "gistic"); + List actualCountsGISTIC = + mapper.getCNACounts( + StudyViewFilterFactory.make(studyViewFilter, null, studyViewFilter.getStudyIds(), null), + List.of(genomicDataFilterGISTIC)); + List expectedCountsGISTIC = + List.of( + new GenomicDataCountItem( + "AKT1", + "gistic", + List.of( + new GenomicDataCount("Homozygously deleted", "-2", 2), + new GenomicDataCount("Heterozygously deleted", "-1", 3), + new GenomicDataCount("Diploid", "0", 3), + new GenomicDataCount("Gained", "1", 3), + new GenomicDataCount("Amplified", "2", 3), + new GenomicDataCount("NA", "NA", 1)))); + assertThat(actualCountsGISTIC) + .usingRecursiveComparison() + .ignoringCollectionOrder() + .isEqualTo(expectedCountsGISTIC); + } + + @Test + public void getMutationCounts() { + StudyViewFilter studyViewFilter = new StudyViewFilter(); + studyViewFilter.setStudyIds(List.of(STUDY_TCGA_PUB)); + + GenomicDataFilter genomicDataFilterMutation = new GenomicDataFilter("AKT1", "cna"); + Map actualMutationCounts = + mapper.getMutationCounts( + StudyViewFilterFactory.make(studyViewFilter, null, studyViewFilter.getStudyIds(), null), + genomicDataFilterMutation); + Map expectedMutationCounts = new HashMap<>(); + expectedMutationCounts.put("mutatedCount", 2); + expectedMutationCounts.put("notMutatedCount", 8); + expectedMutationCounts.put("notProfiledCount", 5); + assertThat(actualMutationCounts) + .usingRecursiveComparison() + .ignoringCollectionOrder() + .isEqualTo(expectedMutationCounts); + } + + @Test + public void getMutationCountsByType() { + StudyViewFilter studyViewFilter = new StudyViewFilter(); + studyViewFilter.setStudyIds(List.of(STUDY_TCGA_PUB)); + + GenomicDataFilter genomicDataFilterMutation = new GenomicDataFilter("AKT1", "mutation"); + List actualMutationCountsByType = + mapper.getMutationCountsByType( + StudyViewFilterFactory.make(studyViewFilter, null, studyViewFilter.getStudyIds(), null), + List.of(genomicDataFilterMutation)); + List expectedMutationCountsByType = + List.of( + new GenomicDataCountItem( + "AKT1", + "mutations", + List.of( + new GenomicDataCount("nonsense mutation", "nonsense_mutation", 2, 1), + new GenomicDataCount("missense mutation", "missense_mutation", 1, 1)))); + assertThat(actualMutationCountsByType) + .usingRecursiveComparison() + .ignoringCollectionOrder() + .isEqualTo(expectedMutationCountsByType); + } + + @Test + public void getProteinExpressionCounts() { + // Testing combined study missing samples when one lacks a relevant genomic profile + StudyViewFilter studyViewFilter = new StudyViewFilter(); + studyViewFilter.setStudyIds(List.of(STUDY_TCGA_PUB, STUDY_ACC_TCGA)); + + GenomicDataBinFilter genomicDataBinFilterRPPA = new GenomicDataBinFilter(); + genomicDataBinFilterRPPA.setHugoGeneSymbol("AKT1"); + genomicDataBinFilterRPPA.setProfileType("rppa"); + + List actualRPPACounts1 = + mapper.getGenomicDataBinCounts( + StudyViewFilterFactory.make(studyViewFilter, null, studyViewFilter.getStudyIds(), null), + List.of(genomicDataBinFilterRPPA)); + + ClinicalDataCount expectedRPPACount1 = new ClinicalDataCount(); + expectedRPPACount1.setAttributeId("AKT1rppa"); + expectedRPPACount1.setValue("0.7360"); + expectedRPPACount1.setCount(1); + ClinicalDataCount expectedRPPACount2 = new ClinicalDataCount(); + expectedRPPACount2.setAttributeId("AKT1rppa"); + expectedRPPACount2.setValue("-0.8097"); + expectedRPPACount2.setCount(1); + ClinicalDataCount expectedRPPACount3 = new ClinicalDataCount(); + expectedRPPACount3.setAttributeId("AKT1rppa"); + expectedRPPACount3.setValue("-0.1260"); + expectedRPPACount3.setCount(1); + ClinicalDataCount expectedRPPACountNA = new ClinicalDataCount(); + expectedRPPACountNA.setAttributeId("AKT1rppa"); + expectedRPPACountNA.setValue("NA"); + expectedRPPACountNA.setCount(16); + + List expectedRPPACounts1 = + List.of(expectedRPPACount1, expectedRPPACount2, expectedRPPACount3, expectedRPPACountNA); + assertThat(actualRPPACounts1) + .usingRecursiveComparison() + .ignoringCollectionOrder() + .isEqualTo(expectedRPPACounts1); + + // Testing NA filtering on combined study missing samples when one lacks a relevant genomic + // profile + // Make genomic data filter to put in study view filter + GenomicDataFilter genomicDataFilterRPPA = new GenomicDataFilter("AKT1", "rppa"); + DataFilterValue dataFilterValue = new DataFilterValue(); + dataFilterValue.setValue("NA"); + genomicDataFilterRPPA.setValues(List.of(dataFilterValue)); + studyViewFilter.setGenomicDataFilters(List.of(genomicDataFilterRPPA)); + + List actualRPPACounts2 = + mapper.getGenomicDataBinCounts( + StudyViewFilterFactory.make(studyViewFilter, null, studyViewFilter.getStudyIds(), null), + List.of(genomicDataBinFilterRPPA)); + + ClinicalDataCount expectedRPPACount = new ClinicalDataCount(); + expectedRPPACount.setAttributeId("AKT1rppa"); + expectedRPPACount.setValue("NA"); + expectedRPPACount.setCount(16); + + List expectedRPPACounts2 = List.of(expectedRPPACount); + assertThat(actualRPPACounts2) + .usingRecursiveComparison() + .ignoringCollectionOrder() + .isEqualTo(expectedRPPACounts2); + } + + @Test + public void getMolecularProfileCounts() { + StudyViewFilter studyViewFilter = new StudyViewFilter(); + studyViewFilter.setStudyIds(List.of(STUDY_TCGA_PUB)); + + var profiles = new ArrayList(Arrays.asList("mutations")); + var profileGroups = new ArrayList>(Arrays.asList(profiles)); + + studyViewFilter.setGenomicProfiles(profileGroups); + + var molecularProfileCounts = + mapper.getMolecularProfileSampleCounts( + StudyViewFilterFactory.make( + studyViewFilter, null, studyViewFilter.getStudyIds(), null)); + + var size = + molecularProfileCounts.stream() + .filter(gc -> gc.getValue().equals("mutations")) + .findFirst() + .get() + .getCount() + .intValue(); + assertEquals(11, size); + } + + @Test + public void getMolecularProfileCountsMultipleStudies() { + StudyViewFilter studyViewFilter = new StudyViewFilter(); + studyViewFilter.setStudyIds(List.of(STUDY_TCGA_PUB, STUDY_ACC_TCGA)); + + var profiles = new ArrayList(Arrays.asList("mutations")); + var profileGroups = new ArrayList>(Arrays.asList(profiles)); + + studyViewFilter.setGenomicProfiles(profileGroups); + + var molecularProfileCounts = + mapper.getMolecularProfileSampleCounts( + StudyViewFilterFactory.make( + studyViewFilter, null, studyViewFilter.getStudyIds(), null)); + + var size = + molecularProfileCounts.stream() + .filter(gc -> gc.getValue().equals("mutations")) + .findFirst() + .get() + .getCount() + .intValue(); + assertEquals(11, size); + } + + @Test + public void getMolecularProfileCountsMultipleProfilesUnion() { + StudyViewFilter studyViewFilter = new StudyViewFilter(); + studyViewFilter.setStudyIds(List.of(STUDY_TCGA_PUB)); + + var profiles = new ArrayList(Arrays.asList("mutations", "mrna")); + var profileGroups = new ArrayList>(Arrays.asList(profiles)); + + studyViewFilter.setGenomicProfiles(profileGroups); + + var molecularProfileCounts = + mapper.getMolecularProfileSampleCounts( + StudyViewFilterFactory.make( + studyViewFilter, null, studyViewFilter.getStudyIds(), null)); + + var sizeMutations = + molecularProfileCounts.stream() + .filter(gc -> gc.getValue().equals("mutations")) + .findFirst() + .get() + .getCount() + .intValue(); + assertEquals(11, sizeMutations); + + var sizeMrna = + molecularProfileCounts.stream() + .filter(gc -> gc.getValue().equals("mrna")) + .findFirst() + .get() + .getCount() + .intValue(); + assertEquals(9, sizeMrna); + } + + @Test + public void getMolecularProfileCountsMultipleProfilesIntersect() { + StudyViewFilter studyViewFilter = new StudyViewFilter(); + studyViewFilter.setStudyIds(List.of(STUDY_TCGA_PUB)); + + var profile1 = new ArrayList(Arrays.asList("mutations")); + var profile2 = new ArrayList(Arrays.asList("mrna")); + var profileGroups = new ArrayList>(Arrays.asList(profile1, profile2)); + + studyViewFilter.setGenomicProfiles(profileGroups); + + var molecularProfileCounts = + mapper.getMolecularProfileSampleCounts( + StudyViewFilterFactory.make( + studyViewFilter, null, studyViewFilter.getStudyIds(), null)); + + var sizeMutations = + molecularProfileCounts.stream() + .filter(gc -> gc.getValue().equals("mutations")) + .findFirst() + .get() + .getCount() + .intValue(); + assertEquals(10, sizeMutations); + } +} diff --git a/src/test/java/org/cbioportal/infrastructure/repository/clickhouse/patient/ClickhousePatientMapperTest.java b/src/test/java/org/cbioportal/infrastructure/repository/clickhouse/patient/ClickhousePatientMapperTest.java new file mode 100644 index 00000000000..16d29a23799 --- /dev/null +++ b/src/test/java/org/cbioportal/infrastructure/repository/clickhouse/patient/ClickhousePatientMapperTest.java @@ -0,0 +1,148 @@ +package org.cbioportal.infrastructure.repository.clickhouse.patient; + +import static org.junit.Assert.*; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import org.cbioportal.domain.studyview.StudyViewFilterFactory; +import org.cbioportal.infrastructure.repository.clickhouse.AbstractTestcontainers; +import org.cbioportal.infrastructure.repository.clickhouse.config.MyBatisConfig; +import org.cbioportal.legacy.service.util.StudyViewColumnarServiceUtil; +import org.cbioportal.legacy.web.parameter.StudyViewFilter; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase; +import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; +import org.springframework.context.annotation.Import; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@Import(MyBatisConfig.class) +@DataJpaTest +@DirtiesContext +@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE) +@ContextConfiguration(initializers = AbstractTestcontainers.Initializer.class) +public class ClickhousePatientMapperTest { + + private static final String STUDY_TCGA_PUB = "study_tcga_pub"; + private static final String STUDY_ACC_TCGA = "acc_tcga"; + + @Autowired private ClickhousePatientMapper mapper; + + @Test + public void getMolecularProfileCounts() { + StudyViewFilter studyViewFilter = new StudyViewFilter(); + studyViewFilter.setStudyIds(List.of(STUDY_TCGA_PUB)); + + var caseList = new ArrayList(Arrays.asList("pub_cna")); + var caseListGroups = new ArrayList(Arrays.asList(caseList)); + + studyViewFilter.setCaseLists(caseListGroups); + + var sampleListCounts = + mapper.getCaseListDataCounts( + StudyViewFilterFactory.make( + studyViewFilter, null, studyViewFilter.getStudyIds(), null)); + + var size = + sampleListCounts.stream() + .filter(gc -> gc.getValue().equals("mrna")) + .findFirst() + .get() + .getCount() + .intValue(); + assertEquals(7, size); + } + + @Test + public void getMolecularProfileCountsMultipleListsOr() { + StudyViewFilter studyViewFilter = new StudyViewFilter(); + studyViewFilter.setStudyIds(List.of(STUDY_TCGA_PUB)); + + var caseList = new ArrayList(Arrays.asList("mrna", "pub_cna")); + var caseListGroups = new ArrayList(Arrays.asList(caseList)); + + studyViewFilter.setCaseLists(caseListGroups); + + var sampleListCounts = + mapper.getCaseListDataCounts( + StudyViewFilterFactory.make( + studyViewFilter, null, studyViewFilter.getStudyIds(), null)); + + var size = + sampleListCounts.stream() + .filter(gc -> gc.getValue().equals("mrna")) + .findFirst() + .get() + .getCount() + .intValue(); + assertEquals(8, size); + } + + @Test + public void getMolecularProfileCountsMultipleListsAnd() { + StudyViewFilter studyViewFilter = new StudyViewFilter(); + studyViewFilter.setStudyIds(List.of(STUDY_TCGA_PUB)); + + var caseList1 = new ArrayList(Arrays.asList("mrna")); + var caseList2 = new ArrayList(Arrays.asList("pub_cna")); + var caseListGroups = new ArrayList(Arrays.asList(caseList1, caseList2)); + + studyViewFilter.setCaseLists(caseListGroups); + + var sampleListCounts = + mapper.getCaseListDataCounts( + StudyViewFilterFactory.make( + studyViewFilter, null, studyViewFilter.getStudyIds(), null)); + + var size = + sampleListCounts.stream() + .filter(gc -> gc.getValue().equals("mrna")) + .findFirst() + .get() + .getCount() + .intValue(); + assertEquals(7, size); + } + + @Test + public void getMolecularProfileCountsAcrossStudies() { + StudyViewFilter studyViewFilter = new StudyViewFilter(); + studyViewFilter.setStudyIds(List.of(STUDY_TCGA_PUB, STUDY_ACC_TCGA)); + + var caseList1 = new ArrayList(Arrays.asList("all")); + var caseListGroups = new ArrayList(Arrays.asList(caseList1)); + + studyViewFilter.setCaseLists(caseListGroups); + + var unMergedCounts = + mapper.getCaseListDataCounts( + StudyViewFilterFactory.make( + studyViewFilter, null, studyViewFilter.getStudyIds(), null)); + + var caseListCountsMerged = StudyViewColumnarServiceUtil.mergeCaseListCounts(unMergedCounts); + + var sizeUnmerged = + unMergedCounts.stream() + .filter(gc -> gc.getValue().equals("all")) + .findFirst() + .get() + .getCount() + .intValue(); + assertEquals(14, sizeUnmerged); + + // now we've combined the "all" from the two studies + var sizeMerged = + caseListCountsMerged.stream() + .filter(gc -> gc.getValue().equals("all")) + .findFirst() + .get() + .getCount() + .intValue(); + assertEquals(15, sizeMerged); + } +} diff --git a/src/test/java/org/cbioportal/infrastructure/repository/clickhouse/sample/ClickhouseSampleMapperTest.java b/src/test/java/org/cbioportal/infrastructure/repository/clickhouse/sample/ClickhouseSampleMapperTest.java new file mode 100644 index 00000000000..38f3aeaa92b --- /dev/null +++ b/src/test/java/org/cbioportal/infrastructure/repository/clickhouse/sample/ClickhouseSampleMapperTest.java @@ -0,0 +1,1066 @@ +package org.cbioportal.infrastructure.repository.clickhouse.sample; + +import static org.junit.Assert.*; + +import java.math.BigDecimal; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import org.cbioportal.domain.sample.Sample; +import org.cbioportal.domain.sample.SampleType; +import org.cbioportal.domain.studyview.StudyViewFilterFactory; +import org.cbioportal.infrastructure.repository.clickhouse.AbstractTestcontainers; +import org.cbioportal.infrastructure.repository.clickhouse.config.MyBatisConfig; +import org.cbioportal.legacy.web.parameter.ClinicalDataFilter; +import org.cbioportal.legacy.web.parameter.CustomSampleIdentifier; +import org.cbioportal.legacy.web.parameter.DataFilterValue; +import org.cbioportal.legacy.web.parameter.StudyViewFilter; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase; +import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; +import org.springframework.context.annotation.Import; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@Import(MyBatisConfig.class) +@DataJpaTest +@DirtiesContext +@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE) +@ContextConfiguration(initializers = AbstractTestcontainers.Initializer.class) +public class ClickhouseSampleMapperTest { + private static final String STUDY_TCGA_PUB = "study_tcga_pub"; + private static final String STUDY_ACC_TCGA = "acc_tcga"; + private static final String STUDY_GENIE_PUB = "study_genie_pub"; + + @Autowired private ClickhouseSampleMapper mapper; + + @Test + public void getFilteredSamples() { + StudyViewFilter studyViewFilter = new StudyViewFilter(); + studyViewFilter.setStudyIds(Arrays.asList(STUDY_TCGA_PUB, STUDY_ACC_TCGA)); + var filteredSamples = + mapper.getFilteredSamples( + StudyViewFilterFactory.make( + studyViewFilter, null, studyViewFilter.getStudyIds(), null)); + assertEquals(19, filteredSamples.size()); + + ClinicalDataFilter customDataFilter = new ClinicalDataFilter(); + customDataFilter.setAttributeId("123"); + DataFilterValue value = new DataFilterValue(); + customDataFilter.setValues(List.of(value)); + studyViewFilter.setCustomDataFilters(List.of(customDataFilter)); + var filteredSamples1 = + mapper.getFilteredSamples( + StudyViewFilterFactory.make( + studyViewFilter, List.of(), studyViewFilter.getStudyIds(), null)); + assertEquals(0, filteredSamples1.size()); + + CustomSampleIdentifier customSampleIdentifier = new CustomSampleIdentifier(); + customSampleIdentifier.setStudyId("acc_tcga"); + customSampleIdentifier.setSampleId("tcga-a1-a0sb-01"); + var filteredSamples2 = + mapper.getFilteredSamples( + StudyViewFilterFactory.make( + studyViewFilter, + List.of(customSampleIdentifier), + studyViewFilter.getStudyIds(), + null)); + assertEquals(1, filteredSamples2.size()); + } + + @Test + public void getSamplesFilteredByClinicalData() { + StudyViewFilter studyViewFilter = new StudyViewFilter(); + studyViewFilter.setStudyIds(Arrays.asList(STUDY_GENIE_PUB, STUDY_ACC_TCGA)); + + // samples of patients with AGE <= 20.0 + studyViewFilter.setClinicalDataFilters( + List.of(newClinicalDataFilter("age", List.of(newDataFilterValue(null, 20.0, null))))); + var filteredSamples1 = + mapper.getFilteredSamples( + StudyViewFilterFactory.make( + studyViewFilter, List.of(), studyViewFilter.getStudyIds(), null)); + assertEquals(4, filteredSamples1.size()); + + // samples of patients with AGE <= 20.0 or (80.0, 82.0] + studyViewFilter.setClinicalDataFilters( + List.of( + newClinicalDataFilter( + "age", + List.of( + newDataFilterValue(null, 20.0, null), newDataFilterValue(80.0, 82.0, null))))); + var filteredSamples2 = + mapper.getFilteredSamples( + StudyViewFilterFactory.make( + studyViewFilter, List.of(), studyViewFilter.getStudyIds(), null)); + assertEquals(6, filteredSamples2.size()); + + // samples of patients with UNKNOWN AGE + studyViewFilter.setClinicalDataFilters( + List.of(newClinicalDataFilter("age", List.of(newDataFilterValue(null, null, "Unknown"))))); + var filteredSamples3 = + mapper.getFilteredSamples( + StudyViewFilterFactory.make( + studyViewFilter, List.of(), studyViewFilter.getStudyIds(), null)); + assertEquals(1, filteredSamples3.size()); + + // samples of patients with AGE <= 20.0 or (80.0, 82.0] or UNKNOWN + // this is a mixed list of filters of both numerical and non-numerical values + studyViewFilter.setClinicalDataFilters( + List.of( + newClinicalDataFilter( + "age", + List.of( + newDataFilterValue(null, 20.0, null), + newDataFilterValue(80.0, 82.0, null), + newDataFilterValue(null, null, "unknown"))))); + var filteredSamples4 = + mapper.getFilteredSamples( + StudyViewFilterFactory.make( + studyViewFilter, List.of(), studyViewFilter.getStudyIds(), null)); + assertEquals(7, filteredSamples4.size()); + + // NA filter + studyViewFilter.setClinicalDataFilters( + List.of(newClinicalDataFilter("age", List.of(newDataFilterValue(null, null, "NA"))))); + var filteredSamples5 = + mapper.getFilteredSamples( + StudyViewFilterFactory.make( + studyViewFilter, List.of(), studyViewFilter.getStudyIds(), null)); + // 4 acc_tcga + 7 study_genie_pub samples with "NA" AGE data or no AGE data + assertEquals(11, filteredSamples5.size()); + + // NA + UNKNOWN + studyViewFilter.setClinicalDataFilters( + List.of( + newClinicalDataFilter( + "age", + List.of( + newDataFilterValue(null, null, "NA"), + newDataFilterValue(null, null, "UNKNOWN"))))); + var filteredSamples6 = + mapper.getFilteredSamples( + StudyViewFilterFactory.make( + studyViewFilter, List.of(), studyViewFilter.getStudyIds(), null)); + // 11 NA + 1 UNKNOWN + assertEquals(12, filteredSamples6.size()); + } + + @Test + public void getMetaSamples() { + var allAccSamplesMeta = + mapper.getMetaSamples(Collections.singletonList(STUDY_ACC_TCGA), null, null, null); + assertEquals(4, allAccSamplesMeta.getTotalCount().intValue()); + + var allTcgaPubSamplesMeta = + mapper.getMetaSamples(Collections.singletonList(STUDY_TCGA_PUB), null, null, null); + assertEquals(15, allTcgaPubSamplesMeta.getTotalCount().intValue()); + + var allSamplesMetaForAccAndTcga = + mapper.getMetaSamples(List.of(STUDY_ACC_TCGA, STUDY_TCGA_PUB), null, null, null); + assertEquals(19, allSamplesMetaForAccAndTcga.getTotalCount().intValue()); + + var tcgaPubSamplesMetaForPatientA1A0SB = + mapper.getMetaSamples( + Collections.singletonList(STUDY_TCGA_PUB), "tcga-a1-a0sb", null, null); + assertEquals(2, tcgaPubSamplesMetaForPatientA1A0SB.getTotalCount().intValue()); + + var specificSamplesMetaForAccAndTcga = + mapper.getMetaSamples( + List.of( + "invalid_study", + "invalid_study", + STUDY_ACC_TCGA, + STUDY_TCGA_PUB, + STUDY_TCGA_PUB, + "mismatching_study_id", + "mismatching_study_id"), + null, + List.of( + // invalid/unknown samples + "unknown", + "does_not_exist", + // samples from acc_tcga or study_tcga_pub + "tcga-a1-b0sq-01", + "tcga-a1-a0sq-01", + "tcga-a1-a0si-01", + // samples from study_genie_pub (should be filtered out because we didn't include + // this study) + "GENIE-TEST-302-01", + "GENIE-TEST-309-01"), + null); + assertEquals(3, specificSamplesMetaForAccAndTcga.getTotalCount().intValue()); + + var keywordFilteredSamplesMetaForAccAndTcgaAndGenie = + mapper.getMetaSamples( + List.of(STUDY_ACC_TCGA, STUDY_TCGA_PUB, STUDY_GENIE_PUB), null, null, "-02"); + assertEquals(4, keywordFilteredSamplesMetaForAccAndTcgaAndGenie.getTotalCount().intValue()); + } + + @Test + public void getMetaSamplesBySampleListIds() { + var studyTcgaPubAll = + mapper.getMetaSamplesBySampleListIds(Collections.singletonList("study_tcga_pub_all")); + assertEquals(14, studyTcgaPubAll.getTotalCount().intValue()); + + var studyTcgaPubAcgh = + mapper.getMetaSamplesBySampleListIds(Collections.singletonList("study_tcga_pub_acgh")); + assertEquals(14, studyTcgaPubAcgh.getTotalCount().intValue()); + + var studyTcgaPubCnaseq = + mapper.getMetaSamplesBySampleListIds(Collections.singletonList("study_tcga_pub_cnaseq")); + assertEquals(7, studyTcgaPubCnaseq.getTotalCount().intValue()); + + var studyTcgaPubComplete = + mapper.getMetaSamplesBySampleListIds(Collections.singletonList("study_tcga_pub_complete")); + assertEquals(7, studyTcgaPubComplete.getTotalCount().intValue()); + + var studyTcgaPubLog2cna = + mapper.getMetaSamplesBySampleListIds(Collections.singletonList("study_tcga_pub_log2cna")); + assertEquals(14, studyTcgaPubLog2cna.getTotalCount().intValue()); + + var studyTcgaPubMethylationHm27 = + mapper.getMetaSamplesBySampleListIds( + Collections.singletonList("study_tcga_pub_methylation_hm27")); + assertEquals(1, studyTcgaPubMethylationHm27.getTotalCount().intValue()); + + var studyTcgaPubMrna = + mapper.getMetaSamplesBySampleListIds(Collections.singletonList("study_tcga_pub_mrna")); + assertEquals(8, studyTcgaPubMrna.getTotalCount().intValue()); + + var studyTcgaPubSequenced = + mapper.getMetaSamplesBySampleListIds(Collections.singletonList("study_tcga_pub_sequenced")); + assertEquals(7, studyTcgaPubSequenced.getTotalCount().intValue()); + + var studyTcgaPubCna = + mapper.getMetaSamplesBySampleListIds(Collections.singletonList("study_tcga_pub_cna")); + assertEquals(7, studyTcgaPubCna.getTotalCount().intValue()); + + var studyTcgaPubRnaSeqV2Mrna = + mapper.getMetaSamplesBySampleListIds( + Collections.singletonList("study_tcga_pub_rna_seq_v2_mrna")); + assertEquals(7, studyTcgaPubRnaSeqV2Mrna.getTotalCount().intValue()); + + var studyTcgaPubMicrorna = + mapper.getMetaSamplesBySampleListIds(Collections.singletonList("study_tcga_pub_microrna")); + assertEquals(0, studyTcgaPubMicrorna.getTotalCount().intValue()); + + var studyTcgaPubRppa = + mapper.getMetaSamplesBySampleListIds(Collections.singletonList("study_tcga_pub_rppa")); + assertEquals(0, studyTcgaPubRppa.getTotalCount().intValue()); + + var studyTcgaPub3wayComplete = + mapper.getMetaSamplesBySampleListIds( + Collections.singletonList("study_tcga_pub_3way_complete")); + assertEquals(7, studyTcgaPub3wayComplete.getTotalCount().intValue()); + + var accTcgaAll = + mapper.getMetaSamplesBySampleListIds(Collections.singletonList("acc_tcga_all")); + assertEquals(1, accTcgaAll.getTotalCount().intValue()); + } + + @Test + public void getSamples() { + var allAccSamples = + mapper.getSamples( + Collections.singletonList(STUDY_ACC_TCGA), null, null, null, null, null, null, null); + assertAccTcgaSampleIds(allAccSamples); + assertNull(allAccSamples.getFirst().sampleType()); + + var allTcgaPubSamples = + mapper.getSamples( + Collections.singletonList(STUDY_TCGA_PUB), null, null, null, null, null, null, null); + assertTcgaPubSampleIds(allTcgaPubSamples); + assertNull(allTcgaPubSamples.getFirst().sampleType()); + + var allSamplesForAccAndTcga = + mapper.getSamples( + List.of(STUDY_ACC_TCGA, STUDY_TCGA_PUB), null, null, null, null, null, null, null); + assertMultiStudySampleIds(allSamplesForAccAndTcga); + assertNull(allSamplesForAccAndTcga.getFirst().sampleType()); + + var tcgaPubSamplesForPatientA1A0SB = + mapper.getSamples( + Collections.singletonList(STUDY_TCGA_PUB), + "tcga-a1-a0sb", + null, + null, + null, + null, + null, + null); + assertSampleIdsForPatientA1A0SB(tcgaPubSamplesForPatientA1A0SB); + assertNull(tcgaPubSamplesForPatientA1A0SB.getFirst().sampleType()); + + var keywordFilteredSamplesForAccAndTcgaAndGenie = + mapper.getSamples( + List.of(STUDY_ACC_TCGA, STUDY_TCGA_PUB, STUDY_GENIE_PUB), + null, + null, + "-02", + null, + null, + null, + null); + assertKeywordFilteredSampleIds(keywordFilteredSamplesForAccAndTcgaAndGenie); + assertNull(keywordFilteredSamplesForAccAndTcgaAndGenie.getFirst().sampleType()); + } + + @Test + public void getSamplesByStudyAndSampleIds() { + var userDefinedSamplesForAccAndTcga = + mapper.getSamples( + List.of( + "invalid_study", + "invalid_study", + STUDY_ACC_TCGA, + STUDY_TCGA_PUB, + STUDY_TCGA_PUB, + "mismatching_study_id", + "mismatching_study_id"), + null, + List.of( + // invalid/unknown samples + "unknown", + "does_not_exist", + // samples from acc_tcga or study_tcga_pub + "tcga-a1-b0sq-01", + "tcga-a1-a0sq-01", + "tcga-a1-a0si-01", + // samples from study_genie_pub (should be filtered out because we didn't include + // this study) + "GENIE-TEST-302-01", + "GENIE-TEST-309-01"), + null, + null, + null, + null, + null); + assertUserDefinedSampleIds(userDefinedSamplesForAccAndTcga); + assertNull(userDefinedSamplesForAccAndTcga.getFirst().sampleType()); + + var userDefinedSamplesForGenie = + mapper.getSamples( + Collections.singletonList(STUDY_GENIE_PUB), + null, + List.of( + // samples from study_genie_pub + "GENIE-TEST-302-01", + "GENIE-TEST-309-01", + // samples from acc_tcga or study_tcga_pub (should be filtered out because we didn't + // include this study) + "tcga-a1-b0sq-01", + "tcga-a1-a0sq-01", + "tcga-a1-a0si-01"), + null, + null, + null, + null, + null); + assertUserDefinedGenieSampleIds(userDefinedSamplesForGenie); + assertNull(userDefinedSamplesForGenie.getFirst().sampleType()); + } + + @Test + public void getSummarySamples() { + var allAccSamples = + mapper.getSummarySamples( + Collections.singletonList(STUDY_ACC_TCGA), null, null, null, null, null, null, null); + assertAccTcgaSamplesSummary(allAccSamples); + assertNull(allAccSamples.getFirst().sequenced()); + assertNull(allAccSamples.getFirst().copyNumberSegmentPresent()); + + var allTcgaPubSamples = + mapper.getSummarySamples( + Collections.singletonList(STUDY_TCGA_PUB), null, null, null, null, null, null, null); + assertTcgaPubSamplesSummary(allTcgaPubSamples); + assertNull(allTcgaPubSamples.getFirst().sequenced()); + assertNull(allTcgaPubSamples.getFirst().copyNumberSegmentPresent()); + + var allSamplesForAccAndTcga = + mapper.getSummarySamples( + List.of(STUDY_ACC_TCGA, STUDY_TCGA_PUB), null, null, null, null, null, null, null); + assertMultiStudySamplesSummary(allSamplesForAccAndTcga); + assertNull(allSamplesForAccAndTcga.getFirst().sequenced()); + assertNull(allSamplesForAccAndTcga.getFirst().copyNumberSegmentPresent()); + + var tcgaPubSamplesForPatientA1A0SB = + mapper.getSummarySamples( + Collections.singletonList(STUDY_TCGA_PUB), + "tcga-a1-a0sb", + null, + null, + null, + null, + null, + null); + assertSamplesSummaryForPatientA1A0SB(tcgaPubSamplesForPatientA1A0SB); + assertNull(tcgaPubSamplesForPatientA1A0SB.getFirst().sequenced()); + assertNull(tcgaPubSamplesForPatientA1A0SB.getFirst().copyNumberSegmentPresent()); + + var keywordFilteredSamplesForAccAndTcgaAndGenie = + mapper.getSummarySamples( + List.of(STUDY_ACC_TCGA, STUDY_TCGA_PUB, STUDY_GENIE_PUB), + null, + null, + "-02", + null, + null, + null, + null); + assertKeywordFilteredSamplesSummary(keywordFilteredSamplesForAccAndTcgaAndGenie); + assertNull(keywordFilteredSamplesForAccAndTcgaAndGenie.getFirst().sequenced()); + assertNull(keywordFilteredSamplesForAccAndTcgaAndGenie.getFirst().copyNumberSegmentPresent()); + } + + @Test + public void getSummarySamplesByStudyAndSampleIds() { + var userDefinedSamplesForAccAndTcga = + mapper.getSummarySamples( + List.of( + "invalid_study", + "invalid_study", + STUDY_ACC_TCGA, + STUDY_TCGA_PUB, + STUDY_TCGA_PUB, + "mismatching_study_id", + "mismatching_study_id"), + null, + List.of( + // invalid/unknown samples + "unknown", + "does_not_exist", + // samples from acc_tcga or study_tcga_pub + "tcga-a1-b0sq-01", + "tcga-a1-a0sq-01", + "tcga-a1-a0si-01", + // samples from study_genie_pub (should be filtered out because we didn't include + // this study) + "GENIE-TEST-302-01", + "GENIE-TEST-309-01"), + null, + null, + null, + null, + null); + assertUserDefinedSamplesSummary(userDefinedSamplesForAccAndTcga); + assertNull(userDefinedSamplesForAccAndTcga.getFirst().sequenced()); + assertNull(userDefinedSamplesForAccAndTcga.getFirst().copyNumberSegmentPresent()); + + var userDefinedSamplesForGenie = + mapper.getSummarySamples( + Collections.singletonList(STUDY_GENIE_PUB), + null, + List.of( + // samples from study_genie_pub + "GENIE-TEST-302-01", + "GENIE-TEST-309-01", + // samples from acc_tcga or study_tcga_pub (should be filtered out because we didn't + // include this study) + "tcga-a1-b0sq-01", + "tcga-a1-a0sq-01", + "tcga-a1-a0si-01"), + null, + null, + null, + null, + null); + assertUserDefinedGenieSamplesSummary(userDefinedSamplesForGenie); + assertNull(userDefinedSamplesForGenie.getFirst().sequenced()); + assertNull(userDefinedSamplesForGenie.getFirst().copyNumberSegmentPresent()); + } + + @Test + public void getDetailedSamples() { + var allAccSamples = + mapper.getDetailedSamples( + Collections.singletonList(STUDY_ACC_TCGA), null, null, null, null, null, null, null); + assertAccTcgaSamplesDetailed(allAccSamples); + + var allTcgaPubSamples = + mapper.getDetailedSamples( + Collections.singletonList(STUDY_TCGA_PUB), null, null, null, null, null, null, null); + assertTcgaPubSamplesDetailed(allTcgaPubSamples); + + var allSamplesForAccAndTcga = + mapper.getDetailedSamples( + List.of(STUDY_ACC_TCGA, STUDY_TCGA_PUB), null, null, null, null, null, null, null); + assertMultiStudySamplesDetailed(allSamplesForAccAndTcga); + + var tcgaPubSamplesForPatientA1A0SB = + mapper.getDetailedSamples( + Collections.singletonList(STUDY_TCGA_PUB), + "tcga-a1-a0sb", + null, + null, + null, + null, + null, + null); + assertSamplesDetailedForPatientA1A0SB(tcgaPubSamplesForPatientA1A0SB); + + var keywordFilteredSamplesForAccAndTcgaAndGenie = + mapper.getDetailedSamples( + List.of(STUDY_ACC_TCGA, STUDY_TCGA_PUB, STUDY_GENIE_PUB), + null, + null, + "-02", + null, + null, + null, + null); + assertKeywordFilteredSamplesDetailed(keywordFilteredSamplesForAccAndTcgaAndGenie); + } + + @Test + public void getDetailedSamplesByStudyAndSampleIds() { + var userDefinedSamplesForAccAndTcga = + mapper.getDetailedSamples( + List.of( + "invalid_study", + "invalid_study", + STUDY_ACC_TCGA, + STUDY_TCGA_PUB, + STUDY_TCGA_PUB, + "mismatching_study_id", + "mismatching_study_id"), + null, + List.of( + // invalid/unknown samples + "unknown", + "does_not_exist", + // samples from acc_tcga or study_tcga_pub + "tcga-a1-b0sq-01", + "tcga-a1-a0sq-01", + "tcga-a1-a0si-01", + // samples from study_genie_pub (should be filtered out because we didn't include + // this study) + "GENIE-TEST-302-01", + "GENIE-TEST-309-01"), + null, + null, + null, + null, + null); + assertUserDefinedSamplesDetailed(userDefinedSamplesForAccAndTcga); + + var userDefinedSamplesForGenie = + mapper.getDetailedSamples( + Collections.singletonList(STUDY_GENIE_PUB), + null, + List.of( + // samples from study_genie_pub + "GENIE-TEST-302-01", + "GENIE-TEST-309-01", + // samples from acc_tcga or study_tcga_pub (should be filtered out because we didn't + // include this study) + "tcga-a1-b0sq-01", + "tcga-a1-a0sq-01", + "tcga-a1-a0si-01"), + null, + null, + null, + null, + null); + assertUserDefinedGenieSamplesDetailed(userDefinedSamplesForGenie); + } + + private void assertAccTcgaSampleIds(List allAccSamples) { + assertEquals(4, allAccSamples.size()); + var allAccSampleIds = allAccSamples.stream().map(Sample::stableId).toList(); + assertTrue(allAccSampleIds.contains("tcga-a1-a0sb-01")); + assertTrue(allAccSampleIds.contains("tcga-a1-b0so-01")); + assertTrue(allAccSampleIds.contains("tcga-a1-b0sp-01")); + assertTrue(allAccSampleIds.contains("tcga-a1-b0sq-01")); + } + + private void assertAccTcgaSamplesSummary(List allAccSamples) { + assertAccTcgaSampleIds(allAccSamples); + var a0sb01 = + allAccSamples.stream() + .filter(s -> s.stableId().equals("tcga-a1-a0sb-01")) + .findFirst() + .get(); + assertEquals(18, a0sb01.patientId().intValue()); + assertEquals(SampleType.PRIMARY_SOLID_TUMOR, a0sb01.sampleType()); + } + + private void assertAccTcgaSamplesDetailed(List allAccSamples) { + assertAccTcgaSamplesSummary(allAccSamples); + var a0sb01 = + allAccSamples.stream() + .filter(s -> s.stableId().equals("tcga-a1-a0sb-01")) + .findFirst() + .get(); + assertFalse(a0sb01.sequenced()); + assertFalse(a0sb01.copyNumberSegmentPresent()); + assertEquals("tcga-a1-a0sb", a0sb01.patientStableId()); + assertEquals("tcga-a1-a0sb", a0sb01.patient().stableId()); + assertEquals(STUDY_ACC_TCGA, a0sb01.patient().cancerStudy().cancerStudyIdentifier()); + } + + private void assertTcgaPubSampleIds(List allTcgaPubSamples) { + assertEquals(15, allTcgaPubSamples.size()); + var allTcgaPubSampleIds = allTcgaPubSamples.stream().map(Sample::stableId).toList(); + assertTrue(allTcgaPubSampleIds.contains("tcga-a1-a0sb-01")); + assertTrue(allTcgaPubSampleIds.contains("tcga-a1-a0sb-02")); + assertTrue(allTcgaPubSampleIds.contains("tcga-a1-a0sm-01")); + assertTrue(allTcgaPubSampleIds.contains("tcga-a1-a0sn-01")); + assertTrue(allTcgaPubSampleIds.contains("tcga-a1-a0so-01")); + assertTrue(allTcgaPubSampleIds.contains("tcga-a1-a0sp-01")); + assertTrue(allTcgaPubSampleIds.contains("tcga-a1-a0sq-01")); + } + + private void assertTcgaPubSamplesSummary(List allTcgaPubSamples) { + assertTcgaPubSampleIds(allTcgaPubSamples); + var a0sb02 = + allTcgaPubSamples.stream() + .filter(s -> s.stableId().equals("tcga-a1-a0sb-02")) + .findFirst() + .get(); + assertEquals(1, a0sb02.patientId().intValue()); + assertEquals(SampleType.PRIMARY_SOLID_TUMOR, a0sb02.sampleType()); + } + + private void assertTcgaPubSamplesDetailed(List allTcgaPubSamples) { + assertTcgaPubSamplesSummary(allTcgaPubSamples); + var a0sb02 = + allTcgaPubSamples.stream() + .filter(s -> s.stableId().equals("tcga-a1-a0sb-02")) + .findFirst() + .get(); + assertFalse(a0sb02.sequenced()); + assertFalse(a0sb02.copyNumberSegmentPresent()); + assertEquals("tcga-a1-a0sb", a0sb02.patientStableId()); + assertEquals("tcga-a1-a0sb", a0sb02.patient().stableId()); + assertEquals(STUDY_TCGA_PUB, a0sb02.patient().cancerStudy().cancerStudyIdentifier()); + } + + private void assertMultiStudySampleIds(List allSamplesForAccAndTcga) { + assertEquals(19, allSamplesForAccAndTcga.size()); + var allSamplesIdsForAccAndTcga = + allSamplesForAccAndTcga.stream().map(Sample::stableId).toList(); + // we have tcga-a1-a0sb-01 in both studies, so the count should be 2 + assertEquals( + 2, + allSamplesIdsForAccAndTcga.stream() + .filter(s -> s.equals("tcga-a1-a0sb-01")) + .toList() + .size()); + assertTrue(allSamplesIdsForAccAndTcga.contains("tcga-a1-a0sb-02")); + assertTrue(allSamplesIdsForAccAndTcga.contains("tcga-a1-a0sm-01")); + assertTrue(allSamplesIdsForAccAndTcga.contains("tcga-a1-a0sn-01")); + assertTrue(allSamplesIdsForAccAndTcga.contains("tcga-a1-a0so-01")); + assertTrue(allSamplesIdsForAccAndTcga.contains("tcga-a1-a0sp-01")); + assertTrue(allSamplesIdsForAccAndTcga.contains("tcga-a1-a0sq-01")); + assertTrue(allSamplesIdsForAccAndTcga.contains("tcga-a1-b0so-01")); + assertTrue(allSamplesIdsForAccAndTcga.contains("tcga-a1-b0sp-01")); + assertTrue(allSamplesIdsForAccAndTcga.contains("tcga-a1-b0sq-01")); + } + + private void assertMultiStudySamplesSummary(List allSamplesForAccAndTcga) { + assertMultiStudySampleIds(allSamplesForAccAndTcga); + assertEquals(SampleType.PRIMARY_SOLID_TUMOR, allSamplesForAccAndTcga.getFirst().sampleType()); + } + + private void assertMultiStudySamplesDetailed(List allSamplesForAccAndTcga) { + assertMultiStudySamplesSummary(allSamplesForAccAndTcga); + assertNotNull( + allSamplesForAccAndTcga.getFirst().patient().cancerStudy().cancerStudyIdentifier()); + } + + private void assertSampleIdsForPatientA1A0SB(List tcgaPubSamplesForPatientA1A0SB) { + assertEquals(2, tcgaPubSamplesForPatientA1A0SB.size()); + var sampleIdsForPatientA1A0SB = + tcgaPubSamplesForPatientA1A0SB.stream().map(Sample::stableId).toList(); + assertTrue(sampleIdsForPatientA1A0SB.contains("tcga-a1-a0sb-01")); + assertTrue(sampleIdsForPatientA1A0SB.contains("tcga-a1-a0sb-02")); + } + + private void assertSamplesSummaryForPatientA1A0SB(List tcgaPubSamplesForPatientA1A0SB) { + assertSampleIdsForPatientA1A0SB(tcgaPubSamplesForPatientA1A0SB); + assertEquals(1, tcgaPubSamplesForPatientA1A0SB.getFirst().patientId().intValue()); + assertEquals( + SampleType.PRIMARY_SOLID_TUMOR, tcgaPubSamplesForPatientA1A0SB.getFirst().sampleType()); + assertEquals(1, tcgaPubSamplesForPatientA1A0SB.getLast().patientId().intValue()); + assertEquals( + SampleType.PRIMARY_SOLID_TUMOR, tcgaPubSamplesForPatientA1A0SB.getLast().sampleType()); + } + + private void assertSamplesDetailedForPatientA1A0SB(List tcgaPubSamplesForPatientA1A0SB) { + assertSamplesSummaryForPatientA1A0SB(tcgaPubSamplesForPatientA1A0SB); + assertEquals("tcga-a1-a0sb", tcgaPubSamplesForPatientA1A0SB.getFirst().patient().stableId()); + assertEquals( + STUDY_TCGA_PUB, + tcgaPubSamplesForPatientA1A0SB.getFirst().patient().cancerStudy().cancerStudyIdentifier()); + assertEquals("tcga-a1-a0sb", tcgaPubSamplesForPatientA1A0SB.getLast().patient().stableId()); + assertEquals( + STUDY_TCGA_PUB, + tcgaPubSamplesForPatientA1A0SB.getLast().patient().cancerStudy().cancerStudyIdentifier()); + } + + private void assertUserDefinedSampleIds(List userDefinedSamplesForAccAndTcga) { + assertEquals(3, userDefinedSamplesForAccAndTcga.size()); + var specificSampleIdsForAccAndTcga = + userDefinedSamplesForAccAndTcga.stream().map(Sample::stableId).toList(); + assertTrue(specificSampleIdsForAccAndTcga.contains("tcga-a1-b0sq-01")); + assertTrue(specificSampleIdsForAccAndTcga.contains("tcga-a1-a0sq-01")); + assertTrue(specificSampleIdsForAccAndTcga.contains("tcga-a1-a0si-01")); + } + + private void assertUserDefinedSamplesSummary(List userDefinedSamplesForAccAndTcga) { + assertUserDefinedSampleIds(userDefinedSamplesForAccAndTcga); + assertEquals( + SampleType.PRIMARY_SOLID_TUMOR, userDefinedSamplesForAccAndTcga.get(0).sampleType()); + assertEquals( + SampleType.PRIMARY_SOLID_TUMOR, userDefinedSamplesForAccAndTcga.get(1).sampleType()); + assertEquals( + SampleType.PRIMARY_SOLID_TUMOR, userDefinedSamplesForAccAndTcga.get(2).sampleType()); + } + + private void assertUserDefinedSamplesDetailed(List userDefinedSamplesForAccAndTcga) { + assertUserDefinedSamplesSummary(userDefinedSamplesForAccAndTcga); + assertNotNull( + userDefinedSamplesForAccAndTcga.get(0).patient().cancerStudy().cancerStudyIdentifier()); + assertNotNull( + userDefinedSamplesForAccAndTcga.get(1).patient().cancerStudy().cancerStudyIdentifier()); + assertNotNull( + userDefinedSamplesForAccAndTcga.get(2).patient().cancerStudy().cancerStudyIdentifier()); + } + + private void assertUserDefinedGenieSampleIds(List userDefinedSamplesForGenie) { + assertEquals(2, userDefinedSamplesForGenie.size()); + var specificSampleIdsForGenie = + userDefinedSamplesForGenie.stream().map(Sample::stableId).toList(); + assertTrue(specificSampleIdsForGenie.contains("GENIE-TEST-302-01")); + assertTrue(specificSampleIdsForGenie.contains("GENIE-TEST-309-01")); + } + + private void assertUserDefinedGenieSamplesSummary(List userDefinedSamplesForGenie) { + assertUserDefinedGenieSampleIds(userDefinedSamplesForGenie); + assertEquals(SampleType.PRIMARY_SOLID_TUMOR, userDefinedSamplesForGenie.get(0).sampleType()); + assertEquals(SampleType.PRIMARY_SOLID_TUMOR, userDefinedSamplesForGenie.get(1).sampleType()); + } + + private void assertUserDefinedGenieSamplesDetailed(List userDefinedSamplesForGenie) { + assertUserDefinedGenieSamplesSummary(userDefinedSamplesForGenie); + assertNotNull( + userDefinedSamplesForGenie.get(0).patient().cancerStudy().cancerStudyIdentifier()); + assertNotNull( + userDefinedSamplesForGenie.get(1).patient().cancerStudy().cancerStudyIdentifier()); + } + + private void assertKeywordFilteredSampleIds( + List keywordFilteredSamplesForAccAndTcgaAndGenie) { + assertEquals(4, keywordFilteredSamplesForAccAndTcgaAndGenie.size()); + var keywordFilteredSamplesIds = + keywordFilteredSamplesForAccAndTcgaAndGenie.stream().map(Sample::stableId).toList(); + assertTrue(keywordFilteredSamplesIds.contains("tcga-a1-a0sb-02")); + assertTrue(keywordFilteredSamplesIds.contains("GENIE-TEST-321-02")); + assertTrue(keywordFilteredSamplesIds.contains("GENIE-TEST-322-02")); + assertTrue(keywordFilteredSamplesIds.contains("GENIE-TEST-323-02")); + } + + private void assertKeywordFilteredSamplesSummary( + List keywordFilteredSamplesForAccAndTcgaAndGenie) { + assertKeywordFilteredSampleIds(keywordFilteredSamplesForAccAndTcgaAndGenie); + assertEquals( + SampleType.PRIMARY_SOLID_TUMOR, + keywordFilteredSamplesForAccAndTcgaAndGenie.get(0).sampleType()); + assertEquals( + SampleType.PRIMARY_SOLID_TUMOR, + keywordFilteredSamplesForAccAndTcgaAndGenie.get(1).sampleType()); + assertEquals( + SampleType.PRIMARY_SOLID_TUMOR, + keywordFilteredSamplesForAccAndTcgaAndGenie.get(2).sampleType()); + assertEquals( + SampleType.PRIMARY_SOLID_TUMOR, + keywordFilteredSamplesForAccAndTcgaAndGenie.get(3).sampleType()); + } + + private void assertKeywordFilteredSamplesDetailed( + List keywordFilteredSamplesForAccAndTcgaAndGenie) { + assertKeywordFilteredSamplesSummary(keywordFilteredSamplesForAccAndTcgaAndGenie); + assertNotNull( + keywordFilteredSamplesForAccAndTcgaAndGenie + .get(0) + .patient() + .cancerStudy() + .cancerStudyIdentifier()); + assertNotNull( + keywordFilteredSamplesForAccAndTcgaAndGenie + .get(1) + .patient() + .cancerStudy() + .cancerStudyIdentifier()); + assertNotNull( + keywordFilteredSamplesForAccAndTcgaAndGenie + .get(2) + .patient() + .cancerStudy() + .cancerStudyIdentifier()); + assertNotNull( + keywordFilteredSamplesForAccAndTcgaAndGenie + .get(3) + .patient() + .cancerStudy() + .cancerStudyIdentifier()); + } + + @Test + public void getSamplesBySampleListIds() { + var studyTcgaPubAll = + mapper.getSamplesBySampleListIds(Collections.singletonList("study_tcga_pub_all")); + assertEquals(14, studyTcgaPubAll.size()); + + var studyTcgaPubAcgh = + mapper.getSamplesBySampleListIds(Collections.singletonList("study_tcga_pub_acgh")); + assertEquals(14, studyTcgaPubAcgh.size()); + + var studyTcgaPubCnaseq = + mapper.getSamplesBySampleListIds(Collections.singletonList("study_tcga_pub_cnaseq")); + assertEquals(7, studyTcgaPubCnaseq.size()); + + var studyTcgaPubComplete = + mapper.getSamplesBySampleListIds(Collections.singletonList("study_tcga_pub_complete")); + assertEquals(7, studyTcgaPubComplete.size()); + + var studyTcgaPubLog2cna = + mapper.getSamplesBySampleListIds(Collections.singletonList("study_tcga_pub_log2cna")); + assertEquals(14, studyTcgaPubLog2cna.size()); + + var studyTcgaPubMethylationHm27 = + mapper.getSamplesBySampleListIds( + Collections.singletonList("study_tcga_pub_methylation_hm27")); + assertEquals(1, studyTcgaPubMethylationHm27.size()); + + var studyTcgaPubMrna = + mapper.getSamplesBySampleListIds(Collections.singletonList("study_tcga_pub_mrna")); + assertEquals(8, studyTcgaPubMrna.size()); + + var studyTcgaPubSequenced = + mapper.getSamplesBySampleListIds(Collections.singletonList("study_tcga_pub_sequenced")); + assertEquals(7, studyTcgaPubSequenced.size()); + + var studyTcgaPubCna = + mapper.getSamplesBySampleListIds(Collections.singletonList("study_tcga_pub_cna")); + assertEquals(7, studyTcgaPubCna.size()); + + var studyTcgaPubRnaSeqV2Mrna = + mapper.getSamplesBySampleListIds( + Collections.singletonList("study_tcga_pub_rna_seq_v2_mrna")); + assertEquals(7, studyTcgaPubRnaSeqV2Mrna.size()); + + var studyTcgaPubMicrorna = + mapper.getSamplesBySampleListIds(Collections.singletonList("study_tcga_pub_microrna")); + assertEquals(0, studyTcgaPubMicrorna.size()); + + var studyTcgaPubRppa = + mapper.getSamplesBySampleListIds(Collections.singletonList("study_tcga_pub_rppa")); + assertEquals(0, studyTcgaPubRppa.size()); + + var studyTcgaPub3wayComplete = + mapper.getSamplesBySampleListIds(Collections.singletonList("study_tcga_pub_3way_complete")); + assertEquals(7, studyTcgaPub3wayComplete.size()); + + var accTcgaAll = mapper.getSamplesBySampleListIds(Collections.singletonList("acc_tcga_all")); + assertEquals(1, accTcgaAll.size()); + } + + @Test + public void getSummarySamplesBySampleListIds() { + var studyTcgaPubAll = + mapper.getSummarySamplesBySampleListIds(Collections.singletonList("study_tcga_pub_all")); + assertEquals(14, studyTcgaPubAll.size()); + assertEquals(SampleType.PRIMARY_SOLID_TUMOR, studyTcgaPubAll.getFirst().sampleType()); + + var studyTcgaPubAcgh = + mapper.getSummarySamplesBySampleListIds(Collections.singletonList("study_tcga_pub_acgh")); + assertEquals(14, studyTcgaPubAcgh.size()); + assertEquals(SampleType.PRIMARY_SOLID_TUMOR, studyTcgaPubAcgh.getFirst().sampleType()); + + var studyTcgaPubCnaseq = + mapper.getSummarySamplesBySampleListIds(Collections.singletonList("study_tcga_pub_cnaseq")); + assertEquals(7, studyTcgaPubCnaseq.size()); + assertEquals(SampleType.PRIMARY_SOLID_TUMOR, studyTcgaPubCnaseq.getFirst().sampleType()); + + var studyTcgaPubComplete = + mapper.getSummarySamplesBySampleListIds( + Collections.singletonList("study_tcga_pub_complete")); + assertEquals(7, studyTcgaPubComplete.size()); + assertEquals(SampleType.PRIMARY_SOLID_TUMOR, studyTcgaPubComplete.getFirst().sampleType()); + + var studyTcgaPubLog2cna = + mapper.getSummarySamplesBySampleListIds( + Collections.singletonList("study_tcga_pub_log2cna")); + assertEquals(14, studyTcgaPubLog2cna.size()); + assertEquals(SampleType.PRIMARY_SOLID_TUMOR, studyTcgaPubLog2cna.getFirst().sampleType()); + + var studyTcgaPubMethylationHm27 = + mapper.getSummarySamplesBySampleListIds( + Collections.singletonList("study_tcga_pub_methylation_hm27")); + assertEquals(1, studyTcgaPubMethylationHm27.size()); + assertEquals( + SampleType.PRIMARY_SOLID_TUMOR, studyTcgaPubMethylationHm27.getFirst().sampleType()); + + var studyTcgaPubMrna = + mapper.getSummarySamplesBySampleListIds(Collections.singletonList("study_tcga_pub_mrna")); + assertEquals(8, studyTcgaPubMrna.size()); + assertEquals(SampleType.PRIMARY_SOLID_TUMOR, studyTcgaPubMrna.getFirst().sampleType()); + + var studyTcgaPubSequenced = + mapper.getSummarySamplesBySampleListIds( + Collections.singletonList("study_tcga_pub_sequenced")); + assertEquals(7, studyTcgaPubSequenced.size()); + assertEquals(SampleType.PRIMARY_SOLID_TUMOR, studyTcgaPubSequenced.getFirst().sampleType()); + + var studyTcgaPubCna = + mapper.getSummarySamplesBySampleListIds(Collections.singletonList("study_tcga_pub_cna")); + assertEquals(7, studyTcgaPubCna.size()); + assertEquals(SampleType.PRIMARY_SOLID_TUMOR, studyTcgaPubCna.getFirst().sampleType()); + + var studyTcgaPubRnaSeqV2Mrna = + mapper.getSummarySamplesBySampleListIds( + Collections.singletonList("study_tcga_pub_rna_seq_v2_mrna")); + assertEquals(7, studyTcgaPubRnaSeqV2Mrna.size()); + assertEquals(SampleType.PRIMARY_SOLID_TUMOR, studyTcgaPubRnaSeqV2Mrna.getFirst().sampleType()); + + var studyTcgaPub3wayComplete = + mapper.getSummarySamplesBySampleListIds( + Collections.singletonList("study_tcga_pub_3way_complete")); + assertEquals(7, studyTcgaPub3wayComplete.size()); + assertEquals(SampleType.PRIMARY_SOLID_TUMOR, studyTcgaPub3wayComplete.getFirst().sampleType()); + + var accTcgaAll = + mapper.getSummarySamplesBySampleListIds(Collections.singletonList("acc_tcga_all")); + assertEquals(1, accTcgaAll.size()); + assertEquals(SampleType.PRIMARY_SOLID_TUMOR, accTcgaAll.getFirst().sampleType()); + } + + @Test + public void getDetailedSamplesBySampleListIds() { + var studyTcgaPubAll = + mapper.getDetailedSamplesBySampleListIds(Collections.singletonList("study_tcga_pub_all")); + assertEquals(14, studyTcgaPubAll.size()); + + var studyTcgaPubAcgh = + mapper.getDetailedSamplesBySampleListIds(Collections.singletonList("study_tcga_pub_acgh")); + assertEquals(14, studyTcgaPubAcgh.size()); + + var studyTcgaPubCnaseq = + mapper.getDetailedSamplesBySampleListIds( + Collections.singletonList("study_tcga_pub_cnaseq")); + assertEquals(7, studyTcgaPubCnaseq.size()); + + var studyTcgaPubComplete = + mapper.getDetailedSamplesBySampleListIds( + Collections.singletonList("study_tcga_pub_complete")); + assertEquals(7, studyTcgaPubComplete.size()); + + var studyTcgaPubLog2cna = + mapper.getDetailedSamplesBySampleListIds( + Collections.singletonList("study_tcga_pub_log2cna")); + assertEquals(14, studyTcgaPubLog2cna.size()); + + var studyTcgaPubMethylationHm27 = + mapper.getDetailedSamplesBySampleListIds( + Collections.singletonList("study_tcga_pub_methylation_hm27")); + assertEquals(1, studyTcgaPubMethylationHm27.size()); + + var studyTcgaPubMrna = + mapper.getDetailedSamplesBySampleListIds(Collections.singletonList("study_tcga_pub_mrna")); + assertEquals(8, studyTcgaPubMrna.size()); + + var studyTcgaPubSequenced = + mapper.getDetailedSamplesBySampleListIds( + Collections.singletonList("study_tcga_pub_sequenced")); + assertEquals(7, studyTcgaPubSequenced.size()); + // all samples should be sequenced + assertEquals(7, studyTcgaPubSequenced.stream().filter(Sample::sequenced).count()); + + var studyTcgaPubCna = + mapper.getDetailedSamplesBySampleListIds(Collections.singletonList("study_tcga_pub_cna")); + assertEquals(7, studyTcgaPubCna.size()); + // only 2 samples should have copy number segments + assertEquals(2, studyTcgaPubCna.stream().filter(Sample::copyNumberSegmentPresent).count()); + assertTrue(studyTcgaPubCna.get(0).copyNumberSegmentPresent()); + assertEquals("tcga-a1-a0sd", studyTcgaPubCna.get(0).patient().stableId()); + assertTrue(studyTcgaPubCna.get(1).copyNumberSegmentPresent()); + assertEquals("tcga-a1-a0se", studyTcgaPubCna.get(1).patient().stableId()); + + var studyTcgaPubRnaSeqV2Mrna = + mapper.getDetailedSamplesBySampleListIds( + Collections.singletonList("study_tcga_pub_rna_seq_v2_mrna")); + assertEquals(7, studyTcgaPubRnaSeqV2Mrna.size()); + + var studyTcgaPubMicrorna = + mapper.getDetailedSamplesBySampleListIds( + Collections.singletonList("study_tcga_pub_microrna")); + assertEquals(0, studyTcgaPubMicrorna.size()); + + var studyTcgaPubRppa = + mapper.getDetailedSamplesBySampleListIds(Collections.singletonList("study_tcga_pub_rppa")); + assertEquals(0, studyTcgaPubRppa.size()); + + var studyTcgaPub3wayComplete = + mapper.getDetailedSamplesBySampleListIds( + Collections.singletonList("study_tcga_pub_3way_complete")); + assertEquals(7, studyTcgaPub3wayComplete.size()); + + var accTcgaAll = + mapper.getDetailedSamplesBySampleListIds(Collections.singletonList("acc_tcga_all")); + assertEquals(1, accTcgaAll.size()); + } + + @Test + public void getSample() { + var sample1 = mapper.getSample(STUDY_TCGA_PUB, "tcga-a1-a0sb-01"); + assertEquals("tcga-a1-a0sb-01", sample1.stableId()); + assertFalse(sample1.sequenced()); + assertTrue(sample1.copyNumberSegmentPresent()); + assertEquals(1, sample1.patientId().intValue()); + assertEquals(1, sample1.patient().internalId().intValue()); + assertEquals(1, sample1.patient().cancerStudyId().intValue()); + assertEquals(1, sample1.patient().cancerStudy().cancerStudyId().intValue()); + assertEquals(STUDY_TCGA_PUB, sample1.patient().cancerStudyIdentifier()); + assertEquals(STUDY_TCGA_PUB, sample1.patient().cancerStudy().cancerStudyIdentifier()); + + var sample2 = mapper.getSample(STUDY_ACC_TCGA, "tcga-a1-a0sb-01"); + assertEquals("tcga-a1-a0sb-01", sample2.stableId()); + assertFalse(sample2.sequenced()); + assertFalse(sample2.copyNumberSegmentPresent()); + assertEquals(18, sample2.patientId().intValue()); + assertEquals(18, sample2.patient().internalId().intValue()); + assertEquals(2, sample2.patient().cancerStudyId().intValue()); + assertEquals(2, sample2.patient().cancerStudy().cancerStudyId().intValue()); + assertEquals(STUDY_ACC_TCGA, sample2.patient().cancerStudyIdentifier()); + assertEquals(STUDY_ACC_TCGA, sample2.patient().cancerStudy().cancerStudyIdentifier()); + + var sample3 = mapper.getSample(STUDY_TCGA_PUB, "tcga-a1-a0sd-01"); + assertTrue(sample3.sequenced()); + } + + private DataFilterValue newDataFilterValue(Double start, Double end, String value) { + DataFilterValue dataFilterValue = new DataFilterValue(); + + dataFilterValue.setStart(start == null ? null : new BigDecimal(start)); + dataFilterValue.setEnd(end == null ? null : new BigDecimal(end)); + dataFilterValue.setValue(value); + + return dataFilterValue; + } + + private ClinicalDataFilter newClinicalDataFilter( + String attributeId, List values) { + ClinicalDataFilter clinicalDataFilter = new ClinicalDataFilter(); + + clinicalDataFilter.setAttributeId(attributeId); + clinicalDataFilter.setValues(values); + + return clinicalDataFilter; + } +} diff --git a/src/test/java/org/cbioportal/infrastructure/repository/clickhouse/sample/ClickhouseSampleRepositoryTest.java b/src/test/java/org/cbioportal/infrastructure/repository/clickhouse/sample/ClickhouseSampleRepositoryTest.java new file mode 100644 index 00000000000..96efa96c901 --- /dev/null +++ b/src/test/java/org/cbioportal/infrastructure/repository/clickhouse/sample/ClickhouseSampleRepositoryTest.java @@ -0,0 +1,75 @@ +package org.cbioportal.infrastructure.repository.clickhouse.sample; + +import static org.junit.Assert.assertEquals; + +import java.util.ArrayList; +import java.util.List; +import org.cbioportal.domain.sample.Sample; +import org.cbioportal.infrastructure.repository.clickhouse.AbstractTestcontainers; +import org.cbioportal.infrastructure.repository.clickhouse.config.MyBatisConfig; +import org.cbioportal.shared.enums.ProjectionType; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase; +import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; +import org.springframework.context.annotation.Import; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@Import(MyBatisConfig.class) +@DataJpaTest +@DirtiesContext +@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE) +@ContextConfiguration(initializers = AbstractTestcontainers.Initializer.class) +public class ClickhouseSampleRepositoryTest { + + private static final String STUDY_TCGA_PUB = "study_tcga_pub"; + + private ClickhouseSampleRepository repository; + + @Autowired + public void configure(ClickhouseSampleMapper mapper) { + this.repository = new ClickhouseSampleRepository(mapper); + } + + @Test + public void getAllSamplesInStudy() { + var sortedByStableIdDesc = getAllTcgaPubSamplesPaginatedAndSorted("stableId", "DESC"); + assertEquals(6, sortedByStableIdDesc.get(0).size()); + assertEquals("tcga-a1-a0sq-01", sortedByStableIdDesc.get(0).getFirst().stableId()); + assertEquals(6, sortedByStableIdDesc.get(1).size()); + assertEquals("tcga-a1-a0sj-01", sortedByStableIdDesc.get(1).getFirst().stableId()); + assertEquals(3, sortedByStableIdDesc.get(2).size()); + assertEquals("tcga-a1-a0sd-01", sortedByStableIdDesc.get(2).getFirst().stableId()); + + var sortedByStableIdAsc = getAllTcgaPubSamplesPaginatedAndSorted("stableId", "ASC"); + assertEquals(6, sortedByStableIdAsc.get(0).size()); + assertEquals("tcga-a1-a0sb-01", sortedByStableIdAsc.get(0).getFirst().stableId()); + assertEquals(6, sortedByStableIdAsc.get(1).size()); + assertEquals("tcga-a1-a0sh-01", sortedByStableIdAsc.get(1).getFirst().stableId()); + assertEquals(3, sortedByStableIdAsc.get(2).size()); + assertEquals("tcga-a1-a0so-01", sortedByStableIdAsc.get(2).getFirst().stableId()); + } + + private List> getAllTcgaPubSamplesPaginatedAndSorted( + String sortBy, String direction) { + var pages = new ArrayList>(); + + pages.add( + repository.getAllSamplesInStudy( + STUDY_TCGA_PUB, ProjectionType.DETAILED, 6, 0, sortBy, direction)); + + pages.add( + repository.getAllSamplesInStudy( + STUDY_TCGA_PUB, ProjectionType.DETAILED, 6, 1, sortBy, direction)); + + pages.add( + repository.getAllSamplesInStudy( + STUDY_TCGA_PUB, ProjectionType.DETAILED, 6, 2, sortBy, direction)); + + return pages; + } +} diff --git a/src/test/java/org/cbioportal/infrastructure/repository/clickhouse/treatment/ClickhouseTreatmentMapperTest.java b/src/test/java/org/cbioportal/infrastructure/repository/clickhouse/treatment/ClickhouseTreatmentMapperTest.java new file mode 100644 index 00000000000..6623270a49d --- /dev/null +++ b/src/test/java/org/cbioportal/infrastructure/repository/clickhouse/treatment/ClickhouseTreatmentMapperTest.java @@ -0,0 +1,125 @@ +package org.cbioportal.infrastructure.repository.clickhouse.treatment; + +import static org.junit.Assert.assertEquals; + +import java.util.List; +import org.cbioportal.domain.studyview.StudyViewFilterFactory; +import org.cbioportal.infrastructure.repository.clickhouse.AbstractTestcontainers; +import org.cbioportal.infrastructure.repository.clickhouse.config.MyBatisConfig; +import org.cbioportal.legacy.model.TemporalRelation; +import org.cbioportal.legacy.web.parameter.StudyViewFilter; +import org.cbioportal.legacy.web.parameter.filter.AndedPatientTreatmentFilters; +import org.cbioportal.legacy.web.parameter.filter.AndedSampleTreatmentFilters; +import org.cbioportal.legacy.web.parameter.filter.OredPatientTreatmentFilters; +import org.cbioportal.legacy.web.parameter.filter.OredSampleTreatmentFilters; +import org.cbioportal.legacy.web.parameter.filter.PatientTreatmentFilter; +import org.cbioportal.legacy.web.parameter.filter.SampleTreatmentFilter; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase; +import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; +import org.springframework.context.annotation.Import; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@Import(MyBatisConfig.class) +@DataJpaTest +@DirtiesContext +@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE) +@ContextConfiguration(initializers = AbstractTestcontainers.Initializer.class) +public class ClickhouseTreatmentMapperTest { + private static final String STUDY_TCGA_PUB = "study_tcga_pub"; + + @Autowired private ClickhouseTreatmentMapper mapper; + + @Test + public void getPatientTreatments() { + + StudyViewFilter studyViewFilter = new StudyViewFilter(); + studyViewFilter.setStudyIds(List.of(STUDY_TCGA_PUB)); + + var patientTreatmentCounts = + mapper.getPatientTreatmentCounts( + StudyViewFilterFactory.make( + studyViewFilter, null, studyViewFilter.getStudyIds(), null)); + + var patientTreatments = + mapper.getPatientTreatments( + StudyViewFilterFactory.make( + studyViewFilter, null, studyViewFilter.getStudyIds(), null)); + + assertEquals(1, patientTreatmentCounts); + assertEquals("madeupanib", patientTreatments.getFirst().treatment()); + + PatientTreatmentFilter filter = new PatientTreatmentFilter(); + filter.setTreatment("madeupanib"); + + OredPatientTreatmentFilters oredPatientTreatmentFilters = new OredPatientTreatmentFilters(); + oredPatientTreatmentFilters.setFilters(List.of(filter)); + + AndedPatientTreatmentFilters andedPatientTreatmentFilters = new AndedPatientTreatmentFilters(); + andedPatientTreatmentFilters.setFilters(List.of(oredPatientTreatmentFilters)); + studyViewFilter.setPatientTreatmentFilters(andedPatientTreatmentFilters); + + patientTreatmentCounts = + mapper.getPatientTreatmentCounts( + StudyViewFilterFactory.make( + studyViewFilter, null, studyViewFilter.getStudyIds(), null)); + + patientTreatments = + mapper.getPatientTreatments( + StudyViewFilterFactory.make( + studyViewFilter, null, studyViewFilter.getStudyIds(), null)); + + assertEquals(1, patientTreatmentCounts); + assertEquals("madeupanib", patientTreatments.getFirst().treatment()); + } + + @Test + public void getTotalSampleTreatmentCounts() { + StudyViewFilter studyViewFilter = new StudyViewFilter(); + studyViewFilter.setStudyIds(List.of(STUDY_TCGA_PUB)); + + var totalSampleTreatmentCount = + mapper.getTotalSampleTreatmentCounts( + StudyViewFilterFactory.make( + studyViewFilter, null, studyViewFilter.getStudyIds(), null)); + + var sampleTreatmentCounts = + mapper.getSampleTreatmentCounts( + StudyViewFilterFactory.make( + studyViewFilter, null, studyViewFilter.getStudyIds(), null)); + + assertEquals(1, totalSampleTreatmentCount); + assertEquals("madeupanib", sampleTreatmentCounts.getFirst().treatment()); + assertEquals(1, sampleTreatmentCounts.getFirst().postSampleCount()); + assertEquals(0, sampleTreatmentCounts.getFirst().preSampleCount()); + + SampleTreatmentFilter filter = new SampleTreatmentFilter(); + filter.setTreatment("madeupanib"); + filter.setTime(TemporalRelation.Pre); + + OredSampleTreatmentFilters oredSampleTreatmentFilters = new OredSampleTreatmentFilters(); + oredSampleTreatmentFilters.setFilters(List.of(filter)); + + AndedSampleTreatmentFilters andedSampleTreatmentFilters = new AndedSampleTreatmentFilters(); + andedSampleTreatmentFilters.setFilters(List.of(oredSampleTreatmentFilters)); + studyViewFilter.setSampleTreatmentFilters(andedSampleTreatmentFilters); + + totalSampleTreatmentCount = + mapper.getTotalSampleTreatmentCounts( + StudyViewFilterFactory.make( + studyViewFilter, null, studyViewFilter.getStudyIds(), null)); + + sampleTreatmentCounts = + mapper.getSampleTreatmentCounts( + StudyViewFilterFactory.make( + studyViewFilter, null, studyViewFilter.getStudyIds(), null)); + + assertEquals(0, totalSampleTreatmentCount); + assertEquals(0, sampleTreatmentCounts.size()); + } +} diff --git a/src/test/java/org/cbioportal/legacy/persistence/helper/AlterationFilterHelperTest.java b/src/test/java/org/cbioportal/legacy/persistence/helper/AlterationFilterHelperTest.java new file mode 100644 index 00000000000..313f2ca96db --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/persistence/helper/AlterationFilterHelperTest.java @@ -0,0 +1,165 @@ +package org.cbioportal.legacy.persistence.helper; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.util.HashMap; +import java.util.Map; +import org.cbioportal.legacy.model.AlterationFilter; +import org.cbioportal.legacy.model.MutationEventType; +import org.junit.Test; + +public class AlterationFilterHelperTest { + + @Test + public void build() { + assertNotNull(AlterationFilterHelper.build(null)); + } + + @Test + public void getMutationTypeList() { + // Create AlterationFilter + AlterationFilter alterationFilter = new AlterationFilter(); + Map mutationEventTypeFilterMap = new HashMap<>(); + mutationEventTypeFilterMap.put(MutationEventType.nonsense_mutation, Boolean.TRUE); + mutationEventTypeFilterMap.put(MutationEventType.other, Boolean.FALSE); + alterationFilter.setMutationEventTypes(mutationEventTypeFilterMap); + + AlterationFilterHelper helper = AlterationFilterHelper.build(alterationFilter); + var mutationList = helper.getMutationTypeList(); + assertFalse(mutationList.hasNone()); + assertFalse(mutationList.hasAll()); + assertTrue(mutationList.hasValues()); + } + + @Test + public void hasDriver() { + AlterationFilter alterationFilter = new AlterationFilter(); + alterationFilter.setIncludeDriver(true); + assertTrue(AlterationFilterHelper.build(alterationFilter).hasDriver()); + } + + @Test + public void hasVUSDriver() { + AlterationFilter alterationFilter = new AlterationFilter(); + alterationFilter.setIncludeVUS(true); + assertTrue(AlterationFilterHelper.build(alterationFilter).hasVUSDriver()); + } + + @Test + public void hasUnknownOncogenicity() { + AlterationFilter alterationFilter = new AlterationFilter(); + alterationFilter.setIncludeUnknownOncogenicity(true); + assertTrue(AlterationFilterHelper.build(alterationFilter).hasUnknownOncogenicity()); + } + + @Test + public void hasGermline() { + AlterationFilter alterationFilter = new AlterationFilter(); + alterationFilter.setIncludeGermline(true); + assertTrue(AlterationFilterHelper.build(alterationFilter).hasGermline()); + } + + @Test + public void hasSomatic() { + AlterationFilter alterationFilter = new AlterationFilter(); + alterationFilter.setIncludeSomatic(true); + assertTrue(AlterationFilterHelper.build(alterationFilter).hasSomatic()); + } + + @Test + public void hasUnknownMutationStatus() { + AlterationFilter alterationFilter = new AlterationFilter(); + alterationFilter.setIncludeUnknownStatus(true); + assertTrue(AlterationFilterHelper.build(alterationFilter).hasUnknownMutationStatus()); + } + + @Test + public void getSelectedTiers() { + AlterationFilter alterationFilter = new AlterationFilter(); + Map tiersMap = new HashMap<>(); + alterationFilter.setTiersBooleanMap(tiersMap); + assertNotNull(AlterationFilterHelper.build(alterationFilter).getSelectedTiers()); + } + + @Test + public void hasUnknownTier() { + AlterationFilter alterationFilter = new AlterationFilter(); + alterationFilter.setIncludeUnknownTier(true); + assertTrue(AlterationFilterHelper.build(alterationFilter).hasUnknownTier()); + } + + @Test + public void isAllDriverAnnotationSelected() { + AlterationFilter alterationFilter = new AlterationFilter(); + alterationFilter.setIncludeDriver(true); + alterationFilter.setIncludeVUS(true); + alterationFilter.setIncludeUnknownOncogenicity(true); + assertTrue(AlterationFilterHelper.build(alterationFilter).isAllDriverAnnotationSelected()); + } + + @Test + public void isNoDriverAnnotationSelected() { + AlterationFilter alterationFilter = new AlterationFilter(); + alterationFilter.setIncludeDriver(false); + alterationFilter.setIncludeVUS(false); + alterationFilter.setIncludeUnknownOncogenicity(false); + assertTrue(AlterationFilterHelper.build(alterationFilter).isNoDriverAnnotationSelected()); + } + + @Test + public void isSomeDriverAnnotationsSelected() { + AlterationFilter alterationFilter = new AlterationFilter(); + alterationFilter.setIncludeDriver(true); + alterationFilter.setIncludeVUS(false); + alterationFilter.setIncludeUnknownOncogenicity(false); + assertTrue(AlterationFilterHelper.build(alterationFilter).isSomeDriverAnnotationsSelected()); + } + + @Test + public void isAllMutationStatusSelected() { + AlterationFilter alterationFilter = new AlterationFilter(); + alterationFilter.setIncludeGermline(true); + alterationFilter.setIncludeSomatic(true); + alterationFilter.setIncludeUnknownStatus(true); + assertTrue(AlterationFilterHelper.build(alterationFilter).isAllMutationStatusSelected()); + } + + @Test + public void isNoMutationStatusSelected() { + AlterationFilter alterationFilter = new AlterationFilter(); + alterationFilter.setIncludeGermline(false); + alterationFilter.setIncludeSomatic(false); + alterationFilter.setIncludeUnknownStatus(false); + assertTrue(AlterationFilterHelper.build(alterationFilter).isNoMutationStatusSelected()); + } + + @Test + public void isSomeMutationStatusSelected() { + AlterationFilter alterationFilter = new AlterationFilter(); + alterationFilter.setIncludeGermline(false); + alterationFilter.setIncludeSomatic(true); + alterationFilter.setIncludeUnknownStatus(false); + assertTrue(AlterationFilterHelper.build(alterationFilter).isSomeMutationStatusSelected()); + } + + @Test + public void isAllTierOptionsSelected() { + AlterationFilter alterationFilter = new AlterationFilter(); + Map tiersMap = new HashMap<>(); + alterationFilter.setTiersBooleanMap(tiersMap); + alterationFilter.setIncludeUnknownTier(true); + assertTrue(AlterationFilterHelper.build(alterationFilter).isAllTierOptionsSelected()); + } + + @Test + public void shouldApply() { + AlterationFilter alterationFilter = new AlterationFilter(); + alterationFilter.setIncludeDriver(true); + alterationFilter.setIncludeVUS(false); + alterationFilter.setIncludeUnknownOncogenicity(false); + assertTrue( + AlterationFilterHelper.build(alterationFilter).shouldApplyMutationAlterationFilter()); + } +} diff --git a/src/test/java/org/cbioportal/legacy/persistence/helper/StudyViewFilterHelperTest.java b/src/test/java/org/cbioportal/legacy/persistence/helper/StudyViewFilterHelperTest.java new file mode 100644 index 00000000000..68bba5304f6 --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/persistence/helper/StudyViewFilterHelperTest.java @@ -0,0 +1,227 @@ +package org.cbioportal.legacy.persistence.helper; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.List; +import org.cbioportal.legacy.web.parameter.DataFilterValue; +import org.cbioportal.legacy.web.parameter.GenomicDataFilter; +import org.junit.Test; + +public class StudyViewFilterHelperTest { + + // (-5, -1], (-1, 3], (3, 7] -> (-5, 7] + @Test + public void testMergeDataFilterNumericalContinuousValues() { + List genomicDataFilters = new ArrayList<>(); + List values = new ArrayList<>(); + values.add(new DataFilterValue(BigDecimal.valueOf(-5), BigDecimal.valueOf(-1))); + values.add(new DataFilterValue(BigDecimal.valueOf(-1), BigDecimal.valueOf(3))); + values.add(new DataFilterValue(BigDecimal.valueOf(3), BigDecimal.valueOf(7))); + genomicDataFilters.add(new GenomicDataFilter(null, null, values)); + + List mergedGenomicDataFilters = + StudyViewFilterHelper.mergeDataFilters(genomicDataFilters); + List mergedDataFilterValues = mergedGenomicDataFilters.getFirst().getValues(); + BigDecimal start = mergedDataFilterValues.getFirst().getStart(); + BigDecimal end = mergedDataFilterValues.getFirst().getEnd(); + assertEquals(0, BigDecimal.valueOf(-5).compareTo(start)); + assertEquals(0, BigDecimal.valueOf(7).compareTo(end)); + } + + // (-2.5, -2.25], (-2.25, -2], (-1.75, -1.5], (-1.5, -1.25] -> (-2.5, -2], (-1.75, -1.25] + @Test + public void testMergeDataFilterNumericalDiscontinuousValues() { + List genomicDataFilters = new ArrayList<>(); + List values = new ArrayList<>(); + values.add(new DataFilterValue(BigDecimal.valueOf(-2.5), BigDecimal.valueOf(-2.25))); + values.add(new DataFilterValue(BigDecimal.valueOf(-2.25), BigDecimal.valueOf(-2))); + values.add(new DataFilterValue(BigDecimal.valueOf(-1.75), BigDecimal.valueOf(-1.5))); + values.add(new DataFilterValue(BigDecimal.valueOf(-1.5), BigDecimal.valueOf(-1.25))); + genomicDataFilters.add(new GenomicDataFilter(null, null, values)); + + List mergedGenomicDataFilters = + StudyViewFilterHelper.mergeDataFilters(genomicDataFilters); + List mergedDataFilterValues = mergedGenomicDataFilters.getFirst().getValues(); + BigDecimal firstStart = mergedDataFilterValues.getFirst().getStart(); + BigDecimal firstEnd = mergedDataFilterValues.getFirst().getEnd(); + assertEquals(0, BigDecimal.valueOf(-2.5).compareTo(firstStart)); + assertEquals(0, BigDecimal.valueOf(-2).compareTo(firstEnd)); + + BigDecimal secondStart = mergedDataFilterValues.get(1).getStart(); + BigDecimal secondEnd = mergedDataFilterValues.get(1).getEnd(); + assertEquals(0, BigDecimal.valueOf(-1.75).compareTo(secondStart)); + assertEquals(0, BigDecimal.valueOf(-1.25).compareTo(secondEnd)); + } + + // (null, -2.25], (-2.25, -2], (-2, null] -> (null, null] + @Test + public void testMergeDataFilterNumericalInfiniteValues() { + List genomicDataFilters = new ArrayList<>(); + List values = new ArrayList<>(); + values.add(new DataFilterValue(null, BigDecimal.valueOf(-2.25))); + values.add(new DataFilterValue(BigDecimal.valueOf(-2.25), BigDecimal.valueOf(-2))); + values.add(new DataFilterValue(BigDecimal.valueOf(-2), null)); + genomicDataFilters.add(new GenomicDataFilter(null, null, values)); + + List mergedGenomicDataFilters = + StudyViewFilterHelper.mergeDataFilters(genomicDataFilters); + List mergedDataFilterValues = mergedGenomicDataFilters.getFirst().getValues(); + BigDecimal start = mergedDataFilterValues.getFirst().getStart(); + BigDecimal end = mergedDataFilterValues.getFirst().getEnd(); + assertNull(start); + assertNull(end); + } + + // (-2.5, -2.25], (-2.25, -2], "NA" -> (-2.5, -1.75], "NA" + // This test also ensures the non-numerical values gets moved to the end + @Test + public void testMergeDataFilterNumericalNonNumericalValues() { + List genomicDataFilters = new ArrayList<>(); + List values = new ArrayList<>(); + values.add(new DataFilterValue(BigDecimal.valueOf(-2.5), BigDecimal.valueOf(-2.25))); + values.add(new DataFilterValue(BigDecimal.valueOf(-2.25), BigDecimal.valueOf(-2))); + values.add(new DataFilterValue("NA")); + genomicDataFilters.add(new GenomicDataFilter(null, null, values)); + + List mergedGenomicDataFilters = + StudyViewFilterHelper.mergeDataFilters(genomicDataFilters); + List mergedDataFilterValues = mergedGenomicDataFilters.getFirst().getValues(); + BigDecimal start = mergedDataFilterValues.getFirst().getStart(); + BigDecimal end = mergedDataFilterValues.getFirst().getEnd(); + String value = mergedDataFilterValues.get(1).getValue(); + assertEquals(0, BigDecimal.valueOf(-2.5).compareTo(start)); + assertEquals(0, BigDecimal.valueOf(-2).compareTo(end)); + assertEquals("NA", value); + } + + // "NA" -> "NA" + @Test + public void testMergeDataFilterNonNumericalOnlyValues() { + List genomicDataFilters = new ArrayList<>(); + List values = new ArrayList<>(); + values.add(new DataFilterValue("NA")); + genomicDataFilters.add(new GenomicDataFilter(null, null, values)); + + List mergedGenomicDataFilters = + StudyViewFilterHelper.mergeDataFilters(genomicDataFilters); + List mergedDataFilterValues = mergedGenomicDataFilters.getFirst().getValues(); + String value = mergedDataFilterValues.getFirst().getValue(); + assertEquals("NA", value); + } + + // invalid null / empty -> unprocessed null / empty + @Test + public void testMergeDataFilterEmptyValidation() { + List mergedUninstantiatedFilters = + StudyViewFilterHelper.mergeDataFilters(null); + assertNull(mergedUninstantiatedFilters); + + List mergedEmptyFilters = + StudyViewFilterHelper.mergeDataFilters(new ArrayList<>()); + assertEquals(0, mergedEmptyFilters.size()); + + List uninstantiatedDataFilters = new ArrayList<>(); + uninstantiatedDataFilters.add(null); + List mergedUninstantiatedDataFilters = + StudyViewFilterHelper.mergeDataFilters(uninstantiatedDataFilters); + assertNull(mergedUninstantiatedDataFilters.getFirst()); + + List uninstantiatedValueFilters = new ArrayList<>(); + uninstantiatedValueFilters.add(new GenomicDataFilter(null, null, null)); + List mergedUninstantiatedValueFilters = + StudyViewFilterHelper.mergeDataFilters(uninstantiatedValueFilters); + assertNull(mergedUninstantiatedValueFilters.getFirst().getValues()); + + List emptyValueFilters = new ArrayList<>(); + emptyValueFilters.add(new GenomicDataFilter(null, null, new ArrayList<>())); + List mergedEmptyValueFilters = + StudyViewFilterHelper.mergeDataFilters(emptyValueFilters); + assertEquals(0, mergedEmptyValueFilters.getFirst().getValues().size()); + } + + // invalid (2, 3, "NA"] -> unprocessed (2, 3, "NA"] + @Test + public void testMergeDataFilterNonNumericalValidation() { + List genomicDataFilters = new ArrayList<>(); + List invalidValues = new ArrayList<>(); + DataFilterValue invalidValue = new DataFilterValue("NA"); + invalidValue.setStart(BigDecimal.valueOf(2)); + invalidValue.setEnd(BigDecimal.valueOf(3)); + invalidValues.add(invalidValue); + genomicDataFilters.add(new GenomicDataFilter(null, null, invalidValues)); + + List mergedGenomicDataFilters = + StudyViewFilterHelper.mergeDataFilters(genomicDataFilters); + List mergedDataFilterValues = mergedGenomicDataFilters.getFirst().getValues(); + BigDecimal start = mergedDataFilterValues.getFirst().getStart(); + BigDecimal end = mergedDataFilterValues.getFirst().getEnd(); + String value = mergedDataFilterValues.getFirst().getValue(); + assertEquals(0, BigDecimal.valueOf(2).compareTo(start)); + assertEquals(0, BigDecimal.valueOf(3).compareTo(end)); + assertEquals("NA", value); + } + + // invalid (42, 6] -> unprocessed (42, 6] + @Test + public void testMergeDataFilterRangeValidation() { + List genomicDataFilters = new ArrayList<>(); + List invalidValues = new ArrayList<>(); + invalidValues.add(new DataFilterValue(BigDecimal.valueOf(42), BigDecimal.valueOf(6))); + genomicDataFilters.add(new GenomicDataFilter(null, null, invalidValues)); + + List mergedGenomicDataFilters = + StudyViewFilterHelper.mergeDataFilters(genomicDataFilters); + List mergedDataFilterValues = mergedGenomicDataFilters.getFirst().getValues(); + BigDecimal start = mergedDataFilterValues.getFirst().getStart(); + BigDecimal end = mergedDataFilterValues.getFirst().getEnd(); + assertEquals(0, BigDecimal.valueOf(42).compareTo(start)); + assertEquals(0, BigDecimal.valueOf(6).compareTo(end)); + } + + // invalid (3, 5], (1, 3] -> unprocessed (3, 5], (1, 3] + @Test + public void testMergeDataFilterContinuousValidation() { + List genomicDataFilters = new ArrayList<>(); + List values = new ArrayList<>(); + values.add(new DataFilterValue(BigDecimal.valueOf(3), BigDecimal.valueOf(5))); + values.add(new DataFilterValue(BigDecimal.valueOf(1), BigDecimal.valueOf(3))); + genomicDataFilters.add(new GenomicDataFilter(null, null, values)); + + List mergedGenomicDataFilters = + StudyViewFilterHelper.mergeDataFilters(genomicDataFilters); + List mergedDataFilterValues = mergedGenomicDataFilters.getFirst().getValues(); + BigDecimal firstStart = mergedDataFilterValues.getFirst().getStart(); + BigDecimal firstEnd = mergedDataFilterValues.getFirst().getEnd(); + assertEquals(0, BigDecimal.valueOf(3).compareTo(firstStart)); + assertEquals(0, BigDecimal.valueOf(5).compareTo(firstEnd)); + BigDecimal secondStart = mergedDataFilterValues.get(1).getStart(); + BigDecimal secondEnd = mergedDataFilterValues.get(1).getEnd(); + assertEquals(0, BigDecimal.valueOf(1).compareTo(secondStart)); + assertEquals(0, BigDecimal.valueOf(3).compareTo(secondEnd)); + } + + // invalid (3, 5], (2, 4] -> unprocessed (3, 5], (2, 4] + @Test + public void testMergeDataFilterNoOverlapValidation() { + List genomicDataFilters = new ArrayList<>(); + List values = new ArrayList<>(); + values.add(new DataFilterValue(BigDecimal.valueOf(3), BigDecimal.valueOf(5))); + values.add(new DataFilterValue(BigDecimal.valueOf(2), BigDecimal.valueOf(4))); + genomicDataFilters.add(new GenomicDataFilter(null, null, values)); + + List mergedGenomicDataFilters = + StudyViewFilterHelper.mergeDataFilters(genomicDataFilters); + List mergedDataFilterValues = mergedGenomicDataFilters.getFirst().getValues(); + BigDecimal firstStart = mergedDataFilterValues.getFirst().getStart(); + BigDecimal firstEnd = mergedDataFilterValues.getFirst().getEnd(); + assertEquals(0, BigDecimal.valueOf(3).compareTo(firstStart)); + assertEquals(0, BigDecimal.valueOf(5).compareTo(firstEnd)); + BigDecimal secondStart = mergedDataFilterValues.get(1).getStart(); + BigDecimal secondEnd = mergedDataFilterValues.get(1).getEnd(); + assertEquals(0, BigDecimal.valueOf(2).compareTo(secondStart)); + assertEquals(0, BigDecimal.valueOf(4).compareTo(secondEnd)); + } +} diff --git a/src/test/java/org/cbioportal/legacy/persistence/mybatis/AlterationDriverAnnotationMyBatisRepositoryTest.java b/src/test/java/org/cbioportal/legacy/persistence/mybatis/AlterationDriverAnnotationMyBatisRepositoryTest.java new file mode 100644 index 00000000000..36a5d73e81d --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/persistence/mybatis/AlterationDriverAnnotationMyBatisRepositoryTest.java @@ -0,0 +1,55 @@ +package org.cbioportal.legacy.persistence.mybatis; + +import java.util.Arrays; +import java.util.List; +import org.cbioportal.legacy.model.AlterationDriverAnnotation; +import org.cbioportal.legacy.persistence.mybatis.config.TestConfig; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +@RunWith(SpringJUnit4ClassRunner.class) +@SpringBootTest(classes = {AlterationDriverAnnotationMyBatisRepository.class, TestConfig.class}) +public class AlterationDriverAnnotationMyBatisRepositoryTest { + + @Autowired + private AlterationDriverAnnotationMyBatisRepository alterationDriverAnnotationMyBatisRepository; + + @Test + public void getAlterationDriverAnnotationsCna() { + List molecularProfileIds = Arrays.asList("study_tcga_pub_gistic"); + List annotations = + alterationDriverAnnotationMyBatisRepository.getAlterationDriverAnnotations( + molecularProfileIds); + Assert.assertEquals(2, annotations.size()); + } + + @Test + public void getAlterationDriverAnnotationsMutations() { + List molecularProfileIds = Arrays.asList("study_tcga_pub_mutations"); + List annotations = + alterationDriverAnnotationMyBatisRepository.getAlterationDriverAnnotations( + molecularProfileIds); + Assert.assertEquals(8, annotations.size()); + } + + @Test + public void getAlterationDriverAnnotationsAll() { + List molecularProfileIds = + Arrays.asList("study_tcga_pub_gistic", "study_tcga_pub_mutations"); + List annotations = + alterationDriverAnnotationMyBatisRepository.getAlterationDriverAnnotations( + molecularProfileIds); + Assert.assertEquals(10, annotations.size()); + } + + @Test + public void getAlterationDriverAnnotationsNull() { + List annotations = + alterationDriverAnnotationMyBatisRepository.getAlterationDriverAnnotations(null); + Assert.assertEquals(0, annotations.size()); + } +} diff --git a/src/test/java/org/cbioportal/legacy/persistence/mybatis/AlterationMyBatisRepositoryTest.java b/src/test/java/org/cbioportal/legacy/persistence/mybatis/AlterationMyBatisRepositoryTest.java new file mode 100644 index 00000000000..8be9921221c --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/persistence/mybatis/AlterationMyBatisRepositoryTest.java @@ -0,0 +1,1313 @@ +package org.cbioportal.legacy.persistence.mybatis; + +import java.util.Arrays; +import java.util.List; +import java.util.Set; +import java.util.TreeSet; +import org.cbioportal.legacy.model.AlterationCountByGene; +import org.cbioportal.legacy.model.AlterationCountByStructuralVariant; +import org.cbioportal.legacy.model.AlterationFilter; +import org.cbioportal.legacy.model.CNA; +import org.cbioportal.legacy.model.CopyNumberCountByGene; +import org.cbioportal.legacy.model.MolecularProfileCaseIdentifier; +import org.cbioportal.legacy.model.MutationEventType; +import org.cbioportal.legacy.model.util.Select; +import org.cbioportal.legacy.persistence.mybatis.config.TestConfig; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +@RunWith(SpringJUnit4ClassRunner.class) +@SpringBootTest( + classes = { + AlterationMyBatisRepository.class, + MolecularProfileMyBatisRepository.class, + TestConfig.class + }) +public class AlterationMyBatisRepositoryTest { + + // mutation and cna events in testSql.sql + // SAMPLE_ID, ENTREZ_GENE_ID, HUGO_GENE_SYMBOL, GENETIC_PROFILE_ID, TYPE, + // MUTATIONio_TYPE, DRIVER_FILTER, DRIVER_TIERS_FILTER, PATIENT_ID, MUTATION_TYPE + // 1 207 AKT1 2 CNA -2 Putative_Driver Tier 1 + // TCGA-A1-A0SB germline + // 2 207 AKT1 2 CNA 2 Putative_Passenger Tier 2 + // TCGA-A1-A0SD germline + // 1 207 AKT1 6 MUTATION Nonsense_Mutation Putative_Driver Tier 1 + // TCGA-A1-A0SB germline + // 2 207 AKT1 6 MUTATION Missense_Mutation Putative_Passenger Tier 2 + // TCGA-A1-A0SD germline + // 1 208 AKT2 2 CNA 2 TCGA-A1-A0SB + // germline + // 3 208 AKT2 6 MUTATION Splice_Site Putative_Passenger Tier 1 + // TCGA-A1-A0SE germline + // 6 672 BRCA1 6 MUTATION Missense_Mutation Putative_Passenger Tier 2 + // TCGA-A1-A0SH germline + // 6 672 BRCA1 6 MUTATION Nonsense_Mutation Putative_Driver Tier 1 + // TCGA-A1-A0SH NA + // 7 672 BRCA1 6 MUTATION Nonsense_Mutation Putative_Driver Tier 2 + // TCGA-A1-A0SI germline + // 12 672 BRCA1 6 MUTATION Splice_Site Putative_Passenger Tier 1 + // TCGA-A1-A0SO germline + // 13 672 BRCA1 6 MUTATION Splice_Site Putative_Driver Tier 1 + // TCGA-A1-A0SP germline + + // structural_variant table in testSql.sql + // SAMPLE_ID, ENTREZ_GENE_ID, HUGO_GENE_SYMBOL, GENETIC_PROFILE_ID, TYPE, MUTATION_TYPE, + // DRIVER_FILTER, DRIVER_TIERS_FILTER, PATIENT_ID, MUTATION_TYPE + // 1 27436-238 EML4-ALK 7 SV Fusion + // TCGA-A1-A0SB germline + // 2 27436-238 EML4-ALK 7 SV Fusion + // TCGA-A1-A0SD somatic + // 1 57670-673 KIAA..-BRAF 7 SV Fusion + // TCGA-A1-A0SB somatic + // 2 57670-673 KIAA..-BRAF 7 SV Fusion + // TCGA-A1-A0SD germline + // 2 57670-673 KIAA..-BRAF 7 SV Fusion + // TCGA-A1-A0SD somatic + // 15 57670-673 KIAA..-BRAF 13 SV Fusion + // TCGA-A1-A0SD somatic + // 1 8031-5979 NCOA4-RET 7 SV Fusion + // TCGA-A1-A0SB somatic + // 15 8031-5979 NCOA4-RET 13 SV Fusion + // TCGA-A1-A0SB somatic + // 15 7113-2078 TMPRSS2-ERG 7 SV Fusion + // TCGA-A1-A0SB somatic + // 15 8031- NCOA4- 13 SV Fusion + // TCGA-A1-A0SB somatic + + @Autowired private AlterationMyBatisRepository alterationMyBatisRepository; + + Select mutationEventTypes = + Select.byValues( + Arrays.asList( + MutationEventType.splice_site, + MutationEventType.nonsense_mutation, + MutationEventType.missense_mutation)); + Select cnaEventTypes = Select.byValues(Arrays.asList(CNA.AMP, CNA.HOMDEL)); + Set sampleIdToProfileId = new TreeSet<>(); + Set svSampleIdToProfileId = new TreeSet<>(); + Set patientIdToProfileId = new TreeSet<>(); + Set svPatientIdToProfileId = new TreeSet<>(); + AlterationFilter alterationFilter; + + Select entrezGeneIds; + Select svEntrezGeneIds; + + @Before + public void setup() { + + sampleIdToProfileId.add( + new MolecularProfileCaseIdentifier("TCGA-A1-A0SB-01", "study_tcga_pub_mutations")); + sampleIdToProfileId.add( + new MolecularProfileCaseIdentifier("TCGA-A1-A0SE-01", "study_tcga_pub_mutations")); + sampleIdToProfileId.add( + new MolecularProfileCaseIdentifier("TCGA-A1-A0SH-01", "study_tcga_pub_mutations")); + sampleIdToProfileId.add( + new MolecularProfileCaseIdentifier("TCGA-A1-A0SI-01", "study_tcga_pub_mutations")); + sampleIdToProfileId.add( + new MolecularProfileCaseIdentifier("TCGA-A1-A0SO-01", "study_tcga_pub_mutations")); + sampleIdToProfileId.add( + new MolecularProfileCaseIdentifier("TCGA-A1-A0SP-01", "study_tcga_pub_mutations")); + sampleIdToProfileId.add( + new MolecularProfileCaseIdentifier("TCGA-A1-A0SD-01", "study_tcga_pub_mutations")); + sampleIdToProfileId.add( + new MolecularProfileCaseIdentifier("TCGA-A1-A0SB-01", "study_tcga_pub_gistic")); + sampleIdToProfileId.add( + new MolecularProfileCaseIdentifier("TCGA-A1-A0SD-01", "study_tcga_pub_gistic")); + svSampleIdToProfileId.add( + new MolecularProfileCaseIdentifier("TCGA-A1-A0SB-01", "study_tcga_pub_sv")); + svSampleIdToProfileId.add( + new MolecularProfileCaseIdentifier("TCGA-A1-A0SD-01", "study_tcga_pub_sv")); + svSampleIdToProfileId.add(new MolecularProfileCaseIdentifier("TCGA-A1-B0SO-01", "acc_tcga_sv")); + + patientIdToProfileId.add( + new MolecularProfileCaseIdentifier("TCGA-A1-A0SB", "study_tcga_pub_mutations")); + patientIdToProfileId.add( + new MolecularProfileCaseIdentifier("TCGA-A1-A0SE", "study_tcga_pub_mutations")); + patientIdToProfileId.add( + new MolecularProfileCaseIdentifier("TCGA-A1-A0SH", "study_tcga_pub_mutations")); + patientIdToProfileId.add( + new MolecularProfileCaseIdentifier("TCGA-A1-A0SI", "study_tcga_pub_mutations")); + patientIdToProfileId.add( + new MolecularProfileCaseIdentifier("TCGA-A1-A0SO", "study_tcga_pub_mutations")); + patientIdToProfileId.add( + new MolecularProfileCaseIdentifier("TCGA-A1-A0SP", "study_tcga_pub_mutations")); + patientIdToProfileId.add( + new MolecularProfileCaseIdentifier("TCGA-A1-A0SD", "study_tcga_pub_mutations")); + patientIdToProfileId.add( + new MolecularProfileCaseIdentifier("TCGA-A1-A0SB", "study_tcga_pub_gistic")); + patientIdToProfileId.add( + new MolecularProfileCaseIdentifier("TCGA-A1-A0SD", "study_tcga_pub_gistic")); + svPatientIdToProfileId.add( + new MolecularProfileCaseIdentifier("TCGA-A1-A0SB", "study_tcga_pub_sv")); + svPatientIdToProfileId.add( + new MolecularProfileCaseIdentifier("TCGA-A1-A0SD", "study_tcga_pub_sv")); + svPatientIdToProfileId.add(new MolecularProfileCaseIdentifier("TCGA-A1-B0SO", "acc_tcga_sv")); + + entrezGeneIds = Select.byValues(Arrays.asList(207, 208, 672, 2064)); + svEntrezGeneIds = Select.byValues(Arrays.asList(57670, 8031, 27436, 7113)); + alterationFilter = + new AlterationFilter( + mutationEventTypes, + cnaEventTypes, + true, + true, + true, + true, + true, + true, + Select.all(), + true); + } + + @Test + public void getSampleMutationGeneCountAllDriverAnnotationsExcluded() throws Exception { + alterationFilter.setIncludeDriver(false); + alterationFilter.setIncludeVUS(false); + alterationFilter.setIncludeUnknownOncogenicity(false); + alterationFilter.setCnaTypeSelect(Select.none()); + List result = + alterationMyBatisRepository.getSampleAlterationGeneCounts( + sampleIdToProfileId, entrezGeneIds, alterationFilter); + Assert.assertEquals(0, result.size()); + } + + @Test + public void getSampleMutationGeneCountAllDriverTiersExcluded() throws Exception { + alterationFilter.setSelectedTiers(Select.none()); + alterationFilter.setIncludeUnknownTier(false); + alterationFilter.setCnaTypeSelect(Select.none()); + List result = + alterationMyBatisRepository.getSampleAlterationGeneCounts( + new TreeSet<>(sampleIdToProfileId), entrezGeneIds, alterationFilter); + Assert.assertEquals(0, result.size()); + } + + @Test + public void getSampleMutationGeneCountAllDriverTiersExcludedWithNullSelect() throws Exception { + alterationFilter.setSelectedTiers(null); + alterationFilter.setIncludeUnknownTier(false); + alterationFilter.setCnaTypeSelect(Select.none()); + List result = + alterationMyBatisRepository.getSampleAlterationGeneCounts( + sampleIdToProfileId, entrezGeneIds, alterationFilter); + Assert.assertEquals(0, result.size()); + } + + @Test + public void getSampleMutationGeneCountAllMutationStatusExcluded() throws Exception { + alterationFilter.setIncludeSomatic(false); + alterationFilter.setIncludeGermline(false); + alterationFilter.setIncludeUnknownStatus(false); + alterationFilter.setCnaTypeSelect(Select.none()); + List result = + alterationMyBatisRepository.getSampleAlterationGeneCounts( + sampleIdToProfileId, entrezGeneIds, alterationFilter); + Assert.assertEquals(0, result.size()); + } + + @Test + public void getSampleMutationGeneCount() throws Exception { + alterationFilter.setCnaTypeSelect(Select.none()); + List result = + alterationMyBatisRepository.getSampleAlterationGeneCounts( + sampleIdToProfileId, entrezGeneIds, alterationFilter); + + Assert.assertEquals(3, result.size()); + AlterationCountByGene result672 = + result.stream().filter(r -> r.getEntrezGeneId() == 672).findFirst().get(); + AlterationCountByGene result207 = + result.stream().filter(r -> r.getEntrezGeneId() == 207).findFirst().get(); + AlterationCountByGene result208 = + result.stream().filter(r -> r.getEntrezGeneId() == 208).findFirst().get(); + Assert.assertEquals((Integer) 5, result672.getTotalCount()); + Assert.assertEquals((Integer) 4, result672.getNumberOfAlteredCases()); + Assert.assertEquals((Integer) 2, result207.getTotalCount()); + Assert.assertEquals((Integer) 2, result207.getNumberOfAlteredCases()); + Assert.assertEquals((Integer) 1, result208.getTotalCount()); + Assert.assertEquals((Integer) 1, result208.getNumberOfAlteredCases()); + } + + @Test + public void getSampleCnaGeneCount() throws Exception { + alterationFilter.setMutationTypeSelect(Select.none()); + List result = + alterationMyBatisRepository.getSampleAlterationGeneCounts( + sampleIdToProfileId, entrezGeneIds, alterationFilter); + + Assert.assertEquals(2, result.size()); + AlterationCountByGene result207 = + result.stream().filter(r -> r.getEntrezGeneId() == 207).findFirst().get(); + AlterationCountByGene result208 = + result.stream().filter(r -> r.getEntrezGeneId() == 208).findFirst().get(); + Assert.assertEquals((Integer) 2, result207.getTotalCount()); + Assert.assertEquals((Integer) 2, result207.getNumberOfAlteredCases()); + Assert.assertEquals((Integer) 1, result208.getTotalCount()); + Assert.assertEquals((Integer) 1, result208.getNumberOfAlteredCases()); + } + + @Test + public void getSampleMutationAndCnaGeneCount() throws Exception { + List result = + alterationMyBatisRepository.getSampleAlterationGeneCounts( + sampleIdToProfileId, entrezGeneIds, alterationFilter); + + Assert.assertEquals(3, result.size()); + AlterationCountByGene result672 = + result.stream().filter(r -> r.getEntrezGeneId() == 672).findFirst().get(); + AlterationCountByGene result207 = + result.stream().filter(r -> r.getEntrezGeneId() == 207).findFirst().get(); + AlterationCountByGene result208 = + result.stream().filter(r -> r.getEntrezGeneId() == 208).findFirst().get(); + Assert.assertEquals((Integer) 5, result672.getTotalCount()); + Assert.assertEquals((Integer) 4, result672.getNumberOfAlteredCases()); + Assert.assertEquals((Integer) 4, result207.getTotalCount()); + Assert.assertEquals((Integer) 2, result207.getNumberOfAlteredCases()); + Assert.assertEquals((Integer) 2, result208.getTotalCount()); + Assert.assertEquals((Integer) 2, result208.getNumberOfAlteredCases()); + } + + @Test + public void whenSampleNotProfiledForCNA() throws Exception { + + Set sampleIdToProfileId = new TreeSet<>(); + // Sample is not profiled for mutations and not cna + sampleIdToProfileId.add( + new MolecularProfileCaseIdentifier("TCGA-A1-A0SE-01", "study_tcga_pub_gistic")); + + List result = + alterationMyBatisRepository.getSampleAlterationGeneCounts( + sampleIdToProfileId, entrezGeneIds, alterationFilter); + Assert.assertEquals(0, result.size()); + } + + @Test + public void getPatientCnaGeneCountAllDriverAnnotationsExcluded() throws Exception { + alterationFilter.setIncludeDriver(false); + alterationFilter.setIncludeVUS(false); + alterationFilter.setIncludeUnknownOncogenicity(false); + alterationFilter.setMutationTypeSelect(Select.none()); + List result = + alterationMyBatisRepository.getPatientAlterationGeneCounts( + patientIdToProfileId, entrezGeneIds, alterationFilter); + Assert.assertEquals(0, result.size()); + } + + @Test + public void getPatientCnaGeneCountAllDriverTiersExcluded() throws Exception { + alterationFilter.setSelectedTiers(Select.none()); + alterationFilter.setIncludeUnknownTier(false); + alterationFilter.setMutationTypeSelect(Select.none()); + List result = + alterationMyBatisRepository.getPatientAlterationGeneCounts( + patientIdToProfileId, entrezGeneIds, alterationFilter); + Assert.assertEquals(0, result.size()); + } + + @Test + public void getPatientCnaGeneCountAllDriverTiersExcludedNullSelect() throws Exception { + alterationFilter.setSelectedTiers(null); + alterationFilter.setIncludeUnknownTier(false); + alterationFilter.setMutationTypeSelect(Select.none()); + List result = + alterationMyBatisRepository.getPatientAlterationGeneCounts( + patientIdToProfileId, entrezGeneIds, alterationFilter); + Assert.assertEquals(0, result.size()); + } + + @Test + public void getPatientCnaGeneCount() throws Exception { + alterationFilter.setMutationTypeSelect(Select.none()); + List result = + alterationMyBatisRepository.getPatientAlterationGeneCounts( + patientIdToProfileId, entrezGeneIds, alterationFilter); + + // For testSql.sql there are no more samples per patient for the investigated genes. + // Therefore, patient level counts are the same as the sample level counts. + Assert.assertEquals(2, result.size()); + AlterationCountByGene result207 = + result.stream().filter(r -> r.getEntrezGeneId() == 207).findFirst().get(); + AlterationCountByGene result208 = + result.stream().filter(r -> r.getEntrezGeneId() == 208).findFirst().get(); + Assert.assertEquals((Integer) 2, result207.getTotalCount()); + Assert.assertEquals((Integer) 2, result207.getNumberOfAlteredCases()); + Assert.assertEquals((Integer) 1, result208.getTotalCount()); + Assert.assertEquals((Integer) 1, result208.getNumberOfAlteredCases()); + } + + @Test + public void getSampleCnaGeneCountLegacy() throws Exception { + + // FIXME: the CnaCountLegacy endpoint is different from the AlterationCount endpoint + // because it returns a single additional value 'cytoband'. It would make sense to + // harmonize these endpoints (both or none return 'cytoband') and use the AlterationCount + // endpoint for all counts. Let's discuss... + List result = + alterationMyBatisRepository.getSampleCnaGeneCounts( + sampleIdToProfileId, entrezGeneIds, alterationFilter); + + Assert.assertEquals(3, result.size()); + AlterationCountByGene result207up = + result.stream() + .filter(r -> r.getEntrezGeneId() == 207 && r.getAlteration() == 2) + .findFirst() + .get(); + AlterationCountByGene result207down = + result.stream() + .filter(r -> r.getEntrezGeneId() == 207 && r.getAlteration() == -2) + .findFirst() + .get(); + AlterationCountByGene result208up = + result.stream().filter(r -> r.getEntrezGeneId() == 208).findFirst().get(); + Assert.assertEquals((Integer) 1, result207up.getNumberOfAlteredCases()); + Assert.assertEquals((Integer) 1, result207down.getNumberOfAlteredCases()); + Assert.assertEquals((Integer) 1, result208up.getNumberOfAlteredCases()); + } + + @Test + public void getPatientCnaGeneCountLegacy() throws Exception { + + // FIXME: the CnaCountLegacy endpoint is different from the AlterationCount endpoint + // because it returns a single additional value 'cytoband'. It would make sense to + // harmonize these endpoints (both or none return 'cytoband') and use the AlterationCount + // endpoint for all counts. Let's discuss... + List result = + alterationMyBatisRepository.getPatientCnaGeneCounts( + patientIdToProfileId, entrezGeneIds, alterationFilter); + + // For testSql.sql there are no more samples per patient for the investigated genes. + // Therefore, patient level counts are the same as the sample level counts. + Assert.assertEquals(3, result.size()); + AlterationCountByGene result207up = + result.stream() + .filter(r -> r.getEntrezGeneId() == 207 && r.getAlteration() == 2) + .findFirst() + .get(); + AlterationCountByGene result207down = + result.stream() + .filter(r -> r.getEntrezGeneId() == 207 && r.getAlteration() == -2) + .findFirst() + .get(); + AlterationCountByGene result208up = + result.stream().filter(r -> r.getEntrezGeneId() == 208).findFirst().get(); + Assert.assertEquals((Integer) 1, result207up.getNumberOfAlteredCases()); + Assert.assertEquals((Integer) 1, result207down.getNumberOfAlteredCases()); + Assert.assertEquals((Integer) 1, result208up.getNumberOfAlteredCases()); + } + + @Test + public void getSampleAlterationGeneCountsReturnsZeroForMutationsAndCnaSelectorsInNone() { + alterationFilter.setCnaTypeSelect(Select.none()); + alterationFilter.setMutationTypeSelect(Select.none()); + alterationFilter.setStructuralVariants(false); + List result = + alterationMyBatisRepository.getSampleAlterationGeneCounts( + sampleIdToProfileId, entrezGeneIds, alterationFilter); + + Assert.assertEquals(0, result.size()); + } + + @Test + public void getSampleAlterationGeneCountsReturnsAllForMutationsAndCnaSelectorsInAll() { + alterationFilter.setCnaTypeSelect(Select.all()); + alterationFilter.setMutationTypeSelect(Select.all()); + List result = + alterationMyBatisRepository.getSampleAlterationGeneCounts( + sampleIdToProfileId, entrezGeneIds, alterationFilter); + + Assert.assertEquals(3, result.size()); + } + + @Test + public void getSampleGeneCountNullIds() throws Exception { + List result = + alterationMyBatisRepository.getSampleAlterationGeneCounts( + null, entrezGeneIds, new AlterationFilter()); + Assert.assertEquals(0, result.size()); + } + + @Test + public void getPatientGeneCountNullIds() throws Exception { + List result = + alterationMyBatisRepository.getPatientAlterationGeneCounts( + null, entrezGeneIds, new AlterationFilter()); + Assert.assertEquals(0, result.size()); + } + + @Test + public void getSampleCnaGeneCountNullIds() throws Exception { + List result = + alterationMyBatisRepository.getSampleCnaGeneCounts( + null, entrezGeneIds, new AlterationFilter()); + Assert.assertEquals(0, result.size()); + } + + @Test + public void getSampleGeneCountIncludeOnlyDriver() throws Exception { + alterationFilter.setIncludeVUS(false); + alterationFilter.setIncludeUnknownOncogenicity(false); + List result = + alterationMyBatisRepository.getSampleAlterationGeneCounts( + sampleIdToProfileId, entrezGeneIds, alterationFilter); + + Assert.assertEquals(2, result.size()); + AlterationCountByGene result672 = + result.stream().filter(r -> r.getEntrezGeneId() == 672).findFirst().get(); + AlterationCountByGene result207 = + result.stream().filter(r -> r.getEntrezGeneId() == 207).findFirst().get(); + Assert.assertEquals((Integer) 3, result672.getTotalCount()); + Assert.assertEquals((Integer) 3, result672.getNumberOfAlteredCases()); + Assert.assertEquals((Integer) 2, result207.getTotalCount()); + Assert.assertEquals((Integer) 1, result207.getNumberOfAlteredCases()); + } + + @Test + public void getSampleGeneCountIncludeOnlyVus() throws Exception { + alterationFilter.setIncludeDriver(false); + alterationFilter.setIncludeUnknownOncogenicity(false); + List result = + alterationMyBatisRepository.getSampleAlterationGeneCounts( + sampleIdToProfileId, entrezGeneIds, alterationFilter); + + Assert.assertEquals(3, result.size()); + AlterationCountByGene result672 = + result.stream().filter(r -> r.getEntrezGeneId() == 672).findFirst().get(); + AlterationCountByGene result207 = + result.stream().filter(r -> r.getEntrezGeneId() == 207).findFirst().get(); + AlterationCountByGene result208 = + result.stream().filter(r -> r.getEntrezGeneId() == 208).findFirst().get(); + Assert.assertEquals((Integer) 2, result672.getTotalCount()); + Assert.assertEquals((Integer) 2, result672.getNumberOfAlteredCases()); + Assert.assertEquals((Integer) 2, result207.getTotalCount()); + Assert.assertEquals((Integer) 1, result207.getNumberOfAlteredCases()); + Assert.assertEquals((Integer) 1, result208.getTotalCount()); + Assert.assertEquals((Integer) 1, result208.getNumberOfAlteredCases()); + } + + @Test + public void getSampleGeneCountIncludeOnlyUnknownOncogenicity() throws Exception { + alterationFilter.setIncludeDriver(false); + alterationFilter.setIncludeVUS(false); + List result = + alterationMyBatisRepository.getSampleAlterationGeneCounts( + sampleIdToProfileId, entrezGeneIds, alterationFilter); + + Assert.assertEquals(1, result.size()); + AlterationCountByGene result208 = + result.stream().filter(r -> r.getEntrezGeneId() == 208).findFirst().get(); + Assert.assertEquals((Integer) 1, result208.getTotalCount()); + Assert.assertEquals((Integer) 1, result208.getNumberOfAlteredCases()); + } + + @Test + public void getSampleGeneCountIncludeOnlyTiers() throws Exception { + // All 'Tier 2' tiers are forced to be interpreted as driver events + alterationFilter.setSelectedTiers(Select.byValues(Arrays.asList("Tier 2"))); + alterationFilter.setIncludeUnknownTier(false); + List result = + alterationMyBatisRepository.getSampleAlterationGeneCounts( + sampleIdToProfileId, entrezGeneIds, alterationFilter); + + Assert.assertEquals(2, result.size()); + AlterationCountByGene result672 = + result.stream().filter(r -> r.getEntrezGeneId() == 672).findFirst().get(); + AlterationCountByGene result207 = + result.stream().filter(r -> r.getEntrezGeneId() == 207).findFirst().get(); + Assert.assertEquals((Integer) 2, result672.getTotalCount()); + Assert.assertEquals((Integer) 2, result672.getNumberOfAlteredCases()); + Assert.assertEquals((Integer) 2, result207.getTotalCount()); + Assert.assertEquals((Integer) 1, result207.getNumberOfAlteredCases()); + } + + @Test + public void getSampleGeneCountIncludeUnknownTier() throws Exception { + alterationFilter.setSelectedTiers(Select.none()); + List result = + alterationMyBatisRepository.getSampleAlterationGeneCounts( + sampleIdToProfileId, entrezGeneIds, alterationFilter); + + Assert.assertEquals(1, result.size()); + AlterationCountByGene result208 = + result.stream().filter(r -> r.getEntrezGeneId() == 208).findFirst().get(); + Assert.assertEquals((Integer) 1, result208.getTotalCount()); + Assert.assertEquals((Integer) 1, result208.getNumberOfAlteredCases()); + } + + @Test + public void getPatientMutationAndCnaGeneCount() throws Exception { + List result = + alterationMyBatisRepository.getPatientAlterationGeneCounts( + patientIdToProfileId, entrezGeneIds, alterationFilter); + + // For testSql.sql there are no more samples per patient for the investigated genes. + // Therefore, patient level counts are the same as the sample level counts. + Assert.assertEquals(3, result.size()); + AlterationCountByGene result672 = + result.stream().filter(r -> r.getEntrezGeneId() == 672).findFirst().get(); + AlterationCountByGene result207 = + result.stream().filter(r -> r.getEntrezGeneId() == 207).findFirst().get(); + AlterationCountByGene result208 = + result.stream().filter(r -> r.getEntrezGeneId() == 208).findFirst().get(); + Assert.assertEquals((Integer) 5, result672.getTotalCount()); + Assert.assertEquals((Integer) 4, result672.getNumberOfAlteredCases()); + Assert.assertEquals((Integer) 4, result207.getTotalCount()); + Assert.assertEquals((Integer) 2, result207.getNumberOfAlteredCases()); + Assert.assertEquals((Integer) 2, result208.getTotalCount()); + Assert.assertEquals((Integer) 2, result208.getNumberOfAlteredCases()); + } + + @Test + public void getPatientMutationGeneCountIncludeOnlyGermline() throws Exception { + alterationFilter.setIncludeSomatic(false); + alterationFilter.setIncludeUnknownStatus(false); + alterationFilter.setCnaTypeSelect(Select.none()); + List result = + alterationMyBatisRepository.getPatientAlterationGeneCounts( + patientIdToProfileId, entrezGeneIds, alterationFilter); + // all but one mutations in testSql.sql are Germline mutations + Assert.assertEquals(3, result.size()); + AlterationCountByGene result672 = + result.stream().filter(r -> r.getEntrezGeneId() == 672).findFirst().get(); + AlterationCountByGene result207 = + result.stream().filter(r -> r.getEntrezGeneId() == 207).findFirst().get(); + AlterationCountByGene result208 = + result.stream().filter(r -> r.getEntrezGeneId() == 208).findFirst().get(); + Assert.assertEquals((Integer) 4, result672.getTotalCount()); + Assert.assertEquals((Integer) 4, result672.getNumberOfAlteredCases()); + Assert.assertEquals((Integer) 2, result207.getTotalCount()); + Assert.assertEquals((Integer) 2, result207.getNumberOfAlteredCases()); + Assert.assertEquals((Integer) 1, result208.getTotalCount()); + Assert.assertEquals((Integer) 1, result208.getNumberOfAlteredCases()); + } + + @Test + public void getPatientMutationGeneCountIncludeOnlySomatic() throws Exception { + alterationFilter.setIncludeGermline(false); + alterationFilter.setIncludeUnknownStatus(false); + alterationFilter.setCnaTypeSelect(Select.none()); + List result = + alterationMyBatisRepository.getPatientAlterationGeneCounts( + patientIdToProfileId, entrezGeneIds, alterationFilter); + // all but one mutations in testSql.sql are Germline mutations + Assert.assertEquals(0, result.size()); + } + + @Test + public void getPatientMutationGeneCountIncludeOnlyUnknownStatus() throws Exception { + alterationFilter.setIncludeGermline(false); + alterationFilter.setIncludeSomatic(false); + alterationFilter.setCnaTypeSelect(Select.none()); + List result = + alterationMyBatisRepository.getPatientAlterationGeneCounts( + patientIdToProfileId, entrezGeneIds, alterationFilter); + // all but one mutations in testSql.sql are Germline mutations + Assert.assertEquals(1, result.size()); + } + + @Test + public void getPatientGeneCountIncludeOnlyDriver() throws Exception { + alterationFilter.setIncludeVUS(false); + alterationFilter.setIncludeUnknownOncogenicity(false); + List result = + alterationMyBatisRepository.getPatientAlterationGeneCounts( + patientIdToProfileId, entrezGeneIds, alterationFilter); + + Assert.assertEquals(2, result.size()); + AlterationCountByGene result672 = + result.stream().filter(r -> r.getEntrezGeneId() == 672).findFirst().get(); + AlterationCountByGene result207 = + result.stream().filter(r -> r.getEntrezGeneId() == 207).findFirst().get(); + Assert.assertEquals((Integer) 3, result672.getTotalCount()); + Assert.assertEquals((Integer) 3, result672.getNumberOfAlteredCases()); + Assert.assertEquals((Integer) 2, result207.getTotalCount()); + Assert.assertEquals((Integer) 1, result207.getNumberOfAlteredCases()); + } + + @Test + public void getPatientGeneCountIncludeOnlyVUS() throws Exception { + alterationFilter.setIncludeDriver(false); + alterationFilter.setIncludeUnknownOncogenicity(false); + List result = + alterationMyBatisRepository.getPatientAlterationGeneCounts( + patientIdToProfileId, entrezGeneIds, alterationFilter); + + Assert.assertEquals(3, result.size()); + AlterationCountByGene result672 = + result.stream().filter(r -> r.getEntrezGeneId() == 672).findFirst().get(); + AlterationCountByGene result207 = + result.stream().filter(r -> r.getEntrezGeneId() == 207).findFirst().get(); + AlterationCountByGene result208 = + result.stream().filter(r -> r.getEntrezGeneId() == 208).findFirst().get(); + Assert.assertEquals((Integer) 2, result672.getTotalCount()); + Assert.assertEquals((Integer) 2, result672.getNumberOfAlteredCases()); + Assert.assertEquals((Integer) 2, result207.getTotalCount()); + Assert.assertEquals((Integer) 1, result207.getNumberOfAlteredCases()); + Assert.assertEquals((Integer) 1, result208.getTotalCount()); + Assert.assertEquals((Integer) 1, result208.getNumberOfAlteredCases()); + } + + @Test + public void getPatientGeneCountIncludeOnlyUnknownOncogenicity() throws Exception { + alterationFilter.setIncludeDriver(false); + alterationFilter.setIncludeVUS(false); + List result = + alterationMyBatisRepository.getPatientAlterationGeneCounts( + patientIdToProfileId, entrezGeneIds, alterationFilter); + + Assert.assertEquals(1, result.size()); + AlterationCountByGene result208 = + result.stream().filter(r -> r.getEntrezGeneId() == 208).findFirst().get(); + Assert.assertEquals((Integer) 1, result208.getTotalCount()); + Assert.assertEquals((Integer) 1, result208.getNumberOfAlteredCases()); + } + + @Test + public void getPatientGeneCountIncludeOnlyTiers() throws Exception { + // All 'Tier 2' tiers are forced to be interpreted as driver events + alterationFilter.setSelectedTiers(Select.byValues(Arrays.asList("Tier 2"))); + alterationFilter.setIncludeUnknownTier(false); + List result = + alterationMyBatisRepository.getPatientAlterationGeneCounts( + patientIdToProfileId, entrezGeneIds, alterationFilter); + + Assert.assertEquals(2, result.size()); + AlterationCountByGene result672 = + result.stream().filter(r -> r.getEntrezGeneId() == 672).findFirst().get(); + AlterationCountByGene result207 = + result.stream().filter(r -> r.getEntrezGeneId() == 207).findFirst().get(); + Assert.assertEquals((Integer) 2, result672.getTotalCount()); + Assert.assertEquals((Integer) 2, result672.getNumberOfAlteredCases()); + Assert.assertEquals((Integer) 2, result207.getTotalCount()); + Assert.assertEquals((Integer) 1, result207.getNumberOfAlteredCases()); + } + + @Test + public void getPatientGeneCountIncludeUnknownTier() throws Exception { + alterationFilter.setSelectedTiers(Select.none()); + List result = + alterationMyBatisRepository.getPatientAlterationGeneCounts( + patientIdToProfileId, entrezGeneIds, alterationFilter); + + Assert.assertEquals(1, result.size()); + AlterationCountByGene result208 = + result.stream().filter(r -> r.getEntrezGeneId() == 208).findFirst().get(); + Assert.assertEquals((Integer) 1, result208.getTotalCount()); + Assert.assertEquals((Integer) 1, result208.getNumberOfAlteredCases()); + } + + @Test + public void getSampleCnaGeneCountLegacyOnlyDriver() throws Exception { + alterationFilter.setIncludeVUS(false); + alterationFilter.setIncludeUnknownOncogenicity(false); + List result = + alterationMyBatisRepository.getSampleCnaGeneCounts( + sampleIdToProfileId, entrezGeneIds, alterationFilter); + + Assert.assertEquals(1, result.size()); + AlterationCountByGene result207 = + result.stream().filter(r -> r.getEntrezGeneId() == 207).findFirst().get(); + Assert.assertEquals((Integer) 1, result207.getTotalCount()); + Assert.assertEquals((Integer) 1, result207.getNumberOfAlteredCases()); + } + + @Test + public void getSampleCnaGeneCountLegacyOnlyVUS() throws Exception { + alterationFilter.setIncludeDriver(false); + alterationFilter.setIncludeUnknownOncogenicity(false); + List result = + alterationMyBatisRepository.getSampleCnaGeneCounts( + sampleIdToProfileId, entrezGeneIds, alterationFilter); + + Assert.assertEquals(1, result.size()); + AlterationCountByGene result207 = + result.stream().filter(r -> r.getEntrezGeneId() == 207).findFirst().get(); + Assert.assertEquals((Integer) 1, result207.getTotalCount()); + Assert.assertEquals((Integer) 1, result207.getNumberOfAlteredCases()); + } + + @Test + public void getSampleCnaGeneCountLegacyOnlyUnknownOncogenicity() throws Exception { + alterationFilter.setIncludeDriver(false); + alterationFilter.setIncludeVUS(false); + List result = + alterationMyBatisRepository.getSampleCnaGeneCounts( + sampleIdToProfileId, entrezGeneIds, alterationFilter); + + Assert.assertEquals(1, result.size()); + AlterationCountByGene result208 = + result.stream().filter(r -> r.getEntrezGeneId() == 208).findFirst().get(); + Assert.assertEquals((Integer) 1, result208.getTotalCount()); + Assert.assertEquals((Integer) 1, result208.getNumberOfAlteredCases()); + } + + @Test + public void getSampleCnaGeneCountLegacyOnlyUnknownTier() throws Exception { + alterationFilter.setSelectedTiers(Select.none()); + List result = + alterationMyBatisRepository.getSampleCnaGeneCounts( + sampleIdToProfileId, entrezGeneIds, alterationFilter); + + Assert.assertEquals(1, result.size()); + AlterationCountByGene result208 = + result.stream().filter(r -> r.getEntrezGeneId() == 208).findFirst().get(); + Assert.assertEquals((Integer) 1, result208.getTotalCount()); + Assert.assertEquals((Integer) 1, result208.getNumberOfAlteredCases()); + } + + @Test + public void getSampleCnaGeneCountLegacyOnlyTier2() throws Exception { + // All 'Tier 2' tiers are forced to be interpreted as driver events + alterationFilter.setSelectedTiers(Select.byValues(Arrays.asList("Tier 2"))); + alterationFilter.setIncludeUnknownTier(false); + List result = + alterationMyBatisRepository.getSampleCnaGeneCounts( + sampleIdToProfileId, entrezGeneIds, alterationFilter); + + Assert.assertEquals(1, result.size()); + AlterationCountByGene result207 = + result.stream().filter(r -> r.getEntrezGeneId() == 207).findFirst().get(); + Assert.assertEquals((Integer) 1, result207.getTotalCount()); + Assert.assertEquals((Integer) 1, result207.getNumberOfAlteredCases()); + } + + @Test + public void getPatientCnaGeneCountLegacyOnlyDriver() throws Exception { + alterationFilter.setIncludeVUS(false); + alterationFilter.setIncludeUnknownOncogenicity(false); + List result = + alterationMyBatisRepository.getPatientCnaGeneCounts( + patientIdToProfileId, entrezGeneIds, alterationFilter); + + Assert.assertEquals(1, result.size()); + AlterationCountByGene result207 = + result.stream().filter(r -> r.getEntrezGeneId() == 207).findFirst().get(); + Assert.assertEquals((Integer) 1, result207.getTotalCount()); + Assert.assertEquals((Integer) 1, result207.getNumberOfAlteredCases()); + } + + @Test + public void getPatientCnaGeneCountLegacyOnlyVUS() throws Exception { + alterationFilter.setIncludeDriver(false); + alterationFilter.setIncludeUnknownOncogenicity(false); + List result = + alterationMyBatisRepository.getPatientCnaGeneCounts( + patientIdToProfileId, entrezGeneIds, alterationFilter); + + Assert.assertEquals(1, result.size()); + AlterationCountByGene result207 = + result.stream().filter(r -> r.getEntrezGeneId() == 207).findFirst().get(); + Assert.assertEquals((Integer) 1, result207.getTotalCount()); + Assert.assertEquals((Integer) 1, result207.getNumberOfAlteredCases()); + } + + @Test + public void getPatientCnaGeneCountLegacyOnlyUnknownOncogenicity() throws Exception { + alterationFilter.setIncludeDriver(false); + alterationFilter.setIncludeVUS(false); + List result = + alterationMyBatisRepository.getPatientCnaGeneCounts( + patientIdToProfileId, entrezGeneIds, alterationFilter); + + Assert.assertEquals(1, result.size()); + AlterationCountByGene result208 = + result.stream().filter(r -> r.getEntrezGeneId() == 208).findFirst().get(); + Assert.assertEquals((Integer) 1, result208.getTotalCount()); + Assert.assertEquals((Integer) 1, result208.getNumberOfAlteredCases()); + } + + @Test + public void getPatientCnaGeneCountLegacyOnlyUnknownTier() throws Exception { + alterationFilter.setSelectedTiers(Select.none()); + List result = + alterationMyBatisRepository.getPatientCnaGeneCounts( + patientIdToProfileId, entrezGeneIds, alterationFilter); + + Assert.assertEquals(1, result.size()); + AlterationCountByGene result208 = + result.stream().filter(r -> r.getEntrezGeneId() == 208).findFirst().get(); + Assert.assertEquals((Integer) 1, result208.getTotalCount()); + Assert.assertEquals((Integer) 1, result208.getNumberOfAlteredCases()); + } + + @Test + public void getPatientCnaGeneCountLegacyOnlyTier2() throws Exception { + // All 'Tier 2' tiers are forced to be interpreted as driver events + alterationFilter.setSelectedTiers(Select.byValues(Arrays.asList("Tier 2"))); + alterationFilter.setIncludeUnknownTier(false); + alterationFilter.setSelectedTiers(Select.byValues(Arrays.asList("Tier 2"))); + List result = + alterationMyBatisRepository.getPatientCnaGeneCounts( + patientIdToProfileId, entrezGeneIds, alterationFilter); + + Assert.assertEquals(1, result.size()); + AlterationCountByGene result207 = + result.stream().filter(r -> r.getEntrezGeneId() == 207).findFirst().get(); + Assert.assertEquals((Integer) 1, result207.getTotalCount()); + Assert.assertEquals((Integer) 1, result207.getNumberOfAlteredCases()); + } + + @Test + public void getPatientCnaGeneCountNullIds() throws Exception { + List result = + alterationMyBatisRepository.getPatientCnaGeneCounts( + null, entrezGeneIds, new AlterationFilter()); + Assert.assertEquals(0, result.size()); + } + + @Test + public void getSampleGeneCountNullEntrezGeneIds() throws Exception { + List result = + alterationMyBatisRepository.getSampleAlterationGeneCounts( + sampleIdToProfileId, null, new AlterationFilter()); + Assert.assertEquals(0, result.size()); + } + + @Test + public void getSampleGeneCountEmptyEntrezGeneIds() throws Exception { + List result = + alterationMyBatisRepository.getSampleAlterationGeneCounts( + sampleIdToProfileId, Select.none(), new AlterationFilter()); + Assert.assertEquals(0, result.size()); + } + + @Test + public void getSampleGeneCountAllEntrezGeneIds() throws Exception { + List result = + alterationMyBatisRepository.getSampleAlterationGeneCounts( + sampleIdToProfileId, Select.all(), new AlterationFilter()); + Assert.assertEquals(3, result.size()); + } + + @Test + public void getPatientGeneCountNullEntrezGeneIds() throws Exception { + List result = + alterationMyBatisRepository.getPatientAlterationGeneCounts( + patientIdToProfileId, null, new AlterationFilter()); + Assert.assertEquals(0, result.size()); + } + + @Test + public void getPatientGeneCountEmptyEntrezGeneIds() throws Exception { + List result = + alterationMyBatisRepository.getPatientAlterationGeneCounts( + patientIdToProfileId, Select.none(), new AlterationFilter()); + Assert.assertEquals(0, result.size()); + } + + @Test + public void getPatientGeneCountAllEntrezGeneIds() throws Exception { + List result = + alterationMyBatisRepository.getPatientAlterationGeneCounts( + patientIdToProfileId, Select.all(), new AlterationFilter()); + Assert.assertEquals(3, result.size()); + } + + @Test + public void getSampleCnaGeneCountNullEntrezGeneIds() throws Exception { + List result = + alterationMyBatisRepository.getSampleCnaGeneCounts( + sampleIdToProfileId, null, new AlterationFilter()); + Assert.assertEquals(0, result.size()); + } + + @Test + public void getSampleCnaGeneCountEmptyEntrezGeneIds() throws Exception { + List result = + alterationMyBatisRepository.getSampleCnaGeneCounts( + sampleIdToProfileId, Select.none(), new AlterationFilter()); + Assert.assertEquals(0, result.size()); + } + + @Test + public void getSampleCnaGeneCountAllEntrezGeneIds() throws Exception { + List result = + alterationMyBatisRepository.getSampleCnaGeneCounts( + sampleIdToProfileId, Select.all(), new AlterationFilter()); + Assert.assertEquals(3, result.size()); + } + + @Test + public void getPatientCnaGeneCountNullEntrezGeneIds() throws Exception { + List result = + alterationMyBatisRepository.getPatientCnaGeneCounts( + patientIdToProfileId, null, new AlterationFilter()); + Assert.assertEquals(0, result.size()); + } + + @Test + public void getPatientCnaGeneCountEmptyEntrezGeneIds() throws Exception { + List result = + alterationMyBatisRepository.getPatientCnaGeneCounts( + patientIdToProfileId, Select.none(), new AlterationFilter()); + Assert.assertEquals(0, result.size()); + } + + @Test + public void getPatientCnaGeneCountAllEntrezGeneIds() throws Exception { + List result = + alterationMyBatisRepository.getPatientCnaGeneCounts( + patientIdToProfileId, Select.all(), new AlterationFilter()); + Assert.assertEquals(3, result.size()); + } + + // StructuralVariant sample count tests + @Test + public void getSampleStructuralVariantCountAllStructuralVariantStatusExcluded() throws Exception { + alterationFilter.setIncludeSomatic(false); + alterationFilter.setIncludeGermline(false); + alterationFilter.setIncludeUnknownStatus(false); + alterationFilter.setStructuralVariants(true); + alterationFilter.setMutationTypeSelect(Select.none()); + alterationFilter.setCnaTypeSelect(Select.none()); + List result = + alterationMyBatisRepository.getSampleAlterationGeneCounts( + svSampleIdToProfileId, svEntrezGeneIds, alterationFilter); + Assert.assertEquals(0, result.size()); + } + + @Test + public void getSampleStructuralVariantCountAllStructuralVariantStatusIncluded() throws Exception { + alterationFilter.setStructuralVariants(true); + alterationFilter.setMutationTypeSelect(Select.none()); + alterationFilter.setCnaTypeSelect(Select.none()); + List result = + alterationMyBatisRepository.getSampleAlterationGeneCounts( + svSampleIdToProfileId, svEntrezGeneIds, alterationFilter); + Assert.assertEquals(4, result.size()); + } + + @Test + public void getSampleStructuralVariantCountIncludeOnlyGermline() throws Exception { + alterationFilter.setIncludeSomatic(false); + alterationFilter.setIncludeUnknownStatus(false); + alterationFilter.setStructuralVariants(true); + alterationFilter.setMutationTypeSelect(Select.none()); + alterationFilter.setCnaTypeSelect(Select.none()); + List result = + alterationMyBatisRepository.getSampleAlterationGeneCounts( + svSampleIdToProfileId, svEntrezGeneIds, alterationFilter); + // two structural variants in testSql.sql are germline mutations + + AlterationCountByGene result57670 = + result.stream().filter(r -> r.getEntrezGeneId() == 57670).findFirst().get(); + AlterationCountByGene result27436 = + result.stream().filter(r -> r.getEntrezGeneId() == 27436).findFirst().get(); + AlterationCountByGene result7113 = + result.stream().filter(r -> r.getEntrezGeneId() == 7113).findFirst().get(); + Assert.assertEquals(3, result.size()); + Assert.assertEquals((Integer) 1, result57670.getTotalCount()); + Assert.assertEquals((Integer) 1, result57670.getNumberOfAlteredCases()); + Assert.assertEquals((Integer) 1, result27436.getTotalCount()); + Assert.assertEquals((Integer) 1, result27436.getNumberOfAlteredCases()); + Assert.assertEquals((Integer) 1, result7113.getTotalCount()); + Assert.assertEquals((Integer) 1, result7113.getNumberOfAlteredCases()); + } + + @Test + public void getSampleStructuralVariantCountIncludeOnlySomatic() throws Exception { + alterationFilter.setIncludeGermline(false); + alterationFilter.setIncludeUnknownStatus(false); + alterationFilter.setStructuralVariants(true); + alterationFilter.setMutationTypeSelect(Select.none()); + alterationFilter.setCnaTypeSelect(Select.none()); + List result = + alterationMyBatisRepository.getSampleAlterationGeneCounts( + svSampleIdToProfileId, svEntrezGeneIds, alterationFilter); + Assert.assertEquals(4, result.size()); + + AlterationCountByGene result57670 = + result.stream().filter(r -> r.getEntrezGeneId() == 57670).findFirst().get(); + AlterationCountByGene result8031 = + result.stream().filter(r -> r.getEntrezGeneId() == 8031).findFirst().get(); + AlterationCountByGene result27436 = + result.stream().filter(r -> r.getEntrezGeneId() == 27436).findFirst().get(); + AlterationCountByGene result7113 = + result.stream().filter(r -> r.getEntrezGeneId() == 7113).findFirst().get(); + Assert.assertEquals((Integer) 3, result57670.getTotalCount()); + Assert.assertEquals((Integer) 3, result57670.getNumberOfAlteredCases()); + Assert.assertEquals((Integer) 3, result8031.getTotalCount()); + Assert.assertEquals((Integer) 2, result8031.getNumberOfAlteredCases()); + Assert.assertEquals((Integer) 1, result27436.getTotalCount()); + Assert.assertEquals((Integer) 1, result27436.getNumberOfAlteredCases()); + Assert.assertEquals((Integer) 1, result7113.getTotalCount()); + Assert.assertEquals((Integer) 1, result7113.getNumberOfAlteredCases()); + } + + @Test + public void getSampleStructuralVariantCountIncludeOnlyUnknownStatus() throws Exception { + alterationFilter.setIncludeGermline(false); + alterationFilter.setIncludeSomatic(false); + alterationFilter.setStructuralVariants(true); + alterationFilter.setMutationTypeSelect(Select.none()); + alterationFilter.setCnaTypeSelect(Select.none()); + List result = + alterationMyBatisRepository.getSampleAlterationGeneCounts( + svSampleIdToProfileId, svEntrezGeneIds, alterationFilter); + Assert.assertEquals(0, result.size()); + } + + // StructuralVariant patient count tests + @Test + public void getPatientStructuralVariantCountAllStructuralVariantStatusExcluded() + throws Exception { + alterationFilter.setIncludeSomatic(false); + alterationFilter.setIncludeGermline(false); + alterationFilter.setIncludeUnknownStatus(false); + alterationFilter.setStructuralVariants(true); + alterationFilter.setMutationTypeSelect(Select.none()); + alterationFilter.setCnaTypeSelect(Select.none()); + List result = + alterationMyBatisRepository.getPatientAlterationGeneCounts( + svPatientIdToProfileId, svEntrezGeneIds, alterationFilter); + Assert.assertEquals(0, result.size()); + } + + @Test + public void getPatientStructuralVariantCountAllStructuralVariantStatusIncluded() + throws Exception { + alterationFilter.setStructuralVariants(true); + alterationFilter.setMutationTypeSelect(Select.none()); + alterationFilter.setCnaTypeSelect(Select.none()); + List result = + alterationMyBatisRepository.getPatientAlterationGeneCounts( + svPatientIdToProfileId, svEntrezGeneIds, alterationFilter); + Assert.assertEquals(4, result.size()); + } + + @Test + public void getPatientStructuralVariantCountIncludeOnlyGermline() throws Exception { + alterationFilter.setIncludeSomatic(false); + alterationFilter.setIncludeUnknownStatus(false); + alterationFilter.setStructuralVariants(true); + alterationFilter.setMutationTypeSelect(Select.none()); + alterationFilter.setCnaTypeSelect(Select.none()); + List result = + alterationMyBatisRepository.getPatientAlterationGeneCounts( + svPatientIdToProfileId, svEntrezGeneIds, alterationFilter); + // two structural variants in testSql.sql are germline mutations + Assert.assertEquals(3, result.size()); + + AlterationCountByGene result57670 = + result.stream().filter(r -> r.getEntrezGeneId() == 57670).findFirst().get(); + AlterationCountByGene result27436 = + result.stream().filter(r -> r.getEntrezGeneId() == 27436).findFirst().get(); + AlterationCountByGene result7113 = + result.stream().filter(r -> r.getEntrezGeneId() == 7113).findFirst().get(); + Assert.assertEquals((Integer) 1, result57670.getTotalCount()); + Assert.assertEquals((Integer) 1, result57670.getNumberOfAlteredCases()); + Assert.assertEquals((Integer) 1, result27436.getTotalCount()); + Assert.assertEquals((Integer) 1, result27436.getNumberOfAlteredCases()); + Assert.assertEquals((Integer) 1, result7113.getTotalCount()); + Assert.assertEquals((Integer) 1, result7113.getNumberOfAlteredCases()); + } + + @Test + public void getPatientStructuralVariantCountIncludeOnlySomatic() throws Exception { + alterationFilter.setIncludeGermline(false); + alterationFilter.setIncludeUnknownStatus(false); + alterationFilter.setStructuralVariants(true); + alterationFilter.setMutationTypeSelect(Select.none()); + alterationFilter.setCnaTypeSelect(Select.none()); + List result = + alterationMyBatisRepository.getPatientAlterationGeneCounts( + svPatientIdToProfileId, svEntrezGeneIds, alterationFilter); + Assert.assertEquals(4, result.size()); + + AlterationCountByGene result57670 = + result.stream().filter(r -> r.getEntrezGeneId() == 57670).findFirst().get(); + AlterationCountByGene result8031 = + result.stream().filter(r -> r.getEntrezGeneId() == 8031).findFirst().get(); + AlterationCountByGene result27436 = + result.stream().filter(r -> r.getEntrezGeneId() == 27436).findFirst().get(); + AlterationCountByGene result7113 = + result.stream().filter(r -> r.getEntrezGeneId() == 7113).findFirst().get(); + Assert.assertEquals((Integer) 3, result57670.getTotalCount()); + Assert.assertEquals((Integer) 3, result57670.getNumberOfAlteredCases()); + Assert.assertEquals((Integer) 3, result8031.getTotalCount()); + Assert.assertEquals((Integer) 2, result8031.getNumberOfAlteredCases()); + Assert.assertEquals((Integer) 1, result27436.getTotalCount()); + Assert.assertEquals((Integer) 1, result27436.getNumberOfAlteredCases()); + Assert.assertEquals((Integer) 1, result7113.getTotalCount()); + Assert.assertEquals((Integer) 1, result7113.getNumberOfAlteredCases()); + } + + @Test + public void getPatientStructuralVariantCountIncludeOnlyUnknownStatus() throws Exception { + alterationFilter.setIncludeGermline(false); + alterationFilter.setIncludeSomatic(false); + alterationFilter.setStructuralVariants(true); + alterationFilter.setMutationTypeSelect(Select.none()); + alterationFilter.setCnaTypeSelect(Select.none()); + List result = + alterationMyBatisRepository.getPatientAlterationGeneCounts( + svPatientIdToProfileId, svEntrezGeneIds, alterationFilter); + Assert.assertEquals(0, result.size()); + } + + @Test + public void getPatientStructuralVariantCountIncludeCustomDriverAnnotationsIncludeUnknown() + throws Exception { + alterationFilter.setStructuralVariants(true); + alterationFilter.setMutationTypeSelect(Select.none()); + alterationFilter.setCnaTypeSelect(Select.none()); + alterationFilter.setSelectedTiers(Select.byValues(Arrays.asList("Class 2"))); + alterationFilter.setIncludeUnknownTier(true); + List result = + alterationMyBatisRepository.getPatientAlterationGeneCounts( + svPatientIdToProfileId, svEntrezGeneIds, alterationFilter); + Assert.assertEquals(4, result.size()); + } + + @Test + public void getPatientStructuralVariantCountIncludeCustomDriverAnnotationsExcludeUnknown() + throws Exception { + alterationFilter.setStructuralVariants(true); + alterationFilter.setMutationTypeSelect(Select.none()); + alterationFilter.setCnaTypeSelect(Select.none()); + alterationFilter.setSelectedTiers(Select.byValues(Arrays.asList("Class 2"))); + alterationFilter.setIncludeUnknownTier(false); + List result = + alterationMyBatisRepository.getPatientAlterationGeneCounts( + svPatientIdToProfileId, svEntrezGeneIds, alterationFilter); + Assert.assertEquals(1, result.size()); + } + + @Test + public void getSampleStructuralVariantCount() throws Exception { + List result = + alterationMyBatisRepository.getSampleStructuralVariantCounts( + svSampleIdToProfileId, alterationFilter); + + // Should be one KIAA154-BRAF, one NCOA4-RET and one NCOA4-null + Assert.assertEquals(5, result.size()); + AlterationCountByStructuralVariant resultEmlAlk = findStructVarCount("EML4", "ALK", result); + AlterationCountByStructuralVariant resultKiaaBraf = + findStructVarCount("KIAA1549", "BRAF", result); + AlterationCountByStructuralVariant resultTmprsErg = + findStructVarCount("TMPRSS2", "ERG", result); + AlterationCountByStructuralVariant resultNcoRet = findStructVarCount("NCOA4", "RET", result); + AlterationCountByStructuralVariant resultNcoNull = findStructVarCount("NCOA4", null, result); + Assert.assertEquals((Integer) 2, resultEmlAlk.getTotalCount()); + Assert.assertEquals((Integer) 2, resultEmlAlk.getNumberOfAlteredCases()); + Assert.assertEquals((Integer) 4, resultKiaaBraf.getTotalCount()); + Assert.assertEquals((Integer) 3, resultKiaaBraf.getNumberOfAlteredCases()); + Assert.assertEquals((Integer) 2, resultNcoRet.getTotalCount()); + Assert.assertEquals((Integer) 2, resultNcoRet.getNumberOfAlteredCases()); + Assert.assertEquals((Integer) 1, resultNcoNull.getTotalCount()); + Assert.assertEquals((Integer) 1, resultNcoNull.getNumberOfAlteredCases()); + Assert.assertEquals((Integer) 2, resultTmprsErg.getTotalCount()); + Assert.assertEquals((Integer) 2, resultTmprsErg.getNumberOfAlteredCases()); + } + + @Test + public void getSampleStructuralVariantCountAllSvStatusExcluded() throws Exception { + + // Note: 'NA' for SV status is not allowed as per file-formats.md + alterationFilter.setIncludeSomatic(false); + alterationFilter.setIncludeGermline(false); + alterationFilter.setIncludeUnknownStatus(false); + List result = + alterationMyBatisRepository.getSampleStructuralVariantCounts( + sampleIdToProfileId, alterationFilter); + + Assert.assertEquals(0, result.size()); + } + + @Test + public void getSampleStructuralVariantCountSomaticSvStatusExcluded() throws Exception { + + // Note: 'NA' for SV status is not allowed as per file-formats.md + alterationFilter.setIncludeSomatic(false); + alterationFilter.setIncludeUnknownStatus(false); + List result = + alterationMyBatisRepository.getSampleStructuralVariantCounts( + svSampleIdToProfileId, alterationFilter); + + Assert.assertEquals(3, result.size()); + AlterationCountByStructuralVariant resultKiaaBraf = + findStructVarCount("KIAA1549", "BRAF", result); + AlterationCountByStructuralVariant resultEmlAlk = findStructVarCount("EML4", "ALK", result); + AlterationCountByStructuralVariant resultTmprsErg = + findStructVarCount("TMPRSS2", "ERG", result); + Assert.assertEquals((Integer) 1, resultKiaaBraf.getTotalCount()); + Assert.assertEquals((Integer) 1, resultKiaaBraf.getNumberOfAlteredCases()); + Assert.assertEquals((Integer) 1, resultEmlAlk.getTotalCount()); + Assert.assertEquals((Integer) 1, resultEmlAlk.getNumberOfAlteredCases()); + Assert.assertEquals((Integer) 1, resultTmprsErg.getTotalCount()); + Assert.assertEquals((Integer) 1, resultTmprsErg.getNumberOfAlteredCases()); + } + + @Test + public void getSampleStructuralVariantCountGermlineSvStatusExcluded() throws Exception { + // Note: 'NA' for SV status is not allowed as per file-formats.md + alterationFilter.setIncludeGermline(false); + alterationFilter.setIncludeUnknownStatus(false); + List result = + alterationMyBatisRepository.getSampleStructuralVariantCounts( + svSampleIdToProfileId, alterationFilter); + + Assert.assertEquals(5, result.size()); + AlterationCountByStructuralVariant resultEmlAlk = findStructVarCount("EML4", "ALK", result); + AlterationCountByStructuralVariant resultKiaaBraf = + findStructVarCount("KIAA1549", "BRAF", result); + AlterationCountByStructuralVariant resultTmprsErg = + findStructVarCount("TMPRSS2", "ERG", result); + AlterationCountByStructuralVariant resultNcoRet = findStructVarCount("NCOA4", "RET", result); + AlterationCountByStructuralVariant resultNcoNull = findStructVarCount("NCOA4", null, result); + Assert.assertEquals((Integer) 1, resultEmlAlk.getTotalCount()); + Assert.assertEquals((Integer) 1, resultEmlAlk.getNumberOfAlteredCases()); + Assert.assertEquals((Integer) 3, resultKiaaBraf.getTotalCount()); + Assert.assertEquals((Integer) 3, resultKiaaBraf.getNumberOfAlteredCases()); + Assert.assertEquals((Integer) 2, resultNcoRet.getTotalCount()); + Assert.assertEquals((Integer) 2, resultNcoRet.getNumberOfAlteredCases()); + Assert.assertEquals((Integer) 1, resultNcoNull.getTotalCount()); + Assert.assertEquals((Integer) 1, resultNcoNull.getNumberOfAlteredCases()); + Assert.assertEquals((Integer) 1, resultTmprsErg.getTotalCount()); + Assert.assertEquals((Integer) 1, resultTmprsErg.getNumberOfAlteredCases()); + } + + @Test + public void getPatientStructuralVariantCount() throws Exception { + List result = + alterationMyBatisRepository.getPatientStructuralVariantCounts( + svPatientIdToProfileId, alterationFilter); + + Assert.assertEquals(4, result.size()); + AlterationCountByStructuralVariant resultEmlAlk = findStructVarCount("EML4", "ALK", result); + AlterationCountByStructuralVariant resultKiaaBraf = + findStructVarCount("KIAA1549", "BRAF", result); + AlterationCountByStructuralVariant resultTmprsErg = + findStructVarCount("TMPRSS2", "ERG", result); + AlterationCountByStructuralVariant resultNcoRet = findStructVarCount("NCOA4", "RET", result); + Assert.assertEquals((Integer) 2, resultEmlAlk.getTotalCount()); + Assert.assertEquals((Integer) 2, resultEmlAlk.getNumberOfAlteredCases()); + Assert.assertEquals((Integer) 4, resultKiaaBraf.getTotalCount()); + Assert.assertEquals((Integer) 3, resultKiaaBraf.getNumberOfAlteredCases()); + Assert.assertEquals((Integer) 2, resultNcoRet.getTotalCount()); + Assert.assertEquals((Integer) 2, resultNcoRet.getNumberOfAlteredCases()); + Assert.assertEquals((Integer) 2, resultTmprsErg.getTotalCount()); + Assert.assertEquals((Integer) 2, resultTmprsErg.getNumberOfAlteredCases()); + } + + private AlterationCountByStructuralVariant findStructVarCount( + String gene1HugoSymbol, + String gene2HugoSymbol, + List counts) { + return counts.stream() + .filter( + c -> + ((c.getGene1HugoGeneSymbol() == null && gene1HugoSymbol == null) + || (c.getGene1HugoGeneSymbol() != null + && c.getGene1HugoGeneSymbol().equals(gene1HugoSymbol))) + && ((c.getGene2HugoGeneSymbol() == null && gene2HugoSymbol == null) + || (c.getGene2HugoGeneSymbol() != null + && c.getGene2HugoGeneSymbol().equals(gene2HugoSymbol)))) + .findFirst() + .get(); + } +} diff --git a/src/test/java/org/cbioportal/legacy/persistence/mybatis/CancerTypeMyBatisRepositoryTest.java b/src/test/java/org/cbioportal/legacy/persistence/mybatis/CancerTypeMyBatisRepositoryTest.java new file mode 100644 index 00000000000..0514120bc69 --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/persistence/mybatis/CancerTypeMyBatisRepositoryTest.java @@ -0,0 +1,108 @@ +package org.cbioportal.legacy.persistence.mybatis; + +import java.util.List; +import org.cbioportal.legacy.model.TypeOfCancer; +import org.cbioportal.legacy.model.meta.BaseMeta; +import org.cbioportal.legacy.persistence.mybatis.config.TestConfig; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +@RunWith(SpringJUnit4ClassRunner.class) +@SpringBootTest(classes = {CancerTypeMyBatisRepository.class, TestConfig.class}) +public class CancerTypeMyBatisRepositoryTest { + + @Autowired private CancerTypeMyBatisRepository cancerTypeMyBatisRepository; + + @Test + public void getAllCancerTypesIdProjection() throws Exception { + + List result = + cancerTypeMyBatisRepository.getAllCancerTypes("ID", null, null, null, null); + + Assert.assertEquals(2, result.size()); + TypeOfCancer typeOfCancer = result.get(0); + Assert.assertEquals("acc", typeOfCancer.getTypeOfCancerId()); + } + + @Test + public void getAllCancerTypesSummaryProjection() throws Exception { + + List result = + cancerTypeMyBatisRepository.getAllCancerTypes("SUMMARY", null, null, null, null); + + Assert.assertEquals(2, result.size()); + TypeOfCancer typeOfCancer = result.get(0); + Assert.assertEquals("brca", typeOfCancer.getTypeOfCancerId()); + Assert.assertEquals("Breast Invasive Carcinoma", typeOfCancer.getName()); + Assert.assertEquals("HotPink", typeOfCancer.getDedicatedColor()); + Assert.assertEquals("Breast", typeOfCancer.getShortName()); + Assert.assertEquals("tissue", typeOfCancer.getParent()); + } + + @Test + public void getAllCancerTypesDetailedProjection() throws Exception { + + List result = + cancerTypeMyBatisRepository.getAllCancerTypes("DETAILED", null, null, null, null); + + Assert.assertEquals(2, result.size()); + TypeOfCancer typeOfCancer = result.get(0); + Assert.assertEquals("brca", typeOfCancer.getTypeOfCancerId()); + Assert.assertEquals("Breast Invasive Carcinoma", typeOfCancer.getName()); + Assert.assertEquals("HotPink", typeOfCancer.getDedicatedColor()); + Assert.assertEquals("Breast", typeOfCancer.getShortName()); + Assert.assertEquals("tissue", typeOfCancer.getParent()); + } + + @Test + public void getAllCancerTypesSummaryProjection1PageSize() throws Exception { + + List result = + cancerTypeMyBatisRepository.getAllCancerTypes("SUMMARY", 1, 0, null, null); + + Assert.assertEquals(1, result.size()); + } + + @Test + public void getAllCancerTypesSummaryProjectionNameSort() throws Exception { + + List result = + cancerTypeMyBatisRepository.getAllCancerTypes("SUMMARY", null, null, "name", "ASC"); + + Assert.assertEquals(2, result.size()); + Assert.assertEquals("Adrenocortical Carcinoma", result.get(0).getName()); + Assert.assertEquals("Breast Invasive Carcinoma", result.get(1).getName()); + } + + @Test + public void getMetaCancerTypes() throws Exception { + + BaseMeta result = cancerTypeMyBatisRepository.getMetaCancerTypes(); + + Assert.assertEquals((Integer) 2, result.getTotalCount()); + } + + @Test + public void getCancerTypeNullResult() throws Exception { + + TypeOfCancer result = cancerTypeMyBatisRepository.getCancerType("invalid_cancer_type"); + + Assert.assertNull(result); + } + + @Test + public void getCancerType() throws Exception { + + TypeOfCancer result = cancerTypeMyBatisRepository.getCancerType("acc"); + + Assert.assertEquals("acc", result.getTypeOfCancerId()); + Assert.assertEquals("Adrenocortical Carcinoma", result.getName()); + Assert.assertEquals("Purple", result.getDedicatedColor()); + Assert.assertEquals("ACC", result.getShortName()); + Assert.assertEquals("adrenal_gland", result.getParent()); + } +} diff --git a/src/test/java/org/cbioportal/legacy/persistence/mybatis/ClinicalAttributeMyBatisRepositoryTest.java b/src/test/java/org/cbioportal/legacy/persistence/mybatis/ClinicalAttributeMyBatisRepositoryTest.java new file mode 100644 index 00000000000..7bc6bac606f --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/persistence/mybatis/ClinicalAttributeMyBatisRepositoryTest.java @@ -0,0 +1,253 @@ +package org.cbioportal.legacy.persistence.mybatis; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Optional; +import org.cbioportal.legacy.model.ClinicalAttribute; +import org.cbioportal.legacy.model.ClinicalAttributeCount; +import org.cbioportal.legacy.model.meta.BaseMeta; +import org.cbioportal.legacy.persistence.mybatis.config.TestConfig; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +@RunWith(SpringJUnit4ClassRunner.class) +@SpringBootTest(classes = {ClinicalAttributeMyBatisRepository.class, TestConfig.class}) +public class ClinicalAttributeMyBatisRepositoryTest { + + @Autowired private ClinicalAttributeMyBatisRepository clinicalAttributeMyBatisRepository; + + @Test + public void getAllClinicalAttributesIdProjection() throws Exception { + + List result = + clinicalAttributeMyBatisRepository.getAllClinicalAttributes("ID", null, null, null, null); + + Assert.assertEquals(28, result.size()); + ClinicalAttribute clinicalAttribute = result.get(0); + Assert.assertEquals("DAYS_TO_COLLECTION", clinicalAttribute.getAttrId()); + Assert.assertEquals("study_tcga_pub", clinicalAttribute.getCancerStudyIdentifier()); + } + + @Test + public void getAllClinicalAttributesSummaryProjection() throws Exception { + + List result = + clinicalAttributeMyBatisRepository.getAllClinicalAttributes( + "SUMMARY", null, null, null, null); + + Assert.assertEquals(28, result.size()); + ClinicalAttribute clinicalAttribute = result.get(0); + Assert.assertEquals("RETROSPECTIVE_COLLECTION", clinicalAttribute.getAttrId()); + Assert.assertEquals("study_tcga_pub", clinicalAttribute.getCancerStudyIdentifier()); + Assert.assertEquals((Integer) 1, clinicalAttribute.getCancerStudyId()); + Assert.assertEquals("STRING", clinicalAttribute.getDatatype()); + Assert.assertEquals( + "Text indicator for the time frame of tissue procurement,indicating that the tissue was " + + "obtained and stored prior to the initiation of the project.", + clinicalAttribute.getDescription()); + Assert.assertEquals( + "Tissue Retrospective Collection Indicator", clinicalAttribute.getDisplayName()); + Assert.assertEquals("1", clinicalAttribute.getPriority()); + Assert.assertEquals(true, clinicalAttribute.getPatientAttribute()); + } + + @Test + public void getAllClinicalAttributesDetailedProjection() throws Exception { + + List result = + clinicalAttributeMyBatisRepository.getAllClinicalAttributes( + "DETAILED", null, null, null, null); + + Assert.assertEquals(28, result.size()); + Optional clinicalAttributeOptional = + result.stream().filter(r -> r.getAttrId().equals("RETROSPECTIVE_COLLECTION")).findAny(); + Assert.assertTrue(clinicalAttributeOptional.isPresent()); + ClinicalAttribute clinicalAttribute = clinicalAttributeOptional.get(); + Assert.assertEquals("study_tcga_pub", clinicalAttribute.getCancerStudyIdentifier()); + Assert.assertEquals((Integer) 1, clinicalAttribute.getCancerStudyId()); + Assert.assertEquals("STRING", clinicalAttribute.getDatatype()); + Assert.assertEquals( + "Text indicator for the time frame of tissue procurement,indicating that the tissue was " + + "obtained and stored prior to the initiation of the project.", + clinicalAttribute.getDescription()); + Assert.assertEquals( + "Tissue Retrospective Collection Indicator", clinicalAttribute.getDisplayName()); + Assert.assertEquals("1", clinicalAttribute.getPriority()); + Assert.assertEquals(true, clinicalAttribute.getPatientAttribute()); + } + + @Test + public void getAllClinicalAttributesSummaryProjection1PageSize() throws Exception { + + List result = + clinicalAttributeMyBatisRepository.getAllClinicalAttributes("SUMMARY", 1, 0, null, null); + + Assert.assertEquals(1, result.size()); + } + + @Test + public void getAllClinicalAttributesSummaryProjectionDisplayNameSort() throws Exception { + + List result = + clinicalAttributeMyBatisRepository.getAllClinicalAttributes( + "SUMMARY", null, null, "displayName", "ASC"); + + Assert.assertEquals(28, result.size()); + Assert.assertEquals("Days to Sample Collection.", result.get(0).getDisplayName()); + Assert.assertEquals("Days to Sample Collection.", result.get(1).getDisplayName()); + Assert.assertEquals("Disease Free (Months)", result.get(2).getDisplayName()); + Assert.assertEquals("Disease Free (Months)", result.get(3).getDisplayName()); + Assert.assertEquals("Disease Free Status", result.get(4).getDisplayName()); + Assert.assertEquals("Disease Free Status", result.get(5).getDisplayName()); + } + + @Test + public void getMetaClinicalAttributes() throws Exception { + + BaseMeta result = clinicalAttributeMyBatisRepository.getMetaClinicalAttributes(); + + Assert.assertEquals((Integer) 28, result.getTotalCount()); + } + + @Test + public void getClinicalAttributeNullResult() throws Exception { + + ClinicalAttribute result = + clinicalAttributeMyBatisRepository.getClinicalAttribute( + "study_tcga_pub", "invalid_clinical_attribute"); + + Assert.assertNull(result); + } + + @Test + public void getClinicalAttribute() throws Exception { + + ClinicalAttribute result = + clinicalAttributeMyBatisRepository.getClinicalAttribute( + "study_tcga_pub", "RETROSPECTIVE_COLLECTION"); + + Assert.assertEquals("RETROSPECTIVE_COLLECTION", result.getAttrId()); + Assert.assertEquals("study_tcga_pub", result.getCancerStudyIdentifier()); + Assert.assertEquals((Integer) 1, result.getCancerStudyId()); + Assert.assertEquals("STRING", result.getDatatype()); + Assert.assertEquals( + "Text indicator for the time frame of tissue procurement,indicating that the tissue was " + + "obtained and stored prior to the initiation of the project.", + result.getDescription()); + Assert.assertEquals("Tissue Retrospective Collection Indicator", result.getDisplayName()); + Assert.assertEquals("1", result.getPriority()); + Assert.assertEquals(true, result.getPatientAttribute()); + } + + @Test + public void getAllClinicalAttributesInStudySummaryProjection() throws Exception { + + List result = + clinicalAttributeMyBatisRepository.getAllClinicalAttributesInStudy( + "study_tcga_pub", "SUMMARY", null, null, null, null); + + Assert.assertEquals(14, result.size()); + Optional clinicalAttributeOptional = + result.stream().filter(r -> r.getAttrId().equals("RETROSPECTIVE_COLLECTION")).findAny(); + Assert.assertTrue(clinicalAttributeOptional.isPresent()); + ClinicalAttribute clinicalAttribute = clinicalAttributeOptional.get(); + Assert.assertEquals("study_tcga_pub", clinicalAttribute.getCancerStudyIdentifier()); + Assert.assertEquals((Integer) 1, clinicalAttribute.getCancerStudyId()); + Assert.assertEquals("STRING", clinicalAttribute.getDatatype()); + Assert.assertEquals( + "Text indicator for the time frame of tissue procurement,indicating that the tissue was " + + "obtained and stored prior to the initiation of the project.", + clinicalAttribute.getDescription()); + Assert.assertEquals( + "Tissue Retrospective Collection Indicator", clinicalAttribute.getDisplayName()); + Assert.assertEquals("1", clinicalAttribute.getPriority()); + Assert.assertEquals(true, clinicalAttribute.getPatientAttribute()); + } + + @Test + public void getMetaClinicalAttributesInStudy() throws Exception { + + BaseMeta result = + clinicalAttributeMyBatisRepository.getMetaClinicalAttributesInStudy("study_tcga_pub"); + + Assert.assertEquals((Integer) 14, result.getTotalCount()); + } + + @Test + public void fetchClinicalAttributes() throws Exception { + + List result = + clinicalAttributeMyBatisRepository.fetchClinicalAttributes( + Arrays.asList("acc_tcga", "study_tcga_pub"), "SUMMARY"); + + Assert.assertEquals(28, result.size()); + ClinicalAttribute clinicalAttribute = result.get(0); + Assert.assertEquals("RETROSPECTIVE_COLLECTION", clinicalAttribute.getAttrId()); + Assert.assertEquals("acc_tcga", clinicalAttribute.getCancerStudyIdentifier()); + Assert.assertEquals((Integer) 2, clinicalAttribute.getCancerStudyId()); + Assert.assertEquals("STRING", clinicalAttribute.getDatatype()); + Assert.assertEquals( + "Text indicator for the time frame of tissue procurement,indicating that the tissue was " + + "obtained and stored prior to the initiation of the project.", + clinicalAttribute.getDescription()); + Assert.assertEquals( + "Tissue Retrospective Collection Indicator", clinicalAttribute.getDisplayName()); + Assert.assertEquals("1", clinicalAttribute.getPriority()); + Assert.assertEquals(true, clinicalAttribute.getPatientAttribute()); + } + + public void fetchMetaClinicalAttributes() throws Exception { + + BaseMeta result = + clinicalAttributeMyBatisRepository.fetchMetaClinicalAttributes( + Arrays.asList("acc_tcga", "study_tcga_pub")); + + Assert.assertEquals((Integer) 28, result.getTotalCount()); + } + + @Test + public void getClinicalAttributeCountsBySampleIds() throws Exception { + + List studyId = new ArrayList<>(); + studyId.add("study_tcga_pub"); + studyId.add("study_tcga_pub"); + List sampleIds = new ArrayList(); + sampleIds.add("TCGA-A1-A0SB-01"); + sampleIds.add("TCGA-A1-A0SD-01"); + List result = + clinicalAttributeMyBatisRepository.getClinicalAttributeCountsBySampleIds( + studyId, sampleIds); + + Assert.assertEquals(10, result.size()); + Optional clinicalAttributeCountOptional = + result.stream().filter(r -> r.getAttrId().equals("RETROSPECTIVE_COLLECTION")).findAny(); + Assert.assertTrue(clinicalAttributeCountOptional.isPresent()); + Assert.assertEquals((Integer) 1, clinicalAttributeCountOptional.get().getCount()); + } + + @Test + public void getClinicalAttributeCountsBySampleListId() throws Exception { + + List studyId = new ArrayList<>(); + studyId.add("study_tcga_pub"); + studyId.add("study_tcga_pub"); + List sampleIds = new ArrayList(); + sampleIds.add("TCGA-A1-A0SB-01"); + sampleIds.add("TCGA-A1-A0SD-01"); + List result = + clinicalAttributeMyBatisRepository.getClinicalAttributeCountsBySampleListId( + "study_tcga_pub_all"); + + Assert.assertEquals(10, result.size()); + ClinicalAttributeCount clinicalAttributeCount = result.get(1); + Optional clinicalAttributeCountOptional = + result.stream().filter(r -> r.getAttrId().equals("OTHER_SAMPLE_ID")).findAny(); + Assert.assertTrue(clinicalAttributeCountOptional.isPresent()); + Assert.assertEquals((Integer) 1, clinicalAttributeCountOptional.get().getCount()); + } +} diff --git a/src/test/java/org/cbioportal/legacy/persistence/mybatis/ClinicalDataMyBatisRepositoryTest.java b/src/test/java/org/cbioportal/legacy/persistence/mybatis/ClinicalDataMyBatisRepositoryTest.java new file mode 100644 index 00000000000..54846a49e0d --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/persistence/mybatis/ClinicalDataMyBatisRepositoryTest.java @@ -0,0 +1,690 @@ +package org.cbioportal.legacy.persistence.mybatis; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Optional; +import java.util.stream.Collectors; +import org.cbioportal.legacy.model.ClinicalData; +import org.cbioportal.legacy.model.ClinicalDataCount; +import org.cbioportal.legacy.model.meta.BaseMeta; +import org.cbioportal.legacy.persistence.PersistenceConstants; +import org.cbioportal.legacy.persistence.mybatis.config.TestConfig; +import org.cbioportal.legacy.persistence.mybatis.util.PaginationCalculator; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +@RunWith(SpringJUnit4ClassRunner.class) +@SpringBootTest( + classes = { + ClinicalDataMyBatisRepository.class, + PatientMyBatisRepository.class, + ClinicalAttributeMyBatisRepository.class, + ClinicalAttributeMapper.class, + PaginationCalculator.class, + TestConfig.class + }) +public class ClinicalDataMyBatisRepositoryTest { + + private static int noPaging = 0; + private static String noSearch = null; + private static String noSort = null; + + List studyIds = new ArrayList<>(); + List sampleIds = new ArrayList<>(); + + @Before + public void init() { + studyIds.add("study_tcga_pub"); + studyIds.add("study_tcga_pub"); + studyIds.add("study_tcga_pub"); + studyIds.add("study_tcga_pub"); + studyIds.add("study_tcga_pub"); + studyIds.add("study_tcga_pub"); + studyIds.add("study_tcga_pub"); + studyIds.add("study_tcga_pub"); + studyIds.add("study_tcga_pub"); + studyIds.add("study_tcga_pub"); + studyIds.add("study_tcga_pub"); + studyIds.add("study_tcga_pub"); + studyIds.add("study_tcga_pub"); + studyIds.add("study_tcga_pub"); + sampleIds.add("TCGA-A1-A0SB-01"); + sampleIds.add("TCGA-A1-A0SD-01"); + sampleIds.add("TCGA-A1-A0SE-01"); + sampleIds.add("TCGA-A1-A0SF-01"); + sampleIds.add("TCGA-A1-A0SG-01"); + sampleIds.add("TCGA-A1-A0SH-01"); + sampleIds.add("TCGA-A1-A0SI-01"); + sampleIds.add("TCGA-A1-A0SJ-01"); + sampleIds.add("TCGA-A1-A0SK-01"); + sampleIds.add("TCGA-A1-A0SM-01"); + sampleIds.add("TCGA-A1-A0SN-01"); + sampleIds.add("TCGA-A1-A0SO-01"); + sampleIds.add("TCGA-A1-A0SP-01"); + sampleIds.add("TCGA-A1-A0SQ-01"); + } + + @Autowired private ClinicalDataMyBatisRepository clinicalDataMyBatisRepository; + + @Test + public void getAllClinicalDataOfSampleInStudyEmptyResult() { + + List result = + clinicalDataMyBatisRepository.getAllClinicalDataOfSampleInStudy( + "invalid_study", null, null, "ID", null, null, null, null); + + Assert.assertEquals(0, result.size()); + } + + @Test + public void getAllClinicalDataOfSampleInStudyNullAttributeSummaryProjection() { + + List result = + clinicalDataMyBatisRepository.getAllClinicalDataOfSampleInStudy( + "study_tcga_pub", "TCGA-A1-A0SB-01", null, "SUMMARY", null, null, null, null); + + Assert.assertEquals(4, result.size()); + Optional clinicalDataOptional = + result.stream().filter(r -> r.getAttrId().equals("DAYS_TO_COLLECTION")).findAny(); + Assert.assertTrue(clinicalDataOptional.isPresent()); + ClinicalData clinicalAttribute = clinicalDataOptional.get(); + + Assert.assertEquals("276", clinicalAttribute.getAttrValue()); + Assert.assertEquals((Integer) 1, clinicalAttribute.getInternalId()); + Assert.assertNull(clinicalAttribute.getClinicalAttribute()); + } + + @Test + public void getAllClinicalDataOfSampleInStudyWithAttributeSummaryProjection() { + + List result = + clinicalDataMyBatisRepository.getAllClinicalDataOfSampleInStudy( + "study_tcga_pub", + "TCGA-A1-A0SB-01", + "OTHER_SAMPLE_ID", + "SUMMARY", + null, + null, + null, + null); + + Assert.assertEquals(1, result.size()); + ClinicalData data = result.get(0); + Assert.assertEquals("OTHER_SAMPLE_ID", data.getAttrId()); + Assert.assertEquals("5C631CE8-F96A-4C35-A459-556FC4AB21E1", data.getAttrValue()); + Assert.assertEquals((Integer) 1, data.getInternalId()); + Assert.assertNull(data.getClinicalAttribute()); + } + + @Test + public void getAllClinicalDataOfSampleInStudyNullAttributeSummaryProjection2PageSize() { + + List result = + clinicalDataMyBatisRepository.getAllClinicalDataOfSampleInStudy( + "study_tcga_pub", "TCGA-A1-A0SB-01", null, "SUMMARY", 2, 0, null, null); + + Assert.assertEquals(2, result.size()); + } + + @Test + public void getAllClinicalDataOfSampleInStudyNullAttributeSummaryProjectionAttrIdSort() { + + List result = + clinicalDataMyBatisRepository.getAllClinicalDataOfSampleInStudy( + "study_tcga_pub", "TCGA-A1-A0SB-01", null, "SUMMARY", null, null, "attrId", "ASC"); + + Assert.assertEquals(4, result.size()); + Assert.assertTrue(result.stream().anyMatch(r -> r.getAttrId().equals("DAYS_TO_COLLECTION"))); + Assert.assertTrue(result.stream().anyMatch(r -> r.getAttrId().equals("IS_FFPE"))); + Assert.assertTrue(result.stream().anyMatch(r -> r.getAttrId().equals("OTHER_SAMPLE_ID"))); + Assert.assertTrue(result.stream().anyMatch(r -> r.getAttrId().equals("SAMPLE_TYPE"))); + } + + @Test + public void getMetaSampleClinicalDataZeroCount() { + + BaseMeta result = + clinicalDataMyBatisRepository.getMetaSampleClinicalData("invalid_study", null, null); + Assert.assertEquals((Integer) 0, result.getTotalCount()); + } + + @Test + public void getMetaSampleClinicalDataNullAttribute() { + + BaseMeta result = + clinicalDataMyBatisRepository.getMetaSampleClinicalData( + "study_tcga_pub", "TCGA-A1-A0SB-01", null); + + Assert.assertEquals((Integer) 4, result.getTotalCount()); + } + + @Test + public void getMetaSampleClinicalDataWithAttribute() { + + BaseMeta result = + clinicalDataMyBatisRepository.getMetaSampleClinicalData( + "study_tcga_pub", "TCGA-A1-A0SB-01", "OTHER_SAMPLE_ID"); + + Assert.assertEquals((Integer) 1, result.getTotalCount()); + } + + @Test + public void getAllClinicalDataOfPatientInStudyEmptyResult() { + + List result = + clinicalDataMyBatisRepository.getAllClinicalDataOfPatientInStudy( + "invalid_study", null, null, "ID", null, null, null, null); + + Assert.assertEquals(0, result.size()); + } + + @Test + public void getAllClinicalDataOfPatientInStudyNullAttributeSummaryProjection() { + + List result = + clinicalDataMyBatisRepository.getAllClinicalDataOfPatientInStudy( + "study_tcga_pub", "TCGA-A1-A0SB", null, "SUMMARY", null, null, null, null); + + Assert.assertEquals(3, result.size()); + + Optional clinicalDataOptional = + result.stream().filter(r -> r.getAttrId().equals("FORM_COMPLETION_DATE")).findAny(); + Assert.assertTrue(clinicalDataOptional.isPresent()); + ClinicalData clinicalAttribute = clinicalDataOptional.get(); + + Assert.assertEquals("2013-12-5", clinicalAttribute.getAttrValue()); + Assert.assertEquals((Integer) 1, clinicalAttribute.getInternalId()); + Assert.assertNull(clinicalAttribute.getClinicalAttribute()); + } + + @Test + public void getAllClinicalDataOfPatientInStudyWithAttributeSummaryProjection() { + + List result = + clinicalDataMyBatisRepository.getAllClinicalDataOfPatientInStudy( + "study_tcga_pub", + "TCGA-A1-A0SB", + "OTHER_PATIENT_ID", + "SUMMARY", + null, + null, + null, + null); + + Assert.assertEquals(1, result.size()); + ClinicalData data = result.get(0); + Assert.assertEquals("OTHER_PATIENT_ID", data.getAttrId()); + Assert.assertEquals("286CF147-B7F7-4A05-8E41-7FBD3717AD71", data.getAttrValue()); + Assert.assertEquals((Integer) 1, data.getInternalId()); + Assert.assertNull(data.getClinicalAttribute()); + } + + @Test + public void getAllClinicalDataOfPatientInStudyNullAttributeSummaryProjection2PageSize() { + + List result = + clinicalDataMyBatisRepository.getAllClinicalDataOfPatientInStudy( + "study_tcga_pub", "TCGA-A1-A0SB", null, "SUMMARY", 2, 0, null, null); + + Assert.assertEquals(2, result.size()); + } + + @Test + public void getAllClinicalDataOfPatientInStudyNullAttributeSummaryProjectionAttrIdSort() { + + List result = + clinicalDataMyBatisRepository.getAllClinicalDataOfPatientInStudy( + "study_tcga_pub", "TCGA-A1-A0SB", null, "SUMMARY", null, null, "attrId", "ASC"); + + Assert.assertEquals(3, result.size()); + Assert.assertTrue(result.stream().anyMatch(r -> r.getAttrId().equals("FORM_COMPLETION_DATE"))); + Assert.assertTrue(result.stream().anyMatch(r -> r.getAttrId().equals("OTHER_PATIENT_ID"))); + Assert.assertTrue( + result.stream().anyMatch(r -> r.getAttrId().equals("RETROSPECTIVE_COLLECTION"))); + } + + @Test + public void getMetaPatientClinicalDataZeroCount() { + + BaseMeta result = + clinicalDataMyBatisRepository.getMetaPatientClinicalData("invalid_study", null, null); + Assert.assertEquals((Integer) 0, result.getTotalCount()); + } + + @Test + public void getMetaPatientClinicalDataNullAttribute() { + + BaseMeta result = + clinicalDataMyBatisRepository.getMetaPatientClinicalData( + "study_tcga_pub", "TCGA-A1-A0SB", null); + + Assert.assertEquals((Integer) 3, result.getTotalCount()); + } + + @Test + public void getMetaPatientClinicalDataWithAttribute() { + + BaseMeta result = + clinicalDataMyBatisRepository.getMetaPatientClinicalData( + "study_tcga_pub", "TCGA-A1-A0SB", "OTHER_PATIENT_ID"); + + Assert.assertEquals((Integer) 1, result.getTotalCount()); + } + + @Test + public void getAllClinicalDataInStudyEmptyResult() { + + List result = + clinicalDataMyBatisRepository.getAllClinicalDataInStudy( + "invalid_study", + null, + PersistenceConstants.SAMPLE_CLINICAL_DATA_TYPE, + "ID", + null, + null, + null, + null); + + Assert.assertEquals(0, result.size()); + } + + @Test + public void getAllClinicalDataInStudyNullAttributeSummaryProjection() { + + List result = + clinicalDataMyBatisRepository.getAllClinicalDataInStudy( + "study_tcga_pub", + null, + PersistenceConstants.SAMPLE_CLINICAL_DATA_TYPE, + "SUMMARY", + null, + null, + null, + null); + + Assert.assertEquals(8, result.size()); + Optional clinicalDataOptional = + result.stream().filter(r -> r.getAttrId().equals("DAYS_TO_COLLECTION")).findAny(); + Assert.assertTrue(clinicalDataOptional.isPresent()); + ClinicalData data = clinicalDataOptional.get(); + Assert.assertEquals("DAYS_TO_COLLECTION", data.getAttrId()); + Assert.assertEquals("276", data.getAttrValue()); + Assert.assertEquals((Integer) 1, data.getInternalId()); + Assert.assertNull(data.getClinicalAttribute()); + } + + @Test + public void getAllClinicalDataInStudyWithAttributeSummaryProjection() { + + List result = + clinicalDataMyBatisRepository.getAllClinicalDataInStudy( + "study_tcga_pub", + "DAYS_TO_COLLECTION", + PersistenceConstants.SAMPLE_CLINICAL_DATA_TYPE, + "SUMMARY", + null, + null, + null, + null); + + Assert.assertEquals(2, result.size()); + Optional sample1DataOptional = + result.stream().filter(r -> r.getSampleId().equals("TCGA-A1-A0SB-01")).findFirst(); + Optional sample2DataOptional = + result.stream().filter(r -> r.getSampleId().equals("TCGA-A1-A0SD-01")).findFirst(); + Assert.assertTrue(sample1DataOptional.isPresent()); + Assert.assertTrue(sample2DataOptional.isPresent()); + final ClinicalData sample1Data = sample1DataOptional.get(); + final ClinicalData sample2Data = sample2DataOptional.get(); + + Assert.assertEquals("DAYS_TO_COLLECTION", sample1Data.getAttrId()); + Assert.assertEquals("276", sample1Data.getAttrValue()); + Assert.assertEquals((Integer) 1, sample1Data.getInternalId()); + Assert.assertNull(sample1Data.getClinicalAttribute()); + + Assert.assertEquals("DAYS_TO_COLLECTION", sample2Data.getAttrId()); + Assert.assertEquals("277", sample2Data.getAttrValue()); + Assert.assertEquals("277", sample2Data.getAttrValue()); + Assert.assertEquals((Integer) 2, sample2Data.getInternalId()); + Assert.assertNull(sample2Data.getClinicalAttribute()); + } + + @Test + public void getAllClinicalDataInStudyNullAttributeSummaryProjection2PageSize() { + + List result = + clinicalDataMyBatisRepository.getAllClinicalDataInStudy( + "study_tcga_pub", + null, + PersistenceConstants.SAMPLE_CLINICAL_DATA_TYPE, + "SUMMARY", + 2, + 0, + null, + null); + + Assert.assertEquals(2, result.size()); + } + + @Test + public void getAllClinicalDataInStudyNullAttributeSummaryProjectionAttrIdSort() { + + List result = + clinicalDataMyBatisRepository.getAllClinicalDataInStudy( + "study_tcga_pub", + null, + PersistenceConstants.SAMPLE_CLINICAL_DATA_TYPE, + "SUMMARY", + null, + null, + "attrId", + "ASC"); + + Assert.assertEquals(8, result.size()); + List attrIds = + result.stream().map(r -> r.getAttrId()).distinct().collect(Collectors.toList()); + + Assert.assertTrue(attrIds.contains("DAYS_TO_COLLECTION")); + Assert.assertTrue(attrIds.contains("IS_FFPE")); + Assert.assertTrue(attrIds.contains("OCT_EMBEDDED")); + Assert.assertTrue(attrIds.contains("OTHER_SAMPLE_ID")); + Assert.assertTrue(attrIds.contains("PATHOLOGY_REPORT_FILE_NAME")); + Assert.assertTrue(attrIds.contains("SAMPLE_TYPE")); + } + + @Test + public void getMetaAllClinicalDataZeroCount() { + + BaseMeta result = + clinicalDataMyBatisRepository.getMetaAllClinicalData( + "invalid_study", null, PersistenceConstants.SAMPLE_CLINICAL_DATA_TYPE); + + Assert.assertEquals((Integer) 0, result.getTotalCount()); + } + + @Test + public void getMetaAllClinicalDataNullAttribute() { + + BaseMeta result = + clinicalDataMyBatisRepository.getMetaAllClinicalData( + "study_tcga_pub", null, PersistenceConstants.SAMPLE_CLINICAL_DATA_TYPE); + + Assert.assertEquals((Integer) 8, result.getTotalCount()); + } + + @Test + public void getMetaAllClinicalDataWithAttribute() { + + BaseMeta result = + clinicalDataMyBatisRepository.getMetaAllClinicalData( + "study_tcga_pub", "DAYS_TO_COLLECTION", PersistenceConstants.SAMPLE_CLINICAL_DATA_TYPE); + + Assert.assertEquals((Integer) 2, result.getTotalCount()); + } + + @Test + public void fetchAllClinicalDataInStudy() { + + List result = + clinicalDataMyBatisRepository.fetchAllClinicalDataInStudy( + "study_tcga_pub", + sampleIds, + null, + PersistenceConstants.SAMPLE_CLINICAL_DATA_TYPE, + "SUMMARY"); + + Assert.assertEquals(8, result.size()); + Optional clinicalDataOptional = + result.stream().filter(r -> r.getAttrId().equals("DAYS_TO_COLLECTION")).findAny(); + Assert.assertTrue(clinicalDataOptional.isPresent()); + ClinicalData clinicalAttribute = clinicalDataOptional.get(); + + Assert.assertEquals("276", clinicalAttribute.getAttrValue()); + Assert.assertEquals((Integer) 1, clinicalAttribute.getInternalId()); + Assert.assertNull(clinicalAttribute.getClinicalAttribute()); + } + + @Test + public void fetchMetaClinicalDataInStudy() { + + BaseMeta result = + clinicalDataMyBatisRepository.fetchMetaClinicalDataInStudy( + "study_tcga_pub", sampleIds, null, PersistenceConstants.SAMPLE_CLINICAL_DATA_TYPE); + + Assert.assertEquals((Integer) 8, result.getTotalCount()); + } + + @Test + public void fetchClinicalDataNullAttributeSummaryProjection() { + + List result = + clinicalDataMyBatisRepository.fetchClinicalData( + studyIds, sampleIds, null, PersistenceConstants.SAMPLE_CLINICAL_DATA_TYPE, "SUMMARY"); + + Assert.assertEquals(8, result.size()); + Optional clinicalDataOptional = + result.stream().filter(r -> r.getAttrId().equals("DAYS_TO_COLLECTION")).findAny(); + Assert.assertTrue(clinicalDataOptional.isPresent()); + ClinicalData clinicalAttribute = clinicalDataOptional.get(); + + Assert.assertEquals("276", clinicalAttribute.getAttrValue()); + Assert.assertEquals((Integer) 1, clinicalAttribute.getInternalId()); + Assert.assertNull(clinicalAttribute.getClinicalAttribute()); + } + + @Test + public void fetchClinicalSampleIdsClinicalTabShowAllSamples() { + + List result = + clinicalDataMyBatisRepository.getVisibleSampleInternalIdsForClinicalTable( + studyIds, sampleIds, noPaging, noPaging, noSearch, noSort, "DESC"); + + Assert.assertEquals(14, result.size()); + } + + @Test + public void fetchClinicalSampleIdsClinicalTablePagingHandleNoneExistingPage() { + + // There are only two patients in total. The second page (index 1) with pageSize 2 does not + // refer to any records. + List resultNonExistingPage = + clinicalDataMyBatisRepository.getVisibleSampleInternalIdsForClinicalTable( + studyIds, sampleIds, 2, 100, noSearch, noSort, "DESC"); + + Assert.assertEquals(0, resultNonExistingPage.size()); + } + + @Test + public void fetchClinicalSampleIdsClinicalTabStringSort() { + + List visibleSampleIdsAsc = + clinicalDataMyBatisRepository.getVisibleSampleInternalIdsForClinicalTable( + studyIds, sampleIds, 2, 0, noSearch, "SAMPLE_TYPE", "ASC"); + List visibleSampleIdsDesc = + clinicalDataMyBatisRepository.getVisibleSampleInternalIdsForClinicalTable( + studyIds, sampleIds, 2, 0, noSearch, "SAMPLE_TYPE", "DESC"); + + Assert.assertEquals(2, visibleSampleIdsAsc.size()); + Assert.assertEquals(2, visibleSampleIdsDesc.size()); + Assert.assertEquals(2, (int) visibleSampleIdsAsc.get(0)); + Assert.assertEquals(1, (int) visibleSampleIdsDesc.get(0)); + } + + @Test + public void fetchClinicalSampleIdsClinicalTabNumericSort() { + + List visibleSampleIdsAsc = + clinicalDataMyBatisRepository.getVisibleSampleInternalIdsForClinicalTable( + studyIds, sampleIds, 14, 0, noSearch, "DAYS_TO_COLLECTION", "ASC"); + List visibleSampleIdsDesc = + clinicalDataMyBatisRepository.getVisibleSampleInternalIdsForClinicalTable( + studyIds, sampleIds, 14, 0, noSearch, "DAYS_TO_COLLECTION", "DESC"); + + Assert.assertEquals(14, visibleSampleIdsAsc.size()); + Assert.assertEquals(14, visibleSampleIdsDesc.size()); + Assert.assertEquals(1, (int) visibleSampleIdsAsc.get(0)); + Assert.assertEquals(2, (int) visibleSampleIdsDesc.get(0)); + } + + @Test + public void fetchClinicalSampleIdsClinicalTabPageing() { + + List visibleSampleIdsAsc = + clinicalDataMyBatisRepository.getVisibleSampleInternalIdsForClinicalTable( + studyIds, sampleIds, 1, 1, noSearch, "SAMPLE_TYPE", "ASC"); + + Assert.assertEquals(1, visibleSampleIdsAsc.size()); + Assert.assertEquals(1, (int) visibleSampleIdsAsc.get(0)); + } + + @Test + public void fetchClinicalSampleIdsClinicalTabSearchBySampleId() { + + List visibleSampleIdsAsc = + clinicalDataMyBatisRepository.getVisibleSampleInternalIdsForClinicalTable( + studyIds, sampleIds, noPaging, noPaging, "A0SB-01", noSort, noSort); + + Assert.assertEquals(1, visibleSampleIdsAsc.size()); + Assert.assertEquals(1, (int) visibleSampleIdsAsc.get(0)); + } + + @Test + public void fetchClinicalSampleIdsClinicalTabSearchByEmptyStringShowsAllSample() { + + List result = + clinicalDataMyBatisRepository.getVisibleSampleInternalIdsForClinicalTable( + studyIds, sampleIds, noPaging, noPaging, "", noSort, "DESC"); + + Assert.assertEquals(14, result.size()); + } + + @Test + public void fetchClinicalSampleIdsClinicalTabSearchByAttributeValue() { + + List visibleSampleIdsAsc = + clinicalDataMyBatisRepository.getVisibleSampleInternalIdsForClinicalTable( + studyIds, sampleIds, noPaging, noPaging, "2013", noSort, noSort); + + Assert.assertEquals(1, visibleSampleIdsAsc.size()); + Assert.assertEquals(1, (int) visibleSampleIdsAsc.get(0)); + } + + @Test + public void fetchClinicalSampleIdsClinicalTabSearchAndSort() { + + List visibleSampleIdsAsc = + clinicalDataMyBatisRepository.getVisibleSampleInternalIdsForClinicalTable( + studyIds, sampleIds, 2, 0, "-01", "SAMPLE_TYPE", "ASC"); + List visibleSampleIdsDesc = + clinicalDataMyBatisRepository.getVisibleSampleInternalIdsForClinicalTable( + studyIds, sampleIds, 2, 0, "-01", "SAMPLE_TYPE", "DESC"); + + Assert.assertEquals(2, visibleSampleIdsAsc.size()); + Assert.assertEquals(2, visibleSampleIdsDesc.size()); + Assert.assertEquals(2, (int) visibleSampleIdsAsc.get(0)); + Assert.assertEquals(1, (int) visibleSampleIdsDesc.get(0)); + } + + @Test + public void fetchMetaClinicalDataNullAttribute() { + + BaseMeta result = + clinicalDataMyBatisRepository.fetchMetaClinicalData( + studyIds, sampleIds, null, PersistenceConstants.SAMPLE_CLINICAL_DATA_TYPE); + + Assert.assertEquals((Integer) 8, result.getTotalCount()); + } + + @Test + public void fetchClinicalDataCounts() { + + List result = + clinicalDataMyBatisRepository.fetchClinicalDataCounts( + Arrays.asList("acc_tcga", "acc_tcga"), + Arrays.asList("TCGA-A1-B0SO-01", "TCGA-A1-A0SB-01"), + Arrays.asList("OTHER_SAMPLE_ID", "DAYS_TO_COLLECTION"), + "SAMPLE", + "SUMMARY"); + + Assert.assertEquals(2, result.size()); + ClinicalDataCount clinicalDataCount1 = result.get(0); + Assert.assertEquals("DAYS_TO_COLLECTION", clinicalDataCount1.getAttributeId()); + Assert.assertEquals("111", clinicalDataCount1.getValue()); + Assert.assertEquals((Integer) 2, clinicalDataCount1.getCount()); + ClinicalDataCount clinicalDataCount2 = result.get(1); + Assert.assertEquals("OTHER_SAMPLE_ID", clinicalDataCount2.getAttributeId()); + Assert.assertEquals("91E7F41C-17B3-4724-96EF-D3C207B964E1", clinicalDataCount2.getValue()); + Assert.assertEquals((Integer) 1, clinicalDataCount2.getCount()); + } + + @Test + public void getSampleClinicalDataBySampleInternalIds() { + List sampleInternalIds = List.of(1, 2); + List result = + clinicalDataMyBatisRepository.getSampleClinicalDataBySampleInternalIds(sampleInternalIds); + String[] attributeIds = + result.stream().map(ClinicalData::getAttrId).distinct().toArray(String[]::new); + Assert.assertEquals(8, result.size()); + Assert.assertTrue(result.stream().anyMatch(r -> r.getAttrId().equals("DAYS_TO_COLLECTION"))); + Assert.assertTrue(result.stream().anyMatch(r -> r.getAttrId().equals("IS_FFPE"))); + Assert.assertTrue(result.stream().anyMatch(r -> r.getAttrId().equals("OTHER_SAMPLE_ID"))); + Assert.assertTrue(result.stream().anyMatch(r -> r.getAttrId().equals("SAMPLE_TYPE"))); + Assert.assertTrue(result.stream().anyMatch(r -> r.getAttrId().equals("OCT_EMBEDDED"))); + Assert.assertTrue( + result.stream().anyMatch(r -> r.getAttrId().equals("PATHOLOGY_REPORT_FILE_NAME"))); + } + + @Test + public void getSampleClinicalDataBySampleInternalIdsEmpty() { + List sampleInternalIds = new ArrayList<>(); + List result = + clinicalDataMyBatisRepository.getSampleClinicalDataBySampleInternalIds(sampleInternalIds); + Assert.assertEquals(0, result.size()); + } + + @Test + public void getSampleClinicalDataBySampleInternalIdsNull() { + List sampleInternalIds = null; + List result = + clinicalDataMyBatisRepository.getSampleClinicalDataBySampleInternalIds(sampleInternalIds); + Assert.assertEquals(0, result.size()); + } + + @Test + public void getPatientClinicalDataBySampleInternalIds() { + List sampleInternalIds = List.of(1, 2); + List result = + clinicalDataMyBatisRepository.getPatientClinicalDataBySampleInternalIds(sampleInternalIds); + String[] attributeIds = + result.stream().map(ClinicalData::getAttrId).distinct().toArray(String[]::new); + Assert.assertEquals(4, result.size()); + Assert.assertTrue(result.stream().anyMatch(r -> r.getAttrId().equals("FORM_COMPLETION_DATE"))); + Assert.assertTrue(result.stream().anyMatch(r -> r.getAttrId().equals("OTHER_PATIENT_ID"))); + Assert.assertTrue( + result.stream().anyMatch(r -> r.getAttrId().equals("RETROSPECTIVE_COLLECTION"))); + Assert.assertTrue( + result.stream().anyMatch(r -> r.getAttrId().equals("PROSPECTIVE_COLLECTION"))); + } + + @Test + public void getPatientClinicalDataBySampleInternalIdsEmpty() { + List sampleInternalIds = new ArrayList<>(); + List result = + clinicalDataMyBatisRepository.getPatientClinicalDataBySampleInternalIds(sampleInternalIds); + Assert.assertEquals(0, result.size()); + } + + @Test + public void getPatientClinicalDataBySampleInternalIdsNull() { + List sampleInternalIds = null; + List result = + clinicalDataMyBatisRepository.getPatientClinicalDataBySampleInternalIds(sampleInternalIds); + Assert.assertEquals(0, result.size()); + } +} diff --git a/src/test/java/org/cbioportal/legacy/persistence/mybatis/ClinicalEventMyBatisRepositoryTest.java b/src/test/java/org/cbioportal/legacy/persistence/mybatis/ClinicalEventMyBatisRepositoryTest.java new file mode 100644 index 00000000000..3e1485b0f52 --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/persistence/mybatis/ClinicalEventMyBatisRepositoryTest.java @@ -0,0 +1,321 @@ +package org.cbioportal.legacy.persistence.mybatis; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.Set; +import java.util.stream.Collectors; +import org.cbioportal.legacy.model.ClinicalEvent; +import org.cbioportal.legacy.model.ClinicalEventData; +import org.cbioportal.legacy.model.meta.BaseMeta; +import org.cbioportal.legacy.persistence.mybatis.config.TestConfig; +import org.cbioportal.legacy.persistence.mybatis.util.MolecularProfileCaseIdentifierUtil; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +@RunWith(SpringJUnit4ClassRunner.class) +@SpringBootTest( + classes = { + ClinicalEventMyBatisRepository.class, + MolecularProfileCaseIdentifierUtil.class, + TestConfig.class + }) +public class ClinicalEventMyBatisRepositoryTest { + + @Autowired private ClinicalEventMyBatisRepository clinicalEventMyBatisRepository; + + @Test + public void getAllClinicalEventsOfPatientInStudyIdProjection() throws Exception { + + List result = + clinicalEventMyBatisRepository.getAllClinicalEventsOfPatientInStudy( + "study_tcga_pub", "TCGA-A1-A0SB", "ID", null, null, null, null); + + Assert.assertEquals(2, result.size()); + + Optional clinicalEventOptional = + result.stream().filter(r -> r.getClinicalEventId() == 2L).findAny(); + Assert.assertTrue(clinicalEventOptional.isPresent()); + ClinicalEvent clinicalEvent = clinicalEventOptional.get(); + + Assert.assertEquals("study_tcga_pub", clinicalEvent.getStudyId()); + Assert.assertEquals("TCGA-A1-A0SB", clinicalEvent.getPatientId()); + Assert.assertEquals("SPECIMEN", clinicalEvent.getEventType()); + } + + @Test + public void getAllClinicalEventsOfPatientInStudySummaryProjection() throws Exception { + + List result = + clinicalEventMyBatisRepository.getAllClinicalEventsOfPatientInStudy( + "study_tcga_pub", "TCGA-A1-A0SB", "SUMMARY", null, null, null, null); + + Assert.assertEquals(2, result.size()); + + Optional clinicalEventOptional = + result.stream().filter(r -> r.getClinicalEventId() == 2L).findAny(); + Assert.assertTrue(clinicalEventOptional.isPresent()); + ClinicalEvent clinicalEvent = clinicalEventOptional.get(); + + Assert.assertEquals("study_tcga_pub", clinicalEvent.getStudyId()); + Assert.assertEquals("TCGA-A1-A0SB", clinicalEvent.getPatientId()); + Assert.assertEquals("SPECIMEN", clinicalEvent.getEventType()); + Assert.assertEquals((Integer) 233, clinicalEvent.getStartDate()); + Assert.assertEquals((Integer) 345, clinicalEvent.getStopDate()); + } + + @Test + public void getAllClinicalEventsOfPatientInStudyDetailedProjection() throws Exception { + + List result = + clinicalEventMyBatisRepository.getAllClinicalEventsOfPatientInStudy( + "study_tcga_pub", "TCGA-A1-A0SB", "DETAILED", null, null, null, null); + + Assert.assertEquals(2, result.size()); + + Optional clinicalEventOptional = + result.stream().filter(r -> r.getClinicalEventId() == 2L).findAny(); + Assert.assertTrue(clinicalEventOptional.isPresent()); + ClinicalEvent clinicalEvent = clinicalEventOptional.get(); + + Assert.assertEquals("study_tcga_pub", clinicalEvent.getStudyId()); + Assert.assertEquals("TCGA-A1-A0SB", clinicalEvent.getPatientId()); + Assert.assertEquals("SPECIMEN", clinicalEvent.getEventType()); + Assert.assertEquals((Integer) 233, clinicalEvent.getStartDate()); + Assert.assertEquals((Integer) 345, clinicalEvent.getStopDate()); + } + + @Test + public void getAllClinicalEventsOfPatientInStudySummaryProjection1PageSize() throws Exception { + + List result = + clinicalEventMyBatisRepository.getAllClinicalEventsOfPatientInStudy( + "study_tcga_pub", "TCGA-A1-A0SB", "SUMMARY", 1, 0, null, null); + + Assert.assertEquals(1, result.size()); + } + + @Test + public void getAllClinicalEventsOfPatientInStudySummaryProjectionEventTypeSort() + throws Exception { + + List result = + clinicalEventMyBatisRepository.getAllClinicalEventsOfPatientInStudy( + "study_tcga_pub", "TCGA-A1-A0SB", "SUMMARY", null, null, "eventType", "ASC"); + + Assert.assertEquals(2, result.size()); + Assert.assertEquals("SPECIMEN", result.get(0).getEventType()); + Assert.assertEquals("STATUS", result.get(1).getEventType()); + } + + @Test + public void getMetaPatientClinicalEvents() throws Exception { + + BaseMeta result = + clinicalEventMyBatisRepository.getMetaPatientClinicalEvents( + "study_tcga_pub", "TCGA-A1-A0SB"); + + Assert.assertEquals((Integer) 2, result.getTotalCount()); + } + + @Test + public void getDataOfClinicalEvents() throws Exception { + + List clinicalEventIds = new ArrayList<>(); + clinicalEventIds.add(1L); + clinicalEventIds.add(2L); + List result = + clinicalEventMyBatisRepository.getDataOfClinicalEvents(clinicalEventIds); + + Assert.assertEquals(4, result.size()); + ClinicalEventData gisticToGene1 = result.get(0); + Assert.assertEquals("STATUS", gisticToGene1.getKey()); + Assert.assertEquals("radiographic_progression", gisticToGene1.getValue()); + ClinicalEventData gisticToGene2 = result.get(1); + Assert.assertEquals("SAMPLE_ID", gisticToGene2.getKey()); + Assert.assertEquals("TCGA-A1-A0SB-01", gisticToGene2.getValue()); + ClinicalEventData gisticToGene3 = result.get(2); + Assert.assertEquals("SURGERY", gisticToGene3.getKey()); + Assert.assertEquals("OA II Initial", gisticToGene3.getValue()); + ClinicalEventData gisticToGene4 = result.get(3); + Assert.assertEquals("SAMPLE_ID", gisticToGene4.getKey()); + Assert.assertEquals("TCGA-A1-A0SB-01", gisticToGene4.getValue()); + } + + @Test + public void getAllClinicalEventsInStudyIdProjection() throws Exception { + List result = + clinicalEventMyBatisRepository.getAllClinicalEventsInStudy( + "study_tcga_pub", "ID", null, null, null, null); + + Assert.assertEquals(5, result.size()); + + Optional clinicalEventOptional = + result.stream().filter(r -> r.getClinicalEventId() == 2L).findAny(); + Assert.assertTrue(clinicalEventOptional.isPresent()); + ClinicalEvent clinicalEvent = clinicalEventOptional.get(); + + Assert.assertEquals((Long) 2L, clinicalEvent.getClinicalEventId()); + Assert.assertEquals("study_tcga_pub", clinicalEvent.getStudyId()); + Assert.assertEquals("SPECIMEN", clinicalEvent.getEventType()); + } + + @Test + public void getAllClinicalEventsInStudySummaryProjection() throws Exception { + + List result = + clinicalEventMyBatisRepository.getAllClinicalEventsInStudy( + "study_tcga_pub", "SUMMARY", null, null, null, null); + + Assert.assertEquals(5, result.size()); + + Optional clinicalEventOptional = + result.stream().filter(r -> r.getClinicalEventId() == 2L).findAny(); + Assert.assertTrue(clinicalEventOptional.isPresent()); + ClinicalEvent clinicalEvent = clinicalEventOptional.get(); + + Assert.assertEquals("study_tcga_pub", clinicalEvent.getStudyId()); + Assert.assertEquals("SPECIMEN", clinicalEvent.getEventType()); + Assert.assertEquals((Integer) 233, clinicalEvent.getStartDate()); + Assert.assertEquals((Integer) 345, clinicalEvent.getStopDate()); + } + + @Test + public void getAllClinicalEventsInStudyDetailedProjection() throws Exception { + + List result = + clinicalEventMyBatisRepository.getAllClinicalEventsInStudy( + "study_tcga_pub", "DETAILED", null, null, null, null); + + Assert.assertEquals(5, result.size()); + + Optional clinicalEventOptional = + result.stream().filter(r -> r.getClinicalEventId() == 2L).findAny(); + Assert.assertTrue(clinicalEventOptional.isPresent()); + ClinicalEvent clinicalEvent = clinicalEventOptional.get(); + + Assert.assertEquals("study_tcga_pub", clinicalEvent.getStudyId()); + Assert.assertEquals("SPECIMEN", clinicalEvent.getEventType()); + Assert.assertEquals((Integer) 233, clinicalEvent.getStartDate()); + Assert.assertEquals((Integer) 345, clinicalEvent.getStopDate()); + } + + @Test + public void getAllClinicalEventsInStudySummaryProjection1PageSize() throws Exception { + + List result = + clinicalEventMyBatisRepository.getAllClinicalEventsInStudy( + "study_tcga_pub", "SUMMARY", 1, 0, null, null); + + Assert.assertEquals(1, result.size()); + } + + @Test + public void getAllClinicalEventsInStudySummaryProjectionEventTypeSort() throws Exception { + + List result = + clinicalEventMyBatisRepository.getAllClinicalEventsInStudy( + "study_tcga_pub", "SUMMARY", null, null, "eventType", "ASC"); + + Assert.assertEquals(5, result.size()); + Assert.assertEquals("SPECIMEN", result.get(1).getEventType()); + Assert.assertEquals("STATUS", result.get(2).getEventType()); + } + + @Test + public void getMetaClinicalEvents() throws Exception { + + BaseMeta result = clinicalEventMyBatisRepository.getMetaClinicalEvents("study_tcga_pub"); + + Assert.assertEquals((Integer) 5, result.getTotalCount()); + } + + @Test + public void getSamplesOfPatientsPerEventTypeInStudy() { + List studyList = new ArrayList<>(); + studyList.add("study_tcga_pub"); + List sampleList = new ArrayList<>(); + sampleList.add("TCGA-A1-A0SB-01"); + Map> result = + clinicalEventMyBatisRepository.getSamplesOfPatientsPerEventTypeInStudy( + studyList, sampleList); + + Assert.assertNotNull(result.get("STATUS")); + } + + @Test + public void getPatientsDistinctClinicalEventInStudies() { + List studyList = new ArrayList<>(); + studyList.add("study_tcga_pub"); + List patientList = new ArrayList<>(); + patientList.add("TCGA-A1-A0SB"); + List result = + clinicalEventMyBatisRepository.getPatientsDistinctClinicalEventInStudies( + studyList, patientList); + + List eventTypes = + result.stream().map(ClinicalEvent::getEventType).collect(Collectors.toList()); + Assert.assertEquals(2, result.size()); + Assert.assertTrue(eventTypes.contains("STATUS")); + } + + @Test + public void getTimelineEvents() { + List studyList = new ArrayList<>(); + studyList.add("study_tcga_pub"); + List patientList = new ArrayList<>(); + patientList.add("TCGA-A1-A0SD"); + + ClinicalEventData clinicalEventData1 = new ClinicalEventData(); + clinicalEventData1.setKey("AGENT"); + clinicalEventData1.setValue("Madeupanib"); + + ClinicalEventData clinicalEventData2 = new ClinicalEventData(); + clinicalEventData2.setKey("AGENT"); + clinicalEventData2.setValue("abc"); + + ClinicalEvent requestClinicalEvent = new ClinicalEvent(); + requestClinicalEvent.setEventType("TREATMENT"); + requestClinicalEvent.setAttributes(Arrays.asList(clinicalEventData1, clinicalEventData2)); + List result = + clinicalEventMyBatisRepository.getTimelineEvents( + studyList, patientList, List.of(requestClinicalEvent)); + + Assert.assertEquals(1, result.size()); + Assert.assertEquals((Integer) 213, result.getFirst().getStartDate()); + Assert.assertEquals((Integer) 543, result.getFirst().getStopDate()); + } + + @Test + public void getClinicalEventsMeta() { + List studyList = new ArrayList<>(); + studyList.add("study_tcga_pub"); + List patientList = new ArrayList<>(); + patientList.add("TCGA-A1-A0SD"); + + ClinicalEventData clinicalEventData1 = new ClinicalEventData(); + clinicalEventData1.setKey("AGENT"); + clinicalEventData1.setValue("Madeupanib"); + + ClinicalEventData clinicalEventData2 = new ClinicalEventData(); + clinicalEventData2.setKey("AGENT"); + clinicalEventData2.setValue("abc"); + + ClinicalEvent requestClinicalEvent = new ClinicalEvent(); + requestClinicalEvent.setEventType("TREATMENT"); + requestClinicalEvent.setAttributes(Arrays.asList(clinicalEventData1, clinicalEventData2)); + List result = + clinicalEventMyBatisRepository.getClinicalEventsMeta( + studyList, patientList, List.of(requestClinicalEvent)); + + List eventTypes = result.stream().map(ClinicalEvent::getEventType).toList(); + Assert.assertEquals(1, result.size()); + Assert.assertTrue(eventTypes.contains("treatment")); + } +} diff --git a/src/test/java/org/cbioportal/legacy/persistence/mybatis/CopyNumberSegmentMyBatisRepositoryTest.java b/src/test/java/org/cbioportal/legacy/persistence/mybatis/CopyNumberSegmentMyBatisRepositoryTest.java new file mode 100644 index 00000000000..e46c6155125 --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/persistence/mybatis/CopyNumberSegmentMyBatisRepositoryTest.java @@ -0,0 +1,260 @@ +package org.cbioportal.legacy.persistence.mybatis; + +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.List; +import org.cbioportal.legacy.model.CopyNumberSeg; +import org.cbioportal.legacy.model.meta.BaseMeta; +import org.cbioportal.legacy.persistence.mybatis.config.TestConfig; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +@RunWith(SpringJUnit4ClassRunner.class) +@SpringBootTest(classes = {CopyNumberSegmentMyBatisRepository.class, TestConfig.class}) +public class CopyNumberSegmentMyBatisRepositoryTest { + + @Autowired private CopyNumberSegmentMyBatisRepository copyNumberSegmentMyBatisRepository; + + @Test + public void getCopyNumberSegmentsInSampleInStudySummaryProjection() throws Exception { + + List result0 = + copyNumberSegmentMyBatisRepository.getCopyNumberSegmentsInSampleInStudy( + "study_tcga_pub", "TCGA-A1-A0SB-01", null, "SUMMARY", null, null, null, null); + List result1 = + copyNumberSegmentMyBatisRepository.getCopyNumberSegmentsInSampleInStudy( + "study_tcga_pub", "TCGA-A1-A0SB-01", "1", "SUMMARY", null, null, null, null); + List result2 = + copyNumberSegmentMyBatisRepository.getCopyNumberSegmentsInSampleInStudy( + "study_tcga_pub", "TCGA-A1-A0SB-01", "2", "SUMMARY", null, null, null, null); + List result3 = + copyNumberSegmentMyBatisRepository.getCopyNumberSegmentsInSampleInStudy( + "study_tcga_pub", "TCGA-A1-A0SB-01", "3", "SUMMARY", null, null, null, null); + + Assert.assertEquals(2, result0.size()); + CopyNumberSeg copyNumberSeg = result0.get(0); + Assert.assertEquals(Long.valueOf(50236594L), copyNumberSeg.getSegId()); + Assert.assertEquals((Integer) 1, copyNumberSeg.getCancerStudyId()); + Assert.assertEquals("study_tcga_pub", copyNumberSeg.getCancerStudyIdentifier()); + Assert.assertEquals((Integer) 1, copyNumberSeg.getSampleId()); + Assert.assertEquals("TCGA-A1-A0SB-01", copyNumberSeg.getSampleStableId()); + Assert.assertEquals("1", copyNumberSeg.getChr()); + Assert.assertEquals((Integer) 324556, copyNumberSeg.getStart()); + Assert.assertEquals((Integer) 180057677, copyNumberSeg.getEnd()); + Assert.assertEquals((Integer) 291, copyNumberSeg.getNumProbes()); + Assert.assertEquals(new BigDecimal("0.0519"), copyNumberSeg.getSegmentMean()); + + Assert.assertEquals(1, result1.size()); + Assert.assertEquals(1, result2.size()); + Assert.assertEquals(0, result3.size()); + } + + @Test + public void fetchSamplesWithCopyNumberSegments() throws Exception { + List studies = new ArrayList<>(); + studies.add("acc_tcga"); + List samples = new ArrayList<>(); + samples.add("TCGA-A1-B0SP-01"); + List emptyResult = + copyNumberSegmentMyBatisRepository.fetchSamplesWithCopyNumberSegments( + studies, samples, null); + Assert.assertEquals(0, emptyResult.size()); + + studies = new ArrayList<>(); + studies.add("study_tcga_pub"); + studies.add("acc_tcga"); + studies.add("acc_tcga"); + samples = new ArrayList<>(); + samples.add("TCGA-A1-A0SB-01"); + samples.add("TCGA-A1-B0SP-01"); + samples.add("TCGA-A1-B0SO-01"); + List result0 = + copyNumberSegmentMyBatisRepository.fetchSamplesWithCopyNumberSegments( + studies, samples, null); + List result1 = + copyNumberSegmentMyBatisRepository.fetchSamplesWithCopyNumberSegments( + studies, samples, "1"); + List result2 = + copyNumberSegmentMyBatisRepository.fetchSamplesWithCopyNumberSegments( + studies, samples, "2"); + List result3 = + copyNumberSegmentMyBatisRepository.fetchSamplesWithCopyNumberSegments( + studies, samples, "3"); + + Assert.assertEquals(2, result0.size()); + Assert.assertEquals((Integer) 1, result0.get(1)); + Assert.assertEquals((Integer) 15, result0.get(0)); + + Assert.assertEquals(1, result1.size()); + Assert.assertEquals((Integer) 1, result1.get(0)); + + Assert.assertEquals(2, result2.size()); + Assert.assertEquals((Integer) 1, result2.get(1)); + Assert.assertEquals((Integer) 15, result2.get(0)); + + Assert.assertEquals(0, result3.size()); + } + + @Test + public void getCopyNumberSegmentsInSampleInStudyDetailedProjection() throws Exception { + + List result = + copyNumberSegmentMyBatisRepository.getCopyNumberSegmentsInSampleInStudy( + "study_tcga_pub", "TCGA-A1-A0SB-01", null, "DETAILED", null, null, null, null); + + Assert.assertEquals(2, result.size()); + CopyNumberSeg copyNumberSeg = result.get(0); + Assert.assertEquals(Long.valueOf(50236594L), copyNumberSeg.getSegId()); + Assert.assertEquals((Integer) 1, copyNumberSeg.getCancerStudyId()); + Assert.assertEquals("study_tcga_pub", copyNumberSeg.getCancerStudyIdentifier()); + Assert.assertEquals((Integer) 1, copyNumberSeg.getSampleId()); + Assert.assertEquals("TCGA-A1-A0SB-01", copyNumberSeg.getSampleStableId()); + Assert.assertEquals("1", copyNumberSeg.getChr()); + Assert.assertEquals((Integer) 324556, copyNumberSeg.getStart()); + Assert.assertEquals((Integer) 180057677, copyNumberSeg.getEnd()); + Assert.assertEquals((Integer) 291, copyNumberSeg.getNumProbes()); + Assert.assertEquals(new BigDecimal("0.0519"), copyNumberSeg.getSegmentMean()); + } + + @Test + public void getCopyNumberSegmentsInSampleInStudySummaryProjection1PageSize() throws Exception { + + List result = + copyNumberSegmentMyBatisRepository.getCopyNumberSegmentsInSampleInStudy( + "study_tcga_pub", "TCGA-A1-A0SB-01", null, "SUMMARY", 1, 0, null, null); + + Assert.assertEquals(1, result.size()); + } + + @Test + public void getCopyNumberSegmentsInSampleInStudySummaryProjectionStartSort() throws Exception { + + List result = + copyNumberSegmentMyBatisRepository.getCopyNumberSegmentsInSampleInStudy( + "study_tcga_pub", "TCGA-A1-A0SB-01", null, "SUMMARY", null, null, "start", "ASC"); + + Assert.assertEquals(2, result.size()); + Assert.assertEquals((Integer) 224556, result.get(0).getStart()); + Assert.assertEquals((Integer) 324556, result.get(1).getStart()); + } + + @Test + public void getMetaCopyNumberSegmentsInSampleInStudy() throws Exception { + + BaseMeta result0 = + copyNumberSegmentMyBatisRepository.getMetaCopyNumberSegmentsInSampleInStudy( + "study_tcga_pub", "TCGA-A1-A0SB-01", null); + BaseMeta result1 = + copyNumberSegmentMyBatisRepository.getMetaCopyNumberSegmentsInSampleInStudy( + "study_tcga_pub", "TCGA-A1-A0SB-01", "1"); + BaseMeta result2 = + copyNumberSegmentMyBatisRepository.getMetaCopyNumberSegmentsInSampleInStudy( + "study_tcga_pub", "TCGA-A1-A0SB-01", "2"); + BaseMeta result3 = + copyNumberSegmentMyBatisRepository.getMetaCopyNumberSegmentsInSampleInStudy( + "study_tcga_pub", "TCGA-A1-A0SB-01", "3"); + + Assert.assertEquals((Integer) 2, result0.getTotalCount()); + Assert.assertEquals((Integer) 1, result1.getTotalCount()); + Assert.assertEquals((Integer) 1, result2.getTotalCount()); + Assert.assertEquals((Integer) 0, result3.getTotalCount()); + } + + @Test + public void fetchCopyNumberSegments() throws Exception { + + List studyIds = new ArrayList<>(); + studyIds.add("study_tcga_pub"); + studyIds.add("acc_tcga"); + List sampleIds = new ArrayList<>(); + sampleIds.add("TCGA-A1-A0SB-01"); + sampleIds.add("TCGA-A1-B0SO-01"); + + List result0 = + copyNumberSegmentMyBatisRepository.fetchCopyNumberSegments( + studyIds, sampleIds, null, "SUMMARY"); + List result1 = + copyNumberSegmentMyBatisRepository.fetchCopyNumberSegments( + studyIds, sampleIds, "1", "SUMMARY"); + List result2 = + copyNumberSegmentMyBatisRepository.fetchCopyNumberSegments( + studyIds, sampleIds, "2", "SUMMARY"); + List result3 = + copyNumberSegmentMyBatisRepository.fetchCopyNumberSegments( + studyIds, sampleIds, "3", "SUMMARY"); + + Assert.assertEquals(3, result0.size()); + Assert.assertEquals("TCGA-A1-A0SB-01", result0.get(0).getSampleStableId()); + Assert.assertEquals("TCGA-A1-A0SB-01", result0.get(1).getSampleStableId()); + Assert.assertEquals("TCGA-A1-B0SO-01", result0.get(2).getSampleStableId()); + + Assert.assertEquals(1, result1.size()); + Assert.assertEquals("TCGA-A1-A0SB-01", result1.get(0).getSampleStableId()); + + Assert.assertEquals(2, result2.size()); + Assert.assertEquals("TCGA-A1-A0SB-01", result2.get(0).getSampleStableId()); + Assert.assertEquals("TCGA-A1-B0SO-01", result2.get(1).getSampleStableId()); + + Assert.assertEquals(0, result3.size()); + } + + @Test + public void fetchMetaCopyNumberSegments() throws Exception { + + List studyIds = new ArrayList<>(); + studyIds.add("study_tcga_pub"); + studyIds.add("acc_tcga"); + List sampleIds = new ArrayList<>(); + sampleIds.add("TCGA-A1-A0SB-01"); + sampleIds.add("TCGA-A1-B0SO-01"); + + BaseMeta result0 = + copyNumberSegmentMyBatisRepository.fetchMetaCopyNumberSegments(studyIds, sampleIds, null); + BaseMeta result1 = + copyNumberSegmentMyBatisRepository.fetchMetaCopyNumberSegments(studyIds, sampleIds, "1"); + BaseMeta result2 = + copyNumberSegmentMyBatisRepository.fetchMetaCopyNumberSegments(studyIds, sampleIds, "2"); + BaseMeta result3 = + copyNumberSegmentMyBatisRepository.fetchMetaCopyNumberSegments(studyIds, sampleIds, "3"); + + Assert.assertEquals((Integer) 3, result0.getTotalCount()); + Assert.assertEquals((Integer) 1, result1.getTotalCount()); + Assert.assertEquals((Integer) 2, result2.getTotalCount()); + Assert.assertEquals((Integer) 0, result3.getTotalCount()); + } + + @Test + public void getCopyNumberSegmentsBySampleListId() throws Exception { + + List result0 = + copyNumberSegmentMyBatisRepository.getCopyNumberSegmentsBySampleListId( + "study_tcga_pub", "study_tcga_pub_methylation_hm27", null, "SUMMARY"); + List result1 = + copyNumberSegmentMyBatisRepository.getCopyNumberSegmentsBySampleListId( + "study_tcga_pub", "study_tcga_pub_methylation_hm27", "1", "SUMMARY"); + List result2 = + copyNumberSegmentMyBatisRepository.getCopyNumberSegmentsBySampleListId( + "study_tcga_pub", "study_tcga_pub_methylation_hm27", "2", "SUMMARY"); + + Assert.assertEquals(1, result0.size()); + CopyNumberSeg copyNumberSeg = result0.get(0); + Assert.assertEquals(Long.valueOf(50236593L), copyNumberSeg.getSegId()); + Assert.assertEquals((Integer) 1, copyNumberSeg.getCancerStudyId()); + Assert.assertEquals("study_tcga_pub", copyNumberSeg.getCancerStudyIdentifier()); + Assert.assertEquals((Integer) 2, copyNumberSeg.getSampleId()); + Assert.assertEquals("TCGA-A1-A0SD-01", copyNumberSeg.getSampleStableId()); + Assert.assertEquals("2", copyNumberSeg.getChr()); + Assert.assertEquals((Integer) 1402650, copyNumberSeg.getStart()); + Assert.assertEquals((Integer) 190262486, copyNumberSeg.getEnd()); + Assert.assertEquals((Integer) 207, copyNumberSeg.getNumProbes()); + Assert.assertEquals(new BigDecimal("0.0265"), copyNumberSeg.getSegmentMean()); + + Assert.assertEquals(0, result1.size()); + + Assert.assertEquals(1, result2.size()); + } +} diff --git a/src/test/java/org/cbioportal/legacy/persistence/mybatis/CosmicCountMyBatisRepositoryTest.java b/src/test/java/org/cbioportal/legacy/persistence/mybatis/CosmicCountMyBatisRepositoryTest.java new file mode 100644 index 00000000000..fbe6eab2fc1 --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/persistence/mybatis/CosmicCountMyBatisRepositoryTest.java @@ -0,0 +1,41 @@ +package org.cbioportal.legacy.persistence.mybatis; + +import java.util.ArrayList; +import java.util.List; +import org.cbioportal.legacy.model.CosmicMutation; +import org.cbioportal.legacy.persistence.mybatis.config.TestConfig; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +@RunWith(SpringJUnit4ClassRunner.class) +@SpringBootTest(classes = {CosmicCountMyBatisRepository.class, TestConfig.class}) +public class CosmicCountMyBatisRepositoryTest { + + @Autowired private CosmicCountMyBatisRepository cosmicCountMyBatisRepository; + + @Test + public void getCosmicCountsByKeywords() { + + List keywords = new ArrayList<>(); + keywords.add("OR4F5 D45 missense"); + keywords.add("SAMD11 P23 silent"); + + List result = + cosmicCountMyBatisRepository.fetchCosmicCountsByKeywords(keywords); + Assert.assertEquals(2, result.size()); + CosmicMutation cosmicMutation1 = result.get(0); + Assert.assertEquals("3677745", cosmicMutation1.getCosmicMutationId()); + Assert.assertEquals("D45A", cosmicMutation1.getProteinChange()); + Assert.assertEquals("OR4F5 D45 missense", cosmicMutation1.getKeyword()); + Assert.assertEquals((Integer) 1, cosmicMutation1.getCount()); + CosmicMutation cosmicMutation2 = result.get(1); + Assert.assertEquals("460103", cosmicMutation2.getCosmicMutationId()); + Assert.assertEquals("P23P", cosmicMutation2.getProteinChange()); + Assert.assertEquals("SAMD11 P23 silent", cosmicMutation2.getKeyword()); + Assert.assertEquals((Integer) 1, cosmicMutation2.getCount()); + } +} diff --git a/src/test/java/org/cbioportal/legacy/persistence/mybatis/DataAccessTokenMyBatisRepositoryTest.java b/src/test/java/org/cbioportal/legacy/persistence/mybatis/DataAccessTokenMyBatisRepositoryTest.java new file mode 100644 index 00000000000..6cb241e6471 --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/persistence/mybatis/DataAccessTokenMyBatisRepositoryTest.java @@ -0,0 +1,84 @@ +package org.cbioportal.legacy.persistence.mybatis; + +import java.util.Calendar; +import java.util.Date; +import java.util.List; +import java.util.UUID; +import org.cbioportal.legacy.model.DataAccessToken; +import org.cbioportal.legacy.persistence.mybatis.config.TestConfig; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.transaction.annotation.Transactional; + +@RunWith(SpringJUnit4ClassRunner.class) +@SpringBootTest(classes = {DataAccessTokenMyBatisRepository.class, TestConfig.class}) +public class DataAccessTokenMyBatisRepositoryTest { + + @Autowired private DataAccessTokenMyBatisRepository dataAccessTokenMyBatisRepository; + + @Test + public void getAllDataAccessTokensForUsername() { + List dataAccessTokensForMockEmail = + dataAccessTokenMyBatisRepository.getAllDataAccessTokensForUsername("mockemail@email.com"); + Assert.assertEquals(1, dataAccessTokensForMockEmail.size()); + List dataAccessTokensForMockEmail3 = + dataAccessTokenMyBatisRepository.getAllDataAccessTokensForUsername("mockemail3@email.com"); + Assert.assertEquals(3, dataAccessTokensForMockEmail3.size()); + for (DataAccessToken dataAccessToken : dataAccessTokensForMockEmail3) { + Assert.assertEquals("mockemail3@email.com", dataAccessToken.getUsername()); + } + } + + @Test + public void getDataAccessToken() { + DataAccessToken dataAccessToken = + dataAccessTokenMyBatisRepository.getDataAccessToken("6c9a641e-9719-fake-data-f17e089b37e8"); + Assert.assertEquals("6c9a641e-9719-fake-data-f17e089b37e8", dataAccessToken.getToken()); + Assert.assertEquals("mockemail2@email.com", dataAccessToken.getUsername()); + } + + @Test + @Transactional + public void addDataAccessToken() { + String uuid = UUID.randomUUID().toString(); + Calendar calendar = Calendar.getInstance(); + Date creationDate = calendar.getTime(); + calendar.add(Calendar.SECOND, 1000); + Date expirationDate = calendar.getTime(); + + DataAccessToken dataAccessToken = + new DataAccessToken(uuid, "mockemail2@email.com", expirationDate, creationDate); + dataAccessTokenMyBatisRepository.addDataAccessToken(dataAccessToken); + + DataAccessToken newDataAccessToken = dataAccessTokenMyBatisRepository.getDataAccessToken(uuid); + Assert.assertEquals(uuid, newDataAccessToken.getToken()); + Assert.assertEquals("mockemail2@email.com", newDataAccessToken.getUsername()); + Assert.assertEquals(creationDate, newDataAccessToken.getCreation()); + Assert.assertEquals(expirationDate, newDataAccessToken.getExpiration()); + } + + @Test + @Transactional + public void removeDataAccessToken() { + dataAccessTokenMyBatisRepository.removeDataAccessToken("6c9a641e-9719-fake-data-f17e089b37e8"); + List dataAccessTokensForMockEmail2 = + dataAccessTokenMyBatisRepository.getAllDataAccessTokensForUsername("mockemail2@email.com"); + Assert.assertEquals(0, dataAccessTokensForMockEmail2.size()); + } + + @Test + @Transactional + public void removeAllDataAccessTokensForUsername() { + List dataAccessTokensForMockEmail4 = + dataAccessTokenMyBatisRepository.getAllDataAccessTokensForUsername("mockemail4@email.com"); + Assert.assertEquals(3, dataAccessTokensForMockEmail4.size()); + dataAccessTokenMyBatisRepository.removeAllDataAccessTokensForUsername("mockemail4@email.com"); + List dataAccessTokensForMockEmail4AfterDeletion = + dataAccessTokenMyBatisRepository.getAllDataAccessTokensForUsername("mockemail4@email.com"); + Assert.assertEquals(0, dataAccessTokensForMockEmail4AfterDeletion.size()); + } +} diff --git a/src/test/java/org/cbioportal/legacy/persistence/mybatis/DiscreteCopyNumberMyBatisRepositoryTest.java b/src/test/java/org/cbioportal/legacy/persistence/mybatis/DiscreteCopyNumberMyBatisRepositoryTest.java new file mode 100644 index 00000000000..dd097a8c999 --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/persistence/mybatis/DiscreteCopyNumberMyBatisRepositoryTest.java @@ -0,0 +1,725 @@ +package org.cbioportal.legacy.persistence.mybatis; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Comparator; +import java.util.List; +import org.cbioportal.legacy.model.CNA; +import org.cbioportal.legacy.model.CopyNumberCountByGene; +import org.cbioportal.legacy.model.DiscreteCopyNumberData; +import org.cbioportal.legacy.model.Gene; +import org.cbioportal.legacy.model.GeneFilterQuery; +import org.cbioportal.legacy.model.ReferenceGenomeGene; +import org.cbioportal.legacy.model.meta.BaseMeta; +import org.cbioportal.legacy.model.util.Select; +import org.cbioportal.legacy.persistence.mybatis.config.TestConfig; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +@RunWith(SpringJUnit4ClassRunner.class) +@SpringBootTest( + classes = { + DiscreteCopyNumberMyBatisRepository.class, + ReferenceGenomeGeneMyBatisRepository.class, + TestConfig.class + }) +public class DiscreteCopyNumberMyBatisRepositoryTest { + + // mutation, cna and struct var events in testSql.sql + // SAMPLE_ID, ENTREZ_GENE_ID, HUGO_GENE_SYMBOL, GENETIC_PROFILE_ID, TYPE, MUTATION_TYPE, + // DRIVER_FILTER, DRIVER_TIERS_FILTER, PATIENT_ID, MUTATION_TYPE + // 1 207 AKT1 2 CNA -2 Putative_Driver Tier 1 TCGA-A1-A0SB + // germline + // 2 207 AKT1 2 CNA 2 Putative_Passenger Tier 2 TCGA-A1-A0SD + // germline + // 1 207 AKT1 6 MUTATION Nonsense_Mutation Putative_Driver Tier 1 TCGA-A1-A0SB + // germline + // 2 207 AKT1 6 MUTATION Missense_Mutation Putative_Passenger Tier 2 TCGA-A1-A0SD + // germline + // 1 208 AKT2 2 CNA 2 TCGA-A1-A0SB + // germline + // 3 208 AKT2 6 MUTATION Splice_Site Putative_Passenger Tier 1 TCGA-A1-A0SE + // germline + // 6 672 BRCA1 6 MUTATION Missense_Mutation Putative_Passenger Tier 2 TCGA-A1-A0SH + // germline + // 6 672 BRCA1 6 MUTATION Nonsense_Mutation Putative_Driver Tier 1 TCGA-A1-A0SH + // NA + // 7 672 BRCA1 6 MUTATION Nonsense_Mutation Putative_Driver Tier 2 TCGA-A1-A0SI + // germline + // 12 672 BRCA1 6 MUTATION Splice_Site Putative_Passenger Tier 1 TCGA-A1-A0SO + // germline + // 13 672 BRCA1 6 MUTATION Splice_Site Putative_Driver Tier 1 TCGA-A1-A0SP + // germline + // 1 27436-238 EML4-ALK 7 SV Fusion + // TCGA-A1-A0SB germline + // 2 27436-238 EML4-ALK 7 SV Fusion + // TCGA-A1-A0SD somatic + // 1 57670-673 KIAA..-BRAF 7 SV Fusion + // TCGA-A1-A0SB somatic + // 2 57670-673 KIAA..-BRAF 7 SV Fusion + // TCGA-A1-A0SD germline + // 2 57670-673 KIAA..-BRAF 7 SV Fusion + // TCGA-A1-A0SD somatic + // 15 57670-673 KIAA..-BRAF 13 SV Fusion + // TCGA-A1-A0SD somatic + // 1 8031-5979 NCOA4-RET 7 SV Fusion + // TCGA-A1-A0SB somatic + // 15 8031-5979 NCOA4-RET 13 SV Fusion + // TCGA-A1-A0SB somatic + // 1 7113-2078 TMPRSS2-ERG 7 SV Fusion + // TCGA-A1-A0SB somatic + // 15 8031-NULL NCOA4- 13 SV Fusion + // TCGA-A1-A0SB somatic + + @Autowired private DiscreteCopyNumberMyBatisRepository discreteCopyNumberMyBatisRepository; + + @Autowired private ReferenceGenomeGeneMyBatisRepository refGeneMyBatisRepository; + + @Before + public void init() { + molecularProfileIds = new ArrayList<>(); + molecularProfileIds.add("study_tcga_pub_gistic"); + molecularProfileIds.add("study_tcga_pub_gistic"); + sampleIds = new ArrayList<>(); + sampleIds.add("TCGA-A1-A0SB-01"); + sampleIds.add("TCGA-A1-A0SD-01"); + tiers = Select.all(); + includeUnknownTier = true; + includeDriver = true; + includeVUS = true; + includeUnknownOncogenicity = true; + cnas = Arrays.asList(CNA.AMP, CNA.HOMDEL); + } + + List molecularProfileIds = new ArrayList<>(); + List sampleIds = new ArrayList<>(); + Select tiers; + boolean includeUnknownTier; + boolean includeDriver; + boolean includeVUS; + boolean includeUnknownOncogenicity; + List cnas; + + @Test + public void getDiscreteCopyNumbersInMolecularProfileBySampleListIdSummaryProjection() + throws Exception { + + List alterations = new ArrayList<>(); + alterations.add(-2); + alterations.add(2); + + List entrezGeneIds = new ArrayList<>(); + entrezGeneIds.add(207); + entrezGeneIds.add(208); + + List result = + discreteCopyNumberMyBatisRepository.getDiscreteCopyNumbersInMolecularProfileBySampleListId( + "study_tcga_pub_gistic", "study_tcga_pub_all", entrezGeneIds, alterations, "SUMMARY"); + + Assert.assertEquals(3, result.size()); + DiscreteCopyNumberData discreteCopyNumberData = result.get(0); + Assert.assertEquals("study_tcga_pub_gistic", discreteCopyNumberData.getMolecularProfileId()); + Assert.assertEquals("TCGA-A1-A0SB-01", discreteCopyNumberData.getSampleId()); + Assert.assertEquals((Integer) 207, discreteCopyNumberData.getEntrezGeneId()); + Assert.assertEquals((Integer) (-2), discreteCopyNumberData.getAlteration()); + Assert.assertNull(discreteCopyNumberData.getGene()); + } + + @Test + public void getDiscreteCopyNumbersInMolecularProfileBySampleListIdDetailedProjection() + throws Exception { + + List alterations = new ArrayList<>(); + alterations.add(-2); + alterations.add(2); + + List entrezGeneIds = new ArrayList<>(); + entrezGeneIds.add(207); + entrezGeneIds.add(208); + + List result = + discreteCopyNumberMyBatisRepository.getDiscreteCopyNumbersInMolecularProfileBySampleListId( + "study_tcga_pub_gistic", "study_tcga_pub_all", entrezGeneIds, alterations, "DETAILED"); + + Assert.assertEquals(3, result.size()); + // We do not test order here + result.sort( + new Comparator() { + @Override + public int compare(DiscreteCopyNumberData o1, DiscreteCopyNumberData o2) { + int sampleIdCompare = o1.getSampleId().compareTo(o2.getSampleId()); + if (sampleIdCompare == 0) { + return o1.getEntrezGeneId().compareTo(o2.getEntrezGeneId()); + } + return sampleIdCompare; + } + }); + DiscreteCopyNumberData discreteCopyNumberDataB207 = result.get(0); + Assert.assertEquals( + "study_tcga_pub_gistic", discreteCopyNumberDataB207.getMolecularProfileId()); + Assert.assertEquals("TCGA-A1-A0SB-01", discreteCopyNumberDataB207.getSampleId()); + Assert.assertEquals((Integer) 207, discreteCopyNumberDataB207.getEntrezGeneId()); + Assert.assertEquals((Integer) (-2), discreteCopyNumberDataB207.getAlteration()); + Assert.assertEquals("Putative_Driver", discreteCopyNumberDataB207.getDriverFilter()); + Assert.assertEquals("Pathogenic", discreteCopyNumberDataB207.getDriverFilterAnnotation()); + Assert.assertEquals("Tier 1", discreteCopyNumberDataB207.getDriverTiersFilter()); + Assert.assertEquals( + "Highly Actionable", discreteCopyNumberDataB207.getDriverTiersFilterAnnotation()); + Gene gene = discreteCopyNumberDataB207.getGene(); + Assert.assertEquals((Integer) 207, gene.getEntrezGeneId()); + Assert.assertEquals("AKT1", gene.getHugoGeneSymbol()); + ReferenceGenomeGene refGene = + refGeneMyBatisRepository.getReferenceGenomeGene(gene.getEntrezGeneId(), "hg19"); + Assert.assertEquals("14q32.33", refGene.getCytoband()); + + DiscreteCopyNumberData discreteCopyNumberDataB208 = result.get(1); + Assert.assertEquals( + "study_tcga_pub_gistic", discreteCopyNumberDataB208.getMolecularProfileId()); + Assert.assertEquals("TCGA-A1-A0SB-01", discreteCopyNumberDataB208.getSampleId()); + Assert.assertEquals((Integer) 208, discreteCopyNumberDataB208.getEntrezGeneId()); + Assert.assertEquals((Integer) (2), discreteCopyNumberDataB208.getAlteration()); + Assert.assertNull(discreteCopyNumberDataB208.getDriverFilter()); + Assert.assertNull(discreteCopyNumberDataB208.getDriverFilterAnnotation()); + Assert.assertNull(discreteCopyNumberDataB208.getDriverTiersFilter()); + Assert.assertNull(discreteCopyNumberDataB208.getDriverTiersFilterAnnotation()); + + DiscreteCopyNumberData discreteCopyNumberDataD207 = result.get(2); + Assert.assertEquals( + "study_tcga_pub_gistic", discreteCopyNumberDataD207.getMolecularProfileId()); + Assert.assertEquals("TCGA-A1-A0SD-01", discreteCopyNumberDataD207.getSampleId()); + Assert.assertEquals((Integer) 207, discreteCopyNumberDataD207.getEntrezGeneId()); + Assert.assertEquals((Integer) (2), discreteCopyNumberDataD207.getAlteration()); + Assert.assertEquals("Putative_Passenger", discreteCopyNumberDataD207.getDriverFilter()); + Assert.assertEquals("Pathogenic", discreteCopyNumberDataD207.getDriverFilterAnnotation()); + Assert.assertEquals("Tier 2", discreteCopyNumberDataD207.getDriverTiersFilter()); + Assert.assertEquals( + "Potentially Actionable", discreteCopyNumberDataD207.getDriverTiersFilterAnnotation()); + } + + @Test + public void getMetaDiscreteCopyNumbersInMolecularProfileBySampleListId() throws Exception { + + List alterations = new ArrayList<>(); + alterations.add(-2); + alterations.add(2); + + List entrezGeneIds = new ArrayList<>(); + entrezGeneIds.add(207); + entrezGeneIds.add(208); + + BaseMeta result = + discreteCopyNumberMyBatisRepository + .getMetaDiscreteCopyNumbersInMolecularProfileBySampleListId( + "study_tcga_pub_gistic", "study_tcga_pub_all", entrezGeneIds, alterations); + + Assert.assertEquals((Integer) 3, result.getTotalCount()); + } + + @Test + public void fetchDiscreteCopyNumbersInMolecularProfile() throws Exception { + + List sampleIds = new ArrayList<>(); + sampleIds.add("TCGA-A1-A0SB-01"); + sampleIds.add("TCGA-A1-A0SD-01"); + + List alterations = new ArrayList<>(); + alterations.add(-2); + alterations.add(2); + + List entrezGeneIds = new ArrayList<>(); + entrezGeneIds.add(207); + entrezGeneIds.add(208); + + List result = + discreteCopyNumberMyBatisRepository.fetchDiscreteCopyNumbersInMolecularProfile( + "study_tcga_pub_gistic", sampleIds, entrezGeneIds, alterations, "SUMMARY"); + + Assert.assertEquals(3, result.size()); + Assert.assertEquals("study_tcga_pub_gistic", result.get(0).getMolecularProfileId()); + Assert.assertEquals("TCGA-A1-A0SB-01", result.get(0).getSampleId()); + Assert.assertEquals("study_tcga_pub_gistic", result.get(1).getMolecularProfileId()); + Assert.assertEquals("TCGA-A1-A0SD-01", result.get(1).getSampleId()); + Assert.assertEquals("study_tcga_pub_gistic", result.get(2).getMolecularProfileId()); + Assert.assertEquals("TCGA-A1-A0SB-01", result.get(2).getSampleId()); + } + + @Test + public void fetchMetaDiscreteCopyNumbersInMolecularProfile() throws Exception { + + List sampleIds = new ArrayList<>(); + sampleIds.add("TCGA-A1-A0SB-01"); + sampleIds.add("TCGA-A1-A0SD-01"); + + List alterations = new ArrayList<>(); + alterations.add(-2); + alterations.add(2); + + List entrezGeneIds = new ArrayList<>(); + entrezGeneIds.add(207); + entrezGeneIds.add(208); + + BaseMeta result = + discreteCopyNumberMyBatisRepository.fetchMetaDiscreteCopyNumbersInMolecularProfile( + "study_tcga_pub_gistic", sampleIds, entrezGeneIds, alterations); + + Assert.assertEquals((Integer) 3, result.getTotalCount()); + } + + @Test + public void getSampleCountByGeneAndAlterationAndSampleIds() throws Exception { + + List result = + discreteCopyNumberMyBatisRepository.getSampleCountByGeneAndAlterationAndSampleIds( + "study_tcga_pub_gistic", null, Arrays.asList(207, 208), Arrays.asList(-2, 2)); + + Assert.assertEquals(2, result.size()); + CopyNumberCountByGene copyNumberSampleCountByGene1 = result.get(0); + Assert.assertEquals((Integer) 207, copyNumberSampleCountByGene1.getEntrezGeneId()); + Assert.assertEquals((Integer) (-2), copyNumberSampleCountByGene1.getAlteration()); + Assert.assertEquals((Integer) 1, copyNumberSampleCountByGene1.getNumberOfAlteredCases()); + CopyNumberCountByGene copyNumberSampleCountByGene2 = result.get(1); + Assert.assertEquals((Integer) 208, copyNumberSampleCountByGene2.getEntrezGeneId()); + Assert.assertEquals((Integer) (2), copyNumberSampleCountByGene2.getAlteration()); + Assert.assertEquals((Integer) 1, copyNumberSampleCountByGene2.getNumberOfAlteredCases()); + } + + @Test + public void getDiscreteCopyNumbersInMultipleMolecularProfiles() throws Exception { + + List molecularProfileIds = new ArrayList<>(); + molecularProfileIds.add("study_tcga_pub_gistic"); + + List sampleIds = new ArrayList<>(); + sampleIds.add("TCGA-A1-A0SB-01"); + sampleIds.add("TCGA-A1-A0SD-01"); + + List alterationTypes = Arrays.asList(new Integer[] {2, -2}); + + List result = + discreteCopyNumberMyBatisRepository.getDiscreteCopyNumbersInMultipleMolecularProfiles( + molecularProfileIds, sampleIds, null, alterationTypes, "SUMMARY"); + + Assert.assertEquals(3, result.size()); + DiscreteCopyNumberData cna1 = result.get(0); + Assert.assertEquals("study_tcga_pub_gistic", cna1.getMolecularProfileId()); + Assert.assertEquals("TCGA-A1-A0SB-01", cna1.getSampleId()); + DiscreteCopyNumberData cna2 = result.get(1); + Assert.assertEquals("study_tcga_pub_gistic", cna2.getMolecularProfileId()); + Assert.assertEquals("TCGA-A1-A0SB-01", cna2.getSampleId()); + DiscreteCopyNumberData cna3 = result.get(2); + Assert.assertEquals("study_tcga_pub_gistic", cna3.getMolecularProfileId()); + Assert.assertEquals("TCGA-A1-A0SD-01", cna3.getSampleId()); + } + + @Test + public void getDiscreteCopyNumbersInMultipleMolecularProfilesByGeneQueries() throws Exception { + + GeneFilterQuery geneFilterQuery1 = + new GeneFilterQuery( + "AKT1", + 207, + cnas, + includeDriver, + includeVUS, + includeUnknownOncogenicity, + tiers, + includeUnknownTier, + false, + false, + false); + GeneFilterQuery geneFilterQuery2 = + new GeneFilterQuery( + "AKT2", + 208, + cnas, + includeDriver, + includeVUS, + includeUnknownOncogenicity, + tiers, + includeUnknownTier, + false, + false, + false); + List geneQueries = Arrays.asList(geneFilterQuery1, geneFilterQuery2); + + List result = + discreteCopyNumberMyBatisRepository + .getDiscreteCopyNumbersInMultipleMolecularProfilesByGeneQueries( + molecularProfileIds, sampleIds, geneQueries, "SUMMARY"); + + Assert.assertEquals(3, result.size()); + assert (result.stream() + .allMatch(r -> r.getMolecularProfileId().equals("study_tcga_pub_gistic"))); + List expectedSampleIds = Arrays.asList("TCGA-A1-A0SB-01", "TCGA-A1-A0SD-01"); + assert (result.stream().allMatch(r -> expectedSampleIds.contains(r.getSampleId()))); + } + + @Test + public void getDiscreteCopyNumbersInMultipleMolecularProfilesByGeneQueriesInlcudeOnlyDriver() + throws Exception { + + includeVUS = false; + includeUnknownOncogenicity = false; + + GeneFilterQuery geneFilterQuery1 = + new GeneFilterQuery( + "AKT1", + 207, + cnas, + includeDriver, + includeVUS, + includeUnknownOncogenicity, + tiers, + includeUnknownTier, + false, + false, + false); + GeneFilterQuery geneFilterQuery2 = + new GeneFilterQuery( + "AKT2", + 208, + cnas, + includeDriver, + includeVUS, + includeUnknownOncogenicity, + tiers, + includeUnknownTier, + false, + false, + false); + List geneQueries = Arrays.asList(geneFilterQuery1, geneFilterQuery2); + + List result = + discreteCopyNumberMyBatisRepository + .getDiscreteCopyNumbersInMultipleMolecularProfilesByGeneQueries( + molecularProfileIds, sampleIds, geneQueries, "SUMMARY"); + + Assert.assertEquals(1, result.size()); + assert (result.stream() + .allMatch(r -> r.getMolecularProfileId().equals("study_tcga_pub_gistic"))); + List expectedSampleIds = Arrays.asList("TCGA-A1-A0SB-01"); + assert (result.stream().allMatch(r -> expectedSampleIds.contains(r.getSampleId()))); + } + + @Test + public void getDiscreteCopyNumbersInMultipleMolecularProfilesByGeneQueriesInlcudeOnlyVus() + throws Exception { + + includeDriver = false; + includeUnknownOncogenicity = false; + + GeneFilterQuery geneFilterQuery1 = + new GeneFilterQuery( + "AKT1", + 207, + cnas, + includeDriver, + includeVUS, + includeUnknownOncogenicity, + tiers, + includeUnknownTier, + false, + false, + false); + GeneFilterQuery geneFilterQuery2 = + new GeneFilterQuery( + "AKT2", + 208, + cnas, + includeDriver, + includeVUS, + includeUnknownOncogenicity, + tiers, + includeUnknownTier, + false, + false, + false); + List geneQueries = Arrays.asList(geneFilterQuery1, geneFilterQuery2); + + List result = + discreteCopyNumberMyBatisRepository + .getDiscreteCopyNumbersInMultipleMolecularProfilesByGeneQueries( + molecularProfileIds, sampleIds, geneQueries, "SUMMARY"); + + Assert.assertEquals(1, result.size()); + assert (result.stream() + .allMatch(r -> r.getMolecularProfileId().equals("study_tcga_pub_gistic"))); + List expectedSampleIds = Arrays.asList("TCGA-A1-A0SD-01"); + assert (result.stream().allMatch(r -> expectedSampleIds.contains(r.getSampleId()))); + } + + @Test + public void + getDiscreteCopyNumbersInMultipleMolecularProfilesByGeneQueriesInlcudeOnlyUnknownOncogenicity() + throws Exception { + + includeDriver = false; + includeVUS = false; + + GeneFilterQuery geneFilterQuery1 = + new GeneFilterQuery( + "AKT1", + 207, + cnas, + includeDriver, + includeVUS, + includeUnknownOncogenicity, + tiers, + includeUnknownTier, + false, + false, + false); + GeneFilterQuery geneFilterQuery2 = + new GeneFilterQuery( + "AKT2", + 208, + cnas, + includeDriver, + includeVUS, + includeUnknownOncogenicity, + tiers, + includeUnknownTier, + false, + false, + false); + List geneQueries = Arrays.asList(geneFilterQuery1, geneFilterQuery2); + + List result = + discreteCopyNumberMyBatisRepository + .getDiscreteCopyNumbersInMultipleMolecularProfilesByGeneQueries( + molecularProfileIds, sampleIds, geneQueries, "SUMMARY"); + + Assert.assertEquals(1, result.size()); + assert (result.stream() + .allMatch(r -> r.getMolecularProfileId().equals("study_tcga_pub_gistic"))); + List expectedSampleIds = Arrays.asList("TCGA-A1-A0SB-01"); + assert (result.stream().allMatch(r -> expectedSampleIds.contains(r.getSampleId()))); + } + + @Test + public void getDiscreteCopyNumbersInMultipleMolecularProfilesByGeneQueriesFilterTiers() + throws Exception { + + Select tiers = Select.byValues(Arrays.asList("Tier 2")); + includeUnknownTier = false; + + GeneFilterQuery geneFilterQuery1 = + new GeneFilterQuery( + "AKT1", + 207, + cnas, + includeDriver, + includeVUS, + includeUnknownOncogenicity, + tiers, + includeUnknownTier, + false, + false, + false); + GeneFilterQuery geneFilterQuery2 = + new GeneFilterQuery( + "AKT2", + 208, + cnas, + includeDriver, + includeVUS, + includeUnknownOncogenicity, + tiers, + includeUnknownTier, + false, + false, + false); + List geneQueries = Arrays.asList(geneFilterQuery1, geneFilterQuery2); + + List result = + discreteCopyNumberMyBatisRepository + .getDiscreteCopyNumbersInMultipleMolecularProfilesByGeneQueries( + molecularProfileIds, sampleIds, geneQueries, "SUMMARY"); + + Assert.assertEquals(1, result.size()); + assert (result.stream() + .allMatch(r -> r.getMolecularProfileId().equals("study_tcga_pub_gistic"))); + List expectedSampleIds = Arrays.asList("TCGA-A1-A0SD-01"); + assert (result.stream().allMatch(r -> expectedSampleIds.contains(r.getSampleId()))); + } + + @Test + public void getDiscreteCopyNumbersInMultipleMolecularProfilesByGeneQueriesFilterUnknownTier() + throws Exception { + + tiers = Select.none(); + + GeneFilterQuery geneFilterQuery1 = + new GeneFilterQuery( + "BRCA1", + 672, + cnas, + includeDriver, + includeVUS, + includeUnknownOncogenicity, + tiers, + includeUnknownTier, + false, + false, + false); + GeneFilterQuery geneFilterQuery2 = + new GeneFilterQuery( + "AKT1", + 207, + cnas, + includeDriver, + includeVUS, + includeUnknownOncogenicity, + tiers, + includeUnknownTier, + false, + false, + false); + GeneFilterQuery geneFilterQuery3 = + new GeneFilterQuery( + "AKT2", + 208, + cnas, + includeDriver, + includeVUS, + includeUnknownOncogenicity, + tiers, + includeUnknownTier, + false, + false, + false); + List geneQueries = + Arrays.asList(geneFilterQuery1, geneFilterQuery2, geneFilterQuery3); + + List result = + discreteCopyNumberMyBatisRepository + .getDiscreteCopyNumbersInMultipleMolecularProfilesByGeneQueries( + molecularProfileIds, sampleIds, geneQueries, "SUMMARY"); + + Assert.assertEquals(1, result.size()); + List expectedSampleIds = Arrays.asList("TCGA-A1-A0SB-01"); + assert (result.stream().allMatch(r -> expectedSampleIds.contains(r.getSampleId()))); + } + + @Test + public void getDiscreteCopyNumbersInMultipleMolecularProfilesByGeneQueriesMixed() + throws Exception { + + Select tiers = Select.byValues(Arrays.asList("Tier 2")); + + GeneFilterQuery geneFilterQuery1 = + new GeneFilterQuery("AKT1", 207, cnas, true, true, true, tiers, false, false, false, false); + GeneFilterQuery geneFilterQuery2 = + new GeneFilterQuery( + "AKT2", 208, cnas, false, false, true, Select.all(), true, false, false, false); + List geneQueries = Arrays.asList(geneFilterQuery1, geneFilterQuery2); + + List result = + discreteCopyNumberMyBatisRepository + .getDiscreteCopyNumbersInMultipleMolecularProfilesByGeneQueries( + molecularProfileIds, sampleIds, geneQueries, "SUMMARY"); + + Assert.assertEquals(2, result.size()); + assert (result.stream() + .allMatch(r -> r.getMolecularProfileId().equals("study_tcga_pub_gistic"))); + List expectedSampleIds = Arrays.asList("TCGA-A1-A0SB-01", "TCGA-A1-A0SD-01"); + assert (result.stream().allMatch(r -> expectedSampleIds.contains(r.getSampleId()))); + } + + @Test + public void getDiscreteCopyNumbersInMultipleMolecularProfilesByGeneQueriesAmpOnly() + throws Exception { + + List cnas = Arrays.asList(CNA.AMP); + + GeneFilterQuery geneFilterQuery1 = + new GeneFilterQuery( + "AKT1", + 207, + cnas, + includeDriver, + includeVUS, + includeUnknownOncogenicity, + tiers, + includeUnknownTier, + false, + false, + false); + GeneFilterQuery geneFilterQuery2 = + new GeneFilterQuery( + "AKT2", + 208, + cnas, + includeDriver, + includeVUS, + includeUnknownOncogenicity, + tiers, + includeUnknownTier, + false, + false, + false); + List geneQueries = Arrays.asList(geneFilterQuery1, geneFilterQuery2); + + List result = + discreteCopyNumberMyBatisRepository + .getDiscreteCopyNumbersInMultipleMolecularProfilesByGeneQueries( + molecularProfileIds, sampleIds, geneQueries, "SUMMARY"); + + Assert.assertEquals(2, result.size()); + assert (result.stream() + .allMatch(r -> r.getMolecularProfileId().equals("study_tcga_pub_gistic"))); + List expectedSampleIds = Arrays.asList("TCGA-A1-A0SB-01", "TCGA-A1-A0SD-01"); + assert (result.stream().allMatch(r -> expectedSampleIds.contains(r.getSampleId()))); + } + + @Test + public void getDiscreteCopyNumbersInMultipleMolecularProfilesByGeneQueriesDeepDelOnly() + throws Exception { + + List cnas = Arrays.asList(CNA.HOMDEL); + + GeneFilterQuery geneFilterQuery1 = + new GeneFilterQuery( + "AKT1", + 207, + cnas, + includeDriver, + includeVUS, + includeUnknownOncogenicity, + tiers, + includeUnknownTier, + false, + false, + false); + GeneFilterQuery geneFilterQuery2 = + new GeneFilterQuery( + "AKT2", + 208, + cnas, + includeDriver, + includeVUS, + includeUnknownOncogenicity, + tiers, + includeUnknownTier, + false, + false, + false); + List geneQueries = Arrays.asList(geneFilterQuery1, geneFilterQuery2); + + List result = + discreteCopyNumberMyBatisRepository + .getDiscreteCopyNumbersInMultipleMolecularProfilesByGeneQueries( + molecularProfileIds, sampleIds, geneQueries, "SUMMARY"); + + Assert.assertEquals(1, result.size()); + assert (result.stream() + .allMatch(r -> r.getMolecularProfileId().equals("study_tcga_pub_gistic"))); + List expectedSampleIds = Arrays.asList("TCGA-A1-A0SB-01"); + assert (result.stream().allMatch(r -> expectedSampleIds.contains(r.getSampleId()))); + } +} diff --git a/src/test/java/org/cbioportal/legacy/persistence/mybatis/GeneMyBatisRepositoryTest.java b/src/test/java/org/cbioportal/legacy/persistence/mybatis/GeneMyBatisRepositoryTest.java new file mode 100644 index 00000000000..b903d482045 --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/persistence/mybatis/GeneMyBatisRepositoryTest.java @@ -0,0 +1,252 @@ +/* + * Copyright (c) 2016 Memorial Sloan-Kettering Cancer Center. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS + * FOR A PARTICULAR PURPOSE. The software and documentation provided hereunder + * is on an "as is" basis, and Memorial Sloan-Kettering Cancer Center has no + * obligations to provide maintenance, support, updates, enhancements or + * modifications. In no event shall Memorial Sloan-Kettering Cancer Center be + * liable to any party for direct, indirect, special, incidental or + * consequential damages, including lost profits, arising out of the use of this + * software and its documentation, even if Memorial Sloan-Kettering Cancer + * Center has been advised of the possibility of such damage. + */ + +/* + * This file is part of cBioPortal. + * + * cBioPortal is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package org.cbioportal.legacy.persistence.mybatis; + +import java.util.ArrayList; +import java.util.List; +import org.cbioportal.legacy.model.Gene; +import org.cbioportal.legacy.model.meta.BaseMeta; +import org.cbioportal.legacy.persistence.mybatis.config.TestConfig; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +@RunWith(SpringJUnit4ClassRunner.class) +@SpringBootTest(classes = {GeneMyBatisRepository.class, TestConfig.class}) +public class GeneMyBatisRepositoryTest { + + @Autowired private GeneMyBatisRepository geneMyBatisRepository; + + @Test + public void getAllGenesIdProjection() throws Exception { + + List result = geneMyBatisRepository.getAllGenes(null, null, "ID", null, null, null, null); + + Assert.assertEquals(23, result.size()); + Gene gene = result.get(0); + Assert.assertEquals((Integer) 207, gene.getEntrezGeneId()); + Assert.assertEquals("AKT1", gene.getHugoGeneSymbol()); + } + + @Test + public void getAllGenesSummaryProjection() throws Exception { + + List result = + geneMyBatisRepository.getAllGenes(null, null, "SUMMARY", null, null, null, null); + + Assert.assertEquals(23, result.size()); + Gene gene = result.get(0); + Assert.assertEquals((Integer) 207, gene.getEntrezGeneId()); + Assert.assertEquals("AKT1", gene.getHugoGeneSymbol()); + Assert.assertEquals("protein-coding", gene.getType()); + } + + @Test + public void getAllGenesDetailedProjection() throws Exception { + + List result = + geneMyBatisRepository.getAllGenes(null, null, "DETAILED", null, null, null, null); + + Assert.assertEquals(23, result.size()); + Gene gene = result.get(0); + Assert.assertEquals((Integer) 207, gene.getEntrezGeneId()); + Assert.assertEquals("AKT1", gene.getHugoGeneSymbol()); + Assert.assertEquals("protein-coding", gene.getType()); + } + + @Test + public void getAllGenesSummaryProjection1PageSize() throws Exception { + + List result = geneMyBatisRepository.getAllGenes(null, null, "SUMMARY", 1, 0, null, null); + + Assert.assertEquals(1, result.size()); + } + + @Test + public void getAllGenesSummaryProjectionHugoGeneSymbolSort() throws Exception { + + List result = + geneMyBatisRepository.getAllGenes( + null, null, "SUMMARY", null, null, "hugoGeneSymbol", "ASC"); + + Assert.assertEquals(23, result.size()); + Assert.assertEquals("AKT1", result.get(0).getHugoGeneSymbol()); + Assert.assertEquals("AKT2", result.get(1).getHugoGeneSymbol()); + Assert.assertEquals("AKT3", result.get(2).getHugoGeneSymbol()); + Assert.assertEquals("ALK", result.get(3).getHugoGeneSymbol()); + Assert.assertEquals("ARAF", result.get(4).getHugoGeneSymbol()); + Assert.assertEquals("ATM", result.get(5).getHugoGeneSymbol()); + Assert.assertEquals("BRAF", result.get(6).getHugoGeneSymbol()); + Assert.assertEquals("SAMD11", result.get(21).getHugoGeneSymbol()); + } + + @Test + public void getMetaGenes() throws Exception { + + BaseMeta result = geneMyBatisRepository.getMetaGenes(null, null); + + Assert.assertEquals((Integer) 23, result.getTotalCount()); + } + + @Test + public void getGeneByEntrezGeneIdNullResult() throws Exception { + + Gene result = geneMyBatisRepository.getGeneByEntrezGeneId(999); + + Assert.assertNull(result); + } + + @Test + public void getGeneByEntrezGeneId() throws Exception { + + Gene result = geneMyBatisRepository.getGeneByEntrezGeneId(207); + + Assert.assertEquals((Integer) 207, result.getEntrezGeneId()); + Assert.assertEquals("AKT1", result.getHugoGeneSymbol()); + Assert.assertEquals("protein-coding", result.getType()); + } + + @Test + public void getGeneByHugoGeneSymbolNullResult() throws Exception { + + Gene result = geneMyBatisRepository.getGeneByHugoGeneSymbol("invalid_gene"); + + Assert.assertNull(result); + } + + @Test + public void getGeneByHugoGeneSymbol() throws Exception { + + Gene result = geneMyBatisRepository.getGeneByHugoGeneSymbol("AKT1"); + + Assert.assertEquals((Integer) 207, result.getEntrezGeneId()); + Assert.assertEquals("AKT1", result.getHugoGeneSymbol()); + Assert.assertEquals("protein-coding", result.getType()); + } + + @Test + public void getAliasesOfGeneByEntrezGeneIdEmptyList() throws Exception { + + List result = geneMyBatisRepository.getAliasesOfGeneByEntrezGeneId(208); + + Assert.assertEquals(0, result.size()); + } + + @Test + public void getAliasesOfGeneByEntrezGeneId() throws Exception { + + List result = geneMyBatisRepository.getAliasesOfGeneByEntrezGeneId(207); + + Assert.assertEquals(2, result.size()); + Assert.assertEquals("AKT alias", result.get(0)); + Assert.assertEquals("AKT alias2", result.get(1)); + } + + @Test + public void getAliasesOfGeneByHugoGeneSymbolEmptyList() throws Exception { + + List result = geneMyBatisRepository.getAliasesOfGeneByHugoGeneSymbol("AKT2"); + + Assert.assertEquals(0, result.size()); + } + + @Test + public void getAliasesOfGeneByHugoGeneSymbol() throws Exception { + + List result = geneMyBatisRepository.getAliasesOfGeneByHugoGeneSymbol("AKT1"); + + Assert.assertEquals(2, result.size()); + Assert.assertEquals("AKT alias", result.get(0)); + Assert.assertEquals("AKT alias2", result.get(1)); + } + + @Test + public void fetchGenesByEntrezGeneIds() throws Exception { + + List entrezGeneIds = new ArrayList<>(); + entrezGeneIds.add(207); + entrezGeneIds.add(208); + + List result = geneMyBatisRepository.fetchGenesByEntrezGeneIds(entrezGeneIds, "SUMMARY"); + + Assert.assertEquals(2, result.size()); + Gene gene = result.get(0); + Assert.assertEquals((Integer) 207, gene.getEntrezGeneId()); + Assert.assertEquals("AKT1", gene.getHugoGeneSymbol()); + Assert.assertEquals("protein-coding", gene.getType()); + } + + @Test + public void fetchGenesByHugoGeneSymbols() throws Exception { + + List hugoGeneSymbols = new ArrayList<>(); + hugoGeneSymbols.add("AKT1"); + hugoGeneSymbols.add("AKT2"); + + List result = + geneMyBatisRepository.fetchGenesByHugoGeneSymbols(hugoGeneSymbols, "SUMMARY"); + + Assert.assertEquals(2, result.size()); + Gene gene = result.get(0); + Assert.assertEquals((Integer) 207, gene.getEntrezGeneId()); + Assert.assertEquals("AKT1", gene.getHugoGeneSymbol()); + Assert.assertEquals("protein-coding", gene.getType()); + } + + @Test + public void fetchMetaGenesByEntrezGeneIds() throws Exception { + + List entrezGeneIds = new ArrayList<>(); + entrezGeneIds.add(207); + entrezGeneIds.add(208); + + BaseMeta result = geneMyBatisRepository.fetchMetaGenesByEntrezGeneIds(entrezGeneIds); + + Assert.assertEquals((Integer) 2, result.getTotalCount()); + } + + @Test + public void fetchMetaGenesByHugoGeneSymbol() throws Exception { + + List hugoGeneSymbols = new ArrayList<>(); + hugoGeneSymbols.add("AKT1"); + hugoGeneSymbols.add("AKT2"); + + BaseMeta result = geneMyBatisRepository.fetchMetaGenesByHugoGeneSymbols(hugoGeneSymbols); + + Assert.assertEquals((Integer) 2, result.getTotalCount()); + } +} diff --git a/src/test/java/org/cbioportal/legacy/persistence/mybatis/GenePanelMyBatisRepositoryTest.java b/src/test/java/org/cbioportal/legacy/persistence/mybatis/GenePanelMyBatisRepositoryTest.java new file mode 100644 index 00000000000..91f1a99ab39 --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/persistence/mybatis/GenePanelMyBatisRepositoryTest.java @@ -0,0 +1,141 @@ +package org.cbioportal.legacy.persistence.mybatis; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import org.cbioportal.legacy.model.GenePanel; +import org.cbioportal.legacy.model.GenePanelData; +import org.cbioportal.legacy.model.GenePanelToGene; +import org.cbioportal.legacy.model.MolecularProfileCaseIdentifier; +import org.cbioportal.legacy.model.meta.BaseMeta; +import org.cbioportal.legacy.persistence.mybatis.config.TestConfig; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +@RunWith(SpringJUnit4ClassRunner.class) +@SpringBootTest(classes = {GenePanelMyBatisRepository.class, TestConfig.class}) +public class GenePanelMyBatisRepositoryTest { + + @Autowired private GenePanelMyBatisRepository genePanelMyBatisRepository; + + @Test + public void getAllGenePanelsIdProjection() throws Exception { + + List result = + genePanelMyBatisRepository.getAllGenePanels("ID", null, null, null, null); + + Assert.assertEquals(2, result.size()); + GenePanel genePanel = result.get(0); + Assert.assertEquals((Integer) 1, genePanel.getInternalId()); + Assert.assertEquals("TESTPANEL1", genePanel.getStableId()); + } + + @Test + public void getAllGenePanelsSummaryProjection() throws Exception { + + List result = + genePanelMyBatisRepository.getAllGenePanels("SUMMARY", null, null, null, null); + + Assert.assertEquals(2, result.size()); + GenePanel genePanel = result.get(0); + Assert.assertEquals((Integer) 1, genePanel.getInternalId()); + Assert.assertEquals("TESTPANEL1", genePanel.getStableId()); + Assert.assertEquals("A test panel consisting of a few genes", genePanel.getDescription()); + } + + @Test + public void getMetaGenePanels() throws Exception { + + BaseMeta result = genePanelMyBatisRepository.getMetaGenePanels(); + + Assert.assertEquals((Integer) 2, result.getTotalCount()); + } + + @Test + public void getGenePanelNullResult() throws Exception { + + GenePanel result = genePanelMyBatisRepository.getGenePanel("invalid_gene_panel"); + + Assert.assertNull(result); + } + + @Test + public void getGenePanel() throws Exception { + + GenePanel result = genePanelMyBatisRepository.getGenePanel("TESTPANEL1"); + + Assert.assertEquals((Integer) 1, result.getInternalId()); + Assert.assertEquals("TESTPANEL1", result.getStableId()); + Assert.assertEquals("A test panel consisting of a few genes", result.getDescription()); + } + + @Test + public void getGenePanelData() throws Exception { + + List result = + genePanelMyBatisRepository.getGenePanelDataBySampleListId( + "study_tcga_pub_mrna", "study_tcga_pub_all"); + + Assert.assertEquals(14, result.size()); + GenePanelData genePanelData = result.get(0); + Assert.assertEquals("study_tcga_pub_mrna", genePanelData.getMolecularProfileId()); + Assert.assertEquals("TESTPANEL1", genePanelData.getGenePanelId()); + Assert.assertEquals("TCGA-A1-A0SB-01", genePanelData.getSampleId()); + } + + @Test + public void fetchGenePanelData() throws Exception { + + List result = + genePanelMyBatisRepository.fetchGenePanelData( + "study_tcga_pub_mrna", Arrays.asList("TCGA-A1-A0SB-01", "TCGA-A1-A0SD-01")); + + Assert.assertEquals(2, result.size()); + GenePanelData genePanelData = result.get(0); + Assert.assertEquals("study_tcga_pub_mrna", genePanelData.getMolecularProfileId()); + Assert.assertEquals("TESTPANEL1", genePanelData.getGenePanelId()); + Assert.assertEquals("TCGA-A1-A0SB-01", genePanelData.getSampleId()); + } + + @Test + public void fetchGenePanelDataInMultipleMolecularProfiles() throws Exception { + + List molecularProfileSampleIdentifiers = new ArrayList<>(); + MolecularProfileCaseIdentifier profileCaseIdentifier = new MolecularProfileCaseIdentifier(); + profileCaseIdentifier.setMolecularProfileId("study_tcga_pub_mrna"); + profileCaseIdentifier.setCaseId("TCGA-A1-A0SB-01"); + molecularProfileSampleIdentifiers.add(profileCaseIdentifier); + + MolecularProfileCaseIdentifier profileCaseIdentifier2 = new MolecularProfileCaseIdentifier(); + profileCaseIdentifier2.setMolecularProfileId("study_tcga_pub_log2CNA"); + profileCaseIdentifier2.setCaseId("TCGA-A1-A0SD-01"); + molecularProfileSampleIdentifiers.add(profileCaseIdentifier2); + + List result = + genePanelMyBatisRepository.fetchGenePanelDataInMultipleMolecularProfiles( + molecularProfileSampleIdentifiers); + + Assert.assertEquals(2, result.size()); + GenePanelData genePanelData = result.get(0); + Assert.assertEquals("study_tcga_pub_mrna", genePanelData.getMolecularProfileId()); + Assert.assertEquals("TESTPANEL1", genePanelData.getGenePanelId()); + Assert.assertEquals("TCGA-A1-A0SB-01", genePanelData.getSampleId()); + } + + @Test + public void getGenesOfPanels() throws Exception { + + List result = + genePanelMyBatisRepository.getGenesOfPanels(Arrays.asList("TESTPANEL1")); + + Assert.assertEquals(3, result.size()); + GenePanelToGene genePanelToGene = result.get(0); + Assert.assertEquals("TESTPANEL1", genePanelToGene.getGenePanelId()); + Assert.assertEquals((Integer) 207, genePanelToGene.getEntrezGeneId()); + Assert.assertEquals("AKT1", genePanelToGene.getHugoGeneSymbol()); + } +} diff --git a/src/test/java/org/cbioportal/legacy/persistence/mybatis/GenericAssayMyBatisRepositoryTest.java b/src/test/java/org/cbioportal/legacy/persistence/mybatis/GenericAssayMyBatisRepositoryTest.java new file mode 100644 index 00000000000..8f060fb53aa --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/persistence/mybatis/GenericAssayMyBatisRepositoryTest.java @@ -0,0 +1,52 @@ +package org.cbioportal.legacy.persistence.mybatis; + +import java.util.Arrays; +import java.util.List; +import org.cbioportal.legacy.model.GenericAssayAdditionalProperty; +import org.cbioportal.legacy.model.meta.GenericAssayMeta; +import org.cbioportal.legacy.persistence.mybatis.config.TestConfig; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +@RunWith(SpringJUnit4ClassRunner.class) +@SpringBootTest(classes = {GenericAssayMyBatisRepository.class, TestConfig.class}) +public class GenericAssayMyBatisRepositoryTest { + + @Autowired private GenericAssayMyBatisRepository genericAssayMyBatisRepository; + + @Test + public void getGenericAssayMeta() { + List stableIds = Arrays.asList("mean_1", "mean_2"); + List result = genericAssayMyBatisRepository.getGenericAssayMeta(stableIds); + Assert.assertEquals(2, result.size()); + } + + @Test + public void getGenericAssayAdditionalproperties() { + List stableIds = Arrays.asList("mean_1", "mean_2"); + List result = + genericAssayMyBatisRepository.getGenericAssayAdditionalproperties(stableIds); + Assert.assertNotNull(result); + Assert.assertEquals(4, result.size()); + + for (GenericAssayAdditionalProperty additionalProperty : result) { + if (additionalProperty.getStableId().equals("mean_1")) { + if (additionalProperty.getName().equals("name")) { + Assert.assertEquals("mean_1", additionalProperty.getValue()); + } else { + Assert.assertEquals("description of mean_1", additionalProperty.getValue()); + } + } else if (additionalProperty.getStableId().equals("mean_2")) { + if (additionalProperty.getName().equals("name")) { + Assert.assertEquals("mean_2", additionalProperty.getValue()); + } else { + Assert.assertEquals("description of mean_2", additionalProperty.getValue()); + } + } + } + } +} diff --git a/src/test/java/org/cbioportal/legacy/persistence/mybatis/GenesetHierarchyMyBatisRepositoryTest.java b/src/test/java/org/cbioportal/legacy/persistence/mybatis/GenesetHierarchyMyBatisRepositoryTest.java new file mode 100644 index 00000000000..70c2a1d892c --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/persistence/mybatis/GenesetHierarchyMyBatisRepositoryTest.java @@ -0,0 +1,93 @@ +package org.cbioportal.legacy.persistence.mybatis; + +import java.util.Arrays; +import java.util.List; +import org.cbioportal.legacy.model.Geneset; +import org.cbioportal.legacy.model.GenesetHierarchyInfo; +import org.cbioportal.legacy.persistence.mybatis.config.TestConfig; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +@RunWith(SpringJUnit4ClassRunner.class) +@SpringBootTest(classes = {GenesetHierarchyMyBatisRepository.class, TestConfig.class}) +public class GenesetHierarchyMyBatisRepositoryTest { + + @Autowired private GenesetHierarchyMyBatisRepository genesetHierarchyMyBatisRepository; + + /** + * Test data is as follows: Root node -> Sub node A -> Parent node 1 -> MORF_ATRX " " " -> + * HINATA_NFKB_MATRIX " " -> Parent node 2 -> HINATA_NFKB_MATRIX Root node -> Sub node B -> x + * (dead branch) + */ + @Test + public void getGenesetHierarchySuperNodes() { + + List result = + genesetHierarchyMyBatisRepository.getGenesetHierarchySuperNodes( + Arrays.asList("MORF_ATRX", "HINATA_NFKB_MATRIX")); + // Expect Root node, Sub node A, Sub node B + Assert.assertEquals(3, result.size()); + // ordered by parentNodeName, nodeName, so Root node and then Sub node A and B: + Assert.assertEquals("Root node", result.get(0).getNodeName()); + Assert.assertEquals(null, result.get(0).getParentNodeName()); + Assert.assertEquals("Sub node A", result.get(1).getNodeName()); + Assert.assertEquals("Root node", result.get(1).getParentNodeName()); + Assert.assertEquals("Sub node B", result.get(2).getNodeName()); + Assert.assertEquals("Root node", result.get(2).getParentNodeName()); + } + + @Test + public void getGenesetHierarchyParents() { + + List result = + genesetHierarchyMyBatisRepository.getGenesetHierarchyParents( + Arrays.asList("MORF_ATRX", "HINATA_NFKB_MATRIX")); + // Expect parent node 1, parent node 2 + Assert.assertEquals(2, result.size()); + // ordered by parentNodeName, nodeName, so parent node 1 and then 2: + Assert.assertEquals("Parent node 1", result.get(0).getNodeName()); + Assert.assertEquals("Sub node A", result.get(0).getParentNodeName()); + Assert.assertEquals("Parent node 2", result.get(1).getNodeName()); + Assert.assertEquals("Sub node A", result.get(1).getParentNodeName()); + + result = + genesetHierarchyMyBatisRepository.getGenesetHierarchyParents(Arrays.asList("MORF_ATRX")); + // Expect parent node 1 + Assert.assertEquals(1, result.size()); + } + + @Test + public void getGenesetHierarchyGenesets() { + + List nodes = + genesetHierarchyMyBatisRepository.getGenesetHierarchyParents( + Arrays.asList("MORF_ATRX", "HINATA_NFKB_MATRIX")); + // Expect parent node 1, parent node 2 + Assert.assertEquals(2, nodes.size()); + // ordered by parentNodeName, nodeName, so parent node 1 and then 2: + Assert.assertEquals("Parent node 1", nodes.get(0).getNodeName()); + List result = + genesetHierarchyMyBatisRepository.getGenesetHierarchyGenesets(nodes.get(0).getNodeId()); + // Expect MORF_ATRX and HINATA_NFKB_MATRIX (but ordered by name, so HINATA first) + Assert.assertEquals(2, result.size()); + Geneset geneset = result.get(0); + Assert.assertEquals("HINATA_NFKB_MATRIX", geneset.getGenesetId()); + Assert.assertEquals("https://hinata_link", geneset.getRefLink()); + geneset = result.get(1); + Assert.assertEquals("MORF_ATRX", geneset.getGenesetId()); + Assert.assertEquals("Morf description", geneset.getDescription()); + + Assert.assertEquals("Parent node 2", nodes.get(1).getNodeName()); + result = + genesetHierarchyMyBatisRepository.getGenesetHierarchyGenesets(nodes.get(1).getNodeId()); + // Expect only HINATA_NFKB_MATRIX + Assert.assertEquals(1, result.size()); + geneset = result.get(0); + Assert.assertEquals("HINATA_NFKB_MATRIX", geneset.getGenesetId()); + Assert.assertEquals("https://hinata_link", geneset.getRefLink()); + } +} diff --git a/src/test/java/org/cbioportal/legacy/persistence/mybatis/GenesetMyBatisRepositoryTest.java b/src/test/java/org/cbioportal/legacy/persistence/mybatis/GenesetMyBatisRepositoryTest.java new file mode 100644 index 00000000000..3433daafc0d --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/persistence/mybatis/GenesetMyBatisRepositoryTest.java @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2016 Memorial Sloan-Kettering Cancer Center. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS + * FOR A PARTICULAR PURPOSE. The software and documentation provided hereunder + * is on an "as is" basis, and Memorial Sloan-Kettering Cancer Center has no + * obligations to provide maintenance, support, updates, enhancements or + * modifications. In no event shall Memorial Sloan-Kettering Cancer Center be + * liable to any party for direct, indirect, special, incidental or + * consequential damages, including lost profits, arising out of the use of this + * software and its documentation, even if Memorial Sloan-Kettering Cancer + * Center has been advised of the possibility of such damage. + */ + +/* + * This file is part of cBioPortal. + * + * cBioPortal is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package org.cbioportal.legacy.persistence.mybatis; + +import java.util.Arrays; +import java.util.List; +import org.cbioportal.legacy.model.Gene; +import org.cbioportal.legacy.model.Geneset; +import org.cbioportal.legacy.model.meta.BaseMeta; +import org.cbioportal.legacy.persistence.PersistenceConstants; +import org.cbioportal.legacy.persistence.mybatis.config.TestConfig; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +@RunWith(SpringJUnit4ClassRunner.class) +@SpringBootTest(classes = {GenesetMyBatisRepository.class, TestConfig.class}) +public class GenesetMyBatisRepositoryTest { + + @Autowired private GenesetMyBatisRepository genesetMyBatisRepository; + + @Test + public void getAllGenesets() { + // String projection, Integer pageSize, Integer pageNumber + List result = + genesetMyBatisRepository.getAllGenesets(PersistenceConstants.SUMMARY_PROJECTION, 10, 0); + Assert.assertEquals(2, result.size()); + // expect: ordered ASC by geneset id: + Geneset geneset = result.get(0); + Assert.assertEquals("HINATA_NFKB_MATRIX", geneset.getGenesetId()); + Assert.assertEquals("https://hinata_link", geneset.getRefLink()); + geneset = result.get(1); + Assert.assertEquals("MORF_ATRX", geneset.getGenesetId()); + Assert.assertEquals("Morf description", geneset.getDescription()); + } + + @Test + public void getMetaGenesets() { + + BaseMeta result = genesetMyBatisRepository.getMetaGenesets(); + Assert.assertEquals(2, result.getTotalCount().intValue()); + } + + @Test + public void getGeneset() { + + Geneset geneset = genesetMyBatisRepository.getGeneset("HINATA_NFKB_MATRIX"); + Assert.assertEquals("https://hinata_link", geneset.getRefLink()); + } + + @Test + public void fetchGenesets() { + + List result = genesetMyBatisRepository.fetchGenesets(Arrays.asList("DUMMY")); + Assert.assertEquals(0, result.size()); + result = genesetMyBatisRepository.fetchGenesets(Arrays.asList("MORF_ATRX")); + Assert.assertEquals(1, result.size()); + result = + genesetMyBatisRepository.fetchGenesets(Arrays.asList("HINATA_NFKB_MATRIX", "MORF_ATRX")); + Assert.assertEquals(2, result.size()); + + // test summary and ID projections: + result = + genesetMyBatisRepository.fetchGenesets( + Arrays.asList("MORF_ATRX", "HINATA_NFKB_MATRIX", "DUMMY")); + Assert.assertEquals(2, result.size()); + Geneset geneset = result.get(0); + // data is sorted ASC on geneset ID, so HINATA_NFKB_MATRIX is first: + Assert.assertEquals("HINATA_NFKB_MATRIX", geneset.getGenesetId()); + } + + @Test + public void getGenesByGenesetId() { + // String genesetId + List genes = genesetMyBatisRepository.getGenesByGenesetId("HINATA_NFKB_MATRIX"); + Assert.assertEquals(2, genes.size()); + Gene gene = genes.get(0); + Assert.assertEquals(369, gene.getEntrezGeneId().intValue()); + gene = genes.get(1); + Assert.assertEquals(472, gene.getEntrezGeneId().intValue()); + + genes = genesetMyBatisRepository.getGenesByGenesetId("MORF_ATRX"); + Assert.assertEquals(3, genes.size()); + gene = genes.get(0); + Assert.assertEquals(1, 207, gene.getEntrezGeneId().intValue()); + gene = genes.get(2); + Assert.assertEquals(10000, gene.getEntrezGeneId().intValue()); + } +} diff --git a/src/test/java/org/cbioportal/legacy/persistence/mybatis/MolecularDataMyBatisRepositoryTest.java b/src/test/java/org/cbioportal/legacy/persistence/mybatis/MolecularDataMyBatisRepositoryTest.java new file mode 100644 index 00000000000..d9e0797a203 --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/persistence/mybatis/MolecularDataMyBatisRepositoryTest.java @@ -0,0 +1,168 @@ +package org.cbioportal.legacy.persistence.mybatis; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import org.cbioportal.legacy.model.GeneMolecularAlteration; +import org.cbioportal.legacy.model.GenesetMolecularAlteration; +import org.cbioportal.legacy.model.MolecularProfileSamples; +import org.cbioportal.legacy.persistence.mybatis.config.TestConfig; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.transaction.annotation.Transactional; + +@RunWith(SpringJUnit4ClassRunner.class) +@SpringBootTest(classes = {MolecularDataMyBatisRepository.class, TestConfig.class}) +public class MolecularDataMyBatisRepositoryTest { + + @Autowired private MolecularDataMyBatisRepository molecularDataMyBatisRepository; + + @Test + public void getCommaSeparatedSampleIdsOfMolecularProfile() throws Exception { + + MolecularProfileSamples result = + molecularDataMyBatisRepository.getCommaSeparatedSampleIdsOfMolecularProfile( + "study_tcga_pub_gistic"); + + Assert.assertEquals("1,2,3,4,5,6,7,8,9,10,11,12,13,14,", result.getCommaSeparatedSampleIds()); + } + + @Test + public void getCommaSeparatedSampleIdsOfMolecularProfiles() throws Exception { + + Map result = + molecularDataMyBatisRepository.commaSeparatedSampleIdsOfMolecularProfilesMap( + Stream.of("study_tcga_pub_mrna", "study_tcga_pub_m_na").collect(Collectors.toSet())); + + Assert.assertEquals(2, result.size()); + Assert.assertEquals( + "1,2,3,4,5,6,7,8,9,10,11,", result.get("study_tcga_pub_m_na").getCommaSeparatedSampleIds()); + Assert.assertEquals( + "2,3,6,8,9,10,12,13,", result.get("study_tcga_pub_mrna").getCommaSeparatedSampleIds()); + } + + @Test + public void getGeneMolecularAlterations() throws Exception { + + List entrezGeneIds = new ArrayList<>(); + entrezGeneIds.add(207); + entrezGeneIds.add(208); + + List result = + molecularDataMyBatisRepository.getGeneMolecularAlterations( + "study_tcga_pub_gistic", entrezGeneIds, "SUMMARY"); + + getGeneMolecularAlterationsCommonTest(result); + } + + @Test + @Transactional(readOnly = true) + public void getGeneMolecularAlterationsIterable() throws Exception { + + List entrezGeneIds = new ArrayList<>(); + entrezGeneIds.add(207); + entrezGeneIds.add(208); + + List result = new ArrayList<>(); + Iterable gmaItr = + molecularDataMyBatisRepository.getGeneMolecularAlterationsIterable( + "study_tcga_pub_gistic", entrezGeneIds, "SUMMARY"); + for (GeneMolecularAlteration gma : gmaItr) { + result.add(gma); + } + + getGeneMolecularAlterationsCommonTest(result); + } + + private void getGeneMolecularAlterationsCommonTest(List result) { + + Assert.assertEquals(2, result.size()); + GeneMolecularAlteration molecularAlteration1 = result.get(0); + Assert.assertEquals((Integer) 207, molecularAlteration1.getEntrezGeneId()); + String[] expected = { + "-0.4674", "-0.6270", "-1.2266", "-1.2479", "-1.2262", "0.6962", "-0.3338", "-0.1264", + "0.7559", "-1.1267", "-0.5893", "-1.1546", "-1.0027", "-1.3157", "" + }; + Assert.assertArrayEquals(expected, molecularAlteration1.getSplitValues()); + GeneMolecularAlteration molecularAlteration2 = result.get(1); + Assert.assertEquals((Integer) 208, molecularAlteration2.getEntrezGeneId()); + String[] expected2 = { + "1.4146", "-0.0662", "-0.8585", "-1.6576", "-0.3552", "-0.8306", "0.8102", "0.1146", "0.3498", + "0.0349", "0.4927", "-0.8665", "-0.4754", "-0.7221", "" + }; + Assert.assertArrayEquals(expected2, molecularAlteration2.getSplitValues()); + } + + @Test + public void getGeneMolecularAlterationsInMultipleMolecularProfiles() throws Exception { + + List entrezGeneIds = new ArrayList<>(); + entrezGeneIds.add(207); + entrezGeneIds.add(208); + + List result = + molecularDataMyBatisRepository.getGeneMolecularAlterationsInMultipleMolecularProfiles( + Stream.of("study_tcga_pub_gistic", "study_tcga_pub_mrna").collect(Collectors.toSet()), + entrezGeneIds, + "SUMMARY"); + + Assert.assertEquals(3, result.size()); + GeneMolecularAlteration molecularAlteration1 = result.get(0); + Assert.assertEquals((Integer) 207, molecularAlteration1.getEntrezGeneId()); + String[] expected = { + "-0.4674", "-0.6270", "-1.2266", "-1.2479", "-1.2262", "0.6962", "-0.3338", "-0.1264", + "0.7559", "-1.1267", "-0.5893", "-1.1546", "-1.0027", "-1.3157", "" + }; + Assert.assertArrayEquals(expected, molecularAlteration1.getSplitValues()); + GeneMolecularAlteration molecularAlteration2 = result.get(1); + Assert.assertEquals((Integer) 208, molecularAlteration2.getEntrezGeneId()); + String[] expected2 = { + "1.4146", "-0.0662", "-0.8585", "-1.6576", "-0.3552", "-0.8306", "0.8102", "0.1146", "0.3498", + "0.0349", "0.4927", "-0.8665", "-0.4754", "-0.7221", "" + }; + Assert.assertArrayEquals(expected2, molecularAlteration2.getSplitValues()); + GeneMolecularAlteration molecularAlteration3 = result.get(2); + Assert.assertEquals((Integer) 208, molecularAlteration3.getEntrezGeneId()); + String[] expected3 = { + "-0.8097", "0.7360", "-1.0225", "-0.8922", "0.7247", "0.3537", "1.2702", "-0.1419", "" + }; + Assert.assertArrayEquals(expected3, molecularAlteration3.getSplitValues()); + } + + @Test + public void getGenesetMolecularAlterations() { + + String genesetId1 = "HINATA_NFKB_MATRIX"; + String genesetId2 = "MORF_ATRX"; + List genesetIds = new ArrayList<>(); + genesetIds.add(genesetId1); + genesetIds.add(genesetId2); + + List result = + molecularDataMyBatisRepository.getGenesetMolecularAlterations( + "study_tcga_pub_gsva_scores", genesetIds, "SUMMARY"); + + // expect 2 items, one for each geneset: + Assert.assertEquals(2, result.size()); + GenesetMolecularAlteration molecularAlteration1 = result.get(0); + Assert.assertEquals(genesetId1, molecularAlteration1.getGenesetId()); + String[] expected = { + "1.0106", "-0.0662", "-0.8585", "-1.6576", "-0.3552", "-0.8306", "0.8102", "0.1106", "0.3098", + "0.0309", "0.0927", "-0.8665", "-0.0750", "-0.7221", "" + }; + Assert.assertArrayEquals(expected, molecularAlteration1.getSplitValues()); + GenesetMolecularAlteration molecularAlteration2 = result.get(1); + Assert.assertEquals(genesetId2, molecularAlteration2.getGenesetId()); + String[] expected2 = { + "-0.0670", "-0.6270", "-1.2266", "-1.2079", "-1.2262", "0.6962", "-0.3338", "-0.1260", + "0.7559", "-1.1267", "-0.5893", "-1.1506", "-1.0027", "-1.3157", "" + }; + Assert.assertArrayEquals(expected2, molecularAlteration2.getSplitValues()); + } +} diff --git a/src/test/java/org/cbioportal/legacy/persistence/mybatis/MolecularProfileMyBatisRepositoryTest.java b/src/test/java/org/cbioportal/legacy/persistence/mybatis/MolecularProfileMyBatisRepositoryTest.java new file mode 100644 index 00000000000..0e93c600346 --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/persistence/mybatis/MolecularProfileMyBatisRepositoryTest.java @@ -0,0 +1,284 @@ +package org.cbioportal.legacy.persistence.mybatis; + +import static org.junit.Assert.assertArrayEquals; + +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import org.cbioportal.legacy.model.CancerStudy; +import org.cbioportal.legacy.model.MolecularProfile; +import org.cbioportal.legacy.model.meta.BaseMeta; +import org.cbioportal.legacy.persistence.mybatis.config.TestConfig; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +@RunWith(SpringJUnit4ClassRunner.class) +@SpringBootTest(classes = {MolecularProfileMyBatisRepository.class, TestConfig.class}) +public class MolecularProfileMyBatisRepositoryTest { + + @Autowired private MolecularProfileMyBatisRepository molecularProfileMyBatisRepository; + + @Test + public void getAllMolecularProfilesIdProjection() throws Exception { + + List result = + molecularProfileMyBatisRepository.getAllMolecularProfiles("ID", null, null, null, null); + + Assert.assertEquals(12, result.size()); + MolecularProfile molecularProfile = result.get(0); + Assert.assertEquals((Integer) 8, molecularProfile.getMolecularProfileId()); + Assert.assertEquals("acc_tcga_mutations", molecularProfile.getStableId()); + Assert.assertNull(molecularProfile.getCancerStudy()); + } + + @Test + public void getAllMolecularProfilesSummaryProjection() throws Exception { + + List result = + molecularProfileMyBatisRepository.getAllMolecularProfiles( + "SUMMARY", null, null, null, null); + + Assert.assertEquals(12, result.size()); + MolecularProfile molecularProfile = result.get(0); + Assert.assertEquals((Integer) 2, molecularProfile.getMolecularProfileId()); + Assert.assertEquals("study_tcga_pub_gistic", molecularProfile.getStableId()); + Assert.assertEquals((Integer) 1, molecularProfile.getCancerStudyId()); + Assert.assertEquals("study_tcga_pub", molecularProfile.getCancerStudyIdentifier()); + Assert.assertEquals( + MolecularProfile.MolecularAlterationType.COPY_NUMBER_ALTERATION, + molecularProfile.getMolecularAlterationType()); + Assert.assertEquals("DISCRETE", molecularProfile.getDatatype()); + Assert.assertEquals("Putative copy-number alterations from GISTIC", molecularProfile.getName()); + Assert.assertEquals( + "Putative copy-number from GISTIC 2.0. Values: -2 = homozygous deletion; -1 = hemizygous " + + "deletion; 0 = neutral / no change; 1 = gain; 2 = high level amplification.", + molecularProfile.getDescription()); + Assert.assertEquals(true, molecularProfile.getShowProfileInAnalysisTab()); + Assert.assertNull(molecularProfile.getCancerStudy()); + } + + @Test + public void getAllMolecularProfilesDetailedProjection() throws Exception { + + List result = + molecularProfileMyBatisRepository.getAllMolecularProfiles( + "DETAILED", null, null, null, null); + + Assert.assertEquals(12, result.size()); + MolecularProfile molecularProfile = result.get(0); + Assert.assertEquals((Integer) 2, molecularProfile.getMolecularProfileId()); + Assert.assertEquals("study_tcga_pub_gistic", molecularProfile.getStableId()); + Assert.assertEquals((Integer) 1, molecularProfile.getCancerStudyId()); + Assert.assertEquals("study_tcga_pub", molecularProfile.getCancerStudyIdentifier()); + Assert.assertEquals( + MolecularProfile.MolecularAlterationType.COPY_NUMBER_ALTERATION, + molecularProfile.getMolecularAlterationType()); + Assert.assertEquals("DISCRETE", molecularProfile.getDatatype()); + Assert.assertEquals("Putative copy-number alterations from GISTIC", molecularProfile.getName()); + Assert.assertEquals( + "Putative copy-number from GISTIC 2.0. Values: -2 = homozygous deletion; -1 = hemizygous " + + "deletion; 0 = neutral / no change; 1 = gain; 2 = high level amplification.", + molecularProfile.getDescription()); + Assert.assertEquals(true, molecularProfile.getShowProfileInAnalysisTab()); + CancerStudy cancerStudy = molecularProfile.getCancerStudy(); + Assert.assertEquals((Integer) 1, cancerStudy.getCancerStudyId()); + Assert.assertEquals("study_tcga_pub", cancerStudy.getCancerStudyIdentifier()); + Assert.assertEquals("brca", cancerStudy.getTypeOfCancerId()); + Assert.assertEquals("Breast Invasive Carcinoma (TCGA, Nature 2012)", cancerStudy.getName()); + Assert.assertEquals( + "The Cancer Genome Atlas (TCGA) Breast" + + " Invasive Carcinoma project. 825 cases.
Nature 2012. Raw data via the TCGA Data Portal.", + cancerStudy.getDescription()); + Assert.assertEquals(true, cancerStudy.getPublicStudy()); + Assert.assertEquals("23000897,26451490", cancerStudy.getPmid()); + Assert.assertEquals("TCGA, Nature 2012, ...", cancerStudy.getCitation()); + Assert.assertEquals("SU2C-PI3K;PUBLIC;GDAC", cancerStudy.getGroups()); + Assert.assertEquals((Integer) 0, cancerStudy.getStatus()); + } + + @Test + public void getAllMolecularProfilesSummaryProjection1PageSize() throws Exception { + + List result = + molecularProfileMyBatisRepository.getAllMolecularProfiles("SUMMARY", 1, 0, null, null); + + Assert.assertEquals(1, result.size()); + } + + @Test + public void getAllMolecularProfilesSummaryProjectionStableIdSort() throws Exception { + + List result = + molecularProfileMyBatisRepository.getAllMolecularProfiles( + "SUMMARY", null, null, "stableId", "ASC"); + + final List expected = + Arrays.asList( + "acc_tcga_mutations", + "acc_tcga_sv", + "study_tcga_pub_gistic", + "study_tcga_pub_gsva_scores", + "study_tcga_pub_log2CNA", + "study_tcga_pub_m_na", + "study_tcga_pub_methylation_hm27", + "study_tcga_pub_mrna", + "study_tcga_pub_mutational_signature", + "study_tcga_pub_mutations", + "study_tcga_pub_sv", + "study_tcga_pub_treatment_ic50"); + assertArrayEquals( + expected.stream().toArray(), result.stream().map(m -> m.getStableId()).toArray()); + } + + @Test + public void getMetaMolecularProfiles() throws Exception { + + BaseMeta result = molecularProfileMyBatisRepository.getMetaMolecularProfiles(); + + Assert.assertEquals((Integer) 12, result.getTotalCount()); + } + + @Test + public void getMolecularProfileNullResult() throws Exception { + + MolecularProfile result = + molecularProfileMyBatisRepository.getMolecularProfile("invalid_molecular_profile"); + + Assert.assertNull(result); + } + + @Test + public void getMolecularProfile() throws Exception { + + MolecularProfile molecularProfile = + molecularProfileMyBatisRepository.getMolecularProfile("study_tcga_pub_gistic"); + + Assert.assertEquals((Integer) 2, molecularProfile.getMolecularProfileId()); + Assert.assertEquals("study_tcga_pub_gistic", molecularProfile.getStableId()); + Assert.assertEquals((Integer) 1, molecularProfile.getCancerStudyId()); + Assert.assertEquals("study_tcga_pub", molecularProfile.getCancerStudyIdentifier()); + Assert.assertEquals( + MolecularProfile.MolecularAlterationType.COPY_NUMBER_ALTERATION, + molecularProfile.getMolecularAlterationType()); + Assert.assertEquals("DISCRETE", molecularProfile.getDatatype()); + Assert.assertEquals("Putative copy-number alterations from GISTIC", molecularProfile.getName()); + Assert.assertEquals( + "Putative copy-number from GISTIC 2.0. Values: -2 = homozygous deletion; -1 = hemizygous " + + "deletion; 0 = neutral / no change; 1 = gain; 2 = high level amplification.", + molecularProfile.getDescription()); + Assert.assertEquals(true, molecularProfile.getShowProfileInAnalysisTab()); + CancerStudy cancerStudy = molecularProfile.getCancerStudy(); + Assert.assertEquals((Integer) 1, cancerStudy.getCancerStudyId()); + Assert.assertEquals("study_tcga_pub", cancerStudy.getCancerStudyIdentifier()); + Assert.assertEquals("brca", cancerStudy.getTypeOfCancerId()); + Assert.assertEquals("Breast Invasive Carcinoma (TCGA, Nature 2012)", cancerStudy.getName()); + Assert.assertEquals( + "The Cancer Genome Atlas (TCGA) Breast" + + " Invasive Carcinoma project. 825 cases.
Nature 2012. Raw data via the TCGA Data Portal.", + cancerStudy.getDescription()); + Assert.assertEquals(true, cancerStudy.getPublicStudy()); + Assert.assertEquals("23000897,26451490", cancerStudy.getPmid()); + Assert.assertEquals("TCGA, Nature 2012, ...", cancerStudy.getCitation()); + Assert.assertEquals("SU2C-PI3K;PUBLIC;GDAC", cancerStudy.getGroups()); + Assert.assertEquals((Integer) 0, cancerStudy.getStatus()); + } + + @Test + public void getMolecularProfiles() throws Exception { + + List result = + molecularProfileMyBatisRepository.getMolecularProfiles( + Stream.of("study_tcga_pub_gistic", "study_tcga_pub_mrna").collect(Collectors.toSet()), + "SUMMARY"); + + final List expected = Arrays.asList("study_tcga_pub_gistic", "study_tcga_pub_mrna"); + assertArrayEquals( + expected.stream().toArray(), result.stream().map(m -> m.getStableId()).toArray()); + } + + @Test + public void getMetaMolecularProfilesById() throws Exception { + + BaseMeta result = + molecularProfileMyBatisRepository.getMetaMolecularProfiles( + Stream.of("study_tcga_pub_gistic", "study_tcga_pub_mrna").collect(Collectors.toSet())); + + Assert.assertEquals((Integer) 2, result.getTotalCount()); + } + + @Test + public void getAllMolecularProfilesInStudySummaryProjection() throws Exception { + + List result = + molecularProfileMyBatisRepository.getAllMolecularProfilesInStudy( + "study_tcga_pub", "SUMMARY", null, null, null, null); + + Assert.assertEquals(10, result.size()); + MolecularProfile molecularProfile = result.get(0); + Assert.assertEquals((Integer) 2, molecularProfile.getMolecularProfileId()); + Assert.assertEquals("study_tcga_pub_gistic", molecularProfile.getStableId()); + Assert.assertEquals((Integer) 1, molecularProfile.getCancerStudyId()); + Assert.assertEquals("study_tcga_pub", molecularProfile.getCancerStudyIdentifier()); + Assert.assertEquals( + MolecularProfile.MolecularAlterationType.COPY_NUMBER_ALTERATION, + molecularProfile.getMolecularAlterationType()); + Assert.assertEquals("DISCRETE", molecularProfile.getDatatype()); + Assert.assertEquals("Putative copy-number alterations from GISTIC", molecularProfile.getName()); + Assert.assertEquals( + "Putative copy-number from GISTIC 2.0. Values: -2 = homozygous deletion; -1 = hemizygous " + + "deletion; 0 = neutral / no change; 1 = gain; 2 = high level amplification.", + molecularProfile.getDescription()); + Assert.assertEquals(true, molecularProfile.getShowProfileInAnalysisTab()); + Assert.assertNull(molecularProfile.getCancerStudy()); + } + + @Test + public void getMetaMolecularProfilesInStudy() throws Exception { + + BaseMeta result = + molecularProfileMyBatisRepository.getMetaMolecularProfilesInStudy("study_tcga_pub"); + + Assert.assertEquals((Integer) 10, result.getTotalCount()); + } + + @Test + public void getMolecularProfilesInStudies() throws Exception { + + List result = + molecularProfileMyBatisRepository.getMolecularProfilesInStudies( + Arrays.asList("study_tcga_pub", "acc_tcga"), "SUMMARY"); + + Assert.assertEquals(12, result.size()); + MolecularProfile molecularProfile = result.get(0); + Assert.assertEquals((Integer) 8, molecularProfile.getMolecularProfileId()); + Assert.assertEquals("acc_tcga_mutations", molecularProfile.getStableId()); + Assert.assertEquals((Integer) 2, molecularProfile.getCancerStudyId()); + Assert.assertEquals("acc_tcga", molecularProfile.getCancerStudyIdentifier()); + Assert.assertEquals( + MolecularProfile.MolecularAlterationType.MUTATION_EXTENDED, + molecularProfile.getMolecularAlterationType()); + Assert.assertEquals("MAF", molecularProfile.getDatatype()); + Assert.assertEquals("Mutations", molecularProfile.getName()); + Assert.assertEquals( + "Mutation data from whole exome sequencing.", molecularProfile.getDescription()); + Assert.assertEquals(true, molecularProfile.getShowProfileInAnalysisTab()); + Assert.assertNull(molecularProfile.getCancerStudy()); + } + + @Test + public void getMetaMolecularProfilesInStudies() throws Exception { + + BaseMeta result = + molecularProfileMyBatisRepository.getMetaMolecularProfilesInStudies( + Arrays.asList("study_tcga_pub", "acc_tcga")); + + Assert.assertEquals((Integer) 12, result.getTotalCount()); + } +} diff --git a/src/test/java/org/cbioportal/legacy/persistence/mybatis/MutationMyBatisRepositoryTest.java b/src/test/java/org/cbioportal/legacy/persistence/mybatis/MutationMyBatisRepositoryTest.java new file mode 100644 index 00000000000..eb2e088c7b0 --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/persistence/mybatis/MutationMyBatisRepositoryTest.java @@ -0,0 +1,1010 @@ +package org.cbioportal.legacy.persistence.mybatis; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Optional; +import java.util.stream.Collectors; +import org.cbioportal.legacy.model.AlleleSpecificCopyNumber; +import org.cbioportal.legacy.model.Gene; +import org.cbioportal.legacy.model.GeneFilterQuery; +import org.cbioportal.legacy.model.GenomicDataCountItem; +import org.cbioportal.legacy.model.Mutation; +import org.cbioportal.legacy.model.MutationCountByPosition; +import org.cbioportal.legacy.model.meta.MutationMeta; +import org.cbioportal.legacy.model.util.Select; +import org.cbioportal.legacy.persistence.mybatis.config.TestConfig; +import org.cbioportal.legacy.persistence.mybatis.util.MolecularProfileCaseIdentifierUtil; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +@RunWith(SpringJUnit4ClassRunner.class) +@SpringBootTest( + classes = { + MutationMyBatisRepository.class, + MolecularProfileCaseIdentifierUtil.class, + TestConfig.class + }) +public class MutationMyBatisRepositoryTest { + + // mutation, cna and struct var events in testSql.sql + // SAMPLE_ID, ENTREZ_GENE_ID, HUGO_GENE_SYMBOL, GENETIC_PROFILE_ID, TYPE, MUTATION_TYPE, + // DRIVER_FILTER, DRIVER_TIERS_FILTER, PATIENT_ID, MUTATION_TYPE + // 1 207 AKT1 2 CNA -2 Putative_Driver Tier 1 TCGA-A1-A0SB + // germline + // 2 207 AKT1 2 CNA 2 Putative_Passenger Tier 2 TCGA-A1-A0SD + // germline + // 1 207 AKT1 6 MUTATION Nonsense_Mutation Putative_Driver Tier 1 TCGA-A1-A0SB + // germline + // 2 207 AKT1 6 MUTATION Missense_Mutation Putative_Passenger Tier 2 TCGA-A1-A0SD + // germline + // 1 208 AKT2 2 CNA 2 TCGA-A1-A0SB + // germline + // 3 208 AKT2 6 MUTATION Splice_Site Putative_Passenger Tier 1 TCGA-A1-A0SE + // germline + // 6 672 BRCA1 6 MUTATION Missense_Mutation Putative_Passenger Tier 2 TCGA-A1-A0SH + // germline + // 6 672 BRCA1 6 MUTATION Nonsense_Mutation Putative_Driver Tier 1 TCGA-A1-A0SH + // NA + // 7 672 BRCA1 6 MUTATION Nonsense_Mutation Putative_Driver Tier 2 TCGA-A1-A0SI + // germline + // 12 672 BRCA1 6 MUTATION Splice_Site Putative_Passenger Tier 1 TCGA-A1-A0SO + // germline + // 13 672 BRCA1 6 MUTATION Splice_Site Putative_Driver Tier 1 TCGA-A1-A0SP + // germline + // 1 27436-238 EML4-ALK 7 SV Fusion + // TCGA-A1-A0SB germline + // 2 27436-238 EML4-ALK 7 SV Fusion + // TCGA-A1-A0SD somatic + // 1 57670-673 KIAA..-BRAF 7 SV Fusion + // TCGA-A1-A0SB somatic + // 2 57670-673 KIAA..-BRAF 7 SV Fusion + // TCGA-A1-A0SD germline + // 2 57670-673 KIAA..-BRAF 7 SV Fusion + // TCGA-A1-A0SD somatic + // 15 57670-673 KIAA..-BRAF 13 SV Fusion + // TCGA-A1-A0SD somatic + // 1 8031-5979 NCOA4-RET 7 SV Fusion + // TCGA-A1-A0SB somatic + // 15 8031-5979 NCOA4-RET 13 SV Fusion + // TCGA-A1-A0SB somatic + // 1 7113-2078 TMPRSS2-ERG 7 SV Fusion + // TCGA-A1-A0SB somatic + // 15 8031-NULL NCOA4- 13 SV Fusion + // TCGA-A1-A0SB somatic + + @Autowired private MutationMyBatisRepository mutationMyBatisRepository; + + @Before + public void init() { + molecularProfileIds = new ArrayList<>(); + molecularProfileIds.add("study_tcga_pub_mutations"); + molecularProfileIds.add("study_tcga_pub_mutations"); + molecularProfileIds.add("study_tcga_pub_mutations"); + molecularProfileIds.add("study_tcga_pub_mutations"); + molecularProfileIds.add("study_tcga_pub_mutations"); + molecularProfileIds.add("study_tcga_pub_mutations"); + molecularProfileIds.add("study_tcga_pub_mutations"); + molecularProfileIds.add("study_tcga_pub_mutations"); + sampleIds = new ArrayList<>(); + sampleIds.add("TCGA-A1-B0SO-01"); + sampleIds.add("TCGA-A1-A0SB-01"); + sampleIds.add("TCGA-A1-A0SD-01"); + sampleIds.add("TCGA-A1-A0SE-01"); + sampleIds.add("TCGA-A1-A0SH-01"); + sampleIds.add("TCGA-A1-A0SI-01"); + sampleIds.add("TCGA-A1-A0SO-01"); + sampleIds.add("TCGA-A1-A0SP-01"); + tiers = Select.all(); + includeUnknownTier = true; + includeDriver = true; + includeVUS = true; + includeUnknownOncogenicity = true; + includeGermline = true; + includeSomatic = true; + includeUnknownStatus = true; + } + + List molecularProfileIds = new ArrayList<>(); + List sampleIds = new ArrayList<>(); + Select tiers; + boolean includeUnknownTier; + boolean includeDriver; + boolean includeVUS; + boolean includeUnknownOncogenicity; + boolean includeGermline; + boolean includeSomatic; + boolean includeUnknownStatus; + + @Test + public void getMutationsInMolecularProfileBySampleListIdIdProjection() throws Exception { + + List result = + mutationMyBatisRepository.getMutationsInMolecularProfileBySampleListId( + "study_tcga_pub_mutations", + "study_tcga_pub_all", + null, + false, + "ID", + null, + null, + null, + null); + + Assert.assertEquals(8, result.size()); + Mutation mutation = result.get(0); + Assert.assertEquals("study_tcga_pub_mutations", mutation.getMolecularProfileId()); + Assert.assertEquals("TCGA-A1-A0SB-01", mutation.getSampleId()); + Assert.assertEquals((Integer) 207, mutation.getEntrezGeneId()); + } + + @Test + public void getMutationsInMolecularProfileBySampleListIdSummaryProjection() throws Exception { + + List result = + mutationMyBatisRepository.getMutationsInMolecularProfileBySampleListId( + "study_tcga_pub_mutations", + "study_tcga_pub_all", + null, + false, + "SUMMARY", + null, + null, + null, + null); + + Assert.assertEquals(8, result.size()); + + Optional mutationOptional = + result.stream().filter(r -> r.getSampleId().equals("TCGA-A1-A0SB-01")).findAny(); + Assert.assertTrue(mutationOptional.isPresent()); + Mutation mutation = mutationOptional.get(); + + Assert.assertEquals("study_tcga_pub_mutations", mutation.getMolecularProfileId()); + Assert.assertEquals((Integer) 207, mutation.getEntrezGeneId()); + Assert.assertEquals("cyclases/Protein", mutation.getAminoAcidChange()); + Assert.assertEquals("genome.wustl.edu", mutation.getCenter()); + Assert.assertEquals((Long) 41244748L, mutation.getEndPosition()); + Assert.assertEquals("BRCA1 truncating", mutation.getKeyword()); + Assert.assertEquals("Germline", mutation.getMutationStatus()); + Assert.assertEquals("Nonsense_Mutation", mutation.getMutationType()); + Assert.assertEquals("37", mutation.getNcbiBuild()); + Assert.assertEquals((Integer) (-1), mutation.getNormalAltCount()); + Assert.assertEquals((Integer) (-1), mutation.getNormalRefCount()); + Assert.assertEquals((Integer) 934, mutation.getProteinPosEnd()); + Assert.assertEquals((Integer) 934, mutation.getProteinPosStart()); + Assert.assertEquals("NM_007294", mutation.getRefseqMrnaId()); + Assert.assertEquals("Q934*", mutation.getProteinChange()); + Assert.assertEquals("G", mutation.getReferenceAllele()); + Assert.assertEquals((Long) 41244748L, mutation.getStartPosition()); + Assert.assertEquals((Integer) (-1), mutation.getTumorAltCount()); + Assert.assertEquals((Integer) (-1), mutation.getTumorRefCount()); + Assert.assertEquals("A", mutation.getTumorSeqAllele()); + Assert.assertEquals("Unknown", mutation.getValidationStatus()); + Assert.assertEquals("SNP", mutation.getVariantType()); + Assert.assertEquals("Putative_Driver", mutation.getDriverFilter()); + Assert.assertEquals("Pathogenic", mutation.getDriverFilterAnnotation()); + Assert.assertEquals("Tier 1", mutation.getDriverTiersFilter()); + Assert.assertEquals("Highly Actionable", mutation.getDriverTiersFilterAnnotation()); + } + + @Test + public void getMutationsInMolecularProfileBySampleListIdAndEntrezGeneIdsSummaryProjection() + throws Exception { + + List entrezGeneIds = new ArrayList<>(); + entrezGeneIds.add(207); + entrezGeneIds.add(208); + + List result = + mutationMyBatisRepository.getMutationsInMolecularProfileBySampleListId( + "study_tcga_pub_mutations", + "study_tcga_pub_all", + entrezGeneIds, + false, + "SUMMARY", + null, + null, + null, + null); + + Assert.assertEquals(3, result.size()); + Optional mutationOptional = + result.stream().filter(r -> r.getSampleId().equals("TCGA-A1-A0SB-01")).findAny(); + Assert.assertTrue(mutationOptional.isPresent()); + Mutation mutation = mutationOptional.get(); + + Assert.assertEquals("study_tcga_pub_mutations", mutation.getMolecularProfileId()); + Assert.assertEquals("TCGA-A1-A0SB-01", mutation.getSampleId()); + Assert.assertEquals((Integer) 207, mutation.getEntrezGeneId()); + Assert.assertEquals("cyclases/Protein", mutation.getAminoAcidChange()); + Assert.assertEquals("genome.wustl.edu", mutation.getCenter()); + Assert.assertEquals((Long) 41244748L, mutation.getEndPosition()); + Assert.assertEquals("BRCA1 truncating", mutation.getKeyword()); + Assert.assertEquals("Germline", mutation.getMutationStatus()); + Assert.assertEquals("Nonsense_Mutation", mutation.getMutationType()); + Assert.assertEquals("37", mutation.getNcbiBuild()); + Assert.assertEquals((Integer) (-1), mutation.getNormalAltCount()); + Assert.assertEquals((Integer) (-1), mutation.getNormalRefCount()); + Assert.assertEquals((Integer) 934, mutation.getProteinPosEnd()); + Assert.assertEquals((Integer) 934, mutation.getProteinPosStart()); + Assert.assertEquals("NM_007294", mutation.getRefseqMrnaId()); + Assert.assertEquals("Q934*", mutation.getProteinChange()); + Assert.assertEquals("G", mutation.getReferenceAllele()); + Assert.assertEquals((Long) 41244748L, mutation.getStartPosition()); + Assert.assertEquals((Integer) (-1), mutation.getTumorAltCount()); + Assert.assertEquals((Integer) (-1), mutation.getTumorRefCount()); + Assert.assertEquals("A", mutation.getTumorSeqAllele()); + Assert.assertEquals("Unknown", mutation.getValidationStatus()); + Assert.assertEquals("SNP", mutation.getVariantType()); + Assert.assertEquals("Putative_Driver", mutation.getDriverFilter()); + Assert.assertEquals("Pathogenic", mutation.getDriverFilterAnnotation()); + Assert.assertEquals("Tier 1", mutation.getDriverTiersFilter()); + Assert.assertEquals("Highly Actionable", mutation.getDriverTiersFilterAnnotation()); + } + + @Test + public void getMutationsInMolecularProfileBySampleListIdDetailedProjection() throws Exception { + + List result = + mutationMyBatisRepository.getMutationsInMolecularProfileBySampleListId( + "study_tcga_pub_mutations", + "study_tcga_pub_all", + null, + false, + "DETAILED", + null, + null, + null, + null); + + Assert.assertEquals(8, result.size()); + + Optional mutationOptional = + result.stream().filter(r -> r.getSampleId().equals("TCGA-A1-A0SB-01")).findAny(); + Assert.assertTrue(mutationOptional.isPresent()); + Mutation mutation = mutationOptional.get(); + + Assert.assertEquals("study_tcga_pub_mutations", mutation.getMolecularProfileId()); + Assert.assertEquals("TCGA-A1-A0SB-01", mutation.getSampleId()); + Assert.assertEquals((Integer) 207, mutation.getEntrezGeneId()); + Assert.assertEquals("cyclases/Protein", mutation.getAminoAcidChange()); + Assert.assertEquals("genome.wustl.edu", mutation.getCenter()); + Assert.assertEquals((Long) 41244748L, mutation.getEndPosition()); + Assert.assertEquals("BRCA1 truncating", mutation.getKeyword()); + Assert.assertEquals("Germline", mutation.getMutationStatus()); + Assert.assertEquals("Nonsense_Mutation", mutation.getMutationType()); + Assert.assertEquals("37", mutation.getNcbiBuild()); + Assert.assertEquals((Integer) (-1), mutation.getNormalAltCount()); + Assert.assertEquals((Integer) (-1), mutation.getNormalRefCount()); + Assert.assertEquals((Integer) 934, mutation.getProteinPosEnd()); + Assert.assertEquals((Integer) 934, mutation.getProteinPosStart()); + Assert.assertEquals("NM_007294", mutation.getRefseqMrnaId()); + Assert.assertEquals("Q934*", mutation.getProteinChange()); + Assert.assertEquals("G", mutation.getReferenceAllele()); + Assert.assertEquals((Long) 41244748L, mutation.getStartPosition()); + Assert.assertEquals((Integer) (-1), mutation.getTumorAltCount()); + Assert.assertEquals((Integer) (-1), mutation.getTumorRefCount()); + Assert.assertEquals("A", mutation.getTumorSeqAllele()); + Assert.assertEquals("Unknown", mutation.getValidationStatus()); + Assert.assertEquals("SNP", mutation.getVariantType()); + Assert.assertEquals("Putative_Driver", mutation.getDriverFilter()); + Assert.assertEquals("Pathogenic", mutation.getDriverFilterAnnotation()); + Assert.assertEquals("Tier 1", mutation.getDriverTiersFilter()); + Assert.assertEquals("Highly Actionable", mutation.getDriverTiersFilterAnnotation()); + Gene gene = mutation.getGene(); + Assert.assertEquals((Integer) 207, gene.getEntrezGeneId()); + Assert.assertEquals("AKT1", gene.getHugoGeneSymbol()); + Assert.assertEquals("protein-coding", gene.getType()); + AlleleSpecificCopyNumber alleleSpecificCopyNumber = mutation.getAlleleSpecificCopyNumber(); + Assert.assertEquals((Integer) (3), alleleSpecificCopyNumber.getAscnIntegerCopyNumber()); + Assert.assertEquals("FACETS", alleleSpecificCopyNumber.getAscnMethod()); + Assert.assertEquals((Float) (1.25f), alleleSpecificCopyNumber.getCcfExpectedCopiesUpper()); + Assert.assertEquals((Float) (1.75f), alleleSpecificCopyNumber.getCcfExpectedCopies()); + Assert.assertEquals("CLONAL", alleleSpecificCopyNumber.getClonal()); + Assert.assertEquals((Integer) (2), alleleSpecificCopyNumber.getMinorCopyNumber()); + Assert.assertEquals((Integer) (1), alleleSpecificCopyNumber.getExpectedAltCopies()); + Assert.assertEquals((Integer) (4), alleleSpecificCopyNumber.getTotalCopyNumber()); + } + + @Test + public void getMutationsInMolecularProfileBySampleListIdSummaryProjection1PageSize() + throws Exception { + + List result = + mutationMyBatisRepository.getMutationsInMolecularProfileBySampleListId( + "study_tcga_pub_mutations", + "study_tcga_pub_all", + null, + false, + "SUMMARY", + 1, + 0, + null, + null); + + Assert.assertEquals(1, result.size()); + } + + @Test + public void getMutationsInMolecularProfileBySampleListIdSummaryProjectionProteinChangeSort() + throws Exception { + + List result = + mutationMyBatisRepository.getMutationsInMolecularProfileBySampleListId( + "study_tcga_pub_mutations", + "study_tcga_pub_all", + null, + false, + "SUMMARY", + null, + null, + "proteinChange", + "ASC"); + + Assert.assertEquals(8, result.size()); + Assert.assertEquals("C27_splice", result.get(0).getProteinChange()); + Assert.assertEquals("C27_splice", result.get(1).getProteinChange()); + Assert.assertEquals("C27_splice", result.get(2).getProteinChange()); + Assert.assertEquals("C61G", result.get(3).getProteinChange()); + } + + @Test + public void getMetaMutationsInMolecularProfileBySampleListId() throws Exception { + + MutationMeta result = + mutationMyBatisRepository.getMetaMutationsInMolecularProfileBySampleListId( + "study_tcga_pub_mutations", "study_tcga_pub_all", null); + + Assert.assertEquals((Integer) 8, result.getTotalCount()); + Assert.assertEquals((Integer) 7, result.getSampleCount()); + } + + @Test + public void getMetaMutationsInMolecularProfileBySampleListIdAndEntrezGeneIds() throws Exception { + + List entrezGeneIds = new ArrayList<>(); + entrezGeneIds.add(207); + entrezGeneIds.add(208); + + MutationMeta result = + mutationMyBatisRepository.getMetaMutationsInMolecularProfileBySampleListId( + "study_tcga_pub_mutations", "study_tcga_pub_all", entrezGeneIds); + + Assert.assertEquals((Integer) 3, result.getTotalCount()); + Assert.assertEquals((Integer) 3, result.getSampleCount()); + } + + @Test + public void getMutationsInMultipleMolecularProfiles() throws Exception { + + List molecularProfileIds = new ArrayList<>(); + molecularProfileIds.add("acc_tcga_mutations"); + molecularProfileIds.add("study_tcga_pub_mutations"); + + List sampleIds = new ArrayList<>(); + sampleIds.add("TCGA-A1-B0SO-01"); + sampleIds.add("TCGA-A1-A0SH-01"); + + List result = + mutationMyBatisRepository.getMutationsInMultipleMolecularProfiles( + molecularProfileIds, sampleIds, null, "SUMMARY", null, null, null, null); + + Assert.assertEquals(3, result.size()); + + Optional sampleOmutationOptional = + result.stream() + .filter( + r -> + r.getSampleId().equals("TCGA-A1-B0SO-01") + && r.getMolecularProfileId().equals("acc_tcga_mutations")) + .findAny(); + + List sampleHmutations = + result.stream() + .filter( + r -> + r.getSampleId().equals("TCGA-A1-A0SH-01") + && r.getMolecularProfileId().equals("study_tcga_pub_mutations")) + .collect(Collectors.toList()); + + Assert.assertEquals(2, sampleHmutations.size()); + Assert.assertTrue(sampleOmutationOptional.isPresent()); + } + + @Test + public void getMutationsInMultipleMolecularProfilesByGeneQueries() throws Exception { + + GeneFilterQuery geneFilterQuery1 = + new GeneFilterQuery( + "BRCA1", + 672, + null, + includeDriver, + includeVUS, + includeUnknownOncogenicity, + tiers, + includeUnknownTier, + includeGermline, + includeSomatic, + includeUnknownStatus); + GeneFilterQuery geneFilterQuery2 = + new GeneFilterQuery( + "AKT1", + 207, + null, + includeDriver, + includeVUS, + includeUnknownOncogenicity, + tiers, + includeUnknownTier, + includeGermline, + includeSomatic, + includeUnknownStatus); + GeneFilterQuery geneFilterQuery3 = + new GeneFilterQuery( + "AKT2", + 208, + null, + includeDriver, + includeVUS, + includeUnknownOncogenicity, + tiers, + includeUnknownTier, + includeGermline, + includeSomatic, + includeUnknownStatus); + List geneQueries = + Arrays.asList(geneFilterQuery1, geneFilterQuery2, geneFilterQuery3); + + List result = + mutationMyBatisRepository.getMutationsInMultipleMolecularProfilesByGeneQueries( + molecularProfileIds, sampleIds, geneQueries, "SUMMARY", null, null, null, null); + + Assert.assertEquals(8, result.size()); + } + + @Test + public void getMutationsInMultipleMolecularProfilesByGeneQueriesIncludeOnlyGermline() + throws Exception { + + includeSomatic = false; + includeUnknownStatus = false; + + GeneFilterQuery geneFilterQuery1 = + new GeneFilterQuery( + "BRCA1", + 672, + null, + includeDriver, + includeVUS, + includeUnknownOncogenicity, + tiers, + includeUnknownTier, + includeGermline, + includeSomatic, + includeUnknownStatus); + GeneFilterQuery geneFilterQuery2 = + new GeneFilterQuery( + "AKT1", + 207, + null, + includeDriver, + includeVUS, + includeUnknownOncogenicity, + tiers, + includeUnknownTier, + includeGermline, + includeSomatic, + includeUnknownStatus); + GeneFilterQuery geneFilterQuery3 = + new GeneFilterQuery( + "AKT2", + 208, + null, + includeDriver, + includeVUS, + includeUnknownOncogenicity, + tiers, + includeUnknownTier, + includeGermline, + includeSomatic, + includeUnknownStatus); + List geneQueries = + Arrays.asList(geneFilterQuery1, geneFilterQuery2, geneFilterQuery3); + + List result = + mutationMyBatisRepository.getMutationsInMultipleMolecularProfilesByGeneQueries( + molecularProfileIds, sampleIds, geneQueries, "SUMMARY", null, null, null, null); + + Assert.assertEquals(7, result.size()); + } + + @Test + public void getMutationsInMultipleMolecularProfilesByGeneQueriesIncludeOnlySomatic() + throws Exception { + + includeGermline = false; + includeUnknownStatus = false; + + GeneFilterQuery geneFilterQuery1 = + new GeneFilterQuery( + "BRCA1", + 672, + null, + includeDriver, + includeVUS, + includeUnknownOncogenicity, + tiers, + includeUnknownTier, + includeGermline, + includeSomatic, + includeUnknownStatus); + GeneFilterQuery geneFilterQuery2 = + new GeneFilterQuery( + "AKT1", + 207, + null, + includeDriver, + includeVUS, + includeUnknownOncogenicity, + tiers, + includeUnknownTier, + includeGermline, + includeSomatic, + includeUnknownStatus); + GeneFilterQuery geneFilterQuery3 = + new GeneFilterQuery( + "AKT2", + 208, + null, + includeDriver, + includeVUS, + includeUnknownOncogenicity, + tiers, + includeUnknownTier, + includeGermline, + includeSomatic, + includeUnknownStatus); + List geneQueries = + Arrays.asList(geneFilterQuery1, geneFilterQuery2, geneFilterQuery3); + + List result = + mutationMyBatisRepository.getMutationsInMultipleMolecularProfilesByGeneQueries( + molecularProfileIds, sampleIds, geneQueries, "SUMMARY", null, null, null, null); + + Assert.assertEquals(0, result.size()); + } + + @Test + public void getMutationsInMultipleMolecularProfilesByGeneQueriesIncludeOnlyUnknownStatus() + throws Exception { + + includeSomatic = false; + includeGermline = false; + + GeneFilterQuery geneFilterQuery1 = + new GeneFilterQuery( + "BRCA1", + 672, + null, + includeDriver, + includeVUS, + includeUnknownOncogenicity, + tiers, + includeUnknownTier, + includeGermline, + includeSomatic, + includeUnknownStatus); + GeneFilterQuery geneFilterQuery2 = + new GeneFilterQuery( + "AKT1", + 207, + null, + includeDriver, + includeVUS, + includeUnknownOncogenicity, + tiers, + includeUnknownTier, + includeGermline, + includeSomatic, + includeUnknownStatus); + GeneFilterQuery geneFilterQuery3 = + new GeneFilterQuery( + "AKT2", + 208, + null, + includeDriver, + includeVUS, + includeUnknownOncogenicity, + tiers, + includeUnknownTier, + includeGermline, + includeSomatic, + includeUnknownStatus); + List geneQueries = + Arrays.asList(geneFilterQuery1, geneFilterQuery2, geneFilterQuery3); + + List result = + mutationMyBatisRepository.getMutationsInMultipleMolecularProfilesByGeneQueries( + molecularProfileIds, sampleIds, geneQueries, "SUMMARY", null, null, null, null); + + Assert.assertEquals(1, result.size()); + } + + @Test + public void getMutationsInMultipleMolecularProfilesByGeneQueriesIncludeOnlyDriver() + throws Exception { + + includeVUS = false; + includeUnknownOncogenicity = false; + + GeneFilterQuery geneFilterQuery1 = + new GeneFilterQuery( + "BRCA1", + 672, + null, + includeDriver, + includeVUS, + includeUnknownOncogenicity, + tiers, + includeUnknownTier, + includeGermline, + includeSomatic, + includeUnknownStatus); + GeneFilterQuery geneFilterQuery2 = + new GeneFilterQuery( + "AKT1", + 207, + null, + includeDriver, + includeVUS, + includeUnknownOncogenicity, + tiers, + includeUnknownTier, + includeGermline, + includeSomatic, + includeUnknownStatus); + GeneFilterQuery geneFilterQuery3 = + new GeneFilterQuery( + "AKT2", + 208, + null, + includeDriver, + includeVUS, + includeUnknownOncogenicity, + tiers, + includeUnknownTier, + includeGermline, + includeSomatic, + includeUnknownStatus); + List geneQueries = + Arrays.asList(geneFilterQuery1, geneFilterQuery2, geneFilterQuery3); + + List result = + mutationMyBatisRepository.getMutationsInMultipleMolecularProfilesByGeneQueries( + molecularProfileIds, sampleIds, geneQueries, "SUMMARY", null, null, null, null); + + Assert.assertEquals(4, result.size()); + List expectedSampleIds = + Arrays.asList("TCGA-A1-A0SB-01", "TCGA-A1-A0SH-01", "TCGA-A1-A0SI-01", "TCGA-A1-A0SP-01"); + Assert.assertTrue(result.stream().allMatch(r -> expectedSampleIds.contains(r.getSampleId()))); + } + + @Test + public void getMutationsInMultipleMolecularProfilesByGeneQueriesIncludeOnlyVUS() + throws Exception { + + includeDriver = false; + includeUnknownOncogenicity = false; + + GeneFilterQuery geneFilterQuery1 = + new GeneFilterQuery( + "BRCA1", + 672, + null, + includeDriver, + includeVUS, + includeUnknownOncogenicity, + tiers, + includeUnknownTier, + includeGermline, + includeSomatic, + includeUnknownStatus); + GeneFilterQuery geneFilterQuery2 = + new GeneFilterQuery( + "AKT1", + 207, + null, + includeDriver, + includeVUS, + includeUnknownOncogenicity, + tiers, + includeUnknownTier, + includeGermline, + includeSomatic, + includeUnknownStatus); + GeneFilterQuery geneFilterQuery3 = + new GeneFilterQuery( + "AKT2", + 208, + null, + includeDriver, + includeVUS, + includeUnknownOncogenicity, + tiers, + includeUnknownTier, + includeGermline, + includeSomatic, + includeUnknownStatus); + List geneQueries = + Arrays.asList(geneFilterQuery1, geneFilterQuery2, geneFilterQuery3); + + List result = + mutationMyBatisRepository.getMutationsInMultipleMolecularProfilesByGeneQueries( + molecularProfileIds, sampleIds, geneQueries, "SUMMARY", null, null, null, null); + + Assert.assertEquals(4, result.size()); + List expectedSampleIds = + Arrays.asList("TCGA-A1-A0SD-01", "TCGA-A1-A0SE-01", "TCGA-A1-A0SH-01", "TCGA-A1-A0SO-01"); + Assert.assertTrue(result.stream().allMatch(r -> expectedSampleIds.contains(r.getSampleId()))); + } + + @Test + public void getMutationsInMultipleMolecularProfilesByGeneQueriesIncludeOnlyUnknownOncogenicity() + throws Exception { + + includeDriver = false; + includeVUS = false; + + GeneFilterQuery geneFilterQuery1 = + new GeneFilterQuery( + "BRCA1", + 672, + null, + includeDriver, + includeVUS, + includeUnknownOncogenicity, + tiers, + includeUnknownTier, + includeGermline, + includeSomatic, + includeUnknownStatus); + GeneFilterQuery geneFilterQuery2 = + new GeneFilterQuery( + "AKT1", + 207, + null, + includeDriver, + includeVUS, + includeUnknownOncogenicity, + tiers, + includeUnknownTier, + includeGermline, + includeSomatic, + includeUnknownStatus); + GeneFilterQuery geneFilterQuery3 = + new GeneFilterQuery( + "AKT2", + 208, + null, + includeDriver, + includeVUS, + includeUnknownOncogenicity, + tiers, + includeUnknownTier, + includeGermline, + includeSomatic, + includeUnknownStatus); + List geneQueries = + Arrays.asList(geneFilterQuery1, geneFilterQuery2, geneFilterQuery3); + + List result = + mutationMyBatisRepository.getMutationsInMultipleMolecularProfilesByGeneQueries( + molecularProfileIds, sampleIds, geneQueries, "SUMMARY", null, null, null, null); + + Assert.assertEquals(0, result.size()); + } + + @Test + public void getMutationsInMultipleMolecularProfilesByGeneQueriesFilterTiers() throws Exception { + + Select tiers = Select.byValues(Arrays.asList("Tier 2")); + includeUnknownTier = false; + + GeneFilterQuery geneFilterQuery1 = + new GeneFilterQuery( + "BRCA1", + 672, + null, + includeDriver, + includeVUS, + includeUnknownOncogenicity, + tiers, + includeUnknownTier, + includeGermline, + includeSomatic, + includeUnknownStatus); + GeneFilterQuery geneFilterQuery2 = + new GeneFilterQuery( + "AKT1", + 207, + null, + includeDriver, + includeVUS, + includeUnknownOncogenicity, + tiers, + includeUnknownTier, + includeGermline, + includeSomatic, + includeUnknownStatus); + GeneFilterQuery geneFilterQuery3 = + new GeneFilterQuery( + "AKT2", + 208, + null, + includeDriver, + includeVUS, + includeUnknownOncogenicity, + tiers, + includeUnknownTier, + includeGermline, + includeSomatic, + includeUnknownStatus); + List geneQueries = + Arrays.asList(geneFilterQuery1, geneFilterQuery2, geneFilterQuery3); + + List result = + mutationMyBatisRepository.getMutationsInMultipleMolecularProfilesByGeneQueries( + molecularProfileIds, sampleIds, geneQueries, "SUMMARY", null, null, null, null); + + Assert.assertEquals(3, result.size()); + List expectedSampleIds = + Arrays.asList("TCGA-A1-A0SD-01", "TCGA-A1-A0SH-01", "TCGA-A1-A0SI-01"); + Assert.assertTrue(result.stream().allMatch(r -> expectedSampleIds.contains(r.getSampleId()))); + } + + @Test + public void getMutationsInMultipleMolecularProfilesByGeneQueriesMixed() throws Exception { + + // BRCA1 - VUS only + // AKT1 - Tier1 only + // AKT2 - driver only + GeneFilterQuery geneFilterQuery1 = + new GeneFilterQuery( + "BRCA1", + 672, + null, + false, + true, + false, + Select.all(), + true, + includeGermline, + includeSomatic, + includeUnknownStatus); + GeneFilterQuery geneFilterQuery2 = + new GeneFilterQuery( + "AKT1", + 207, + null, + includeDriver, + includeVUS, + includeUnknownOncogenicity, + Select.byValues(Arrays.asList("Tier 1")), + false, + includeGermline, + includeSomatic, + includeUnknownStatus); + GeneFilterQuery geneFilterQuery3 = + new GeneFilterQuery( + "AKT2", + 208, + null, + true, + false, + false, + Select.all(), + true, + includeGermline, + includeSomatic, + includeUnknownStatus); + List geneQueries = + Arrays.asList(geneFilterQuery1, geneFilterQuery2, geneFilterQuery3); + + List result = + mutationMyBatisRepository.getMutationsInMultipleMolecularProfilesByGeneQueries( + molecularProfileIds, sampleIds, geneQueries, "SUMMARY", null, null, null, null); + + Assert.assertEquals(3, result.size()); + List expectedSampleIds = + Arrays.asList("TCGA-A1-A0SB-01", "TCGA-A1-A0SH-01", "TCGA-A1-A0SO-01"); + Assert.assertTrue(result.stream().allMatch(r -> expectedSampleIds.contains(r.getSampleId()))); + } + + @Test + public void getMetaMutationsInMultipleMolecularProfiles() throws Exception { + + List molecularProfileIds = new ArrayList<>(); + molecularProfileIds.add("acc_tcga_mutations"); + molecularProfileIds.add("study_tcga_pub_mutations"); + + List sampleIds = new ArrayList<>(); + sampleIds.add("TCGA-A1-B0SO-01"); + sampleIds.add("TCGA-A1-A0SH-01"); + + MutationMeta result = + mutationMyBatisRepository.getMetaMutationsInMultipleMolecularProfiles( + molecularProfileIds, sampleIds, null); + + Assert.assertEquals((Integer) 3, result.getTotalCount()); + Assert.assertEquals((Integer) 2, result.getSampleCount()); + } + + @Test + public void fetchMutationsInMolecularProfile() throws Exception { + + List sampleIds = new ArrayList<>(); + sampleIds.add("TCGA-A1-A0SH-01"); + sampleIds.add("TCGA-A1-A0SO-01"); + + List result = + mutationMyBatisRepository.fetchMutationsInMolecularProfile( + "study_tcga_pub_mutations", sampleIds, null, false, "SUMMARY", null, null, null, null); + + Assert.assertEquals(3, result.size()); + Assert.assertEquals("study_tcga_pub_mutations", result.get(0).getMolecularProfileId()); + Assert.assertEquals("TCGA-A1-A0SH-01", result.get(0).getSampleId()); + Assert.assertEquals("study_tcga_pub_mutations", result.get(1).getMolecularProfileId()); + Assert.assertEquals("TCGA-A1-A0SH-01", result.get(1).getSampleId()); + Assert.assertEquals("study_tcga_pub_mutations", result.get(2).getMolecularProfileId()); + Assert.assertEquals("TCGA-A1-A0SO-01", result.get(2).getSampleId()); + } + + @Test + public void fetchMetaMutationsInMolecularProfile() throws Exception { + + List sampleIds = new ArrayList<>(); + sampleIds.add("TCGA-A1-A0SH-01"); + sampleIds.add("TCGA-A1-A0SO-01"); + + MutationMeta result = + mutationMyBatisRepository.fetchMetaMutationsInMolecularProfile( + "study_tcga_pub_mutations", sampleIds, null); + + Assert.assertEquals((Integer) 3, result.getTotalCount()); + Assert.assertEquals((Integer) 2, result.getSampleCount()); + } + + @Test + public void getMutationCountByPosition() throws Exception { + + MutationCountByPosition result = + mutationMyBatisRepository.getMutationCountByPosition(672, 61, 936); + + Assert.assertEquals((Integer) 672, result.getEntrezGeneId()); + Assert.assertEquals((Integer) 61, result.getProteinPosStart()); + Assert.assertEquals((Integer) 936, result.getProteinPosEnd()); + Assert.assertEquals((Integer) 3, result.getCount()); + } + + @Test + public void getMutationCountsByType() { + GenomicDataCountItem result = + mutationMyBatisRepository.getMutationCountsByType( + Collections.singletonList("study_tcga_pub_mutations"), + sampleIds, + Collections.singletonList(207), + "mutations"); + + Assert.assertEquals("AKT1", result.getHugoGeneSymbol()); + Assert.assertEquals("mutations", result.getProfileType()); + Assert.assertEquals(2, result.getCounts().size()); + } +} diff --git a/src/test/java/org/cbioportal/legacy/persistence/mybatis/PatientMyBatisRepositoryTest.java b/src/test/java/org/cbioportal/legacy/persistence/mybatis/PatientMyBatisRepositoryTest.java new file mode 100644 index 00000000000..ee5283bcb40 --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/persistence/mybatis/PatientMyBatisRepositoryTest.java @@ -0,0 +1,231 @@ +package org.cbioportal.legacy.persistence.mybatis; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; +import org.cbioportal.legacy.model.CancerStudy; +import org.cbioportal.legacy.model.Patient; +import org.cbioportal.legacy.model.meta.BaseMeta; +import org.cbioportal.legacy.persistence.mybatis.config.TestConfig; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +@RunWith(SpringJUnit4ClassRunner.class) +@SpringBootTest(classes = {PatientMyBatisRepository.class, TestConfig.class}) +public class PatientMyBatisRepositoryTest { + + @Autowired private PatientMyBatisRepository patientMyBatisRepository; + + @Test + public void getAllPatients() throws Exception { + + List result = + patientMyBatisRepository.getAllPatients(null, "ID", null, null, null, null); + + Assert.assertEquals(18, result.size()); + Patient patient = result.get(0); + Assert.assertEquals((Integer) 1, patient.getInternalId()); + Assert.assertEquals("TCGA-A1-A0SB", patient.getStableId()); + Assert.assertNull(patient.getCancerStudy()); + } + + @Test + public void getAllPatientsByKeywordMatchingSample() { + // Sample TCGA-A1-A0SB-02 belongs to patient TCGA-A1-A0SB + List result = + patientMyBatisRepository.getAllPatients("TCGA-A1-A0SB-02", "ID", null, null, null, null); + List actual = result.stream().map(Patient::getStableId).collect(Collectors.toList()); + List expected = Collections.singletonList("TCGA-A1-A0SB"); + + Assert.assertEquals(expected, actual); + } + + @Test + public void getMetaPatients() throws Exception { + + BaseMeta result = patientMyBatisRepository.getMetaPatients(null); + + Assert.assertEquals((Integer) 18, result.getTotalCount()); + } + + @Test + public void getAllPatientsInStudyIdProjection() throws Exception { + + List result = + patientMyBatisRepository.getAllPatientsInStudy( + "study_tcga_pub", "ID", null, null, null, null); + + Assert.assertEquals(14, result.size()); + Patient patient = result.get(0); + Assert.assertEquals((Integer) 1, patient.getInternalId()); + Assert.assertEquals("TCGA-A1-A0SB", patient.getStableId()); + Assert.assertNull(patient.getCancerStudy()); + } + + @Test + public void getAllPatientsInStudySummaryProjection() throws Exception { + + List result = + patientMyBatisRepository.getAllPatientsInStudy( + "study_tcga_pub", "SUMMARY", null, null, null, null); + + Assert.assertEquals(14, result.size()); + Patient patient = result.get(0); + Assert.assertEquals((Integer) 1, patient.getInternalId()); + Assert.assertEquals("TCGA-A1-A0SB", patient.getStableId()); + Assert.assertEquals((Integer) 1, patient.getCancerStudyId()); + Assert.assertEquals("study_tcga_pub", patient.getCancerStudyIdentifier()); + Assert.assertNull(patient.getCancerStudy()); + } + + @Test + public void getAllPatientsInStudyDetailedProjection() throws Exception { + + List result = + patientMyBatisRepository.getAllPatientsInStudy( + "study_tcga_pub", "DETAILED", null, null, null, null); + + Assert.assertEquals(14, result.size()); + Patient patient = result.get(0); + Assert.assertEquals((Integer) 1, patient.getInternalId()); + Assert.assertEquals("TCGA-A1-A0SB", patient.getStableId()); + Assert.assertEquals((Integer) 1, patient.getCancerStudyId()); + Assert.assertEquals("study_tcga_pub", patient.getCancerStudyIdentifier()); + CancerStudy cancerStudy = patient.getCancerStudy(); + Assert.assertEquals((Integer) 1, cancerStudy.getCancerStudyId()); + Assert.assertEquals("study_tcga_pub", cancerStudy.getCancerStudyIdentifier()); + Assert.assertEquals("brca", cancerStudy.getTypeOfCancerId()); + Assert.assertEquals("Breast Invasive Carcinoma (TCGA, Nature 2012)", cancerStudy.getName()); + Assert.assertEquals( + "The Cancer Genome Atlas (TCGA) Breast" + + " Invasive Carcinoma project. 825 cases.
Nature 2012. Raw data via the TCGA Data Portal.", + cancerStudy.getDescription()); + Assert.assertEquals(true, cancerStudy.getPublicStudy()); + Assert.assertEquals("23000897,26451490", cancerStudy.getPmid()); + Assert.assertEquals("TCGA, Nature 2012, ...", cancerStudy.getCitation()); + Assert.assertEquals("SU2C-PI3K;PUBLIC;GDAC", cancerStudy.getGroups()); + Assert.assertEquals((Integer) 0, cancerStudy.getStatus()); + } + + @Test + public void getAllPatientsInStudySummaryProjection1PageSize() throws Exception { + + List result = + patientMyBatisRepository.getAllPatientsInStudy( + "study_tcga_pub", "SUMMARY", 1, 0, null, null); + + Assert.assertEquals(1, result.size()); + } + + @Test + public void getAllPatientsInStudySummaryProjectionStableIdSort() throws Exception { + + List result = + patientMyBatisRepository.getAllPatientsInStudy( + "study_tcga_pub", "SUMMARY", null, null, "stableId", "ASC"); + + Assert.assertEquals(14, result.size()); + Assert.assertEquals("TCGA-A1-A0SB", result.get(0).getStableId()); + Assert.assertEquals("TCGA-A1-A0SD", result.get(1).getStableId()); + Assert.assertEquals("TCGA-A1-A0SE", result.get(2).getStableId()); + Assert.assertEquals("TCGA-A1-A0SF", result.get(3).getStableId()); + Assert.assertEquals("TCGA-A1-A0SG", result.get(4).getStableId()); + Assert.assertEquals("TCGA-A1-A0SH", result.get(5).getStableId()); + } + + @Test + public void getMetaPatientsInStudy() throws Exception { + + BaseMeta result = patientMyBatisRepository.getMetaPatientsInStudy("study_tcga_pub"); + + Assert.assertEquals((Integer) 14, result.getTotalCount()); + } + + @Test + public void getPatientInStudyNullResult() throws Exception { + + Patient result = + patientMyBatisRepository.getPatientInStudy("study_tcga_pub", "invalid_patient"); + + Assert.assertNull(result); + } + + @Test + public void getPatientInStudy() throws Exception { + + Patient patient = patientMyBatisRepository.getPatientInStudy("study_tcga_pub", "TCGA-A1-A0SI"); + + Assert.assertEquals((Integer) 7, patient.getInternalId()); + Assert.assertEquals("TCGA-A1-A0SI", patient.getStableId()); + Assert.assertEquals((Integer) 1, patient.getCancerStudyId()); + Assert.assertEquals("study_tcga_pub", patient.getCancerStudyIdentifier()); + CancerStudy cancerStudy = patient.getCancerStudy(); + Assert.assertEquals((Integer) 1, cancerStudy.getCancerStudyId()); + Assert.assertEquals("study_tcga_pub", cancerStudy.getCancerStudyIdentifier()); + Assert.assertEquals("brca", cancerStudy.getTypeOfCancerId()); + Assert.assertEquals("Breast Invasive Carcinoma (TCGA, Nature 2012)", cancerStudy.getName()); + Assert.assertEquals( + "The Cancer Genome Atlas (TCGA) Breast" + + " Invasive Carcinoma project. 825 cases.
Nature 2012. Raw data via the TCGA Data Portal.", + cancerStudy.getDescription()); + Assert.assertEquals(true, cancerStudy.getPublicStudy()); + Assert.assertEquals("23000897,26451490", cancerStudy.getPmid()); + Assert.assertEquals("TCGA, Nature 2012, ...", cancerStudy.getCitation()); + Assert.assertEquals("SU2C-PI3K;PUBLIC;GDAC", cancerStudy.getGroups()); + Assert.assertEquals((Integer) 0, cancerStudy.getStatus()); + } + + @Test + public void fetchPatients() throws Exception { + + List studyIds = new ArrayList<>(); + studyIds.add("study_tcga_pub"); + studyIds.add("study_tcga_pub"); + List patientIds = new ArrayList<>(); + patientIds.add("TCGA-A1-A0SB"); + patientIds.add("TCGA-A1-A0SE"); + + List result = patientMyBatisRepository.fetchPatients(studyIds, patientIds, "SUMMARY"); + + Assert.assertEquals(2, result.size()); + Assert.assertEquals("TCGA-A1-A0SB", result.get(0).getStableId()); + Assert.assertEquals("TCGA-A1-A0SE", result.get(1).getStableId()); + } + + @Test + public void fetchMetaPatients() throws Exception { + + List studyIds = new ArrayList<>(); + studyIds.add("study_tcga_pub"); + studyIds.add("study_tcga_pub"); + List patientIds = new ArrayList<>(); + patientIds.add("TCGA-A1-A0SB"); + patientIds.add("TCGA-A1-A0SE"); + + BaseMeta result = patientMyBatisRepository.fetchMetaPatients(studyIds, patientIds); + + Assert.assertEquals((Integer) 2, result.getTotalCount()); + } + + @Test + public void getPatientIdsOfSamples() throws Exception { + + List result = + patientMyBatisRepository.getPatientsOfSamples( + Arrays.asList("study_tcga_pub", "study_tcga_pub", "study_tcga_pub"), + Arrays.asList("TCGA-A1-A0SB-01", "TCGA-A1-A0SD-01", "TCGA-A1-A0SB-02")); + + Assert.assertEquals(2, result.size()); + List stableIds = result.stream().map(r -> r.getStableId()).collect(Collectors.toList()); + Assert.assertTrue(stableIds.contains("TCGA-A1-A0SD")); + Assert.assertTrue(stableIds.contains("TCGA-A1-A0SB")); + } +} diff --git a/src/test/java/org/cbioportal/legacy/persistence/mybatis/ReferenceGenomeGeneMyBatisRepositoryTest.java b/src/test/java/org/cbioportal/legacy/persistence/mybatis/ReferenceGenomeGeneMyBatisRepositoryTest.java new file mode 100644 index 00000000000..60d95ba7216 --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/persistence/mybatis/ReferenceGenomeGeneMyBatisRepositoryTest.java @@ -0,0 +1,75 @@ +package org.cbioportal.legacy.persistence.mybatis; + +import java.util.ArrayList; +import java.util.List; +import org.cbioportal.legacy.model.Gene; +import org.cbioportal.legacy.model.ReferenceGenome; +import org.cbioportal.legacy.model.ReferenceGenomeGene; +import org.cbioportal.legacy.persistence.mybatis.config.TestConfig; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +@RunWith(SpringJUnit4ClassRunner.class) +@SpringBootTest( + classes = { + ReferenceGenomeGeneMyBatisRepository.class, + GeneMyBatisRepository.class, + TestConfig.class + }) +public class ReferenceGenomeGeneMyBatisRepositoryTest { + + @Autowired private ReferenceGenomeGeneMyBatisRepository refGeneMyBatisRepository; + + @Autowired private GeneMyBatisRepository geneMyBatisRepository; + + @Test + public void getAllGenesByGenomeName() throws Exception { + List result = + refGeneMyBatisRepository.getAllGenesByGenomeName( + ReferenceGenome.HOMO_SAPIENS_DEFAULT_GENOME_NAME); + ReferenceGenomeGene refGene = result.get(0); + Gene gene = geneMyBatisRepository.getGeneByEntrezGeneId(refGene.getEntrezGeneId()); + Assert.assertEquals((Integer) 207, gene.getEntrezGeneId()); + Assert.assertEquals("AKT1", gene.getHugoGeneSymbol()); + } + + @Test + public void getReferenceGenomeGene() throws Exception { + String genomeName = ReferenceGenome.HOMO_SAPIENS_DEFAULT_GENOME_NAME; + ReferenceGenomeGene refGene = refGeneMyBatisRepository.getReferenceGenomeGene(207, genomeName); + Gene gene = geneMyBatisRepository.getGeneByEntrezGeneId(refGene.getEntrezGeneId()); + Assert.assertEquals((Integer) 207, gene.getEntrezGeneId()); + Assert.assertEquals("AKT1", gene.getHugoGeneSymbol()); + Assert.assertEquals("14q32.33", refGene.getCytoband()); + } + + @Test + public void getReferenceGenomeGeneByEntityId() throws Exception { + ReferenceGenomeGene refGene = + refGeneMyBatisRepository.getReferenceGenomeGeneByEntityId((Integer) 2, "hg38"); + Gene gene = geneMyBatisRepository.getGeneByEntrezGeneId(refGene.getEntrezGeneId()); + Assert.assertEquals((Integer) 208, gene.getEntrezGeneId()); + Assert.assertEquals("AKT2", gene.getHugoGeneSymbol()); + Assert.assertEquals("19q13.2", refGene.getCytoband()); + } + + @Test + public void getGenesByGenomeName() throws Exception { + List geneIds = new ArrayList<>(); + geneIds.add((Integer) 207); + geneIds.add((Integer) 208); + List result = + refGeneMyBatisRepository.getGenesByGenomeName( + geneIds, ReferenceGenome.HOMO_SAPIENS_DEFAULT_GENOME_NAME); + Assert.assertEquals(2, result.size()); + ReferenceGenomeGene refGene = result.get(0); + Gene gene = geneMyBatisRepository.getGeneByEntrezGeneId(refGene.getEntrezGeneId()); + Assert.assertEquals((Integer) 207, gene.getEntrezGeneId()); + Assert.assertEquals("AKT1", gene.getHugoGeneSymbol()); + Assert.assertEquals("14q32.33", refGene.getCytoband()); + } +} diff --git a/src/test/java/org/cbioportal/legacy/persistence/mybatis/ResourceDataMyBatisRepositoryTest.java b/src/test/java/org/cbioportal/legacy/persistence/mybatis/ResourceDataMyBatisRepositoryTest.java new file mode 100644 index 00000000000..51c23f152f1 --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/persistence/mybatis/ResourceDataMyBatisRepositoryTest.java @@ -0,0 +1,153 @@ +package org.cbioportal.legacy.persistence.mybatis; + +import java.util.List; +import org.cbioportal.legacy.model.ResourceData; +import org.cbioportal.legacy.model.ResourceDefinition; +import org.cbioportal.legacy.model.ResourceType; +import org.cbioportal.legacy.persistence.mybatis.config.TestConfig; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +@RunWith(SpringJUnit4ClassRunner.class) +@SpringBootTest(classes = {ResourceDataMyBatisRepository.class, TestConfig.class}) +public class ResourceDataMyBatisRepositoryTest { + + @Autowired private ResourceDataMyBatisRepository resourceDataMyBatisRepository; + + @Test + public void getAllResourceDataOfSampleInStudyIdProjection() throws Exception { + + List result = + resourceDataMyBatisRepository.getAllResourceDataOfSampleInStudy( + "study_tcga_pub", null, null, "ID", null, null, null, null); + + Assert.assertEquals(7, result.size()); + ResourceData resourceData = result.get(0); + Assert.assertEquals("TCGA-A1-A0SB-01", resourceData.getSampleId()); + Assert.assertEquals("TCGA-A1-A0SB", resourceData.getPatientId()); + Assert.assertEquals("HE", resourceData.getResourceId()); + Assert.assertNull(resourceData.getUrl()); + Assert.assertNull(resourceData.getResourceDefinition()); + } + + @Test + public void getAllResourceDataOfSampleInStudySummaryProjection() throws Exception { + + List result = + resourceDataMyBatisRepository.getAllResourceDataOfSampleInStudy( + "study_tcga_pub", null, null, "SUMMARY", null, null, null, null); + + Assert.assertEquals(7, result.size()); + ResourceData resourceData = result.get(0); + Assert.assertEquals("TCGA-A1-A0SB-01", resourceData.getSampleId()); + Assert.assertEquals("TCGA-A1-A0SB", resourceData.getPatientId()); + Assert.assertEquals("HE", resourceData.getResourceId()); + Assert.assertEquals( + "https://upload.wikimedia.org/wikipedia/commons/8/80/Breast_DCIS_histopathology_%281%29.jpg", + resourceData.getUrl()); + Assert.assertNull(resourceData.getResourceDefinition()); + } + + @Test + public void getAllResourceDataOfSampleInStudyDetailedProjection() throws Exception { + + List result = + resourceDataMyBatisRepository.getAllResourceDataOfSampleInStudy( + "study_tcga_pub", null, null, "DETAILED", null, null, null, null); + + Assert.assertEquals(7, result.size()); + ResourceData resourceData = result.get(0); + Assert.assertEquals("TCGA-A1-A0SB-01", resourceData.getSampleId()); + Assert.assertEquals("TCGA-A1-A0SB", resourceData.getPatientId()); + Assert.assertEquals("HE", resourceData.getResourceId()); + Assert.assertEquals( + "https://upload.wikimedia.org/wikipedia/commons/8/80/Breast_DCIS_histopathology_%281%29.jpg", + resourceData.getUrl()); + ResourceDefinition resourceDefinition = resourceData.getResourceDefinition(); + Assert.assertEquals("H&E Slide", resourceDefinition.getDisplayName()); + Assert.assertEquals("H&E Slide", resourceDefinition.getDescription()); + ResourceType resourceType = resourceDefinition.getResourceType(); + Assert.assertEquals(ResourceType.SAMPLE, resourceType); + Assert.assertEquals(true, resourceDefinition.getOpenByDefault()); + Assert.assertEquals("1", resourceDefinition.getPriority()); + Assert.assertEquals("study_tcga_pub", resourceDefinition.getCancerStudyIdentifier()); + } + + @Test + public void getAllResourceDataOfSampleInStudySummaryProjection1PageSize() throws Exception { + + List result = + resourceDataMyBatisRepository.getAllResourceDataOfSampleInStudy( + "study_tcga_pub", null, null, "SUMMARY", 1, 0, null, null); + + Assert.assertEquals(1, result.size()); + } + + @Test + public void getAllResourceDataOfSampleInStudySummaryProjectionSampleIdSort() throws Exception { + + List result = + resourceDataMyBatisRepository.getAllResourceDataOfSampleInStudy( + "study_tcga_pub", null, null, "SUMMARY", null, null, "sampleId", "DESC"); + + Assert.assertEquals(7, result.size()); + Assert.assertEquals("TCGA-A1-A0SH-01", result.get(0).getSampleId()); + Assert.assertEquals("TCGA-A1-A0SG-01", result.get(1).getSampleId()); + Assert.assertEquals("TCGA-A1-A0SF-01", result.get(2).getSampleId()); + Assert.assertEquals("TCGA-A1-A0SE-01", result.get(3).getSampleId()); + Assert.assertEquals("TCGA-A1-A0SD-01", result.get(4).getSampleId()); + Assert.assertEquals("TCGA-A1-A0SB-02", result.get(5).getSampleId()); + Assert.assertEquals("TCGA-A1-A0SB-01", result.get(6).getSampleId()); + } + + @Test + public void getAllResouceDataOfPatientInStudy() throws Exception { + + List result = + resourceDataMyBatisRepository.getAllResourceDataOfPatientInStudy( + "study_tcga_pub", "TCGA-A1-A0SB", null, "DETAILED", null, null, null, null); + + Assert.assertEquals(1, result.size()); + ResourceData resourceData = result.get(0); + Assert.assertEquals("TCGA-A1-A0SB", resourceData.getPatientId()); + Assert.assertEquals("IDC_OHIF_V2", resourceData.getResourceId()); + Assert.assertEquals( + "https://upload.wikimedia.org/wikipedia/commons/thumb/e/ea/SADDLE_PE.JPG/721px-SADDLE_PE.JPG", + resourceData.getUrl()); + ResourceDefinition resourceDefinition = resourceData.getResourceDefinition(); + Assert.assertEquals("CT Scan", resourceDefinition.getDisplayName()); + Assert.assertEquals("CT Scan", resourceDefinition.getDescription()); + ResourceType resourceType = resourceDefinition.getResourceType(); + Assert.assertEquals(ResourceType.PATIENT, resourceType); + Assert.assertEquals(true, resourceDefinition.getOpenByDefault()); + Assert.assertEquals("1", resourceDefinition.getPriority()); + Assert.assertEquals("study_tcga_pub", resourceDefinition.getCancerStudyIdentifier()); + } + + @Test + public void getAllResourceDataForStudy() throws Exception { + + List result = + resourceDataMyBatisRepository.getAllResourceDataForStudy( + "acc_tcga", null, "DETAILED", null, null, null, null); + + Assert.assertEquals(1, result.size()); + ResourceData resourceData = result.get(0); + Assert.assertEquals("FIGURES", resourceData.getResourceId()); + Assert.assertEquals( + "https://upload.wikimedia.org/wikipedia/commons/thumb/5/56/Tumor_Mesothelioma2_legend.jpg/220px-Tumor_Mesothelioma2_legend.jpg", + resourceData.getUrl()); + ResourceDefinition resourceDefinition = resourceData.getResourceDefinition(); + Assert.assertEquals("Figures", resourceDefinition.getDisplayName()); + Assert.assertEquals("Figures", resourceDefinition.getDescription()); + ResourceType resourceType = resourceDefinition.getResourceType(); + Assert.assertEquals(ResourceType.STUDY, resourceType); + Assert.assertEquals(true, resourceDefinition.getOpenByDefault()); + Assert.assertEquals("1", resourceDefinition.getPriority()); + Assert.assertEquals("acc_tcga", resourceDefinition.getCancerStudyIdentifier()); + } +} diff --git a/src/test/java/org/cbioportal/legacy/persistence/mybatis/ResourceDefinitionMyBatisRepositoryTest.java b/src/test/java/org/cbioportal/legacy/persistence/mybatis/ResourceDefinitionMyBatisRepositoryTest.java new file mode 100644 index 00000000000..a3e4df209e2 --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/persistence/mybatis/ResourceDefinitionMyBatisRepositoryTest.java @@ -0,0 +1,83 @@ +package org.cbioportal.legacy.persistence.mybatis; + +import java.util.List; +import org.cbioportal.legacy.model.ResourceDefinition; +import org.cbioportal.legacy.model.ResourceType; +import org.cbioportal.legacy.persistence.mybatis.config.TestConfig; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +@RunWith(SpringJUnit4ClassRunner.class) +@SpringBootTest(classes = {ResourceDefinitionMyBatisRepository.class, TestConfig.class}) +public class ResourceDefinitionMyBatisRepositoryTest { + + @Autowired private ResourceDefinitionMyBatisRepository resourceDefinitionMyBatisRepository; + + @Test + public void getResourceDefinition() throws Exception { + + ResourceDefinition result = + resourceDefinitionMyBatisRepository.getResourceDefinition("study_tcga_pub", "HE"); + + Assert.assertEquals("H&E Slide", result.getDisplayName()); + Assert.assertEquals("H&E Slide", result.getDescription()); + Assert.assertEquals(ResourceType.SAMPLE, result.getResourceType()); + Assert.assertEquals("1", result.getPriority()); + Assert.assertEquals(true, result.getOpenByDefault()); + } + + @Test + public void fetchResourceDefinitionsIdProjection() throws Exception { + + List result = + resourceDefinitionMyBatisRepository.fetchResourceDefinitions( + List.of("study_tcga_pub"), "ID", null, null, null, null); + + Assert.assertEquals(2, result.size()); + ResourceDefinition resourceDefinition = result.get(0); + Assert.assertEquals("HE", resourceDefinition.getResourceId()); + Assert.assertEquals("H&E Slide", resourceDefinition.getDisplayName()); + Assert.assertNull(resourceDefinition.getDescription()); + Assert.assertNull(resourceDefinition.getResourceType()); + Assert.assertNull(resourceDefinition.getPriority()); + Assert.assertNull(resourceDefinition.getOpenByDefault()); + } + + @Test + public void fetchResourceDefinitionsSummaryProjection() throws Exception { + + List result = + resourceDefinitionMyBatisRepository.fetchResourceDefinitions( + List.of("study_tcga_pub"), "SUMMARY", null, null, null, null); + + Assert.assertEquals(2, result.size()); + ResourceDefinition resourceDefinition = result.get(0); + Assert.assertEquals("HE", resourceDefinition.getResourceId()); + Assert.assertEquals("H&E Slide", resourceDefinition.getDisplayName()); + Assert.assertEquals("H&E Slide", resourceDefinition.getDescription()); + Assert.assertEquals(ResourceType.SAMPLE, resourceDefinition.getResourceType()); + Assert.assertEquals("1", resourceDefinition.getPriority()); + Assert.assertEquals(true, resourceDefinition.getOpenByDefault()); + } + + @Test + public void fetchResourceDefinitionsDetailedProjection() throws Exception { + + List result = + resourceDefinitionMyBatisRepository.fetchResourceDefinitions( + List.of("study_tcga_pub"), "DETAILED", null, null, null, null); + + Assert.assertEquals(2, result.size()); + ResourceDefinition resourceDefinition = result.get(0); + Assert.assertEquals("HE", resourceDefinition.getResourceId()); + Assert.assertEquals("H&E Slide", resourceDefinition.getDisplayName()); + Assert.assertEquals("H&E Slide", resourceDefinition.getDescription()); + Assert.assertEquals(ResourceType.SAMPLE, resourceDefinition.getResourceType()); + Assert.assertEquals("1", resourceDefinition.getPriority()); + Assert.assertEquals(true, resourceDefinition.getOpenByDefault()); + } +} diff --git a/src/test/java/org/cbioportal/legacy/persistence/mybatis/SampleListMyBatisRepositoryTest.java b/src/test/java/org/cbioportal/legacy/persistence/mybatis/SampleListMyBatisRepositoryTest.java new file mode 100644 index 00000000000..311c81e3cfc --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/persistence/mybatis/SampleListMyBatisRepositoryTest.java @@ -0,0 +1,247 @@ +package org.cbioportal.legacy.persistence.mybatis; + +import java.util.Arrays; +import java.util.List; +import org.cbioportal.legacy.model.CancerStudy; +import org.cbioportal.legacy.model.SampleList; +import org.cbioportal.legacy.model.meta.BaseMeta; +import org.cbioportal.legacy.persistence.mybatis.config.TestConfig; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +@RunWith(SpringJUnit4ClassRunner.class) +@SpringBootTest(classes = {SampleListMyBatisRepository.class, TestConfig.class}) +public class SampleListMyBatisRepositoryTest { + + @Autowired private SampleListMyBatisRepository sampleListMyBatisRepository; + + @Test + public void getAllSampleListsIdProjection() throws Exception { + + List result = + sampleListMyBatisRepository.getAllSampleLists("ID", null, null, null, null); + + Assert.assertEquals(14, result.size()); + SampleList sampleList = result.get(0); + Assert.assertEquals((Integer) 14, sampleList.getListId()); + Assert.assertEquals("acc_tcga_all", sampleList.getStableId()); + Assert.assertNull(sampleList.getCancerStudy()); + } + + @Test + public void getAllSampleListsSummaryProjection() throws Exception { + + List result = + sampleListMyBatisRepository.getAllSampleLists("SUMMARY", null, null, null, null); + + Assert.assertEquals(14, result.size()); + SampleList sampleList = result.get(0); + Assert.assertEquals((Integer) 1, sampleList.getListId()); + Assert.assertEquals("study_tcga_pub_all", sampleList.getStableId()); + Assert.assertEquals((Integer) 1, sampleList.getCancerStudyId()); + Assert.assertEquals("study_tcga_pub", sampleList.getCancerStudyIdentifier()); + Assert.assertEquals("other", sampleList.getCategory()); + Assert.assertEquals("All Tumors", sampleList.getName()); + Assert.assertEquals("All tumor samples", sampleList.getDescription()); + Assert.assertNull(sampleList.getCancerStudy()); + } + + @Test + public void getAllSampleListsDetailedProjection() throws Exception { + + List result = + sampleListMyBatisRepository.getAllSampleLists("DETAILED", null, null, null, null); + + Assert.assertEquals(14, result.size()); + SampleList sampleList = result.get(0); + Assert.assertEquals((Integer) 1, sampleList.getListId()); + Assert.assertEquals("study_tcga_pub_all", sampleList.getStableId()); + Assert.assertEquals((Integer) 1, sampleList.getCancerStudyId()); + Assert.assertEquals("study_tcga_pub", sampleList.getCancerStudyIdentifier()); + Assert.assertEquals("other", sampleList.getCategory()); + Assert.assertEquals("All Tumors", sampleList.getName()); + Assert.assertEquals("All tumor samples", sampleList.getDescription()); + CancerStudy cancerStudy = sampleList.getCancerStudy(); + Assert.assertEquals((Integer) 1, cancerStudy.getCancerStudyId()); + Assert.assertEquals("study_tcga_pub", cancerStudy.getCancerStudyIdentifier()); + Assert.assertEquals("brca", cancerStudy.getTypeOfCancerId()); + Assert.assertEquals("Breast Invasive Carcinoma (TCGA, Nature 2012)", cancerStudy.getName()); + Assert.assertEquals( + "The Cancer Genome Atlas (TCGA) Breast" + + " Invasive Carcinoma project. 825 cases.
Nature 2012. Raw data via the TCGA Data Portal.", + cancerStudy.getDescription()); + Assert.assertEquals(true, cancerStudy.getPublicStudy()); + Assert.assertEquals("23000897,26451490", cancerStudy.getPmid()); + Assert.assertEquals("TCGA, Nature 2012, ...", cancerStudy.getCitation()); + Assert.assertEquals("SU2C-PI3K;PUBLIC;GDAC", cancerStudy.getGroups()); + Assert.assertEquals((Integer) 0, cancerStudy.getStatus()); + } + + @Test + public void getAllSampleListsSummaryProjection1PageSize() throws Exception { + + List result = + sampleListMyBatisRepository.getAllSampleLists("SUMMARY", 1, 0, null, null); + + Assert.assertEquals(1, result.size()); + } + + @Test + public void getAllSampleListsSummaryProjectionStableIdSort() throws Exception { + + List result = + sampleListMyBatisRepository.getAllSampleLists("SUMMARY", null, null, "stableId", "ASC"); + + Assert.assertEquals(14, result.size()); + Assert.assertEquals("acc_tcga_all", result.get(0).getStableId()); + Assert.assertEquals("study_tcga_pub_3way_complete", result.get(1).getStableId()); + Assert.assertEquals("study_tcga_pub_acgh", result.get(2).getStableId()); + Assert.assertEquals("study_tcga_pub_all", result.get(3).getStableId()); + Assert.assertEquals("study_tcga_pub_cna", result.get(4).getStableId()); + Assert.assertEquals("study_tcga_pub_cnaseq", result.get(5).getStableId()); + } + + @Test + public void getMetaSampleLists() throws Exception { + + BaseMeta result = sampleListMyBatisRepository.getMetaSampleLists(); + + Assert.assertEquals((Integer) 14, result.getTotalCount()); + } + + @Test + public void getSampleListNullResult() throws Exception { + + SampleList result = sampleListMyBatisRepository.getSampleList("invalid_sample_list"); + + Assert.assertNull(result); + } + + @Test + public void getSampleList() throws Exception { + + SampleList sampleList = sampleListMyBatisRepository.getSampleList("study_tcga_pub_all"); + + Assert.assertEquals((Integer) 1, sampleList.getListId()); + Assert.assertEquals("study_tcga_pub_all", sampleList.getStableId()); + Assert.assertEquals((Integer) 1, sampleList.getCancerStudyId()); + Assert.assertEquals("study_tcga_pub", sampleList.getCancerStudyIdentifier()); + Assert.assertEquals("other", sampleList.getCategory()); + Assert.assertEquals("All Tumors", sampleList.getName()); + Assert.assertEquals("All tumor samples", sampleList.getDescription()); + CancerStudy cancerStudy = sampleList.getCancerStudy(); + Assert.assertEquals((Integer) 1, cancerStudy.getCancerStudyId()); + Assert.assertEquals("study_tcga_pub", cancerStudy.getCancerStudyIdentifier()); + Assert.assertEquals("brca", cancerStudy.getTypeOfCancerId()); + Assert.assertEquals("Breast Invasive Carcinoma (TCGA, Nature 2012)", cancerStudy.getName()); + Assert.assertEquals( + "The Cancer Genome Atlas (TCGA) Breast" + + " Invasive Carcinoma project. 825 cases.
Nature 2012. Raw data via the TCGA Data Portal.", + cancerStudy.getDescription()); + Assert.assertEquals(true, cancerStudy.getPublicStudy()); + Assert.assertEquals("23000897,26451490", cancerStudy.getPmid()); + Assert.assertEquals("TCGA, Nature 2012, ...", cancerStudy.getCitation()); + Assert.assertEquals("SU2C-PI3K;PUBLIC;GDAC", cancerStudy.getGroups()); + Assert.assertEquals((Integer) 0, cancerStudy.getStatus()); + } + + @Test + public void getSampleLists() throws Exception { + + List result = + sampleListMyBatisRepository.getSampleLists( + Arrays.asList("study_tcga_pub_all", "study_tcga_pub_acgh"), "SUMMARY"); + + Assert.assertEquals(2, result.size()); + SampleList sampleList = result.get(0); + Assert.assertEquals((Integer) 2, sampleList.getListId()); + Assert.assertEquals("study_tcga_pub_acgh", sampleList.getStableId()); + Assert.assertEquals((Integer) 1, sampleList.getCancerStudyId()); + Assert.assertEquals("study_tcga_pub", sampleList.getCancerStudyIdentifier()); + Assert.assertEquals("other", sampleList.getCategory()); + Assert.assertEquals("Tumors aCGH", sampleList.getName()); + Assert.assertEquals("All tumors with aCGH data", sampleList.getDescription()); + Assert.assertNull(sampleList.getCancerStudy()); + } + + @Test + public void getAllSampleListsInStudySummaryProjection() throws Exception { + + List result = + sampleListMyBatisRepository.getAllSampleListsInStudies( + Arrays.asList("study_tcga_pub"), "SUMMARY", null, null, null, null); + + Assert.assertEquals(13, result.size()); + SampleList sampleList = result.get(0); + Assert.assertEquals((Integer) 1, sampleList.getListId()); + Assert.assertEquals("study_tcga_pub_all", sampleList.getStableId()); + Assert.assertEquals((Integer) 1, sampleList.getCancerStudyId()); + Assert.assertEquals("study_tcga_pub", sampleList.getCancerStudyIdentifier()); + Assert.assertEquals("other", sampleList.getCategory()); + Assert.assertEquals("All Tumors", sampleList.getName()); + Assert.assertEquals("All tumor samples", sampleList.getDescription()); + Assert.assertNull(sampleList.getCancerStudy()); + } + + @Test + public void getAllSampleListsInStudyDetailedProjection() throws Exception { + + List result = + sampleListMyBatisRepository.getAllSampleListsInStudies( + Arrays.asList("study_tcga_pub"), "DETAILED", null, null, null, null); + + Assert.assertEquals(13, result.size()); + SampleList sampleList = result.get(0); + Assert.assertEquals((Integer) 1, sampleList.getListId()); + Assert.assertEquals("study_tcga_pub_all", sampleList.getStableId()); + Assert.assertEquals((Integer) 1, sampleList.getCancerStudyId()); + Assert.assertEquals("study_tcga_pub", sampleList.getCancerStudyIdentifier()); + Assert.assertEquals("other", sampleList.getCategory()); + Assert.assertEquals("All Tumors", sampleList.getName()); + Assert.assertEquals("All tumor samples", sampleList.getDescription()); + CancerStudy cancerStudy = sampleList.getCancerStudy(); + Assert.assertEquals((Integer) 1, cancerStudy.getCancerStudyId()); + Assert.assertEquals("study_tcga_pub", cancerStudy.getCancerStudyIdentifier()); + Assert.assertEquals("brca", cancerStudy.getTypeOfCancerId()); + Assert.assertEquals("Breast Invasive Carcinoma (TCGA, Nature 2012)", cancerStudy.getName()); + Assert.assertEquals( + "The Cancer Genome Atlas (TCGA) Breast" + + " Invasive Carcinoma project. 825 cases.
Nature 2012. Raw data via the TCGA Data Portal.", + cancerStudy.getDescription()); + Assert.assertEquals(true, cancerStudy.getPublicStudy()); + Assert.assertEquals("23000897,26451490", cancerStudy.getPmid()); + Assert.assertEquals("TCGA, Nature 2012, ...", cancerStudy.getCitation()); + Assert.assertEquals("SU2C-PI3K;PUBLIC;GDAC", cancerStudy.getGroups()); + Assert.assertEquals((Integer) 0, cancerStudy.getStatus()); + } + + @Test + public void getMetaSampleListsInStudy() throws Exception { + + BaseMeta result = sampleListMyBatisRepository.getMetaSampleListsInStudy("study_tcga_pub"); + + Assert.assertEquals((Integer) 13, result.getTotalCount()); + } + + @Test + public void getAllSampleIdsInSampleList() throws Exception { + + List result = + sampleListMyBatisRepository.getAllSampleIdsInSampleList("study_tcga_pub_all"); + + Assert.assertEquals(14, result.size()); + Assert.assertEquals("TCGA-A1-A0SB-01", result.get(0)); + Assert.assertEquals("TCGA-A1-A0SD-01", result.get(1)); + Assert.assertEquals("TCGA-A1-A0SE-01", result.get(2)); + Assert.assertEquals("TCGA-A1-A0SF-01", result.get(3)); + Assert.assertEquals("TCGA-A1-A0SG-01", result.get(4)); + Assert.assertEquals("TCGA-A1-A0SQ-01", result.get(13)); + } +} diff --git a/src/test/java/org/cbioportal/legacy/persistence/mybatis/SampleMyBatisRepositoryTest.java b/src/test/java/org/cbioportal/legacy/persistence/mybatis/SampleMyBatisRepositoryTest.java new file mode 100644 index 00000000000..c03b83df00e --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/persistence/mybatis/SampleMyBatisRepositoryTest.java @@ -0,0 +1,415 @@ +package org.cbioportal.legacy.persistence.mybatis; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; +import org.cbioportal.legacy.model.CancerStudy; +import org.cbioportal.legacy.model.Patient; +import org.cbioportal.legacy.model.Sample; +import org.cbioportal.legacy.model.meta.BaseMeta; +import org.cbioportal.legacy.persistence.mybatis.config.TestConfig; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +@RunWith(SpringJUnit4ClassRunner.class) +@SpringBootTest(classes = {SampleMyBatisRepository.class, TestConfig.class}) +public class SampleMyBatisRepositoryTest { + + @Autowired private SampleMyBatisRepository sampleMyBatisRepository; + + @Test + public void getAllSamplesInStudyIdProjection() throws Exception { + + List result = + sampleMyBatisRepository.getAllSamplesInStudy( + "study_tcga_pub", "ID", null, null, null, null); + + Assert.assertEquals(15, result.size()); + Sample sample = result.get(0); + Assert.assertEquals((Integer) 1, sample.getInternalId()); + Assert.assertEquals("TCGA-A1-A0SB-01", sample.getStableId()); + Assert.assertNull(sample.getPatient()); + } + + @Test + public void getAllSamplesInStudySummaryProjection() throws Exception { + + List result = + sampleMyBatisRepository.getAllSamplesInStudy( + "study_tcga_pub", "SUMMARY", null, null, null, null); + + Assert.assertEquals(15, result.size()); + Sample sample = result.get(0); + Assert.assertEquals((Integer) 1, sample.getInternalId()); + Assert.assertEquals("TCGA-A1-A0SB-01", sample.getStableId()); + Assert.assertEquals(Sample.SampleType.PRIMARY_SOLID_TUMOR, sample.getSampleType()); + Assert.assertEquals((Integer) 1, sample.getPatientId()); + Assert.assertEquals("TCGA-A1-A0SB", sample.getPatientStableId()); + Assert.assertNull(sample.getPatient()); + } + + @Test + public void getAllSamplesInStudyDetailedProjection() throws Exception { + + List result = + sampleMyBatisRepository.getAllSamplesInStudy( + "study_tcga_pub", "DETAILED", null, null, null, null); + + Assert.assertEquals(15, result.size()); + Sample sample = result.get(0); + Assert.assertEquals((Integer) 1, sample.getInternalId()); + Assert.assertEquals("TCGA-A1-A0SB-01", sample.getStableId()); + Assert.assertEquals(Sample.SampleType.PRIMARY_SOLID_TUMOR, sample.getSampleType()); + Assert.assertEquals((Integer) 1, sample.getPatientId()); + Assert.assertEquals("TCGA-A1-A0SB", sample.getPatientStableId()); + Patient patient = sample.getPatient(); + Assert.assertEquals((Integer) 1, patient.getInternalId()); + Assert.assertEquals("TCGA-A1-A0SB", patient.getStableId()); + Assert.assertEquals((Integer) 1, patient.getCancerStudyId()); + Assert.assertEquals("study_tcga_pub", patient.getCancerStudyIdentifier()); + CancerStudy cancerStudy = patient.getCancerStudy(); + Assert.assertEquals((Integer) 1, cancerStudy.getCancerStudyId()); + Assert.assertEquals("study_tcga_pub", cancerStudy.getCancerStudyIdentifier()); + Assert.assertEquals("brca", cancerStudy.getTypeOfCancerId()); + Assert.assertEquals("Breast Invasive Carcinoma (TCGA, Nature 2012)", cancerStudy.getName()); + Assert.assertEquals( + "The Cancer Genome Atlas (TCGA) Breast" + + " Invasive Carcinoma project. 825 cases.
Nature 2012. Raw data via the TCGA Data Portal.", + cancerStudy.getDescription()); + Assert.assertEquals(true, cancerStudy.getPublicStudy()); + Assert.assertEquals("23000897,26451490", cancerStudy.getPmid()); + Assert.assertEquals("TCGA, Nature 2012, ...", cancerStudy.getCitation()); + Assert.assertEquals("SU2C-PI3K;PUBLIC;GDAC", cancerStudy.getGroups()); + Assert.assertEquals((Integer) 0, cancerStudy.getStatus()); + } + + @Test + public void getAllSamplesInStudySummaryProjection1PageSize() throws Exception { + + List result = + sampleMyBatisRepository.getAllSamplesInStudy("study_tcga_pub", "SUMMARY", 1, 0, null, null); + + Assert.assertEquals(1, result.size()); + } + + @Test + public void getAllSamplesInStudySummaryProjectionStableIdSort() throws Exception { + + List result = + sampleMyBatisRepository.getAllSamplesInStudy( + "study_tcga_pub", "SUMMARY", null, null, "stableId", "ASC"); + + Assert.assertEquals(15, result.size()); + Assert.assertEquals("TCGA-A1-A0SB-01", result.get(0).getStableId()); + Assert.assertEquals("TCGA-A1-A0SB-02", result.get(1).getStableId()); + Assert.assertEquals("TCGA-A1-A0SD-01", result.get(2).getStableId()); + Assert.assertEquals("TCGA-A1-A0SE-01", result.get(3).getStableId()); + Assert.assertEquals("TCGA-A1-A0SF-01", result.get(4).getStableId()); + Assert.assertEquals("TCGA-A1-A0SG-01", result.get(5).getStableId()); + } + + @Test + public void getMetaSamplesInStudy() throws Exception { + + BaseMeta result = sampleMyBatisRepository.getMetaSamplesInStudy("study_tcga_pub"); + + Assert.assertEquals((Integer) 15, result.getTotalCount()); + } + + @Test + public void getSampleInStudyNullResult() throws Exception { + + Sample result = sampleMyBatisRepository.getSampleInStudy("study_tcga_pub", "invalid_sample"); + + Assert.assertNull(result); + } + + @Test + public void getSampleInStudy() throws Exception { + + Sample sample = sampleMyBatisRepository.getSampleInStudy("study_tcga_pub", "TCGA-A1-A0SI-01"); + + Assert.assertEquals((Integer) 7, sample.getInternalId()); + Assert.assertEquals("TCGA-A1-A0SI-01", sample.getStableId()); + Assert.assertEquals(Sample.SampleType.PRIMARY_SOLID_TUMOR, sample.getSampleType()); + Assert.assertEquals((Integer) 7, sample.getPatientId()); + Assert.assertEquals("TCGA-A1-A0SI", sample.getPatientStableId()); + Patient patient = sample.getPatient(); + Assert.assertEquals((Integer) 7, patient.getInternalId()); + Assert.assertEquals("TCGA-A1-A0SI", patient.getStableId()); + Assert.assertEquals((Integer) 1, patient.getCancerStudyId()); + Assert.assertEquals("study_tcga_pub", patient.getCancerStudyIdentifier()); + CancerStudy cancerStudy = patient.getCancerStudy(); + Assert.assertEquals((Integer) 1, cancerStudy.getCancerStudyId()); + Assert.assertEquals("study_tcga_pub", cancerStudy.getCancerStudyIdentifier()); + Assert.assertEquals("brca", cancerStudy.getTypeOfCancerId()); + Assert.assertEquals("Breast Invasive Carcinoma (TCGA, Nature 2012)", cancerStudy.getName()); + Assert.assertEquals( + "The Cancer Genome Atlas (TCGA) Breast" + + " Invasive Carcinoma project. 825 cases.
Nature 2012. Raw data via the TCGA Data Portal.", + cancerStudy.getDescription()); + Assert.assertEquals(true, cancerStudy.getPublicStudy()); + Assert.assertEquals("23000897,26451490", cancerStudy.getPmid()); + Assert.assertEquals("TCGA, Nature 2012, ...", cancerStudy.getCitation()); + Assert.assertEquals("SU2C-PI3K;PUBLIC;GDAC", cancerStudy.getGroups()); + Assert.assertEquals((Integer) 0, cancerStudy.getStatus()); + } + + @Test + public void getAllSamplesOfPatientInStudyIdProjection() throws Exception { + + List result = + sampleMyBatisRepository.getAllSamplesOfPatientInStudy( + "study_tcga_pub", "TCGA-A1-A0SB", "ID", null, null, null, null); + + Assert.assertEquals(2, result.size()); + Sample sample = result.get(0); + Assert.assertEquals((Integer) 1, sample.getInternalId()); + Assert.assertEquals("TCGA-A1-A0SB-01", sample.getStableId()); + Assert.assertNull(sample.getPatient()); + } + + @Test + public void getAllSamplesOfPatientInStudySummaryProjection() throws Exception { + + List result = + sampleMyBatisRepository.getAllSamplesOfPatientInStudy( + "study_tcga_pub", "TCGA-A1-A0SB", "SUMMARY", null, null, null, null); + + Assert.assertEquals(2, result.size()); + Sample sample = result.get(0); + Assert.assertEquals((Integer) 1, sample.getInternalId()); + Assert.assertEquals("TCGA-A1-A0SB-01", sample.getStableId()); + Assert.assertEquals(Sample.SampleType.PRIMARY_SOLID_TUMOR, sample.getSampleType()); + Assert.assertEquals((Integer) 1, sample.getPatientId()); + Assert.assertEquals("TCGA-A1-A0SB", sample.getPatientStableId()); + Assert.assertNull(sample.getPatient()); + } + + @Test + public void getAllSamplesOfPatientInStudyDetailedProjection() throws Exception { + + List result = + sampleMyBatisRepository.getAllSamplesOfPatientInStudy( + "study_tcga_pub", "TCGA-A1-A0SB", "DETAILED", null, null, null, null); + + Assert.assertEquals(2, result.size()); + Sample sample = result.get(0); + Assert.assertEquals((Integer) 1, sample.getInternalId()); + Assert.assertEquals("TCGA-A1-A0SB-01", sample.getStableId()); + Assert.assertEquals(Sample.SampleType.PRIMARY_SOLID_TUMOR, sample.getSampleType()); + Assert.assertEquals((Integer) 1, sample.getPatientId()); + Assert.assertEquals("TCGA-A1-A0SB", sample.getPatientStableId()); + Patient patient = sample.getPatient(); + Assert.assertEquals((Integer) 1, patient.getInternalId()); + Assert.assertEquals("TCGA-A1-A0SB", patient.getStableId()); + Assert.assertEquals((Integer) 1, patient.getCancerStudyId()); + Assert.assertEquals("study_tcga_pub", patient.getCancerStudyIdentifier()); + CancerStudy cancerStudy = patient.getCancerStudy(); + Assert.assertEquals((Integer) 1, cancerStudy.getCancerStudyId()); + Assert.assertEquals("study_tcga_pub", cancerStudy.getCancerStudyIdentifier()); + Assert.assertEquals("brca", cancerStudy.getTypeOfCancerId()); + Assert.assertEquals("Breast Invasive Carcinoma (TCGA, Nature 2012)", cancerStudy.getName()); + Assert.assertEquals( + "The Cancer Genome Atlas (TCGA) Breast" + + " Invasive Carcinoma project. 825 cases.
Nature 2012. Raw data via the TCGA Data Portal.", + cancerStudy.getDescription()); + Assert.assertEquals(true, cancerStudy.getPublicStudy()); + Assert.assertEquals("23000897,26451490", cancerStudy.getPmid()); + Assert.assertEquals("TCGA, Nature 2012, ...", cancerStudy.getCitation()); + Assert.assertEquals("SU2C-PI3K;PUBLIC;GDAC", cancerStudy.getGroups()); + Assert.assertEquals((Integer) 0, cancerStudy.getStatus()); + } + + @Test + public void getAllSamplesOfPatientInStudySummaryProjection1PageSize() throws Exception { + + List result = + sampleMyBatisRepository.getAllSamplesOfPatientInStudy( + "study_tcga_pub", "TCGA-A1-A0SB", "SUMMARY", 1, 0, null, null); + + Assert.assertEquals(1, result.size()); + } + + @Test + public void getAllSamplesOfPatientInStudySummaryProjectionStableIdSort() throws Exception { + + List result = + sampleMyBatisRepository.getAllSamplesOfPatientInStudy( + "study_tcga_pub", "TCGA-A1-A0SB", "SUMMARY", null, null, "stableId", "ASC"); + + Assert.assertEquals(2, result.size()); + Assert.assertEquals("TCGA-A1-A0SB-01", result.get(0).getStableId()); + Assert.assertEquals("TCGA-A1-A0SB-02", result.get(1).getStableId()); + } + + @Test + public void getMetaSamplesOfPatientInStudy() throws Exception { + + BaseMeta result = + sampleMyBatisRepository.getMetaSamplesOfPatientInStudy("study_tcga_pub", "TCGA-A1-A0SB"); + + Assert.assertEquals((Integer) 2, result.getTotalCount()); + } + + @Test + public void getAllSamplesOfPatientsInStudy() throws Exception { + + List result = + sampleMyBatisRepository.getAllSamplesOfPatientsInStudy( + "study_tcga_pub", Arrays.asList("TCGA-A1-A0SB", "TCGA-A1-A0SE"), "SUMMARY"); + + Assert.assertEquals(3, result.size()); + Sample sample = result.get(0); + Assert.assertEquals((Integer) 1, sample.getInternalId()); + Assert.assertEquals("TCGA-A1-A0SB-01", sample.getStableId()); + Assert.assertEquals(Sample.SampleType.PRIMARY_SOLID_TUMOR, sample.getSampleType()); + Assert.assertEquals((Integer) 1, sample.getPatientId()); + Assert.assertEquals("TCGA-A1-A0SB", sample.getPatientStableId()); + Assert.assertNull(sample.getPatient()); + } + + @Test + public void fetchSamples() throws Exception { + + List studyIds = new ArrayList<>(); + studyIds.add("study_tcga_pub"); + studyIds.add("study_tcga_pub"); + List sampleIds = new ArrayList<>(); + sampleIds.add("TCGA-A1-A0SB-01"); + sampleIds.add("TCGA-A1-A0SE-01"); + + List result = sampleMyBatisRepository.fetchSamples(studyIds, sampleIds, "SUMMARY"); + + Assert.assertEquals(2, result.size()); + Assert.assertEquals("TCGA-A1-A0SB-01", result.get(0).getStableId()); + Assert.assertEquals("TCGA-A1-A0SE-01", result.get(1).getStableId()); + } + + @Test + public void fetchSamplesBySampleListId() throws Exception { + + List sampleListIds = new ArrayList<>(); + sampleListIds.add("study_tcga_pub_all"); + sampleListIds.add("study_tcga_pub_acgh"); + + List result = + sampleMyBatisRepository.fetchSamplesBySampleListIds(sampleListIds, "SUMMARY"); + + Assert.assertEquals(14, result.size()); + Assert.assertEquals("TCGA-A1-A0SB-01", result.get(0).getStableId()); + Assert.assertEquals("TCGA-A1-A0SD-01", result.get(1).getStableId()); + Assert.assertEquals("TCGA-A1-A0SE-01", result.get(2).getStableId()); + Assert.assertEquals("TCGA-A1-A0SF-01", result.get(3).getStableId()); + Assert.assertEquals("TCGA-A1-A0SG-01", result.get(4).getStableId()); + Assert.assertEquals("TCGA-A1-A0SH-01", result.get(5).getStableId()); + } + + @Test + public void fetchMetaSamples() throws Exception { + + List studyIds = new ArrayList<>(); + studyIds.add("study_tcga_pub"); + studyIds.add("study_tcga_pub"); + List sampleIds = new ArrayList<>(); + sampleIds.add("TCGA-A1-A0SB-01"); + sampleIds.add("TCGA-A1-A0SE-01"); + + BaseMeta result = sampleMyBatisRepository.fetchMetaSamples(studyIds, sampleIds); + + Assert.assertEquals((Integer) 2, result.getTotalCount()); + } + + @Test + public void fetchMetaSamplesBySampleListId() throws Exception { + + List sampleListIds = new ArrayList<>(); + sampleListIds.add("study_tcga_pub_all"); + sampleListIds.add("study_tcga_pub_acgh"); + + BaseMeta result = sampleMyBatisRepository.fetchMetaSamples(sampleListIds); + + Assert.assertEquals((Integer) 14, result.getTotalCount()); + } + + @Test + public void getSamplesByInternalIds() throws Exception { + + List result = sampleMyBatisRepository.getSamplesByInternalIds(Arrays.asList(1, 2)); + + Assert.assertEquals(2, result.size()); + Assert.assertEquals("TCGA-A1-A0SB-01", result.get(0).getStableId()); + Assert.assertEquals("TCGA-A1-A0SD-01", result.get(1).getStableId()); + } + + @Test + public void getSamplesByKeyword() { + List result = + sampleMyBatisRepository.getAllSamples("TCGA-A1-A0SB", null, "SUMMARY", 10, 0, null, null); + List actual = result.stream().map((Sample::getStableId)).collect(Collectors.toList()); + List expected = Arrays.asList("TCGA-A1-A0SB-01", "TCGA-A1-A0SB-01", "TCGA-A1-A0SB-02"); + + Assert.assertEquals(expected, actual); + } + + @Test + public void getSamplesByEmptyKeyword() { + List result = + sampleMyBatisRepository.getAllSamples(" ", null, "SUMMARY", 10, 0, null, null); + List actual = result.stream().map((Sample::getStableId)).collect(Collectors.toList()); + List expected = + Arrays.asList( + "TCGA-A1-A0SB-01", + "TCGA-A1-A0SB-01", + "TCGA-A1-A0SB-02", + "TCGA-A1-A0SD-01", + "TCGA-A1-A0SE-01", + "TCGA-A1-A0SF-01", + "TCGA-A1-A0SG-01", + "TCGA-A1-A0SH-01", + "TCGA-A1-A0SI-01", + "TCGA-A1-A0SJ-01"); + + Assert.assertEquals(expected, actual); + } + + @Test + public void getSamplesByKeywordFilterByStudies() { + List result = + sampleMyBatisRepository.getAllSamples( + "TCGA-A1", Collections.singletonList("acc_tcga"), "SUMMARY", 10, 0, null, null); + List actual = result.stream().map(Sample::getStableId).collect(Collectors.toList()); + List expected = + Arrays.asList("TCGA-A1-A0SB-01", "TCGA-A1-B0SO-01", "TCGA-A1-B0SP-01", "TCGA-A1-B0SQ-01"); + + Assert.assertEquals(expected, actual); + } + + @Test + public void getSamplesByKeywordFilterByNoStudies() { + List result = + sampleMyBatisRepository.getAllSamples( + "TCGA-A1", new ArrayList<>(), "SUMMARY", 10, 0, null, null); + List actual = result.stream().map(Sample::getStableId).collect(Collectors.toList()); + List expected = Collections.emptyList(); + + Assert.assertEquals(expected, actual); + } + + @Test + public void getMetaSamplesByKeyword() { + BaseMeta actual = sampleMyBatisRepository.getMetaSamples("TCGA-A1-A0SB", null); + Integer expected = 3; + + Assert.assertEquals(expected, actual.getTotalCount()); + } +} diff --git a/src/test/java/org/cbioportal/legacy/persistence/mybatis/SignificantCopyNumberRegionMyBatisRepositoryTest.java b/src/test/java/org/cbioportal/legacy/persistence/mybatis/SignificantCopyNumberRegionMyBatisRepositoryTest.java new file mode 100644 index 00000000000..248823daafe --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/persistence/mybatis/SignificantCopyNumberRegionMyBatisRepositoryTest.java @@ -0,0 +1,129 @@ +package org.cbioportal.legacy.persistence.mybatis; + +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.List; +import org.cbioportal.legacy.model.Gistic; +import org.cbioportal.legacy.model.GisticToGene; +import org.cbioportal.legacy.model.meta.BaseMeta; +import org.cbioportal.legacy.persistence.mybatis.config.TestConfig; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +@RunWith(SpringJUnit4ClassRunner.class) +@SpringBootTest(classes = {SignificantCopyNumberRegionMyBatisRepository.class, TestConfig.class}) +public class SignificantCopyNumberRegionMyBatisRepositoryTest { + + @Autowired + private SignificantCopyNumberRegionMyBatisRepository significantCopyNumberRegionMyBatisRepository; + + @Test + public void getSignificantCopyNumberRegionsIdProjection() throws Exception { + + List result = + significantCopyNumberRegionMyBatisRepository.getSignificantCopyNumberRegions( + "study_tcga_pub", "ID", null, null, null, null); + + Assert.assertEquals(2, result.size()); + Gistic gistic = result.get(0); + Assert.assertEquals((Long) 1L, gistic.getGisticRoiId()); + Assert.assertEquals("study_tcga_pub", gistic.getCancerStudyId()); + Assert.assertEquals((Integer) 1, gistic.getChromosome()); + Assert.assertEquals("1q32.32", gistic.getCytoband()); + } + + @Test + public void getSignificantCopyNumberRegionsSummaryProjection() throws Exception { + + List result = + significantCopyNumberRegionMyBatisRepository.getSignificantCopyNumberRegions( + "study_tcga_pub", "SUMMARY", null, null, null, null); + + Assert.assertEquals(2, result.size()); + Gistic gistic = result.get(0); + Assert.assertEquals((Long) 1L, gistic.getGisticRoiId()); + Assert.assertEquals("study_tcga_pub", gistic.getCancerStudyId()); + Assert.assertEquals((Integer) 1, gistic.getChromosome()); + Assert.assertEquals("1q32.32", gistic.getCytoband()); + Assert.assertEquals((Integer) 123, gistic.getWidePeakStart()); + Assert.assertEquals((Integer) 136, gistic.getWidePeakEnd()); + Assert.assertEquals(new BigDecimal("0.0208839997649193"), gistic.getqValue()); + Assert.assertEquals(false, gistic.getAmp()); + } + + @Test + public void getSignificantCopyNumberRegionsDetailedProjection() throws Exception { + + List result = + significantCopyNumberRegionMyBatisRepository.getSignificantCopyNumberRegions( + "study_tcga_pub", "DETAILED", null, null, null, null); + + Assert.assertEquals(2, result.size()); + Gistic gistic = result.get(0); + Assert.assertEquals((Long) 1L, gistic.getGisticRoiId()); + Assert.assertEquals("study_tcga_pub", gistic.getCancerStudyId()); + Assert.assertEquals((Integer) 1, gistic.getChromosome()); + Assert.assertEquals("1q32.32", gistic.getCytoband()); + Assert.assertEquals((Integer) 123, gistic.getWidePeakStart()); + Assert.assertEquals((Integer) 136, gistic.getWidePeakEnd()); + Assert.assertEquals(new BigDecimal("0.0208839997649193"), gistic.getqValue()); + Assert.assertEquals(false, gistic.getAmp()); + } + + @Test + public void getSignificantCopyNumberRegionsSummaryProjection1PageSize() throws Exception { + + List result = + significantCopyNumberRegionMyBatisRepository.getSignificantCopyNumberRegions( + "study_tcga_pub", "SUMMARY", 1, 0, null, null); + + Assert.assertEquals(1, result.size()); + } + + @Test + public void getSignificantCopyNumberRegionsSummaryProjectionQValueSort() throws Exception { + + List result = + significantCopyNumberRegionMyBatisRepository.getSignificantCopyNumberRegions( + "study_tcga_pub", "SUMMARY", null, null, "qValue", "ASC"); + + Assert.assertEquals(2, result.size()); + Assert.assertEquals(new BigDecimal("0.000323799991747364"), result.get(0).getqValue()); + Assert.assertEquals(new BigDecimal("0.0208839997649193"), result.get(1).getqValue()); + } + + @Test + public void getMetaSignificantCopyNumberRegions() throws Exception { + + BaseMeta result = + significantCopyNumberRegionMyBatisRepository.getMetaSignificantCopyNumberRegions( + "study_tcga_pub"); + + Assert.assertEquals((Integer) 2, result.getTotalCount()); + } + + @Test + public void getGenesOfRegions() throws Exception { + + List gisticRoiIds = new ArrayList<>(); + gisticRoiIds.add(1L); + gisticRoiIds.add(2L); + List result = + significantCopyNumberRegionMyBatisRepository.getGenesOfRegions(gisticRoiIds); + + Assert.assertEquals(3, result.size()); + GisticToGene gisticToGene1 = result.get(0); + Assert.assertEquals((Integer) 207, gisticToGene1.getEntrezGeneId()); + Assert.assertEquals("AKT1", gisticToGene1.getHugoGeneSymbol()); + GisticToGene gisticToGene2 = result.get(1); + Assert.assertEquals((Integer) 208, gisticToGene2.getEntrezGeneId()); + Assert.assertEquals("AKT2", gisticToGene2.getHugoGeneSymbol()); + GisticToGene gisticToGene3 = result.get(2); + Assert.assertEquals((Integer) 207, gisticToGene3.getEntrezGeneId()); + Assert.assertEquals("AKT1", gisticToGene3.getHugoGeneSymbol()); + } +} diff --git a/src/test/java/org/cbioportal/legacy/persistence/mybatis/SignificantlyMutatedGeneMyBatisRepositoryTest.java b/src/test/java/org/cbioportal/legacy/persistence/mybatis/SignificantlyMutatedGeneMyBatisRepositoryTest.java new file mode 100644 index 00000000000..e416cd5d967 --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/persistence/mybatis/SignificantlyMutatedGeneMyBatisRepositoryTest.java @@ -0,0 +1,105 @@ +package org.cbioportal.legacy.persistence.mybatis; + +import java.math.BigDecimal; +import java.util.List; +import org.cbioportal.legacy.model.MutSig; +import org.cbioportal.legacy.model.meta.BaseMeta; +import org.cbioportal.legacy.persistence.mybatis.config.TestConfig; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +@RunWith(SpringJUnit4ClassRunner.class) +@SpringBootTest(classes = {SignificantlyMutatedGeneMyBatisRepository.class, TestConfig.class}) +public class SignificantlyMutatedGeneMyBatisRepositoryTest { + + @Autowired + private SignificantlyMutatedGeneMyBatisRepository significantlyMutatedGeneMyBatisRepository; + + @Test + public void getSignificantlyMutatedGenesIdProjection() throws Exception { + + List result = + significantlyMutatedGeneMyBatisRepository.getSignificantlyMutatedGenes( + "study_tcga_pub", "ID", null, null, null, null); + + Assert.assertEquals(2, result.size()); + MutSig mutSig = result.get(0); + Assert.assertEquals((Integer) 207, mutSig.getEntrezGeneId()); + } + + @Test + public void getSignificantlyMutatedGenesSummaryProjection() throws Exception { + + List result = + significantlyMutatedGeneMyBatisRepository.getSignificantlyMutatedGenes( + "study_tcga_pub", "SUMMARY", null, null, null, null); + + Assert.assertEquals(2, result.size()); + MutSig mutSig = result.get(0); + Assert.assertEquals((Integer) 207, mutSig.getEntrezGeneId()); + Assert.assertEquals((Integer) 1, mutSig.getCancerStudyId()); + Assert.assertEquals("study_tcga_pub", mutSig.getCancerStudyIdentifier()); + Assert.assertEquals("AKT1", mutSig.getHugoGeneSymbol()); + Assert.assertEquals((Integer) 998421, mutSig.getNumbasescovered()); + Assert.assertEquals((Integer) 17, mutSig.getNummutations()); + Assert.assertEquals((Integer) 1, mutSig.getRank()); + Assert.assertEquals(new BigDecimal("0.00000315"), mutSig.getpValue()); + Assert.assertEquals(new BigDecimal("0.00233"), mutSig.getqValue()); + } + + @Test + public void getSignificantlyMutatedGenesDetailedProjection() throws Exception { + + List result = + significantlyMutatedGeneMyBatisRepository.getSignificantlyMutatedGenes( + "study_tcga_pub", "DETAILED", null, null, null, null); + + Assert.assertEquals(2, result.size()); + MutSig mutSig = result.get(0); + Assert.assertEquals((Integer) 207, mutSig.getEntrezGeneId()); + Assert.assertEquals((Integer) 1, mutSig.getCancerStudyId()); + Assert.assertEquals("study_tcga_pub", mutSig.getCancerStudyIdentifier()); + Assert.assertEquals("AKT1", mutSig.getHugoGeneSymbol()); + Assert.assertEquals((Integer) 998421, mutSig.getNumbasescovered()); + Assert.assertEquals((Integer) 17, mutSig.getNummutations()); + Assert.assertEquals((Integer) 1, mutSig.getRank()); + Assert.assertEquals(new BigDecimal("0.00000315"), mutSig.getpValue()); + Assert.assertEquals(new BigDecimal("0.00233"), mutSig.getqValue()); + } + + @Test + public void getSignificantlyMutatedGenesSummaryProjection1PageSize() throws Exception { + + List result = + significantlyMutatedGeneMyBatisRepository.getSignificantlyMutatedGenes( + "study_tcga_pub", "SUMMARY", 1, 0, null, null); + + Assert.assertEquals(1, result.size()); + } + + @Test + public void getSignificantlyMutatedGenesSummaryProjectionPValueSort() throws Exception { + + List result = + significantlyMutatedGeneMyBatisRepository.getSignificantlyMutatedGenes( + "study_tcga_pub", "SUMMARY", null, null, "pValue", "ASC"); + + Assert.assertEquals(2, result.size()); + Assert.assertEquals(new BigDecimal("0.000000012"), result.get(0).getpValue()); + Assert.assertEquals(new BigDecimal("0.00000315"), result.get(1).getpValue()); + } + + @Test + public void getMetaSignificantlyMutatedGenes() throws Exception { + + BaseMeta result = + significantlyMutatedGeneMyBatisRepository.getMetaSignificantlyMutatedGenes( + "study_tcga_pub"); + + Assert.assertEquals((Integer) 2, result.getTotalCount()); + } +} diff --git a/src/test/java/org/cbioportal/legacy/persistence/mybatis/StructuralVariantMyBatisRepositoryTest.java b/src/test/java/org/cbioportal/legacy/persistence/mybatis/StructuralVariantMyBatisRepositoryTest.java new file mode 100644 index 00000000000..1f710d9f7ad --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/persistence/mybatis/StructuralVariantMyBatisRepositoryTest.java @@ -0,0 +1,1008 @@ +/* + * Copyright (c) 2018 - 2022 The Hyve B.V. + * This code is licensed under the GNU Affero General Public License (AGPL), + * version 3, or (at your option) any later version. + */ + +/* + * This file is part of cBioPortal. + * + * cBioPortal is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package org.cbioportal.legacy.persistence.mybatis; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; +import org.cbioportal.legacy.model.GeneFilterQuery; +import org.cbioportal.legacy.model.StructuralVariant; +import org.cbioportal.legacy.model.StructuralVariantFilterQuery; +import org.cbioportal.legacy.model.StructuralVariantGeneSubQuery; +import org.cbioportal.legacy.model.StructuralVariantQuery; +import org.cbioportal.legacy.model.StructuralVariantSpecialValue; +import org.cbioportal.legacy.model.util.Select; +import org.cbioportal.legacy.persistence.mybatis.config.TestConfig; +import org.cbioportal.legacy.persistence.mybatis.util.MolecularProfileCaseIdentifierUtil; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +@RunWith(SpringJUnit4ClassRunner.class) +@SpringBootTest( + classes = { + StructuralVariantMyBatisRepository.class, + StructuralVariantMapper.class, + MolecularProfileCaseIdentifierUtil.class, + TestConfig.class + }) +public class StructuralVariantMyBatisRepositoryTest { + + // struct var events in testSql.sql + // SAMPLE_ID, ENTREZ_GENE_ID, HUGO_GENE_SYMBOL, GENETIC_PROFILE_ID, GENETIC + // PRODFILE, TYPE, MUTATION_TYPE, DRIVER_FILTER, DRIVER_TIERS_FILTER, PATIENT_ID, MUTATION_TYPE + // 1 27436-238 EML4-ALK 7 study_tcga_pub_sv SV Fusion + // TCGA-A1-A0SB germline + // 2 27436-238 EML4-ALK 7 study_tcga_pub_sv SV Fusion + // TCGA-A1-A0SD somatic + // 1 57670-673 KIAA..-BRAF 7 study_tcga_pub_sv SV Fusion + // TCGA-A1-A0SB somatic + // 2 57670-673 KIAA..-BRAF 7 study_tcga_pub_sv SV Fusion + // TCGA-A1-A0SD germline + // 2 57670-673 KIAA..-BRAF 7 study_tcga_pub_sv SV Fusion + // TCGA-A1-A0SD somatic + // 15 57670-673 KIAA..-BRAF 13 acc_tcga_sv SV Fusion + // TCGA-A1-A0SD somatic + // 1 8031-5979 NCOA4-RET 7 study_tcga_pub_sv SV Fusion + // TCGA-A1-A0SB somatic + // 15 8031-5979 NCOA4-RET 13 acc_tcga_sv SV Fusion + // TCGA-A1-A0SB somatic + // 1 7113-2078 TMPRSS2-ERG 7 study_tcga_pub_sv SV Fusion + // TCGA-A1-A0SB somatic + // 15 8031-NULL NCOA4- 13 acc_tcga_sv SV Fusion + // TCGA-A1-A0SB somatic + + @Autowired StructuralVariantMyBatisRepository structuralVariantMyBatisRepository; + + @Before + public void init() { + molecularProfileIds = new ArrayList<>(); + molecularProfileIds.add("study_tcga_pub_sv"); + molecularProfileIds.add("study_tcga_pub_sv"); + molecularProfileIds.add("acc_tcga_sv"); + sampleIds = new ArrayList<>(); + sampleIds.add("TCGA-A1-A0SB-01"); + sampleIds.add("TCGA-A1-A0SD-01"); + sampleIds.add("TCGA-A1-B0SO-01"); + tiers = Select.all(); + includeUnknownTier = true; + includeDriver = true; + includeVUS = true; + includeUnknownOncogenicity = true; + includeGermline = true; + includeSomatic = true; + includeUnknownStatus = true; + + GeneFilterQuery geneFilterQuery1 = + new GeneFilterQuery( + "KIAA1549", + 57670, + null, + includeDriver, + includeVUS, + includeUnknownOncogenicity, + tiers, + includeUnknownTier, + includeGermline, + includeSomatic, + includeUnknownStatus); + GeneFilterQuery geneFilterQuery2 = + new GeneFilterQuery( + "EML4", + 27436, + null, + includeDriver, + includeVUS, + includeUnknownOncogenicity, + tiers, + includeUnknownTier, + includeGermline, + includeSomatic, + includeUnknownStatus); + GeneFilterQuery geneFilterQuery3 = + new GeneFilterQuery( + "TMPRSS2", + 7113, + null, + includeDriver, + includeVUS, + includeUnknownOncogenicity, + tiers, + includeUnknownTier, + includeGermline, + includeSomatic, + includeUnknownStatus); + GeneFilterQuery geneFilterQuery4 = + new GeneFilterQuery( + "NCOA4", + 8031, + null, + includeDriver, + includeVUS, + includeUnknownOncogenicity, + tiers, + includeUnknownTier, + includeGermline, + includeSomatic, + includeUnknownStatus); + geneQueries = + Arrays.asList(geneFilterQuery1, geneFilterQuery2, geneFilterQuery3, geneFilterQuery4); + + // Only search for the KIAA1549-BRAF and EML4-ALK fusions. + structVarFilterQuery1 = + new StructuralVariantFilterQuery( + "KIAA1549", + 57670, + "BRAF", + 673, + includeDriver, + includeVUS, + includeUnknownOncogenicity, + tiers, + includeUnknownTier, + includeGermline, + includeSomatic, + includeUnknownStatus); + structVarFilterQuery2 = + new StructuralVariantFilterQuery( + "EML4", + 27436, + "ALK", + 238, + includeDriver, + includeVUS, + includeUnknownOncogenicity, + tiers, + includeUnknownTier, + includeGermline, + includeSomatic, + includeUnknownStatus); + structVarQueries = Arrays.asList(structVarFilterQuery1, structVarFilterQuery2); + structVarFilterQueryNullGene1 = + new StructuralVariantFilterQuery( + null, + null, + "BRAF", + 673, + includeDriver, + includeVUS, + includeUnknownOncogenicity, + tiers, + includeUnknownTier, + includeGermline, + includeSomatic, + includeUnknownStatus); + structVarFilterQueryNullGene2 = + new StructuralVariantFilterQuery( + "NCOA4", + 8031, + null, + null, + includeDriver, + includeVUS, + includeUnknownOncogenicity, + tiers, + includeUnknownTier, + includeGermline, + includeSomatic, + includeUnknownStatus); + } + + List molecularProfileIds = new ArrayList<>(); + List sampleIds = new ArrayList<>(); + Select tiers; + boolean includeUnknownTier; + boolean includeDriver; + boolean includeVUS; + boolean includeUnknownOncogenicity; + boolean includeGermline; + boolean includeSomatic; + boolean includeUnknownStatus; + private List geneQueries; + List noEntrezIds = Collections.emptyList(); + private List noStructVars = Collections.emptyList(); + private List structVarQueries; + private StructuralVariantFilterQuery structVarFilterQuery1; + private StructuralVariantFilterQuery structVarFilterQuery2; + private StructuralVariantFilterQuery structVarFilterQueryNullGene1; + private StructuralVariantFilterQuery structVarFilterQueryNullGene2; + + @Test + public void fetchStructuralVariantsNoSampleIdentifiers() { + + List molecularProfileIds = new ArrayList<>(); + List entrezGeneIds = new ArrayList<>(); + List sampleIds = new ArrayList<>(); + molecularProfileIds.add("study_tcga_pub_sv"); + entrezGeneIds.add(57670); + + List result = + structuralVariantMyBatisRepository.fetchStructuralVariants( + molecularProfileIds, sampleIds, entrezGeneIds, noStructVars); + + Assert.assertEquals(3, result.size()); + StructuralVariant structuralVariantFirstResult = result.get(0); + Assert.assertEquals("study_tcga_pub_sv", structuralVariantFirstResult.getMolecularProfileId()); + Assert.assertEquals((String) "TCGA-A1-A0SB-01", structuralVariantFirstResult.getSampleId()); + Assert.assertEquals((String) "TCGA-A1-A0SB", structuralVariantFirstResult.getPatientId()); + Assert.assertEquals((String) "study_tcga_pub", structuralVariantFirstResult.getStudyId()); + Assert.assertEquals((Integer) 57670, structuralVariantFirstResult.getSite1EntrezGeneId()); + Assert.assertEquals("KIAA1549", structuralVariantFirstResult.getSite1HugoSymbol()); + Assert.assertEquals( + "ENST00000242365", structuralVariantFirstResult.getSite1EnsemblTranscriptId()); + Assert.assertEquals("7", structuralVariantFirstResult.getSite1Chromosome()); + Assert.assertEquals((Integer) 138536968, structuralVariantFirstResult.getSite1Position()); + Assert.assertEquals( + "KIAA1549-BRAF.K16B10.COSF509_1", structuralVariantFirstResult.getSite1Description()); + Assert.assertEquals((Integer) 673, structuralVariantFirstResult.getSite2EntrezGeneId()); + Assert.assertEquals("BRAF", structuralVariantFirstResult.getSite2HugoSymbol()); + Assert.assertEquals( + "ENST00000288602", structuralVariantFirstResult.getSite2EnsemblTranscriptId()); + Assert.assertEquals("7", structuralVariantFirstResult.getSite2Chromosome()); + Assert.assertEquals((Integer) 140482957, structuralVariantFirstResult.getSite2Position()); + Assert.assertEquals( + "KIAA1549-BRAF.K16B10.COSF509_2", structuralVariantFirstResult.getSite2Description()); + Assert.assertEquals(null, structuralVariantFirstResult.getSite2EffectOnFrame()); + Assert.assertEquals("GRCh37", structuralVariantFirstResult.getNcbiBuild()); + Assert.assertEquals("no", structuralVariantFirstResult.getDnaSupport()); + Assert.assertEquals("yes", structuralVariantFirstResult.getRnaSupport()); + Assert.assertEquals(null, structuralVariantFirstResult.getNormalReadCount()); + Assert.assertEquals((Integer) 100000, structuralVariantFirstResult.getTumorReadCount()); + Assert.assertEquals(null, structuralVariantFirstResult.getNormalVariantCount()); + Assert.assertEquals((Integer) 90000, structuralVariantFirstResult.getTumorVariantCount()); + Assert.assertEquals(null, structuralVariantFirstResult.getNormalPairedEndReadCount()); + Assert.assertEquals(null, structuralVariantFirstResult.getTumorPairedEndReadCount()); + Assert.assertEquals(null, structuralVariantFirstResult.getNormalSplitReadCount()); + Assert.assertEquals(null, structuralVariantFirstResult.getTumorSplitReadCount()); + Assert.assertEquals( + "KIAA1549-BRAF.K16B10.COSF509", structuralVariantFirstResult.getAnnotation()); + Assert.assertEquals(null, structuralVariantFirstResult.getBreakpointType()); + Assert.assertEquals(null, structuralVariantFirstResult.getConnectionType()); + Assert.assertEquals("Fusion", structuralVariantFirstResult.getEventInfo()); + Assert.assertEquals(null, structuralVariantFirstResult.getVariantClass()); + Assert.assertEquals(null, structuralVariantFirstResult.getLength()); + Assert.assertEquals("Gain-of-Function", structuralVariantFirstResult.getComments()); + Assert.assertEquals("Putative_Passenger", structuralVariantFirstResult.getDriverFilter()); + Assert.assertEquals("Pathogenic", structuralVariantFirstResult.getDriverFilterAnn()); + Assert.assertEquals("Tier 1", structuralVariantFirstResult.getDriverTiersFilter()); + Assert.assertEquals( + "Potentially Actionable", structuralVariantFirstResult.getDriverTiersFilterAnn()); + Assert.assertEquals("SOMATIC", structuralVariantFirstResult.getSvStatus()); + StructuralVariant structuralVariantSecondResult = result.get(1); + Assert.assertEquals("study_tcga_pub_sv", structuralVariantSecondResult.getMolecularProfileId()); + Assert.assertEquals((String) "TCGA-A1-A0SD-01", structuralVariantSecondResult.getSampleId()); + Assert.assertEquals((String) "TCGA-A1-A0SD", structuralVariantSecondResult.getPatientId()); + Assert.assertEquals((String) "study_tcga_pub", structuralVariantSecondResult.getStudyId()); + Assert.assertEquals((Integer) 57670, structuralVariantSecondResult.getSite1EntrezGeneId()); + Assert.assertEquals("KIAA1549", structuralVariantSecondResult.getSite1HugoSymbol()); + Assert.assertEquals( + "ENST00000242365", structuralVariantSecondResult.getSite1EnsemblTranscriptId()); + Assert.assertEquals("7", structuralVariantSecondResult.getSite1Chromosome()); + Assert.assertEquals((Integer) 138536968, structuralVariantSecondResult.getSite1Position()); + Assert.assertEquals( + "KIAA1549-BRAF.K16B10.COSF509_1", structuralVariantSecondResult.getSite1Description()); + Assert.assertEquals((Integer) 673, structuralVariantSecondResult.getSite2EntrezGeneId()); + Assert.assertEquals("BRAF", structuralVariantSecondResult.getSite2HugoSymbol()); + Assert.assertEquals( + "ENST00000288602", structuralVariantSecondResult.getSite2EnsemblTranscriptId()); + Assert.assertEquals("7", structuralVariantSecondResult.getSite2Chromosome()); + Assert.assertEquals((Integer) 140482957, structuralVariantSecondResult.getSite2Position()); + Assert.assertEquals( + "KIAA1549-BRAF.K16B10.COSF509_2", structuralVariantSecondResult.getSite2Description()); + Assert.assertEquals(null, structuralVariantSecondResult.getSite2EffectOnFrame()); + Assert.assertEquals("GRCh37", structuralVariantSecondResult.getNcbiBuild()); + Assert.assertEquals("no", structuralVariantSecondResult.getDnaSupport()); + Assert.assertEquals("yes", structuralVariantSecondResult.getRnaSupport()); + Assert.assertEquals(null, structuralVariantSecondResult.getNormalReadCount()); + Assert.assertEquals((Integer) 100000, structuralVariantSecondResult.getTumorReadCount()); + Assert.assertEquals(null, structuralVariantSecondResult.getNormalVariantCount()); + Assert.assertEquals((Integer) 90000, structuralVariantSecondResult.getTumorVariantCount()); + Assert.assertEquals(null, structuralVariantSecondResult.getNormalPairedEndReadCount()); + Assert.assertEquals(null, structuralVariantSecondResult.getTumorPairedEndReadCount()); + Assert.assertEquals(null, structuralVariantSecondResult.getNormalSplitReadCount()); + Assert.assertEquals(null, structuralVariantSecondResult.getTumorSplitReadCount()); + Assert.assertEquals( + "KIAA1549-BRAF.K16B10.COSF509", structuralVariantSecondResult.getAnnotation()); + Assert.assertEquals(null, structuralVariantSecondResult.getBreakpointType()); + Assert.assertEquals(null, structuralVariantSecondResult.getConnectionType()); + Assert.assertEquals("Fusion", structuralVariantSecondResult.getEventInfo()); + Assert.assertEquals(null, structuralVariantSecondResult.getVariantClass()); + Assert.assertEquals(null, structuralVariantSecondResult.getLength()); + Assert.assertEquals("Gain-of-Function", structuralVariantSecondResult.getComments()); + Assert.assertEquals(null, structuralVariantSecondResult.getDriverFilter()); + Assert.assertEquals(null, structuralVariantSecondResult.getDriverFilterAnn()); + Assert.assertEquals(null, structuralVariantSecondResult.getDriverTiersFilter()); + Assert.assertEquals(null, structuralVariantSecondResult.getDriverTiersFilterAnn()); + Assert.assertEquals("GERMLINE", structuralVariantSecondResult.getSvStatus()); + StructuralVariant structuralVariantThirdResult = result.get(2); + Assert.assertEquals("study_tcga_pub_sv", structuralVariantThirdResult.getMolecularProfileId()); + Assert.assertEquals((String) "TCGA-A1-A0SD-01", structuralVariantThirdResult.getSampleId()); + Assert.assertEquals((String) "TCGA-A1-A0SD", structuralVariantThirdResult.getPatientId()); + Assert.assertEquals((String) "study_tcga_pub", structuralVariantThirdResult.getStudyId()); + Assert.assertEquals((Integer) 57670, structuralVariantThirdResult.getSite1EntrezGeneId()); + Assert.assertEquals("KIAA1549", structuralVariantThirdResult.getSite1HugoSymbol()); + Assert.assertEquals( + "ENST00000242365", structuralVariantThirdResult.getSite1EnsemblTranscriptId()); + Assert.assertEquals("7", structuralVariantThirdResult.getSite1Chromosome()); + Assert.assertEquals((Integer) 138536968, structuralVariantThirdResult.getSite1Position()); + Assert.assertEquals( + "KIAA1549-BRAF.K16B10.COSF509_1", structuralVariantThirdResult.getSite1Description()); + Assert.assertEquals((Integer) 673, structuralVariantThirdResult.getSite2EntrezGeneId()); + Assert.assertEquals("BRAF", structuralVariantThirdResult.getSite2HugoSymbol()); + Assert.assertEquals( + "ENST00000288602", structuralVariantThirdResult.getSite2EnsemblTranscriptId()); + Assert.assertEquals("7", structuralVariantThirdResult.getSite2Chromosome()); + Assert.assertEquals((Integer) 140482957, structuralVariantThirdResult.getSite2Position()); + Assert.assertEquals( + "KIAA1549-BRAF.K16B10.COSF509_2", structuralVariantThirdResult.getSite2Description()); + Assert.assertEquals(null, structuralVariantThirdResult.getSite2EffectOnFrame()); + Assert.assertEquals("GRCh37", structuralVariantThirdResult.getNcbiBuild()); + Assert.assertEquals("no", structuralVariantThirdResult.getDnaSupport()); + Assert.assertEquals("yes", structuralVariantThirdResult.getRnaSupport()); + Assert.assertEquals(null, structuralVariantThirdResult.getNormalReadCount()); + Assert.assertEquals((Integer) 100000, structuralVariantThirdResult.getTumorReadCount()); + Assert.assertEquals(null, structuralVariantThirdResult.getNormalVariantCount()); + Assert.assertEquals((Integer) 90000, structuralVariantThirdResult.getTumorVariantCount()); + Assert.assertEquals(null, structuralVariantThirdResult.getNormalPairedEndReadCount()); + Assert.assertEquals(null, structuralVariantThirdResult.getTumorPairedEndReadCount()); + Assert.assertEquals(null, structuralVariantThirdResult.getNormalSplitReadCount()); + Assert.assertEquals(null, structuralVariantThirdResult.getTumorSplitReadCount()); + Assert.assertEquals( + "KIAA1549-BRAF.K16B10.COSF509", structuralVariantThirdResult.getAnnotation()); + Assert.assertEquals(null, structuralVariantThirdResult.getBreakpointType()); + Assert.assertEquals(null, structuralVariantThirdResult.getConnectionType()); + Assert.assertEquals("Fusion", structuralVariantThirdResult.getEventInfo()); + Assert.assertEquals(null, structuralVariantThirdResult.getVariantClass()); + Assert.assertEquals(null, structuralVariantThirdResult.getLength()); + Assert.assertEquals("Gain-of-Function", structuralVariantThirdResult.getComments()); + Assert.assertEquals(null, structuralVariantThirdResult.getDriverFilter()); + Assert.assertEquals(null, structuralVariantThirdResult.getDriverFilterAnn()); + Assert.assertEquals(null, structuralVariantThirdResult.getDriverTiersFilter()); + Assert.assertEquals(null, structuralVariantThirdResult.getDriverTiersFilterAnn()); + Assert.assertEquals("SOMATIC", structuralVariantThirdResult.getSvStatus()); + } + + @Test + public void fetchStructuralVariantsWithSampleIdentifier() throws Exception { + + List molecularProfileIds = new ArrayList<>(); + List entrezGeneIds = new ArrayList(); + List sampleIds = new ArrayList(); + + molecularProfileIds.add("study_tcga_pub_sv"); + entrezGeneIds.add(57670); + sampleIds.add("TCGA-A1-A0SB-01"); + + List result = + structuralVariantMyBatisRepository.fetchStructuralVariants( + molecularProfileIds, sampleIds, entrezGeneIds, noStructVars); + + Assert.assertEquals(1, result.size()); + StructuralVariant structuralVariantResult = result.get(0); + Assert.assertEquals("study_tcga_pub_sv", structuralVariantResult.getMolecularProfileId()); + Assert.assertEquals((String) "TCGA-A1-A0SB-01", structuralVariantResult.getSampleId()); + Assert.assertEquals((String) "TCGA-A1-A0SB", structuralVariantResult.getPatientId()); + Assert.assertEquals((String) "study_tcga_pub", structuralVariantResult.getStudyId()); + } + + @Test + public void fetchStructuralVariantsMultiStudyWithSampleIdentifiers() throws Exception { + + List entrezGeneIds = new ArrayList(); + List molecularProfileIds = new ArrayList(); + List sampleIds = new ArrayList(); + + entrezGeneIds.add(57670); + molecularProfileIds.add("study_tcga_pub_sv"); + sampleIds.add("TCGA-A1-A0SB-01"); + molecularProfileIds.add("acc_tcga_sv"); + sampleIds.add("TCGA-A1-B0SO-01"); + + List result = + structuralVariantMyBatisRepository.fetchStructuralVariants( + molecularProfileIds, sampleIds, entrezGeneIds, noStructVars); + + Assert.assertEquals(2, result.size()); + StructuralVariant structuralVariantFirstResult = result.get(0); + Assert.assertEquals("acc_tcga_sv", structuralVariantFirstResult.getMolecularProfileId()); + Assert.assertEquals((String) "TCGA-A1-B0SO-01", structuralVariantFirstResult.getSampleId()); + Assert.assertEquals((String) "TCGA-A1-B0SO", structuralVariantFirstResult.getPatientId()); + Assert.assertEquals((String) "acc_tcga", structuralVariantFirstResult.getStudyId()); + Assert.assertEquals("acc_tcga_sv", structuralVariantFirstResult.getMolecularProfileId()); + Assert.assertEquals("TCGA-A1-B0SO-01", structuralVariantFirstResult.getSampleId()); + Assert.assertEquals("TCGA-A1-B0SO", structuralVariantFirstResult.getPatientId()); + Assert.assertEquals("acc_tcga", structuralVariantFirstResult.getStudyId()); + StructuralVariant structuralVariantSecondResult = result.get(1); + Assert.assertEquals("study_tcga_pub_sv", structuralVariantSecondResult.getMolecularProfileId()); + Assert.assertEquals((String) "TCGA-A1-A0SB-01", structuralVariantSecondResult.getSampleId()); + Assert.assertEquals((String) "TCGA-A1-A0SB", structuralVariantSecondResult.getPatientId()); + Assert.assertEquals((String) "study_tcga_pub", structuralVariantSecondResult.getStudyId()); + } + + @Test + public void fetchStructuralVariantsMultiStudyNoGeneIdentifiers() throws Exception { + + List molecularProfileIds = new ArrayList<>(); + List sampleIds = new ArrayList<>(); + molecularProfileIds.add("study_tcga_pub_sv"); + sampleIds.add("TCGA-A1-A0SB-01"); + molecularProfileIds.add("acc_tcga_sv"); + sampleIds.add("TCGA-A1-B0SO-01"); + + List result = + structuralVariantMyBatisRepository.fetchStructuralVariants( + molecularProfileIds, sampleIds, noEntrezIds, noStructVars); + + Assert.assertEquals(8, result.size()); + } + + @Test + public void fetchStructuralVariantsMultiStudyByGeneQueriesWithSampleIdentifiers() + throws Exception { + + List result = + structuralVariantMyBatisRepository.fetchStructuralVariantsByGeneQueries( + molecularProfileIds, sampleIds, geneQueries); + + Assert.assertEquals(11, result.size()); + + List resultTcgaPubVariants = + result.stream() + .filter(s -> "study_tcga_pub_sv".equals(s.getMolecularProfileId())) + .map(StructuralVariant::getAnnotation) + .collect(Collectors.toList()); + List resultTcgaVariants = + result.stream() + .filter(s -> "acc_tcga_sv".equals(s.getMolecularProfileId())) + .map(StructuralVariant::getAnnotation) + .collect(Collectors.toList()); + + Assert.assertArrayEquals( + new String[] { + "EML4-ALK.E6bA20.AB374362", + "EML4-ALK.E6bA20.AB374362-2", + "KIAA1549-BRAF.K16B10.COSF509", + "KIAA1549-BRAF.K16B10.COSF509", + "KIAA1549-BRAF.K16B10.COSF509", + "NCOA4-RET.N7R1", + "TMPRSS2-ERG.T1E2.COSF23.1" + }, + resultTcgaPubVariants.toArray()); + Assert.assertArrayEquals( + new String[] { + "KIAA1549-BRAF.K16B10.COSF509", + "NCOA4-NULL", + "NCOA4-RET.N7R1-2", + "TMPRSS2-ERG.T1E2.COSF23.1" + }, + resultTcgaVariants.toArray()); + } + + @Test + public void fetchStructuralVariantsMultiStudyByGeneQueriesWithSampleIdentifiersExcludePassenger() + throws Exception { + + // There is one passenger event in 'study_tcga_pub_sv', the rest is unannotated + geneQueries.stream() + .forEach( + q -> { + q.setIncludeVUS(false); + }); + + List result = + structuralVariantMyBatisRepository.fetchStructuralVariantsByGeneQueries( + molecularProfileIds, sampleIds, geneQueries); + + Assert.assertEquals(10, result.size()); + + List resultTcgaPubVariants = + result.stream() + .filter(s -> "study_tcga_pub_sv".equals(s.getMolecularProfileId())) + .map(StructuralVariant::getAnnotation) + .collect(Collectors.toList()); + List resultTcgaVariants = + result.stream() + .filter(s -> "acc_tcga_sv".equals(s.getMolecularProfileId())) + .map(StructuralVariant::getAnnotation) + .collect(Collectors.toList()); + + Assert.assertArrayEquals( + new String[] { + "EML4-ALK.E6bA20.AB374362", + "EML4-ALK.E6bA20.AB374362-2", + "KIAA1549-BRAF.K16B10.COSF509", + "KIAA1549-BRAF.K16B10.COSF509", + "NCOA4-RET.N7R1", + "TMPRSS2-ERG.T1E2.COSF23.1" + }, + resultTcgaPubVariants.toArray()); + Assert.assertArrayEquals( + new String[] { + "KIAA1549-BRAF.K16B10.COSF509", + "NCOA4-NULL", + "NCOA4-RET.N7R1-2", + "TMPRSS2-ERG.T1E2.COSF23.1" + }, + resultTcgaVariants.toArray()); + } + + @Test + public void + fetchStructuralVariantsMultiStudyByGeneQueriesWithSampleIdentifiersSelectUnknownOncogenicity() + throws Exception { + + // There is one passenger event in 'study_tcga_pub_sv', the rest is unannotatedd + geneQueries.stream() + .forEach( + q -> { + q.setIncludeDriver(false); + q.setIncludeVUS(false); + }); + + List result = + structuralVariantMyBatisRepository.fetchStructuralVariantsByGeneQueries( + molecularProfileIds, sampleIds, geneQueries); + + Assert.assertEquals(8, result.size()); + + List resultTcgaPubVariants = + result.stream() + .filter(s -> "study_tcga_pub_sv".equals(s.getMolecularProfileId())) + .map(StructuralVariant::getAnnotation) + .collect(Collectors.toList()); + List resultTcgaVariants = + result.stream() + .filter(s -> "acc_tcga_sv".equals(s.getMolecularProfileId())) + .map(StructuralVariant::getAnnotation) + .collect(Collectors.toList()); + + Assert.assertArrayEquals( + new String[] { + "EML4-ALK.E6bA20.AB374362", + "KIAA1549-BRAF.K16B10.COSF509", + "KIAA1549-BRAF.K16B10.COSF509", + "TMPRSS2-ERG.T1E2.COSF23.1" + }, + resultTcgaPubVariants.toArray()); + Assert.assertArrayEquals( + new String[] { + "KIAA1549-BRAF.K16B10.COSF509", + "NCOA4-NULL", + "NCOA4-RET.N7R1-2", + "TMPRSS2-ERG.T1E2.COSF23.1" + }, + resultTcgaVariants.toArray()); + } + + @Test + public void + fetchStructuralVariantsMultiStudyByGeneQueriesWithSampleIdentifiersExcludeUnknownOncogenicity() + throws Exception { + + // There is one passenger event in 'study_tcga_pub_sv', the rest is unannotated + + geneQueries.stream() + .forEach( + q -> { + q.setIncludeDriver(false); + q.setIncludeUnknownOncogenicity(false); + }); + + List result = + structuralVariantMyBatisRepository.fetchStructuralVariantsByGeneQueries( + molecularProfileIds, sampleIds, geneQueries); + + Assert.assertEquals(1, result.size()); + + List resultTcgaPubVariants = + result.stream() + .filter(s -> "study_tcga_pub_sv".equals(s.getMolecularProfileId())) + .map(StructuralVariant::getAnnotation) + .collect(Collectors.toList()); + + Assert.assertArrayEquals( + new String[] {"KIAA1549-BRAF.K16B10.COSF509"}, resultTcgaPubVariants.toArray()); + } + + @Test + public void fetchStructuralVariantsMultiStudyByGeneQueriesWithSampleIdentifiersIncludeTier() + throws Exception { + + // There is one passenger event that is 'Tier 1 annotated' in 'study_tcga_pub_sv', the rest is + // unannotated + geneQueries.stream() + .forEach( + q -> { + q.setIncludeUnknownTier(false); + q.setSelectedTiers(Select.byValues(Arrays.asList("Tier 1"))); + }); + + List result = + structuralVariantMyBatisRepository.fetchStructuralVariantsByGeneQueries( + molecularProfileIds, sampleIds, geneQueries); + + Assert.assertEquals(1, result.size()); + + List resultTcgaPubVariants = + result.stream() + .filter(s -> "study_tcga_pub_sv".equals(s.getMolecularProfileId())) + .map(StructuralVariant::getAnnotation) + .collect(Collectors.toList()); + + Assert.assertArrayEquals( + new String[] {"KIAA1549-BRAF.K16B10.COSF509"}, resultTcgaPubVariants.toArray()); + } + + @Test + public void fetchStructuralVariantsMultiStudyByGeneQueriesWithSampleIdentifiersUnknownTier() + throws Exception { + + // There is one passenger event that is 'Tier 1 annotated' in 'study_tcga_pub_sv', the rest is + // unannotated + geneQueries.stream() + .forEach( + q -> { + q.setSelectedTiers(Select.none()); + }); + + List result = + structuralVariantMyBatisRepository.fetchStructuralVariantsByGeneQueries( + molecularProfileIds, sampleIds, geneQueries); + + Assert.assertEquals(8, result.size()); + + List resultTcgaPubVariants = + result.stream() + .filter(s -> "study_tcga_pub_sv".equals(s.getMolecularProfileId())) + .map(StructuralVariant::getAnnotation) + .collect(Collectors.toList()); + List resultTcgaVariants = + result.stream() + .filter(s -> "acc_tcga_sv".equals(s.getMolecularProfileId())) + .map(StructuralVariant::getAnnotation) + .collect(Collectors.toList()); + + Assert.assertArrayEquals( + new String[] { + "EML4-ALK.E6bA20.AB374362", + "KIAA1549-BRAF.K16B10.COSF509", + "KIAA1549-BRAF.K16B10.COSF509", + "TMPRSS2-ERG.T1E2.COSF23.1" + }, + resultTcgaPubVariants.toArray()); + Assert.assertArrayEquals( + new String[] { + "KIAA1549-BRAF.K16B10.COSF509", + "NCOA4-NULL", + "NCOA4-RET.N7R1-2", + "TMPRSS2-ERG.T1E2.COSF23.1" + }, + resultTcgaVariants.toArray()); + } + + @Test + public void fetchStructuralVariantsWithSingleStructuralVariantQueries() throws Exception { + + List molecularProfileIds = new ArrayList<>(); + List sampleIds = new ArrayList<>(); + + molecularProfileIds.add("study_tcga_pub_sv"); + + List singleStructVarQuery = new ArrayList<>(); + singleStructVarQuery.add( + new StructuralVariantQuery( + new StructuralVariantGeneSubQuery(27436), new StructuralVariantGeneSubQuery(238))); + + List result = + structuralVariantMyBatisRepository.fetchStructuralVariants( + molecularProfileIds, sampleIds, noEntrezIds, singleStructVarQuery); + + Assert.assertEquals(2, result.size()); + StructuralVariant structuralVariantFirstResult = result.get(0); + Assert.assertEquals((Integer) 27436, structuralVariantFirstResult.getSite1EntrezGeneId()); + Assert.assertEquals((Integer) 238, structuralVariantFirstResult.getSite2EntrezGeneId()); + Assert.assertEquals("Fusion", structuralVariantFirstResult.getEventInfo()); + } + + @Test + public void fetchStructuralVariantsWithStructuralVariantQueryAndGeneId() throws Exception { + + List molecularProfileIds = new ArrayList<>(); + List sampleIds = new ArrayList<>(); + + molecularProfileIds.add("study_tcga_pub_sv"); + + List entrezGeneId = Arrays.asList(8031); + List singleStructVarQuery = new ArrayList<>(); + singleStructVarQuery.add( + new StructuralVariantQuery( + new StructuralVariantGeneSubQuery(27436), new StructuralVariantGeneSubQuery(238))); + + List result = + structuralVariantMyBatisRepository.fetchStructuralVariants( + molecularProfileIds, sampleIds, entrezGeneId, singleStructVarQuery); + + Assert.assertEquals(3, result.size()); + } + + @Test + public void fetchStructuralVariantsWithMultipleStructuralVariantQueries() throws Exception { + List molecularProfileIds = new ArrayList<>(); + List sampleIds = new ArrayList<>(); + + molecularProfileIds.add("study_tcga_pub_sv"); + + List multipleStructVarQueries = new ArrayList<>(); + multipleStructVarQueries.add( + new StructuralVariantQuery( + new StructuralVariantGeneSubQuery(27436), new StructuralVariantGeneSubQuery(238))); + multipleStructVarQueries.add( + new StructuralVariantQuery( + new StructuralVariantGeneSubQuery(57670), new StructuralVariantGeneSubQuery(673))); + + List result = + structuralVariantMyBatisRepository.fetchStructuralVariants( + molecularProfileIds, sampleIds, noEntrezIds, multipleStructVarQueries); + + Assert.assertEquals(5, result.size()); + + List structuralVariantFirstResult = + result.stream() + .filter( + sv -> + Objects.equals(sv.getSite1EntrezGeneId(), 27436) + && Objects.equals(sv.getSite2EntrezGeneId(), 238)) + .collect(Collectors.toList()); + ; + Assert.assertEquals(2, structuralVariantFirstResult.size()); + + List structuralVariantSecondResults = + result.stream() + .filter( + sv -> + Objects.equals(sv.getSite1EntrezGeneId(), 57670) + && Objects.equals(sv.getSite2EntrezGeneId(), 673)) + .collect(Collectors.toList()); + Assert.assertEquals(3, structuralVariantSecondResults.size()); + } + + @Test + public void fetchStructuralVariantsWithMultipleStructuralVariantIdentifierWildcardQueryValue() { + List molecularProfileIds = new ArrayList<>(); + List sampleIds = new ArrayList<>(); + + molecularProfileIds.add("study_tcga_pub_sv"); + + List structVarQueries = new ArrayList<>(); + + StructuralVariantQuery svId1 = + new StructuralVariantQuery( + new StructuralVariantGeneSubQuery(27436), + new StructuralVariantGeneSubQuery(StructuralVariantSpecialValue.ANY_GENE)); + structVarQueries.add(svId1); + + StructuralVariantQuery svId2 = + new StructuralVariantQuery( + new StructuralVariantGeneSubQuery(StructuralVariantSpecialValue.ANY_GENE), + new StructuralVariantGeneSubQuery(673)); + structVarQueries.add(svId2); + + List result = + structuralVariantMyBatisRepository.fetchStructuralVariants( + molecularProfileIds, sampleIds, noEntrezIds, structVarQueries); + + Assert.assertEquals(5, result.size()); + + List structuralVariantFirstResult = + result.stream() + .filter( + sv -> + Objects.equals(sv.getSite1EntrezGeneId(), 27436) + && Objects.equals(sv.getSite2EntrezGeneId(), 238)) + .collect(Collectors.toList()); + ; + Assert.assertEquals(2, structuralVariantFirstResult.size()); + + List structuralVariantSecondResults = + result.stream() + .filter( + sv -> + Objects.equals(sv.getSite1EntrezGeneId(), 57670) + && Objects.equals(sv.getSite2EntrezGeneId(), 673)) + .collect(Collectors.toList()); + Assert.assertEquals(3, structuralVariantSecondResults.size()); + } + + @Test + public void fetchStructuralVariantsWithMultipleStructuralVariantQueryNullQueryValue() { + List molecularProfileIds = new ArrayList<>(); + List sampleIds = new ArrayList<>(); + + molecularProfileIds.add("acc_tcga_sv"); + + List structVarQueries = new ArrayList<>(); + StructuralVariantQuery structVarWithNull = + new StructuralVariantQuery( + new StructuralVariantGeneSubQuery(8031), + new StructuralVariantGeneSubQuery(StructuralVariantSpecialValue.NO_GENE)); + structVarQueries.add(structVarWithNull); + + List result = + structuralVariantMyBatisRepository.fetchStructuralVariants( + molecularProfileIds, sampleIds, noEntrezIds, structVarQueries); + + Assert.assertEquals(1, result.size()); + Assert.assertEquals((Integer) 8031, result.get(0).getSite1EntrezGeneId()); + Assert.assertEquals("ENST00000340058_NULL", result.get(0).getSite2EnsemblTranscriptId()); + } + + @Test + public void fetchStructuralVariantsMultiStudyByStructVarQueriesAll() throws Exception { + + List result = + structuralVariantMyBatisRepository.fetchStructuralVariantsByStructVarQueries( + molecularProfileIds, sampleIds, structVarQueries); + + Assert.assertEquals(6, result.size()); + + List resultTcgaPubVariants = + result.stream() + .filter(s -> "study_tcga_pub_sv".equals(s.getMolecularProfileId())) + .map(StructuralVariant::getAnnotation) + .collect(Collectors.toList()); + List resultTcgaVariants = + result.stream() + .filter(s -> "acc_tcga_sv".equals(s.getMolecularProfileId())) + .map(StructuralVariant::getAnnotation) + .collect(Collectors.toList()); + + Assert.assertArrayEquals( + new String[] { + "EML4-ALK.E6bA20.AB374362", + "EML4-ALK.E6bA20.AB374362-2", + "KIAA1549-BRAF.K16B10.COSF509", + "KIAA1549-BRAF.K16B10.COSF509", + "KIAA1549-BRAF.K16B10.COSF509" + }, + resultTcgaPubVariants.toArray()); + Assert.assertArrayEquals( + new String[] {"KIAA1549-BRAF.K16B10.COSF509"}, resultTcgaVariants.toArray()); + } + + @Test + public void fetchStructuralVariantsMultiStudyByStructVarQueriesNoGermline() throws Exception { + + structVarFilterQuery1.setIncludeGermline(false); + structVarFilterQuery2.setIncludeGermline(false); + + List result = + structuralVariantMyBatisRepository.fetchStructuralVariantsByStructVarQueries( + molecularProfileIds, sampleIds, structVarQueries); + + Assert.assertEquals(4, result.size()); + + List resultTcgaPubVariants = + result.stream() + .filter(s -> "study_tcga_pub_sv".equals(s.getMolecularProfileId())) + .map(StructuralVariant::getAnnotation) + .collect(Collectors.toList()); + List resultTcgaVariants = + result.stream() + .filter(s -> "acc_tcga_sv".equals(s.getMolecularProfileId())) + .map(StructuralVariant::getAnnotation) + .collect(Collectors.toList()); + + Assert.assertArrayEquals( + new String[] { + "EML4-ALK.E6bA20.AB374362-2", + "KIAA1549-BRAF.K16B10.COSF509", + "KIAA1549-BRAF.K16B10.COSF509" + }, + resultTcgaPubVariants.toArray()); + Assert.assertArrayEquals( + new String[] {"KIAA1549-BRAF.K16B10.COSF509"}, resultTcgaVariants.toArray()); + } + + @Test + public void fetchStructuralVariantsMultiStudyByStructVarQueriesNoSomatic() throws Exception { + + structVarFilterQuery1.setIncludeSomatic(false); + structVarFilterQuery2.setIncludeSomatic(false); + + List result = + structuralVariantMyBatisRepository.fetchStructuralVariantsByStructVarQueries( + molecularProfileIds, sampleIds, structVarQueries); + + Assert.assertEquals(2, result.size()); + + List resultTcgaPubVariants = + result.stream() + .filter(s -> "study_tcga_pub_sv".equals(s.getMolecularProfileId())) + .map(StructuralVariant::getAnnotation) + .collect(Collectors.toList()); + List resultTcgaVariants = + result.stream() + .filter(s -> "acc_tcga_sv".equals(s.getMolecularProfileId())) + .map(StructuralVariant::getAnnotation) + .collect(Collectors.toList()); + + Assert.assertArrayEquals( + new String[] {"EML4-ALK.E6bA20.AB374362", "KIAA1549-BRAF.K16B10.COSF509"}, + resultTcgaPubVariants.toArray()); + Assert.assertEquals(0, resultTcgaVariants.size()); + } + + @Test + public void fetchStructuralVariantsMultiStudyByStructVarQueriesAnyGene1() throws Exception { + + structVarFilterQuery1.getGene1Query().setSpecialValue(StructuralVariantSpecialValue.ANY_GENE); + structVarFilterQuery2.getGene1Query().setSpecialValue(StructuralVariantSpecialValue.ANY_GENE); + + List result = + structuralVariantMyBatisRepository.fetchStructuralVariantsByStructVarQueries( + molecularProfileIds, sampleIds, structVarQueries); + + Assert.assertEquals(6, result.size()); + } + + @Test + public void fetchStructuralVariantsMultiStudyByStructVarQueriesAnyGene2() throws Exception { + + structVarFilterQuery1.getGene2Query().setSpecialValue(StructuralVariantSpecialValue.ANY_GENE); + structVarFilterQuery2.getGene2Query().setSpecialValue(StructuralVariantSpecialValue.ANY_GENE); + + List result = + structuralVariantMyBatisRepository.fetchStructuralVariantsByStructVarQueries( + molecularProfileIds, sampleIds, structVarQueries); + + Assert.assertEquals(6, result.size()); + } + + @Test + public void fetchStructuralVariantsMultiStudyByStructVarQueriesNullGene1() throws Exception { + + List result = + structuralVariantMyBatisRepository.fetchStructuralVariantsByStructVarQueries( + molecularProfileIds, sampleIds, Arrays.asList(structVarFilterQueryNullGene1)); + + Assert.assertEquals(0, result.size()); + } + + @Test + public void fetchStructuralVariantsMultiStudyByStructVarQueriesNullGene2() throws Exception { + + List result = + structuralVariantMyBatisRepository.fetchStructuralVariantsByStructVarQueries( + molecularProfileIds, sampleIds, Arrays.asList(structVarFilterQueryNullGene2)); + + Assert.assertEquals(1, result.size()); + } +} diff --git a/src/test/java/org/cbioportal/legacy/persistence/mybatis/StudyMyBatisRepositoryTest.java b/src/test/java/org/cbioportal/legacy/persistence/mybatis/StudyMyBatisRepositoryTest.java new file mode 100644 index 00000000000..8ae3ea51cd3 --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/persistence/mybatis/StudyMyBatisRepositoryTest.java @@ -0,0 +1,259 @@ +package org.cbioportal.legacy.persistence.mybatis; + +import java.text.SimpleDateFormat; +import java.util.Arrays; +import java.util.List; +import java.util.TimeZone; +import org.cbioportal.legacy.model.CancerStudy; +import org.cbioportal.legacy.model.CancerStudyTags; +import org.cbioportal.legacy.model.TypeOfCancer; +import org.cbioportal.legacy.model.meta.BaseMeta; +import org.cbioportal.legacy.persistence.mybatis.config.TestConfig; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +@RunWith(SpringJUnit4ClassRunner.class) +@SpringBootTest(classes = {StudyMyBatisRepository.class, TestConfig.class}) +public class StudyMyBatisRepositoryTest { + + @Autowired private StudyMyBatisRepository studyMyBatisRepository; + + @Test + public void getAllStudiesIdProjection() throws Exception { + + List result = + studyMyBatisRepository.getAllStudies(null, "ID", null, null, null, null); + + Assert.assertEquals(2, result.size()); + CancerStudy cancerStudy = result.get(0); + Assert.assertEquals((Integer) 2, cancerStudy.getCancerStudyId()); + Assert.assertEquals("acc_tcga", cancerStudy.getCancerStudyIdentifier()); + Assert.assertNull(cancerStudy.getTypeOfCancer()); + } + + @Test + public void getAllStudiesSummaryProjection() throws Exception { + + List result = + studyMyBatisRepository.getAllStudies(null, "SUMMARY", null, null, null, null); + + SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + simpleDateFormat.setTimeZone(TimeZone.getTimeZone("UTC")); + + Assert.assertEquals(2, result.size()); + CancerStudy cancerStudy = result.get(0); + Assert.assertEquals((Integer) 1, cancerStudy.getCancerStudyId()); + Assert.assertEquals("study_tcga_pub", cancerStudy.getCancerStudyIdentifier()); + Assert.assertEquals("brca", cancerStudy.getTypeOfCancerId()); + Assert.assertEquals("Breast Invasive Carcinoma (TCGA, Nature 2012)", cancerStudy.getName()); + Assert.assertEquals( + "The Cancer Genome Atlas (TCGA) Breast" + + " Invasive Carcinoma project. 825 cases.
Nature 2012. Raw data via the TCGA Data Portal.", + cancerStudy.getDescription()); + Assert.assertEquals(true, cancerStudy.getPublicStudy()); + Assert.assertEquals("23000897,26451490", cancerStudy.getPmid()); + Assert.assertEquals("TCGA, Nature 2012, ...", cancerStudy.getCitation()); + Assert.assertEquals("SU2C-PI3K;PUBLIC;GDAC", cancerStudy.getGroups()); + Assert.assertEquals((Integer) 0, cancerStudy.getStatus()); + Assert.assertEquals( + simpleDateFormat.parse("2011-12-18 13:17:17+00:00"), cancerStudy.getImportDate()); + Assert.assertEquals((Integer) 14, cancerStudy.getAllSampleCount()); + Assert.assertNull(cancerStudy.getTypeOfCancer()); + } + + @Test + public void getAllStudiesDetailedProjection() throws Exception { + + List result = + studyMyBatisRepository.getAllStudies(null, "DETAILED", null, null, null, null); + + SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + simpleDateFormat.setTimeZone(TimeZone.getTimeZone("UTC")); + + Assert.assertEquals(2, result.size()); + CancerStudy cancerStudy = result.get(0); + Assert.assertEquals((Integer) 1, cancerStudy.getCancerStudyId()); + Assert.assertEquals("study_tcga_pub", cancerStudy.getCancerStudyIdentifier()); + Assert.assertEquals("brca", cancerStudy.getTypeOfCancerId()); + Assert.assertEquals("Breast Invasive Carcinoma (TCGA, Nature 2012)", cancerStudy.getName()); + Assert.assertEquals( + "The Cancer Genome Atlas (TCGA) Breast" + + " Invasive Carcinoma project. 825 cases.
Nature 2012. Raw data via the TCGA Data Portal.", + cancerStudy.getDescription()); + Assert.assertEquals(true, cancerStudy.getPublicStudy()); + Assert.assertEquals("23000897,26451490", cancerStudy.getPmid()); + Assert.assertEquals("TCGA, Nature 2012, ...", cancerStudy.getCitation()); + Assert.assertEquals("SU2C-PI3K;PUBLIC;GDAC", cancerStudy.getGroups()); + Assert.assertEquals((Integer) 0, cancerStudy.getStatus()); + Assert.assertEquals(simpleDateFormat.parse("2011-12-18 13:17:17"), cancerStudy.getImportDate()); + Assert.assertEquals((Integer) 14, cancerStudy.getAllSampleCount()); + Assert.assertEquals((Integer) 7, cancerStudy.getCnaSampleCount()); + Assert.assertEquals((Integer) 7, cancerStudy.getCompleteSampleCount()); + Assert.assertEquals((Integer) 1, cancerStudy.getMethylationHm27SampleCount()); + Assert.assertEquals((Integer) 0, cancerStudy.getMiRnaSampleCount()); + Assert.assertEquals((Integer) 8, cancerStudy.getMrnaMicroarraySampleCount()); + Assert.assertEquals((Integer) 0, cancerStudy.getMrnaRnaSeqSampleCount()); + Assert.assertEquals((Integer) 7, cancerStudy.getMrnaRnaSeqV2SampleCount()); + Assert.assertEquals((Integer) 0, cancerStudy.getRppaSampleCount()); + Assert.assertEquals((Integer) 7, cancerStudy.getSequencedSampleCount()); + TypeOfCancer typeOfCancer = cancerStudy.getTypeOfCancer(); + Assert.assertEquals("brca", typeOfCancer.getTypeOfCancerId()); + Assert.assertEquals("Breast Invasive Carcinoma", typeOfCancer.getName()); + Assert.assertEquals("HotPink", typeOfCancer.getDedicatedColor()); + Assert.assertEquals("Breast", typeOfCancer.getShortName()); + Assert.assertEquals("tissue", typeOfCancer.getParent()); + } + + @Test + public void getAllStudiesSummaryProjection1PageSize() throws Exception { + + List result = + studyMyBatisRepository.getAllStudies(null, "SUMMARY", 1, 0, null, null); + + Assert.assertEquals(1, result.size()); + } + + @Test + public void getAllStudiesSummaryProjectionCancerStudyIdentifierSort() throws Exception { + + List result = + studyMyBatisRepository.getAllStudies( + null, "SUMMARY", null, null, "cancerStudyIdentifier", "ASC"); + + Assert.assertEquals(2, result.size()); + Assert.assertEquals("acc_tcga", result.get(0).getCancerStudyIdentifier()); + Assert.assertEquals("study_tcga_pub", result.get(1).getCancerStudyIdentifier()); + } + + @Test + public void getMetaStudies() throws Exception { + + BaseMeta result = studyMyBatisRepository.getMetaStudies(null); + + Assert.assertEquals((Integer) 2, result.getTotalCount()); + } + + @Test + public void getStudyNullResult() throws Exception { + + CancerStudy result = studyMyBatisRepository.getStudy("invalid_study", "DETAILED"); + + Assert.assertNull(result); + } + + @Test + public void getStudy() throws Exception { + + CancerStudy result = studyMyBatisRepository.getStudy("study_tcga_pub", "DETAILED"); + + SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + simpleDateFormat.setTimeZone(TimeZone.getTimeZone("UTC")); + + Assert.assertEquals((Integer) 1, result.getCancerStudyId()); + Assert.assertEquals("study_tcga_pub", result.getCancerStudyIdentifier()); + Assert.assertEquals("brca", result.getTypeOfCancerId()); + Assert.assertEquals("Breast Invasive Carcinoma (TCGA, Nature 2012)", result.getName()); + Assert.assertEquals( + "The Cancer Genome Atlas (TCGA) Breast" + + " Invasive Carcinoma project. 825 cases.
Nature 2012. Raw data via the TCGA Data Portal.", + result.getDescription()); + Assert.assertEquals(true, result.getPublicStudy()); + Assert.assertEquals("23000897,26451490", result.getPmid()); + Assert.assertEquals("TCGA, Nature 2012, ...", result.getCitation()); + Assert.assertEquals("SU2C-PI3K;PUBLIC;GDAC", result.getGroups()); + Assert.assertEquals((Integer) 0, result.getStatus()); + Assert.assertEquals(simpleDateFormat.parse("2011-12-18 13:17:17"), result.getImportDate()); + Assert.assertEquals((Integer) 14, result.getAllSampleCount()); + Assert.assertEquals((Integer) 7, result.getCnaSampleCount()); + Assert.assertEquals((Integer) 7, result.getCompleteSampleCount()); + Assert.assertEquals((Integer) 1, result.getMethylationHm27SampleCount()); + Assert.assertEquals((Integer) 0, result.getMiRnaSampleCount()); + Assert.assertEquals((Integer) 8, result.getMrnaMicroarraySampleCount()); + Assert.assertEquals((Integer) 0, result.getMrnaRnaSeqSampleCount()); + Assert.assertEquals((Integer) 7, result.getMrnaRnaSeqV2SampleCount()); + Assert.assertEquals((Integer) 0, result.getRppaSampleCount()); + Assert.assertEquals((Integer) 7, result.getSequencedSampleCount()); + TypeOfCancer typeOfCancer = result.getTypeOfCancer(); + Assert.assertEquals("brca", typeOfCancer.getTypeOfCancerId()); + Assert.assertEquals("Breast Invasive Carcinoma", typeOfCancer.getName()); + Assert.assertEquals("HotPink", typeOfCancer.getDedicatedColor()); + Assert.assertEquals("Breast", typeOfCancer.getShortName()); + Assert.assertEquals("tissue", typeOfCancer.getParent()); + } + + @Test + public void fetchStudies() throws Exception { + + List result = + studyMyBatisRepository.fetchStudies(Arrays.asList("study_tcga_pub", "acc_tcga"), "SUMMARY"); + + SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + simpleDateFormat.setTimeZone(TimeZone.getTimeZone("UTC")); + + Assert.assertEquals(2, result.size()); + CancerStudy cancerStudy = result.get(0); + Assert.assertEquals((Integer) 1, cancerStudy.getCancerStudyId()); + Assert.assertEquals("study_tcga_pub", cancerStudy.getCancerStudyIdentifier()); + Assert.assertEquals("brca", cancerStudy.getTypeOfCancerId()); + Assert.assertEquals("Breast Invasive Carcinoma (TCGA, Nature 2012)", cancerStudy.getName()); + Assert.assertEquals( + "The Cancer Genome Atlas (TCGA) Breast" + + " Invasive Carcinoma project. 825 cases.
Nature 2012. Raw data via the TCGA Data Portal.", + cancerStudy.getDescription()); + Assert.assertEquals(true, cancerStudy.getPublicStudy()); + Assert.assertEquals("23000897,26451490", cancerStudy.getPmid()); + Assert.assertEquals("TCGA, Nature 2012, ...", cancerStudy.getCitation()); + Assert.assertEquals("SU2C-PI3K;PUBLIC;GDAC", cancerStudy.getGroups()); + Assert.assertEquals((Integer) 0, cancerStudy.getStatus()); + Assert.assertEquals(simpleDateFormat.parse("2011-12-18 13:17:17"), cancerStudy.getImportDate()); + Assert.assertEquals((Integer) 14, cancerStudy.getAllSampleCount()); + Assert.assertNull(cancerStudy.getTypeOfCancer()); + } + + @Test + public void fetchMetaStudies() throws Exception { + + BaseMeta result = + studyMyBatisRepository.fetchMetaStudies(Arrays.asList("study_tcga_pub", "acc_tcga")); + + Assert.assertEquals((Integer) 2, result.getTotalCount()); + } + + @Test + public void getTags() throws Exception { + + CancerStudyTags result = studyMyBatisRepository.getTags("study_tcga_pub"); + + Assert.assertEquals( + "{\"Analyst\": {\"Name\": \"Jack\", \"Email\": \"jack@something.com\"}, \"Load id\": 35}", + result.getTags()); + } + + @Test + public void getMultipleTags() throws Exception { + + List result = + studyMyBatisRepository.getTagsForMultipleStudies( + Arrays.asList("study_tcga_pub", "acc_tcga")); + + Assert.assertEquals(2, result.size()); + CancerStudyTags cancerStudyTags1 = result.get(1); + Assert.assertEquals((Integer) 1, cancerStudyTags1.getCancerStudyId()); + Assert.assertEquals("study_tcga_pub", cancerStudyTags1.getStudyId()); + Assert.assertEquals( + "{\"Analyst\": {\"Name\": \"Jack\", \"Email\": \"jack@something.com\"}, \"Load id\": 35}", + cancerStudyTags1.getTags()); + CancerStudyTags cancerStudyTags2 = result.get(0); + Assert.assertEquals((Integer) 2, cancerStudyTags2.getCancerStudyId()); + Assert.assertEquals("acc_tcga", cancerStudyTags2.getStudyId()); + Assert.assertEquals("{\"Load id\": 36}", cancerStudyTags2.getTags()); + } +} diff --git a/src/test/java/org/cbioportal/legacy/persistence/mybatis/TreatmentMyBatisRepositoryTest.java b/src/test/java/org/cbioportal/legacy/persistence/mybatis/TreatmentMyBatisRepositoryTest.java new file mode 100644 index 00000000000..305312ec8fc --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/persistence/mybatis/TreatmentMyBatisRepositoryTest.java @@ -0,0 +1,176 @@ +package org.cbioportal.legacy.persistence.mybatis; + +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import org.cbioportal.legacy.model.ClinicalEventKeyCode; +import org.cbioportal.legacy.model.ClinicalEventSample; +import org.cbioportal.legacy.model.Treatment; +import org.cbioportal.legacy.persistence.TreatmentRepository; +import org.cbioportal.legacy.persistence.mybatis.config.TestConfig; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +@RunWith(SpringJUnit4ClassRunner.class) +@SpringBootTest(classes = {TreatmentMyBatisRepository.class, TestConfig.class}) +public class TreatmentMyBatisRepositoryTest { + + @Autowired TreatmentRepository treatmentRepository; + + @Test + public void getTreatmentsByPatientId() { + Treatment treatment1 = new Treatment(); + treatment1.setTreatment("Madeupanib"); + treatment1.setStudyId("study_tcga_pub"); + treatment1.setPatientId("TCGA-A1-A0SD"); + treatment1.setStart(213); + treatment1.setStop(445); + + Treatment treatment2 = new Treatment(); + treatment2.setTreatment("abc"); + treatment2.setStudyId("study_tcga_pub"); + treatment2.setPatientId("TCGA-A1-A0SD"); + treatment2.setStart(313); + treatment2.setStop(543); + + Map> expected = new HashMap<>(); + expected.put("TCGA-A1-A0SD", Arrays.asList(treatment1, treatment2)); + + Map> actual = + treatmentRepository.getTreatmentsByPatientId( + Collections.singletonList("TCGA-A1-A0SD-01"), + Collections.singletonList("study_tcga_pub"), + ClinicalEventKeyCode.Agent); + + Assert.assertEquals(actual, expected); + } + + @Test + public void getTreatmentAgentsByPatientId() { + Treatment treatment1 = new Treatment(); + treatment1.setTreatment("Directly to forehead"); + treatment1.setStudyId("study_tcga_pub"); + treatment1.setPatientId("TCGA-A1-A0SD"); + treatment1.setStart(213); + treatment1.setStop(445); + + Treatment treatment2 = new Treatment(); + treatment2.setTreatment("Elbow"); + treatment2.setStudyId("study_tcga_pub"); + treatment2.setPatientId("TCGA-A1-A0SD"); + treatment2.setStart(213); + treatment2.setStop(445); + + Treatment treatment3 = new Treatment(); + treatment3.setTreatment("Left arm"); + treatment3.setStudyId("study_tcga_pub"); + treatment3.setPatientId("TCGA-A1-A0SD"); + treatment3.setStart(313); + treatment3.setStop(543); + + Treatment treatment4 = new Treatment(); + treatment4.setTreatment("Ankle"); + treatment4.setStudyId("study_tcga_pub"); + treatment4.setPatientId("TCGA-A1-A0SD"); + treatment4.setStart(313); + treatment4.setStop(543); + + Map> expected = new HashMap<>(); + expected.put("TCGA-A1-A0SD", Arrays.asList(treatment1, treatment2, treatment3, treatment4)); + + Map> actual = + treatmentRepository.getTreatmentsByPatientId( + Collections.singletonList("TCGA-A1-A0SD-01"), + Collections.singletonList("study_tcga_pub"), + ClinicalEventKeyCode.AgentTarget); + + Assert.assertEquals(actual, expected); + } + + @Test + public void getSamplesByPatientIdWhenNoMatchingSamples() { + ClinicalEventSample clinicalEventSample = new ClinicalEventSample(); + clinicalEventSample.setPatientId("TCGA-A1-A0SD"); + clinicalEventSample.setSampleId("TCGA-A1-A0SD-01"); + clinicalEventSample.setStudyId("study_tcga_pub"); + clinicalEventSample.setTimeTaken(211); + + HashMap> expected = new HashMap<>(); + + Map> actual = + treatmentRepository.getSamplesByPatientId( + Collections.singletonList("TCGA-A1-A0SD-01"), + Collections.singletonList("study_tcga_pub")); + + Assert.assertEquals(actual, expected); + } + + @Test + public void getSamplesByPatientId() { + ClinicalEventSample clinicalEventSample = new ClinicalEventSample(); + clinicalEventSample.setPatientId("TCGA-A1-A0SB"); + clinicalEventSample.setSampleId("TCGA-A1-A0SB-01"); + clinicalEventSample.setStudyId("study_tcga_pub"); + clinicalEventSample.setTimeTaken(211); + + HashMap> expected = new HashMap<>(); + expected.put("TCGA-A1-A0SB", Collections.singletonList(clinicalEventSample)); + + Map> actual = + treatmentRepository.getSamplesByPatientId( + Collections.singletonList("TCGA-A1-A0SB-01"), + Collections.singletonList("study_tcga_pub")); + + Assert.assertEquals(actual, expected); + } + + @Test + public void getShallowSamplesByPatientId() { + ClinicalEventSample clinicalEventSample = new ClinicalEventSample(); + clinicalEventSample.setPatientId("TCGA-A1-A0SD"); + clinicalEventSample.setSampleId("TCGA-A1-A0SD-01"); + clinicalEventSample.setStudyId("study_tcga_pub"); + clinicalEventSample.setTimeTaken(213); + + HashMap> expected = new HashMap<>(); + expected.put("TCGA-A1-A0SD", Collections.singletonList(clinicalEventSample)); + + Map> actual = + treatmentRepository.getShallowSamplesByPatientId( + Collections.singletonList("TCGA-A1-A0SD-01"), + Collections.singletonList("study_tcga_pub")); + + Assert.assertEquals(actual, expected); + } + + @Test + public void hasTreatmentData() { + + Assert.assertEquals( + true, + treatmentRepository.hasTreatmentData( + Collections.singletonList("study_tcga_pub"), ClinicalEventKeyCode.Agent)); + + Assert.assertEquals( + false, + treatmentRepository.hasTreatmentData( + Collections.singletonList("acc_tcga"), ClinicalEventKeyCode.Agent)); + } + + @Test + public void hasSampleTimelineData() { + + Assert.assertEquals( + true, + treatmentRepository.hasSampleTimelineData(Collections.singletonList("study_tcga_pub"))); + + Assert.assertEquals( + false, treatmentRepository.hasSampleTimelineData(Collections.singletonList("acc_tcga"))); + } +} diff --git a/src/test/java/org/cbioportal/legacy/persistence/mybatis/VariantCountMyBatisRepositoryTest.java b/src/test/java/org/cbioportal/legacy/persistence/mybatis/VariantCountMyBatisRepositoryTest.java new file mode 100644 index 00000000000..cdf2c79ea54 --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/persistence/mybatis/VariantCountMyBatisRepositoryTest.java @@ -0,0 +1,52 @@ +package org.cbioportal.legacy.persistence.mybatis; + +import java.util.Arrays; +import java.util.List; +import java.util.Optional; +import org.cbioportal.legacy.model.VariantCount; +import org.cbioportal.legacy.persistence.mybatis.config.TestConfig; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +@RunWith(SpringJUnit4ClassRunner.class) +@SpringBootTest(classes = {VariantCountMyBatisRepository.class, TestConfig.class}) +public class VariantCountMyBatisRepositoryTest { + + @Autowired private VariantCountMyBatisRepository variantCountMyBatisRepository; + + @Test + public void fetchVariantCounts() throws Exception { + + List result = + variantCountMyBatisRepository.fetchVariantCounts( + "study_tcga_pub_mutations", + Arrays.asList(207, 207, 369), + Arrays.asList("AKT1 truncating", null, "ARAF G1513 missense")); + + Assert.assertEquals(3, result.size()); + + Optional variantCountOptional = + result.stream().filter(r -> r.getKeyword() == null).findAny(); + Assert.assertTrue(variantCountOptional.isPresent()); + VariantCount variantCount1 = variantCountOptional.get(); + + Assert.assertEquals("study_tcga_pub_mutations", variantCount1.getMolecularProfileId()); + Assert.assertEquals((Integer) 207, variantCount1.getEntrezGeneId()); + Assert.assertEquals((Integer) 21, variantCount1.getNumberOfSamplesWithKeyword()); + Assert.assertEquals((Integer) 22, variantCount1.getNumberOfSamplesWithMutationInGene()); + + variantCountOptional = + result.stream().filter(r -> r.getKeyword().equals("AKT1 truncating")).findAny(); + Assert.assertTrue(variantCountOptional.isPresent()); + VariantCount variantCount2 = variantCountOptional.get(); + + Assert.assertEquals("study_tcga_pub_mutations", variantCount2.getMolecularProfileId()); + Assert.assertEquals((Integer) 207, variantCount2.getEntrezGeneId()); + Assert.assertEquals((Integer) 54, variantCount2.getNumberOfSamplesWithKeyword()); + Assert.assertEquals((Integer) 64, variantCount2.getNumberOfSamplesWithMutationInGene()); + } +} diff --git a/src/test/java/org/cbioportal/legacy/persistence/mybatis/config/TestConfig.java b/src/test/java/org/cbioportal/legacy/persistence/mybatis/config/TestConfig.java new file mode 100644 index 00000000000..9ef9923e5f1 --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/persistence/mybatis/config/TestConfig.java @@ -0,0 +1,58 @@ +package org.cbioportal.legacy.persistence.mybatis.config; + +import java.util.Properties; +import javax.sql.DataSource; +import org.apache.ibatis.mapping.DatabaseIdProvider; +import org.apache.ibatis.mapping.VendorDatabaseIdProvider; +import org.apache.ibatis.session.SqlSessionFactory; +import org.cbioportal.legacy.persistence.mybatis.typehandler.SampleTypeTypeHandler; +import org.mybatis.spring.SqlSessionFactoryBean; +import org.mybatis.spring.annotation.MapperScan; +import org.springframework.boot.test.context.TestConfiguration; +import org.springframework.context.annotation.Bean; +import org.springframework.jdbc.datasource.DataSourceTransactionManager; +import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; +import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType; +import org.springframework.transaction.PlatformTransactionManager; + +@TestConfiguration +@MapperScan("org.cbioportal.legacy.persistence.mybatis") +public class TestConfig { + + @Bean + public DataSource dataSource() { + return new EmbeddedDatabaseBuilder() + .setType(EmbeddedDatabaseType.H2) + .setName("testdb;DATABASE_TO_UPPER=false;MODE=MYSQL;NON_KEYWORDS=END,KEY,VALUE") + .addScript("cgds-h2.sql") + .addScript("testSql.sql") + .build(); + } + + @Bean + public SqlSessionFactory sqlSessionFactory() throws Exception { + SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean(); + factoryBean.setDataSource(dataSource()); + // mapper that mediate string to enum conversions + factoryBean.setTypeHandlers(new SampleTypeTypeHandler()); + // Create a MyBatis Configuration object + org.apache.ibatis.session.Configuration configuration = + new org.apache.ibatis.session.Configuration(); + + // Set your custom DatabaseIdProvider + DatabaseIdProvider databaseIdProvider = new VendorDatabaseIdProvider(); + Properties properties = new Properties(); + // Set your database-to-databaseId mapping in the properties + properties.setProperty("MySQL", "mysql"); + properties.setProperty("H2", "h2"); + // Add more mappings as needed + databaseIdProvider.setProperties(properties); + factoryBean.setDatabaseIdProvider(databaseIdProvider); + return factoryBean.getObject(); + } + + @Bean + public PlatformTransactionManager platformTransactionManager() { + return new DataSourceTransactionManager(dataSource()); + } +} diff --git a/src/test/java/org/cbioportal/legacy/persistence/mybatis/util/MolecularProfileCaseIdentifierUtilTest.java b/src/test/java/org/cbioportal/legacy/persistence/mybatis/util/MolecularProfileCaseIdentifierUtilTest.java new file mode 100644 index 00000000000..4398af0cf9d --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/persistence/mybatis/util/MolecularProfileCaseIdentifierUtilTest.java @@ -0,0 +1,53 @@ +package org.cbioportal.legacy.persistence.mybatis.util; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Map; +import java.util.Set; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.junit.MockitoJUnitRunner; + +@RunWith(MockitoJUnitRunner.class) +public class MolecularProfileCaseIdentifierUtilTest { + @InjectMocks private MolecularProfileCaseIdentifierUtil molecularProfileCaseIdentifierUtil; + + @Test + public void getGroupedCasesByMolecularProfileId() { + + final String MOLECULAR_PROFILE_ID_1 = "molecular_profile_id_1"; + final String MOLECULAR_PROFILE_ID_2 = "molecular_profile_id_2"; + final String SAMPLE_ID_1 = "sample_id_1"; + final String SAMPLE_ID_2 = "sample_id_2"; + final String SAMPLE_ID_3 = "sample_id_3"; + + Map> result = + molecularProfileCaseIdentifierUtil.getGroupedCasesByMolecularProfileId( + new ArrayList<>(), new ArrayList<>()); + Assert.assertEquals("empty request", 0, result.size()); + + result = + molecularProfileCaseIdentifierUtil.getGroupedCasesByMolecularProfileId( + Arrays.asList(MOLECULAR_PROFILE_ID_1), new ArrayList<>()); + Assert.assertEquals("empty sample ids", 1, result.size()); + Assert.assertEquals(0, result.get(MOLECULAR_PROFILE_ID_1).size()); + + result = + molecularProfileCaseIdentifierUtil.getGroupedCasesByMolecularProfileId( + Arrays.asList(MOLECULAR_PROFILE_ID_1, MOLECULAR_PROFILE_ID_1, MOLECULAR_PROFILE_ID_1), + Arrays.asList(SAMPLE_ID_1, SAMPLE_ID_2, SAMPLE_ID_3)); + + Assert.assertEquals("valid - single profile", 1, result.size()); + + result = + molecularProfileCaseIdentifierUtil.getGroupedCasesByMolecularProfileId( + Arrays.asList(MOLECULAR_PROFILE_ID_1, MOLECULAR_PROFILE_ID_1, MOLECULAR_PROFILE_ID_2), + Arrays.asList(SAMPLE_ID_1, SAMPLE_ID_2, SAMPLE_ID_3)); + + Assert.assertEquals("valid - multiple profiles", 2, result.size()); + Assert.assertEquals(2, result.get(MOLECULAR_PROFILE_ID_1).size()); + Assert.assertEquals(1, result.get(MOLECULAR_PROFILE_ID_2).size()); + } +} diff --git a/src/test/java/org/cbioportal/legacy/persistence/mybatis/util/PaginationCalculatorTest.java b/src/test/java/org/cbioportal/legacy/persistence/mybatis/util/PaginationCalculatorTest.java new file mode 100644 index 00000000000..f78051f34cb --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/persistence/mybatis/util/PaginationCalculatorTest.java @@ -0,0 +1,45 @@ +package org.cbioportal.legacy.persistence.mybatis.util; + +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = PaginationCalculator.class) +public class PaginationCalculatorTest { + + @Test + public void testOffsetNull() { + Assert.assertNull(PaginationCalculator.offset(null, 1)); + Assert.assertNull(PaginationCalculator.offset(1, null)); + Assert.assertNull(PaginationCalculator.offset(null, null)); + } + + @Test + public void testOffset() { + Assert.assertEquals(0, (int) PaginationCalculator.offset(10, 0)); + Assert.assertEquals(10, (int) PaginationCalculator.offset(10, 1)); + Assert.assertEquals(100, (int) PaginationCalculator.offset(10, 10)); + } + + @Test + public void testLastIndexNull() { + Assert.assertNull(PaginationCalculator.lastIndex(null, 1, 1)); + Assert.assertNull(PaginationCalculator.lastIndex(1, null, 1)); + Assert.assertNull(PaginationCalculator.lastIndex(null, null, 1)); + Assert.assertNull(PaginationCalculator.lastIndex(null, 1, 1)); + Assert.assertNull(PaginationCalculator.lastIndex(1, 1, null)); + Assert.assertNull(PaginationCalculator.lastIndex(null, 1, null)); + Assert.assertNull(PaginationCalculator.lastIndex(1, null, null)); + Assert.assertNull(PaginationCalculator.lastIndex(null, null, null)); + } + + @Test + public void testLastIndex() { + Assert.assertEquals(3, (int) PaginationCalculator.lastIndex(0, 3, 26)); + Assert.assertEquals(6, (int) PaginationCalculator.lastIndex(3, 3, 26)); + Assert.assertEquals(26, (int) PaginationCalculator.lastIndex(25, 3, 26)); + } +} diff --git a/src/test/java/org/cbioportal/legacy/persistence/util/CustomKeyGeneratorTest.java b/src/test/java/org/cbioportal/legacy/persistence/util/CustomKeyGeneratorTest.java new file mode 100644 index 00000000000..fce64a3b644 --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/persistence/util/CustomKeyGeneratorTest.java @@ -0,0 +1,101 @@ +package org.cbioportal.legacy.persistence.util; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.lang.reflect.Method; +import java.util.Arrays; +import org.cbioportal.legacy.model.CancerStudy; +import org.cbioportal.legacy.persistence.CacheEnabledConfig; +import org.cbioportal.legacy.persistence.StudyRepository; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnitRunner; + +@RunWith(MockitoJUnitRunner.class) +public class CustomKeyGeneratorTest { + + @InjectMocks private CustomKeyGenerator customKeyGenerator; + + @Mock private StudyRepository studyRepository; + + @Mock private CacheEnabledConfig cacheEnabledConfig; + + private String studyId1 = "test_study_1"; + private String studyId2 = "test_study_2"; + + @Before + public void setUp() throws Exception { + when(cacheEnabledConfig.isEnabled()).thenReturn(true); + CancerStudy cancerStudy1 = mock(CancerStudy.class); + when(cancerStudy1.getCancerStudyIdentifier()).thenReturn(studyId1); + CancerStudy cancerStudy2 = mock(CancerStudy.class); + when(cancerStudy2.getCancerStudyIdentifier()).thenReturn(studyId2); + when(studyRepository.getAllStudies(any(), any(), any(), any(), any(), any())) + .thenReturn(Arrays.asList(cancerStudy1, cancerStudy2)); + } + + @Test + public void testGenerateCacheDisabled() { + when(cacheEnabledConfig.isEnabled()).thenReturn(false); + Assert.assertEquals("", customKeyGenerator.generate(null, null)); + } + + @Test + public void testGenerateCacheSuccessNoParams() throws Exception { + Method functionToPass = this.getClass().getMethod("testGenerateCacheSuccessNoParams"); + Object hello = customKeyGenerator.generate(this, functionToPass); + Assert.assertTrue(hello instanceof String); + Assert.assertEquals( + "CustomKeyGeneratorTest" + + CustomKeyGenerator.CACHE_KEY_PARAM_DELIMITER + + "testGenerateCacheSuccessNoParams" + + CustomKeyGenerator.CACHE_KEY_PARAM_DELIMITER, + (String) hello); + } + + @Test + public void testGenerateCacheSuccessWithParams() throws Exception { + Method functionToPass = this.getClass().getMethod("testGenerateCacheSuccessNoParams"); + Object hello = customKeyGenerator.generate(this, functionToPass, "one", "two"); + Assert.assertTrue(hello instanceof String); + StringBuilder expected = new StringBuilder(); + expected.append("CustomKeyGeneratorTest"); + expected.append(CustomKeyGenerator.CACHE_KEY_PARAM_DELIMITER); + expected.append("testGenerateCacheSuccessNoParams"); + expected.append(CustomKeyGenerator.CACHE_KEY_PARAM_DELIMITER); + expected.append("\"one\""); + expected.append(CustomKeyGenerator.CACHE_KEY_PARAM_DELIMITER); + expected.append("\"two\""); + Assert.assertEquals(expected.toString(), (String) hello); + } + + // Make sure that the study ids are extracted into the key name + // when hashing is active due to long params. This is to ensure + // that cache eviction for specific studies can occur. + @Test + public void testGenerateCacheSuccessWithLongParam() throws Exception { + Method functionToPass = this.getClass().getMethod("testGenerateCacheSuccessNoParams"); + + StringBuilder requestParams = new StringBuilder(); + requestParams.append("-----"); + requestParams.append(studyId1); + requestParams.append("-----"); + requestParams.append(studyId2); + requestParams.append("-----"); + for (int i = CustomKeyGenerator.PARAM_LENGTH_HASH_LIMIT + 100; i > 0; i--) { + requestParams.append("-"); + } + Object hello = + customKeyGenerator.generate(this, functionToPass, "one", requestParams.toString()); + + Assert.assertTrue(hello instanceof String); + Assert.assertTrue( + ((String) hello).contains("test_study_1_test_study_2_22cc100378d5dc33c03fb0f39a61c692")); + } +} diff --git a/src/test/java/org/cbioportal/legacy/persistence/util/CustomRedisCacheIntegrationTest.java b/src/test/java/org/cbioportal/legacy/persistence/util/CustomRedisCacheIntegrationTest.java new file mode 100644 index 00000000000..2b7a9569943 --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/persistence/util/CustomRedisCacheIntegrationTest.java @@ -0,0 +1,33 @@ +package org.cbioportal.legacy.persistence.util; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +import org.cbioportal.legacy.persistence.util.fakeclient.MockInMemoryRedissonClient; +import org.junit.Test; + +/** + * This test is... not great, but it's my attempt to create a runnable integration test for the + * CustomRedisCache that doesn't have a ton of dependencies or a long runtime. Believe it or not, + * this test did catch some bugs; so while it isn't a perfect integration test by any means, I think + * it is worth something. + * + *

What I've done is create a hollow implementation of RedissionClient that acts as a _very_ + * primitive in memory cache. This test just runs some basic caching operations, namely set, get, + * and clear. + */ +public class CustomRedisCacheIntegrationTest { + @Test + public void shouldAddThenEvict() { + MockInMemoryRedissonClient fakeClient = new MockInMemoryRedissonClient(); + CustomRedisCache subject = new CustomRedisCache("generalCache", fakeClient, 100); + + subject.put("key", "value"); + Object actualValue = subject.lookup("key"); + assertEquals("value", actualValue); + + subject.clear(); + actualValue = subject.lookup("key"); + assertNull(actualValue); + } +} diff --git a/src/test/java/org/cbioportal/legacy/persistence/util/CustomRedisCacheManagerTest.java b/src/test/java/org/cbioportal/legacy/persistence/util/CustomRedisCacheManagerTest.java new file mode 100644 index 00000000000..51380543145 --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/persistence/util/CustomRedisCacheManagerTest.java @@ -0,0 +1,50 @@ +package org.cbioportal.legacy.persistence.util; + +import static org.junit.Assert.*; + +import java.util.*; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnitRunner; +import org.redisson.api.RedissonClient; +import org.springframework.cache.Cache; + +@RunWith(MockitoJUnitRunner.class) +public class CustomRedisCacheManagerTest { + @Mock RedissonClient client; + + @Test + public void shouldGetStaticCache() { + CustomRedisCacheManager subject = new CustomRedisCacheManager(client, 100); + + Cache actualFirstCall = subject.getCache("aStaticFunkyCache"); + Cache actualSecondCall = subject.getCache("aStaticFunkyCache"); + + assertEquals("aStaticFunkyCache", actualFirstCall.getName()); + assertEquals(client, actualFirstCall.getNativeCache()); + // the first and second call should return the same cache object + assertSame(actualFirstCall, actualSecondCall); + } + + @Test + public void shouldReturnNamesOfCachesWhenNonePresent() { + CustomRedisCacheManager subject = new CustomRedisCacheManager(client, 100); + Collection actual = subject.getCacheNames(); + assertEquals(new HashSet<>(), new HashSet<>(actual)); + } + + @Test + public void shouldReturnNamesOfCachesWhenSomePresent() { + CustomRedisCacheManager subject = new CustomRedisCacheManager(client, 100); + subject.getCache("cache and release", false); + subject.getCache("Cache-22", true); + subject.getCache("cache money", false); + + Set actual = new HashSet<>(subject.getCacheNames()); + HashSet expected = + new HashSet<>(Arrays.asList("cache and release", "Cache-22", "cache money")); + + assertEquals(expected, actual); + } +} diff --git a/src/test/java/org/cbioportal/legacy/persistence/util/CustomRedisCacheTest.java b/src/test/java/org/cbioportal/legacy/persistence/util/CustomRedisCacheTest.java new file mode 100644 index 00000000000..47178a3ed12 --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/persistence/util/CustomRedisCacheTest.java @@ -0,0 +1,306 @@ +package org.cbioportal.legacy.persistence.util; + +import static org.junit.Assert.*; +import static org.mockito.Mockito.*; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.concurrent.TimeUnit; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.junit.MockitoJUnitRunner; +import org.redisson.api.RBucket; +import org.redisson.api.RKeys; +import org.redisson.api.RedissonClient; +import org.springframework.cache.Cache; + +@RunWith(MockitoJUnitRunner.class) +public class CustomRedisCacheTest { + + @Mock RedissonClient client; + + private RKeys mockKeys; + + @Before + public void setUp() throws Exception { + + List keys = + Arrays.asList("subject_1_key_1", "subject_1_key_2", "subject_2_key_1", "subject_2_key_2"); + mockKeys = mock(RKeys.class); + when(client.getKeys()).thenReturn(mockKeys); + when(mockKeys.getKeysStream()).thenReturn(keys.stream()); + } + + @Test + public void shouldHaveGetters() { + CustomRedisCache subject = new CustomRedisCache("subject", client, -1); + + assertEquals("subject", subject.getName()); + assertEquals(client, subject.getNativeCache()); + } + + @Test + public void shouldLookupObjectThatDoesNotExist() { + RBucket bucket = Mockito.mock(RBucket.class); + when(bucket.get()).thenReturn(null); + when(client.getBucket("subject:57_onions")).thenReturn(bucket); + + CustomRedisCache subject = new CustomRedisCache("subject", client, -1); + Object actual = subject.lookup("57_onions"); + + assertNull(actual); + } + + @Test + public void shouldLookupObjectThatDoesExistForStaticCache() { + RBucket bucket = Mockito.mock(RBucket.class); + when(bucket.get()).thenReturn(toStoreValue("success")); + when(client.getBucket("subject:57_onions")).thenReturn(bucket); + + CustomRedisCache subject = new CustomRedisCache("subject", client, -1); + Object actual = subject.lookup("57_onions"); + + assertEquals("success", actual); + // cache is static, so don't refresh + verify(bucket, times(0)).expireAsync(-1, TimeUnit.MINUTES); + } + + @Test + public void shouldLookupObjectThatDoesExistForGeneralCache() { + RBucket bucket = Mockito.mock(RBucket.class); + when(bucket.get()).thenReturn(toStoreValue("success")); + when(client.getBucket("subject:57_onions")).thenReturn(bucket); + + CustomRedisCache subject = new CustomRedisCache("subject", client, 100); + Object actual = subject.lookup("57_onions"); + + assertEquals("success", actual); + // cache is not static, so refresh + verify(bucket, times(1)).expireAsync(100, TimeUnit.MINUTES); + } + + @Test + public void shouldGetObjectThatDoesNotExist() { + String defaultReturn = "this gets returned if the object DNE in cache"; + RBucket bucket = Mockito.mock(RBucket.class); + when(bucket.get()).thenReturn(null); + when(client.getBucket("subject:57_onions")).thenReturn(bucket); + + CustomRedisCache subject = new CustomRedisCache("subject", client, -1); + Object actual = subject.get("57_onions", () -> defaultReturn); + + assertEquals(defaultReturn, actual); + } + + @Test + public void shouldGetObjectThatDoesExistForStaticCache() { + String defaultReturn = "this gets returned if the object DNE in cache"; + RBucket bucket = Mockito.mock(RBucket.class); + when(bucket.get()).thenReturn(toStoreValue("success")); + when(client.getBucket("subject:57_onions")).thenReturn(bucket); + + CustomRedisCache subject = new CustomRedisCache("subject", client, -1); + Object actual = subject.get("57_onions", () -> defaultReturn); + + assertEquals("success", actual); + // cache is static, so don't refresh + verify(bucket, times(0)).expireAsync(-1, TimeUnit.MINUTES); + } + + @Test + public void shouldGetObjectThatDoesExistForGeneralCache() { + String defaultReturn = "this gets returned if the object DNE in cache"; + RBucket bucket = Mockito.mock(RBucket.class); + when(bucket.get()).thenReturn(toStoreValue("success")); + when(client.getBucket("subject:57_onions")).thenReturn(bucket); + + CustomRedisCache subject = new CustomRedisCache("subject", client, 100); + Object actual = subject.get("57_onions", () -> defaultReturn); + + assertEquals("success", actual); + // cache is not static, so refresh + verify(bucket, times(1)).expireAsync(100, TimeUnit.MINUTES); + } + + @Test(expected = Cache.ValueRetrievalException.class) + public void shouldPropagateValueLoaderException() { + String defaultReturn = "this gets returned if the object DNE in cache"; + RBucket bucket = Mockito.mock(RBucket.class); + when(bucket.get()).thenReturn(null); + when(client.getBucket("subject:57_onions")).thenReturn(bucket); + + CustomRedisCache subject = new CustomRedisCache("subject", client, -1); + subject.get( + "57_onions", + () -> { + throw new RuntimeException("uh oh"); + }); + } + + @Test + public void shouldPutObjectInStaticCache() { + RBucket bucket = Mockito.mock(RBucket.class); + when(client.getBucket("subject:57_onions")).thenReturn(bucket); + + CustomRedisCache subject = new CustomRedisCache("subject", client, -1); + subject.put("57_onions", "success"); + + // this is tricky to verify, because the value is compressed before + // it gets added to the cache + verify(bucket, times(1)).setAsync(any()); + verify(bucket, times(0)).setAsync(any(), anyLong(), any(TimeUnit.class)); + } + + @Test + public void shouldPutObjectInGeneralCache() { + RBucket bucket = Mockito.mock(RBucket.class); + when(client.getBucket("subject:57_onions")).thenReturn(bucket); + + CustomRedisCache subject = new CustomRedisCache("subject", client, 100); + subject.put("57_onions", "success"); + + // this is tricky to verify, because the value is compressed before + // it gets added to the cache + verify(bucket, times(0)).setAsync(any()); + verify(bucket, times(1)).setAsync(any(), anyLong(), any(TimeUnit.class)); + } + + @Test + public void shouldPutAbsentObject() { + RBucket bucket = Mockito.mock(RBucket.class); + when(bucket.get()).thenReturn(null); + when(client.getBucket("subject:57_onions")).thenReturn(bucket); + + CustomRedisCache subject = new CustomRedisCache("subject", client, 100); + Cache.ValueWrapper actual = subject.putIfAbsent("57_onions", "success"); + + // the value is absent, so there should be a put + verify(bucket, times(1)).setAsync(any(), anyLong(), any(TimeUnit.class)); + assertEquals("success", actual.get()); + } + + @Test + public void shouldNotPutPresentObject() { + RBucket bucket = Mockito.mock(RBucket.class); + when(bucket.get()).thenReturn(toStoreValue("success")); + when(client.getBucket("subject:57_onions")).thenReturn(bucket); + + CustomRedisCache subject = new CustomRedisCache("subject", client, 100); + Cache.ValueWrapper actual = subject.putIfAbsent("57_onions", "success"); + + // the value is absent, so there should be a put + verify(bucket, times(0)).setAsync(any(), anyLong(), any(TimeUnit.class)); + assertEquals("success", actual.get()); + } + + @Test + public void evictIfPresentNoStringPattern() { + CustomRedisCache subject = new CustomRedisCache("subject", client, 100); + subject.evictIfPresent(new HashMap()); + subject.evictIfPresent(new HashMap()); + verify(mockKeys, never()).delete(anyString()); + } + + @Test + public void evictIfPresentNullPattern() { + CustomRedisCache subject = new CustomRedisCache("subject", client, 100); + subject.evictIfPresent(null); + verify(mockKeys, never()).delete(anyString()); + } + + @Test + public void evictIfPresentSuccess() { + CustomRedisCache subject = new CustomRedisCache("subject_1", client, 100); + subject.evictIfPresent(".*key_2.*"); + verify(mockKeys, times(1)).delete(eq("subject_1_key_2")); + } + + @Test + public void evictNoStringPattern() { + CustomRedisCache subject = new CustomRedisCache("subject", client, 100); + subject.evict(new HashMap()); + verify(mockKeys, never()).delete(anyString()); + } + + @Test + public void evictNullPattern() { + CustomRedisCache subject = new CustomRedisCache("subject", client, 100); + subject.evict(null); + verify(mockKeys, never()).delete(anyString()); + } + + @Test + public void evictSuccess() { + CustomRedisCache subject = new CustomRedisCache("subject_1", client, 100); + subject.evict(".*key_2.*"); + verify(mockKeys, times(1)).delete(eq("subject_1_key_2")); + } + + @Test + public void shouldClear() { + RKeys allKeys = mock(RKeys.class); + when(client.getKeys()).thenReturn(allKeys); + CustomRedisCache subject = new CustomRedisCache("subject", client, 100); + subject.clear(); + + // evict is a no op, so there should be no calls to the client + verify(client, times(1)).getKeys(); + verify(allKeys, times(1)).deleteByPattern("subject:*"); + } + + @Test + public void shouldInvalidateEmptyCache() { + RKeys allKeys = mock(RKeys.class); + when(allKeys.deleteByPattern("subject:*")).thenReturn(0L); + when(client.getKeys()).thenReturn(allKeys); + CustomRedisCache subject = new CustomRedisCache("subject", client, 100); + boolean actual = subject.invalidate(); + + // evict is a no op, so there should be no calls to the client + verify(client, times(1)).getKeys(); + verify(allKeys, times(1)).deleteByPattern("subject:*"); + assertFalse(actual); + } + + @Test + public void shouldRoundTripObject() { + String toRoundTrip = "The quick brown fox jumped over the lazy dog"; + CustomRedisCache subject = new CustomRedisCache("subject", client, -1); + + Object compressed = subject.toStoreValue(toRoundTrip); + String roundTripped = (String) subject.fromStoreValue(compressed); + + assertEquals(toRoundTrip, roundTripped); + } + + @Test + public void shouldRoundTripPrimitive() { + int toRoundTrip = Integer.MAX_VALUE; + CustomRedisCache subject = new CustomRedisCache("subject", client, -1); + + Object compressed = subject.toStoreValue(toRoundTrip); + int roundTripped = (int) subject.fromStoreValue(compressed); + + assertEquals(toRoundTrip, roundTripped); + } + + @Test + public void shouldRoundTripNull() { + Object toRoundTrip = null; + CustomRedisCache subject = new CustomRedisCache("subject", client, -1); + + Object compressed = subject.toStoreValue(toRoundTrip); + Object roundTripped = subject.fromStoreValue(compressed); + + assertEquals(toRoundTrip, roundTripped); + } + + private Object toStoreValue(Object rawValue) { + CustomRedisCache converter = new CustomRedisCache("", client, -1); + return converter.toStoreValue(rawValue); + } +} diff --git a/src/test/java/org/cbioportal/legacy/persistence/util/EhCacheUtilsTest.java b/src/test/java/org/cbioportal/legacy/persistence/util/EhCacheUtilsTest.java new file mode 100644 index 00000000000..8492543ff68 --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/persistence/util/EhCacheUtilsTest.java @@ -0,0 +1,65 @@ +package org.cbioportal.legacy.persistence.util; + +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.*; + +import java.util.ArrayList; +import java.util.List; +import javax.cache.Cache; +import javax.cache.CacheManager; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnitRunner; + +@RunWith(MockitoJUnitRunner.class) +public class EhCacheUtilsTest { + + @InjectMocks private EhCacheUtils ehCacheUtils; + + @Mock private Cache cache; + + @Mock private CacheManager cacheManager; + + private String cacheName = "test_cache"; + + @Before + public void setUp() throws Exception { + + List> keysInCache = new ArrayList<>(); + keysInCache.add(createEntry("a_study1_a")); + keysInCache.add(createEntry("a__a")); + + when(cache.iterator()).thenReturn(keysInCache.iterator()); + when(cacheManager.getCache(eq(cacheName))).thenReturn(cache); + } + + private Cache.Entry createEntry(String key) { + Cache.Entry mock = mock(Cache.Entry.class); + when(mock.getKey()).thenReturn(key); + return mock; + } + + @Test + public void evictByPatternAll() { + ehCacheUtils.evictByPattern(cacheName, ".*"); + verify(cache, times(1)).remove(eq("a_study1_a")); + verify(cache, times(1)).remove(eq("a__a")); + } + + @Test + public void evictByPatternOnlyStudy() { + ehCacheUtils.evictByPattern(cacheName, "^(?=.*study1).*"); + verify(cache, times(1)).remove(eq("a_study1_a")); + verify(cache, never()).remove(eq("a__a")); + } + + @Test + public void evictByPatternNotStudy() { + ehCacheUtils.evictByPattern(cacheName, "^(?!.*study1).*"); + verify(cache, never()).remove(eq("a_study1_a")); + verify(cache, times(1)).remove(eq("a__a")); + } +} diff --git a/src/test/java/org/cbioportal/legacy/persistence/util/RedisCacheUtilsTest.java b/src/test/java/org/cbioportal/legacy/persistence/util/RedisCacheUtilsTest.java new file mode 100644 index 00000000000..cbe30b81b0d --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/persistence/util/RedisCacheUtilsTest.java @@ -0,0 +1,63 @@ +package org.cbioportal.legacy.persistence.util; + +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.*; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnitRunner; +import org.redisson.api.RKeys; +import org.redisson.api.RedissonClient; +import org.springframework.cache.Cache; +import org.springframework.cache.CacheManager; + +@RunWith(MockitoJUnitRunner.class) +public class RedisCacheUtilsTest { + + @InjectMocks private RedisCacheUtils redisCacheUtils; + + @Mock private Cache cache; + @Mock private RedissonClient redissonClient; + @Mock private RKeys keys; + + @Mock private CacheManager cacheManager; + + private String cacheName = "1_test_cache"; + + @Before + public void setUp() throws Exception { + + List keysInCache = new ArrayList<>(); + keysInCache.add("1_test_cache:a_study1_a"); + keysInCache.add("1_test_cache:a__a"); + keysInCache.add("2_test_cache:a_study2_a"); + keysInCache.add("2_test_cache:a__a"); + + when(cache.getName()).thenReturn(cacheName); + when(cache.getNativeCache()).thenReturn(redissonClient); + when(redissonClient.getKeys()).thenReturn(keys); + when(keys.getKeysStream()).thenReturn(keysInCache.stream()); + when(cacheManager.getCache(eq(cacheName))).thenReturn(cache); + } + + @Test + public void evictByPatternAll() { + redisCacheUtils.evictByPattern(cacheName, ".*"); + verify(cache, times(1)).evict(eq(".*")); + } + + @Test + public void getKeysSelectsForCacheName() { + List keys = redisCacheUtils.getKeys(cacheName); + // make sure the cache removes keys with a different prefix ("2_test_cache" in this case) + List expectedKeys = Arrays.asList("1_test_cache:a_study1_a", "1_test_cache:a__a"); + Assert.assertArrayEquals(expectedKeys.toArray(), keys.toArray()); + } +} diff --git a/src/test/java/org/cbioportal/legacy/persistence/util/fakeclient/MockInMemoryRedissonClient.java b/src/test/java/org/cbioportal/legacy/persistence/util/fakeclient/MockInMemoryRedissonClient.java new file mode 100644 index 00000000000..bd15eb8a26c --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/persistence/util/fakeclient/MockInMemoryRedissonClient.java @@ -0,0 +1,655 @@ +package org.cbioportal.legacy.persistence.util.fakeclient; + +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.TimeUnit; +import org.redisson.api.*; +import org.redisson.api.redisnode.BaseRedisNodes; +import org.redisson.api.redisnode.RedisNodes; +import org.redisson.client.codec.Codec; +import org.redisson.codec.JsonCodec; +import org.redisson.config.Config; + +public class MockInMemoryRedissonClient implements RedissonClient { + private final ConcurrentHashMap rBucketMap; + private final ConcurrentHashMap valueMap; + + public MockInMemoryRedissonClient() { + rBucketMap = new ConcurrentHashMap<>(); + valueMap = new ConcurrentHashMap<>(); + } + + @Override + public RBucket getBucket(String s) { + return rBucketMap.computeIfAbsent(s, (key) -> new MockRBucket(valueMap, key)); + } + + /* + * Methods we don't use + */ + @Override + public RKeys getKeys() { + return new MockRKeys(rBucketMap, valueMap); + } + + @Override + public RTimeSeries getTimeSeries(String s) { + throw new UnsupportedOperationException(); + } + + @Override + public RTimeSeries getTimeSeries(String s, Codec codec) { + throw new UnsupportedOperationException(); + } + + @Override + public RStream getStream(String s) { + throw new UnsupportedOperationException(); + } + + @Override + public RStream getStream(String s, Codec codec) { + throw new UnsupportedOperationException(); + } + + @Override + public RSearch getSearch() { + throw new UnsupportedOperationException(); + } + + @Override + public RSearch getSearch(Codec codec) { + throw new UnsupportedOperationException(); + } + + @Override + public RRateLimiter getRateLimiter(String s) { + throw new UnsupportedOperationException(); + } + + @Override + public RBinaryStream getBinaryStream(String s) { + throw new UnsupportedOperationException(); + } + + @Override + public RGeo getGeo(String s) { + throw new UnsupportedOperationException(); + } + + @Override + public RGeo getGeo(String s, Codec codec) { + throw new UnsupportedOperationException(); + } + + @Override + public RSetCache getSetCache(String s) { + throw new UnsupportedOperationException(); + } + + @Override + public RSetCache getSetCache(String s, Codec codec) { + throw new UnsupportedOperationException(); + } + + @Override + public RMapCache getMapCache(String s, Codec codec) { + throw new UnsupportedOperationException(); + } + + @Override + public RMapCache getMapCache(String s, Codec codec, MapOptions mapOptions) { + throw new UnsupportedOperationException(); + } + + @Override + public RMapCache getMapCache(String s) { + throw new UnsupportedOperationException(); + } + + @Override + public RMapCache getMapCache(String s, MapOptions mapOptions) { + throw new UnsupportedOperationException(); + } + + @Override + public RBucket getBucket(String s, Codec codec) { + throw new UnsupportedOperationException(); + } + + @Override + public RBuckets getBuckets() { + throw new UnsupportedOperationException(); + } + + @Override + public RBuckets getBuckets(Codec codec) { + throw new UnsupportedOperationException(); + } + + @Override + public RJsonBucket getJsonBucket(String name, JsonCodec codec) { + throw new UnsupportedOperationException(); + } + + @Override + public RHyperLogLog getHyperLogLog(String s) { + throw new UnsupportedOperationException(); + } + + @Override + public RHyperLogLog getHyperLogLog(String s, Codec codec) { + throw new UnsupportedOperationException(); + } + + @Override + public RList getList(String s) { + throw new UnsupportedOperationException(); + } + + @Override + public RList getList(String s, Codec codec) { + throw new UnsupportedOperationException(); + } + + @Override + public RListMultimap getListMultimap(String s) { + throw new UnsupportedOperationException(); + } + + @Override + public RListMultimap getListMultimap(String s, Codec codec) { + throw new UnsupportedOperationException(); + } + + @Override + public RListMultimapCache getListMultimapCache(String s) { + throw new UnsupportedOperationException(); + } + + @Override + public RListMultimapCache getListMultimapCache(String s, Codec codec) { + throw new UnsupportedOperationException(); + } + + @Override + public RLocalCachedMap getLocalCachedMap( + String s, LocalCachedMapOptions localCachedMapOptions) { + throw new UnsupportedOperationException(); + } + + @Override + public RLocalCachedMap getLocalCachedMap( + String s, Codec codec, LocalCachedMapOptions localCachedMapOptions) { + throw new UnsupportedOperationException(); + } + + @Override + public RMap getMap(String s) { + throw new UnsupportedOperationException(); + } + + @Override + public RMap getMap(String s, MapOptions mapOptions) { + throw new UnsupportedOperationException(); + } + + @Override + public RMap getMap(String s, Codec codec) { + throw new UnsupportedOperationException(); + } + + @Override + public RMap getMap(String s, Codec codec, MapOptions mapOptions) { + throw new UnsupportedOperationException(); + } + + @Override + public RSetMultimap getSetMultimap(String s) { + throw new UnsupportedOperationException(); + } + + @Override + public RSetMultimap getSetMultimap(String s, Codec codec) { + throw new UnsupportedOperationException(); + } + + @Override + public RSetMultimapCache getSetMultimapCache(String s) { + throw new UnsupportedOperationException(); + } + + @Override + public RSetMultimapCache getSetMultimapCache(String s, Codec codec) { + throw new UnsupportedOperationException(); + } + + @Override + public RSemaphore getSemaphore(String s) { + throw new UnsupportedOperationException(); + } + + @Override + public RPermitExpirableSemaphore getPermitExpirableSemaphore(String s) { + throw new UnsupportedOperationException(); + } + + @Override + public RLock getLock(String s) { + throw new UnsupportedOperationException(); + } + + @Override + public RLock getSpinLock(String s) { + throw new UnsupportedOperationException(); + } + + @Override + public RLock getSpinLock(String s, LockOptions.BackOff backOff) { + throw new UnsupportedOperationException(); + } + + @Override + public RFencedLock getFencedLock(String s) { + throw new UnsupportedOperationException(); + } + + @Override + public RLock getMultiLock(RLock... rLocks) { + throw new UnsupportedOperationException(); + } + + /** + * @param rLocks + * @deprecated + */ + @Override + @Deprecated + public RLock getRedLock(RLock... rLocks) { + throw new UnsupportedOperationException(); + } + + @Override + public RLock getFairLock(String s) { + throw new UnsupportedOperationException(); + } + + @Override + public RReadWriteLock getReadWriteLock(String s) { + throw new UnsupportedOperationException(); + } + + @Override + public RSet getSet(String s) { + throw new UnsupportedOperationException(); + } + + @Override + public RSet getSet(String s, Codec codec) { + throw new UnsupportedOperationException(); + } + + @Override + public RSortedSet getSortedSet(String s) { + throw new UnsupportedOperationException(); + } + + @Override + public RSortedSet getSortedSet(String s, Codec codec) { + throw new UnsupportedOperationException(); + } + + @Override + public RScoredSortedSet getScoredSortedSet(String s) { + throw new UnsupportedOperationException(); + } + + @Override + public RScoredSortedSet getScoredSortedSet(String s, Codec codec) { + throw new UnsupportedOperationException(); + } + + @Override + public RLexSortedSet getLexSortedSet(String s) { + throw new UnsupportedOperationException(); + } + + @Override + public RShardedTopic getShardedTopic(String s) { + throw new UnsupportedOperationException(); + } + + @Override + public RShardedTopic getShardedTopic(String s, Codec codec) { + throw new UnsupportedOperationException(); + } + + @Override + public RTopic getTopic(String s) { + throw new UnsupportedOperationException(); + } + + @Override + public RTopic getTopic(String s, Codec codec) { + throw new UnsupportedOperationException(); + } + + @Override + public RReliableTopic getReliableTopic(String s) { + throw new UnsupportedOperationException(); + } + + @Override + public RReliableTopic getReliableTopic(String s, Codec codec) { + throw new UnsupportedOperationException(); + } + + @Override + public RPatternTopic getPatternTopic(String s) { + throw new UnsupportedOperationException(); + } + + @Override + public RPatternTopic getPatternTopic(String s, Codec codec) { + throw new UnsupportedOperationException(); + } + + @Override + public RQueue getQueue(String s) { + throw new UnsupportedOperationException(); + } + + @Override + public RTransferQueue getTransferQueue(String s) { + throw new UnsupportedOperationException(); + } + + @Override + public RTransferQueue getTransferQueue(String s, Codec codec) { + throw new UnsupportedOperationException(); + } + + @Override + public RDelayedQueue getDelayedQueue(RQueue rQueue) { + throw new UnsupportedOperationException(); + } + + @Override + public RQueue getQueue(String s, Codec codec) { + throw new UnsupportedOperationException(); + } + + @Override + public RRingBuffer getRingBuffer(String s) { + throw new UnsupportedOperationException(); + } + + @Override + public RRingBuffer getRingBuffer(String s, Codec codec) { + throw new UnsupportedOperationException(); + } + + @Override + public RPriorityQueue getPriorityQueue(String s) { + throw new UnsupportedOperationException(); + } + + @Override + public RPriorityQueue getPriorityQueue(String s, Codec codec) { + throw new UnsupportedOperationException(); + } + + @Override + public RPriorityBlockingQueue getPriorityBlockingQueue(String s) { + throw new UnsupportedOperationException(); + } + + @Override + public RPriorityBlockingQueue getPriorityBlockingQueue(String s, Codec codec) { + throw new UnsupportedOperationException(); + } + + @Override + public RPriorityBlockingDeque getPriorityBlockingDeque(String s) { + throw new UnsupportedOperationException(); + } + + @Override + public RPriorityBlockingDeque getPriorityBlockingDeque(String s, Codec codec) { + throw new UnsupportedOperationException(); + } + + @Override + public RPriorityDeque getPriorityDeque(String s) { + throw new UnsupportedOperationException(); + } + + @Override + public RPriorityDeque getPriorityDeque(String s, Codec codec) { + throw new UnsupportedOperationException(); + } + + @Override + public RBlockingQueue getBlockingQueue(String s) { + throw new UnsupportedOperationException(); + } + + @Override + public RBlockingQueue getBlockingQueue(String s, Codec codec) { + throw new UnsupportedOperationException(); + } + + @Override + public RBoundedBlockingQueue getBoundedBlockingQueue(String s) { + throw new UnsupportedOperationException(); + } + + @Override + public RBoundedBlockingQueue getBoundedBlockingQueue(String s, Codec codec) { + throw new UnsupportedOperationException(); + } + + @Override + public RDeque getDeque(String s) { + throw new UnsupportedOperationException(); + } + + @Override + public RDeque getDeque(String s, Codec codec) { + throw new UnsupportedOperationException(); + } + + @Override + public RBlockingDeque getBlockingDeque(String s) { + throw new UnsupportedOperationException(); + } + + @Override + public RBlockingDeque getBlockingDeque(String s, Codec codec) { + throw new UnsupportedOperationException(); + } + + @Override + public RAtomicLong getAtomicLong(String s) { + throw new UnsupportedOperationException(); + } + + @Override + public RAtomicDouble getAtomicDouble(String s) { + throw new UnsupportedOperationException(); + } + + @Override + public RLongAdder getLongAdder(String s) { + throw new UnsupportedOperationException(); + } + + @Override + public RDoubleAdder getDoubleAdder(String s) { + throw new UnsupportedOperationException(); + } + + @Override + public RCountDownLatch getCountDownLatch(String s) { + throw new UnsupportedOperationException(); + } + + @Override + public RBitSet getBitSet(String s) { + throw new UnsupportedOperationException(); + } + + @Override + public RBloomFilter getBloomFilter(String s) { + throw new UnsupportedOperationException(); + } + + @Override + public RBloomFilter getBloomFilter(String s, Codec codec) { + throw new UnsupportedOperationException(); + } + + @Override + public RIdGenerator getIdGenerator(String s) { + throw new UnsupportedOperationException(); + } + + @Override + public RFunction getFunction() { + throw new UnsupportedOperationException(); + } + + @Override + public RFunction getFunction(Codec codec) { + throw new UnsupportedOperationException(); + } + + @Override + public RScript getScript() { + throw new UnsupportedOperationException(); + } + + @Override + public RScript getScript(Codec codec) { + throw new UnsupportedOperationException(); + } + + @Override + public RScheduledExecutorService getExecutorService(String s) { + throw new UnsupportedOperationException(); + } + + @Override + public RScheduledExecutorService getExecutorService(String s, ExecutorOptions executorOptions) { + throw new UnsupportedOperationException(); + } + + @Override + public RScheduledExecutorService getExecutorService(String s, Codec codec) { + throw new UnsupportedOperationException(); + } + + @Override + public RScheduledExecutorService getExecutorService( + String s, Codec codec, ExecutorOptions executorOptions) { + throw new UnsupportedOperationException(); + } + + @Override + public RRemoteService getRemoteService() { + throw new UnsupportedOperationException(); + } + + @Override + public RRemoteService getRemoteService(Codec codec) { + throw new UnsupportedOperationException(); + } + + @Override + public RRemoteService getRemoteService(String s) { + throw new UnsupportedOperationException(); + } + + @Override + public RRemoteService getRemoteService(String s, Codec codec) { + throw new UnsupportedOperationException(); + } + + @Override + public RTransaction createTransaction(TransactionOptions transactionOptions) { + throw new UnsupportedOperationException(); + } + + @Override + public RBatch createBatch(BatchOptions batchOptions) { + throw new UnsupportedOperationException(); + } + + @Override + public RBatch createBatch() { + throw new UnsupportedOperationException(); + } + + @Override + public RLiveObjectService getLiveObjectService() { + throw new UnsupportedOperationException(); + } + + @Override + public RedissonRxClient rxJava() { + throw new UnsupportedOperationException(); + } + + @Override + public RedissonReactiveClient reactive() { + throw new UnsupportedOperationException(); + } + + @Override + public void shutdown() {} + + @Override + public void shutdown(long l, long l1, TimeUnit timeUnit) {} + + @Override + public Config getConfig() { + throw new UnsupportedOperationException(); + } + + @Override + public T getRedisNodes(RedisNodes redisNodes) { + throw new UnsupportedOperationException(); + } + + /** + * @deprecated + */ + @Override + @Deprecated + public NodesGroup getNodesGroup() { + throw new UnsupportedOperationException(); + } + + /** + * @deprecated + */ + @Override + @Deprecated + public ClusterNodesGroup getClusterNodesGroup() { + throw new UnsupportedOperationException(); + } + + @Override + public boolean isShutdown() { + return false; + } + + @Override + public boolean isShuttingDown() { + return false; + } + + @Override + public String getId() { + throw new UnsupportedOperationException(); + } +} diff --git a/src/test/java/org/cbioportal/legacy/persistence/util/fakeclient/MockRBucket.java b/src/test/java/org/cbioportal/legacy/persistence/util/fakeclient/MockRBucket.java new file mode 100644 index 00000000000..899178e4fd6 --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/persistence/util/fakeclient/MockRBucket.java @@ -0,0 +1,551 @@ +package org.cbioportal.legacy.persistence.util.fakeclient; + +import java.time.Duration; +import java.time.Instant; +import java.util.Date; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.TimeUnit; +import org.redisson.api.ObjectListener; +import org.redisson.api.RBucket; +import org.redisson.api.RFuture; +import org.redisson.client.codec.Codec; + +public class MockRBucket implements RBucket { + private final ConcurrentHashMap rBucketCache; + private final String key; + + public MockRBucket(ConcurrentHashMap rBucketCache, String key) { + this.rBucketCache = rBucketCache; + this.key = key; + } + + @Override + public Object get() { + return rBucketCache.get(key); + } + + @Override + public void set(Object o) { + rBucketCache.put(key, o); + } + + @Override + public void set(Object o, long l, TimeUnit timeUnit) { + // This cache is really primitive, so ttl isn't fully implemented + // Instead, if the ttl is 0, the object isn't added, but for any other value, it is + // in the cache forever. + if (l == 0) { + set(null); + } else { + set(o); + } + } + + @Override + public void setAndKeepTTL(Object o) {} + + @Override + public RFuture setAsync(Object o) { + set(o); + return null; + } + + @Override + public RFuture setAsync(Object o, long l, TimeUnit timeUnit) { + set(o, l, timeUnit); + return null; + } + + @Override + public RFuture setAndKeepTTLAsync(Object o) { + return null; + } + + @Override + public RFuture expireAsync(long l, TimeUnit timeUnit) { + // This cache is really primitive, so ttl isn't fully implemented + // Instead, if the ttl is 0, the object removed, but for any other value, + // it isn't touched. + if (l == 0) { + set(null); + } + return null; + } + + /* + * Methods we don't use + */ + @Override + public long size() { + throw new UnsupportedOperationException(); + } + + @Override + public Object getAndDelete() { + throw new UnsupportedOperationException(); + } + + @Override + public boolean trySet(Object o) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean trySet(Object o, long l, TimeUnit timeUnit) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean setIfAbsent(Object o) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean setIfAbsent(Object o, Duration duration) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean setIfExists(Object o) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean setIfExists(Object o, long l, TimeUnit timeUnit) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean compareAndSet(Object o, Object v1) { + throw new UnsupportedOperationException(); + } + + @Override + public Object getAndSet(Object o) { + throw new UnsupportedOperationException(); + } + + @Override + public Object getAndSet(Object o, long l, TimeUnit timeUnit) { + throw new UnsupportedOperationException(); + } + + @Override + public Object getAndExpire(Duration duration) { + throw new UnsupportedOperationException(); + } + + @Override + public Object getAndExpire(Instant instant) { + throw new UnsupportedOperationException(); + } + + @Override + public Object getAndClearExpire() { + throw new UnsupportedOperationException(); + } + + @Override + public Long getIdleTime() { + throw new UnsupportedOperationException(); + } + + @Override + public long sizeInMemory() { + throw new UnsupportedOperationException(); + } + + @Override + public void restore(byte[] bytes) {} + + @Override + public void restore(byte[] bytes, long l, TimeUnit timeUnit) {} + + @Override + public void restoreAndReplace(byte[] bytes) {} + + @Override + public void restoreAndReplace(byte[] bytes, long l, TimeUnit timeUnit) {} + + @Override + public byte[] dump() { + throw new UnsupportedOperationException(); + } + + @Override + public boolean touch() { + throw new UnsupportedOperationException(); + } + + @Override + public void migrate(String s, int i, int i1, long l) {} + + @Override + public void copy(String s, int i, int i1, long l) {} + + @Override + public boolean move(int i) { + throw new UnsupportedOperationException(); + } + + @Override + public String getName() { + throw new UnsupportedOperationException(); + } + + @Override + public boolean delete() { + throw new UnsupportedOperationException(); + } + + @Override + public boolean unlink() { + throw new UnsupportedOperationException(); + } + + @Override + public void rename(String s) {} + + @Override + public boolean renamenx(String s) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean isExists() { + throw new UnsupportedOperationException(); + } + + @Override + public Codec getCodec() { + throw new UnsupportedOperationException(); + } + + @Override + public int addListener(ObjectListener objectListener) { + throw new UnsupportedOperationException(); + } + + @Override + public void removeListener(int i) {} + + @Override + public RFuture sizeAsync() { + throw new UnsupportedOperationException(); + } + + @Override + public RFuture getAsync() { + throw new UnsupportedOperationException(); + } + + @Override + public RFuture getAndDeleteAsync() { + throw new UnsupportedOperationException(); + } + + @Override + public RFuture trySetAsync(Object o) { + throw new UnsupportedOperationException(); + } + + @Override + public RFuture trySetAsync(Object o, long l, TimeUnit timeUnit) { + throw new UnsupportedOperationException(); + } + + @Override + public RFuture setIfAbsentAsync(Object o) { + throw new UnsupportedOperationException(); + } + + @Override + public RFuture setIfAbsentAsync(Object o, Duration duration) { + throw new UnsupportedOperationException(); + } + + @Override + public RFuture setIfExistsAsync(Object o) { + throw new UnsupportedOperationException(); + } + + @Override + public RFuture setIfExistsAsync(Object o, long l, TimeUnit timeUnit) { + throw new UnsupportedOperationException(); + } + + @Override + public RFuture compareAndSetAsync(Object o, Object v1) { + throw new UnsupportedOperationException(); + } + + @Override + public RFuture getAndSetAsync(Object o) { + throw new UnsupportedOperationException(); + } + + @Override + public RFuture getAndSetAsync(Object o, long l, TimeUnit timeUnit) { + throw new UnsupportedOperationException(); + } + + @Override + public RFuture getAndExpireAsync(Duration duration) { + throw new UnsupportedOperationException(); + } + + @Override + public RFuture getAndExpireAsync(Instant instant) { + throw new UnsupportedOperationException(); + } + + @Override + public RFuture getAndClearExpireAsync() { + throw new UnsupportedOperationException(); + } + + @Override + public boolean expire(long l, TimeUnit timeUnit) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean expireAt(long l) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean expireAt(Date date) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean expire(Instant instant) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean expireIfSet(Instant instant) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean expireIfNotSet(Instant instant) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean expireIfGreater(Instant instant) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean expireIfLess(Instant instant) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean expire(Duration duration) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean expireIfSet(Duration duration) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean expireIfNotSet(Duration duration) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean expireIfGreater(Duration duration) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean expireIfLess(Duration duration) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean clearExpire() { + throw new UnsupportedOperationException(); + } + + @Override + public long remainTimeToLive() { + throw new UnsupportedOperationException(); + } + + @Override + public long getExpireTime() { + throw new UnsupportedOperationException(); + } + + @Override + public RFuture expireAtAsync(Date date) { + throw new UnsupportedOperationException(); + } + + @Override + public RFuture expireAtAsync(long l) { + throw new UnsupportedOperationException(); + } + + @Override + public RFuture expireAsync(Instant instant) { + throw new UnsupportedOperationException(); + } + + @Override + public RFuture expireIfSetAsync(Instant instant) { + throw new UnsupportedOperationException(); + } + + @Override + public RFuture expireIfNotSetAsync(Instant instant) { + throw new UnsupportedOperationException(); + } + + @Override + public RFuture expireIfGreaterAsync(Instant instant) { + throw new UnsupportedOperationException(); + } + + @Override + public RFuture expireIfLessAsync(Instant instant) { + throw new UnsupportedOperationException(); + } + + @Override + public RFuture expireAsync(Duration duration) { + throw new UnsupportedOperationException(); + } + + @Override + public RFuture expireIfSetAsync(Duration duration) { + throw new UnsupportedOperationException(); + } + + @Override + public RFuture expireIfNotSetAsync(Duration duration) { + throw new UnsupportedOperationException(); + } + + @Override + public RFuture expireIfGreaterAsync(Duration duration) { + throw new UnsupportedOperationException(); + } + + @Override + public RFuture expireIfLessAsync(Duration duration) { + throw new UnsupportedOperationException(); + } + + @Override + public RFuture clearExpireAsync() { + throw new UnsupportedOperationException(); + } + + @Override + public RFuture remainTimeToLiveAsync() { + throw new UnsupportedOperationException(); + } + + @Override + public RFuture getExpireTimeAsync() { + throw new UnsupportedOperationException(); + } + + @Override + public RFuture getIdleTimeAsync() { + throw new UnsupportedOperationException(); + } + + @Override + public RFuture sizeInMemoryAsync() { + throw new UnsupportedOperationException(); + } + + @Override + public RFuture restoreAsync(byte[] bytes) { + throw new UnsupportedOperationException(); + } + + @Override + public RFuture restoreAsync(byte[] bytes, long l, TimeUnit timeUnit) { + throw new UnsupportedOperationException(); + } + + @Override + public RFuture restoreAndReplaceAsync(byte[] bytes) { + throw new UnsupportedOperationException(); + } + + @Override + public RFuture restoreAndReplaceAsync(byte[] bytes, long l, TimeUnit timeUnit) { + throw new UnsupportedOperationException(); + } + + @Override + public RFuture dumpAsync() { + throw new UnsupportedOperationException(); + } + + @Override + public RFuture touchAsync() { + throw new UnsupportedOperationException(); + } + + @Override + public RFuture migrateAsync(String s, int i, int i1, long l) { + throw new UnsupportedOperationException(); + } + + @Override + public RFuture copyAsync(String s, int i, int i1, long l) { + throw new UnsupportedOperationException(); + } + + @Override + public RFuture moveAsync(int i) { + throw new UnsupportedOperationException(); + } + + @Override + public RFuture deleteAsync() { + throw new UnsupportedOperationException(); + } + + @Override + public RFuture unlinkAsync() { + throw new UnsupportedOperationException(); + } + + @Override + public RFuture renameAsync(String s) { + throw new UnsupportedOperationException(); + } + + @Override + public RFuture renamenxAsync(String s) { + throw new UnsupportedOperationException(); + } + + @Override + public RFuture isExistsAsync() { + throw new UnsupportedOperationException(); + } + + @Override + public RFuture addListenerAsync(ObjectListener objectListener) { + throw new UnsupportedOperationException(); + } + + @Override + public RFuture removeListenerAsync(int i) { + throw new UnsupportedOperationException(); + } +} diff --git a/src/test/java/org/cbioportal/legacy/persistence/util/fakeclient/MockRKeys.java b/src/test/java/org/cbioportal/legacy/persistence/util/fakeclient/MockRKeys.java new file mode 100644 index 00000000000..c0920e9a7a8 --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/persistence/util/fakeclient/MockRKeys.java @@ -0,0 +1,315 @@ +package org.cbioportal.legacy.persistence.util.fakeclient; + +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.TimeUnit; +import java.util.function.Predicate; +import java.util.regex.Pattern; +import java.util.stream.Stream; +import org.redisson.api.*; + +public class MockRKeys implements RKeys { + private final ConcurrentMap cache; + private final ConcurrentHashMap valueMap; + + public MockRKeys( + ConcurrentMap cache, ConcurrentHashMap valueMap) { + this.cache = cache; + this.valueMap = valueMap; + } + + @Override + public long deleteByPattern(String s) { + Predicate matches = Pattern.compile(s).asPredicate(); + + valueMap.keySet().stream().filter(matches).forEach(valueMap::remove); + + return cache.keySet().stream().filter(matches).peek(cache::remove).count(); + } + + @Override + public Iterable getKeysWithLimit(int i) { + throw new UnsupportedOperationException(); + } + + @Override + public Iterable getKeysWithLimit(String s, int i) { + throw new UnsupportedOperationException(); + } + + /* + * Methods we don't use + */ + @Override + public boolean move(String s, int i) { + throw new UnsupportedOperationException(); + } + + @Override + public void migrate(String s, String s1, int i, int i1, long l) { + throw new UnsupportedOperationException(); + } + + @Override + public void copy(String s, String s1, int i, int i1, long l) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean expire(String s, long l, TimeUnit timeUnit) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean expireAt(String s, long l) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean clearExpire(String s) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean renamenx(String s, String s1) { + throw new UnsupportedOperationException(); + } + + @Override + public void rename(String s, String s1) {} + + @Override + public long remainTimeToLive(String s) { + throw new UnsupportedOperationException(); + } + + @Override + public long touch(String... strings) { + throw new UnsupportedOperationException(); + } + + @Override + public long countExists(String... strings) { + throw new UnsupportedOperationException(); + } + + @Override + public RType getType(String s) { + throw new UnsupportedOperationException(); + } + + @Override + public int getSlot(String s) { + throw new UnsupportedOperationException(); + } + + @Override + public Iterable getKeysByPattern(String s) { + throw new UnsupportedOperationException(); + } + + @Override + public Iterable getKeysByPattern(String s, int i) { + throw new UnsupportedOperationException(); + } + + @Override + public Iterable getKeys() { + throw new UnsupportedOperationException(); + } + + @Override + public Iterable getKeys(int i) { + throw new UnsupportedOperationException(); + } + + @Override + public Stream getKeysStreamByPattern(String s) { + throw new UnsupportedOperationException(); + } + + @Override + public Stream getKeysStreamByPattern(String s, int i) { + throw new UnsupportedOperationException(); + } + + @Override + public Stream getKeysStream() { + throw new UnsupportedOperationException(); + } + + @Override + public Stream getKeysStream(int i) { + throw new UnsupportedOperationException(); + } + + @Override + public String randomKey() { + throw new UnsupportedOperationException(); + } + + @Override + public long delete(RObject... rObjects) { + throw new UnsupportedOperationException(); + } + + @Override + public long delete(String... strings) { + throw new UnsupportedOperationException(); + } + + @Override + public long unlink(String... strings) { + throw new UnsupportedOperationException(); + } + + @Override + public long count() { + throw new UnsupportedOperationException(); + } + + @Override + public void swapdb(int i, int i1) { + throw new UnsupportedOperationException(); + } + + @Override + public void flushdb() { + throw new UnsupportedOperationException(); + } + + @Override + public void flushdbParallel() { + throw new UnsupportedOperationException(); + } + + @Override + public void flushall() { + throw new UnsupportedOperationException(); + } + + @Override + public void flushallParallel() { + throw new UnsupportedOperationException(); + } + + @Override + public RFuture moveAsync(String s, int i) { + throw new UnsupportedOperationException(); + } + + @Override + public RFuture migrateAsync(String s, String s1, int i, int i1, long l) { + throw new UnsupportedOperationException(); + } + + @Override + public RFuture copyAsync(String s, String s1, int i, int i1, long l) { + throw new UnsupportedOperationException(); + } + + @Override + public RFuture expireAsync(String s, long l, TimeUnit timeUnit) { + throw new UnsupportedOperationException(); + } + + @Override + public RFuture expireAtAsync(String s, long l) { + throw new UnsupportedOperationException(); + } + + @Override + public RFuture clearExpireAsync(String s) { + throw new UnsupportedOperationException(); + } + + @Override + public RFuture renamenxAsync(String s, String s1) { + throw new UnsupportedOperationException(); + } + + @Override + public RFuture renameAsync(String s, String s1) { + throw new UnsupportedOperationException(); + } + + @Override + public RFuture remainTimeToLiveAsync(String s) { + throw new UnsupportedOperationException(); + } + + @Override + public RFuture touchAsync(String... strings) { + throw new UnsupportedOperationException(); + } + + @Override + public RFuture countExistsAsync(String... strings) { + throw new UnsupportedOperationException(); + } + + @Override + public RFuture getTypeAsync(String s) { + throw new UnsupportedOperationException(); + } + + @Override + public RFuture getSlotAsync(String s) { + throw new UnsupportedOperationException(); + } + + @Override + public RFuture randomKeyAsync() { + throw new UnsupportedOperationException(); + } + + @Override + public RFuture deleteByPatternAsync(String s) { + throw new UnsupportedOperationException(); + } + + @Override + public RFuture deleteAsync(RObject... rObjects) { + throw new UnsupportedOperationException(); + } + + @Override + public RFuture deleteAsync(String... strings) { + throw new UnsupportedOperationException(); + } + + @Override + public RFuture unlinkAsync(String... strings) { + throw new UnsupportedOperationException(); + } + + @Override + public RFuture countAsync() { + throw new UnsupportedOperationException(); + } + + @Override + public RFuture swapdbAsync(int i, int i1) { + throw new UnsupportedOperationException(); + } + + @Override + public RFuture flushdbAsync() { + throw new UnsupportedOperationException(); + } + + @Override + public RFuture flushallAsync() { + throw new UnsupportedOperationException(); + } + + @Override + public RFuture flushdbParallelAsync() { + throw new UnsupportedOperationException(); + } + + @Override + public RFuture flushallParallelAsync() { + throw new UnsupportedOperationException(); + } +} diff --git a/src/test/java/org/cbioportal/legacy/proxy/MonkifierTest.java b/src/test/java/org/cbioportal/legacy/proxy/MonkifierTest.java new file mode 100644 index 00000000000..5e5de52108f --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/proxy/MonkifierTest.java @@ -0,0 +1,60 @@ +package org.cbioportal.legacy.proxy; + +import java.util.HashMap; +import java.util.Map; +import org.cbioportal.application.proxy.Monkifier; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.junit.MockitoJUnitRunner; + +@RunWith(MockitoJUnitRunner.class) +public class MonkifierTest { + private Monkifier monkifier = new Monkifier(); + + @Test + public void decodeBase64() { + String encoded = "aW5jbHVkZUV2aWRlbmNl"; + String decoded = this.monkifier.decodeBase64(encoded); + Assert.assertEquals("includeEvidence", decoded); + } + + @Test + public void encodeBase64() { + String plain = "13:g.32914438del"; + String encoded = this.monkifier.encodeBase64(plain); + Assert.assertEquals("MTM6Zy4zMjkxNDQzOGRlbA==", encoded); + } + + @Test + public void decodeQueryString() { + // no param + Map encodedQueryParamsEmpty = new HashMap<>(); + String decodedQueryString1 = monkifier.decodeQueryString(encodedQueryParamsEmpty); + Assert.assertEquals("", decodedQueryString1); + + // single param + Map encodedQueryParamsSingleParam = new HashMap<>(); + encodedQueryParamsSingleParam.put("aW5jbHVkZUV2aWRlbmNl", new String[] {"ZmFsc2U="}); + String decodedQueryString2 = monkifier.decodeQueryString(encodedQueryParamsSingleParam); + Assert.assertEquals("includeEvidence=false", decodedQueryString2); + + // multiple param + Map encodedQueryParamsMultiParam = new HashMap<>(); + encodedQueryParamsMultiParam.put("aW5jbHVkZUV2aWRlbmNl", new String[] {"ZmFsc2U="}); + encodedQueryParamsMultiParam.put("aGd2c2c=", new String[] {"MTM6Zy4zMjkxNDQzOGRlbA=="}); + + String decodedQueryString3 = monkifier.decodeQueryString(encodedQueryParamsMultiParam); + Assert.assertEquals("hgvsg=13:g.32914438del&includeEvidence=false", decodedQueryString3); + + // multiple param with a problematic character '>' + Map encodedQueryParamsMultiParamUrlBreaker = new HashMap<>(); + encodedQueryParamsMultiParamUrlBreaker.put("cmVmZXJlbmNlR2Vub21l", new String[] {"R1JDaDM3"}); + encodedQueryParamsMultiParamUrlBreaker.put( + "aGd2c2c=", new String[] {"NzpnLjE0MDQ1MzEzNkE+VA=="}); + + String decodedQueryString4 = + monkifier.decodeQueryString(encodedQueryParamsMultiParamUrlBreaker); + Assert.assertEquals("hgvsg=7:g.140453136A%3ET&referenceGenome=GRCh37", decodedQueryString4); + } +} diff --git a/src/test/java/org/cbioportal/legacy/service/impl/AlterationCountServiceImplTest.java b/src/test/java/org/cbioportal/legacy/service/impl/AlterationCountServiceImplTest.java new file mode 100644 index 00000000000..cbad8324ef5 --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/service/impl/AlterationCountServiceImplTest.java @@ -0,0 +1,371 @@ +package org.cbioportal.legacy.service.impl; + +import static org.mockito.ArgumentMatchers.anySet; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.anyBoolean; +import static org.mockito.Mockito.anyList; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.TreeSet; +import org.apache.commons.math3.util.Pair; +import org.cbioportal.legacy.model.AlterationCountByGene; +import org.cbioportal.legacy.model.AlterationCountByStructuralVariant; +import org.cbioportal.legacy.model.AlterationFilter; +import org.cbioportal.legacy.model.CNA; +import org.cbioportal.legacy.model.CopyNumberCountByGene; +import org.cbioportal.legacy.model.MolecularProfile; +import org.cbioportal.legacy.model.MolecularProfileCaseIdentifier; +import org.cbioportal.legacy.model.MutationEventType; +import org.cbioportal.legacy.model.util.Select; +import org.cbioportal.legacy.persistence.AlterationRepository; +import org.cbioportal.legacy.persistence.MolecularProfileRepository; +import org.cbioportal.legacy.service.exception.MolecularProfileNotFoundException; +import org.cbioportal.legacy.service.util.AlterationEnrichmentUtil; +import org.cbioportal.legacy.service.util.MolecularProfileUtil; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.mockito.Spy; +import org.mockito.junit.MockitoJUnitRunner; + +@RunWith(MockitoJUnitRunner.class) +public class AlterationCountServiceImplTest extends BaseServiceImplTest { + + private AlterationCountServiceImpl alterationCountService; + @Mock private AlterationRepository alterationRepository; + @Mock private AlterationEnrichmentUtil alterationEnrichmentUtil; + @Mock private AlterationEnrichmentUtil alterationEnrichmentUtilCna; + + @Mock + private AlterationEnrichmentUtil + alterationEnrichmentUtilStructVar; + + @Spy @InjectMocks private MolecularProfileUtil molecularProfileUtil; + @Mock private MolecularProfileRepository molecularProfileRepository; + + List caseIdentifiers = + Arrays.asList(new MolecularProfileCaseIdentifier("A", MOLECULAR_PROFILE_ID)); + Select mutationEventTypes = + Select.byValues(Arrays.asList(MutationEventType.missense_mutation)); + Select cnaEventTypes = Select.byValues(Arrays.asList(CNA.AMP)); + Select entrezGeneIds = Select.all(); + boolean includeFrequency = true; + boolean includeMissingAlterationsFromGenePanel = false; + List expectedCountByGeneList; + List expectedCnaCountByGeneList; + List expectedStructuralVariantList; + AlterationFilter alterationFilter = + new AlterationFilter( + mutationEventTypes, + cnaEventTypes, + false, + false, + false, + false, + false, + false, + Select.none(), + false); + + @Before + public void setup() { + MockitoAnnotations.openMocks(this); + + alterationCountService = + new AlterationCountServiceImpl( + alterationRepository, + alterationEnrichmentUtil, + alterationEnrichmentUtilCna, + alterationEnrichmentUtilStructVar, + molecularProfileRepository); + + MolecularProfile molecularProfile = new MolecularProfile(); + molecularProfile.setStableId(MOLECULAR_PROFILE_ID); + molecularProfile.setCancerStudyIdentifier(STUDY_ID); + + when(molecularProfileRepository.getMolecularProfiles( + Collections.singleton(MOLECULAR_PROFILE_ID), "SUMMARY")) + .thenReturn(Arrays.asList(molecularProfile)); + + AlterationCountByGene alterationCountByGene = new AlterationCountByGene(); + alterationCountByGene.setEntrezGeneId(ENTREZ_GENE_ID_1); + expectedCountByGeneList = Arrays.asList(alterationCountByGene); + + CopyNumberCountByGene copyNumberCountByGene = new CopyNumberCountByGene(); + copyNumberCountByGene.setEntrezGeneId(ENTREZ_GENE_ID_1); + copyNumberCountByGene.setAlteration(2); + expectedCnaCountByGeneList = Arrays.asList(copyNumberCountByGene); + + final AlterationCountByStructuralVariant alterationCountByStructuralVariant = + new AlterationCountByStructuralVariant(); + alterationCountByStructuralVariant.setGene1EntrezGeneId(ENTREZ_GENE_ID_1); + alterationCountByStructuralVariant.setGene2EntrezGeneId(ENTREZ_GENE_ID_2); + alterationCountByStructuralVariant.setGene1HugoGeneSymbol(HUGO_GENE_SYMBOL_1); + alterationCountByStructuralVariant.setGene2HugoGeneSymbol(HUGO_GENE_SYMBOL_2); + expectedStructuralVariantList = Arrays.asList(alterationCountByStructuralVariant); + } + + @Test + public void getSampleAlterationGeneCounts() { + + // this mock tests correct argument types + when(alterationRepository.getSampleAlterationGeneCounts( + new HashSet<>(caseIdentifiers), entrezGeneIds, alterationFilter)) + .thenReturn(expectedCountByGeneList); + + Pair, Long> result = + alterationCountService.getSampleAlterationGeneCounts( + caseIdentifiers, + entrezGeneIds, + includeFrequency, + includeMissingAlterationsFromGenePanel, + alterationFilter); + + verify(alterationEnrichmentUtil, times(1)) + .includeFrequencyForSamples(anyList(), anyList(), anyBoolean()); + } + + @Test + public void getPatientAlterationGeneCounts() { + + // this mock tests correct argument types + when(alterationRepository.getPatientAlterationGeneCounts( + new HashSet<>(caseIdentifiers), entrezGeneIds, alterationFilter)) + .thenReturn(expectedCountByGeneList); + + alterationCountService.getPatientAlterationGeneCounts( + caseIdentifiers, + entrezGeneIds, + includeFrequency, + includeMissingAlterationsFromGenePanel, + alterationFilter); + + verify(alterationEnrichmentUtil, times(1)) + .includeFrequencyForPatients(anyList(), anyList(), anyBoolean()); + } + + @Test + public void getSampleMutationGeneCounts() { + // this mock tests correct argument types + when(alterationRepository.getSampleAlterationGeneCounts( + new HashSet<>(caseIdentifiers), entrezGeneIds, alterationFilter)) + .thenReturn(expectedCountByGeneList); + + Pair, Long> result = + alterationCountService.getSampleMutationGeneCounts( + caseIdentifiers, + entrezGeneIds, + includeFrequency, + includeMissingAlterationsFromGenePanel, + alterationFilter); + + Assert.assertEquals(expectedCountByGeneList, result.getFirst()); + } + + @Test + public void getPatientMutationGeneCounts() throws MolecularProfileNotFoundException { + + // this mock tests correct argument types + when(alterationRepository.getPatientAlterationGeneCounts( + new HashSet<>(caseIdentifiers), entrezGeneIds, alterationFilter)) + .thenReturn(expectedCountByGeneList); + + Pair, Long> result = + alterationCountService.getPatientMutationGeneCounts( + caseIdentifiers, + entrezGeneIds, + includeFrequency, + includeMissingAlterationsFromGenePanel, + alterationFilter); + + Assert.assertEquals(expectedCountByGeneList, result.getFirst()); + } + + @Test + public void getSampleCnaGeneCounts() { + + // this mock tests correct argument types + when(alterationRepository.getSampleCnaGeneCounts( + new TreeSet<>(caseIdentifiers), entrezGeneIds, alterationFilter)) + .thenReturn(expectedCnaCountByGeneList); + + Pair, Long> result = + alterationCountService.getSampleCnaGeneCounts( + caseIdentifiers, + entrezGeneIds, + includeFrequency, + includeMissingAlterationsFromGenePanel, + alterationFilter); + + verify(alterationEnrichmentUtilCna, times(1)) + .includeFrequencyForSamples(anyList(), anyList(), anyBoolean()); + Assert.assertEquals(expectedCnaCountByGeneList, result.getFirst()); + } + + @Test + public void getPatientCnaGeneCounts() { + + // this mock tests correct argument types + when(alterationRepository.getPatientCnaGeneCounts( + new HashSet<>(caseIdentifiers), entrezGeneIds, alterationFilter)) + .thenReturn(expectedCnaCountByGeneList); + + Pair, Long> result = + alterationCountService.getPatientCnaGeneCounts( + caseIdentifiers, + entrezGeneIds, + includeFrequency, + includeMissingAlterationsFromGenePanel, + alterationFilter); + + verify(alterationEnrichmentUtilCna, times(1)) + .includeFrequencyForPatients(anyList(), anyList(), anyBoolean()); + Assert.assertEquals(expectedCnaCountByGeneList, result.getFirst()); + } + + @Test + public void getSampleStructuralVariantCounts() { + + when(alterationRepository.getSampleStructuralVariantCounts( + new TreeSet<>(caseIdentifiers), alterationFilter)) + .thenReturn(expectedStructuralVariantList); + + Pair, Long> result = + alterationCountService.getSampleStructuralVariantCounts( + caseIdentifiers, + includeFrequency, + includeMissingAlterationsFromGenePanel, + alterationFilter); + + verify(alterationEnrichmentUtilStructVar, times(1)) + .includeFrequencyForSamples(anyList(), anyList(), anyBoolean()); + Assert.assertEquals(expectedStructuralVariantList, result.getFirst()); + } + + @Test + public void testMergeAlterationCountsAcrossStudies() { + // Setup case identifiers from multiple studies + MolecularProfileCaseIdentifier case1 = + new MolecularProfileCaseIdentifier("Sample1", MOLECULAR_PROFILE_ID); + MolecularProfileCaseIdentifier case2 = + new MolecularProfileCaseIdentifier("Sample2", "another_profile_id"); + List multiStudyCaseIdentifiers = Arrays.asList(case1, case2); + + // Create a second molecular profile for a different study + MolecularProfile molecularProfile1 = new MolecularProfile(); + molecularProfile1.setStableId(MOLECULAR_PROFILE_ID); + molecularProfile1.setCancerStudyIdentifier(STUDY_ID); + + MolecularProfile molecularProfile2 = new MolecularProfile(); + molecularProfile2.setStableId("another_profile_id"); + molecularProfile2.setCancerStudyIdentifier("another_study_id"); + + // Mock the repository to return profiles for both studies + when(molecularProfileRepository.getMolecularProfiles( + new HashSet<>(Arrays.asList(MOLECULAR_PROFILE_ID, "another_profile_id")), "SUMMARY")) + .thenReturn(Arrays.asList(molecularProfile1, molecularProfile2)); + + // Create two alteration counts for the same gene from different studies + AlterationCountByGene geneCount1 = new AlterationCountByGene(); + geneCount1.setEntrezGeneId(ENTREZ_GENE_ID_1); + geneCount1.setHugoGeneSymbol(HUGO_GENE_SYMBOL_1); + geneCount1.setNumberOfAlteredCases(5); + geneCount1.setTotalCount(10); + + AlterationCountByGene geneCount2 = new AlterationCountByGene(); + geneCount2.setEntrezGeneId(ENTREZ_GENE_ID_1); + geneCount2.setHugoGeneSymbol(HUGO_GENE_SYMBOL_1); + geneCount2.setNumberOfAlteredCases(3); + geneCount2.setTotalCount(7); + + // Define expected values explicitly + final int expectedTotalCount = 17; // 10 + 7 + final int expectedAlteredCases = 8; // 5 + 3 + + // Mock the repository to return different counts for different study groups + when(alterationRepository.getSampleAlterationGeneCounts( + anySet(), eq(entrezGeneIds), eq(alterationFilter))) + .thenAnswer( + invocation -> { + Set caseSet = invocation.getArgument(0); + String profileId = caseSet.iterator().next().getMolecularProfileId(); + if (profileId.equals(MOLECULAR_PROFILE_ID)) { + return List.of(geneCount1); + } else { + return List.of(geneCount2); + } + }); + + // Mock frequency calculation to return a static value + when(alterationEnrichmentUtil.includeFrequencyForSamples(anyList(), anyList(), anyBoolean())) + .thenReturn(20L); + + // Call the method under test + Pair, Long> result = + alterationCountService.getSampleAlterationGeneCounts( + multiStudyCaseIdentifiers, + entrezGeneIds, + includeFrequency, + includeMissingAlterationsFromGenePanel, + alterationFilter); + + // Verify the repository was called for each study group + verify(alterationRepository, times(2)) + .getSampleAlterationGeneCounts(anySet(), eq(entrezGeneIds), eq(alterationFilter)); + + // Verify frequency calculation was called + verify(alterationEnrichmentUtil, times(1)) + .includeFrequencyForSamples( + anyList(), anyList(), eq(includeMissingAlterationsFromGenePanel)); + + // Check result integrity + Assert.assertNotNull("Result should not be null", result); + Assert.assertNotNull("Gene count list should not be null", result.getFirst()); + Assert.assertEquals("Should return one merged gene count", 1, result.getFirst().size()); + + // Verify the counts were properly merged + AlterationCountByGene mergedCount = result.getFirst().getFirst(); + Assert.assertEquals( + "EntrezGeneId should match", ENTREZ_GENE_ID_1, mergedCount.getEntrezGeneId()); + Assert.assertEquals( + "HugoGeneSymbol should match", HUGO_GENE_SYMBOL_1, mergedCount.getHugoGeneSymbol()); + Assert.assertEquals( + "Total count should be summed", expectedTotalCount, mergedCount.getTotalCount().intValue()); + Assert.assertEquals( + "Number of altered cases should be summed", + expectedAlteredCases, + mergedCount.getNumberOfAlteredCases().intValue()); + + // Verify total profiled count + Assert.assertEquals( + "Total profiled count should match mocked value", 20L, result.getSecond().longValue()); + } + + @Test + public void testMergeAlterationCountsWithEmptyInput() { + // Test with empty input + Pair, Long> result = + alterationCountService.getSampleAlterationGeneCounts( + Collections.emptyList(), // empty list + entrezGeneIds, + includeFrequency, + includeMissingAlterationsFromGenePanel, + alterationFilter); + + // Verify results + Assert.assertNotNull("Result should not be null", result); + Assert.assertTrue("Gene count list should be empty", result.getFirst().isEmpty()); + Assert.assertEquals("Profiled count should be zero", 0L, result.getSecond().longValue()); + } +} diff --git a/src/test/java/org/cbioportal/legacy/service/impl/AlterationDriverAnnotationServiceImplTest.java b/src/test/java/org/cbioportal/legacy/service/impl/AlterationDriverAnnotationServiceImplTest.java new file mode 100644 index 00000000000..0864cdfb3b4 --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/service/impl/AlterationDriverAnnotationServiceImplTest.java @@ -0,0 +1,151 @@ +package org.cbioportal.legacy.service.impl; + +import static org.mockito.ArgumentMatchers.isNull; +import static org.mockito.Mockito.when; + +import java.util.Arrays; +import java.util.List; +import org.cbioportal.legacy.model.AlterationDriverAnnotation; +import org.cbioportal.legacy.model.CustomDriverAnnotationReport; +import org.cbioportal.legacy.persistence.AlterationDriverAnnotationRepository; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnitRunner; + +@RunWith(MockitoJUnitRunner.Silent.class) +public class AlterationDriverAnnotationServiceImplTest { + + @InjectMocks private AlterationDriverAnnotationServiceImpl alterationDriverAnnotationService; + @Mock private AlterationDriverAnnotationRepository alterationDriverAnnotationRepository; + private AlterationDriverAnnotation alterationDriverAnnotation1; + private AlterationDriverAnnotation alterationDriverAnnotation2; + + @Before + public void setUp() throws Exception { + alterationDriverAnnotation1 = new AlterationDriverAnnotation(); + alterationDriverAnnotation2 = new AlterationDriverAnnotation(); + } + + @Test + public void getCustomDriverAnnotationProps() { + + alterationDriverAnnotation1.setDriverFilter("Putative_Driver"); + alterationDriverAnnotation1.setDriverTiersFilter("Class1"); + alterationDriverAnnotation2.setDriverFilter("Putative_Passenger"); + alterationDriverAnnotation2.setDriverTiersFilter("Class2"); + List annotationList = + Arrays.asList(alterationDriverAnnotation1, alterationDriverAnnotation2); + when(alterationDriverAnnotationRepository.getAlterationDriverAnnotations(isNull())) + .thenReturn(annotationList); + + CustomDriverAnnotationReport props = + alterationDriverAnnotationService.getCustomDriverAnnotationProps(null); + + Assert.assertTrue(props.getHasBinary()); + Assert.assertTrue(props.getTiers().containsAll(Arrays.asList("Class1", "Class2"))); + } + + @Test + public void getCustomDriverAnnotationPropsNoFilter() { + alterationDriverAnnotation1.setDriverFilter("Filter1"); + alterationDriverAnnotation1.setDriverTiersFilter("Class1"); + alterationDriverAnnotation2.setDriverFilter("Filter2"); + alterationDriverAnnotation2.setDriverTiersFilter("Class2"); + List annotationList = + Arrays.asList(alterationDriverAnnotation1, alterationDriverAnnotation2); + when(alterationDriverAnnotationRepository.getAlterationDriverAnnotations(isNull())) + .thenReturn(annotationList); + + CustomDriverAnnotationReport props = + alterationDriverAnnotationService.getCustomDriverAnnotationProps(null); + + Assert.assertFalse(props.getHasBinary()); + Assert.assertTrue(props.getTiers().containsAll(Arrays.asList("Class1", "Class2"))); + } + + @Test + public void getCustomDriverAnnotationPropsNoTiersFilter() { + + alterationDriverAnnotation1.setDriverFilter("Putative_Driver"); + alterationDriverAnnotation2.setDriverFilter("Putative_Passenger"); + List annotationList = + Arrays.asList(alterationDriverAnnotation1, alterationDriverAnnotation2); + when(alterationDriverAnnotationRepository.getAlterationDriverAnnotations(isNull())) + .thenReturn(annotationList); + + CustomDriverAnnotationReport props = + alterationDriverAnnotationService.getCustomDriverAnnotationProps(null); + + Assert.assertTrue(props.getHasBinary()); + Assert.assertEquals(0, props.getTiers().size()); + } + + @Test + public void getCustomDriverAnnotationPropsOneFilter() { + + alterationDriverAnnotation1.setDriverFilter("Putative_Driver"); + List annotationList = + Arrays.asList(alterationDriverAnnotation1, alterationDriverAnnotation2); + when(alterationDriverAnnotationRepository.getAlterationDriverAnnotations(isNull())) + .thenReturn(annotationList); + + CustomDriverAnnotationReport props = + alterationDriverAnnotationService.getCustomDriverAnnotationProps(null); + + Assert.assertTrue(props.getHasBinary()); + Assert.assertEquals(0, props.getTiers().size()); + } + + @Test + public void getCustomDriverAnnotationPropsNoFiltersAtAll() { + + List annotationList = + Arrays.asList(alterationDriverAnnotation1, alterationDriverAnnotation2); + when(alterationDriverAnnotationRepository.getAlterationDriverAnnotations(isNull())) + .thenReturn(annotationList); + + CustomDriverAnnotationReport props = + alterationDriverAnnotationService.getCustomDriverAnnotationProps(null); + + Assert.assertFalse(props.getHasBinary()); + Assert.assertEquals(0, props.getTiers().size()); + } + + @Test + public void getCustomDriverAnnotationPropsWithoutNATiers() { + AlterationDriverAnnotation naTierAnnotation = new AlterationDriverAnnotation(); + naTierAnnotation.setDriverTiersFilter("NA"); + List molecularProfileIds = Arrays.asList("test_1", "test_2"); + List annotationList = + Arrays.asList(alterationDriverAnnotation1, naTierAnnotation); + when(alterationDriverAnnotationRepository.getAlterationDriverAnnotations(molecularProfileIds)) + .thenReturn(annotationList); + + CustomDriverAnnotationReport props = + alterationDriverAnnotationService.getCustomDriverAnnotationProps(molecularProfileIds); + + Assert.assertFalse( + "NA has to be removed from the set of tiers", props.getTiers().contains("NA")); + } + + @Test + public void getCustomDriverAnnotationPropsWithoutEmptyTiers() { + AlterationDriverAnnotation emptyTierAnnotation = new AlterationDriverAnnotation(); + emptyTierAnnotation.setDriverTiersFilter(""); + List molecularProfileIds = Arrays.asList("test_1", "test_2"); + List annotationList = + Arrays.asList(alterationDriverAnnotation1, emptyTierAnnotation); + when(alterationDriverAnnotationRepository.getAlterationDriverAnnotations(molecularProfileIds)) + .thenReturn(annotationList); + + CustomDriverAnnotationReport props = + alterationDriverAnnotationService.getCustomDriverAnnotationProps(molecularProfileIds); + + Assert.assertFalse( + "Empty string tier has to be removed from the set", props.getTiers().contains("")); + } +} diff --git a/src/test/java/org/cbioportal/legacy/service/impl/AlterationEnrichmentServiceImplTest.java b/src/test/java/org/cbioportal/legacy/service/impl/AlterationEnrichmentServiceImplTest.java new file mode 100644 index 00000000000..92ce5cc1209 --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/service/impl/AlterationEnrichmentServiceImplTest.java @@ -0,0 +1,90 @@ +package org.cbioportal.legacy.service.impl; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import org.apache.commons.math3.util.Pair; +import org.cbioportal.legacy.model.AlterationCountByGene; +import org.cbioportal.legacy.model.AlterationEnrichment; +import org.cbioportal.legacy.model.AlterationFilter; +import org.cbioportal.legacy.model.CNA; +import org.cbioportal.legacy.model.EnrichmentType; +import org.cbioportal.legacy.model.MolecularProfileCaseIdentifier; +import org.cbioportal.legacy.model.MutationCountByGene; +import org.cbioportal.legacy.model.MutationEventType; +import org.cbioportal.legacy.model.util.Select; +import org.cbioportal.legacy.service.AlterationCountService; +import org.cbioportal.legacy.service.util.AlterationEnrichmentUtil; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.junit.MockitoJUnitRunner; + +@RunWith(MockitoJUnitRunner.Silent.class) +public class AlterationEnrichmentServiceImplTest extends BaseServiceImplTest { + + @InjectMocks private AlterationEnrichmentServiceImpl alterationEnrichmentService; + @Mock private AlterationCountService alterationCountService; + @Mock private AlterationEnrichmentUtil alterationEnrichmentUtil; + + @Test + public void getAlterationEnrichments() throws Exception { + // create set1, set2 list of entities + MolecularProfileCaseIdentifier molecularProfileCase1 = new MolecularProfileCaseIdentifier(); + molecularProfileCase1.setCaseId("sample_id_1"); + molecularProfileCase1.setMolecularProfileId("test1_mutations"); + MolecularProfileCaseIdentifier molecularProfileCase2 = new MolecularProfileCaseIdentifier(); + molecularProfileCase2.setCaseId("sample_id_2"); + molecularProfileCase2.setMolecularProfileId("test2_mutations"); + List molecularProfileCaseSet1 = new ArrayList<>(); + molecularProfileCaseSet1.add(molecularProfileCase1); + molecularProfileCaseSet1.add(molecularProfileCase2); + + MolecularProfileCaseIdentifier molecularProfileCase3 = new MolecularProfileCaseIdentifier(); + molecularProfileCase3.setCaseId("sample_id_3"); + molecularProfileCase3.setMolecularProfileId("test3_mutations"); + MolecularProfileCaseIdentifier molecularProfileCase4 = new MolecularProfileCaseIdentifier(); + molecularProfileCase4.setCaseId("sample_id_4"); + molecularProfileCase4.setMolecularProfileId("test4_mutations"); + List molecularProfileCaseSet2 = new ArrayList<>(); + molecularProfileCaseSet2.add(molecularProfileCase3); + molecularProfileCaseSet2.add(molecularProfileCase4); + + Map> groupMolecularProfileCaseSets = + new HashMap>(); + groupMolecularProfileCaseSets.put("altered group", molecularProfileCaseSet1); + groupMolecularProfileCaseSets.put("unaltered group", molecularProfileCaseSet2); + + Pair, Long> alterationSampleCountByGeneList = + new Pair<>(new ArrayList<>(), 0L); + Select mutationTypes = Select.none(); + Select cnaTypes = Select.none(); + + AlterationFilter alterationFilter = new AlterationFilter(); + + // return counts for each of the two groups + for (String molecularProfileId : groupMolecularProfileCaseSets.keySet()) { + Mockito.when( + alterationCountService.getSampleAlterationGeneCounts( + groupMolecularProfileCaseSets.get(molecularProfileId), + Select.all(), + true, + true, + alterationFilter)) + .thenReturn(alterationSampleCountByGeneList); + } + + List expectedAlterationEnrichments = new ArrayList<>(); + Mockito.when(alterationEnrichmentUtil.createAlterationEnrichments(new HashMap<>())) + .thenReturn(expectedAlterationEnrichments); + + List result = + alterationEnrichmentService.getAlterationEnrichments( + groupMolecularProfileCaseSets, EnrichmentType.SAMPLE, alterationFilter); + Assert.assertEquals(result, expectedAlterationEnrichments); + } +} diff --git a/src/test/java/org/cbioportal/legacy/service/impl/BaseServiceImplTest.java b/src/test/java/org/cbioportal/legacy/service/impl/BaseServiceImplTest.java new file mode 100644 index 00000000000..28636bbd9bc --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/service/impl/BaseServiceImplTest.java @@ -0,0 +1,69 @@ +package org.cbioportal.legacy.service.impl; + +public class BaseServiceImplTest { + + public static final String PROJECTION = "projection"; + public static final Integer PAGE_SIZE = 1000; + public static final Integer PAGE_NUMBER = 0; + public static final String SORT = "sort"; + public static final String DIRECTION = "direction"; + public static final String STUDY_ID = "study_id"; + public static final String MOLECULAR_PROFILE_ID = "molecular_profile_id"; + public static final String MOLECULAR_PROFILE_ID_A = "molecular_profile_id_a"; + public static final String MOLECULAR_PROFILE_ID_B = "molecular_profile_id_b"; + public static final String SAMPLE_ID1 = "sample_id1"; + public static final String SAMPLE_ID2 = "sample_id2"; + public static final String SAMPLE_ID3 = "sample_id3"; + public static final String SAMPLE_ID4 = "sample_id4"; + public static final String PATIENT_ID_1 = "patient_id1"; + public static final String PATIENT_ID_2 = "patient_id2"; + public static final String PATIENT_ID_3 = "patient_id3"; + public static final String CLINICAL_ATTRIBUTE_ID_1 = "attribute_id1"; + public static final String CLINICAL_ATTRIBUTE_ID_2 = "attribute_id2"; + public static final String CLINICAL_ATTRIBUTE_ID_3 = "attribute_id3"; + public static final String CANCER_TYPE_ID = "cancer_type_id"; + public static final String CLINICAL_DATA_TYPE = "clinical_data_type"; + public static final Integer ENTREZ_GENE_ID_1 = 1; + public static final Integer ENTREZ_GENE_ID_2 = 2; + public static final Integer ENTREZ_GENE_ID_3 = 3; + public static final Integer ENTREZ_GENE_ID_4 = 4; + public static final Integer GENETIC_ENTITY_ID_1 = 1; + public static final Integer GENETIC_ENTITY_ID_2 = 2; + public static final Integer GENETIC_ENTITY_ID_3 = 3; + public static final Integer GENETIC_ENTITY_ID_4 = 4; + public static final Integer REFERENCE_GENOME_ID = 1; + public static final String GENESET_ID1 = "geneset_id1"; + public static final String GENESET_ID2 = "geneset_id2"; + public static final String HUGO_GENE_SYMBOL = "hugo_gene_symbol"; + public static final String SAMPLE_LIST_ID = "sample_list_id"; + public static final String ALIAS = "alias"; + public static final String GENE_ID_TYPE = "gene_id_type"; + public static final String KEYWORD = "keyword"; + public static final Long GISTIC_ROI_ID = 1L; + public static final Long CLINICAL_EVENT_ID = 1L; + public static final Integer PROTEIN_POS_START = 1; + public static final Integer PROTEIN_POS_END = 2; + public static final String GENE_PANEL_ID = "gene_panel_id"; + public static final Integer SAMPLE_INTERNAL_ID = 1; + public static final Integer SAMPLE_INTERNAL_ID2 = 2; + public static final String SEQUENCED_LIST_SUFFIX = "_sequenced"; + public static final String SORT_ORDER1 = "ASC"; + public static final String SORT_ORDER2 = "DESC"; + public static final Float PIVOT_POINT1 = 1f; + public static final Float PIVOT_POINT2 = 2f; + public static final String HUGO_GENE_SYMBOL_1 = "HUGO1"; + public static final String HUGO_GENE_SYMBOL_2 = "HUGO2"; + public static final String HUGO_GENE_SYMBOL_3 = "HUGO3"; + public static final String STABLE_ID_1 = "stable_id1"; + public static final String STABLE_ID_2 = "stable_id2"; + public static final String CATEGORY_VALUE_1 = "category_value1"; + public static final String CATEGORY_VALUE_2 = "category_value2"; + public static final String EMPTY_VALUE_1 = ""; + public static final String EMPTY_VALUE_2 = "NA"; + public static final String PROFILE_TYPE_1 = "profile_type1"; + public static final String PROFILE_TYPE_2 = "profile_type2"; + public static final String NAMESPACE_OUTER_KEY_1 = "test1"; + public static final String NAMESPACE_OUTER_KEY_2 = "test2"; + public static final String NAMESPACE_INNER_KEY_1 = "annotation1"; + public static final String NAMESPACE_INNER_KEY_2 = "annotation2"; +} diff --git a/src/test/java/org/cbioportal/legacy/service/impl/CacheServiceImplTest.java b/src/test/java/org/cbioportal/legacy/service/impl/CacheServiceImplTest.java new file mode 100644 index 00000000000..4e5fedc2306 --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/service/impl/CacheServiceImplTest.java @@ -0,0 +1,118 @@ +package org.cbioportal.legacy.service.impl; + +import static org.mockito.Mockito.*; + +import java.util.Arrays; +import java.util.List; +import org.cbioportal.legacy.model.CancerStudy; +import org.cbioportal.legacy.persistence.StudyRepository; +import org.cbioportal.legacy.persistence.cachemaputil.StaticRefCacheMapUtil; +import org.cbioportal.legacy.persistence.util.CacheUtils; +import org.cbioportal.legacy.service.exception.CacheOperationException; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnitRunner; +import org.springframework.cache.Cache; +import org.springframework.cache.CacheManager; +import org.springframework.test.util.ReflectionTestUtils; + +@RunWith(MockitoJUnitRunner.class) +public class CacheServiceImplTest { + + @InjectMocks private CacheServiceImpl cachingService; + + @Mock private CacheManager cacheManager; + + @Mock private StaticRefCacheMapUtil cacheMapUtil; + + @Mock private CacheUtils cacheUtils; + + private Cache mockCache; + private String clearAllKeysRegex = ".*"; + + @Mock private StudyRepository studyRepository; + + @Before + public void init() { + when(cacheManager.getCacheNames()).thenReturn(Arrays.asList("name_1", "name_2")); + CancerStudy cancerStudy1 = mock(CancerStudy.class); + when(cancerStudy1.getCancerStudyIdentifier()).thenReturn("study1"); + CancerStudy cancerStudy2 = mock(CancerStudy.class); + when(cancerStudy2.getCancerStudyIdentifier()).thenReturn("study2"); + List studies = Arrays.asList(cancerStudy1, cancerStudy2); + when(studyRepository.getAllStudies( + nullable(String.class), + nullable(String.class), + nullable(Integer.class), + nullable(Integer.class), + nullable(String.class), + nullable(String.class))) + .thenReturn(studies); + } + + @Test + public void evictAllCachesSuccess() throws Exception { + cachingService.clearCaches(true); + verify(cacheUtils, times(2)).evictByPattern(anyString(), eq(clearAllKeysRegex)); + verify(cacheMapUtil, times(1)).initializeCacheMemory(); + } + + @Test + public void evictAllCachesNullManager() throws Exception { + ReflectionTestUtils.setField(cachingService, "cacheManager", null); + cachingService.clearCaches(true); + verify(cacheUtils, never()).evictByPattern(anyString(), anyString()); + verify(cacheMapUtil, times(1)).initializeCacheMemory(); + ReflectionTestUtils.setField(cachingService, "cacheManager", cacheManager); + } + + @Test + public void evictAllCachesSkipSpringManagedCache() throws Exception { + cachingService.clearCaches(false); + verify(cacheUtils, never()).evictByPattern(anyString(), anyString()); + verify(cacheMapUtil, times(1)).initializeCacheMemory(); + } + + @Test(expected = CacheOperationException.class) + public void evictAllCachesThrowsException() throws Exception { + doThrow(RuntimeException.class).when(cacheUtils).evictByPattern(anyString(), anyString()); + cachingService.clearCaches(true); + } + + @Test + public void evictCacheForStudySuccess() throws Exception { + List studiesInPortal = Arrays.asList("study1", "study2"); + cachingService.clearCachesForStudy("study3", true); + verify(cacheUtils, times(2)) + .evictByPattern(anyString(), eq("^(?=.*study3).*|^(?!.*study3)(?!.*study1)(?!.*study2).*")); + verify(cacheMapUtil, times(1)).initializeCacheMemory(); + } + + @Test + public void evictCacheForStudyNullManager() throws Exception { + ReflectionTestUtils.setField(cachingService, "cacheManager", null); + List studiesInPortal = Arrays.asList("study1", "study2"); + cachingService.clearCachesForStudy("study3", true); + verify(cacheUtils, never()).evictByPattern(anyString(), anyString()); + verify(cacheMapUtil, times(1)).initializeCacheMemory(); + ReflectionTestUtils.setField(cachingService, "cacheManager", cacheManager); + } + + @Test + public void evictCacheForStudySkipSpringManagedCache() throws Exception { + List studiesInPortal = Arrays.asList("study1", "study2"); + cachingService.clearCachesForStudy("study3", false); + verify(cacheUtils, never()).evictByPattern(anyString(), anyString()); + verify(cacheMapUtil, times(1)).initializeCacheMemory(); + } + + @Test(expected = CacheOperationException.class) + public void evictCacheForStudyThrowsException() throws Exception { + List studiesInPortal = Arrays.asList("study1", "study2"); + doThrow(RuntimeException.class).when(cacheUtils).evictByPattern(anyString(), anyString()); + cachingService.clearCachesForStudy("study3", true); + } +} diff --git a/src/test/java/org/cbioportal/legacy/service/impl/CancerTypeServiceImplTest.java b/src/test/java/org/cbioportal/legacy/service/impl/CancerTypeServiceImplTest.java new file mode 100644 index 00000000000..b353f04b154 --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/service/impl/CancerTypeServiceImplTest.java @@ -0,0 +1,74 @@ +package org.cbioportal.legacy.service.impl; + +import java.util.ArrayList; +import java.util.List; +import org.cbioportal.legacy.model.TypeOfCancer; +import org.cbioportal.legacy.model.meta.BaseMeta; +import org.cbioportal.legacy.persistence.CancerTypeRepository; +import org.cbioportal.legacy.service.exception.CancerTypeNotFoundException; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.junit.MockitoJUnitRunner; + +@RunWith(MockitoJUnitRunner.class) +public class CancerTypeServiceImplTest extends BaseServiceImplTest { + + @InjectMocks private CancerTypeServiceImpl cancerTypeService; + + @Mock private CancerTypeRepository cancerTypeRepository; + + @Test + public void getAllCancerTypes() throws Exception { + + List expectedTypeOfCancerList = new ArrayList<>(); + TypeOfCancer typeOfCancer = new TypeOfCancer(); + expectedTypeOfCancerList.add(typeOfCancer); + + Mockito.when( + cancerTypeRepository.getAllCancerTypes( + PROJECTION, PAGE_SIZE, PAGE_NUMBER, SORT, DIRECTION)) + .thenReturn(expectedTypeOfCancerList); + + List result = + cancerTypeService.getAllCancerTypes(PROJECTION, PAGE_SIZE, PAGE_NUMBER, SORT, DIRECTION); + + Assert.assertEquals(expectedTypeOfCancerList, result); + } + + @Test + public void getMetaCancerTypes() throws Exception { + + BaseMeta expectedBaseMeta = new BaseMeta(); + + Mockito.when(cancerTypeRepository.getMetaCancerTypes()).thenReturn(expectedBaseMeta); + + BaseMeta result = cancerTypeService.getMetaCancerTypes(); + + Assert.assertEquals(expectedBaseMeta, result); + } + + @Test(expected = CancerTypeNotFoundException.class) + public void getCancerTypeNotFound() throws Exception { + + Mockito.when(cancerTypeRepository.getCancerType(CANCER_TYPE_ID)).thenReturn(null); + + cancerTypeService.getCancerType(CANCER_TYPE_ID); + } + + @Test + public void getCancerType() throws Exception { + + TypeOfCancer expectedTypeOfCancer = new TypeOfCancer(); + + Mockito.when(cancerTypeRepository.getCancerType(CANCER_TYPE_ID)) + .thenReturn(expectedTypeOfCancer); + + TypeOfCancer result = cancerTypeService.getCancerType(CANCER_TYPE_ID); + + Assert.assertEquals(expectedTypeOfCancer, result); + } +} diff --git a/src/test/java/org/cbioportal/legacy/service/impl/ClinicalAttributeServiceImplTest.java b/src/test/java/org/cbioportal/legacy/service/impl/ClinicalAttributeServiceImplTest.java new file mode 100644 index 00000000000..661a47e72db --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/service/impl/ClinicalAttributeServiceImplTest.java @@ -0,0 +1,209 @@ +package org.cbioportal.legacy.service.impl; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import org.cbioportal.legacy.model.ClinicalAttribute; +import org.cbioportal.legacy.model.ClinicalAttributeCount; +import org.cbioportal.legacy.model.meta.BaseMeta; +import org.cbioportal.legacy.persistence.ClinicalAttributeRepository; +import org.cbioportal.legacy.service.StudyService; +import org.cbioportal.legacy.service.exception.ClinicalAttributeNotFoundException; +import org.cbioportal.legacy.service.exception.StudyNotFoundException; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.junit.MockitoJUnitRunner; +import org.springframework.test.util.ReflectionTestUtils; + +@RunWith(MockitoJUnitRunner.class) +public class ClinicalAttributeServiceImplTest extends BaseServiceImplTest { + + @InjectMocks private ClinicalAttributeServiceImpl clinicalAttributeService; + + @Mock private ClinicalAttributeRepository clinicalAttributeRepository; + @Mock private StudyService studyService; + + @Before + public void setup() { + ReflectionTestUtils.setField(clinicalAttributeService, "AUTHENTICATE", "false"); + } + + @Test + public void getAllClinicalAttributes() throws Exception { + + List expectedClinicalAttributeList = new ArrayList<>(); + ClinicalAttribute clinicalAttribute = new ClinicalAttribute(); + expectedClinicalAttributeList.add(clinicalAttribute); + + Mockito.when( + clinicalAttributeRepository.getAllClinicalAttributes( + PROJECTION, PAGE_SIZE, PAGE_NUMBER, SORT, DIRECTION)) + .thenReturn(expectedClinicalAttributeList); + + List result = + clinicalAttributeService.getAllClinicalAttributes( + PROJECTION, PAGE_SIZE, PAGE_NUMBER, SORT, DIRECTION); + + Assert.assertEquals(expectedClinicalAttributeList, result); + } + + @Test + public void getMetaClinicalAttributes() throws Exception { + + BaseMeta expectedBaseMeta = new BaseMeta(); + Mockito.when(clinicalAttributeRepository.getMetaClinicalAttributes()) + .thenReturn(expectedBaseMeta); + BaseMeta result = clinicalAttributeService.getMetaClinicalAttributes(); + + Assert.assertEquals(expectedBaseMeta, result); + } + + @Test(expected = ClinicalAttributeNotFoundException.class) + public void getClinicalAttributeNotFound() throws Exception { + + Mockito.when( + clinicalAttributeRepository.getClinicalAttribute(STUDY_ID, CLINICAL_ATTRIBUTE_ID_1)) + .thenReturn(null); + clinicalAttributeService.getClinicalAttribute(STUDY_ID, CLINICAL_ATTRIBUTE_ID_1); + } + + @Test(expected = StudyNotFoundException.class) + public void getClinicalAttributeStudyNotFound() throws Exception { + + Mockito.when(studyService.getStudy(STUDY_ID)).thenThrow(new StudyNotFoundException(STUDY_ID)); + clinicalAttributeService.getClinicalAttribute(STUDY_ID, CLINICAL_ATTRIBUTE_ID_1); + } + + @Test + public void getClinicalAttribute() throws Exception { + + ClinicalAttribute expectedClinicalAttribute = new ClinicalAttribute(); + + Mockito.when( + clinicalAttributeRepository.getClinicalAttribute(STUDY_ID, CLINICAL_ATTRIBUTE_ID_1)) + .thenReturn(expectedClinicalAttribute); + + ClinicalAttribute result = + clinicalAttributeService.getClinicalAttribute(STUDY_ID, CLINICAL_ATTRIBUTE_ID_1); + + Assert.assertEquals(expectedClinicalAttribute, result); + } + + @Test + public void getAllClinicalAttributesInStudy() throws Exception { + + List expectedClinicalAttributeList = new ArrayList<>(); + ClinicalAttribute clinicalAttribute = new ClinicalAttribute(); + expectedClinicalAttributeList.add(clinicalAttribute); + + Mockito.when( + clinicalAttributeRepository.getAllClinicalAttributesInStudy( + STUDY_ID, PROJECTION, PAGE_SIZE, PAGE_NUMBER, SORT, DIRECTION)) + .thenReturn(expectedClinicalAttributeList); + + List result = + clinicalAttributeService.getAllClinicalAttributesInStudy( + STUDY_ID, PROJECTION, PAGE_SIZE, PAGE_NUMBER, SORT, DIRECTION); + + Assert.assertEquals(expectedClinicalAttributeList, result); + } + + @Test(expected = StudyNotFoundException.class) + public void getAllClinicalAttributesInStudyNotFound() throws Exception { + + Mockito.when(studyService.getStudy(STUDY_ID)).thenThrow(new StudyNotFoundException(STUDY_ID)); + clinicalAttributeService.getAllClinicalAttributesInStudy( + STUDY_ID, PROJECTION, PAGE_SIZE, PAGE_NUMBER, SORT, DIRECTION); + } + + @Test + public void getMetaClinicalAttributesInStudy() throws Exception { + + BaseMeta expectedBaseMeta = new BaseMeta(); + Mockito.when(clinicalAttributeRepository.getMetaClinicalAttributesInStudy(STUDY_ID)) + .thenReturn(expectedBaseMeta); + BaseMeta result = clinicalAttributeService.getMetaClinicalAttributesInStudy(STUDY_ID); + + Assert.assertEquals(expectedBaseMeta, result); + } + + @Test(expected = StudyNotFoundException.class) + public void getMetaClinicalAttributesInStudyNotFound() throws Exception { + + Mockito.when(studyService.getStudy(STUDY_ID)).thenThrow(new StudyNotFoundException(STUDY_ID)); + clinicalAttributeService.getMetaClinicalAttributesInStudy(STUDY_ID); + } + + @Test + public void fetchClinicalAttributes() throws Exception { + + List expectedClinicalAttributeList = new ArrayList<>(); + ClinicalAttribute clinicalAttribute = new ClinicalAttribute(); + expectedClinicalAttributeList.add(clinicalAttribute); + + Mockito.when( + clinicalAttributeRepository.fetchClinicalAttributes( + Arrays.asList(STUDY_ID), PROJECTION)) + .thenReturn(expectedClinicalAttributeList); + + List result = + clinicalAttributeService.fetchClinicalAttributes(Arrays.asList(STUDY_ID), PROJECTION); + + Assert.assertEquals(expectedClinicalAttributeList, result); + } + + @Test + public void fetchMetaClinicalAttributes() throws Exception { + + BaseMeta expectedBaseMeta = new BaseMeta(); + Mockito.when(clinicalAttributeRepository.fetchMetaClinicalAttributes(Arrays.asList(STUDY_ID))) + .thenReturn(expectedBaseMeta); + BaseMeta result = clinicalAttributeService.fetchMetaClinicalAttributes(Arrays.asList(STUDY_ID)); + + Assert.assertEquals(expectedBaseMeta, result); + } + + @Test + public void getClinicalAttributeCountsBySampleIds() throws Exception { + + List sampleIds = new ArrayList<>(); + List studyIds = new ArrayList<>(); + sampleIds.add(SAMPLE_ID1); + studyIds.add(STUDY_ID); + + List expectedClinicalAttributeCounts = new ArrayList<>(); + ClinicalAttributeCount clinicalAttributeCount = new ClinicalAttributeCount(); + expectedClinicalAttributeCounts.add(clinicalAttributeCount); + + Mockito.when( + clinicalAttributeRepository.getClinicalAttributeCountsBySampleIds(sampleIds, studyIds)) + .thenReturn(expectedClinicalAttributeCounts); + + List result = + clinicalAttributeService.getClinicalAttributeCountsBySampleIds(sampleIds, studyIds); + + Assert.assertEquals(expectedClinicalAttributeCounts, result); + } + + @Test + public void getClinicalAttributeCountsBySampleListId() throws Exception { + + List expectedClinicalAttributeList = new ArrayList<>(); + ClinicalAttributeCount clinicalAttributeCount = new ClinicalAttributeCount(); + expectedClinicalAttributeList.add(clinicalAttributeCount); + + Mockito.when( + clinicalAttributeRepository.getClinicalAttributeCountsBySampleListId(SAMPLE_LIST_ID)) + .thenReturn(expectedClinicalAttributeList); + + List result = + clinicalAttributeService.getClinicalAttributeCountsBySampleListId(SAMPLE_LIST_ID); + + Assert.assertEquals(expectedClinicalAttributeList, result); + } +} diff --git a/src/test/java/org/cbioportal/legacy/service/impl/ClinicalDataServiceImplTest.java b/src/test/java/org/cbioportal/legacy/service/impl/ClinicalDataServiceImplTest.java new file mode 100755 index 00000000000..94314fbee4e --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/service/impl/ClinicalDataServiceImplTest.java @@ -0,0 +1,558 @@ +package org.cbioportal.legacy.service.impl; + +import static org.mockito.Mockito.when; + +import java.util.*; +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.cbioportal.legacy.model.ClinicalAttribute; +import org.cbioportal.legacy.model.ClinicalData; +import org.cbioportal.legacy.model.ClinicalDataCount; +import org.cbioportal.legacy.model.ClinicalDataCountItem; +import org.cbioportal.legacy.model.Patient; +import org.cbioportal.legacy.model.SampleClinicalDataCollection; +import org.cbioportal.legacy.model.meta.BaseMeta; +import org.cbioportal.legacy.persistence.ClinicalDataRepository; +import org.cbioportal.legacy.service.ClinicalAttributeService; +import org.cbioportal.legacy.service.PatientService; +import org.cbioportal.legacy.service.SampleService; +import org.cbioportal.legacy.service.StudyService; +import org.cbioportal.legacy.service.exception.PatientNotFoundException; +import org.cbioportal.legacy.service.exception.SampleNotFoundException; +import org.cbioportal.legacy.service.exception.StudyNotFoundException; +import org.cbioportal.legacy.service.util.ClinicalAttributeUtil; +import org.cbioportal.legacy.utils.Encoder; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Spy; +import org.mockito.junit.MockitoJUnitRunner; + +@RunWith(MockitoJUnitRunner.class) +public class ClinicalDataServiceImplTest extends BaseServiceImplTest { + + @InjectMocks private ClinicalDataServiceImpl clinicalDataService; + + @Mock private ClinicalDataRepository clinicalDataRepository; + @Mock private StudyService studyService; + @Mock private PatientService patientService; + @Mock private SampleService sampleService; + @Mock private ClinicalAttributeService clinicalAttributeService; + @Spy private ClinicalAttributeUtil clinicalAttributeUtil = new ClinicalAttributeUtil(); + + ClinicalData datum1 = new ClinicalData(); + ClinicalData datum2 = new ClinicalData(); + String uniqueKeySample1; + String uniqueKeySample2; + List sampleStudyIds = Arrays.asList(STUDY_ID, STUDY_ID, STUDY_ID); + List sampleIds = Arrays.asList(SAMPLE_ID1, SAMPLE_ID2, SAMPLE_ID3); + + Integer pageSize = 2; + Integer pageNumber = 0; + String searchTerm = "mySearch"; + String sortBy = "column name"; + String direction = "ASC"; + List sampleInternalIds = Arrays.asList(0, 1); + List sampleInternalIdsAll = Arrays.asList(0, 1, 2, 3); + + @Before + public void init() { + + datum1.setSampleId("SampleA"); + datum1.setStudyId("Study1"); + uniqueKeySample1 = Encoder.calculateBase64("SampleA", "Study1"); + + datum2.setSampleId("SampleA"); + datum2.setStudyId("Study2"); + uniqueKeySample2 = Encoder.calculateBase64("SampleA", "Study2"); + } + + @Test + public void getAllClinicalDataOfSampleInStudy() throws Exception { + + List expectedSampleClinicalDataList = new ArrayList<>(); + ClinicalData sampleClinicalData = new ClinicalData(); + expectedSampleClinicalDataList.add(sampleClinicalData); + + when(clinicalDataRepository.getAllClinicalDataOfSampleInStudy( + STUDY_ID, + SAMPLE_ID1, + CLINICAL_ATTRIBUTE_ID_1, + PROJECTION, + PAGE_SIZE, + PAGE_NUMBER, + SORT, + DIRECTION)) + .thenReturn(expectedSampleClinicalDataList); + + List result = + clinicalDataService.getAllClinicalDataOfSampleInStudy( + STUDY_ID, + SAMPLE_ID1, + CLINICAL_ATTRIBUTE_ID_1, + PROJECTION, + PAGE_SIZE, + PAGE_NUMBER, + SORT, + DIRECTION); + + Assert.assertEquals(expectedSampleClinicalDataList, result); + } + + @Test(expected = SampleNotFoundException.class) + public void getAllClinicalDataOfSampleInStudySampleNotFound() throws Exception { + + when(sampleService.getSampleInStudy(STUDY_ID, SAMPLE_ID1)) + .thenThrow(new SampleNotFoundException(STUDY_ID, SAMPLE_ID1)); + clinicalDataService.getAllClinicalDataOfSampleInStudy( + STUDY_ID, + SAMPLE_ID1, + CLINICAL_ATTRIBUTE_ID_1, + PROJECTION, + PAGE_SIZE, + PAGE_NUMBER, + SORT, + DIRECTION); + } + + @Test + public void getMetaSampleClinicalData() throws Exception { + + BaseMeta expectedBaseMeta = new BaseMeta(); + + when(clinicalDataRepository.getMetaSampleClinicalData( + STUDY_ID, SAMPLE_ID1, CLINICAL_ATTRIBUTE_ID_1)) + .thenReturn(expectedBaseMeta); + + BaseMeta result = + clinicalDataService.getMetaSampleClinicalData( + STUDY_ID, SAMPLE_ID1, CLINICAL_ATTRIBUTE_ID_1); + + Assert.assertEquals(expectedBaseMeta, result); + } + + @Test(expected = SampleNotFoundException.class) + public void getMetaSampleClinicalDataSampleNotFound() throws Exception { + + when(sampleService.getSampleInStudy(STUDY_ID, SAMPLE_ID1)) + .thenThrow(new SampleNotFoundException(STUDY_ID, SAMPLE_ID1)); + clinicalDataService.getMetaSampleClinicalData(STUDY_ID, SAMPLE_ID1, CLINICAL_ATTRIBUTE_ID_1); + } + + @Test + public void getAllClinicalDataOfPatientInStudy() throws Exception { + + List expectedPatientClinicalDataList = new ArrayList<>(); + ClinicalData patientClinicalData = new ClinicalData(); + expectedPatientClinicalDataList.add(patientClinicalData); + + when(clinicalDataRepository.getAllClinicalDataOfPatientInStudy( + STUDY_ID, + PATIENT_ID_1, + CLINICAL_ATTRIBUTE_ID_1, + PROJECTION, + PAGE_SIZE, + PAGE_NUMBER, + SORT, + DIRECTION)) + .thenReturn(expectedPatientClinicalDataList); + + List result = + clinicalDataService.getAllClinicalDataOfPatientInStudy( + STUDY_ID, + PATIENT_ID_1, + CLINICAL_ATTRIBUTE_ID_1, + PROJECTION, + PAGE_SIZE, + PAGE_NUMBER, + SORT, + DIRECTION); + + Assert.assertEquals(expectedPatientClinicalDataList, result); + } + + @Test(expected = PatientNotFoundException.class) + public void getAllClinicalDataOfPatientInStudyPatientNotFound() throws Exception { + + when(patientService.getPatientInStudy(STUDY_ID, PATIENT_ID_1)) + .thenThrow(new PatientNotFoundException(STUDY_ID, PATIENT_ID_1)); + clinicalDataService.getAllClinicalDataOfPatientInStudy( + STUDY_ID, + PATIENT_ID_1, + CLINICAL_ATTRIBUTE_ID_1, + PROJECTION, + PAGE_SIZE, + PAGE_NUMBER, + SORT, + DIRECTION); + } + + @Test + public void getMetaPatientClinicalData() throws Exception { + + BaseMeta expectedBaseMeta = new BaseMeta(); + + when(clinicalDataRepository.getMetaPatientClinicalData( + STUDY_ID, PATIENT_ID_1, CLINICAL_ATTRIBUTE_ID_1)) + .thenReturn(expectedBaseMeta); + + BaseMeta result = + clinicalDataService.getMetaPatientClinicalData( + STUDY_ID, PATIENT_ID_1, CLINICAL_ATTRIBUTE_ID_1); + + Assert.assertEquals(expectedBaseMeta, result); + } + + @Test(expected = PatientNotFoundException.class) + public void getMetaPatientClinicalDataPatientNotFound() throws Exception { + + when(patientService.getPatientInStudy(STUDY_ID, PATIENT_ID_1)) + .thenThrow(new PatientNotFoundException(STUDY_ID, PATIENT_ID_1)); + clinicalDataService.getMetaPatientClinicalData(STUDY_ID, PATIENT_ID_1, CLINICAL_ATTRIBUTE_ID_1); + } + + @Test + public void getAllClinicalDataInStudy() throws Exception { + + List expectedSampleClinicalDataList = new ArrayList<>(); + ClinicalData sampleClinicalData = new ClinicalData(); + expectedSampleClinicalDataList.add(sampleClinicalData); + + when(clinicalDataRepository.getAllClinicalDataInStudy( + STUDY_ID, + CLINICAL_ATTRIBUTE_ID_1, + CLINICAL_DATA_TYPE, + PROJECTION, + PAGE_SIZE, + PAGE_NUMBER, + SORT, + DIRECTION)) + .thenReturn(expectedSampleClinicalDataList); + + List result = + clinicalDataService.getAllClinicalDataInStudy( + STUDY_ID, + CLINICAL_ATTRIBUTE_ID_1, + CLINICAL_DATA_TYPE, + PROJECTION, + PAGE_SIZE, + PAGE_NUMBER, + SORT, + DIRECTION); + + Assert.assertEquals(expectedSampleClinicalDataList, result); + } + + @Test(expected = StudyNotFoundException.class) + public void getAllClinicalDataInStudyNotFound() throws Exception { + + when(studyService.getStudy(STUDY_ID)).thenThrow(new StudyNotFoundException(STUDY_ID)); + clinicalDataService.getAllClinicalDataInStudy( + STUDY_ID, + CLINICAL_ATTRIBUTE_ID_1, + CLINICAL_DATA_TYPE, + PROJECTION, + PAGE_SIZE, + PAGE_NUMBER, + SORT, + DIRECTION); + } + + @Test + public void getMetaAllClinicalData() throws Exception { + + BaseMeta expectedBaseMeta = new BaseMeta(); + expectedBaseMeta.setTotalCount(5); + + when(clinicalDataRepository.getMetaAllClinicalData( + STUDY_ID, CLINICAL_ATTRIBUTE_ID_1, CLINICAL_DATA_TYPE)) + .thenReturn(expectedBaseMeta); + + BaseMeta result = + clinicalDataService.getMetaAllClinicalData( + STUDY_ID, CLINICAL_ATTRIBUTE_ID_1, CLINICAL_DATA_TYPE); + + Assert.assertEquals((Integer) 5, result.getTotalCount()); + } + + @Test(expected = StudyNotFoundException.class) + public void getMetaAllClinicalDataStudyNotFound() throws Exception { + + when(studyService.getStudy(STUDY_ID)).thenThrow(new StudyNotFoundException(STUDY_ID)); + clinicalDataService.getMetaAllClinicalData( + STUDY_ID, CLINICAL_ATTRIBUTE_ID_1, CLINICAL_DATA_TYPE); + } + + @Test + public void fetchClinicalDataPatientClinicalDataType() throws Exception { + + List studyIds = new ArrayList<>(); + studyIds.add(STUDY_ID); + List patientIds = new ArrayList<>(); + patientIds.add(PATIENT_ID_1); + + List expectedPatientClinicalDataList = new ArrayList<>(); + ClinicalData patientClinicalData = new ClinicalData(); + expectedPatientClinicalDataList.add(patientClinicalData); + + when(clinicalDataRepository.fetchClinicalData( + studyIds, + patientIds, + Arrays.asList(CLINICAL_ATTRIBUTE_ID_1), + CLINICAL_DATA_TYPE, + PROJECTION)) + .thenReturn(expectedPatientClinicalDataList); + + List result = + clinicalDataService.fetchClinicalData( + studyIds, + patientIds, + Arrays.asList(CLINICAL_ATTRIBUTE_ID_1), + CLINICAL_DATA_TYPE, + PROJECTION); + + Assert.assertEquals(expectedPatientClinicalDataList, result); + } + + @Test + public void fetchMetaClinicalDataPatientClinicalDataType() throws Exception { + + List studyIds = new ArrayList<>(); + studyIds.add(STUDY_ID); + List patientIds = new ArrayList<>(); + patientIds.add(PATIENT_ID_1); + + BaseMeta expectedBaseMeta = new BaseMeta(); + expectedBaseMeta.setTotalCount(5); + + when(clinicalDataRepository.fetchMetaClinicalData( + studyIds, patientIds, Arrays.asList(CLINICAL_ATTRIBUTE_ID_1), CLINICAL_DATA_TYPE)) + .thenReturn(expectedBaseMeta); + + BaseMeta result = + clinicalDataService.fetchMetaClinicalData( + studyIds, patientIds, Arrays.asList(CLINICAL_ATTRIBUTE_ID_1), CLINICAL_DATA_TYPE); + + Assert.assertEquals((Integer) 5, result.getTotalCount()); + } + + @Test + public void fetchClinicalDataCounts() throws Exception { + + ClinicalAttribute clinicalAttribute1 = new ClinicalAttribute(); + clinicalAttribute1.setAttrId(CLINICAL_ATTRIBUTE_ID_1); + clinicalAttribute1.setPatientAttribute(true); + ClinicalAttribute clinicalAttribute2 = new ClinicalAttribute(); + clinicalAttribute2.setAttrId(CLINICAL_ATTRIBUTE_ID_2); + clinicalAttribute2.setPatientAttribute(true); + ClinicalAttribute clinicalAttribute3 = new ClinicalAttribute(); + clinicalAttribute3.setAttrId(CLINICAL_ATTRIBUTE_ID_3); + clinicalAttribute3.setPatientAttribute(false); + + ClinicalAttribute clinicalAttribute4 = new ClinicalAttribute(); + clinicalAttribute4.setAttrId(CLINICAL_ATTRIBUTE_ID_1); + clinicalAttribute4.setPatientAttribute(false); + + when(clinicalAttributeService.getClinicalAttributesByStudyIdsAndAttributeIds( + Arrays.asList(STUDY_ID, STUDY_ID, STUDY_ID), + Arrays.asList( + CLINICAL_ATTRIBUTE_ID_1, CLINICAL_ATTRIBUTE_ID_2, CLINICAL_ATTRIBUTE_ID_3))) + .thenReturn( + Arrays.asList( + clinicalAttribute1, clinicalAttribute2, clinicalAttribute3, clinicalAttribute4)); + + ClinicalDataCount clinicalDataCount2 = new ClinicalDataCount(); + clinicalDataCount2.setAttributeId(CLINICAL_ATTRIBUTE_ID_1); + clinicalDataCount2.setValue("NA"); + clinicalDataCount2.setCount(1); + ClinicalDataCount clinicalDataCount5 = new ClinicalDataCount(); + clinicalDataCount5.setAttributeId(CLINICAL_ATTRIBUTE_ID_3); + clinicalDataCount5.setValue("N/A"); + clinicalDataCount5.setCount(3); + ClinicalDataCount clinicalDataCount6 = new ClinicalDataCount(); + clinicalDataCount6.setAttributeId(CLINICAL_ATTRIBUTE_ID_1); + clinicalDataCount6.setValue("value1"); + clinicalDataCount6.setCount(2); + + when(clinicalDataRepository.fetchClinicalDataCounts( + Arrays.asList(STUDY_ID, STUDY_ID, STUDY_ID), + Arrays.asList(SAMPLE_ID1, SAMPLE_ID2, SAMPLE_ID3), + Arrays.asList(CLINICAL_ATTRIBUTE_ID_3, CLINICAL_ATTRIBUTE_ID_1), + "SAMPLE", + "SUMMARY")) + .thenReturn(Arrays.asList(clinicalDataCount2, clinicalDataCount5, clinicalDataCount6)); + + ClinicalDataCount clinicalDataCount3 = new ClinicalDataCount(); + clinicalDataCount3.setAttributeId(CLINICAL_ATTRIBUTE_ID_2); + clinicalDataCount3.setValue("value2"); + clinicalDataCount3.setCount(1); + ClinicalDataCount clinicalDataCount4 = new ClinicalDataCount(); + clinicalDataCount4.setAttributeId(CLINICAL_ATTRIBUTE_ID_2); + clinicalDataCount4.setValue("value3"); + clinicalDataCount4.setCount(1); + + when(clinicalDataRepository.fetchClinicalDataCounts( + Arrays.asList(STUDY_ID, STUDY_ID, STUDY_ID), + Arrays.asList(SAMPLE_ID1, SAMPLE_ID2, SAMPLE_ID3), + Arrays.asList(CLINICAL_ATTRIBUTE_ID_2), + "PATIENT", + "SUMMARY")) + .thenReturn(Arrays.asList(clinicalDataCount3, clinicalDataCount4)); + + ClinicalDataCount clinicalDataCount1 = new ClinicalDataCount(); + clinicalDataCount1.setAttributeId(CLINICAL_ATTRIBUTE_ID_1); + clinicalDataCount1.setValue("value1"); + clinicalDataCount1.setCount(2); + + when(clinicalDataRepository.fetchClinicalDataCounts( + Arrays.asList(STUDY_ID, STUDY_ID, STUDY_ID), + Arrays.asList(SAMPLE_ID1, SAMPLE_ID2, SAMPLE_ID3), + Arrays.asList(CLINICAL_ATTRIBUTE_ID_1), + "PATIENT", + "DETAILED")) + .thenReturn(Arrays.asList(clinicalDataCount1)); + + List patients = new ArrayList<>(); + Patient patient1 = new Patient(); + patient1.setStableId(PATIENT_ID_1); + patient1.setCancerStudyIdentifier(STUDY_ID); + patients.add(patient1); + Patient patient2 = new Patient(); + patient2.setStableId(PATIENT_ID_2); + patient2.setCancerStudyIdentifier(STUDY_ID); + patients.add(patient2); + Patient patient3 = new Patient(); + patient3.setStableId(PATIENT_ID_3); + patient3.setCancerStudyIdentifier(STUDY_ID); + patients.add(patient3); + + when(patientService.getPatientsOfSamples( + Arrays.asList(STUDY_ID, STUDY_ID, STUDY_ID), + Arrays.asList(SAMPLE_ID1, SAMPLE_ID2, SAMPLE_ID3))) + .thenReturn(patients); + + List result = + clinicalDataService.fetchClinicalDataCounts( + Arrays.asList(STUDY_ID, STUDY_ID, STUDY_ID), + Arrays.asList(SAMPLE_ID1, SAMPLE_ID2, SAMPLE_ID3), + Arrays.asList( + CLINICAL_ATTRIBUTE_ID_1, CLINICAL_ATTRIBUTE_ID_2, CLINICAL_ATTRIBUTE_ID_3)); + + Assert.assertEquals(3, result.size()); + + ClinicalDataCountItem counts3 = result.get(0); + Assert.assertEquals(CLINICAL_ATTRIBUTE_ID_3, counts3.getAttributeId()); + List clinicalDataCounts3 = counts3.getCounts(); + Assert.assertEquals(1, clinicalDataCounts3.size()); + ClinicalDataCount count5 = clinicalDataCounts3.get(0); + Assert.assertEquals(CLINICAL_ATTRIBUTE_ID_3, count5.getAttributeId()); + Assert.assertEquals("NA", count5.getValue()); + Assert.assertEquals((Integer) 3, count5.getCount()); + + ClinicalDataCountItem counts2 = result.get(1); + Assert.assertEquals(CLINICAL_ATTRIBUTE_ID_2, counts2.getAttributeId()); + List clinicalDataCounts2 = counts2.getCounts(); + Assert.assertEquals(3, clinicalDataCounts2.size()); + ClinicalDataCount count3 = clinicalDataCounts2.get(0); + Assert.assertEquals(CLINICAL_ATTRIBUTE_ID_2, count3.getAttributeId()); + Assert.assertEquals("value2", count3.getValue()); + Assert.assertEquals((Integer) 1, count3.getCount()); + ClinicalDataCount count4 = clinicalDataCounts2.get(1); + Assert.assertEquals(CLINICAL_ATTRIBUTE_ID_2, count4.getAttributeId()); + Assert.assertEquals("value3", count4.getValue()); + Assert.assertEquals((Integer) 1, count4.getCount()); + + ClinicalDataCountItem counts1 = result.get(2); + Assert.assertEquals(CLINICAL_ATTRIBUTE_ID_1, counts1.getAttributeId()); + List clinicalDataCounts1 = counts1.getCounts(); + Assert.assertEquals(1, clinicalDataCounts1.size()); + ClinicalDataCount count1 = clinicalDataCounts1.get(0); + Assert.assertEquals(CLINICAL_ATTRIBUTE_ID_1, count1.getAttributeId()); + Assert.assertEquals("value1", count1.getValue()); + Assert.assertEquals((Integer) 4, count1.getCount()); + } + + @Test + public void fetchSampleClinicalTableHappyCase() { + + when(clinicalDataRepository.getVisibleSampleInternalIdsForClinicalTable( + sampleStudyIds, sampleIds, null, null, searchTerm, sortBy, direction)) + .thenReturn(sampleInternalIdsAll); + + when(clinicalDataRepository.getSampleClinicalDataBySampleInternalIds(sampleInternalIds)) + .thenReturn(List.of(datum1, datum2)); + when(clinicalDataRepository.getPatientClinicalDataBySampleInternalIds(sampleInternalIds)) + .thenReturn(List.of(datum1, datum2)); + + ImmutablePair result = + clinicalDataService.fetchSampleClinicalTable( + sampleStudyIds, sampleIds, pageSize, pageNumber, searchTerm, sortBy, direction); + SampleClinicalDataCollection clinicalDataCollection = result.getLeft(); + Integer itemCount = result.getRight(); + + Assert.assertEquals(4, (int) itemCount); + Assert.assertEquals(2, clinicalDataCollection.getByUniqueSampleKey().size()); + Assert.assertTrue(clinicalDataCollection.getByUniqueSampleKey().containsKey(uniqueKeySample1)); + Assert.assertTrue(clinicalDataCollection.getByUniqueSampleKey().containsKey(uniqueKeySample2)); + Assert.assertEquals( + 2, clinicalDataCollection.getByUniqueSampleKey().get(uniqueKeySample1).size()); + Assert.assertEquals( + 2, clinicalDataCollection.getByUniqueSampleKey().get(uniqueKeySample2).size()); + Assert.assertEquals( + "SampleA", + clinicalDataCollection.getByUniqueSampleKey().get(uniqueKeySample1).get(0).getSampleId()); + Assert.assertEquals( + "Study1", + clinicalDataCollection.getByUniqueSampleKey().get(uniqueKeySample1).get(0).getStudyId()); + Assert.assertEquals( + "SampleA", + clinicalDataCollection.getByUniqueSampleKey().get(uniqueKeySample2).get(0).getSampleId()); + Assert.assertEquals( + "Study2", + clinicalDataCollection.getByUniqueSampleKey().get(uniqueKeySample2).get(0).getStudyId()); + } + + @Test + public void fetchSampleClinicalTableEmptyIdLists() { + Assert.assertEquals( + 0, + clinicalDataService + .fetchSampleClinicalTable( + null, sampleIds, pageSize, pageNumber, searchTerm, sortBy, direction) + .getLeft() + .getByUniqueSampleKey() + .size()); + Assert.assertEquals( + 0, + clinicalDataService + .fetchSampleClinicalTable( + sampleStudyIds, null, pageSize, pageNumber, searchTerm, sortBy, direction) + .getLeft() + .getByUniqueSampleKey() + .size()); + Assert.assertEquals( + 0, + clinicalDataService + .fetchSampleClinicalTable( + new ArrayList<>(), sampleIds, pageSize, pageNumber, searchTerm, sortBy, direction) + .getLeft() + .getByUniqueSampleKey() + .size()); + Assert.assertEquals( + 0, + clinicalDataService + .fetchSampleClinicalTable( + sampleStudyIds, + new ArrayList<>(), + pageSize, + pageNumber, + searchTerm, + sortBy, + direction) + .getLeft() + .getByUniqueSampleKey() + .size()); + } +} diff --git a/src/test/java/org/cbioportal/legacy/service/impl/ClinicalEventServiceImplTest.java b/src/test/java/org/cbioportal/legacy/service/impl/ClinicalEventServiceImplTest.java new file mode 100644 index 00000000000..a81767137fe --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/service/impl/ClinicalEventServiceImplTest.java @@ -0,0 +1,412 @@ +package org.cbioportal.legacy.service.impl; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.anyList; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.when; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import org.cbioportal.legacy.model.ClinicalData; +import org.cbioportal.legacy.model.ClinicalEvent; +import org.cbioportal.legacy.model.ClinicalEventData; +import org.cbioportal.legacy.model.ClinicalEventTypeCount; +import org.cbioportal.legacy.model.Patient; +import org.cbioportal.legacy.model.meta.BaseMeta; +import org.cbioportal.legacy.persistence.ClinicalEventRepository; +import org.cbioportal.legacy.service.PatientService; +import org.cbioportal.legacy.service.exception.PatientNotFoundException; +import org.cbioportal.legacy.web.parameter.ClinicalEventRequest; +import org.cbioportal.legacy.web.parameter.ClinicalEventRequestIdentifier; +import org.cbioportal.legacy.web.parameter.OccurrencePosition; +import org.cbioportal.legacy.web.parameter.SurvivalRequest; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnitRunner; + +@RunWith(MockitoJUnitRunner.class) +public class ClinicalEventServiceImplTest extends BaseServiceImplTest { + private static final String TEST_CLINICAL_EVENT_TYPE_1 = "SERVICE"; + private static final String TEST_CLINICAL_EVENT_TYPE_2 = "test_clinical_event_type_2"; + private static final String TEST_CLINICAL_EVENT_TYPE_3 = "test_clinical_event_type_3"; + private static final String TEST_SURVIVAL_PREFIX = "survival_prefix"; + + @InjectMocks private ClinicalEventServiceImpl clinicalEventService; + + @Mock private ClinicalEventRepository clinicalEventRepository; + @Mock private PatientService patientService; + + @Test + public void getAllClinicalEventsOfPatientInStudy() throws Exception { + + List expectedClinicalEventList = new ArrayList<>(); + ClinicalEvent clinicalEvent = new ClinicalEvent(); + clinicalEvent.setClinicalEventId(CLINICAL_EVENT_ID); + expectedClinicalEventList.add(clinicalEvent); + + when(clinicalEventRepository.getAllClinicalEventsOfPatientInStudy( + STUDY_ID, PATIENT_ID_1, PROJECTION, PAGE_SIZE, PAGE_NUMBER, SORT, DIRECTION)) + .thenReturn(expectedClinicalEventList); + + List expectedClinicalEventDataList = new ArrayList<>(); + ClinicalEventData clinicalEventData = new ClinicalEventData(); + clinicalEventData.setClinicalEventId(CLINICAL_EVENT_ID); + expectedClinicalEventDataList.add(clinicalEventData); + + when(clinicalEventRepository.getDataOfClinicalEvents(Arrays.asList(CLINICAL_EVENT_ID))) + .thenReturn(expectedClinicalEventDataList); + + List result = + clinicalEventService.getAllClinicalEventsOfPatientInStudy( + STUDY_ID, PATIENT_ID_1, PROJECTION, PAGE_SIZE, PAGE_NUMBER, SORT, DIRECTION); + + assertEquals(1, result.size()); + assertEquals(clinicalEvent, result.get(0)); + assertEquals(1, result.get(0).getAttributes().size()); + assertEquals(clinicalEventData, result.get(0).getAttributes().get(0)); + } + + @Test(expected = PatientNotFoundException.class) + public void getAllClinicalEventsOfPatientInStudyPatientNotFound() throws Exception { + + when(patientService.getPatientInStudy(STUDY_ID, PATIENT_ID_1)) + .thenThrow(new PatientNotFoundException(STUDY_ID, PATIENT_ID_1)); + clinicalEventService.getAllClinicalEventsOfPatientInStudy( + STUDY_ID, PATIENT_ID_1, PROJECTION, PAGE_SIZE, PAGE_NUMBER, SORT, DIRECTION); + } + + @Test + public void getMetaPatientClinicalEvents() throws Exception { + + BaseMeta expectedBaseMeta = new BaseMeta(); + when(clinicalEventRepository.getMetaPatientClinicalEvents(STUDY_ID, PATIENT_ID_1)) + .thenReturn(expectedBaseMeta); + BaseMeta result = clinicalEventService.getMetaPatientClinicalEvents(STUDY_ID, PATIENT_ID_1); + + assertEquals(expectedBaseMeta, result); + } + + @Test(expected = PatientNotFoundException.class) + public void getMetaPatientClinicalEventsPatientNotFound() throws Exception { + + when(patientService.getPatientInStudy(STUDY_ID, PATIENT_ID_1)) + .thenThrow(new PatientNotFoundException(STUDY_ID, PATIENT_ID_1)); + clinicalEventService.getMetaPatientClinicalEvents(STUDY_ID, PATIENT_ID_1); + } + + @Test + public void getAllClinicalEventsInStudy() { + + List expectedClinicalEventList = new ArrayList<>(); + ClinicalEvent clinicalEvent = new ClinicalEvent(); + clinicalEvent.setClinicalEventId(CLINICAL_EVENT_ID); + expectedClinicalEventList.add(clinicalEvent); + + when(clinicalEventRepository.getAllClinicalEventsInStudy( + STUDY_ID, PROJECTION, PAGE_SIZE, PAGE_NUMBER, SORT, DIRECTION)) + .thenReturn(expectedClinicalEventList); + + List expectedClinicalEventDataList = new ArrayList<>(); + ClinicalEventData clinicalEventData = new ClinicalEventData(); + clinicalEventData.setClinicalEventId(CLINICAL_EVENT_ID); + expectedClinicalEventDataList.add(clinicalEventData); + + when(clinicalEventRepository.getDataOfClinicalEvents(Arrays.asList(CLINICAL_EVENT_ID))) + .thenReturn(expectedClinicalEventDataList); + + List result = + clinicalEventService.getAllClinicalEventsInStudy( + STUDY_ID, PROJECTION, PAGE_SIZE, PAGE_NUMBER, SORT, DIRECTION); + + assertEquals(1, result.size()); + assertEquals(clinicalEvent, result.get(0)); + assertEquals(1, result.get(0).getAttributes().size()); + assertEquals(clinicalEventData, result.get(0).getAttributes().get(0)); + } + + @Test + public void getMetaClinicalEvents() throws Exception { + + BaseMeta expectedBaseMeta = new BaseMeta(); + when(clinicalEventRepository.getMetaClinicalEvents(STUDY_ID)).thenReturn(expectedBaseMeta); + BaseMeta result = clinicalEventService.getMetaClinicalEvents(STUDY_ID); + + assertEquals(expectedBaseMeta, result); + } + + @Test + public void getPatientsSamplesPerClinicalEventType() { + List studyIds = Arrays.asList(STUDY_ID); + List sampleIds = Arrays.asList(SAMPLE_ID1); + + Map> patientsSamplesPerEventType = new HashMap<>(); + patientsSamplesPerEventType.put(TEST_CLINICAL_EVENT_TYPE_1, new HashSet<>(sampleIds)); + + when(clinicalEventRepository.getSamplesOfPatientsPerEventTypeInStudy(anyList(), anyList())) + .thenReturn(patientsSamplesPerEventType); + + assertEquals( + patientsSamplesPerEventType, + clinicalEventService.getPatientsSamplesPerClinicalEventType(studyIds, sampleIds)); + } + + @Test + public void getClinicalEventTypeCounts() { + List studyIds = Arrays.asList(STUDY_ID); + List sampleIds = Arrays.asList(SAMPLE_ID1); + + Patient p = new Patient(); + p.setCancerStudyIdentifier(STUDY_ID); + p.setStableId(PATIENT_ID_1); + + ClinicalEvent ce = new ClinicalEvent(); + ce.setEventType(TEST_CLINICAL_EVENT_TYPE_1); + + when(patientService.getPatientsOfSamples(anyList(), anyList())).thenReturn(Arrays.asList(p)); + when(clinicalEventRepository.getPatientsDistinctClinicalEventInStudies(anyList(), anyList())) + .thenReturn(Arrays.asList(ce)); + + List eventTypeCounts = + clinicalEventService.getClinicalEventTypeCounts(studyIds, sampleIds); + assertEquals(1, eventTypeCounts.size()); + int eventTypeCount = eventTypeCounts.get(0).getCount(); + assertEquals(1, eventTypeCount); + } + + @Test + public void getSurvivalDataReturnsCorrectDataWhenEndEventsExist() { + List studyIds = List.of(STUDY_ID); + List patientIds = Arrays.asList(PATIENT_ID_1, PATIENT_ID_2, PATIENT_ID_3); + + List startClinicalEvents = new ArrayList<>(); + ClinicalEvent clinicalEvent1 = new ClinicalEvent(); + clinicalEvent1.setStudyId(STUDY_ID); + clinicalEvent1.setPatientId(PATIENT_ID_1); + clinicalEvent1.setStartDate(0); + clinicalEvent1.setStopDate(500); + + ClinicalEvent clinicalEvent2 = new ClinicalEvent(); + clinicalEvent2.setStudyId(STUDY_ID); + clinicalEvent2.setPatientId(PATIENT_ID_2); + clinicalEvent2.setStartDate(100); + clinicalEvent2.setStopDate(1000); + + ClinicalEvent clinicalEvent3 = new ClinicalEvent(); + clinicalEvent3.setStudyId(STUDY_ID); + clinicalEvent3.setPatientId(PATIENT_ID_3); + clinicalEvent3.setStartDate(1000); + clinicalEvent3.setStopDate(1200); + + startClinicalEvents.add(clinicalEvent1); + startClinicalEvents.add(clinicalEvent2); + startClinicalEvents.add(clinicalEvent3); + + List startEventMetas = new ArrayList<>(); + ClinicalEvent startEventMeta = new ClinicalEvent(); + startEventMeta.setEventType(TEST_CLINICAL_EVENT_TYPE_1); + startEventMetas.add(startEventMeta); + + when(clinicalEventRepository.getTimelineEvents(anyList(), anyList(), eq(startEventMetas))) + .thenReturn(startClinicalEvents); + + List endClinicalEvents = new ArrayList<>(); + ClinicalEvent clinicalEvent4 = new ClinicalEvent(); + clinicalEvent4.setStudyId(STUDY_ID); + clinicalEvent4.setPatientId(PATIENT_ID_1); + clinicalEvent4.setStartDate(500); + clinicalEvent4.setStopDate(1000); + + endClinicalEvents.add(clinicalEvent4); + + List endEventMetas = new ArrayList<>(); + ClinicalEvent endEventMeta = new ClinicalEvent(); + endEventMeta.setEventType(TEST_CLINICAL_EVENT_TYPE_2); + endEventMetas.add(endEventMeta); + + when(clinicalEventRepository.getTimelineEvents(anyList(), anyList(), eq(endEventMetas))) + .thenReturn(endClinicalEvents); + + List censoredClinicalEvents = new ArrayList<>(); + ClinicalEvent clinicalEvent5 = new ClinicalEvent(); + clinicalEvent5.setStudyId(STUDY_ID); + clinicalEvent5.setPatientId(PATIENT_ID_2); + clinicalEvent5.setStartDate(1000); + clinicalEvent5.setStopDate(2000); + + ClinicalEvent clinicalEvent6 = new ClinicalEvent(); + clinicalEvent6.setStudyId(STUDY_ID); + clinicalEvent6.setPatientId(PATIENT_ID_3); + clinicalEvent6.setStartDate(600); + clinicalEvent6.setStopDate(1000); + + censoredClinicalEvents.add(clinicalEvent5); + censoredClinicalEvents.add(clinicalEvent6); + + List censoredEventMetas = new ArrayList<>(); + ClinicalEvent censoredEventMeta = new ClinicalEvent(); + censoredEventMeta.setEventType(TEST_CLINICAL_EVENT_TYPE_3); + censoredEventMetas.add(censoredEventMeta); + + when(clinicalEventRepository.getTimelineEvents(anyList(), anyList(), eq(censoredEventMetas))) + .thenReturn(censoredClinicalEvents); + + SurvivalRequest survivalRequest = new SurvivalRequest(); + + ClinicalEventRequestIdentifier startEventRequestIdentifier = + new ClinicalEventRequestIdentifier(); + Set startClinicalEventRequests = new HashSet<>(); + ClinicalEventRequest clinicalEventRequest1 = new ClinicalEventRequest(); + clinicalEventRequest1.setEventType(TEST_CLINICAL_EVENT_TYPE_1); + startClinicalEventRequests.add(clinicalEventRequest1); + startEventRequestIdentifier.setClinicalEventRequests(startClinicalEventRequests); + startEventRequestIdentifier.setPosition(OccurrencePosition.FIRST); + survivalRequest.setStartEventRequestIdentifier(startEventRequestIdentifier); + + ClinicalEventRequestIdentifier endEventRequestIdentifier = new ClinicalEventRequestIdentifier(); + Set endClinicalEventRequests = new HashSet<>(); + ClinicalEventRequest clinicalEventRequest2 = new ClinicalEventRequest(); + clinicalEventRequest2.setEventType(TEST_CLINICAL_EVENT_TYPE_2); + endClinicalEventRequests.add(clinicalEventRequest2); + endEventRequestIdentifier.setClinicalEventRequests(endClinicalEventRequests); + endEventRequestIdentifier.setPosition(OccurrencePosition.LAST); + survivalRequest.setEndEventRequestIdentifier(endEventRequestIdentifier); + + ClinicalEventRequestIdentifier censoredEventRequestIdentifier = + new ClinicalEventRequestIdentifier(); + Set censoredClinicalEventRequests = new HashSet<>(); + ClinicalEventRequest clinicalEventRequest3 = new ClinicalEventRequest(); + clinicalEventRequest3.setEventType(TEST_CLINICAL_EVENT_TYPE_3); + censoredClinicalEventRequests.add(clinicalEventRequest3); + censoredEventRequestIdentifier.setClinicalEventRequests(censoredClinicalEventRequests); + censoredEventRequestIdentifier.setPosition(OccurrencePosition.LAST); + survivalRequest.setCensoredEventRequestIdentifier(censoredEventRequestIdentifier); + + List result = + clinicalEventService.getSurvivalData( + studyIds, patientIds, TEST_SURVIVAL_PREFIX, survivalRequest); + + assertEquals(4, result.size()); + assertEquals(PATIENT_ID_1, result.getFirst().getPatientId()); + assertEquals("survival_prefix_MONTHS", result.get(0).getAttrId()); + assertEquals("32.89473684210527", result.get(0).getAttrValue()); + assertEquals("survival_prefix_STATUS", result.get(1).getAttrId()); + assertEquals("1:EVENT", result.get(1).getAttrValue()); + assertEquals(PATIENT_ID_2, result.get(2).getPatientId()); + assertEquals("survival_prefix_MONTHS", result.get(2).getAttrId()); + assertEquals("62.5", result.get(2).getAttrValue()); + assertEquals("survival_prefix_STATUS", result.get(3).getAttrId()); + assertEquals("0:CENSORED", result.get(3).getAttrValue()); + } + + @Test + public void getSurvivalDataReturnsEmptyListWhenNoEventsExist() { + List studyIds = List.of(STUDY_ID); + List patientIds = Arrays.asList(PATIENT_ID_1, PATIENT_ID_2, PATIENT_ID_3); + + List clinicalEventList = new ArrayList<>(); + ClinicalEvent clinicalEvent1 = new ClinicalEvent(); + clinicalEvent1.setStudyId(STUDY_ID); + clinicalEvent1.setPatientId(PATIENT_ID_1); + clinicalEvent1.setStartDate(0); + clinicalEvent1.setStopDate(500); + + ClinicalEvent clinicalEvent2 = new ClinicalEvent(); + clinicalEvent2.setStudyId(STUDY_ID); + clinicalEvent2.setPatientId(PATIENT_ID_2); + clinicalEvent2.setStartDate(100); + clinicalEvent2.setStopDate(1000); + + clinicalEventList.add(clinicalEvent1); + clinicalEventList.add(clinicalEvent2); + + SurvivalRequest survivalRequest = new SurvivalRequest(); + + ClinicalEventRequestIdentifier startEventRequestIdentifier = + new ClinicalEventRequestIdentifier(); + Set startClinicalEventRequests = new HashSet<>(); + ClinicalEventRequest clinicalEventRequest1 = new ClinicalEventRequest(); + clinicalEventRequest1.setEventType(TEST_CLINICAL_EVENT_TYPE_1); + startClinicalEventRequests.add(clinicalEventRequest1); + startEventRequestIdentifier.setClinicalEventRequests(startClinicalEventRequests); + startEventRequestIdentifier.setPosition(OccurrencePosition.FIRST); + survivalRequest.setStartEventRequestIdentifier(startEventRequestIdentifier); + + ClinicalEventRequestIdentifier endEventRequestIdentifier = new ClinicalEventRequestIdentifier(); + Set endClinicalEventRequests = new HashSet<>(); + ClinicalEventRequest clinicalEventRequest2 = new ClinicalEventRequest(); + clinicalEventRequest2.setEventType(TEST_CLINICAL_EVENT_TYPE_2); + endClinicalEventRequests.add(clinicalEventRequest2); + endEventRequestIdentifier.setClinicalEventRequests(endClinicalEventRequests); + endEventRequestIdentifier.setPosition(OccurrencePosition.LAST); + survivalRequest.setEndEventRequestIdentifier(endEventRequestIdentifier); + + ClinicalEventRequestIdentifier censoredEventRequestIdentifier = + new ClinicalEventRequestIdentifier(); + Set censoredClinicalEventRequests = new HashSet<>(); + ClinicalEventRequest clinicalEventRequest3 = new ClinicalEventRequest(); + clinicalEventRequest3.setEventType(TEST_CLINICAL_EVENT_TYPE_3); + censoredClinicalEventRequests.add(clinicalEventRequest3); + censoredEventRequestIdentifier.setClinicalEventRequests(censoredClinicalEventRequests); + censoredEventRequestIdentifier.setPosition(OccurrencePosition.LAST); + survivalRequest.setCensoredEventRequestIdentifier(censoredEventRequestIdentifier); + + when(clinicalEventRepository.getTimelineEvents(anyList(), anyList(), anyList())) + .thenReturn(new ArrayList<>()); + + List result = + clinicalEventService.getSurvivalData( + studyIds, patientIds, TEST_SURVIVAL_PREFIX, survivalRequest); + + assertTrue(result.isEmpty()); + } + + @Test + public void getClinicalEventsMetaReturnsCorrectDataForValidInput() { + List studyIds = List.of(STUDY_ID); + List patientIds = Arrays.asList(PATIENT_ID_1, PATIENT_ID_2); + List clinicalEvents = new ArrayList<>(); + ClinicalEvent event1 = new ClinicalEvent(); + event1.setStudyId(STUDY_ID); + event1.setPatientId(PATIENT_ID_1); + ClinicalEvent event2 = new ClinicalEvent(); + event2.setStudyId(STUDY_ID); + event2.setPatientId(PATIENT_ID_2); + clinicalEvents.add(event1); + clinicalEvents.add(event2); + + when(clinicalEventRepository.getClinicalEventsMeta(anyList(), anyList(), anyList())) + .thenReturn(clinicalEvents); + + List result = + clinicalEventService.getClinicalEventsMeta(studyIds, patientIds, clinicalEvents); + + assertEquals(2, result.size()); + assertEquals("study_id", result.get(0).getStudyId()); + assertEquals("patient_id1", result.get(0).getPatientId()); + assertEquals("study_id", result.get(1).getStudyId()); + assertEquals("patient_id2", result.get(1).getPatientId()); + } + + @Test + public void getClinicalEventsMetaReturnsEmptyListForInvalidInput() { + List studyIds = List.of(STUDY_ID); + List patientIds = Arrays.asList(PATIENT_ID_1, PATIENT_ID_2); + List clinicalEvents = new ArrayList<>(); + + when(clinicalEventRepository.getClinicalEventsMeta(anyList(), anyList(), anyList())) + .thenReturn(new ArrayList<>()); + + List result = + clinicalEventService.getClinicalEventsMeta(studyIds, patientIds, clinicalEvents); + + assertTrue(result.isEmpty()); + } +} diff --git a/src/test/java/org/cbioportal/legacy/service/impl/CoExpressionServiceImplTest.java b/src/test/java/org/cbioportal/legacy/service/impl/CoExpressionServiceImplTest.java new file mode 100644 index 00000000000..a0168d233ef --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/service/impl/CoExpressionServiceImplTest.java @@ -0,0 +1,536 @@ +package org.cbioportal.legacy.service.impl; + +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.concurrent.CompletableFuture; +import org.cbioportal.legacy.model.CoExpression; +import org.cbioportal.legacy.model.EntityType; +import org.cbioportal.legacy.model.Gene; +import org.cbioportal.legacy.model.GeneMolecularData; +import org.cbioportal.legacy.model.Geneset; +import org.cbioportal.legacy.model.GenesetMolecularData; +import org.cbioportal.legacy.model.MolecularProfile; +import org.cbioportal.legacy.persistence.SampleListRepository; +import org.cbioportal.legacy.service.GeneService; +import org.cbioportal.legacy.service.GenesetDataService; +import org.cbioportal.legacy.service.GenesetService; +import org.cbioportal.legacy.service.MolecularDataService; +import org.cbioportal.legacy.service.MolecularProfileService; +import org.cbioportal.legacy.service.util.CoExpressionAsyncMethods; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.junit.MockitoJUnitRunner; + +@RunWith(MockitoJUnitRunner.Silent.class) +public class CoExpressionServiceImplTest extends BaseServiceImplTest { + + private static final double THRESHOLD = 0.3; + + @InjectMocks private CoExpressionServiceImpl coExpressionService; + + @Mock private CoExpressionAsyncMethods asyncMethods; + @Mock private MolecularDataService molecularDataService; + @Mock private GenesetDataService genesetDataService; + @Mock private GeneService geneService; + @Mock private GenesetService genesetService; + @Mock private MolecularProfileService molecularProfileService; + @Mock private SampleListRepository sampleListRepository; + + @Test + public void getGeneCorrelationForQueriedGene() throws Exception { + + List molecularDataList = createGeneMolecularData(); + Mockito.when( + molecularDataService.getMolecularData( + MOLECULAR_PROFILE_ID_A, SAMPLE_LIST_ID, null, "SUMMARY")) + .thenReturn(molecularDataList); + Mockito.when( + molecularDataService.getMolecularData( + MOLECULAR_PROFILE_ID_B, SAMPLE_LIST_ID, null, "SUMMARY")) + .thenReturn(molecularDataList); + + List genes = createGenes(); + + Mockito.when(geneService.getGene("2")).thenReturn(genes.get(0)); + + Mockito.when(geneService.getGene("3")).thenReturn(genes.get(1)); + + Mockito.when(geneService.getGene("4")).thenReturn(genes.get(2)); + + MolecularProfile geneMolecularProfile = createGeneMolecularProfile(); + + Mockito.when(molecularProfileService.getMolecularProfile(MOLECULAR_PROFILE_ID_A)) + .thenReturn(geneMolecularProfile); + Mockito.when(molecularProfileService.getMolecularProfile(MOLECULAR_PROFILE_ID_B)) + .thenReturn(geneMolecularProfile); + + List> allValuesA = createAllValuesA(); + List valuesB = createValuesB(); + List> coExpressions = createCoExpressions(); + + Mockito.when(asyncMethods.computeCoExpression("2", allValuesA.get(0), valuesB, THRESHOLD)) + .thenReturn(coExpressions.get(0)); + Mockito.when(asyncMethods.computeCoExpression("3", allValuesA.get(1), valuesB, THRESHOLD)) + .thenReturn(coExpressions.get(1)); + Mockito.when(asyncMethods.computeCoExpression("4", allValuesA.get(2), valuesB, THRESHOLD)) + .thenReturn(CompletableFuture.supplyAsync(() -> null)); + + List result = + coExpressionService.getCoExpressions( + "1", + EntityType.GENE, + SAMPLE_LIST_ID, + MOLECULAR_PROFILE_ID_A, + MOLECULAR_PROFILE_ID_B, + THRESHOLD); + + Assert.assertEquals(2, result.size()); + CoExpression coExpression1 = result.get(0); + Assert.assertEquals("2", coExpression1.getGeneticEntityId()); + Assert.assertEquals(new BigDecimal("0.5"), coExpression1.getSpearmansCorrelation()); + Assert.assertEquals(new BigDecimal("0.6666666666666667"), coExpression1.getpValue()); + CoExpression coExpression2 = result.get(1); + Assert.assertEquals("3", coExpression2.getGeneticEntityId()); + Assert.assertEquals( + new BigDecimal("0.8660254037844386"), coExpression2.getSpearmansCorrelation()); + Assert.assertEquals(new BigDecimal("0.3333333333333333"), coExpression2.getpValue()); + } + + @Test + public void fetchGeneCoExpressions() throws Exception { + + List molecularDataList = createGeneMolecularData(); + Mockito.when( + molecularDataService.fetchMolecularData( + MOLECULAR_PROFILE_ID_A, Arrays.asList(SAMPLE_ID1, SAMPLE_ID2), null, "SUMMARY")) + .thenReturn(molecularDataList); + Mockito.when( + molecularDataService.fetchMolecularData( + MOLECULAR_PROFILE_ID_B, Arrays.asList(SAMPLE_ID1, SAMPLE_ID2), null, "SUMMARY")) + .thenReturn(molecularDataList); + + List genes = createGenes(); + + Mockito.when(geneService.getGene("2")).thenReturn(genes.get(0)); + + Mockito.when(geneService.getGene("3")).thenReturn(genes.get(1)); + + Mockito.when(geneService.getGene("4")).thenReturn(genes.get(2)); + + MolecularProfile geneMolecularProfile = createGeneMolecularProfile(); + + Mockito.when(molecularProfileService.getMolecularProfile(MOLECULAR_PROFILE_ID_A)) + .thenReturn(geneMolecularProfile); + Mockito.when(molecularProfileService.getMolecularProfile(MOLECULAR_PROFILE_ID_B)) + .thenReturn(geneMolecularProfile); + + List> allValuesA = createAllValuesA(); + List valuesB = createValuesB(); + List> coExpressions = createCoExpressions(); + + Mockito.when(asyncMethods.computeCoExpression("2", allValuesA.get(0), valuesB, THRESHOLD)) + .thenReturn(coExpressions.get(0)); + Mockito.when(asyncMethods.computeCoExpression("3", allValuesA.get(1), valuesB, THRESHOLD)) + .thenReturn(coExpressions.get(1)); + Mockito.when(asyncMethods.computeCoExpression("4", allValuesA.get(2), valuesB, THRESHOLD)) + .thenReturn(CompletableFuture.supplyAsync(() -> null)); + + List result = + coExpressionService.fetchCoExpressions( + "1", + EntityType.GENE, + Arrays.asList(SAMPLE_ID1, SAMPLE_ID2), + MOLECULAR_PROFILE_ID_A, + MOLECULAR_PROFILE_ID_B, + THRESHOLD); + + Assert.assertEquals(2, result.size()); + CoExpression coExpression1 = result.get(0); + Assert.assertEquals("2", coExpression1.getGeneticEntityId()); + Assert.assertEquals(new BigDecimal("0.5"), coExpression1.getSpearmansCorrelation()); + Assert.assertEquals(new BigDecimal("0.6666666666666667"), coExpression1.getpValue()); + CoExpression coExpression2 = result.get(1); + Assert.assertEquals("3", coExpression2.getGeneticEntityId()); + Assert.assertEquals( + new BigDecimal("0.8660254037844386"), coExpression2.getSpearmansCorrelation()); + Assert.assertEquals(new BigDecimal("0.3333333333333333"), coExpression2.getpValue()); + } + + @Test + public void getGenesetCoExpressions() throws Exception { + + List molecularDataList = createGenesetMolecularData(); + Mockito.when( + genesetDataService.fetchGenesetData("profile_id_gsva_scores_a", SAMPLE_LIST_ID, null)) + .thenReturn(molecularDataList); + Mockito.when( + genesetDataService.fetchGenesetData("profile_id_gsva_scores_b", SAMPLE_LIST_ID, null)) + .thenReturn(molecularDataList); + + List genesets = createGenesets(); + + Mockito.when(genesetService.getGeneset("BIOCARTA_ASBCELL_PATHWAY")).thenReturn(genesets.get(0)); + + Mockito.when(genesetService.getGeneset("KEGG_DNA_REPLICATION")).thenReturn(genesets.get(1)); + + Mockito.when(genesetService.getGeneset("REACTOME_DIGESTION_OF_DIETARY_CARBOHYDRATE")) + .thenReturn(genesets.get(2)); + + MolecularProfile genesetMolecularProfile = createGenesetMolecularProfile(); + + Mockito.when(molecularProfileService.getMolecularProfile("profile_id_gsva_scores_a")) + .thenReturn(genesetMolecularProfile); + Mockito.when(molecularProfileService.getMolecularProfile("profile_id_gsva_scores_b")) + .thenReturn(genesetMolecularProfile); + + List> allValuesA = createAllValuesA(); + List valuesB = createValuesB(); + List> coExpressions = createCoExpressions(); + + Mockito.when( + asyncMethods.computeCoExpression( + "BIOCARTA_ASBCELL_PATHWAY", allValuesA.get(0), valuesB, THRESHOLD)) + .thenReturn(coExpressions.get(2)); + Mockito.when( + asyncMethods.computeCoExpression( + "KEGG_DNA_REPLICATION", allValuesA.get(1), valuesB, THRESHOLD)) + .thenReturn(coExpressions.get(3)); + Mockito.when( + asyncMethods.computeCoExpression( + "REACTOME_DIGESTION_OF_DIETARY_CARBOHYDRATE", + allValuesA.get(2), + valuesB, + THRESHOLD)) + .thenReturn(CompletableFuture.supplyAsync(() -> null)); + + List result = + coExpressionService.getCoExpressions( + "GENESET_ID_TEST", + EntityType.GENESET, + SAMPLE_LIST_ID, + "profile_id_gsva_scores_a", + "profile_id_gsva_scores_b", + THRESHOLD); + + Assert.assertEquals(2, result.size()); + CoExpression coExpression1 = result.get(0); + Assert.assertEquals("KEGG_DNA_REPLICATION", coExpression1.getGeneticEntityId()); + Assert.assertEquals( + new BigDecimal("0.8660254037844386"), coExpression1.getSpearmansCorrelation()); + Assert.assertEquals(new BigDecimal("0.3333333333333333"), coExpression1.getpValue()); + CoExpression coExpression2 = result.get(1); + Assert.assertEquals("BIOCARTA_ASBCELL_PATHWAY", coExpression2.getGeneticEntityId()); + Assert.assertEquals(new BigDecimal("0.5"), coExpression2.getSpearmansCorrelation()); + Assert.assertEquals(new BigDecimal("0.6666666666666667"), coExpression2.getpValue()); + } + + @Test + public void fetchGenesetCoExpressions() throws Exception { + + List molecularDataList = createGenesetMolecularData(); + Mockito.when( + genesetDataService.fetchGenesetData( + "profile_id_gsva_scores_a", Arrays.asList(SAMPLE_ID1, SAMPLE_ID2), null)) + .thenReturn(molecularDataList); + Mockito.when( + genesetDataService.fetchGenesetData( + "profile_id_gsva_scores_b", Arrays.asList(SAMPLE_ID1, SAMPLE_ID2), null)) + .thenReturn(molecularDataList); + + List genesets = createGenesets(); + + Mockito.when(genesetService.getGeneset("BIOCARTA_ASBCELL_PATHWAY")).thenReturn(genesets.get(0)); + + Mockito.when(genesetService.getGeneset("KEGG_DNA_REPLICATION")).thenReturn(genesets.get(1)); + + Mockito.when(genesetService.getGeneset("REACTOME_DIGESTION_OF_DIETARY_CARBOHYDRATE")) + .thenReturn(genesets.get(2)); + + Mockito.when(genesetService.getGeneset("BIOCARTA_ASBCELL_PATHWAY")).thenReturn(genesets.get(0)); + + MolecularProfile genesetMolecularProfile = createGenesetMolecularProfile(); + + Mockito.when(molecularProfileService.getMolecularProfile("profile_id_gsva_scores_b")) + .thenReturn(genesetMolecularProfile); + Mockito.when( + genesetDataService.fetchGenesetData( + "profile_id_gsva_scores_b", Arrays.asList(SAMPLE_ID1, SAMPLE_ID2), null)) + .thenReturn(molecularDataList); + + List> allValuesA = createAllValuesA(); + List valuesB = createValuesB(); + List> coExpressions = createCoExpressions(); + + Mockito.when( + asyncMethods.computeCoExpression( + "BIOCARTA_ASBCELL_PATHWAY", allValuesA.get(0), valuesB, THRESHOLD)) + .thenReturn(coExpressions.get(2)); + Mockito.when( + asyncMethods.computeCoExpression( + "KEGG_DNA_REPLICATION", allValuesA.get(1), valuesB, THRESHOLD)) + .thenReturn(coExpressions.get(3)); + Mockito.when( + asyncMethods.computeCoExpression( + "REACTOME_DIGESTION_OF_DIETARY_CARBOHYDRATE", + allValuesA.get(2), + valuesB, + THRESHOLD)) + .thenReturn(CompletableFuture.supplyAsync(() -> null)); + + List result = + coExpressionService.fetchCoExpressions( + "GENESET_ID_TEST", + EntityType.GENESET, + Arrays.asList(SAMPLE_ID1, SAMPLE_ID2), + "profile_id_gsva_scores_a", + "profile_id_gsva_scores_b", + THRESHOLD); + + Assert.assertEquals(2, result.size()); + CoExpression coExpression1 = result.get(0); + Assert.assertEquals("KEGG_DNA_REPLICATION", coExpression1.getGeneticEntityId()); + Assert.assertEquals( + new BigDecimal("0.8660254037844386"), coExpression1.getSpearmansCorrelation()); + Assert.assertEquals(new BigDecimal("0.3333333333333333"), coExpression1.getpValue()); + CoExpression coExpression2 = result.get(1); + Assert.assertEquals("BIOCARTA_ASBCELL_PATHWAY", coExpression2.getGeneticEntityId()); + Assert.assertEquals(new BigDecimal("0.5"), coExpression2.getSpearmansCorrelation()); + Assert.assertEquals(new BigDecimal("0.6666666666666667"), coExpression2.getpValue()); + } + + private List createGeneMolecularData() { + List molecularDataList = new ArrayList<>(); + GeneMolecularData geneMolecularData1 = new GeneMolecularData(); + geneMolecularData1.setEntrezGeneId(ENTREZ_GENE_ID_1); + geneMolecularData1.setValue("2.1"); + geneMolecularData1.setSampleId("sample_id1"); + molecularDataList.add(geneMolecularData1); + GeneMolecularData geneMolecularData2 = new GeneMolecularData(); + geneMolecularData2.setEntrezGeneId(ENTREZ_GENE_ID_1); + geneMolecularData2.setValue("3"); + geneMolecularData2.setSampleId("sample_id2"); + molecularDataList.add(geneMolecularData2); + GeneMolecularData geneMolecularData3 = new GeneMolecularData(); + geneMolecularData3.setEntrezGeneId(ENTREZ_GENE_ID_1); + geneMolecularData3.setValue("3"); + geneMolecularData3.setSampleId("sample_id3"); + molecularDataList.add(geneMolecularData3); + GeneMolecularData geneMolecularData4 = new GeneMolecularData(); + geneMolecularData4.setEntrezGeneId(ENTREZ_GENE_ID_2); + geneMolecularData4.setValue("2"); + geneMolecularData4.setSampleId("sample_id1"); + molecularDataList.add(geneMolecularData4); + GeneMolecularData geneMolecularData5 = new GeneMolecularData(); + geneMolecularData5.setEntrezGeneId(ENTREZ_GENE_ID_2); + geneMolecularData5.setValue("3"); + geneMolecularData5.setSampleId("sample_id2"); + molecularDataList.add(geneMolecularData5); + GeneMolecularData geneMolecularData6 = new GeneMolecularData(); + geneMolecularData6.setEntrezGeneId(ENTREZ_GENE_ID_2); + geneMolecularData6.setValue("2"); + geneMolecularData6.setSampleId("sample_id3"); + molecularDataList.add(geneMolecularData6); + GeneMolecularData geneMolecularData7 = new GeneMolecularData(); + geneMolecularData7.setEntrezGeneId(ENTREZ_GENE_ID_3); + geneMolecularData7.setValue("1.1"); + geneMolecularData7.setSampleId("sample_id1"); + molecularDataList.add(geneMolecularData7); + GeneMolecularData geneMolecularData8 = new GeneMolecularData(); + geneMolecularData8.setEntrezGeneId(ENTREZ_GENE_ID_3); + geneMolecularData8.setValue("5"); + geneMolecularData8.setSampleId("sample_id2"); + molecularDataList.add(geneMolecularData8); + GeneMolecularData geneMolecularData9 = new GeneMolecularData(); + geneMolecularData9.setEntrezGeneId(ENTREZ_GENE_ID_3); + geneMolecularData9.setValue("3"); + geneMolecularData9.setSampleId("sample_id3"); + molecularDataList.add(geneMolecularData9); + GeneMolecularData geneMolecularData10 = new GeneMolecularData(); + geneMolecularData10.setEntrezGeneId(ENTREZ_GENE_ID_4); + geneMolecularData10.setValue("1"); + geneMolecularData10.setSampleId("sample_id1"); + molecularDataList.add(geneMolecularData10); + GeneMolecularData geneMolecularData11 = new GeneMolecularData(); + geneMolecularData11.setEntrezGeneId(ENTREZ_GENE_ID_4); + geneMolecularData11.setValue("4"); + geneMolecularData11.setSampleId("sample_id2"); + molecularDataList.add(geneMolecularData11); + GeneMolecularData geneMolecularData12 = new GeneMolecularData(); + geneMolecularData12.setEntrezGeneId(ENTREZ_GENE_ID_4); + geneMolecularData12.setValue("0"); + geneMolecularData12.setSampleId("sample_id3"); + molecularDataList.add(geneMolecularData12); + return molecularDataList; + } + + private List createGenes() { + List genes = new ArrayList<>(); + Gene gene1 = new Gene(); + gene1.setEntrezGeneId(2); + gene1.setHugoGeneSymbol("HUGO2"); + gene1.setGeneticEntityId(GENETIC_ENTITY_ID_2); + genes.add(gene1); + Gene gene2 = new Gene(); + gene2.setEntrezGeneId(3); + gene2.setHugoGeneSymbol("HUGO3"); + gene2.setGeneticEntityId(GENETIC_ENTITY_ID_3); + genes.add(gene2); + Gene gene3 = new Gene(); + gene3.setEntrezGeneId(4); + gene3.setHugoGeneSymbol("HUGO4"); + gene3.setGeneticEntityId(GENETIC_ENTITY_ID_4); + genes.add(gene3); + return genes; + } + + private List createGenesetMolecularData() { + List molecularDataList = new ArrayList<>(); + GenesetMolecularData genesetMolecularData1 = new GenesetMolecularData(); + genesetMolecularData1.setGenesetId("GENESET_ID_TEST"); + genesetMolecularData1.setValue("2.1"); + genesetMolecularData1.setSampleId("sample_id1"); + molecularDataList.add(genesetMolecularData1); + GenesetMolecularData genesetMolecularData2 = new GenesetMolecularData(); + genesetMolecularData2.setGenesetId("GENESET_ID_TEST"); + genesetMolecularData2.setValue("3"); + genesetMolecularData2.setSampleId("sample_id2"); + molecularDataList.add(genesetMolecularData2); + GenesetMolecularData genesetMolecularData3 = new GenesetMolecularData(); + genesetMolecularData3.setGenesetId("GENESET_ID_TEST"); + genesetMolecularData3.setValue("3"); + genesetMolecularData3.setSampleId("sample_id3"); + molecularDataList.add(genesetMolecularData3); + GenesetMolecularData genesetMolecularData4 = new GenesetMolecularData(); + genesetMolecularData4.setGenesetId("BIOCARTA_ASBCELL_PATHWAY"); + genesetMolecularData4.setValue("2"); + genesetMolecularData4.setSampleId("sample_id1"); + molecularDataList.add(genesetMolecularData4); + GenesetMolecularData genesetMolecularData5 = new GenesetMolecularData(); + genesetMolecularData5.setGenesetId("BIOCARTA_ASBCELL_PATHWAY"); + genesetMolecularData5.setValue("3"); + genesetMolecularData5.setSampleId("sample_id2"); + molecularDataList.add(genesetMolecularData5); + GenesetMolecularData genesetMolecularData6 = new GenesetMolecularData(); + genesetMolecularData6.setGenesetId("BIOCARTA_ASBCELL_PATHWAY"); + genesetMolecularData6.setValue("2"); + genesetMolecularData6.setSampleId("sample_id3"); + molecularDataList.add(genesetMolecularData6); + GenesetMolecularData genesetMolecularData7 = new GenesetMolecularData(); + genesetMolecularData7.setGenesetId("KEGG_DNA_REPLICATION"); + genesetMolecularData7.setValue("1.1"); + genesetMolecularData7.setSampleId("sample_id1"); + molecularDataList.add(genesetMolecularData7); + GenesetMolecularData genesetMolecularData8 = new GenesetMolecularData(); + genesetMolecularData8.setGenesetId("KEGG_DNA_REPLICATION"); + genesetMolecularData8.setValue("5"); + genesetMolecularData8.setSampleId("sample_id2"); + molecularDataList.add(genesetMolecularData8); + GenesetMolecularData genesetMolecularData9 = new GenesetMolecularData(); + genesetMolecularData9.setGenesetId("KEGG_DNA_REPLICATION"); + genesetMolecularData9.setValue("3"); + genesetMolecularData9.setSampleId("sample_id3"); + molecularDataList.add(genesetMolecularData9); + GenesetMolecularData genesetMolecularData10 = new GenesetMolecularData(); + genesetMolecularData10.setGenesetId("REACTOME_DIGESTION_OF_DIETARY_CARBOHYDRATE"); + genesetMolecularData10.setValue("1"); + genesetMolecularData10.setSampleId("sample_id1"); + molecularDataList.add(genesetMolecularData10); + GenesetMolecularData genesetMolecularData11 = new GenesetMolecularData(); + genesetMolecularData11.setGenesetId("REACTOME_DIGESTION_OF_DIETARY_CARBOHYDRATE"); + genesetMolecularData11.setValue("4"); + genesetMolecularData11.setSampleId("sample_id2"); + molecularDataList.add(genesetMolecularData11); + GenesetMolecularData genesetMolecularData12 = new GenesetMolecularData(); + genesetMolecularData12.setGenesetId("REACTOME_DIGESTION_OF_DIETARY_CARBOHYDRATE"); + genesetMolecularData12.setValue("0"); + genesetMolecularData12.setSampleId("sample_id3"); + molecularDataList.add(genesetMolecularData12); + return molecularDataList; + } + + private List createGenesets() { + List genesets = new ArrayList<>(); + Geneset geneset1 = new Geneset(); + geneset1.setGenesetId("BIOCARTA_ASBCELL_PATHWAY"); + geneset1.setName("BIOCARTA_ASBCELL_PATHWAY"); + genesets.add(geneset1); + Geneset geneset2 = new Geneset(); + geneset2.setGenesetId("KEGG_DNA_REPLICATION"); + geneset2.setName("KEGG_DNA_REPLICATION"); + genesets.add(geneset2); + Geneset geneset3 = new Geneset(); + geneset3.setGenesetId("REACTOME_DIGESTION_OF_DIETARY_CARBOHYDRATE"); + geneset3.setName("REACTOME_DIGESTION_OF_DIETARY_CARBOHYDRATE"); + genesets.add(geneset3); + return genesets; + } + + private List> createAllValuesA() { + List> allValuesA = new ArrayList<>(); + List valuesA1 = new ArrayList<>(); + valuesA1.add("2"); + valuesA1.add("3"); + valuesA1.add("2"); + allValuesA.add(valuesA1); + List valuesA2 = new ArrayList<>(); + valuesA2.add("1.1"); + valuesA2.add("5"); + valuesA2.add("3"); + allValuesA.add(valuesA2); + List valuesA3 = new ArrayList<>(); + valuesA3.add("1"); + valuesA3.add("4"); + valuesA3.add("0"); + allValuesA.add(valuesA3); + return allValuesA; + } + + private List createValuesB() { + return new ArrayList<>(Arrays.asList("2.1", "3", "3")); + } + + private List> createCoExpressions() { + List> coExpressions = new ArrayList<>(); + CoExpression coExpression1 = new CoExpression(); + coExpression1.setGeneticEntityId("2"); + coExpression1.setSpearmansCorrelation(new BigDecimal("0.5")); + coExpression1.setpValue(new BigDecimal("0.6666666666666667")); + coExpressions.add(CompletableFuture.supplyAsync(() -> coExpression1)); + CoExpression coExpression2 = new CoExpression(); + coExpression2.setGeneticEntityId("3"); + coExpression2.setSpearmansCorrelation(new BigDecimal("0.8660254037844386")); + coExpression2.setpValue(new BigDecimal("0.3333333333333333")); + coExpressions.add(CompletableFuture.supplyAsync(() -> coExpression2)); + CoExpression coExpression3 = new CoExpression(); + coExpression3.setGeneticEntityId("BIOCARTA_ASBCELL_PATHWAY"); + coExpression3.setSpearmansCorrelation(new BigDecimal("0.5")); + coExpression3.setpValue(new BigDecimal("0.6666666666666667")); + coExpressions.add(CompletableFuture.supplyAsync(() -> coExpression3)); + CoExpression coExpression4 = new CoExpression(); + coExpression4.setGeneticEntityId("KEGG_DNA_REPLICATION"); + coExpression4.setSpearmansCorrelation(new BigDecimal("0.8660254037844386")); + coExpression4.setpValue(new BigDecimal("0.3333333333333333")); + coExpressions.add(CompletableFuture.supplyAsync(() -> coExpression4)); + return coExpressions; + } + + private MolecularProfile createGeneMolecularProfile() { + MolecularProfile geneMolecularProfile = new MolecularProfile(); + geneMolecularProfile.setMolecularAlterationType( + MolecularProfile.MolecularAlterationType.MRNA_EXPRESSION); + return geneMolecularProfile; + } + + private MolecularProfile createGenesetMolecularProfile() { + MolecularProfile genesetMolecularProfile = new MolecularProfile(); + genesetMolecularProfile.setMolecularAlterationType( + MolecularProfile.MolecularAlterationType.GENESET_SCORE); + return genesetMolecularProfile; + } +} diff --git a/src/test/java/org/cbioportal/legacy/service/impl/CopyNumberSegmentServiceImplTest.java b/src/test/java/org/cbioportal/legacy/service/impl/CopyNumberSegmentServiceImplTest.java new file mode 100644 index 00000000000..657fc9bf7ac --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/service/impl/CopyNumberSegmentServiceImplTest.java @@ -0,0 +1,132 @@ +package org.cbioportal.legacy.service.impl; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import org.cbioportal.legacy.model.CopyNumberSeg; +import org.cbioportal.legacy.model.meta.BaseMeta; +import org.cbioportal.legacy.persistence.CopyNumberSegmentRepository; +import org.cbioportal.legacy.service.SampleService; +import org.cbioportal.legacy.service.exception.SampleNotFoundException; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.junit.MockitoJUnitRunner; + +@RunWith(MockitoJUnitRunner.class) +public class CopyNumberSegmentServiceImplTest extends BaseServiceImplTest { + + @InjectMocks private CopyNumberSegmentServiceImpl copyNumberSegmentService; + + @Mock private CopyNumberSegmentRepository copyNumberSegmentRepository; + @Mock private SampleService sampleService; + + @Test + public void getCopyNumberSegmentsInSampleInStudy() throws Exception { + + List expectedCopyNumberSegList = new ArrayList<>(); + CopyNumberSeg copyNumberSeg = new CopyNumberSeg(); + expectedCopyNumberSegList.add(copyNumberSeg); + + Mockito.when( + copyNumberSegmentRepository.getCopyNumberSegmentsInSampleInStudy( + STUDY_ID, SAMPLE_ID1, null, PROJECTION, PAGE_SIZE, PAGE_NUMBER, SORT, DIRECTION)) + .thenReturn(expectedCopyNumberSegList); + + List result = + copyNumberSegmentService.getCopyNumberSegmentsInSampleInStudy( + STUDY_ID, SAMPLE_ID1, null, PROJECTION, PAGE_SIZE, PAGE_NUMBER, SORT, DIRECTION); + + Assert.assertEquals(expectedCopyNumberSegList, result); + } + + @Test(expected = SampleNotFoundException.class) + public void getCopyNumberSegmentsInSampleInStudySampleNotFound() throws Exception { + + Mockito.when(sampleService.getSampleInStudy(STUDY_ID, SAMPLE_ID1)) + .thenThrow(new SampleNotFoundException(STUDY_ID, SAMPLE_ID1)); + copyNumberSegmentService.getCopyNumberSegmentsInSampleInStudy( + STUDY_ID, SAMPLE_ID1, null, PROJECTION, PAGE_SIZE, PAGE_NUMBER, SORT, DIRECTION); + } + + @Test + public void getMetaCopyNumberSegmentsInSampleInStudy() throws Exception { + + BaseMeta expectedBaseMeta = new BaseMeta(); + + Mockito.when( + copyNumberSegmentRepository.getMetaCopyNumberSegmentsInSampleInStudy( + STUDY_ID, SAMPLE_ID1, null)) + .thenReturn(expectedBaseMeta); + + BaseMeta result = + copyNumberSegmentService.getMetaCopyNumberSegmentsInSampleInStudy( + STUDY_ID, SAMPLE_ID1, null); + + Assert.assertEquals(expectedBaseMeta, result); + } + + @Test(expected = SampleNotFoundException.class) + public void getMetaCopyNumberSegmentsInSampleInStudySampleNotFound() throws Exception { + + Mockito.when(sampleService.getSampleInStudy(STUDY_ID, SAMPLE_ID1)) + .thenThrow(new SampleNotFoundException(STUDY_ID, SAMPLE_ID1)); + copyNumberSegmentService.getMetaCopyNumberSegmentsInSampleInStudy(STUDY_ID, SAMPLE_ID1, null); + } + + @Test + public void fetchCopyNumberSegments() throws Exception { + + List expectedCopyNumberSegList = new ArrayList<>(); + CopyNumberSeg copyNumberSeg = new CopyNumberSeg(); + expectedCopyNumberSegList.add(copyNumberSeg); + + Mockito.when( + copyNumberSegmentRepository.fetchCopyNumberSegments( + Arrays.asList(STUDY_ID), Arrays.asList(PATIENT_ID_1), null, PROJECTION)) + .thenReturn(expectedCopyNumberSegList); + + List result = + copyNumberSegmentService.fetchCopyNumberSegments( + Arrays.asList(STUDY_ID), Arrays.asList(PATIENT_ID_1), null, PROJECTION); + + Assert.assertEquals(expectedCopyNumberSegList, result); + } + + @Test + public void fetchMetaCopyNumberSegments() throws Exception { + + BaseMeta expectedBaseMeta = new BaseMeta(); + Mockito.when( + copyNumberSegmentRepository.fetchMetaCopyNumberSegments( + Arrays.asList(STUDY_ID), Arrays.asList(PATIENT_ID_1), null)) + .thenReturn(expectedBaseMeta); + BaseMeta result = + copyNumberSegmentService.fetchMetaCopyNumberSegments( + Arrays.asList(STUDY_ID), Arrays.asList(PATIENT_ID_1), null); + + Assert.assertEquals(expectedBaseMeta, result); + } + + @Test + public void getCopyNumberSegmentsBySampleListId() throws Exception { + + List expectedCopyNumberSegList = new ArrayList<>(); + CopyNumberSeg copyNumberSeg = new CopyNumberSeg(); + expectedCopyNumberSegList.add(copyNumberSeg); + + Mockito.when( + copyNumberSegmentRepository.getCopyNumberSegmentsBySampleListId( + STUDY_ID, SAMPLE_LIST_ID, null, PROJECTION)) + .thenReturn(expectedCopyNumberSegList); + + List result = + copyNumberSegmentService.getCopyNumberSegmentsBySampleListId( + STUDY_ID, SAMPLE_LIST_ID, null, PROJECTION); + + Assert.assertEquals(expectedCopyNumberSegList, result); + } +} diff --git a/src/test/java/org/cbioportal/legacy/service/impl/CosmicCountServiceImplTest.java b/src/test/java/org/cbioportal/legacy/service/impl/CosmicCountServiceImplTest.java new file mode 100644 index 00000000000..d7aaccf2cc2 --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/service/impl/CosmicCountServiceImplTest.java @@ -0,0 +1,38 @@ +package org.cbioportal.legacy.service.impl; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import org.cbioportal.legacy.model.CosmicMutation; +import org.cbioportal.legacy.persistence.CosmicCountRepository; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.junit.MockitoJUnitRunner; + +@RunWith(MockitoJUnitRunner.class) +public class CosmicCountServiceImplTest extends BaseServiceImplTest { + + @InjectMocks private CosmicCountServiceImpl cosmicCountService; + + @Mock private CosmicCountRepository cosmicCountRepository; + + @Test + public void getCosmicCountsByKeywords() throws Exception { + + List expectedCosmicMutationList = new ArrayList<>(); + CosmicMutation cosmicMutation = new CosmicMutation(); + expectedCosmicMutationList.add(cosmicMutation); + + Mockito.when(cosmicCountRepository.fetchCosmicCountsByKeywords(Arrays.asList(KEYWORD))) + .thenReturn(expectedCosmicMutationList); + + List result = + cosmicCountService.fetchCosmicCountsByKeywords(Arrays.asList(KEYWORD)); + + Assert.assertEquals(expectedCosmicMutationList, result); + } +} diff --git a/src/test/java/org/cbioportal/legacy/service/impl/DiscreteCopyNumberServiceImplTest.java b/src/test/java/org/cbioportal/legacy/service/impl/DiscreteCopyNumberServiceImplTest.java new file mode 100644 index 00000000000..f87305141a8 --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/service/impl/DiscreteCopyNumberServiceImplTest.java @@ -0,0 +1,461 @@ +package org.cbioportal.legacy.service.impl; + +import static org.mockito.ArgumentMatchers.anyList; +import static org.mockito.ArgumentMatchers.anyString; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; +import org.cbioportal.legacy.model.CNA; +import org.cbioportal.legacy.model.DiscreteCopyNumberData; +import org.cbioportal.legacy.model.Gene; +import org.cbioportal.legacy.model.GeneFilterQuery; +import org.cbioportal.legacy.model.GeneMolecularData; +import org.cbioportal.legacy.model.MolecularProfile; +import org.cbioportal.legacy.model.meta.BaseMeta; +import org.cbioportal.legacy.persistence.DiscreteCopyNumberRepository; +import org.cbioportal.legacy.service.MolecularDataService; +import org.cbioportal.legacy.service.MolecularProfileService; +import org.cbioportal.legacy.service.exception.MolecularProfileNotFoundException; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.junit.MockitoJUnitRunner; + +@RunWith(MockitoJUnitRunner.class) +public class DiscreteCopyNumberServiceImplTest extends BaseServiceImplTest { + + @InjectMocks private DiscreteCopyNumberServiceImpl discreteCopyNumberService; + + @Mock private DiscreteCopyNumberRepository discreteCopyNumberRepository; + @Mock private MolecularDataService molecularDataService; + @Mock private MolecularProfileService molecularProfileService; + + @Test + public void getDiscreteCopyNumbersInMultipleMolecularProfilesHomdelOrAmp() { + List returned = + Arrays.asList( + discreteCopyNumberData("sample1", "study1", -2), + discreteCopyNumberData("sample2", "study2", 2)); + List profiles = Arrays.asList("profile1", "profile2"); + List samples = Arrays.asList("sample1", "sample2"); + List geneIds = Arrays.asList(0, 1); + List alterationTypes = Arrays.asList(-2, 2); + Mockito.when( + discreteCopyNumberRepository.getDiscreteCopyNumbersInMultipleMolecularProfiles( + profiles, samples, geneIds, alterationTypes, PROJECTION)) + .thenReturn(returned); + + List actual = + discreteCopyNumberService.getDiscreteCopyNumbersInMultipleMolecularProfiles( + profiles, samples, geneIds, alterationTypes, PROJECTION); + + Assert.assertEquals(toStrings(returned), toStrings(actual)); + } + + @Test + public void getDiscreteCopyNumbersWithAnnotationJson() { + List returned = + Arrays.asList( + discreteCopyNumberData("sample1", "study1", -2), + discreteCopyNumberData("sample2", "study2", 2)); + returned.get(0).setAnnotationJson("{\"columnName\":{\"fieldName\":\"fieldValue\"}}"); + List profiles = Arrays.asList("profile1", "profile2"); + List samples = Arrays.asList("sample1", "sample2"); + List geneIds = Arrays.asList(0, 1); + List alterationTypes = Arrays.asList(-2, 2); + + Mockito.when( + discreteCopyNumberRepository.getDiscreteCopyNumbersInMultipleMolecularProfiles( + profiles, samples, geneIds, alterationTypes, PROJECTION)) + .thenReturn(returned); + + List actual = + discreteCopyNumberService.getDiscreteCopyNumbersInMultipleMolecularProfiles( + profiles, samples, geneIds, alterationTypes, PROJECTION); + + Assert.assertEquals(toStrings(returned), toStrings(actual)); + } + + @Test + public void getDiscreteCopyNumbersWithoutAnnotationJson() { + List returned = + Arrays.asList( + discreteCopyNumberData("sample1", "study1", -2), + discreteCopyNumberData("sample2", "study2", 2)); + List profiles = Arrays.asList("profile1", "profile2"); + List samples = Arrays.asList("sample1", "sample2"); + List geneIds = Arrays.asList(0, 1); + List alterationTypes = Arrays.asList(-2, 2); + + Mockito.when( + discreteCopyNumberRepository.getDiscreteCopyNumbersInMultipleMolecularProfiles( + profiles, samples, geneIds, alterationTypes, PROJECTION)) + .thenReturn(returned); + + List actual = + discreteCopyNumberService.getDiscreteCopyNumbersInMultipleMolecularProfiles( + profiles, samples, geneIds, alterationTypes, PROJECTION); + Assert.assertNull(returned.get(0).getAnnotationJson()); + Assert.assertEquals(toStrings(returned), toStrings(actual)); + } + + @Test + public void getDiscreteCopyNumbersInMultipleMolecularProfilesAllAlterationTypes() { + List returned = + Arrays.asList( + geneMolecularData("sample1", "study1", "-2"), + geneMolecularData("sample2", "study1", "-1"), + geneMolecularData("sample3", "study1", "0"), + geneMolecularData("sample4", "study1", "1"), + geneMolecularData("sample5", "study2", "2")); + + List profiles = Arrays.asList("profile1", "profile2"); + List samples = Arrays.asList("sample1", "sample2"); + List alterationTypes = + Arrays.asList(CNA.AMP, CNA.HOMDEL, CNA.DIPLOID, CNA.GAIN, CNA.HETLOSS); + GeneFilterQuery query = new GeneFilterQuery(); + query.setAlterations(alterationTypes); + List geneQueries = Arrays.asList(query); + Mockito.when( + molecularDataService.getMolecularDataInMultipleMolecularProfilesByGeneQueries( + anyList(), anyList(), anyList(), anyString())) + .thenReturn(returned); + + List actual = + discreteCopyNumberService.getDiscreteCopyNumbersInMultipleMolecularProfilesByGeneQueries( + profiles, samples, geneQueries, PROJECTION); + List expected = + Arrays.asList( + discreteCopyNumberData("sample1", "study1", -2), + discreteCopyNumberData("sample2", "study1", -1), + discreteCopyNumberData("sample3", "study1", 0), + discreteCopyNumberData("sample4", "study1", 1), + discreteCopyNumberData("sample5", "study2", 2)); + + Assert.assertEquals(toStrings(expected), toStrings(actual)); + } + + @Test + public void getDiscreteCopyNumbersInMultipleMolecularProfilesEmptyAlterationTypes() { + List returned = + Arrays.asList( + geneMolecularData("sample1", "study1", "-2"), + geneMolecularData("sample2", "study1", "-1"), + geneMolecularData("sample3", "study1", "0"), + geneMolecularData("sample4", "study1", "1"), + geneMolecularData("sample5", "study2", "2")); + + List profiles = Arrays.asList("profile1", "profile2"); + List samples = Arrays.asList("sample1", "sample2"); + List alterationTypes = Collections.emptyList(); + GeneFilterQuery query = new GeneFilterQuery(); + query.setAlterations(alterationTypes); + List geneQueries = Arrays.asList(query); + + List actual = + discreteCopyNumberService.getDiscreteCopyNumbersInMultipleMolecularProfilesByGeneQueries( + profiles, samples, geneQueries, PROJECTION); + Assert.assertEquals(Collections.emptyList(), toStrings(actual)); + } + + @Test + public void getDiscreteCopyNumbersInMolecularProfileBySampleListIdHomdelOrAmp() throws Exception { + + createMolecularProfile(); + + List expectedDiscreteCopyNumberDataList = new ArrayList<>(); + DiscreteCopyNumberData discreteCopyNumberData = new DiscreteCopyNumberData(); + expectedDiscreteCopyNumberDataList.add(discreteCopyNumberData); + + List alterationTypes = new ArrayList<>(); + alterationTypes.add(-2); + + Mockito.when( + discreteCopyNumberRepository.getDiscreteCopyNumbersInMolecularProfileBySampleListId( + MOLECULAR_PROFILE_ID, + SAMPLE_LIST_ID, + Arrays.asList(ENTREZ_GENE_ID_1), + alterationTypes, + PROJECTION)) + .thenReturn(expectedDiscreteCopyNumberDataList); + + List result = + discreteCopyNumberService.getDiscreteCopyNumbersInMolecularProfileBySampleListId( + MOLECULAR_PROFILE_ID, + SAMPLE_LIST_ID, + Arrays.asList(ENTREZ_GENE_ID_1), + alterationTypes, + PROJECTION); + + Assert.assertEquals(expectedDiscreteCopyNumberDataList, result); + } + + @Test + public void getDiscreteCopyNumbersInMolecularProfileBySampleListIdNonHomdelOrAmp() + throws Exception { + + createMolecularProfile(); + + List expectedMolecularDataList = new ArrayList<>(); + GeneMolecularData molecularData = new GeneMolecularData(); + molecularData.setValue("-1"); + molecularData.setMolecularProfileId(MOLECULAR_PROFILE_ID); + molecularData.setSampleId(SAMPLE_ID1); + molecularData.setEntrezGeneId(ENTREZ_GENE_ID_1); + Gene gene = new Gene(); + molecularData.setGene(gene); + expectedMolecularDataList.add(molecularData); + + Mockito.when( + molecularDataService.getMolecularData( + MOLECULAR_PROFILE_ID, SAMPLE_LIST_ID, Arrays.asList(ENTREZ_GENE_ID_1), PROJECTION)) + .thenReturn(expectedMolecularDataList); + + List alterationTypes = new ArrayList<>(); + alterationTypes.add(-1); + + List result = + discreteCopyNumberService.getDiscreteCopyNumbersInMolecularProfileBySampleListId( + MOLECULAR_PROFILE_ID, + SAMPLE_LIST_ID, + Arrays.asList(ENTREZ_GENE_ID_1), + alterationTypes, + PROJECTION); + + Assert.assertEquals(1, result.size()); + DiscreteCopyNumberData discreteCopyNumberData = result.get(0); + Assert.assertEquals((Integer) (-1), discreteCopyNumberData.getAlteration()); + Assert.assertEquals(MOLECULAR_PROFILE_ID, discreteCopyNumberData.getMolecularProfileId()); + Assert.assertEquals(SAMPLE_ID1, discreteCopyNumberData.getSampleId()); + Assert.assertEquals(ENTREZ_GENE_ID_1, discreteCopyNumberData.getEntrezGeneId()); + Assert.assertEquals(gene, discreteCopyNumberData.getGene()); + } + + @Test + public void getMetaDiscreteCopyNumbersInMolecularProfileBySampleListIdHomdelOrAmp() + throws Exception { + + createMolecularProfile(); + + List alterationTypes = new ArrayList<>(); + alterationTypes.add(-2); + + BaseMeta expectedBaseMeta = new BaseMeta(); + Mockito.when( + discreteCopyNumberRepository.getMetaDiscreteCopyNumbersInMolecularProfileBySampleListId( + MOLECULAR_PROFILE_ID, + SAMPLE_LIST_ID, + Arrays.asList(ENTREZ_GENE_ID_1), + alterationTypes)) + .thenReturn(expectedBaseMeta); + + BaseMeta result = + discreteCopyNumberService.getMetaDiscreteCopyNumbersInMolecularProfileBySampleListId( + MOLECULAR_PROFILE_ID, SAMPLE_LIST_ID, Arrays.asList(ENTREZ_GENE_ID_1), alterationTypes); + + Assert.assertEquals(expectedBaseMeta, result); + } + + @Test + public void getMetaDiscreteCopyNumbersInMolecularProfileBySampleListIdNonHomdelOrAmp() + throws Exception { + + createMolecularProfile(); + + List expectedMolecularDataList = new ArrayList<>(); + GeneMolecularData molecularData = new GeneMolecularData(); + molecularData.setValue("-1"); + expectedMolecularDataList.add(molecularData); + + Mockito.when( + molecularDataService.getMolecularData( + MOLECULAR_PROFILE_ID, SAMPLE_LIST_ID, Arrays.asList(ENTREZ_GENE_ID_1), "ID")) + .thenReturn(expectedMolecularDataList); + + List alterationTypes = new ArrayList<>(); + alterationTypes.add(-1); + + BaseMeta result = + discreteCopyNumberService.getMetaDiscreteCopyNumbersInMolecularProfileBySampleListId( + MOLECULAR_PROFILE_ID, SAMPLE_LIST_ID, Arrays.asList(ENTREZ_GENE_ID_1), alterationTypes); + + Assert.assertEquals((Integer) 1, result.getTotalCount()); + } + + @Test + public void fetchDiscreteCopyNumbersInMolecularProfileHomdelOrAmp() throws Exception { + + createMolecularProfile(); + + List expectedDiscreteCopyNumberDataList = new ArrayList<>(); + DiscreteCopyNumberData discreteCopyNumberData = new DiscreteCopyNumberData(); + expectedDiscreteCopyNumberDataList.add(discreteCopyNumberData); + + List alterationTypes = new ArrayList<>(); + alterationTypes.add(-2); + + Mockito.when( + discreteCopyNumberRepository.fetchDiscreteCopyNumbersInMolecularProfile( + MOLECULAR_PROFILE_ID, + Arrays.asList(SAMPLE_ID1), + Arrays.asList(ENTREZ_GENE_ID_1), + alterationTypes, + PROJECTION)) + .thenReturn(expectedDiscreteCopyNumberDataList); + + List result = + discreteCopyNumberService.fetchDiscreteCopyNumbersInMolecularProfile( + MOLECULAR_PROFILE_ID, + Arrays.asList(SAMPLE_ID1), + Arrays.asList(ENTREZ_GENE_ID_1), + alterationTypes, + PROJECTION); + + Assert.assertEquals(expectedDiscreteCopyNumberDataList, result); + } + + @Test + public void fetchDiscreteCopyNumbersInMolecularProfileNonHomdelOrAmp() throws Exception { + + createMolecularProfile(); + + List expectedMolecularDataList = new ArrayList<>(); + GeneMolecularData molecularData = new GeneMolecularData(); + molecularData.setValue("-1"); + molecularData.setMolecularProfileId(MOLECULAR_PROFILE_ID); + molecularData.setSampleId(SAMPLE_ID1); + molecularData.setEntrezGeneId(ENTREZ_GENE_ID_1); + Gene gene = new Gene(); + molecularData.setGene(gene); + expectedMolecularDataList.add(molecularData); + + Mockito.when( + molecularDataService.fetchMolecularData( + MOLECULAR_PROFILE_ID, + Arrays.asList(SAMPLE_ID1), + Arrays.asList(ENTREZ_GENE_ID_1), + PROJECTION)) + .thenReturn(expectedMolecularDataList); + + List alterationTypes = new ArrayList<>(); + alterationTypes.add(-1); + + List result = + discreteCopyNumberService.fetchDiscreteCopyNumbersInMolecularProfile( + MOLECULAR_PROFILE_ID, + Arrays.asList(SAMPLE_ID1), + Arrays.asList(ENTREZ_GENE_ID_1), + alterationTypes, + PROJECTION); + + Assert.assertEquals(1, result.size()); + DiscreteCopyNumberData discreteCopyNumberData = result.get(0); + Assert.assertEquals((Integer) (-1), discreteCopyNumberData.getAlteration()); + Assert.assertEquals(MOLECULAR_PROFILE_ID, discreteCopyNumberData.getMolecularProfileId()); + Assert.assertEquals(SAMPLE_ID1, discreteCopyNumberData.getSampleId()); + Assert.assertEquals(ENTREZ_GENE_ID_1, discreteCopyNumberData.getEntrezGeneId()); + Assert.assertEquals(gene, discreteCopyNumberData.getGene()); + } + + @Test + public void fetchMetaDiscreteCopyNumbersInMolecularProfileHomdelOrAmp() throws Exception { + + createMolecularProfile(); + + List alterationTypes = new ArrayList<>(); + alterationTypes.add(-2); + + BaseMeta expectedBaseMeta = new BaseMeta(); + Mockito.when( + discreteCopyNumberRepository.fetchMetaDiscreteCopyNumbersInMolecularProfile( + MOLECULAR_PROFILE_ID, + Arrays.asList(SAMPLE_ID1), + Arrays.asList(ENTREZ_GENE_ID_1), + alterationTypes)) + .thenReturn(expectedBaseMeta); + + BaseMeta result = + discreteCopyNumberService.fetchMetaDiscreteCopyNumbersInMolecularProfile( + MOLECULAR_PROFILE_ID, + Arrays.asList(SAMPLE_ID1), + Arrays.asList(ENTREZ_GENE_ID_1), + alterationTypes); + + Assert.assertEquals(expectedBaseMeta, result); + } + + @Test + public void fetchMetaDiscreteCopyNumbersInMolecularProfileNonHomdelOrAmp() throws Exception { + + createMolecularProfile(); + + List expectedMolecularDataList = new ArrayList<>(); + GeneMolecularData molecularData = new GeneMolecularData(); + molecularData.setValue("-1"); + expectedMolecularDataList.add(molecularData); + + Mockito.when( + molecularDataService.fetchMolecularData( + MOLECULAR_PROFILE_ID, + Arrays.asList(SAMPLE_ID1), + Arrays.asList(ENTREZ_GENE_ID_1), + "ID")) + .thenReturn(expectedMolecularDataList); + + List alterationTypes = new ArrayList<>(); + alterationTypes.add(-1); + + BaseMeta result = + discreteCopyNumberService.fetchMetaDiscreteCopyNumbersInMolecularProfile( + MOLECULAR_PROFILE_ID, + Arrays.asList(SAMPLE_ID1), + Arrays.asList(ENTREZ_GENE_ID_1), + alterationTypes); + + Assert.assertEquals((Integer) 1, result.getTotalCount()); + } + + private void createMolecularProfile() throws MolecularProfileNotFoundException { + + MolecularProfile molecularProfile = new MolecularProfile(); + molecularProfile.setMolecularAlterationType( + MolecularProfile.MolecularAlterationType.COPY_NUMBER_ALTERATION); + molecularProfile.setDatatype("DISCRETE"); + Mockito.when(molecularProfileService.getMolecularProfile(MOLECULAR_PROFILE_ID)) + .thenReturn(molecularProfile); + } + + private DiscreteCopyNumberData discreteCopyNumberData( + String sample, String study, Integer alteration) { + DiscreteCopyNumberData data = new DiscreteCopyNumberData(); + data.setStudyId(study); + data.setSampleId(sample); + data.setAlteration(alteration); + + return data; + } + + private GeneMolecularData geneMolecularData(String sample, String study, String alteration) { + GeneMolecularData data = new GeneMolecularData(); + data.setSampleId(sample); + data.setStudyId(study); + data.setValue(alteration); + + return data; + } + + // I don't want to pollute DiscreteCopyNumberData with an equals that + // isn't necessarily accurate for anything outside this very narrow test + // so here's a quick string conversion method instead. + private List toStrings(List data) { + return data.stream() + .map(d -> d.getAlteration() + " " + d.getStudyId() + " " + d.getSampleId()) + .collect(Collectors.toList()); + } +} diff --git a/src/test/java/org/cbioportal/legacy/service/impl/ExpressionEnrichmentServiceImplTest.java b/src/test/java/org/cbioportal/legacy/service/impl/ExpressionEnrichmentServiceImplTest.java new file mode 100644 index 00000000000..7e96287a16e --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/service/impl/ExpressionEnrichmentServiceImplTest.java @@ -0,0 +1,491 @@ +package org.cbioportal.legacy.service.impl; + +import java.math.BigDecimal; +import java.util.*; +import org.cbioportal.legacy.model.CancerStudy; +import org.cbioportal.legacy.model.EnrichmentType; +import org.cbioportal.legacy.model.ExpressionEnrichment; +import org.cbioportal.legacy.model.Gene; +import org.cbioportal.legacy.model.GeneMolecularAlteration; +import org.cbioportal.legacy.model.GenericAssayEnrichment; +import org.cbioportal.legacy.model.GenericAssayMolecularAlteration; +import org.cbioportal.legacy.model.GenomicEnrichment; +import org.cbioportal.legacy.model.GroupStatistics; +import org.cbioportal.legacy.model.MolecularProfile; +import org.cbioportal.legacy.model.MolecularProfileCaseIdentifier; +import org.cbioportal.legacy.model.MolecularProfileSamples; +import org.cbioportal.legacy.model.ReferenceGenome; +import org.cbioportal.legacy.model.Sample; +import org.cbioportal.legacy.model.meta.GenericAssayMeta; +import org.cbioportal.legacy.persistence.MolecularDataRepository; +import org.cbioportal.legacy.service.GeneService; +import org.cbioportal.legacy.service.GenericAssayService; +import org.cbioportal.legacy.service.MolecularProfileService; +import org.cbioportal.legacy.service.SampleService; +import org.cbioportal.legacy.service.exception.MolecularProfileNotFoundException; +import org.cbioportal.legacy.service.util.ExpressionEnrichmentUtil; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.junit.MockitoJUnitRunner; + +@RunWith(MockitoJUnitRunner.class) +public class ExpressionEnrichmentServiceImplTest extends BaseServiceImplTest { + + @InjectMocks private ExpressionEnrichmentServiceImpl enrichmentServiceImpl; + @Mock private SampleService sampleService; + @Mock private MolecularProfileService molecularProfileService; + @Mock private MolecularDataRepository molecularDataRepository; + @Mock private GeneService geneService; + @Mock private ExpressionEnrichmentUtil expressionEnrichmentUtil; + @Mock private GenericAssayService genericAssayService; + + CancerStudy cancerStudy = new CancerStudy(); + MolecularProfile geneMolecularProfile = new MolecularProfile(); + MolecularProfileSamples molecularProfileSamples = new MolecularProfileSamples(); + List samples = new ArrayList<>(); + Map> molecularProfileCaseSets = new HashMap<>(); + Map> molecularProfilePatientLevelCaseSets = + new HashMap<>(); + // patient level only data + public static final String SAMPLE_ID5 = "sample_id5"; + + @Before + public void setup() throws MolecularProfileNotFoundException { + cancerStudy.setReferenceGenome(ReferenceGenome.HOMO_SAPIENS_DEFAULT_GENOME_NAME); + cancerStudy.setCancerStudyIdentifier(STUDY_ID); + + geneMolecularProfile.setCancerStudyIdentifier(STUDY_ID); + geneMolecularProfile.setStableId(MOLECULAR_PROFILE_ID); + + geneMolecularProfile.setCancerStudy(cancerStudy); + + molecularProfileSamples.setMolecularProfileId(MOLECULAR_PROFILE_ID); + molecularProfileSamples.setCommaSeparatedSampleIds("1,2,3,4"); + + Sample sample1 = new Sample(); + sample1.setStableId(SAMPLE_ID1); + sample1.setInternalId(1); + sample1.setCancerStudyIdentifier(STUDY_ID); + sample1.setPatientId(1); + samples.add(sample1); + Sample sample2 = new Sample(); + sample2.setStableId(SAMPLE_ID2); + sample2.setInternalId(2); + sample2.setCancerStudyIdentifier(STUDY_ID); + sample2.setPatientId(2); + samples.add(sample2); + Sample sample3 = new Sample(); + sample3.setStableId(SAMPLE_ID3); + sample3.setInternalId(3); + sample3.setCancerStudyIdentifier(STUDY_ID); + sample3.setPatientId(3); + samples.add(sample3); + Sample sample4 = new Sample(); + sample4.setStableId(SAMPLE_ID4); + sample4.setInternalId(4); + sample4.setCancerStudyIdentifier(STUDY_ID); + sample4.setPatientId(4); + samples.add(sample4); + + List alteredSampleIdentifieres = new ArrayList<>(); + List unalteredSampleIdentifieres = new ArrayList<>(); + List unalteredPatientLevelSampleIdentifieres = + new ArrayList<>(); + + MolecularProfileCaseIdentifier caseIdentifier1 = new MolecularProfileCaseIdentifier(); + caseIdentifier1.setMolecularProfileId(MOLECULAR_PROFILE_ID); + caseIdentifier1.setCaseId(SAMPLE_ID1); + alteredSampleIdentifieres.add(caseIdentifier1); + + MolecularProfileCaseIdentifier caseIdentifier2 = new MolecularProfileCaseIdentifier(); + caseIdentifier2.setMolecularProfileId(MOLECULAR_PROFILE_ID); + caseIdentifier2.setCaseId(SAMPLE_ID2); + alteredSampleIdentifieres.add(caseIdentifier2); + + MolecularProfileCaseIdentifier caseIdentifier3 = new MolecularProfileCaseIdentifier(); + caseIdentifier3.setMolecularProfileId(MOLECULAR_PROFILE_ID); + caseIdentifier3.setCaseId(SAMPLE_ID3); + unalteredSampleIdentifieres.add(caseIdentifier3); + unalteredPatientLevelSampleIdentifieres.add(caseIdentifier3); + + MolecularProfileCaseIdentifier caseIdentifier4 = new MolecularProfileCaseIdentifier(); + caseIdentifier4.setMolecularProfileId(MOLECULAR_PROFILE_ID); + caseIdentifier4.setCaseId(SAMPLE_ID4); + unalteredSampleIdentifieres.add(caseIdentifier4); + unalteredPatientLevelSampleIdentifieres.add(caseIdentifier4); + + // patient level only data + MolecularProfileCaseIdentifier caseIdentifier5 = new MolecularProfileCaseIdentifier(); + caseIdentifier5.setMolecularProfileId(MOLECULAR_PROFILE_ID); + caseIdentifier5.setCaseId(SAMPLE_ID5); + unalteredPatientLevelSampleIdentifieres.add(caseIdentifier5); + + molecularProfileCaseSets.put("altered samples", alteredSampleIdentifieres); + molecularProfileCaseSets.put("unaltered samples", unalteredSampleIdentifieres); + molecularProfilePatientLevelCaseSets.put("altered samples", alteredSampleIdentifieres); + molecularProfilePatientLevelCaseSets.put( + "unaltered samples", unalteredPatientLevelSampleIdentifieres); + + Mockito.when(molecularProfileService.getMolecularProfile(MOLECULAR_PROFILE_ID)) + .thenReturn(geneMolecularProfile); + } + + @Test + public void getGenomicEnrichments() throws Exception { + geneMolecularProfile.setMolecularAlterationType( + MolecularProfile.MolecularAlterationType.MRNA_EXPRESSION); + + List molecularDataList = new ArrayList(); + GeneMolecularAlteration geneMolecularAlteration1 = new GeneMolecularAlteration(); + geneMolecularAlteration1.setEntrezGeneId(ENTREZ_GENE_ID_2); + geneMolecularAlteration1.setValues("2,3,2.1,3"); + molecularDataList.add(geneMolecularAlteration1); + + GeneMolecularAlteration geneMolecularAlteration2 = new GeneMolecularAlteration(); + geneMolecularAlteration2.setEntrezGeneId(ENTREZ_GENE_ID_3); + geneMolecularAlteration2.setValues("1.1,5,2.3,3"); + molecularDataList.add(geneMolecularAlteration2); + Mockito.when( + molecularDataRepository.getGeneMolecularAlterationsIterableFast(MOLECULAR_PROFILE_ID)) + .thenReturn(molecularDataList); + + List expectedEnrichments = new ArrayList<>(); + GenomicEnrichment enrichment1 = new GenomicEnrichment(); + enrichment1.setEntrezGeneId(ENTREZ_GENE_ID_2); + enrichment1.setHugoGeneSymbol(HUGO_GENE_SYMBOL_2); + GroupStatistics unalteredGroupStats1 = new GroupStatistics(); + unalteredGroupStats1.setName("unaltered samples"); + unalteredGroupStats1.setMeanExpression(new BigDecimal("2.55")); + unalteredGroupStats1.setStandardDeviation(new BigDecimal("0.6363961030678927")); + GroupStatistics alteredGroupStats1 = new GroupStatistics(); + alteredGroupStats1.setName("altered samples"); + alteredGroupStats1.setMeanExpression(new BigDecimal("2.5")); + alteredGroupStats1.setStandardDeviation(new BigDecimal("0.7071067811865476")); + enrichment1.setGroupsStatistics(List.of(unalteredGroupStats1, alteredGroupStats1)); + enrichment1.setpValue(new BigDecimal("0.9475795430163914")); + expectedEnrichments.add(enrichment1); + + GenomicEnrichment enrichment2 = new GenomicEnrichment(); + enrichment2.setEntrezGeneId(ENTREZ_GENE_ID_3); + enrichment2.setHugoGeneSymbol(HUGO_GENE_SYMBOL_3); + GroupStatistics unalteredGroupStats2 = new GroupStatistics(); + unalteredGroupStats2.setName("unaltered samples"); + unalteredGroupStats2.setMeanExpression(new BigDecimal("2.65")); + unalteredGroupStats2.setStandardDeviation(new BigDecimal("0.4949747468305834")); + GroupStatistics alteredGroupStats2 = new GroupStatistics(); + alteredGroupStats2.setName("altered samples"); + alteredGroupStats2.setMeanExpression(new BigDecimal("3.05")); + alteredGroupStats2.setStandardDeviation(new BigDecimal("2.7577164466275352")); + enrichment2.setGroupsStatistics(List.of(unalteredGroupStats2, alteredGroupStats2)); + enrichment2.setpValue(new BigDecimal("0.8716148250471419")); + expectedEnrichments.add(enrichment2); + Mockito.when( + expressionEnrichmentUtil.getEnrichments( + geneMolecularProfile, + molecularProfileCaseSets, + EnrichmentType.SAMPLE, + molecularDataList)) + .thenReturn(expectedEnrichments); + + List expectedGeneList = new ArrayList<>(); + Gene gene1 = new Gene(); + gene1.setEntrezGeneId(ENTREZ_GENE_ID_2); + gene1.setHugoGeneSymbol(HUGO_GENE_SYMBOL_2); + expectedGeneList.add(gene1); + Gene gene2 = new Gene(); + gene2.setEntrezGeneId(ENTREZ_GENE_ID_3); + gene2.setHugoGeneSymbol(HUGO_GENE_SYMBOL_3); + expectedGeneList.add(gene2); + + Mockito.when(geneService.fetchGenes(Arrays.asList("2", "3"), "ENTREZ_GENE_ID", "SUMMARY")) + .thenReturn(expectedGeneList); + + List result = + enrichmentServiceImpl.getGenomicEnrichments( + MOLECULAR_PROFILE_ID, molecularProfileCaseSets, EnrichmentType.SAMPLE); + + Assert.assertEquals(2, result.size()); + GenomicEnrichment expressionEnrichment = result.get(0); + Assert.assertEquals(ENTREZ_GENE_ID_2, expressionEnrichment.getEntrezGeneId()); + Assert.assertEquals(HUGO_GENE_SYMBOL_2, expressionEnrichment.getHugoGeneSymbol()); + Assert.assertEquals(null, expressionEnrichment.getCytoband()); + Assert.assertEquals(2, expressionEnrichment.getGroupsStatistics().size()); + + GroupStatistics unalteredGroupStats = expressionEnrichment.getGroupsStatistics().get(0); + Assert.assertEquals("unaltered samples", unalteredGroupStats.getName()); + Assert.assertEquals(new BigDecimal("2.55"), unalteredGroupStats.getMeanExpression()); + Assert.assertEquals( + new BigDecimal("0.6363961030678927"), unalteredGroupStats.getStandardDeviation()); + + GroupStatistics alteredGroupStats = expressionEnrichment.getGroupsStatistics().get(1); + Assert.assertEquals("altered samples", alteredGroupStats.getName()); + Assert.assertEquals(new BigDecimal("2.5"), alteredGroupStats.getMeanExpression()); + Assert.assertEquals( + new BigDecimal("0.7071067811865476"), alteredGroupStats.getStandardDeviation()); + + Assert.assertEquals(new BigDecimal("0.9475795430163914"), expressionEnrichment.getpValue()); + + expressionEnrichment = result.get(1); + Assert.assertEquals(ENTREZ_GENE_ID_3, expressionEnrichment.getEntrezGeneId()); + Assert.assertEquals(HUGO_GENE_SYMBOL_3, expressionEnrichment.getHugoGeneSymbol()); + Assert.assertEquals(null, expressionEnrichment.getCytoband()); + Assert.assertEquals(2, expressionEnrichment.getGroupsStatistics().size()); + + unalteredGroupStats = expressionEnrichment.getGroupsStatistics().get(0); + Assert.assertEquals("unaltered samples", unalteredGroupStats.getName()); + Assert.assertEquals(new BigDecimal("2.65"), unalteredGroupStats.getMeanExpression()); + Assert.assertEquals( + new BigDecimal("0.4949747468305834"), unalteredGroupStats.getStandardDeviation()); + + alteredGroupStats = expressionEnrichment.getGroupsStatistics().get(1); + Assert.assertEquals("altered samples", alteredGroupStats.getName()); + Assert.assertEquals(new BigDecimal("3.05"), alteredGroupStats.getMeanExpression()); + Assert.assertEquals( + new BigDecimal("2.7577164466275352"), alteredGroupStats.getStandardDeviation()); + + Assert.assertEquals(new BigDecimal("0.8716148250471419"), expressionEnrichment.getpValue()); + } + + @Test + public void getGenericAssayNumericalEnrichments() throws Exception { + geneMolecularProfile.setMolecularAlterationType( + MolecularProfile.MolecularAlterationType.GENERIC_ASSAY); + + List molecularDataList = + new ArrayList(); + GenericAssayMolecularAlteration genericAssayMolecularAlteration1 = + new GenericAssayMolecularAlteration(); + genericAssayMolecularAlteration1.setGenericAssayStableId(HUGO_GENE_SYMBOL_1); + genericAssayMolecularAlteration1.setValues("2,3,2.1,3"); + molecularDataList.add(genericAssayMolecularAlteration1); + + GenericAssayMolecularAlteration genericAssayMolecularAlteration2 = + new GenericAssayMolecularAlteration(); + genericAssayMolecularAlteration2.setGenericAssayStableId(HUGO_GENE_SYMBOL_2); + genericAssayMolecularAlteration2.setValues("1.1,5,2.3,3"); + molecularDataList.add(genericAssayMolecularAlteration2); + Mockito.when( + molecularDataRepository.getGenericAssayMolecularAlterationsIterable( + MOLECULAR_PROFILE_ID, null, "SUMMARY")) + .thenReturn(molecularDataList); + + List expectedEnrichments = new ArrayList<>(); + GenericAssayEnrichment enrichment1 = new GenericAssayEnrichment(); + enrichment1.setStableId(HUGO_GENE_SYMBOL_1); + GroupStatistics unalteredGroupStats1 = new GroupStatistics(); + unalteredGroupStats1.setName("unaltered samples"); + unalteredGroupStats1.setMeanExpression(new BigDecimal("2.55")); + unalteredGroupStats1.setStandardDeviation(new BigDecimal("0.6363961030678927")); + GroupStatistics alteredGroupStats1 = new GroupStatistics(); + alteredGroupStats1.setName("altered samples"); + alteredGroupStats1.setMeanExpression(new BigDecimal("2.5")); + alteredGroupStats1.setStandardDeviation(new BigDecimal("0.7071067811865476")); + enrichment1.setGroupsStatistics(List.of(unalteredGroupStats1, alteredGroupStats1)); + enrichment1.setpValue(new BigDecimal("0.9475795430163914")); + expectedEnrichments.add(enrichment1); + + GenericAssayEnrichment enrichment2 = new GenericAssayEnrichment(); + enrichment2.setStableId(HUGO_GENE_SYMBOL_2); + GroupStatistics unalteredGroupStats2 = new GroupStatistics(); + unalteredGroupStats2.setName("unaltered samples"); + unalteredGroupStats2.setMeanExpression(new BigDecimal("2.65")); + unalteredGroupStats2.setStandardDeviation(new BigDecimal("0.4949747468305834")); + GroupStatistics alteredGroupStats2 = new GroupStatistics(); + alteredGroupStats2.setName("altered samples"); + alteredGroupStats2.setMeanExpression(new BigDecimal("3.05")); + alteredGroupStats2.setStandardDeviation(new BigDecimal("2.7577164466275352")); + enrichment2.setGroupsStatistics(List.of(unalteredGroupStats2, alteredGroupStats2)); + enrichment2.setpValue(new BigDecimal("0.8716148250471419")); + expectedEnrichments.add(enrichment2); + Mockito.when( + expressionEnrichmentUtil.getEnrichments( + geneMolecularProfile, + molecularProfileCaseSets, + EnrichmentType.SAMPLE, + molecularDataList)) + .thenReturn(expectedEnrichments); + + Mockito.when( + genericAssayService.getGenericAssayMetaByStableIdsAndMolecularIds( + Arrays.asList(HUGO_GENE_SYMBOL_1, HUGO_GENE_SYMBOL_2), + Arrays.asList(MOLECULAR_PROFILE_ID, MOLECULAR_PROFILE_ID), + "SUMMARY")) + .thenReturn( + Arrays.asList( + new GenericAssayMeta(HUGO_GENE_SYMBOL_1), + new GenericAssayMeta(HUGO_GENE_SYMBOL_2))); + + List result = + enrichmentServiceImpl.getGenericAssayNumericalEnrichments( + MOLECULAR_PROFILE_ID, molecularProfileCaseSets, EnrichmentType.SAMPLE); + + Assert.assertEquals(2, result.size()); + GenericAssayEnrichment genericAssayEnrichment = result.get(0); + Assert.assertEquals(HUGO_GENE_SYMBOL_1, genericAssayEnrichment.getStableId()); + Assert.assertEquals(2, genericAssayEnrichment.getGroupsStatistics().size()); + + GroupStatistics unalteredGroupStats = genericAssayEnrichment.getGroupsStatistics().get(0); + Assert.assertEquals("unaltered samples", unalteredGroupStats.getName()); + Assert.assertEquals(new BigDecimal("2.55"), unalteredGroupStats.getMeanExpression()); + Assert.assertEquals( + new BigDecimal("0.6363961030678927"), unalteredGroupStats.getStandardDeviation()); + + GroupStatistics alteredGroupStats = genericAssayEnrichment.getGroupsStatistics().get(1); + Assert.assertEquals("altered samples", alteredGroupStats.getName()); + Assert.assertEquals(new BigDecimal("2.5"), alteredGroupStats.getMeanExpression()); + Assert.assertEquals( + new BigDecimal("0.7071067811865476"), alteredGroupStats.getStandardDeviation()); + + Assert.assertEquals(new BigDecimal("0.9475795430163914"), genericAssayEnrichment.getpValue()); + + genericAssayEnrichment = result.get(1); + Assert.assertEquals(HUGO_GENE_SYMBOL_2, genericAssayEnrichment.getStableId()); + Assert.assertEquals(2, genericAssayEnrichment.getGroupsStatistics().size()); + + unalteredGroupStats = genericAssayEnrichment.getGroupsStatistics().get(0); + Assert.assertEquals("unaltered samples", unalteredGroupStats.getName()); + Assert.assertEquals(new BigDecimal("2.65"), unalteredGroupStats.getMeanExpression()); + Assert.assertEquals( + new BigDecimal("0.4949747468305834"), unalteredGroupStats.getStandardDeviation()); + + alteredGroupStats = genericAssayEnrichment.getGroupsStatistics().get(1); + Assert.assertEquals("altered samples", alteredGroupStats.getName()); + Assert.assertEquals(new BigDecimal("3.05"), alteredGroupStats.getMeanExpression()); + Assert.assertEquals( + new BigDecimal("2.7577164466275352"), alteredGroupStats.getStandardDeviation()); + + Assert.assertEquals(new BigDecimal("0.8716148250471419"), genericAssayEnrichment.getpValue()); + } + + @Test + public void getGenericAssayPatientLevelEnrichments() throws Exception { + geneMolecularProfile.setMolecularAlterationType( + MolecularProfile.MolecularAlterationType.GENERIC_ASSAY); + geneMolecularProfile.setPatientLevel(true); + + List molecularDataList = + new ArrayList(); + GenericAssayMolecularAlteration genericAssayMolecularAlteration1 = + new GenericAssayMolecularAlteration(); + genericAssayMolecularAlteration1.setGenericAssayStableId(HUGO_GENE_SYMBOL_1); + genericAssayMolecularAlteration1.setValues("2,3,2.1,3,3,3"); + molecularDataList.add(genericAssayMolecularAlteration1); + + GenericAssayMolecularAlteration genericAssayMolecularAlteration2 = + new GenericAssayMolecularAlteration(); + genericAssayMolecularAlteration2.setGenericAssayStableId(HUGO_GENE_SYMBOL_2); + genericAssayMolecularAlteration2.setValues("1.1,5,2.3,3,3"); + molecularDataList.add(genericAssayMolecularAlteration2); + Mockito.when( + molecularDataRepository.getGenericAssayMolecularAlterationsIterable( + MOLECULAR_PROFILE_ID, null, "SUMMARY")) + .thenReturn(molecularDataList); + + List expectedEnrichments = new ArrayList<>(); + GenericAssayEnrichment enrichment1 = new GenericAssayEnrichment(); + enrichment1.setStableId(HUGO_GENE_SYMBOL_1); + GroupStatistics unalteredGroupStats1 = new GroupStatistics(); + unalteredGroupStats1.setName("unaltered samples"); + unalteredGroupStats1.setMeanExpression(new BigDecimal("2.55")); + unalteredGroupStats1.setStandardDeviation(new BigDecimal("0.6363961030678927")); + GroupStatistics alteredGroupStats1 = new GroupStatistics(); + alteredGroupStats1.setName("altered samples"); + alteredGroupStats1.setMeanExpression(new BigDecimal("2.5")); + alteredGroupStats1.setStandardDeviation(new BigDecimal("0.7071067811865476")); + enrichment1.setGroupsStatistics(List.of(unalteredGroupStats1, alteredGroupStats1)); + enrichment1.setpValue(new BigDecimal("0.9475795430163914")); + expectedEnrichments.add(enrichment1); + + GenericAssayEnrichment enrichment2 = new GenericAssayEnrichment(); + enrichment2.setStableId(HUGO_GENE_SYMBOL_2); + GroupStatistics unalteredGroupStats2 = new GroupStatistics(); + unalteredGroupStats2.setName("unaltered samples"); + unalteredGroupStats2.setMeanExpression(new BigDecimal("2.65")); + unalteredGroupStats2.setStandardDeviation(new BigDecimal("0.4949747468305834")); + GroupStatistics alteredGroupStats2 = new GroupStatistics(); + alteredGroupStats2.setName("altered samples"); + alteredGroupStats2.setMeanExpression(new BigDecimal("3.05")); + alteredGroupStats2.setStandardDeviation(new BigDecimal("2.7577164466275352")); + enrichment2.setGroupsStatistics(List.of(unalteredGroupStats2, alteredGroupStats2)); + enrichment2.setpValue(new BigDecimal("0.8716148250471419")); + expectedEnrichments.add(enrichment2); + Mockito.when( + expressionEnrichmentUtil.getEnrichments( + geneMolecularProfile, + molecularProfileCaseSets, + EnrichmentType.SAMPLE, + molecularDataList)) + .thenReturn(expectedEnrichments); + + Mockito.when( + genericAssayService.getGenericAssayMetaByStableIdsAndMolecularIds( + Arrays.asList(HUGO_GENE_SYMBOL_1, HUGO_GENE_SYMBOL_2), + Arrays.asList(MOLECULAR_PROFILE_ID, MOLECULAR_PROFILE_ID), + "SUMMARY")) + .thenReturn( + Arrays.asList( + new GenericAssayMeta(HUGO_GENE_SYMBOL_1), + new GenericAssayMeta(HUGO_GENE_SYMBOL_2))); + + // add 5th sample which is the second sample of patient 4 + Sample sample5 = new Sample(); + sample5.setStableId(SAMPLE_ID5); + sample5.setInternalId(5); + sample5.setCancerStudyIdentifier(STUDY_ID); + sample5.setPatientId(4); + samples.add(sample5); + + Mockito.when( + sampleService.fetchSamples( + Arrays.asList(STUDY_ID, STUDY_ID, STUDY_ID, STUDY_ID, STUDY_ID), + Arrays.asList(SAMPLE_ID3, SAMPLE_ID4, SAMPLE_ID5, SAMPLE_ID1, SAMPLE_ID2), + "SUMMARY")) + .thenReturn(samples); + + List result = + enrichmentServiceImpl.getGenericAssayNumericalEnrichments( + MOLECULAR_PROFILE_ID, molecularProfilePatientLevelCaseSets, EnrichmentType.SAMPLE); + + Assert.assertEquals(2, result.size()); + GenericAssayEnrichment genericAssayEnrichment = result.get(0); + Assert.assertEquals(HUGO_GENE_SYMBOL_1, genericAssayEnrichment.getStableId()); + Assert.assertEquals(2, genericAssayEnrichment.getGroupsStatistics().size()); + + GroupStatistics unalteredGroupStats = genericAssayEnrichment.getGroupsStatistics().get(0); + Assert.assertEquals("unaltered samples", unalteredGroupStats.getName()); + Assert.assertEquals(new BigDecimal("2.55"), unalteredGroupStats.getMeanExpression()); + Assert.assertEquals( + new BigDecimal("0.6363961030678927"), unalteredGroupStats.getStandardDeviation()); + + GroupStatistics alteredGroupStats = genericAssayEnrichment.getGroupsStatistics().get(1); + Assert.assertEquals("altered samples", alteredGroupStats.getName()); + Assert.assertEquals(new BigDecimal("2.5"), alteredGroupStats.getMeanExpression()); + Assert.assertEquals( + new BigDecimal("0.7071067811865476"), alteredGroupStats.getStandardDeviation()); + + Assert.assertEquals(new BigDecimal("0.9475795430163914"), genericAssayEnrichment.getpValue()); + + genericAssayEnrichment = result.get(1); + Assert.assertEquals(HUGO_GENE_SYMBOL_2, genericAssayEnrichment.getStableId()); + Assert.assertEquals(2, genericAssayEnrichment.getGroupsStatistics().size()); + + unalteredGroupStats = genericAssayEnrichment.getGroupsStatistics().get(0); + Assert.assertEquals("unaltered samples", unalteredGroupStats.getName()); + Assert.assertEquals(new BigDecimal("2.65"), unalteredGroupStats.getMeanExpression()); + Assert.assertEquals( + new BigDecimal("0.4949747468305834"), unalteredGroupStats.getStandardDeviation()); + + alteredGroupStats = genericAssayEnrichment.getGroupsStatistics().get(1); + Assert.assertEquals("altered samples", alteredGroupStats.getName()); + Assert.assertEquals(new BigDecimal("3.05"), alteredGroupStats.getMeanExpression()); + Assert.assertEquals( + new BigDecimal("2.7577164466275352"), alteredGroupStats.getStandardDeviation()); + + Assert.assertEquals(new BigDecimal("0.8716148250471419"), genericAssayEnrichment.getpValue()); + } +} diff --git a/src/test/java/org/cbioportal/legacy/service/impl/GeneMemoizerServiceTest.java b/src/test/java/org/cbioportal/legacy/service/impl/GeneMemoizerServiceTest.java new file mode 100644 index 00000000000..0092a090096 --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/service/impl/GeneMemoizerServiceTest.java @@ -0,0 +1,78 @@ +package org.cbioportal.legacy.service.impl; + +import java.util.Arrays; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import org.cbioportal.legacy.model.ReferenceGenomeGene; +import org.cbioportal.legacy.service.StaticDataTimestampService; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.junit.MockitoJUnitRunner; + +@RunWith(MockitoJUnitRunner.class) +public class GeneMemoizerServiceTest { + @Mock private StaticDataTimestampService timestampService; + + @InjectMocks private GeneMemoizerServiceImpl geneMemoizerService; + + private static final String GENOME = "hg19"; + private static final List GENES = + Arrays.asList(gene("BRAF"), gene("NRAS"), gene("KRAS"), gene("SUGT1P4-STRA6LP-CCDC180")); + + private static ReferenceGenomeGene gene(String name) { + ReferenceGenomeGene referenceGenomeGene = new ReferenceGenomeGene(); + referenceGenomeGene.setHugoGeneSymbol(name); + return referenceGenomeGene; + } + + @Test + public void shouldReturnNullWhenUncached() throws Exception { + initializeTimestamps(new Date(), new Date()); + + List actual = geneMemoizerService.fetchGenes("hg19"); + + Assert.assertEquals(null, actual); + } + + @Test + public void shouldReturnCachedWhenNeitherExpired() throws Exception { + initializeTimestamps(new Date(0L), new Date(0L)); + geneMemoizerService.cacheGenes(GENES, GENOME); + + List actual = geneMemoizerService.fetchGenes("hg19"); + + Assert.assertEquals(GENES, actual); + } + + @Test + public void shouldReturnNullWhenGeneExpired() throws Exception { + initializeTimestamps(new Date(Long.MAX_VALUE), new Date(0L)); + geneMemoizerService.cacheGenes(GENES, GENOME); + + List actual = geneMemoizerService.fetchGenes("hg19"); + + Assert.assertEquals(null, actual); + } + + @Test + public void shouldReturnNullWhenGenomeExpired() throws Exception { + initializeTimestamps(new Date(0L), new Date(Long.MAX_VALUE)); + geneMemoizerService.cacheGenes(GENES, GENOME); + + List actual = geneMemoizerService.fetchGenes("hg19"); + + Assert.assertEquals(null, actual); + } + + private void initializeTimestamps(Date gene, Date referenceGenomeGene) { + HashMap timestamps = new HashMap<>(); + timestamps.put("gene", gene); + timestamps.put("reference_genome_gene", referenceGenomeGene); + Mockito.when(timestampService.getTimestampsAsDates(Mockito.anyList())).thenReturn(timestamps); + } +} diff --git a/src/test/java/org/cbioportal/legacy/service/impl/GenePanelServiceImplTest.java b/src/test/java/org/cbioportal/legacy/service/impl/GenePanelServiceImplTest.java new file mode 100644 index 00000000000..77b14217bed --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/service/impl/GenePanelServiceImplTest.java @@ -0,0 +1,309 @@ +package org.cbioportal.legacy.service.impl; + +import java.util.*; +import java.util.stream.Collectors; +import org.cbioportal.legacy.model.GenePanel; +import org.cbioportal.legacy.model.GenePanelData; +import org.cbioportal.legacy.model.GenePanelToGene; +import org.cbioportal.legacy.model.MolecularProfile; +import org.cbioportal.legacy.model.MolecularProfileCaseIdentifier; +import org.cbioportal.legacy.model.meta.BaseMeta; +import org.cbioportal.legacy.persistence.GenePanelRepository; +import org.cbioportal.legacy.service.MolecularProfileService; +import org.cbioportal.legacy.service.exception.GenePanelNotFoundException; +import org.cbioportal.legacy.service.util.MolecularProfileUtil; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.Spy; +import org.mockito.junit.MockitoJUnitRunner; + +@RunWith(MockitoJUnitRunner.Silent.class) +public class GenePanelServiceImplTest extends BaseServiceImplTest { + + @InjectMocks private GenePanelServiceImpl genePanelService; + + @Mock private GenePanelRepository genePanelRepository; + @Mock private MolecularProfileService molecularProfileService; + @Spy @InjectMocks private MolecularProfileUtil molecularProfileUtil; + + @Test + public void getAllGenePanelsSummaryProjection() throws Exception { + + List expectedGenePanelList = new ArrayList<>(); + + Mockito.when( + genePanelRepository.getAllGenePanels( + "SUMMARY", PAGE_SIZE, PAGE_NUMBER, SORT, DIRECTION)) + .thenReturn(expectedGenePanelList); + + List result = + genePanelService.getAllGenePanels("SUMMARY", PAGE_SIZE, PAGE_NUMBER, SORT, DIRECTION); + + Assert.assertEquals(expectedGenePanelList, result); + } + + @Test + public void getAllGenePanelsDetailedProjection() throws Exception { + + List expectedGenePanelList = new ArrayList<>(); + GenePanel genePanel = new GenePanel(); + genePanel.setStableId(GENE_PANEL_ID); + expectedGenePanelList.add(genePanel); + List expectedGenePanelToGeneList = new ArrayList<>(); + GenePanelToGene genePanelToGene = new GenePanelToGene(); + genePanelToGene.setGenePanelId(GENE_PANEL_ID); + expectedGenePanelToGeneList.add(genePanelToGene); + + Mockito.when( + genePanelRepository.getAllGenePanels( + "DETAILED", PAGE_SIZE, PAGE_NUMBER, SORT, DIRECTION)) + .thenReturn(expectedGenePanelList); + + Mockito.when(genePanelRepository.getGenesOfPanels(Arrays.asList(GENE_PANEL_ID))) + .thenReturn(expectedGenePanelToGeneList); + + List result = + genePanelService.getAllGenePanels("DETAILED", PAGE_SIZE, PAGE_NUMBER, SORT, DIRECTION); + + Assert.assertEquals(expectedGenePanelList, result); + Assert.assertEquals(1, result.size()); + Assert.assertEquals(genePanel, result.get(0)); + Assert.assertEquals(1, result.get(0).getGenes().size()); + Assert.assertEquals(genePanelToGene, result.get(0).getGenes().get(0)); + } + + @Test + public void getMetaGenePanels() throws Exception { + + BaseMeta expectedBaseMeta = new BaseMeta(); + + Mockito.when(genePanelRepository.getMetaGenePanels()).thenReturn(expectedBaseMeta); + + BaseMeta result = genePanelService.getMetaGenePanels(); + + Assert.assertEquals(expectedBaseMeta, result); + } + + @Test(expected = GenePanelNotFoundException.class) + public void getGenePanelNotFound() throws Exception { + + Mockito.when(genePanelRepository.getGenePanel(GENE_PANEL_ID)).thenReturn(null); + + genePanelService.getGenePanel(GENE_PANEL_ID); + } + + @Test + public void getGenePanel() throws Exception { + + GenePanel genePanel = new GenePanel(); + genePanel.setStableId(GENE_PANEL_ID); + List expectedGenePanelToGeneList = new ArrayList<>(); + GenePanelToGene genePanelToGene = new GenePanelToGene(); + genePanelToGene.setGenePanelId(GENE_PANEL_ID); + expectedGenePanelToGeneList.add(genePanelToGene); + + Mockito.when(genePanelRepository.getGenePanel(GENE_PANEL_ID)).thenReturn(genePanel); + + Mockito.when(genePanelRepository.getGenesOfPanels(Arrays.asList(GENE_PANEL_ID))) + .thenReturn(expectedGenePanelToGeneList); + + GenePanel result = genePanelService.getGenePanel(GENE_PANEL_ID); + + Assert.assertEquals(genePanel, result); + Assert.assertEquals(1, result.getGenes().size()); + Assert.assertEquals(genePanelToGene, result.getGenes().get(0)); + } + + @Test + public void getGenePanelData() throws Exception { + + List genePanelDataList = new ArrayList<>(); + GenePanelData genePanelData = new GenePanelData(); + genePanelData.setGenePanelId(GENE_PANEL_ID); + genePanelData.setMolecularProfileId(MOLECULAR_PROFILE_ID); + genePanelData.setSampleId(SAMPLE_ID1); + genePanelData.setPatientId(PATIENT_ID_1); + genePanelData.setStudyId(STUDY_ID); + genePanelData.setProfiled(true); + genePanelDataList.add(genePanelData); + GenePanelData genePanelData2 = new GenePanelData(); + genePanelData2.setMolecularProfileId(MOLECULAR_PROFILE_ID); + genePanelData2.setSampleId(SAMPLE_ID2); + genePanelData2.setPatientId(PATIENT_ID_2); + genePanelData2.setStudyId(STUDY_ID); + genePanelData2.setProfiled(false); + genePanelDataList.add(genePanelData2); + + MolecularProfile molecularProfile = new MolecularProfile(); + molecularProfile.setStableId(MOLECULAR_PROFILE_ID); + molecularProfile.setCancerStudyIdentifier(STUDY_ID); + molecularProfile.setMolecularAlterationType( + MolecularProfile.MolecularAlterationType.COPY_NUMBER_ALTERATION); + + Mockito.when(molecularProfileService.getMolecularProfile(MOLECULAR_PROFILE_ID)) + .thenReturn(molecularProfile); + + Mockito.when( + genePanelRepository.getGenePanelDataBySampleListId( + MOLECULAR_PROFILE_ID, SAMPLE_LIST_ID)) + .thenReturn(genePanelDataList); + + List result = + genePanelService.getGenePanelData(MOLECULAR_PROFILE_ID, SAMPLE_LIST_ID); + + Assert.assertEquals(2, result.size()); + GenePanelData resultGenePanelData1 = result.get(0); + Assert.assertEquals(SAMPLE_ID1, resultGenePanelData1.getSampleId()); + Assert.assertEquals(GENE_PANEL_ID, resultGenePanelData1.getGenePanelId()); + Assert.assertEquals(MOLECULAR_PROFILE_ID, resultGenePanelData1.getMolecularProfileId()); + Assert.assertEquals(PATIENT_ID_1, resultGenePanelData1.getPatientId()); + Assert.assertEquals(STUDY_ID, resultGenePanelData1.getStudyId()); + Assert.assertEquals(true, resultGenePanelData1.getProfiled()); + GenePanelData resultGenePanelData2 = result.get(1); + Assert.assertEquals(SAMPLE_ID2, resultGenePanelData2.getSampleId()); + Assert.assertNull(resultGenePanelData2.getGenePanelId()); + Assert.assertEquals(MOLECULAR_PROFILE_ID, resultGenePanelData2.getMolecularProfileId()); + Assert.assertEquals(PATIENT_ID_2, resultGenePanelData2.getPatientId()); + Assert.assertEquals(STUDY_ID, resultGenePanelData2.getStudyId()); + Assert.assertEquals(false, resultGenePanelData2.getProfiled()); + } + + @Test + public void getGenePanelDataInvalidSampleListId() throws Exception { + + MolecularProfile molecularProfile = new MolecularProfile(); + molecularProfile.setStableId(MOLECULAR_PROFILE_ID); + molecularProfile.setCancerStudyIdentifier(STUDY_ID); + molecularProfile.setMolecularAlterationType( + MolecularProfile.MolecularAlterationType.COPY_NUMBER_ALTERATION); + + Mockito.when(molecularProfileService.getMolecularProfile(MOLECULAR_PROFILE_ID)) + .thenReturn(molecularProfile); + + List result = + genePanelService.getGenePanelData(MOLECULAR_PROFILE_ID, SAMPLE_LIST_ID); + + Assert.assertEquals(0, result.size()); + } + + @Test + public void fetchGenePanelData() throws Exception { + + List genePanelDataList = new ArrayList<>(); + GenePanelData genePanelData = new GenePanelData(); + genePanelData.setGenePanelId(GENE_PANEL_ID); + genePanelData.setMolecularProfileId(MOLECULAR_PROFILE_ID); + genePanelData.setSampleId(SAMPLE_ID1); + genePanelData.setPatientId(PATIENT_ID_1); + genePanelData.setStudyId(STUDY_ID); + genePanelData.setProfiled(true); + genePanelDataList.add(genePanelData); + + MolecularProfile molecularProfile = new MolecularProfile(); + molecularProfile.setStableId(MOLECULAR_PROFILE_ID); + molecularProfile.setCancerStudyIdentifier(STUDY_ID); + molecularProfile.setMolecularAlterationType( + MolecularProfile.MolecularAlterationType.COPY_NUMBER_ALTERATION); + + Mockito.when( + molecularProfileService.getMolecularProfiles( + Collections.singleton(MOLECULAR_PROFILE_ID), "SUMMARY")) + .thenReturn(Arrays.asList(molecularProfile)); + + Mockito.when(genePanelRepository.fetchGenePanelDataByMolecularProfileId(MOLECULAR_PROFILE_ID)) + .thenReturn(genePanelDataList); + + List result = + genePanelService.fetchGenePanelData( + MOLECULAR_PROFILE_ID, Arrays.asList(SAMPLE_ID1, SAMPLE_ID2)); + + Assert.assertEquals(1, result.size()); + GenePanelData resultGenePanelData1 = result.get(0); + Assert.assertEquals(SAMPLE_ID1, resultGenePanelData1.getSampleId()); + Assert.assertEquals(GENE_PANEL_ID, resultGenePanelData1.getGenePanelId()); + Assert.assertEquals(MOLECULAR_PROFILE_ID, resultGenePanelData1.getMolecularProfileId()); + Assert.assertEquals(PATIENT_ID_1, resultGenePanelData1.getPatientId()); + Assert.assertEquals(STUDY_ID, resultGenePanelData1.getStudyId()); + Assert.assertEquals(true, resultGenePanelData1.getProfiled()); + } + + @Test + public void fetchGenePanelDataInMultipleMolecularProfiles() throws Exception { + + List genePanelDataList = new ArrayList<>(); + GenePanelData genePanelData = new GenePanelData(); + genePanelData.setGenePanelId(GENE_PANEL_ID); + genePanelData.setMolecularProfileId(MOLECULAR_PROFILE_ID); + genePanelData.setSampleId(SAMPLE_ID1); + genePanelData.setPatientId(PATIENT_ID_1); + genePanelData.setStudyId(STUDY_ID); + genePanelData.setProfiled(true); + genePanelDataList.add(genePanelData); + + GenePanelData genePanelData2 = new GenePanelData(); + genePanelData2.setMolecularProfileId(MOLECULAR_PROFILE_ID); + genePanelData2.setSampleId(SAMPLE_ID2); + genePanelData2.setPatientId(PATIENT_ID_2); + genePanelData2.setStudyId(STUDY_ID); + genePanelData2.setProfiled(true); + genePanelDataList.add(genePanelData2); + + Set molecularProfileSampleIdentifiers = new HashSet<>(); + MolecularProfileCaseIdentifier profileCaseIdentifier = new MolecularProfileCaseIdentifier(); + profileCaseIdentifier.setMolecularProfileId(MOLECULAR_PROFILE_ID); + profileCaseIdentifier.setCaseId(SAMPLE_ID1); + molecularProfileSampleIdentifiers.add(profileCaseIdentifier); + + MolecularProfileCaseIdentifier profileCaseIdentifier2 = new MolecularProfileCaseIdentifier(); + profileCaseIdentifier2.setMolecularProfileId(MOLECULAR_PROFILE_ID); + profileCaseIdentifier2.setCaseId(SAMPLE_ID2); + molecularProfileSampleIdentifiers.add(profileCaseIdentifier2); + + MolecularProfileCaseIdentifier profileCaseIdentifier3 = new MolecularProfileCaseIdentifier(); + profileCaseIdentifier3.setMolecularProfileId("invalid_profile"); + profileCaseIdentifier3.setCaseId(SAMPLE_ID3); + molecularProfileSampleIdentifiers.add(profileCaseIdentifier3); + + Mockito.when(genePanelRepository.fetchGenePanelDataByMolecularProfileId(MOLECULAR_PROFILE_ID)) + .thenReturn(genePanelDataList); + Set molecularProfileIds = + molecularProfileSampleIdentifiers.stream() + .map(MolecularProfileCaseIdentifier::getMolecularProfileId) + .collect(Collectors.toSet()); + + MolecularProfile molecularProfile = new MolecularProfile(); + molecularProfile.setStableId(MOLECULAR_PROFILE_ID); + molecularProfile.setCancerStudyIdentifier(STUDY_ID); + molecularProfile.setMolecularAlterationType( + MolecularProfile.MolecularAlterationType.COPY_NUMBER_ALTERATION); + + Mockito.when( + molecularProfileService.getMolecularProfiles( + new HashSet<>(molecularProfileIds), "SUMMARY")) + .thenReturn(Arrays.asList(molecularProfile)); + + List result = + genePanelService.fetchGenePanelDataInMultipleMolecularProfiles( + new ArrayList<>(molecularProfileSampleIdentifiers)); + + Assert.assertEquals(2, result.size()); + GenePanelData resultGenePanelData1 = result.get(0); + Assert.assertEquals(SAMPLE_ID1, resultGenePanelData1.getSampleId()); + Assert.assertEquals(GENE_PANEL_ID, resultGenePanelData1.getGenePanelId()); + Assert.assertEquals(MOLECULAR_PROFILE_ID, resultGenePanelData1.getMolecularProfileId()); + Assert.assertEquals(PATIENT_ID_1, resultGenePanelData1.getPatientId()); + Assert.assertEquals(STUDY_ID, resultGenePanelData1.getStudyId()); + Assert.assertEquals(true, resultGenePanelData1.getProfiled()); + GenePanelData resultGenePanelData2 = result.get(1); + Assert.assertEquals(SAMPLE_ID2, resultGenePanelData2.getSampleId()); + Assert.assertNull(resultGenePanelData2.getGenePanelId()); + Assert.assertEquals(MOLECULAR_PROFILE_ID, resultGenePanelData2.getMolecularProfileId()); + Assert.assertEquals(PATIENT_ID_2, resultGenePanelData2.getPatientId()); + Assert.assertEquals(STUDY_ID, resultGenePanelData2.getStudyId()); + Assert.assertEquals(true, resultGenePanelData2.getProfiled()); + } +} diff --git a/src/test/java/org/cbioportal/legacy/service/impl/GeneServiceImplTest.java b/src/test/java/org/cbioportal/legacy/service/impl/GeneServiceImplTest.java new file mode 100644 index 00000000000..e459afcd4cf --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/service/impl/GeneServiceImplTest.java @@ -0,0 +1,177 @@ +package org.cbioportal.legacy.service.impl; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import org.cbioportal.legacy.model.Gene; +import org.cbioportal.legacy.model.meta.BaseMeta; +import org.cbioportal.legacy.persistence.GeneRepository; +import org.cbioportal.legacy.service.exception.GeneNotFoundException; +import org.cbioportal.legacy.service.util.ChromosomeCalculator; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.junit.MockitoJUnitRunner; + +@RunWith(MockitoJUnitRunner.class) +public class GeneServiceImplTest extends BaseServiceImplTest { + + @InjectMocks private GeneServiceImpl geneService; + + @Mock private GeneRepository geneRepository; + @Mock private ChromosomeCalculator chromosomeCalculator; + + @Test + public void getAllGenes() throws Exception { + + List expectedGeneList = new ArrayList<>(); + Gene gene = new Gene(); + gene.setHugoGeneSymbol(HUGO_GENE_SYMBOL); + expectedGeneList.add(gene); + + Mockito.when( + geneRepository.getAllGenes( + KEYWORD, ALIAS, PROJECTION, PAGE_SIZE, PAGE_NUMBER, SORT, DIRECTION)) + .thenReturn(expectedGeneList); + + List result = + geneService.getAllGenes( + KEYWORD, ALIAS, PROJECTION, PAGE_SIZE, PAGE_NUMBER, SORT, DIRECTION); + + Assert.assertEquals(expectedGeneList, result); + } + + @Test + public void getMetaGenes() throws Exception { + + BaseMeta expectedBaseMeta = new BaseMeta(); + Mockito.when(geneRepository.getMetaGenes(null, ALIAS)).thenReturn(expectedBaseMeta); + + BaseMeta result = geneService.getMetaGenes(null, ALIAS); + + Assert.assertEquals(expectedBaseMeta, result); + } + + @Test(expected = GeneNotFoundException.class) + public void getGeneByEntrezGeneIdNotFound() throws Exception { + + Mockito.when(geneRepository.getGeneByEntrezGeneId(ENTREZ_GENE_ID_1)).thenReturn(null); + + geneService.getGene(ENTREZ_GENE_ID_1.toString()); + } + + @Test + public void getGeneByEntrezGeneId() throws Exception { + + Gene expectedGene = new Gene(); + Mockito.when(geneRepository.getGeneByEntrezGeneId(ENTREZ_GENE_ID_1)).thenReturn(expectedGene); + + Gene result = geneService.getGene(ENTREZ_GENE_ID_1.toString()); + + Assert.assertEquals(expectedGene, result); + } + + @Test(expected = GeneNotFoundException.class) + public void getGeneByHugoGeneSymbolNotFound() throws Exception { + + Mockito.when(geneRepository.getGeneByHugoGeneSymbol(HUGO_GENE_SYMBOL)).thenReturn(null); + + geneService.getGene(HUGO_GENE_SYMBOL); + } + + @Test + public void getGeneByHugoGeneSymbol() throws Exception { + + Gene expectedGene = new Gene(); + Mockito.when(geneRepository.getGeneByHugoGeneSymbol(HUGO_GENE_SYMBOL)).thenReturn(expectedGene); + + Gene result = geneService.getGene(HUGO_GENE_SYMBOL); + + Assert.assertEquals(expectedGene, result); + } + + @Test + public void getAliasesOfGeneByEntrezGeneId() throws Exception { + + Gene expectedGene = new Gene(); + Mockito.when(geneRepository.getGeneByEntrezGeneId(ENTREZ_GENE_ID_1)).thenReturn(expectedGene); + List expectedAliases = new ArrayList<>(); + expectedAliases.add("alias"); + Mockito.when(geneRepository.getAliasesOfGeneByEntrezGeneId(ENTREZ_GENE_ID_1)) + .thenReturn(expectedAliases); + List result = geneService.getAliasesOfGene(ENTREZ_GENE_ID_1.toString()); + + Assert.assertEquals(expectedAliases, result); + } + + @Test(expected = GeneNotFoundException.class) + public void getAliasesOfGeneByEntrezGeneIdGeneNotFound() throws Exception { + + Mockito.when(geneRepository.getGeneByEntrezGeneId(ENTREZ_GENE_ID_1)).thenReturn(null); + geneService.getAliasesOfGene(ENTREZ_GENE_ID_1.toString()); + } + + @Test + public void getAliasesOfGeneByHugoGeneSymbol() throws Exception { + + Gene expectedGene = new Gene(); + Mockito.when(geneRepository.getGeneByHugoGeneSymbol(HUGO_GENE_SYMBOL)).thenReturn(expectedGene); + List expectedAliases = new ArrayList<>(); + expectedAliases.add("alias"); + Mockito.when(geneRepository.getAliasesOfGeneByHugoGeneSymbol(HUGO_GENE_SYMBOL)) + .thenReturn(expectedAliases); + List result = geneService.getAliasesOfGene(HUGO_GENE_SYMBOL); + + Assert.assertEquals(expectedAliases, result); + } + + @Test(expected = GeneNotFoundException.class) + public void getAliasesOfGeneByHugoGeneSymbolGeneNotFound() throws Exception { + + Mockito.when(geneRepository.getGeneByHugoGeneSymbol(HUGO_GENE_SYMBOL)).thenReturn(null); + geneService.getAliasesOfGene(HUGO_GENE_SYMBOL); + } + + @Test + public void fetchGenes() throws Exception { + + List expectedGeneList = new ArrayList<>(); + Gene gene = new Gene(); + gene.setHugoGeneSymbol(HUGO_GENE_SYMBOL); + expectedGeneList.add(gene); + + List geneIds = new ArrayList<>(); + geneIds.add(HUGO_GENE_SYMBOL); + + Mockito.when( + geneRepository.fetchGenesByHugoGeneSymbols(Arrays.asList(HUGO_GENE_SYMBOL), PROJECTION)) + .thenReturn(expectedGeneList); + + List result = geneService.fetchGenes(geneIds, GENE_ID_TYPE, PROJECTION); + + Assert.assertEquals(1, result.size()); + Assert.assertEquals(gene, result.get(0)); + } + + @Test + public void fetchMetaGenes() throws Exception { + + BaseMeta expectedBaseMeta1 = new BaseMeta(); + expectedBaseMeta1.setTotalCount(1); + BaseMeta expectedBaseMeta2 = new BaseMeta(); + expectedBaseMeta2.setTotalCount(1); + + List geneIds = new ArrayList<>(); + geneIds.add(HUGO_GENE_SYMBOL); + + Mockito.when(geneRepository.fetchMetaGenesByHugoGeneSymbols(Arrays.asList(HUGO_GENE_SYMBOL))) + .thenReturn(expectedBaseMeta2); + + BaseMeta result = geneService.fetchMetaGenes(geneIds, GENE_ID_TYPE); + + Assert.assertEquals((Integer) 1, result.getTotalCount()); + } +} diff --git a/src/test/java/org/cbioportal/legacy/service/impl/GenericAssayEnrichmentServiceImplTest.java b/src/test/java/org/cbioportal/legacy/service/impl/GenericAssayEnrichmentServiceImplTest.java new file mode 100644 index 00000000000..19445be424c --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/service/impl/GenericAssayEnrichmentServiceImplTest.java @@ -0,0 +1,359 @@ +package org.cbioportal.legacy.service.impl; + +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import org.cbioportal.legacy.model.CancerStudy; +import org.cbioportal.legacy.model.EnrichmentType; +import org.cbioportal.legacy.model.ExpressionEnrichment; +import org.cbioportal.legacy.model.GenericAssayBinaryEnrichment; +import org.cbioportal.legacy.model.GenericAssayCategoricalEnrichment; +import org.cbioportal.legacy.model.GenericAssayMolecularAlteration; +import org.cbioportal.legacy.model.GroupStatistics; +import org.cbioportal.legacy.model.MolecularProfile; +import org.cbioportal.legacy.model.MolecularProfileCaseIdentifier; +import org.cbioportal.legacy.model.MolecularProfileSamples; +import org.cbioportal.legacy.model.ReferenceGenome; +import org.cbioportal.legacy.model.Sample; +import org.cbioportal.legacy.model.meta.GenericAssayMeta; +import org.cbioportal.legacy.persistence.MolecularDataRepository; +import org.cbioportal.legacy.service.GenericAssayService; +import org.cbioportal.legacy.service.MolecularProfileService; +import org.cbioportal.legacy.service.SampleService; +import org.cbioportal.legacy.service.exception.MolecularProfileNotFoundException; +import org.cbioportal.legacy.service.util.ExpressionEnrichmentUtil; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.junit.MockitoJUnitRunner; + +@RunWith(MockitoJUnitRunner.class) +public class GenericAssayEnrichmentServiceImplTest extends BaseServiceImplTest { + @InjectMocks private ExpressionEnrichmentServiceImpl expressionEnrichmentServiceImpl; + @Mock private SampleService sampleService; + @Mock private MolecularProfileService molecularProfileService; + @Mock private MolecularDataRepository molecularDataRepository; + + @Mock private GenericAssayService genericAssayService; + + @Mock private ExpressionEnrichmentUtil expressionEnrichmentUtil; + + CancerStudy cancerStudy = new CancerStudy(); + MolecularProfile geneMolecularProfile = new MolecularProfile(); + MolecularProfileSamples molecularProfileSamples = new MolecularProfileSamples(); + List samples = new ArrayList<>(); + Map> molecularProfileCaseSets = new HashMap<>(); + Map> molecularProfilePatientLevelCaseSets = + new HashMap<>(); + // patient level only data + public static final String SAMPLE_ID5 = "sample_id5"; + + @Before + public void setup() throws MolecularProfileNotFoundException { + cancerStudy.setReferenceGenome(ReferenceGenome.HOMO_SAPIENS_DEFAULT_GENOME_NAME); + cancerStudy.setCancerStudyIdentifier(STUDY_ID); + + geneMolecularProfile.setCancerStudyIdentifier(STUDY_ID); + geneMolecularProfile.setStableId(MOLECULAR_PROFILE_ID); + + geneMolecularProfile.setCancerStudy(cancerStudy); + + molecularProfileSamples.setMolecularProfileId(MOLECULAR_PROFILE_ID); + molecularProfileSamples.setCommaSeparatedSampleIds("1,2,3,4"); + + Sample sample1 = new Sample(); + sample1.setStableId(SAMPLE_ID1); + sample1.setInternalId(1); + sample1.setCancerStudyIdentifier(STUDY_ID); + sample1.setPatientId(1); + samples.add(sample1); + Sample sample2 = new Sample(); + sample2.setStableId(SAMPLE_ID2); + sample2.setInternalId(2); + sample2.setCancerStudyIdentifier(STUDY_ID); + sample2.setPatientId(2); + samples.add(sample2); + Sample sample3 = new Sample(); + sample3.setStableId(SAMPLE_ID3); + sample3.setInternalId(3); + sample3.setCancerStudyIdentifier(STUDY_ID); + sample3.setPatientId(3); + samples.add(sample3); + Sample sample4 = new Sample(); + sample4.setStableId(SAMPLE_ID4); + sample4.setInternalId(4); + sample4.setCancerStudyIdentifier(STUDY_ID); + sample4.setPatientId(4); + samples.add(sample4); + + List alteredSampleIdentifieres = new ArrayList<>(); + List unalteredSampleIdentifieres = new ArrayList<>(); + List unalteredPatientLevelSampleIdentifieres = + new ArrayList<>(); + + MolecularProfileCaseIdentifier caseIdentifier1 = new MolecularProfileCaseIdentifier(); + caseIdentifier1.setMolecularProfileId(MOLECULAR_PROFILE_ID); + caseIdentifier1.setCaseId(SAMPLE_ID1); + alteredSampleIdentifieres.add(caseIdentifier1); + + MolecularProfileCaseIdentifier caseIdentifier2 = new MolecularProfileCaseIdentifier(); + caseIdentifier2.setMolecularProfileId(MOLECULAR_PROFILE_ID); + caseIdentifier2.setCaseId(SAMPLE_ID2); + alteredSampleIdentifieres.add(caseIdentifier2); + + MolecularProfileCaseIdentifier caseIdentifier3 = new MolecularProfileCaseIdentifier(); + caseIdentifier3.setMolecularProfileId(MOLECULAR_PROFILE_ID); + caseIdentifier3.setCaseId(SAMPLE_ID3); + unalteredSampleIdentifieres.add(caseIdentifier3); + unalteredPatientLevelSampleIdentifieres.add(caseIdentifier3); + + MolecularProfileCaseIdentifier caseIdentifier4 = new MolecularProfileCaseIdentifier(); + caseIdentifier4.setMolecularProfileId(MOLECULAR_PROFILE_ID); + caseIdentifier4.setCaseId(SAMPLE_ID4); + unalteredSampleIdentifieres.add(caseIdentifier4); + unalteredPatientLevelSampleIdentifieres.add(caseIdentifier4); + + // patient level only data + MolecularProfileCaseIdentifier caseIdentifier5 = new MolecularProfileCaseIdentifier(); + caseIdentifier5.setMolecularProfileId(MOLECULAR_PROFILE_ID); + caseIdentifier5.setCaseId(SAMPLE_ID5); + unalteredPatientLevelSampleIdentifieres.add(caseIdentifier5); + + molecularProfileCaseSets.put("altered samples", alteredSampleIdentifieres); + molecularProfileCaseSets.put("unaltered samples", unalteredSampleIdentifieres); + molecularProfilePatientLevelCaseSets.put("altered samples", alteredSampleIdentifieres); + molecularProfilePatientLevelCaseSets.put( + "unaltered samples", unalteredPatientLevelSampleIdentifieres); + + Mockito.when(molecularProfileService.getMolecularProfile(MOLECULAR_PROFILE_ID)) + .thenReturn(geneMolecularProfile); + } + + @Test + public void getGenericAssayBinaryEnrichments() throws Exception { + geneMolecularProfile.setMolecularAlterationType( + MolecularProfile.MolecularAlterationType.GENERIC_ASSAY); + geneMolecularProfile.setDatatype("BINARY"); + List molecularDataList = + new ArrayList(); + GenericAssayMolecularAlteration genericAssayMolecularAlteration1 = + new GenericAssayMolecularAlteration(); + genericAssayMolecularAlteration1.setGenericAssayStableId(HUGO_GENE_SYMBOL_1); + + // here are 2 groups + genericAssayMolecularAlteration1.setValues("true,true,true,false"); + molecularDataList.add(genericAssayMolecularAlteration1); + + GenericAssayMolecularAlteration genericAssayMolecularAlteration2 = + new GenericAssayMolecularAlteration(); + genericAssayMolecularAlteration2.setGenericAssayStableId(HUGO_GENE_SYMBOL_2); + genericAssayMolecularAlteration2.setValues("true,false,false,true"); + molecularDataList.add(genericAssayMolecularAlteration2); + Mockito.when( + molecularDataRepository.getGenericAssayMolecularAlterationsIterable( + MOLECULAR_PROFILE_ID, null, "SUMMARY")) + .thenReturn(molecularDataList); + + List expectedEnrichments = new ArrayList<>(); + GenericAssayBinaryEnrichment enrichment1 = new GenericAssayBinaryEnrichment(); + enrichment1.setStableId(HUGO_GENE_SYMBOL_1); + GroupStatistics unalteredGroupStats1 = new GroupStatistics(); + unalteredGroupStats1.setName("unaltered samples"); + unalteredGroupStats1.setMeanExpression(new BigDecimal("0.5")); + unalteredGroupStats1.setStandardDeviation(new BigDecimal("0.7071067811865476")); + GroupStatistics alteredGroupStats1 = new GroupStatistics(); + alteredGroupStats1.setName("altered samples"); + alteredGroupStats1.setMeanExpression(new BigDecimal("1.0")); + alteredGroupStats1.setStandardDeviation(new BigDecimal("0.0")); + enrichment1.setGroupsStatistics(List.of(unalteredGroupStats1, alteredGroupStats1)); + enrichment1.setpValue(new BigDecimal("0.49999999999999983")); + enrichment1.setqValue(new BigDecimal("0.99999999999999966")); + expectedEnrichments.add(enrichment1); + + GenericAssayBinaryEnrichment enrichment2 = new GenericAssayBinaryEnrichment(); + enrichment2.setStableId(HUGO_GENE_SYMBOL_2); + GroupStatistics unalteredGroupStats2 = new GroupStatistics(); + unalteredGroupStats2.setName("unaltered samples"); + unalteredGroupStats2.setMeanExpression(new BigDecimal("0.5")); + unalteredGroupStats2.setStandardDeviation(new BigDecimal("0.7071067811865476")); + GroupStatistics alteredGroupStats2 = new GroupStatistics(); + alteredGroupStats2.setName("altered samples"); + alteredGroupStats2.setMeanExpression(new BigDecimal("0.5")); + alteredGroupStats2.setStandardDeviation(new BigDecimal("0.7071067811865476")); + enrichment2.setGroupsStatistics(List.of(unalteredGroupStats2, alteredGroupStats2)); + enrichment2.setpValue(new BigDecimal("1.0")); + enrichment2.setqValue(new BigDecimal("1.0")); + expectedEnrichments.add(enrichment2); + + Mockito.when( + expressionEnrichmentUtil.getGenericAssayBinaryEnrichments( + geneMolecularProfile, + molecularProfileCaseSets, + EnrichmentType.SAMPLE, + molecularDataList)) + .thenReturn(expectedEnrichments); + + Mockito.when( + genericAssayService.getGenericAssayMetaByStableIdsAndMolecularIds( + Arrays.asList(HUGO_GENE_SYMBOL_1, HUGO_GENE_SYMBOL_2), + Arrays.asList(MOLECULAR_PROFILE_ID, MOLECULAR_PROFILE_ID), + "SUMMARY")) + .thenReturn( + Arrays.asList( + new GenericAssayMeta(HUGO_GENE_SYMBOL_1), + new GenericAssayMeta(HUGO_GENE_SYMBOL_2))); + + List result = + expressionEnrichmentServiceImpl.getGenericAssayBinaryEnrichments( + MOLECULAR_PROFILE_ID, molecularProfileCaseSets, EnrichmentType.SAMPLE); + + Assert.assertEquals(2, result.size()); + GenericAssayBinaryEnrichment genericAssayBinaryEnrichment = result.get(0); + Assert.assertEquals(HUGO_GENE_SYMBOL_1, genericAssayBinaryEnrichment.getStableId()); + Assert.assertEquals(2, genericAssayBinaryEnrichment.getGroupsStatistics().size()); + + GroupStatistics unalteredGroupStats = genericAssayBinaryEnrichment.getGroupsStatistics().get(0); + Assert.assertEquals("unaltered samples", unalteredGroupStats.getName()); + Assert.assertEquals(new BigDecimal("0.5"), unalteredGroupStats.getMeanExpression()); + Assert.assertEquals( + new BigDecimal("0.7071067811865476"), unalteredGroupStats.getStandardDeviation()); + + GroupStatistics alteredGroupStats = genericAssayBinaryEnrichment.getGroupsStatistics().get(1); + Assert.assertEquals("altered samples", alteredGroupStats.getName()); + Assert.assertEquals(new BigDecimal("1.0"), alteredGroupStats.getMeanExpression()); + Assert.assertEquals(new BigDecimal("0.0"), alteredGroupStats.getStandardDeviation()); + + Assert.assertEquals( + new BigDecimal("0.49999999999999983"), genericAssayBinaryEnrichment.getpValue()); + Assert.assertEquals( + new BigDecimal("0.99999999999999966"), genericAssayBinaryEnrichment.getqValue()); + + genericAssayBinaryEnrichment = result.get(1); + Assert.assertEquals(HUGO_GENE_SYMBOL_2, genericAssayBinaryEnrichment.getStableId()); + Assert.assertEquals(2, genericAssayBinaryEnrichment.getGroupsStatistics().size()); + + unalteredGroupStats = genericAssayBinaryEnrichment.getGroupsStatistics().get(0); + Assert.assertEquals("unaltered samples", unalteredGroupStats.getName()); + Assert.assertEquals(new BigDecimal("0.5"), unalteredGroupStats.getMeanExpression()); + Assert.assertEquals( + new BigDecimal("0.7071067811865476"), unalteredGroupStats.getStandardDeviation()); + + alteredGroupStats = genericAssayBinaryEnrichment.getGroupsStatistics().get(1); + Assert.assertEquals("altered samples", alteredGroupStats.getName()); + Assert.assertEquals(new BigDecimal("0.5"), alteredGroupStats.getMeanExpression()); + Assert.assertEquals( + new BigDecimal("0.7071067811865476"), alteredGroupStats.getStandardDeviation()); + + Assert.assertEquals(new BigDecimal("1.0"), genericAssayBinaryEnrichment.getpValue()); + Assert.assertEquals(new BigDecimal("1.0"), genericAssayBinaryEnrichment.getqValue()); + } + + @Test + public void getGenericAssayCategoricalEnrichments() throws MolecularProfileNotFoundException { + geneMolecularProfile.setMolecularAlterationType( + MolecularProfile.MolecularAlterationType.GENERIC_ASSAY); + geneMolecularProfile.setDatatype("CATEGORICAL"); + List molecularDataList = + new ArrayList(); + GenericAssayMolecularAlteration genericAssayMolecularAlteration1 = + new GenericAssayMolecularAlteration(); + genericAssayMolecularAlteration1.setGenericAssayStableId(HUGO_GENE_SYMBOL_1); + genericAssayMolecularAlteration1.setValues("category1,category1,category2,category2"); + molecularDataList.add(genericAssayMolecularAlteration1); + + GenericAssayMolecularAlteration genericAssayMolecularAlteration2 = + new GenericAssayMolecularAlteration(); + genericAssayMolecularAlteration2.setGenericAssayStableId(HUGO_GENE_SYMBOL_2); + genericAssayMolecularAlteration2.setValues("category2,category2,category1,category1"); + molecularDataList.add(genericAssayMolecularAlteration2); + Mockito.when( + molecularDataRepository.getGenericAssayMolecularAlterationsIterable( + MOLECULAR_PROFILE_ID, null, "SUMMARY")) + .thenReturn(molecularDataList); + + List expectedEnrichments = new ArrayList<>(); + GenericAssayCategoricalEnrichment enrichment1 = new GenericAssayCategoricalEnrichment(); + enrichment1.setStableId(HUGO_GENE_SYMBOL_1); + GroupStatistics unalteredGroupStats1 = new GroupStatistics(); + unalteredGroupStats1.setName("unaltered samples"); + GroupStatistics alteredGroupStats1 = new GroupStatistics(); + alteredGroupStats1.setName("altered samples"); + enrichment1.setGroupsStatistics(List.of(unalteredGroupStats1, alteredGroupStats1)); + enrichment1.setpValue(new BigDecimal("0.04550026389635764")); + enrichment1.setqValue(new BigDecimal("0.04550026389635764")); + expectedEnrichments.add(enrichment1); + + GenericAssayCategoricalEnrichment enrichment2 = new GenericAssayCategoricalEnrichment(); + enrichment2.setStableId(HUGO_GENE_SYMBOL_2); + GroupStatistics unalteredGroupStats2 = new GroupStatistics(); + unalteredGroupStats2.setName("unaltered samples"); + GroupStatistics alteredGroupStats2 = new GroupStatistics(); + alteredGroupStats2.setName("altered samples"); + enrichment2.setGroupsStatistics(List.of(unalteredGroupStats2, alteredGroupStats2)); + enrichment2.setpValue(new BigDecimal("0.04550026389635764")); + enrichment2.setqValue(new BigDecimal("0.04550026389635764")); + expectedEnrichments.add(enrichment2); + + Mockito.when( + expressionEnrichmentUtil.getGenericAssayCategoricalEnrichments( + geneMolecularProfile, + molecularProfileCaseSets, + EnrichmentType.SAMPLE, + molecularDataList)) + .thenReturn(expectedEnrichments); + + Mockito.when( + genericAssayService.getGenericAssayMetaByStableIdsAndMolecularIds( + Arrays.asList(HUGO_GENE_SYMBOL_1, HUGO_GENE_SYMBOL_2), + Arrays.asList(MOLECULAR_PROFILE_ID, MOLECULAR_PROFILE_ID), + "SUMMARY")) + .thenReturn( + Arrays.asList( + new GenericAssayMeta(HUGO_GENE_SYMBOL_1), + new GenericAssayMeta(HUGO_GENE_SYMBOL_2))); + + List result = + expressionEnrichmentServiceImpl.getGenericAssayCategoricalEnrichments( + MOLECULAR_PROFILE_ID, molecularProfileCaseSets, EnrichmentType.SAMPLE); + + Assert.assertEquals(2, result.size()); + GenericAssayCategoricalEnrichment genericAssayCategoricalEnrichment = result.get(0); + Assert.assertEquals(HUGO_GENE_SYMBOL_1, genericAssayCategoricalEnrichment.getStableId()); + Assert.assertEquals(2, genericAssayCategoricalEnrichment.getGroupsStatistics().size()); + + GroupStatistics unalteredGroupStats = + genericAssayCategoricalEnrichment.getGroupsStatistics().get(0); + Assert.assertEquals("unaltered samples", unalteredGroupStats.getName()); + + GroupStatistics alteredGroupStats = + genericAssayCategoricalEnrichment.getGroupsStatistics().get(1); + Assert.assertEquals("altered samples", alteredGroupStats.getName()); + + Assert.assertEquals( + new BigDecimal("0.04550026389635764"), genericAssayCategoricalEnrichment.getpValue()); + Assert.assertEquals( + new BigDecimal("0.04550026389635764"), genericAssayCategoricalEnrichment.getqValue()); + + genericAssayCategoricalEnrichment = result.get(1); + Assert.assertEquals(HUGO_GENE_SYMBOL_2, genericAssayCategoricalEnrichment.getStableId()); + Assert.assertEquals(2, genericAssayCategoricalEnrichment.getGroupsStatistics().size()); + + unalteredGroupStats = genericAssayCategoricalEnrichment.getGroupsStatistics().get(0); + Assert.assertEquals("unaltered samples", unalteredGroupStats.getName()); + + alteredGroupStats = genericAssayCategoricalEnrichment.getGroupsStatistics().get(1); + Assert.assertEquals("altered samples", alteredGroupStats.getName()); + + Assert.assertEquals( + new BigDecimal("0.04550026389635764"), genericAssayCategoricalEnrichment.getpValue()); + Assert.assertEquals( + new BigDecimal("0.04550026389635764"), genericAssayCategoricalEnrichment.getqValue()); + } +} diff --git a/src/test/java/org/cbioportal/legacy/service/impl/GenericAssayServiceImpTest.java b/src/test/java/org/cbioportal/legacy/service/impl/GenericAssayServiceImpTest.java new file mode 100644 index 00000000000..93d69660924 --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/service/impl/GenericAssayServiceImpTest.java @@ -0,0 +1,357 @@ +package org.cbioportal.legacy.service.impl; + +import java.util.*; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import org.cbioportal.legacy.model.GenericAssayAdditionalProperty; +import org.cbioportal.legacy.model.GenericAssayData; +import org.cbioportal.legacy.model.GenericAssayMolecularAlteration; +import org.cbioportal.legacy.model.MolecularProfile; +import org.cbioportal.legacy.model.MolecularProfile.MolecularAlterationType; +import org.cbioportal.legacy.model.MolecularProfileSamples; +import org.cbioportal.legacy.model.Sample; +import org.cbioportal.legacy.model.meta.GenericAssayMeta; +import org.cbioportal.legacy.persistence.GenericAssayRepository; +import org.cbioportal.legacy.persistence.MolecularDataRepository; +import org.cbioportal.legacy.persistence.PersistenceConstants; +import org.cbioportal.legacy.service.MolecularProfileService; +import org.cbioportal.legacy.service.SampleService; +import org.cbioportal.legacy.service.exception.GenericAssayNotFoundException; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.junit.MockitoJUnitRunner; + +@RunWith(MockitoJUnitRunner.Silent.class) +public class GenericAssayServiceImpTest extends BaseServiceImplTest { + + public static final String GENERIC_ASSAY_ID_1 = "generic_assay_id_1"; + public static final String STUDY_ID_1 = "study_id_1"; + private static final int INTERNAL_ID_1 = 1; + public static final String GENERIC_ASSAY_ID_2 = "generic_assay_id_2"; + public static final String STUDY_ID_2 = "study_id_2"; + private static final int INTERNAL_ID_2 = 2; + public static final String ENTITY_TYPE = "GENERIC_ASSAY"; + + private static final String PROFILE_ID = "test_profile_id"; + private static final List PROFILE_ID_LIST = Arrays.asList(PROFILE_ID); + private static final List idList = Arrays.asList(GENERIC_ASSAY_ID_1, GENERIC_ASSAY_ID_2); + private static final List mockGenericAssayMetaList = + createGenericAssayMetaList(); + private static final List mockGenericAssayAdditionalPropertyList = + createGenericAssayAdditionalPropertyList(); + private static final String MOLECULAR_PROFILE_ID_1 = "molecular_profile_id_1"; + private static final String MOLECULAR_PROFILE_ID_2 = "molecular_profile_id_2"; + private static final String STABLE_ID_1 = "stable_id_1"; + private static final String STABLE_ID_2 = "stable_id_2"; + + private static final String PROPERTY_NAME_1 = "property_name_1"; + private static final String PROPERTY_NAME_2 = "property_name_2"; + private static final String PROPERTY_VALUE_1 = "property_value_1"; + private static final String PROPERTY_VALUE_2 = "property_value_2"; + + @InjectMocks private GenericAssayServiceImpl genericAssayService; + + @Mock private GenericAssayRepository genericAssayRepository; + @Mock private SampleService sampleService; + @Mock private MolecularProfileService geneticProfileService; + @Mock private MolecularDataRepository geneticDataRepository; + + /** + * This is executed n times, for each of the n test methods below: + * + * @throws Exception + * @throws DaoException + */ + @Before + public void setUp() throws Exception { + + MolecularProfileSamples molecularProfileSamples1 = new MolecularProfileSamples(); + molecularProfileSamples1.setMolecularProfileId(MOLECULAR_PROFILE_ID_1); + molecularProfileSamples1.setCommaSeparatedSampleIds("1,2,"); + + MolecularProfileSamples molecularProfileSamples2 = new MolecularProfileSamples(); + molecularProfileSamples2.setMolecularProfileId(MOLECULAR_PROFILE_ID_2); + molecularProfileSamples2.setCommaSeparatedSampleIds("1,2,"); + + Map commaSeparatedSampleIdsOfMolecularProfilesMap1 = + new HashMap<>(); + commaSeparatedSampleIdsOfMolecularProfilesMap1.put( + MOLECULAR_PROFILE_ID_1, molecularProfileSamples1); + + Map commaSeparatedSampleIdsOfMolecularProfilesMap2 = + new HashMap<>(); + commaSeparatedSampleIdsOfMolecularProfilesMap2.put( + MOLECULAR_PROFILE_ID_1, molecularProfileSamples1); + commaSeparatedSampleIdsOfMolecularProfilesMap2.put( + MOLECULAR_PROFILE_ID_2, molecularProfileSamples2); + + // stub for samples + Mockito.when( + geneticDataRepository.commaSeparatedSampleIdsOfMolecularProfilesMap( + Collections.singleton(MOLECULAR_PROFILE_ID_1))) + .thenReturn(commaSeparatedSampleIdsOfMolecularProfilesMap1); + Mockito.when( + geneticDataRepository.commaSeparatedSampleIdsOfMolecularProfilesMap( + Stream.of(MOLECULAR_PROFILE_ID_1, MOLECULAR_PROFILE_ID_2) + .collect(Collectors.toSet()))) + .thenReturn(commaSeparatedSampleIdsOfMolecularProfilesMap2); + + List sampleList1 = new ArrayList<>(); + Sample sample = new Sample(); + sample.setCancerStudyIdentifier(STUDY_ID); + sample.setInternalId(INTERNAL_ID_1); + sample.setStableId(SAMPLE_ID1); + sampleList1.add(sample); + Mockito.when( + sampleService.fetchSamples(Arrays.asList(STUDY_ID), Arrays.asList(SAMPLE_ID1), "ID")) + .thenReturn(sampleList1); + List sampleListAll = new ArrayList<>(sampleList1); + sample = new Sample(); + sample.setCancerStudyIdentifier(STUDY_ID); + sample.setInternalId(INTERNAL_ID_2); + sample.setStableId(SAMPLE_ID2); + sampleListAll.add(sample); + Mockito.when( + sampleService.fetchSamples( + Arrays.asList(STUDY_ID), Arrays.asList(SAMPLE_ID1, SAMPLE_ID2), "ID")) + .thenReturn(sampleListAll); + Mockito.when( + sampleService.fetchSamples( + Arrays.asList(STUDY_ID, STUDY_ID), Arrays.asList(SAMPLE_ID1, SAMPLE_ID2), "ID")) + .thenReturn(sampleListAll); + + // stub for genetic profile + MolecularProfile geneticProfile1 = new MolecularProfile(); + geneticProfile1.setCancerStudyIdentifier(STUDY_ID); + geneticProfile1.setStableId(MOLECULAR_PROFILE_ID_1); + geneticProfile1.setMolecularAlterationType(MolecularAlterationType.GENERIC_ASSAY); + MolecularProfile geneticProfile2 = new MolecularProfile(); + geneticProfile2.setCancerStudyIdentifier(STUDY_ID); + geneticProfile2.setStableId(MOLECULAR_PROFILE_ID_2); + geneticProfile2.setMolecularAlterationType(MolecularAlterationType.GENERIC_ASSAY); + List geneticProfiles = new ArrayList(); + geneticProfiles.add(geneticProfile1); + geneticProfiles.add(geneticProfile2); + + Mockito.when(geneticProfileService.getMolecularProfile(MOLECULAR_PROFILE_ID_1)) + .thenReturn(geneticProfile1); + Mockito.when( + geneticProfileService.getMolecularProfiles( + Collections.singleton(MOLECULAR_PROFILE_ID_1), "SUMMARY")) + .thenReturn(Arrays.asList(geneticProfile1)); + Mockito.when( + geneticProfileService.getMolecularProfiles( + Stream.of(MOLECULAR_PROFILE_ID_1, MOLECULAR_PROFILE_ID_2) + .collect(Collectors.toSet()), + "SUMMARY")) + .thenReturn(geneticProfiles); + + // stub for repository data + List genericAssayMolecularAlterationList1 = new ArrayList<>(); + + GenericAssayMolecularAlteration genericAssayMolecularAlteration1 = + new GenericAssayMolecularAlteration(); + genericAssayMolecularAlteration1.setMolecularProfileId(MOLECULAR_PROFILE_ID_1); + genericAssayMolecularAlteration1.setGenericAssayStableId(STABLE_ID_1); + genericAssayMolecularAlteration1.setValues("0.2,0.499"); + + GenericAssayMolecularAlteration genericAssayMolecularAlteration2 = + new GenericAssayMolecularAlteration(); + genericAssayMolecularAlteration2.setMolecularProfileId(MOLECULAR_PROFILE_ID_1); + genericAssayMolecularAlteration2.setGenericAssayStableId(STABLE_ID_2); + genericAssayMolecularAlteration2.setValues("0.89,-0.509"); + + genericAssayMolecularAlterationList1.add(genericAssayMolecularAlteration1); + genericAssayMolecularAlterationList1.add(genericAssayMolecularAlteration2); + + List genericAssayMolecularAlterationList2 = new ArrayList<>(); + + genericAssayMolecularAlteration1 = new GenericAssayMolecularAlteration(); + genericAssayMolecularAlteration1.setMolecularProfileId(MOLECULAR_PROFILE_ID_2); + genericAssayMolecularAlteration1.setGenericAssayStableId(STABLE_ID_1); + genericAssayMolecularAlteration1.setValues("0.2,0.499"); + + genericAssayMolecularAlteration2 = new GenericAssayMolecularAlteration(); + genericAssayMolecularAlteration2.setMolecularProfileId(MOLECULAR_PROFILE_ID_2); + genericAssayMolecularAlteration2.setGenericAssayStableId(STABLE_ID_2); + genericAssayMolecularAlteration2.setValues("0.89,-0.509"); + + genericAssayMolecularAlterationList2.add(genericAssayMolecularAlteration1); + genericAssayMolecularAlterationList2.add(genericAssayMolecularAlteration2); + + List entrezGeneIds = new ArrayList<>(); + entrezGeneIds.add(ENTREZ_GENE_ID_1); + Mockito.when( + geneticDataRepository.getGenericAssayMolecularAlterations( + MOLECULAR_PROFILE_ID_1, Arrays.asList(STABLE_ID_1, STABLE_ID_2), "SUMMARY")) + .thenReturn(genericAssayMolecularAlterationList1); + Mockito.when( + geneticDataRepository.getGenericAssayMolecularAlterations( + MOLECULAR_PROFILE_ID_2, Arrays.asList(STABLE_ID_1, STABLE_ID_2), "SUMMARY")) + .thenReturn(genericAssayMolecularAlterationList2); + } + + @Test + public void fetchGenericAssayDataInMultipleMolecularProfiles() throws Exception { + + List result = + genericAssayService.fetchGenericAssayData( + Arrays.asList(MOLECULAR_PROFILE_ID_1, MOLECULAR_PROFILE_ID_2), + Arrays.asList(SAMPLE_ID1, SAMPLE_ID2), + Arrays.asList(STABLE_ID_1, STABLE_ID_2), + PersistenceConstants.SUMMARY_PROJECTION); + + // what we expect: 2 molecular profiles x 2 samples x 2 generic assay items = 8 GenericAssayData + // items: + // MOLECULAR_PROFILE_1: + // SAMPLE_1: + // generic assay1 value: 0.2 + // generic assay2 value: 0.89 + // SAMPLE_2: + // generic assay1 value: 0.499 + // generic assay2 value: -0.509 + // MOLECULAR_PROFILE_2: + // SAMPLE_1: + // generic assay1 value: 0.2 + // generic assay2 value: 0.89 + // SAMPLE_2: + // generic assay1 value: 0.499 + // generic assay2 value: -0.509 + Assert.assertEquals(8, result.size()); + GenericAssayData item1 = result.get(0); + Assert.assertEquals(item1.getSampleId(), SAMPLE_ID1); + Assert.assertEquals(item1.getStableId(), STABLE_ID_1); + Assert.assertEquals(item1.getValue(), "0.2"); + Assert.assertEquals(item1.getMolecularProfileId(), MOLECULAR_PROFILE_ID_1); + GenericAssayData item2 = result.get(1); + Assert.assertEquals(item2.getSampleId(), SAMPLE_ID1); + Assert.assertEquals(item2.getStableId(), STABLE_ID_2); + Assert.assertEquals(item2.getValue(), "0.89"); + Assert.assertEquals(item2.getMolecularProfileId(), MOLECULAR_PROFILE_ID_1); + GenericAssayData item7 = result.get(6); + Assert.assertEquals(item7.getSampleId(), SAMPLE_ID2); + Assert.assertEquals(item7.getStableId(), STABLE_ID_1); + Assert.assertEquals(item7.getValue(), "0.499"); + Assert.assertEquals(item7.getMolecularProfileId(), MOLECULAR_PROFILE_ID_2); + GenericAssayData item8 = result.get(7); + Assert.assertEquals(item8.getSampleId(), SAMPLE_ID2); + Assert.assertEquals(item8.getStableId(), STABLE_ID_2); + Assert.assertEquals(item8.getValue(), "-0.509"); + Assert.assertEquals(item8.getMolecularProfileId(), MOLECULAR_PROFILE_ID_2); + } + + @Test + public void fetchGenericAssayData() throws Exception { + + List result = + genericAssayService.fetchGenericAssayData( + MOLECULAR_PROFILE_ID_1, + Arrays.asList(SAMPLE_ID1, SAMPLE_ID2), + Arrays.asList(STABLE_ID_1, STABLE_ID_2), + PersistenceConstants.SUMMARY_PROJECTION); + + // what we expect: 2 samples x 2 generic assay items = 4 GenericAssayData items: + // SAMPLE_1: + // generic assay1 value: 0.2 + // generic assay2 value: 0.89 + // SAMPLE_2: + // generic assay1 value: 0.499 + // generic assay2 value: -0.509 + Assert.assertEquals(4, result.size()); + GenericAssayData item1 = result.get(0); + Assert.assertEquals(item1.getSampleId(), SAMPLE_ID1); + Assert.assertEquals(item1.getStableId(), STABLE_ID_1); + Assert.assertEquals(item1.getValue(), "0.2"); + Assert.assertEquals(item1.getMolecularProfileId(), MOLECULAR_PROFILE_ID_1); + GenericAssayData item2 = result.get(1); + Assert.assertEquals(item2.getSampleId(), SAMPLE_ID1); + Assert.assertEquals(item2.getStableId(), STABLE_ID_2); + Assert.assertEquals(item2.getValue(), "0.89"); + Assert.assertEquals(item2.getMolecularProfileId(), MOLECULAR_PROFILE_ID_1); + GenericAssayData item4 = result.get(3); + Assert.assertEquals(item4.getSampleId(), SAMPLE_ID2); + Assert.assertEquals(item4.getStableId(), STABLE_ID_2); + Assert.assertEquals(item4.getValue(), "-0.509"); + Assert.assertEquals(item4.getMolecularProfileId(), MOLECULAR_PROFILE_ID_1); + + // check when selecting only 1 sample: + result = + genericAssayService.fetchGenericAssayData( + MOLECULAR_PROFILE_ID_1, + Arrays.asList(SAMPLE_ID1), + Arrays.asList(STABLE_ID_1, STABLE_ID_2), + PersistenceConstants.SUMMARY_PROJECTION); + Assert.assertEquals(2, result.size()); + item1 = result.get(0); + Assert.assertEquals(item1.getSampleId(), SAMPLE_ID1); + Assert.assertEquals(item1.getStableId(), STABLE_ID_1); + Assert.assertEquals(item1.getValue(), "0.2"); + Assert.assertEquals(item1.getMolecularProfileId(), MOLECULAR_PROFILE_ID_1); + } + + @Test + public void getGenericAssayMetaByStableIdsAndMolecularIds() throws GenericAssayNotFoundException { + Mockito.when(genericAssayRepository.getGenericAssayMeta(idList)) + .thenReturn(mockGenericAssayMetaList); + + Mockito.when(genericAssayRepository.getGenericAssayStableIdsByMolecularIds(PROFILE_ID_LIST)) + .thenReturn(idList); + + Mockito.when(genericAssayRepository.getGenericAssayAdditionalproperties(idList)) + .thenReturn(mockGenericAssayAdditionalPropertyList); + + List result = + genericAssayService.getGenericAssayMetaByStableIdsAndMolecularIds( + idList, PROFILE_ID_LIST, PersistenceConstants.SUMMARY_PROJECTION); + GenericAssayMeta meta1 = result.get(0); + GenericAssayMeta meta2 = result.get(1); + Assert.assertEquals(mockGenericAssayMetaList.get(0).getEntityType(), meta1.getEntityType()); + Assert.assertEquals(mockGenericAssayMetaList.get(0).getStableId(), meta1.getStableId()); + Assert.assertEquals( + mockGenericAssayMetaList.get(0).getGenericEntityMetaProperties(), + meta1.getGenericEntityMetaProperties()); + + Assert.assertEquals(mockGenericAssayMetaList.get(1).getEntityType(), meta2.getEntityType()); + Assert.assertEquals(mockGenericAssayMetaList.get(1).getStableId(), meta2.getStableId()); + Assert.assertEquals( + mockGenericAssayMetaList.get(1).getGenericEntityMetaProperties(), + meta2.getGenericEntityMetaProperties()); + } + + private static List createGenericAssayMetaList() { + + List genericAssayMetaList = new ArrayList<>(); + + GenericAssayMeta meta1 = new GenericAssayMeta(GENERIC_ASSAY_ID_1, ENTITY_TYPE); + HashMap map1 = new HashMap(); + map1.put(PROPERTY_NAME_1, PROPERTY_VALUE_1); + meta1.setGenericEntityMetaProperties(map1); + genericAssayMetaList.add(meta1); + + GenericAssayMeta meta2 = new GenericAssayMeta(GENERIC_ASSAY_ID_2, ENTITY_TYPE); + HashMap map2 = new HashMap(); + map2.put(PROPERTY_NAME_2, PROPERTY_VALUE_2); + meta2.setGenericEntityMetaProperties(map2); + genericAssayMetaList.add(meta2); + return genericAssayMetaList; + } + + private static List createGenericAssayAdditionalPropertyList() { + + List genericAssayAdditionalPropertyList = new ArrayList<>(); + + GenericAssayAdditionalProperty property1 = + new GenericAssayAdditionalProperty(PROPERTY_NAME_1, PROPERTY_VALUE_1, GENERIC_ASSAY_ID_1); + genericAssayAdditionalPropertyList.add(property1); + + GenericAssayAdditionalProperty property2 = + new GenericAssayAdditionalProperty(PROPERTY_NAME_2, PROPERTY_VALUE_2, GENERIC_ASSAY_ID_2); + genericAssayAdditionalPropertyList.add(property2); + return genericAssayAdditionalPropertyList; + } +} diff --git a/src/test/java/org/cbioportal/legacy/service/impl/GenesetCorrelationServiceImplTest.java b/src/test/java/org/cbioportal/legacy/service/impl/GenesetCorrelationServiceImplTest.java new file mode 100644 index 00000000000..99613b1b59a --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/service/impl/GenesetCorrelationServiceImplTest.java @@ -0,0 +1,183 @@ +package org.cbioportal.legacy.service.impl; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import org.cbioportal.legacy.model.Gene; +import org.cbioportal.legacy.model.GeneMolecularData; +import org.cbioportal.legacy.model.GenesetCorrelation; +import org.cbioportal.legacy.model.GenesetMolecularData; +import org.cbioportal.legacy.model.MolecularProfile; +import org.cbioportal.legacy.service.GenesetDataService; +import org.cbioportal.legacy.service.GenesetService; +import org.cbioportal.legacy.service.MolecularDataService; +import org.cbioportal.legacy.service.MolecularProfileService; +import org.cbioportal.legacy.service.SampleService; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.junit.MockitoJUnitRunner; + +@RunWith(MockitoJUnitRunner.class) +public class GenesetCorrelationServiceImplTest extends BaseServiceImplTest { + + @InjectMocks private GenesetCorrelationServiceImpl genesetCorrelationService; + + @Mock private GenesetDataService genesetDataService; + @Mock private MolecularDataService geneticDataService; + @Mock private GenesetService genesetService; + @Mock private SampleService sampleService; + @Mock private MolecularProfileService geneticProfileService; + + /** + * This is executed n times, for each of the n test methods below: + * + * @throws Exception + * @throws DaoException + */ + @Before + public void setUp() throws Exception { + + // stub for geneset gene list: + List geneList = new ArrayList<>(); + Gene gene = new Gene(); + gene.setEntrezGeneId(1); + geneList.add(gene); + gene = new Gene(); + gene.setEntrezGeneId(2); + geneList.add(gene); + Mockito.when(genesetService.getGenesByGenesetId(GENESET_ID1)).thenReturn(geneList); + + // stub for geneset data list: + List genesetDataList1 = new ArrayList(); + genesetDataList1.add(getSimpleFlatGenesetDataItem(SAMPLE_ID1, GENESET_ID1, "0.2")); + genesetDataList1.add(getSimpleFlatGenesetDataItem(SAMPLE_ID2, GENESET_ID1, "0.499")); + Mockito.when( + genesetDataService.fetchGenesetData( + MOLECULAR_PROFILE_ID, + Arrays.asList(SAMPLE_ID1, SAMPLE_ID2), + Arrays.asList(GENESET_ID1))) + .thenReturn(genesetDataList1); + // simulate 1 empty sample: + Mockito.when( + genesetDataService.fetchGenesetData( + MOLECULAR_PROFILE_ID, + Arrays.asList(SAMPLE_ID1, SAMPLE_ID2, SAMPLE_ID3), + Arrays.asList(GENESET_ID1))) + .thenReturn(genesetDataList1); + + // dummy stubs (normally these will return different profiles, but for the test this is enough: + MolecularProfile geneticProfile = new MolecularProfile(); + geneticProfile.setStableId(MOLECULAR_PROFILE_ID); + Mockito.when(geneticProfileService.getMolecularProfilesReferredBy(MOLECULAR_PROFILE_ID)) + .thenReturn(Arrays.asList(geneticProfile)); + MolecularProfile zscoreGeneticProfile = new MolecularProfile(); + zscoreGeneticProfile.setStableId(MOLECULAR_PROFILE_ID); + zscoreGeneticProfile.setDatatype("Z-SCORE"); + Mockito.when(geneticProfileService.getMolecularProfilesReferringTo(MOLECULAR_PROFILE_ID)) + .thenReturn(Arrays.asList(zscoreGeneticProfile)); + + // stub for gene data list, one gene at a time: + List geneDataList1 = new ArrayList(); + geneDataList1.add(getSimpleFlatGeneDataItem(SAMPLE_ID1, 1, "0.2")); + geneDataList1.add(getSimpleFlatGeneDataItem(SAMPLE_ID2, 1, "0.350")); + Mockito.when( + geneticDataService.fetchMolecularData( + MOLECULAR_PROFILE_ID, + Arrays.asList(SAMPLE_ID1, SAMPLE_ID2), + Arrays.asList(1), + "SUMMARY")) + .thenReturn(geneDataList1); + // simulate 1 empty sample: + Mockito.when( + geneticDataService.fetchMolecularData( + MOLECULAR_PROFILE_ID, + Arrays.asList(SAMPLE_ID1, SAMPLE_ID2, SAMPLE_ID3), + Arrays.asList(1), + "SUMMARY")) + .thenReturn(geneDataList1); + + List geneDataList2 = new ArrayList(); + geneDataList2.add(getSimpleFlatGeneDataItem(SAMPLE_ID1, 2, "0.89")); + geneDataList2.add(getSimpleFlatGeneDataItem(SAMPLE_ID2, 2, "-0.509")); + Mockito.when( + geneticDataService.fetchMolecularData( + MOLECULAR_PROFILE_ID, + Arrays.asList(SAMPLE_ID1, SAMPLE_ID2), + Arrays.asList(2), + "SUMMARY")) + .thenReturn(geneDataList2); + // simulate 1 empty sample: + Mockito.when( + geneticDataService.fetchMolecularData( + MOLECULAR_PROFILE_ID, + Arrays.asList(SAMPLE_ID1, SAMPLE_ID2, SAMPLE_ID3), + Arrays.asList(2), + "SUMMARY")) + .thenReturn(geneDataList2); + } + + private GenesetMolecularData getSimpleFlatGenesetDataItem( + String sampleStableId, String genesetId, String value) { + + GenesetMolecularData item = new GenesetMolecularData(); + item.setMolecularProfileId(MOLECULAR_PROFILE_ID); + item.setGenesetId(genesetId); + item.setSampleId(sampleStableId); + item.setValue(value); + return item; + } + + private GeneMolecularData getSimpleFlatGeneDataItem( + String sampleStableId, int entrezGeneId, String value) { + + GeneMolecularData item = new GeneMolecularData(); + item.setMolecularProfileId(MOLECULAR_PROFILE_ID); + item.setEntrezGeneId(entrezGeneId); + item.setSampleId(sampleStableId); + item.setValue(value); + return item; + } + + @Test + public void fetchCorrelatedGenes() throws Exception { + + List result = + genesetCorrelationService.fetchCorrelatedGenes( + GENESET_ID1, MOLECULAR_PROFILE_ID, Arrays.asList(SAMPLE_ID1, SAMPLE_ID2), 0.3); + + // what we expect: gene 1 has good correlation with geneset 1, while gene 2 is anti-correlated. + // So + // we expect only gene 1 to return, with correlation close to 1.0 (it is artificially high in + // this example) + + Assert.assertEquals(1, result.size()); + Assert.assertEquals(1, result.get(0).getEntrezGeneId().intValue()); + Assert.assertEquals((Double) 1.0, result.get(0).getCorrelationValue()); + + result = + genesetCorrelationService.fetchCorrelatedGenes( + GENESET_ID1, MOLECULAR_PROFILE_ID, Arrays.asList(SAMPLE_ID1, SAMPLE_ID2), -1.0); + + // now we expect both genes to return, since correlation threshold is at -1.0 (just a dummy + // threshold for testing): + Assert.assertEquals(2, result.size()); + Assert.assertEquals(1, result.get(0).getEntrezGeneId().intValue()); + Assert.assertEquals((Double) 1.0, result.get(0).getCorrelationValue()); + Assert.assertEquals(2, result.get(1).getEntrezGeneId().intValue()); + Assert.assertEquals((Double) (-1.0), result.get(1).getCorrelationValue()); + + // test when 1 of the samples does not have data: + result = + genesetCorrelationService.fetchCorrelatedGenes( + GENESET_ID1, + MOLECULAR_PROFILE_ID, + Arrays.asList(SAMPLE_ID1, SAMPLE_ID2, SAMPLE_ID3), + -1.0); + Assert.assertEquals(2, result.size()); + } +} diff --git a/src/test/java/org/cbioportal/legacy/service/impl/GenesetDataServiceImplTest.java b/src/test/java/org/cbioportal/legacy/service/impl/GenesetDataServiceImplTest.java new file mode 100644 index 00000000000..8b42dd1d8aa --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/service/impl/GenesetDataServiceImplTest.java @@ -0,0 +1,140 @@ +package org.cbioportal.legacy.service.impl; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import org.cbioportal.legacy.model.GenesetMolecularAlteration; +import org.cbioportal.legacy.model.GenesetMolecularData; +import org.cbioportal.legacy.model.MolecularProfile; +import org.cbioportal.legacy.model.MolecularProfileSamples; +import org.cbioportal.legacy.model.Sample; +import org.cbioportal.legacy.persistence.MolecularDataRepository; +import org.cbioportal.legacy.service.MolecularProfileService; +import org.cbioportal.legacy.service.SampleService; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.junit.MockitoJUnitRunner; + +@RunWith(MockitoJUnitRunner.class) +public class GenesetDataServiceImplTest extends BaseServiceImplTest { + + @InjectMocks private GenesetDataServiceImpl genesetDataService; + + @Mock private MolecularDataRepository geneticDataRepository; + @Mock private SampleService sampleService; + @Mock private MolecularProfileService geneticProfileService; + + /** + * This is executed n times, for each of the n test methods below: + * + * @throws Exception + * @throws DaoException + */ + @Before + public void setUp() throws Exception { + + MolecularProfileSamples molecularProfileSamples = new MolecularProfileSamples(); + molecularProfileSamples.setMolecularProfileId(MOLECULAR_PROFILE_ID); + molecularProfileSamples.setCommaSeparatedSampleIds("1,2,"); + + // stub for samples + Mockito.when( + geneticDataRepository.getCommaSeparatedSampleIdsOfMolecularProfile( + MOLECULAR_PROFILE_ID)) + .thenReturn(molecularProfileSamples); + + List sampleList1 = new ArrayList<>(); + Sample sample = new Sample(); + sample.setInternalId(1); + sample.setStableId(SAMPLE_ID1); + sampleList1.add(sample); + Mockito.when( + sampleService.fetchSamples(Arrays.asList(STUDY_ID), Arrays.asList(SAMPLE_ID1), "ID")) + .thenReturn(sampleList1); + List sampleListAll = new ArrayList<>(sampleList1); + sample = new Sample(); + sample.setInternalId(2); + sample.setStableId(SAMPLE_ID2); + sampleListAll.add(sample); + Mockito.when( + sampleService.fetchSamples( + Arrays.asList(STUDY_ID, STUDY_ID), Arrays.asList(SAMPLE_ID1, SAMPLE_ID2), "ID")) + .thenReturn(sampleListAll); + + // stub for genetic profile + MolecularProfile geneticProfile = new MolecularProfile(); + geneticProfile.setCancerStudyIdentifier(STUDY_ID); + Mockito.when(geneticProfileService.getMolecularProfile(MOLECULAR_PROFILE_ID)) + .thenReturn(geneticProfile); + + // stub for repository data + List genesetGeneticAlterationList = new ArrayList<>(); + GenesetMolecularAlteration genesetGeneticAlteration = new GenesetMolecularAlteration(); + genesetGeneticAlteration.setGenesetId(GENESET_ID1); + genesetGeneticAlteration.setValues("0.2,0.499"); + genesetGeneticAlterationList.add(genesetGeneticAlteration); + genesetGeneticAlteration = new GenesetMolecularAlteration(); + genesetGeneticAlteration.setGenesetId(GENESET_ID2); + genesetGeneticAlteration.setValues("0.89,-0.509"); + genesetGeneticAlterationList.add(genesetGeneticAlteration); + + List entrezGeneIds = new ArrayList<>(); + entrezGeneIds.add(ENTREZ_GENE_ID_1); + Mockito.when( + geneticDataRepository.getGenesetMolecularAlterations( + MOLECULAR_PROFILE_ID, Arrays.asList(GENESET_ID1, GENESET_ID2), "SUMMARY")) + .thenReturn(genesetGeneticAlterationList); + } + + @Test + public void fetchGenesetData() throws Exception { + + List result = + genesetDataService.fetchGenesetData( + MOLECULAR_PROFILE_ID, + Arrays.asList(SAMPLE_ID1, SAMPLE_ID2), + Arrays.asList(GENESET_ID1, GENESET_ID2)); + + // what we expect: 2 samples x 2 geneset items = 4 GenesetData items: + // SAMPLE_1: + // geneset1 value: 0.2 + // geneset2 value: 0.89 + // SAMPLE_2: + // geneset1 value: 0.499 + // geneset2 value: -0.509 + Assert.assertEquals(4, result.size()); + GenesetMolecularData item1 = result.get(0); + Assert.assertEquals(item1.getSampleId(), SAMPLE_ID1); + Assert.assertEquals(item1.getGenesetId(), GENESET_ID1); + Assert.assertEquals(item1.getValue(), "0.2"); + Assert.assertEquals(item1.getMolecularProfileId(), MOLECULAR_PROFILE_ID); + GenesetMolecularData item2 = result.get(1); + Assert.assertEquals(item2.getSampleId(), SAMPLE_ID1); + Assert.assertEquals(item2.getGenesetId(), GENESET_ID2); + Assert.assertEquals(item2.getValue(), "0.89"); + Assert.assertEquals(item2.getMolecularProfileId(), MOLECULAR_PROFILE_ID); + GenesetMolecularData item4 = result.get(3); + Assert.assertEquals(item4.getSampleId(), SAMPLE_ID2); + Assert.assertEquals(item4.getGenesetId(), GENESET_ID2); + Assert.assertEquals(item4.getValue(), "-0.509"); + Assert.assertEquals(item4.getMolecularProfileId(), MOLECULAR_PROFILE_ID); + + // check when selecting only 1 sample: + result = + genesetDataService.fetchGenesetData( + MOLECULAR_PROFILE_ID, + Arrays.asList(SAMPLE_ID1), + Arrays.asList(GENESET_ID1, GENESET_ID2)); + Assert.assertEquals(2, result.size()); + item1 = result.get(0); + Assert.assertEquals(item1.getSampleId(), SAMPLE_ID1); + Assert.assertEquals(item1.getGenesetId(), GENESET_ID1); + Assert.assertEquals(item1.getValue(), "0.2"); + Assert.assertEquals(item1.getMolecularProfileId(), MOLECULAR_PROFILE_ID); + } +} diff --git a/src/test/java/org/cbioportal/legacy/service/impl/GenesetHierarchyServiceImplTest.java b/src/test/java/org/cbioportal/legacy/service/impl/GenesetHierarchyServiceImplTest.java new file mode 100644 index 00000000000..f419f3c3085 --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/service/impl/GenesetHierarchyServiceImplTest.java @@ -0,0 +1,240 @@ +package org.cbioportal.legacy.service.impl; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import org.cbioportal.legacy.model.Geneset; +import org.cbioportal.legacy.model.GenesetHierarchyInfo; +import org.cbioportal.legacy.model.GenesetMolecularData; +import org.cbioportal.legacy.model.MolecularProfile; +import org.cbioportal.legacy.persistence.GenesetHierarchyRepository; +import org.cbioportal.legacy.service.GenesetDataService; +import org.cbioportal.legacy.service.GenesetService; +import org.cbioportal.legacy.service.MolecularDataService; +import org.cbioportal.legacy.service.MolecularProfileService; +import org.cbioportal.legacy.service.SampleService; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.junit.MockitoJUnitRunner; + +@RunWith(MockitoJUnitRunner.Silent.class) +public class GenesetHierarchyServiceImplTest extends BaseServiceImplTest { + + @InjectMocks private GenesetHierarchyServiceImpl genesetHierarchyService; + + @Mock private GenesetDataService genesetDataService; + @Mock private MolecularDataService geneticDataService; + @Mock private GenesetService genesetService; + @Mock private SampleService sampleService; + @Mock private MolecularProfileService geneticProfileService; + @Mock private GenesetHierarchyRepository genesetHierarchyRepository; + + public static final String PVALUE_GENETIC_PROFILE_ID = "p_value_genetic_profile_id"; + + /** + * This is executed n times, for each of the n test methods below: + * + * @throws Exception + * @throws DaoException + */ + @Before + public void setUp() throws Exception { + + MolecularProfile geneticProfile = new MolecularProfile(); + geneticProfile.setCancerStudyIdentifier(STUDY_ID); + geneticProfile.setDatatype("GSVA-SCORE"); + Mockito.when(geneticProfileService.getMolecularProfile(MOLECULAR_PROFILE_ID)) + .thenReturn(geneticProfile); + + // stub for geneset scores: + List genesetScoresDataList1 = new ArrayList(); + genesetScoresDataList1.add(getSimpleFlatGenesetDataItem(SAMPLE_ID1, GENESET_ID1, "0.2")); + genesetScoresDataList1.add(getSimpleFlatGenesetDataItem(SAMPLE_ID2, GENESET_ID1, "0.499")); + genesetScoresDataList1.add(getSimpleFlatGenesetDataItem(SAMPLE_ID3, GENESET_ID1, "0.470")); + genesetScoresDataList1.add(getSimpleFlatGenesetDataItem(SAMPLE_ID1, GENESET_ID2, "-0.35")); + genesetScoresDataList1.add(getSimpleFlatGenesetDataItem(SAMPLE_ID2, GENESET_ID2, "0.12")); + genesetScoresDataList1.add(getSimpleFlatGenesetDataItem(SAMPLE_ID3, GENESET_ID2, "-0.11")); + Mockito.when( + genesetDataService.fetchGenesetData( + MOLECULAR_PROFILE_ID, Arrays.asList(SAMPLE_ID1, SAMPLE_ID2, SAMPLE_ID3), null)) + .thenReturn(genesetScoresDataList1); + + // stubs for related p-values: + MolecularProfile pvalueGeneticProfile = new MolecularProfile(); + pvalueGeneticProfile.setStableId(PVALUE_GENETIC_PROFILE_ID); + pvalueGeneticProfile.setDatatype("P-VALUE"); + Mockito.when(geneticProfileService.getMolecularProfilesReferringTo(MOLECULAR_PROFILE_ID)) + .thenReturn(Arrays.asList(pvalueGeneticProfile)); + + List genesetPvaluesDataList1 = new ArrayList(); + genesetPvaluesDataList1.add(getSimpleFlatGenesetDataItem(SAMPLE_ID1, GENESET_ID1, "0.016")); + genesetPvaluesDataList1.add(getSimpleFlatGenesetDataItem(SAMPLE_ID2, GENESET_ID1, "0.0359")); + genesetPvaluesDataList1.add(getSimpleFlatGenesetDataItem(SAMPLE_ID3, GENESET_ID1, "0.0219")); + genesetPvaluesDataList1.add(getSimpleFlatGenesetDataItem(SAMPLE_ID1, GENESET_ID2, "0.046")); + genesetPvaluesDataList1.add(getSimpleFlatGenesetDataItem(SAMPLE_ID2, GENESET_ID2, "0.0019")); + genesetPvaluesDataList1.add(getSimpleFlatGenesetDataItem(SAMPLE_ID3, GENESET_ID2, "0.001")); + Mockito.when( + genesetDataService.fetchGenesetData( + PVALUE_GENETIC_PROFILE_ID, Arrays.asList(SAMPLE_ID1, SAMPLE_ID2, SAMPLE_ID3), null)) + .thenReturn(genesetPvaluesDataList1); + + // stubs for hierarchy nodes, parents and genesets: + + List hierarchySuperNodes = new ArrayList(); + GenesetHierarchyInfo node1 = new GenesetHierarchyInfo(); + node1.setNodeId(1); + node1.setNodeName("Root node"); + hierarchySuperNodes.add(node1); + GenesetHierarchyInfo node2 = new GenesetHierarchyInfo(); + node2.setNodeId(2); + node2.setNodeName("sub node A"); + node2.setParentId(1); + node2.setParentNodeName(node1.getNodeName()); + hierarchySuperNodes.add(node2); + GenesetHierarchyInfo node3 = new GenesetHierarchyInfo(); + node3.setNodeId(3); + node3.setNodeName("sub node B"); + node3.setParentId(1); + node3.setParentNodeName(node1.getNodeName()); + hierarchySuperNodes.add(node3); + Mockito.when( + genesetHierarchyRepository.getGenesetHierarchySuperNodes( + Arrays.asList(GENESET_ID1, GENESET_ID2))) + .thenReturn(hierarchySuperNodes); + Mockito.when( + genesetHierarchyRepository.getGenesetHierarchySuperNodes( + Arrays.asList(GENESET_ID2, GENESET_ID1))) + .thenReturn(hierarchySuperNodes); + + List hierarchyParents = new ArrayList(); + GenesetHierarchyInfo parentNode1 = new GenesetHierarchyInfo(); + parentNode1.setNodeId(4); + parentNode1.setNodeName("parent node 1"); + parentNode1.setParentId(2); + parentNode1.setParentNodeName(node2.getNodeName()); + hierarchyParents.add(parentNode1); + GenesetHierarchyInfo parentNode2 = new GenesetHierarchyInfo(); + parentNode2.setNodeId(5); + parentNode2.setNodeName("parent node 2"); + parentNode2.setParentId(2); + parentNode2.setParentNodeName(node2.getNodeName()); + hierarchyParents.add(parentNode2); + Mockito.when( + genesetHierarchyRepository.getGenesetHierarchyParents( + Arrays.asList(GENESET_ID1, GENESET_ID2))) + .thenReturn(hierarchyParents); + Mockito.when( + genesetHierarchyRepository.getGenesetHierarchyParents( + Arrays.asList(GENESET_ID2, GENESET_ID1))) + .thenReturn(hierarchyParents); + + Geneset geneset1 = new Geneset(); + geneset1.setGenesetId(GENESET_ID1); + geneset1.setDescription(GENESET_ID1); + geneset1.setName(GENESET_ID1); + Geneset geneset2 = new Geneset(); + geneset2.setGenesetId(GENESET_ID2); + geneset2.setDescription(GENESET_ID2); + geneset2.setName(GENESET_ID2); + Mockito.when(genesetHierarchyRepository.getGenesetHierarchyGenesets(parentNode1.getNodeId())) + .thenReturn(Arrays.asList(geneset1, geneset2)); // genesets 1 and 2 as children + Mockito.when(genesetHierarchyRepository.getGenesetHierarchyGenesets(parentNode2.getNodeId())) + .thenReturn(Arrays.asList(geneset2)); // only geneset 2 as child + } + + private GenesetMolecularData getSimpleFlatGenesetDataItem( + String sampleStableId, String genesetId, String value) { + + GenesetMolecularData item = new GenesetMolecularData(); + item.setMolecularProfileId(MOLECULAR_PROFILE_ID); + item.setGenesetId(genesetId); + item.setSampleId(sampleStableId); + item.setValue(value); + return item; + } + + @Test + public void fetchCorrelatedGenes() throws Exception { + + // 50th percentile (median), with thresholds abs_score=0.4 and p-value=0.05: + List result = + genesetHierarchyService.fetchGenesetHierarchyInfo( + MOLECULAR_PROFILE_ID, 50, 0.4, 0.05, Arrays.asList(SAMPLE_ID1, SAMPLE_ID2, SAMPLE_ID3)); + + // what we expect: at threshold 0.4 only GENESET_ID1 will qualify, so only the hierarchy related + // to this + // geneset should return. That is: + // Root node -> sub node A -> parent node 1 -> GENESET_ID1, with representative (median) + // score=0.470 and p-value=0.0219 + + Assert.assertEquals(3, result.size()); + // 3 nodes, last one with 1 leaf (geneset): + Assert.assertEquals(null, result.get(0).getGenesets()); + Assert.assertEquals(1, result.get(2).getGenesets().size()); + Geneset geneset = result.get(2).getGenesets().get(0); + Assert.assertEquals(GENESET_ID1, geneset.getGenesetId()); + Assert.assertEquals((Double) 0.470, geneset.getRepresentativeScore()); + Assert.assertEquals((Double) 0.0219, geneset.getRepresentativePvalue()); + + // 90th percentile, with thresholds abs_score=0.3 and p-value=0.05: + result = + genesetHierarchyService.fetchGenesetHierarchyInfo( + MOLECULAR_PROFILE_ID, 90, 0.3, 0.05, Arrays.asList(SAMPLE_ID1, SAMPLE_ID2, SAMPLE_ID3)); + + // what we expect: at threshold 0.3 both GENESET_ID1 & 2 will qualify, so the hierarchy related + // to these + // genesets should return. That is: + // Root node -> sub node A -> parent node 1 -> GENESET_ID1, with representative score=0.499 + // and p-value=0.0359 + // -> GENESET_ID2, with representative score=-0.35 + // and p-value=0.046 + // Root node -> sub node A -> parent node 2 -> GENESET_ID2, with representative score=-0.35 + // and p-value=0.046 + Assert.assertEquals(4, result.size()); + // 4 nodes, last 2 with leaf(s): + Assert.assertEquals(null, result.get(0).getGenesets()); + Assert.assertEquals(null, result.get(1).getGenesets()); + Assert.assertEquals(2, result.get(2).getGenesets().size()); + Assert.assertEquals(1, result.get(3).getGenesets().size()); + geneset = result.get(2).getGenesets().get(0); + Assert.assertEquals(GENESET_ID1, geneset.getGenesetId()); + Assert.assertEquals((Double) 0.499, geneset.getRepresentativeScore()); + Assert.assertEquals((Double) 0.0359, geneset.getRepresentativePvalue()); + geneset = result.get(2).getGenesets().get(1); + Assert.assertEquals(GENESET_ID2, geneset.getGenesetId()); + Assert.assertEquals((Double) (-0.35), geneset.getRepresentativeScore()); + Assert.assertEquals((Double) 0.046, geneset.getRepresentativePvalue()); + // last one is also GENESET_ID2: + Assert.assertEquals(geneset, result.get(3).getGenesets().get(0)); + + // 40th percentile, with thresholds abs_score=0.1 and (stricter) p-value=0.01: + result = + genesetHierarchyService.fetchGenesetHierarchyInfo( + MOLECULAR_PROFILE_ID, 40, 0.1, 0.01, Arrays.asList(SAMPLE_ID1, SAMPLE_ID2, SAMPLE_ID3)); + + // what we expect: at threshold 0.1 both GENESET_ID1 & 2 will initially qualify, but GENESET_ID1 + // will finally not + // make it because of its p-values. So result should be: + // Root node -> sub node A -> parent node 1 -> GENESET_ID2, with representative score=0.12 + // and p-value=0.0019 + // Root node -> sub node A -> parent node 2 -> GENESET_ID2, with representative score=0.12 + // and p-value=0.0019 + Assert.assertEquals(4, result.size()); + // 4 nodes, last 2 with one leaf each: + Assert.assertEquals(null, result.get(0).getGenesets()); + Assert.assertEquals(null, result.get(1).getGenesets()); + Assert.assertEquals(1, result.get(2).getGenesets().size()); + Assert.assertEquals(1, result.get(3).getGenesets().size()); + geneset = result.get(2).getGenesets().get(0); + Assert.assertEquals(GENESET_ID2, geneset.getGenesetId()); + Assert.assertEquals((Double) 0.12, geneset.getRepresentativeScore()); + Assert.assertEquals((Double) 0.0019, geneset.getRepresentativePvalue()); + // last one is also GENESET_ID2: + Assert.assertEquals(geneset, result.get(3).getGenesets().get(0)); + } +} diff --git a/src/test/java/org/cbioportal/legacy/service/impl/GenesetServiceImplTest.java b/src/test/java/org/cbioportal/legacy/service/impl/GenesetServiceImplTest.java new file mode 100644 index 00000000000..a6e27e6a59c --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/service/impl/GenesetServiceImplTest.java @@ -0,0 +1,111 @@ +package org.cbioportal.legacy.service.impl; + +import java.util.ArrayList; +import java.util.List; +import org.cbioportal.legacy.model.Gene; +import org.cbioportal.legacy.model.Geneset; +import org.cbioportal.legacy.model.meta.BaseMeta; +import org.cbioportal.legacy.persistence.GenesetRepository; +import org.cbioportal.legacy.service.MolecularProfileService; +import org.cbioportal.legacy.service.SampleService; +import org.cbioportal.legacy.service.exception.GenesetNotFoundException; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.junit.MockitoJUnitRunner; + +@RunWith(MockitoJUnitRunner.Silent.class) +public class GenesetServiceImplTest extends BaseServiceImplTest { + + public static final String GENESET_ID_1 = "geneset_id_1"; + private static final Integer INTERNAL_ID_1 = 1; + public static final String GENESET_ID_2 = "geneset_id_2"; + private static final Integer INTERNAL_ID_2 = 2; + + @InjectMocks private GenesetServiceImpl genesetService; + + @Mock private GenesetRepository genesetRepository; + @Mock private SampleService sampleService; + @Mock private MolecularProfileService geneticProfileService; + + @Test + public void getAllGenesets() { + + List genesetList = createGenesetList(); + Mockito.when(genesetRepository.getAllGenesets(PROJECTION, PAGE_SIZE, PAGE_NUMBER)) + .thenReturn(genesetList); + + List result = genesetService.getAllGenesets(PROJECTION, PAGE_SIZE, PAGE_NUMBER); + + Assert.assertEquals(genesetList, result); + } + + @Test + public void getMetaGenesets() { + + BaseMeta expectedBaseMeta = new BaseMeta(); + Mockito.when(genesetRepository.getMetaGenesets()).thenReturn(expectedBaseMeta); + BaseMeta result = genesetService.getMetaGenesets(); + + Assert.assertEquals(expectedBaseMeta, result); + } + + @Test + public void getGeneset() throws GenesetNotFoundException { + + Geneset geneset = createGenesetList().get(0); + Mockito.when(genesetRepository.getGeneset(GENESET_ID_1)).thenReturn(geneset); + + Geneset result = genesetService.getGeneset(GENESET_ID_1); + Assert.assertEquals(geneset, result); + } + + @Test(expected = GenesetNotFoundException.class) + public void getGeneByEntrezGeneIdNotFound() throws GenesetNotFoundException { + + Geneset geneset = createGenesetList().get(0); + Mockito.when(genesetRepository.getGeneset(GENESET_ID_1)).thenReturn(geneset); + // expect GenesetNotFoundException here: + genesetService.getGeneset("wrongId"); + } + + @Test + public void getGenesByGenesetId() throws GenesetNotFoundException { + + List genes = createGeneList(); + Mockito.when(genesetRepository.getGenesByGenesetId(GENESET_ID_2)).thenReturn(genes); + + Geneset geneset = createGenesetList().get(1); + Mockito.when(genesetRepository.getGeneset(GENESET_ID_2)).thenReturn(geneset); + + List result = genesetService.getGenesByGenesetId(GENESET_ID_2); + Assert.assertEquals(genes, result); + } + + private List createGenesetList() { + List genesetList = new ArrayList<>(); + Geneset geneset1 = new Geneset(); + geneset1.setInternalId(INTERNAL_ID_1); + geneset1.setGenesetId(GENESET_ID_1); + genesetList.add(geneset1); + Geneset geneset2 = new Geneset(); + geneset2.setInternalId(INTERNAL_ID_2); + geneset2.setGenesetId(GENESET_ID_2); + genesetList.add(geneset2); + return genesetList; + } + + private List createGeneList() { + List geneList = new ArrayList<>(); + Gene gene1 = new Gene(); + gene1.setEntrezGeneId(1); + geneList.add(gene1); + Gene gene2 = new Gene(); + gene2.setEntrezGeneId(2); + geneList.add(gene2); + return geneList; + } +} diff --git a/src/test/java/org/cbioportal/legacy/service/impl/MolecularDataServiceImplTest.java b/src/test/java/org/cbioportal/legacy/service/impl/MolecularDataServiceImplTest.java new file mode 100644 index 00000000000..e133c7fef39 --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/service/impl/MolecularDataServiceImplTest.java @@ -0,0 +1,309 @@ +package org.cbioportal.legacy.service.impl; + +import static org.mockito.ArgumentMatchers.anyList; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.*; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import org.cbioportal.legacy.model.DiscreteCopyNumberData; +import org.cbioportal.legacy.model.GeneMolecularAlteration; +import org.cbioportal.legacy.model.GeneMolecularData; +import org.cbioportal.legacy.model.MolecularProfile; +import org.cbioportal.legacy.model.MolecularProfileSamples; +import org.cbioportal.legacy.model.Sample; +import org.cbioportal.legacy.model.meta.BaseMeta; +import org.cbioportal.legacy.persistence.DiscreteCopyNumberRepository; +import org.cbioportal.legacy.persistence.MolecularDataRepository; +import org.cbioportal.legacy.persistence.SampleListRepository; +import org.cbioportal.legacy.service.MolecularProfileService; +import org.cbioportal.legacy.service.SampleService; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnitRunner; + +@RunWith(MockitoJUnitRunner.class) +public class MolecularDataServiceImplTest extends BaseServiceImplTest { + + @InjectMocks private MolecularDataServiceImpl molecularDataService; + + @Mock private MolecularDataRepository molecularDataRepository; + @Mock private DiscreteCopyNumberRepository discreteCopyNumberRepository; + @Mock private SampleService sampleService; + @Mock private MolecularProfileService molecularProfileService; + @Mock private SampleListRepository sampleListRepository; + + @Test + public void getMolecularData() throws Exception { + + when(sampleListRepository.getAllSampleIdsInSampleList(SAMPLE_LIST_ID)) + .thenReturn(Arrays.asList(SAMPLE_ID1)); + + MolecularProfileSamples molecularProfileSamples = new MolecularProfileSamples(); + molecularProfileSamples.setMolecularProfileId(MOLECULAR_PROFILE_ID); + molecularProfileSamples.setCommaSeparatedSampleIds("1,2,"); + + when(molecularDataRepository.getCommaSeparatedSampleIdsOfMolecularProfile(MOLECULAR_PROFILE_ID)) + .thenReturn(molecularProfileSamples); + + MolecularProfile molecularProfile = new MolecularProfile(); + molecularProfile.setCancerStudyIdentifier(STUDY_ID); + molecularProfile.setMolecularAlterationType( + MolecularProfile.MolecularAlterationType.MRNA_EXPRESSION); + when(molecularProfileService.getMolecularProfile(MOLECULAR_PROFILE_ID)) + .thenReturn(molecularProfile); + + List sampleList = new ArrayList<>(); + Sample sample = new Sample(); + sample.setInternalId(1); + sample.setStableId(SAMPLE_ID1); + sampleList.add(sample); + when(sampleService.fetchSamples(Arrays.asList(STUDY_ID), Arrays.asList(SAMPLE_ID1), "ID")) + .thenReturn(sampleList); + + List molecularAlterationList = new ArrayList<>(); + GeneMolecularAlteration molecularAlteration = new GeneMolecularAlteration(); + molecularAlteration.setEntrezGeneId(ENTREZ_GENE_ID_1); + molecularAlteration.setValues("0.4674,-0.3456"); + molecularAlterationList.add(molecularAlteration); + + List entrezGeneIds = new ArrayList<>(); + entrezGeneIds.add(ENTREZ_GENE_ID_1); + when(molecularDataRepository.getGeneMolecularAlterations( + MOLECULAR_PROFILE_ID, entrezGeneIds, PROJECTION)) + .thenReturn(molecularAlterationList); + + List result = + molecularDataService.getMolecularData( + MOLECULAR_PROFILE_ID, SAMPLE_LIST_ID, entrezGeneIds, PROJECTION); + + Assert.assertEquals(1, result.size()); + GeneMolecularData molecularData = result.get(0); + Assert.assertEquals(ENTREZ_GENE_ID_1, molecularData.getEntrezGeneId()); + Assert.assertEquals(MOLECULAR_PROFILE_ID, molecularData.getMolecularProfileId()); + Assert.assertEquals(SAMPLE_ID1, molecularData.getSampleId()); + Assert.assertEquals("0.4674", molecularData.getValue()); + } + + @Test + public void getMetaMolecularData() throws Exception { + + when(sampleListRepository.getAllSampleIdsInSampleList(SAMPLE_LIST_ID)) + .thenReturn(Arrays.asList(SAMPLE_ID1)); + + MolecularProfileSamples molecularProfileSamples = new MolecularProfileSamples(); + molecularProfileSamples.setMolecularProfileId(MOLECULAR_PROFILE_ID); + molecularProfileSamples.setCommaSeparatedSampleIds("1,2,"); + + when(molecularDataRepository.getCommaSeparatedSampleIdsOfMolecularProfile(MOLECULAR_PROFILE_ID)) + .thenReturn(molecularProfileSamples); + + MolecularProfile molecularProfile = new MolecularProfile(); + molecularProfile.setCancerStudyIdentifier(STUDY_ID); + molecularProfile.setMolecularAlterationType( + MolecularProfile.MolecularAlterationType.MRNA_EXPRESSION); + when(molecularProfileService.getMolecularProfile(MOLECULAR_PROFILE_ID)) + .thenReturn(molecularProfile); + + List sampleList = new ArrayList<>(); + Sample sample = new Sample(); + sample.setInternalId(1); + sample.setStableId(SAMPLE_ID1); + sampleList.add(sample); + when(sampleService.fetchSamples(Arrays.asList(STUDY_ID), Arrays.asList(SAMPLE_ID1), "ID")) + .thenReturn(sampleList); + + List molecularAlterationList = new ArrayList<>(); + GeneMolecularAlteration molecularAlteration = new GeneMolecularAlteration(); + molecularAlteration.setEntrezGeneId(ENTREZ_GENE_ID_1); + molecularAlteration.setValues("0.4674,-0.3456"); + molecularAlterationList.add(molecularAlteration); + + List entrezGeneIds = new ArrayList<>(); + entrezGeneIds.add(ENTREZ_GENE_ID_1); + when(molecularDataRepository.getGeneMolecularAlterations( + MOLECULAR_PROFILE_ID, entrezGeneIds, "ID")) + .thenReturn(molecularAlterationList); + + BaseMeta result = + molecularDataService.getMetaMolecularData( + MOLECULAR_PROFILE_ID, SAMPLE_LIST_ID, entrezGeneIds); + + Assert.assertEquals((Integer) 1, result.getTotalCount()); + } + + @Test + public void getMolecularDataOfAllSamplesOfMolecularProfile() throws Exception { + + MolecularProfile molecularProfile = new MolecularProfile(); + molecularProfile.setMolecularAlterationType( + MolecularProfile.MolecularAlterationType.MRNA_EXPRESSION); + when(molecularProfileService.getMolecularProfile(MOLECULAR_PROFILE_ID)) + .thenReturn(molecularProfile); + + MolecularProfileSamples molecularProfileSamples = new MolecularProfileSamples(); + molecularProfileSamples.setMolecularProfileId(MOLECULAR_PROFILE_ID); + molecularProfileSamples.setCommaSeparatedSampleIds("1,2,"); + + when(molecularDataRepository.getCommaSeparatedSampleIdsOfMolecularProfile(MOLECULAR_PROFILE_ID)) + .thenReturn(molecularProfileSamples); + + List molecularAlterationList = new ArrayList<>(); + GeneMolecularAlteration molecularAlteration = new GeneMolecularAlteration(); + molecularAlteration.setEntrezGeneId(ENTREZ_GENE_ID_1); + molecularAlteration.setValues("0.4674,-0.3456"); + molecularAlterationList.add(molecularAlteration); + + List entrezGeneIds = new ArrayList<>(); + entrezGeneIds.add(ENTREZ_GENE_ID_1); + when(molecularDataRepository.getGeneMolecularAlterations( + MOLECULAR_PROFILE_ID, entrezGeneIds, PROJECTION)) + .thenReturn(molecularAlterationList); + + List internalIds = new ArrayList<>(); + internalIds.add(1); + internalIds.add(2); + + List samples = new ArrayList<>(); + Sample sample1 = new Sample(); + sample1.setInternalId(1); + sample1.setStableId(SAMPLE_ID1); + samples.add(sample1); + Sample sample2 = new Sample(); + sample2.setInternalId(2); + sample2.setStableId("sample_id_2"); + samples.add(sample2); + when(sampleService.getSamplesByInternalIds(internalIds)).thenReturn(samples); + + List result = + molecularDataService.fetchMolecularData( + MOLECULAR_PROFILE_ID, null, entrezGeneIds, PROJECTION); + + Assert.assertEquals(2, result.size()); + GeneMolecularData molecularData1 = result.get(0); + Assert.assertEquals(ENTREZ_GENE_ID_1, molecularData1.getEntrezGeneId()); + Assert.assertEquals(MOLECULAR_PROFILE_ID, molecularData1.getMolecularProfileId()); + Assert.assertEquals(SAMPLE_ID1, molecularData1.getSampleId()); + Assert.assertEquals("0.4674", molecularData1.getValue()); + GeneMolecularData molecularData2 = result.get(1); + Assert.assertEquals(ENTREZ_GENE_ID_1, molecularData2.getEntrezGeneId()); + Assert.assertEquals(MOLECULAR_PROFILE_ID, molecularData2.getMolecularProfileId()); + Assert.assertEquals("sample_id_2", molecularData2.getSampleId()); + Assert.assertEquals("-0.3456", molecularData2.getValue()); + } + + @Test + public void fetchMetaMolecularData() throws Exception { + + MolecularProfile molecularProfile = new MolecularProfile(); + molecularProfile.setMolecularAlterationType( + MolecularProfile.MolecularAlterationType.MRNA_EXPRESSION); + when(molecularProfileService.getMolecularProfile(MOLECULAR_PROFILE_ID)) + .thenReturn(molecularProfile); + + MolecularProfileSamples molecularProfileSamples = new MolecularProfileSamples(); + molecularProfileSamples.setMolecularProfileId(MOLECULAR_PROFILE_ID); + molecularProfileSamples.setCommaSeparatedSampleIds("1,2,"); + + when(molecularDataRepository.getCommaSeparatedSampleIdsOfMolecularProfile(MOLECULAR_PROFILE_ID)) + .thenReturn(molecularProfileSamples); + + List molecularAlterationList = new ArrayList<>(); + GeneMolecularAlteration molecularAlteration = new GeneMolecularAlteration(); + molecularAlteration.setEntrezGeneId(ENTREZ_GENE_ID_1); + molecularAlteration.setValues("0.4674,-0.3456"); + molecularAlterationList.add(molecularAlteration); + + List entrezGeneIds = new ArrayList<>(); + entrezGeneIds.add(ENTREZ_GENE_ID_1); + when(molecularDataRepository.getGeneMolecularAlterations( + MOLECULAR_PROFILE_ID, entrezGeneIds, "ID")) + .thenReturn(molecularAlterationList); + + List internalIds = new ArrayList<>(); + internalIds.add(1); + internalIds.add(2); + + List samples = new ArrayList<>(); + Sample sample1 = new Sample(); + sample1.setInternalId(1); + sample1.setStableId(SAMPLE_ID1); + samples.add(sample1); + Sample sample2 = new Sample(); + sample2.setInternalId(2); + sample2.setStableId("sample_id_2"); + samples.add(sample2); + when(sampleService.getSamplesByInternalIds(internalIds)).thenReturn(samples); + + BaseMeta result = + molecularDataService.fetchMetaMolecularData(MOLECULAR_PROFILE_ID, null, entrezGeneIds); + + Assert.assertEquals((Integer) 2, result.getTotalCount()); + } + + @Test + public void getNumberOfSamplesInMolecularProfile() throws Exception { + + MolecularProfileSamples molecularProfileSamples = new MolecularProfileSamples(); + molecularProfileSamples.setMolecularProfileId(MOLECULAR_PROFILE_ID); + molecularProfileSamples.setCommaSeparatedSampleIds("1,2,"); + + when(molecularDataRepository.getCommaSeparatedSampleIdsOfMolecularProfile(MOLECULAR_PROFILE_ID)) + .thenReturn(molecularProfileSamples); + + Integer result = + molecularDataService.getNumberOfSamplesInMolecularProfile(MOLECULAR_PROFILE_ID); + + Assert.assertEquals((Integer) 2, result); + } + + @Test + public void getMolecularDataInMultipleMolecularProfilesByGeneQueries() { + + // two record come in .. + List unfilteredData = new ArrayList<>(); + GeneMolecularData geneMolecularData1 = new GeneMolecularData(); + geneMolecularData1.setEntrezGeneId(1); + geneMolecularData1.setMolecularProfileId("profile1"); + geneMolecularData1.setValue("-2"); + geneMolecularData1.setSampleId("sample1"); + GeneMolecularData geneMolecularData2 = new GeneMolecularData(); + geneMolecularData2.setEntrezGeneId(1); + geneMolecularData2.setMolecularProfileId("profile1"); + geneMolecularData2.setValue("-1"); + geneMolecularData2.setSampleId("sample2"); + unfilteredData.add(geneMolecularData1); + unfilteredData.add(geneMolecularData2); + + MolecularDataServiceImpl spy = spy(molecularDataService); + doReturn(unfilteredData) + .when(spy) + .getMolecularDataInMultipleMolecularProfiles(anyList(), anyList(), anyList(), anyString()); + + List selectedCnaEvents = new ArrayList<>(); + DiscreteCopyNumberData discreteCopyNumberData1 = new DiscreteCopyNumberData(); + discreteCopyNumberData1.setEntrezGeneId(1); + discreteCopyNumberData1.setMolecularProfileId("profile1"); + discreteCopyNumberData1.setAlteration(-2); + discreteCopyNumberData1.setSampleId("sample1"); + selectedCnaEvents.add(discreteCopyNumberData1); + + when(discreteCopyNumberRepository + .getDiscreteCopyNumbersInMultipleMolecularProfilesByGeneQueries( + anyList(), anyList(), anyList(), anyString())) + .thenReturn(selectedCnaEvents); + + List filteredData = + spy.getMolecularDataInMultipleMolecularProfilesByGeneQueries( + Arrays.asList(), Arrays.asList(), Arrays.asList(), "projection"); + + // one record comes out ... + // so, test whether record correctly removed from result set + Assert.assertEquals(1, filteredData.size()); + Assert.assertEquals("sample1", filteredData.get(0).getSampleId()); + } +} diff --git a/src/test/java/org/cbioportal/legacy/service/impl/MolecularProfileServiceImplTest.java b/src/test/java/org/cbioportal/legacy/service/impl/MolecularProfileServiceImplTest.java new file mode 100644 index 00000000000..5267016d750 --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/service/impl/MolecularProfileServiceImplTest.java @@ -0,0 +1,239 @@ +package org.cbioportal.legacy.service.impl; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import org.cbioportal.legacy.model.MolecularProfile; +import org.cbioportal.legacy.model.meta.BaseMeta; +import org.cbioportal.legacy.persistence.MolecularProfileRepository; +import org.cbioportal.legacy.service.StudyService; +import org.cbioportal.legacy.service.exception.MolecularProfileNotFoundException; +import org.cbioportal.legacy.service.exception.StudyNotFoundException; +import org.cbioportal.legacy.service.util.MolecularProfileUtil; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.junit.MockitoJUnitRunner; +import org.springframework.test.util.ReflectionTestUtils; + +@RunWith(MockitoJUnitRunner.class) +public class MolecularProfileServiceImplTest extends BaseServiceImplTest { + + @InjectMocks private MolecularProfileServiceImpl molecularProfileService; + + @Mock private MolecularProfileRepository molecularProfileRepository; + @Mock private StudyService studyService; + @Mock private MolecularProfileUtil molecularProfileUtil; + + @Before + public void setup() { + ReflectionTestUtils.setField(molecularProfileService, "AUTHENTICATE", "false"); + } + + @Test + public void getAllMolecularProfiles() throws Exception { + + List expectedMolecularProfileList = new ArrayList<>(); + MolecularProfile molecularProfile = new MolecularProfile(); + expectedMolecularProfileList.add(molecularProfile); + + Mockito.when( + molecularProfileRepository.getAllMolecularProfiles( + PROJECTION, PAGE_SIZE, PAGE_NUMBER, SORT, DIRECTION)) + .thenReturn(expectedMolecularProfileList); + + List result = + molecularProfileService.getAllMolecularProfiles( + PROJECTION, PAGE_SIZE, PAGE_NUMBER, SORT, DIRECTION); + + Assert.assertEquals(expectedMolecularProfileList, result); + } + + @Test + public void getMetaMolecularProfiles() throws Exception { + + BaseMeta expectedBaseMeta = new BaseMeta(); + + Mockito.when(molecularProfileRepository.getMetaMolecularProfiles()) + .thenReturn(expectedBaseMeta); + + BaseMeta result = molecularProfileService.getMetaMolecularProfiles(); + + Assert.assertEquals(expectedBaseMeta, result); + } + + @Test(expected = MolecularProfileNotFoundException.class) + public void getMolecularProfileNotFound() throws Exception { + + Mockito.when(molecularProfileRepository.getMolecularProfile(MOLECULAR_PROFILE_ID)) + .thenReturn(null); + + molecularProfileService.getMolecularProfile(MOLECULAR_PROFILE_ID); + } + + @Test + public void getMolecularProfile() throws Exception { + + MolecularProfile expectedMolecularProfile = new MolecularProfile(); + + Mockito.when(molecularProfileRepository.getMolecularProfile(MOLECULAR_PROFILE_ID)) + .thenReturn(expectedMolecularProfile); + + MolecularProfile result = molecularProfileService.getMolecularProfile(MOLECULAR_PROFILE_ID); + + Assert.assertEquals(expectedMolecularProfile, result); + } + + @Test + public void getMolecularProfiles() throws Exception { + + List expectedMolecularProfiles = new ArrayList<>(); + + Mockito.when( + molecularProfileRepository.getMolecularProfiles( + Collections.singleton(MOLECULAR_PROFILE_ID), PROJECTION)) + .thenReturn(expectedMolecularProfiles); + + List result = + molecularProfileService.getMolecularProfiles( + Collections.singleton(MOLECULAR_PROFILE_ID), PROJECTION); + + Assert.assertEquals(expectedMolecularProfiles, result); + } + + @Test + public void getMetaMolecularProfilesById() throws Exception { + + BaseMeta expectedBaseMeta = new BaseMeta(); + + Mockito.when( + molecularProfileRepository.getMetaMolecularProfiles( + Collections.singleton(MOLECULAR_PROFILE_ID))) + .thenReturn(expectedBaseMeta); + + BaseMeta result = + molecularProfileService.getMetaMolecularProfiles( + Collections.singleton(MOLECULAR_PROFILE_ID)); + + Assert.assertEquals(expectedBaseMeta, result); + } + + @Test + public void getAllMolecularProfilesInStudy() throws Exception { + + List expectedMolecularProfileList = new ArrayList<>(); + MolecularProfile molecularProfile = new MolecularProfile(); + expectedMolecularProfileList.add(molecularProfile); + + Mockito.when( + molecularProfileRepository.getAllMolecularProfilesInStudy( + STUDY_ID, PROJECTION, PAGE_SIZE, PAGE_NUMBER, SORT, DIRECTION)) + .thenReturn(expectedMolecularProfileList); + + List result = + molecularProfileService.getAllMolecularProfilesInStudy( + STUDY_ID, PROJECTION, PAGE_SIZE, PAGE_NUMBER, SORT, DIRECTION); + + Assert.assertEquals(expectedMolecularProfileList, result); + } + + @Test(expected = StudyNotFoundException.class) + public void getAllMolecularProfilesInStudyNotFound() throws Exception { + + Mockito.when(studyService.getStudy(STUDY_ID)).thenThrow(new StudyNotFoundException(STUDY_ID)); + molecularProfileService.getAllMolecularProfilesInStudy( + STUDY_ID, PROJECTION, PAGE_SIZE, PAGE_NUMBER, SORT, DIRECTION); + } + + @Test + public void getMetaMolecularProfilesInStudy() throws Exception { + + BaseMeta expectedBaseMeta = new BaseMeta(); + + Mockito.when(molecularProfileRepository.getMetaMolecularProfilesInStudy(STUDY_ID)) + .thenReturn(expectedBaseMeta); + + BaseMeta result = molecularProfileService.getMetaMolecularProfilesInStudy(STUDY_ID); + + Assert.assertEquals(expectedBaseMeta, result); + } + + @Test(expected = StudyNotFoundException.class) + public void getMetaMolecularProfilesInStudyNotFound() throws Exception { + + Mockito.when(studyService.getStudy(STUDY_ID)).thenThrow(new StudyNotFoundException(STUDY_ID)); + molecularProfileService.getMetaMolecularProfilesInStudy(STUDY_ID); + } + + @Test + public void getMolecularProfilesInStudies() throws Exception { + + List expectedMolecularProfileList = new ArrayList<>(); + MolecularProfile molecularProfile = new MolecularProfile(); + expectedMolecularProfileList.add(molecularProfile); + + Mockito.when( + molecularProfileRepository.getMolecularProfilesInStudies( + Arrays.asList(STUDY_ID), PROJECTION)) + .thenReturn(expectedMolecularProfileList); + + List result = + molecularProfileService.getMolecularProfilesInStudies(Arrays.asList(STUDY_ID), PROJECTION); + + Assert.assertEquals(expectedMolecularProfileList, result); + } + + @Test + public void getMetaMolecularProfilesInStudies() throws Exception { + + BaseMeta expectedBaseMeta = new BaseMeta(); + + Mockito.when( + molecularProfileRepository.getMetaMolecularProfilesInStudies(Arrays.asList(STUDY_ID))) + .thenReturn(expectedBaseMeta); + + BaseMeta result = + molecularProfileService.getMetaMolecularProfilesInStudies(Arrays.asList(STUDY_ID)); + + Assert.assertEquals(expectedBaseMeta, result); + } + + @Test + public void getMolecularProfilesReferredBy() throws Exception { + List expectedMolecularProfileList = new ArrayList<>(); + MolecularProfile molecularProfile = new MolecularProfile(); + expectedMolecularProfileList.add(molecularProfile); + + Mockito.when(molecularProfileRepository.getMolecularProfile(MOLECULAR_PROFILE_ID)) + .thenReturn(molecularProfile); + Mockito.when(molecularProfileRepository.getMolecularProfilesReferredBy(MOLECULAR_PROFILE_ID)) + .thenReturn(expectedMolecularProfileList); + + List result = + molecularProfileService.getMolecularProfilesReferredBy(MOLECULAR_PROFILE_ID); + + Assert.assertEquals(expectedMolecularProfileList, result); + } + + @Test + public void getMolecularProfilesReferringTo() throws Exception { + List expectedMolecularProfileList = new ArrayList<>(); + MolecularProfile molecularProfile = new MolecularProfile(); + expectedMolecularProfileList.add(molecularProfile); + + Mockito.when(molecularProfileRepository.getMolecularProfile(MOLECULAR_PROFILE_ID)) + .thenReturn(molecularProfile); + Mockito.when(molecularProfileRepository.getMolecularProfilesReferringTo(MOLECULAR_PROFILE_ID)) + .thenReturn(expectedMolecularProfileList); + + List result = + molecularProfileService.getMolecularProfilesReferringTo(MOLECULAR_PROFILE_ID); + + Assert.assertEquals(expectedMolecularProfileList, result); + } +} diff --git a/src/test/java/org/cbioportal/legacy/service/impl/MrnaPercentileServiceImplTest.java b/src/test/java/org/cbioportal/legacy/service/impl/MrnaPercentileServiceImplTest.java new file mode 100644 index 00000000000..8a06ca84983 --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/service/impl/MrnaPercentileServiceImplTest.java @@ -0,0 +1,101 @@ +package org.cbioportal.legacy.service.impl; + +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.List; +import org.cbioportal.legacy.model.GeneMolecularData; +import org.cbioportal.legacy.model.MolecularProfile; +import org.cbioportal.legacy.model.MrnaPercentile; +import org.cbioportal.legacy.service.MolecularDataService; +import org.cbioportal.legacy.service.MolecularProfileService; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.junit.MockitoJUnitRunner; + +@RunWith(MockitoJUnitRunner.class) +public class MrnaPercentileServiceImplTest extends BaseServiceImplTest { + + @InjectMocks private MrnaPercentileServiceImpl mrnaPercentileService; + + @Mock private MolecularDataService molecularDataService; + @Mock private MolecularProfileService molecularProfileService; + + @Test + public void fetchMrnaPercentile() throws Exception { + + List molecularDataList = new ArrayList<>(); + GeneMolecularData molecularData1 = new GeneMolecularData(); + molecularData1.setMolecularProfileId(MOLECULAR_PROFILE_ID); + molecularData1.setEntrezGeneId(ENTREZ_GENE_ID_1); + molecularData1.setSampleId(SAMPLE_ID1); + molecularData1.setValue("0.3456"); + molecularDataList.add(molecularData1); + GeneMolecularData molecularData2 = new GeneMolecularData(); + molecularData2.setMolecularProfileId(MOLECULAR_PROFILE_ID); + molecularData2.setEntrezGeneId(ENTREZ_GENE_ID_1); + molecularData2.setSampleId("sample_id_2"); + molecularData2.setValue("0.2456"); + molecularDataList.add(molecularData2); + GeneMolecularData molecularData3 = new GeneMolecularData(); + molecularData3.setMolecularProfileId(MOLECULAR_PROFILE_ID); + molecularData3.setEntrezGeneId(ENTREZ_GENE_ID_1); + molecularData3.setSampleId("sample_id_3"); + molecularData3.setValue("0.2457"); + molecularDataList.add(molecularData3); + GeneMolecularData molecularData4 = new GeneMolecularData(); + molecularData4.setMolecularProfileId(MOLECULAR_PROFILE_ID); + molecularData4.setEntrezGeneId(2); + molecularData4.setSampleId(SAMPLE_ID1); + molecularData4.setValue("NA"); + molecularDataList.add(molecularData4); + GeneMolecularData molecularData5 = new GeneMolecularData(); + molecularData5.setMolecularProfileId(MOLECULAR_PROFILE_ID); + molecularData5.setEntrezGeneId(2); + molecularData5.setSampleId("sample_id_2"); + molecularData5.setValue("0.1456"); + molecularDataList.add(molecularData5); + GeneMolecularData molecularData6 = new GeneMolecularData(); + molecularData6.setMolecularProfileId(MOLECULAR_PROFILE_ID); + molecularData6.setEntrezGeneId(2); + molecularData6.setSampleId("sample_id_3"); + molecularData6.setValue("-0.1234"); + molecularDataList.add(molecularData6); + + MolecularProfile molecularProfile = new MolecularProfile(); + molecularProfile.setMolecularAlterationType( + MolecularProfile.MolecularAlterationType.MRNA_EXPRESSION); + Mockito.when(molecularProfileService.getMolecularProfile(MOLECULAR_PROFILE_ID)) + .thenReturn(molecularProfile); + + List entrezGeneIds = new ArrayList<>(); + entrezGeneIds.add(ENTREZ_GENE_ID_1); + entrezGeneIds.add(2); + + Mockito.when( + molecularDataService.fetchMolecularData( + MOLECULAR_PROFILE_ID, null, entrezGeneIds, "SUMMARY")) + .thenReturn(molecularDataList); + + List result = + mrnaPercentileService.fetchMrnaPercentile( + MOLECULAR_PROFILE_ID, "sample_id_2", entrezGeneIds); + + Assert.assertEquals(2, result.size()); + MrnaPercentile mrnaPercentile1 = result.get(0); + Assert.assertEquals(MOLECULAR_PROFILE_ID, mrnaPercentile1.getMolecularProfileId()); + Assert.assertEquals("sample_id_2", mrnaPercentile1.getSampleId()); + Assert.assertEquals(ENTREZ_GENE_ID_1, mrnaPercentile1.getEntrezGeneId()); + Assert.assertEquals(new BigDecimal("0.2456"), mrnaPercentile1.getzScore()); + Assert.assertEquals(new BigDecimal("33.33"), mrnaPercentile1.getPercentile()); + MrnaPercentile mrnaPercentile2 = result.get(1); + Assert.assertEquals(MOLECULAR_PROFILE_ID, mrnaPercentile2.getMolecularProfileId()); + Assert.assertEquals("sample_id_2", mrnaPercentile2.getSampleId()); + Assert.assertEquals((Integer) 2, mrnaPercentile2.getEntrezGeneId()); + Assert.assertEquals(new BigDecimal("0.1456"), mrnaPercentile2.getzScore()); + Assert.assertEquals(new BigDecimal("100.00"), mrnaPercentile2.getPercentile()); + } +} diff --git a/src/test/java/org/cbioportal/legacy/service/impl/MutationServiceImplTest.java b/src/test/java/org/cbioportal/legacy/service/impl/MutationServiceImplTest.java new file mode 100644 index 00000000000..9c09086fabe --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/service/impl/MutationServiceImplTest.java @@ -0,0 +1,369 @@ +package org.cbioportal.legacy.service.impl; + +import static org.mockito.ArgumentMatchers.anyList; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mock; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import org.cbioportal.legacy.model.Gene; +import org.cbioportal.legacy.model.GeneFilterQuery; +import org.cbioportal.legacy.model.GenomicDataCount; +import org.cbioportal.legacy.model.GenomicDataCountItem; +import org.cbioportal.legacy.model.MolecularProfile; +import org.cbioportal.legacy.model.Mutation; +import org.cbioportal.legacy.model.MutationCountByPosition; +import org.cbioportal.legacy.model.MutationEventType; +import org.cbioportal.legacy.model.meta.MutationMeta; +import org.cbioportal.legacy.persistence.MutationRepository; +import org.cbioportal.legacy.service.MolecularProfileService; +import org.cbioportal.legacy.service.exception.MolecularProfileNotFoundException; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.junit.MockitoJUnitRunner; + +@RunWith(MockitoJUnitRunner.Silent.class) +public class MutationServiceImplTest extends BaseServiceImplTest { + + @InjectMocks private MutationServiceImpl mutationService; + + @Mock private MutationRepository mutationRepository; + @Mock private MolecularProfileService molecularProfileService; + + @Test + public void getMutationsInMolecularProfileBySampleListId() throws Exception { + + MolecularProfile molecularProfile = new MolecularProfile(); + molecularProfile.setMolecularAlterationType( + MolecularProfile.MolecularAlterationType.MUTATION_EXTENDED); + Mockito.when(molecularProfileService.getMolecularProfile(MOLECULAR_PROFILE_ID)) + .thenReturn(molecularProfile); + + List expectedMutationList = new ArrayList<>(); + Mutation mutation = new Mutation(); + Gene gene = new Gene(); + mutation.setGene(gene); + mutation.setChr("19"); + expectedMutationList.add(mutation); + + Mockito.when( + mutationRepository.getMutationsInMolecularProfileBySampleListId( + MOLECULAR_PROFILE_ID, + SAMPLE_LIST_ID, + Arrays.asList(ENTREZ_GENE_ID_1), + false, + PROJECTION, + PAGE_SIZE, + PAGE_NUMBER, + SORT, + DIRECTION)) + .thenReturn(expectedMutationList); + + List result = + mutationService.getMutationsInMolecularProfileBySampleListId( + MOLECULAR_PROFILE_ID, + SAMPLE_LIST_ID, + Arrays.asList(ENTREZ_GENE_ID_1), + false, + PROJECTION, + PAGE_SIZE, + PAGE_NUMBER, + SORT, + DIRECTION); + + Assert.assertEquals(expectedMutationList, result); + Assert.assertEquals("19", result.get(0).getChr()); + } + + @Test(expected = MolecularProfileNotFoundException.class) + public void getMutationsInMolecularProfileBySampleListIdMolecularProfileNotFound() + throws Exception { + + Mockito.when(molecularProfileService.getMolecularProfile(MOLECULAR_PROFILE_ID)) + .thenThrow(new MolecularProfileNotFoundException(MOLECULAR_PROFILE_ID)); + mutationService.getMutationsInMolecularProfileBySampleListId( + MOLECULAR_PROFILE_ID, + SAMPLE_LIST_ID, + Arrays.asList(ENTREZ_GENE_ID_1), + false, + PROJECTION, + PAGE_SIZE, + PAGE_NUMBER, + SORT, + DIRECTION); + } + + @Test + public void getMetaMutationsInMolecularProfileBySampleListId() throws Exception { + + MolecularProfile molecularProfile = new MolecularProfile(); + molecularProfile.setMolecularAlterationType( + MolecularProfile.MolecularAlterationType.MUTATION_EXTENDED); + Mockito.when(molecularProfileService.getMolecularProfile(MOLECULAR_PROFILE_ID)) + .thenReturn(molecularProfile); + + MutationMeta expectedMutationMeta = new MutationMeta(); + Mockito.when( + mutationRepository.getMetaMutationsInMolecularProfileBySampleListId( + MOLECULAR_PROFILE_ID, SAMPLE_LIST_ID, Arrays.asList(ENTREZ_GENE_ID_1))) + .thenReturn(expectedMutationMeta); + MutationMeta result = + mutationService.getMetaMutationsInMolecularProfileBySampleListId( + MOLECULAR_PROFILE_ID, SAMPLE_LIST_ID, Arrays.asList(ENTREZ_GENE_ID_1)); + + Assert.assertEquals(expectedMutationMeta, result); + } + + @Test(expected = MolecularProfileNotFoundException.class) + public void getMetaMutationsInMolecularProfileBySampleListIdMolecularProfileNotFound() + throws Exception { + + Mockito.when(molecularProfileService.getMolecularProfile(MOLECULAR_PROFILE_ID)) + .thenThrow(new MolecularProfileNotFoundException(MOLECULAR_PROFILE_ID)); + mutationService.getMetaMutationsInMolecularProfileBySampleListId( + MOLECULAR_PROFILE_ID, SAMPLE_LIST_ID, Arrays.asList(ENTREZ_GENE_ID_1)); + } + + @Test + public void getMutationsInMultipleMolecularProfiles() throws Exception { + + List expectedMutationList = new ArrayList<>(); + Mutation mutation = new Mutation(); + Gene gene = new Gene(); + mutation.setGene(gene); + mutation.setChr("19"); + expectedMutationList.add(mutation); + + Mockito.when( + mutationRepository.getMutationsInMultipleMolecularProfiles( + anyList(), + anyList(), + anyList(), + eq(PROJECTION), + eq(PAGE_SIZE), + eq(PAGE_NUMBER), + eq(SORT), + eq(DIRECTION))) + .thenReturn(expectedMutationList); + + List result = + mutationService.getMutationsInMultipleMolecularProfiles( + Arrays.asList(MOLECULAR_PROFILE_ID), + Arrays.asList(SAMPLE_ID1), + Arrays.asList(ENTREZ_GENE_ID_1), + PROJECTION, + PAGE_SIZE, + PAGE_NUMBER, + SORT, + DIRECTION); + + Assert.assertEquals(expectedMutationList, result); + Assert.assertEquals("19", result.get(0).getChr()); + } + + @Test + public void getMutationsInMultipleMolecularProfilesByGeneQueries() throws Exception { + + List expectedMutationList = new ArrayList<>(); + Mutation mutation = new Mutation(); + Gene gene = new Gene(); + mutation.setGene(gene); + mutation.setChr("19"); + expectedMutationList.add(mutation); + + GeneFilterQuery geneFilterQuery = mock(GeneFilterQuery.class); + + Mockito.when( + mutationRepository.getMutationsInMultipleMolecularProfilesByGeneQueries( + anyList(), + anyList(), + anyList(), + eq(PROJECTION), + eq(PAGE_SIZE), + eq(PAGE_NUMBER), + eq(SORT), + eq(DIRECTION))) + .thenReturn(expectedMutationList); + + List result = + mutationService.getMutationsInMultipleMolecularProfilesByGeneQueries( + Arrays.asList(MOLECULAR_PROFILE_ID), + Arrays.asList(SAMPLE_ID1), + Arrays.asList(geneFilterQuery), + PROJECTION, + PAGE_SIZE, + PAGE_NUMBER, + SORT, + DIRECTION); + + Assert.assertEquals(expectedMutationList, result); + Assert.assertEquals("19", result.get(0).getChr()); + } + + @Test + public void getMetaMutationsInMultipleMolecularProfiles() throws Exception { + + MutationMeta expectedMutationMeta = new MutationMeta(); + Mockito.when( + mutationRepository.getMetaMutationsInMultipleMolecularProfiles( + Arrays.asList(MOLECULAR_PROFILE_ID), + Arrays.asList(SAMPLE_ID1), + Arrays.asList(ENTREZ_GENE_ID_1))) + .thenReturn(expectedMutationMeta); + MutationMeta result = + mutationService.getMetaMutationsInMultipleMolecularProfiles( + Arrays.asList(MOLECULAR_PROFILE_ID), + Arrays.asList(SAMPLE_ID1), + Arrays.asList(ENTREZ_GENE_ID_1)); + + Assert.assertEquals(expectedMutationMeta, result); + } + + @Test + public void fetchMutationsInMolecularProfile() throws Exception { + + MolecularProfile molecularProfile = new MolecularProfile(); + molecularProfile.setMolecularAlterationType( + MolecularProfile.MolecularAlterationType.MUTATION_EXTENDED); + Mockito.when(molecularProfileService.getMolecularProfile(MOLECULAR_PROFILE_ID)) + .thenReturn(molecularProfile); + + List expectedMutationList = new ArrayList<>(); + Mutation mutation = new Mutation(); + Gene gene = new Gene(); + mutation.setGene(gene); + mutation.setChr("19"); + expectedMutationList.add(mutation); + + Mockito.when( + mutationRepository.fetchMutationsInMolecularProfile( + MOLECULAR_PROFILE_ID, + Arrays.asList(SAMPLE_ID1), + Arrays.asList(ENTREZ_GENE_ID_1), + false, + PROJECTION, + PAGE_SIZE, + PAGE_NUMBER, + SORT, + DIRECTION)) + .thenReturn(expectedMutationList); + + List result = + mutationService.fetchMutationsInMolecularProfile( + MOLECULAR_PROFILE_ID, + Arrays.asList(SAMPLE_ID1), + Arrays.asList(ENTREZ_GENE_ID_1), + false, + PROJECTION, + PAGE_SIZE, + PAGE_NUMBER, + SORT, + DIRECTION); + + Assert.assertEquals(expectedMutationList, result); + Assert.assertEquals("19", result.get(0).getChr()); + } + + @Test(expected = MolecularProfileNotFoundException.class) + public void fetchMutationsInMolecularProfileNotFound() throws Exception { + + Mockito.when(molecularProfileService.getMolecularProfile(MOLECULAR_PROFILE_ID)) + .thenThrow(new MolecularProfileNotFoundException(MOLECULAR_PROFILE_ID)); + mutationService.fetchMutationsInMolecularProfile( + MOLECULAR_PROFILE_ID, + Arrays.asList(SAMPLE_ID1), + Arrays.asList(ENTREZ_GENE_ID_1), + false, + PROJECTION, + PAGE_SIZE, + PAGE_NUMBER, + SORT, + DIRECTION); + } + + @Test + public void fetchMetaMutationsInMolecularProfile() throws Exception { + + MolecularProfile molecularProfile = new MolecularProfile(); + molecularProfile.setMolecularAlterationType( + MolecularProfile.MolecularAlterationType.MUTATION_EXTENDED); + Mockito.when(molecularProfileService.getMolecularProfile(MOLECULAR_PROFILE_ID)) + .thenReturn(molecularProfile); + + MutationMeta expectedMutationMeta = new MutationMeta(); + Mockito.when( + mutationRepository.fetchMetaMutationsInMolecularProfile( + MOLECULAR_PROFILE_ID, Arrays.asList(SAMPLE_ID1), Arrays.asList(ENTREZ_GENE_ID_1))) + .thenReturn(expectedMutationMeta); + MutationMeta result = + mutationService.fetchMetaMutationsInMolecularProfile( + MOLECULAR_PROFILE_ID, Arrays.asList(SAMPLE_ID1), Arrays.asList(ENTREZ_GENE_ID_1)); + + Assert.assertEquals(expectedMutationMeta, result); + } + + @Test(expected = MolecularProfileNotFoundException.class) + public void fetchMetaMutationsInMolecularProfileNotFound() throws Exception { + + Mockito.when(molecularProfileService.getMolecularProfile(MOLECULAR_PROFILE_ID)) + .thenThrow(new MolecularProfileNotFoundException(MOLECULAR_PROFILE_ID)); + mutationService.fetchMetaMutationsInMolecularProfile( + MOLECULAR_PROFILE_ID, Arrays.asList(SAMPLE_ID1), Arrays.asList(ENTREZ_GENE_ID_1)); + } + + @Test + public void fetchMutationCountsByPosition() throws Exception { + + MutationCountByPosition expectedMutationCountByPosition = new MutationCountByPosition(); + Mockito.when( + mutationRepository.getMutationCountByPosition( + ENTREZ_GENE_ID_1, PROTEIN_POS_START, PROTEIN_POS_END)) + .thenReturn(expectedMutationCountByPosition); + + List result = + mutationService.fetchMutationCountsByPosition( + Arrays.asList(ENTREZ_GENE_ID_1), + Arrays.asList(PROTEIN_POS_START), + Arrays.asList(PROTEIN_POS_END)); + + Assert.assertEquals(1, result.size()); + Assert.assertEquals(expectedMutationCountByPosition, result.get(0)); + } + + @Test + public void getMutationCountsByType() { + GenomicDataCountItem expectedGenomicDataCountItem = new GenomicDataCountItem(); + expectedGenomicDataCountItem.setProfileType(PROFILE_TYPE_1); + expectedGenomicDataCountItem.setHugoGeneSymbol(HUGO_GENE_SYMBOL_1); + GenomicDataCount expectedGenomicDataCount = new GenomicDataCount(); + expectedGenomicDataCount.setLabel(MutationEventType.missense_mutation.getMutationType()); + expectedGenomicDataCount.setValue(MutationEventType.missense_mutation.getMutationType()); + expectedGenomicDataCount.setCount(2); + expectedGenomicDataCount.setUniqueCount(1); + expectedGenomicDataCountItem.setCounts(Collections.singletonList(expectedGenomicDataCount)); + + Mockito.when( + mutationRepository.getMutationCountsByType( + Collections.singletonList(MOLECULAR_PROFILE_ID), + Collections.singletonList(SAMPLE_ID1), + Collections.singletonList(ENTREZ_GENE_ID_1), + PROFILE_TYPE_1)) + .thenReturn(expectedGenomicDataCountItem); + + GenomicDataCountItem result = + mutationService.getMutationCountsByType( + Collections.singletonList(MOLECULAR_PROFILE_ID), + Collections.singletonList(SAMPLE_ID1), + Collections.singletonList(ENTREZ_GENE_ID_1), + PROFILE_TYPE_1); + + Assert.assertEquals(expectedGenomicDataCountItem, result); + Assert.assertEquals(1, result.getCounts().size()); + } +} diff --git a/src/test/java/org/cbioportal/legacy/service/impl/MutationSpectrumServiceImplTest.java b/src/test/java/org/cbioportal/legacy/service/impl/MutationSpectrumServiceImplTest.java new file mode 100644 index 00000000000..fb440f5effa --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/service/impl/MutationSpectrumServiceImplTest.java @@ -0,0 +1,134 @@ +package org.cbioportal.legacy.service.impl; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import org.cbioportal.legacy.model.Mutation; +import org.cbioportal.legacy.model.MutationSpectrum; +import org.cbioportal.legacy.service.MutationService; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.junit.MockitoJUnitRunner; + +@RunWith(MockitoJUnitRunner.class) +public class MutationSpectrumServiceImplTest extends BaseServiceImplTest { + + @InjectMocks private MutationSpectrumServiceImpl mutationSpectrumService; + + @Mock private MutationService mutationService; + + @Test + public void getMutationSpectrums() throws Exception { + + List mutationList = createMutationList(); + + Mockito.when( + mutationService.getMutationsInMolecularProfileBySampleListId( + MOLECULAR_PROFILE_ID, + SAMPLE_LIST_ID, + null, + true, + "SUMMARY", + null, + null, + null, + null)) + .thenReturn(mutationList); + + List result = + mutationSpectrumService.getMutationSpectrums(MOLECULAR_PROFILE_ID, SAMPLE_LIST_ID); + + Assert.assertEquals(2, result.size()); + MutationSpectrum mutationSpectrum1 = result.get(0); + Assert.assertEquals(MOLECULAR_PROFILE_ID, mutationSpectrum1.getMolecularProfileId()); + Assert.assertEquals(SAMPLE_ID1, mutationSpectrum1.getSampleId()); + Assert.assertEquals((Integer) 2, mutationSpectrum1.getCtoA()); + Assert.assertEquals((Integer) 0, mutationSpectrum1.getCtoG()); + Assert.assertEquals((Integer) 0, mutationSpectrum1.getCtoT()); + Assert.assertEquals((Integer) 0, mutationSpectrum1.getTtoA()); + Assert.assertEquals((Integer) 0, mutationSpectrum1.getTtoC()); + Assert.assertEquals((Integer) 0, mutationSpectrum1.getTtoG()); + MutationSpectrum mutationSpectrum2 = result.get(1); + Assert.assertEquals(MOLECULAR_PROFILE_ID, mutationSpectrum2.getMolecularProfileId()); + Assert.assertEquals(SAMPLE_ID2, mutationSpectrum2.getSampleId()); + Assert.assertEquals((Integer) 0, mutationSpectrum2.getCtoA()); + Assert.assertEquals((Integer) 0, mutationSpectrum2.getCtoG()); + Assert.assertEquals((Integer) 1, mutationSpectrum2.getCtoT()); + Assert.assertEquals((Integer) 1, mutationSpectrum2.getTtoA()); + Assert.assertEquals((Integer) 0, mutationSpectrum2.getTtoC()); + Assert.assertEquals((Integer) 0, mutationSpectrum2.getTtoG()); + } + + @Test + public void fetchMutationSpectrums() throws Exception { + + List mutationList = createMutationList(); + + Mockito.when( + mutationService.fetchMutationsInMolecularProfile( + MOLECULAR_PROFILE_ID, + Arrays.asList(SAMPLE_ID1, SAMPLE_ID2), + null, + true, + "SUMMARY", + null, + null, + null, + null)) + .thenReturn(mutationList); + + List result = + mutationSpectrumService.fetchMutationSpectrums( + MOLECULAR_PROFILE_ID, Arrays.asList(SAMPLE_ID1, SAMPLE_ID2)); + + Assert.assertEquals(2, result.size()); + MutationSpectrum mutationSpectrum1 = result.get(0); + Assert.assertEquals(MOLECULAR_PROFILE_ID, mutationSpectrum1.getMolecularProfileId()); + Assert.assertEquals(SAMPLE_ID1, mutationSpectrum1.getSampleId()); + Assert.assertEquals((Integer) 2, mutationSpectrum1.getCtoA()); + Assert.assertEquals((Integer) 0, mutationSpectrum1.getCtoG()); + Assert.assertEquals((Integer) 0, mutationSpectrum1.getCtoT()); + Assert.assertEquals((Integer) 0, mutationSpectrum1.getTtoA()); + Assert.assertEquals((Integer) 0, mutationSpectrum1.getTtoC()); + Assert.assertEquals((Integer) 0, mutationSpectrum1.getTtoG()); + MutationSpectrum mutationSpectrum2 = result.get(1); + Assert.assertEquals(MOLECULAR_PROFILE_ID, mutationSpectrum2.getMolecularProfileId()); + Assert.assertEquals(SAMPLE_ID2, mutationSpectrum2.getSampleId()); + Assert.assertEquals((Integer) 0, mutationSpectrum2.getCtoA()); + Assert.assertEquals((Integer) 0, mutationSpectrum2.getCtoG()); + Assert.assertEquals((Integer) 1, mutationSpectrum2.getCtoT()); + Assert.assertEquals((Integer) 1, mutationSpectrum2.getTtoA()); + Assert.assertEquals((Integer) 0, mutationSpectrum2.getTtoC()); + Assert.assertEquals((Integer) 0, mutationSpectrum2.getTtoG()); + } + + private List createMutationList() { + + List mutationList = new ArrayList<>(); + Mutation mutation1 = new Mutation(); + mutation1.setSampleId(SAMPLE_ID1); + mutation1.setReferenceAllele("C"); + mutation1.setTumorSeqAllele("A"); + mutationList.add(mutation1); + Mutation mutation2 = new Mutation(); + mutation2.setSampleId(SAMPLE_ID1); + mutation2.setReferenceAllele("G"); + mutation2.setTumorSeqAllele("T"); + mutationList.add(mutation2); + Mutation mutation3 = new Mutation(); + mutation3.setSampleId(SAMPLE_ID2); + mutation3.setReferenceAllele("T"); + mutation3.setTumorSeqAllele("A"); + mutationList.add(mutation3); + Mutation mutation4 = new Mutation(); + mutation4.setSampleId(SAMPLE_ID2); + mutation4.setReferenceAllele("C"); + mutation4.setTumorSeqAllele("T"); + mutationList.add(mutation4); + return mutationList; + } +} diff --git a/src/test/java/org/cbioportal/legacy/service/impl/NamespaceAttributeServiceImplTest.java b/src/test/java/org/cbioportal/legacy/service/impl/NamespaceAttributeServiceImplTest.java new file mode 100644 index 00000000000..14ed7a24548 --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/service/impl/NamespaceAttributeServiceImplTest.java @@ -0,0 +1,73 @@ +package org.cbioportal.legacy.service.impl; + +import static org.mockito.ArgumentMatchers.any; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import org.cbioportal.legacy.model.NamespaceAttribute; +import org.cbioportal.legacy.model.NamespaceAttributeCount; +import org.cbioportal.legacy.persistence.NamespaceRepository; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.junit.MockitoJUnitRunner; + +@RunWith(MockitoJUnitRunner.class) +public class NamespaceAttributeServiceImplTest extends BaseServiceImplTest { + + @InjectMocks private NamespaceAttributeServiceImpl namespaceAttributeService; + + @Mock private NamespaceRepository namespaceRepository; + + @Test + public void fetchNamespaceAttributes() { + + List expectedNamespaceAttributeList = new ArrayList<>(); + NamespaceAttribute namespaceAttribute = + new NamespaceAttribute(NAMESPACE_OUTER_KEY_1, NAMESPACE_INNER_KEY_1); + expectedNamespaceAttributeList.add(namespaceAttribute); + + Mockito.when(namespaceRepository.getNamespaceOuterKey(Arrays.asList(STUDY_ID))) + .thenReturn(expectedNamespaceAttributeList); + + Mockito.when(namespaceRepository.getNamespaceInnerKey(any(), any())) + .thenReturn(expectedNamespaceAttributeList); + + List result = + namespaceAttributeService.fetchNamespaceAttributes(Arrays.asList(STUDY_ID)); + + Assert.assertEquals(expectedNamespaceAttributeList, result); + } + + @Test + public void getNamespaceAttributeCountsBySampleIds() { + + List namespaceAttributes = new ArrayList<>(); + NamespaceAttribute namespaceAttribute = + new NamespaceAttribute(NAMESPACE_OUTER_KEY_1, NAMESPACE_INNER_KEY_1); + List sampleIds = new ArrayList<>(); + List studyIds = new ArrayList<>(); + sampleIds.add(SAMPLE_ID1); + studyIds.add(STUDY_ID); + namespaceAttributes.add(namespaceAttribute); + + List expectedNamespaceAttributeCounts = new ArrayList<>(); + NamespaceAttributeCount namespaceAttributeCount = new NamespaceAttributeCount(); + expectedNamespaceAttributeCounts.add(namespaceAttributeCount); + + Mockito.when( + namespaceRepository.getNamespaceAttributeCountsBySampleIds( + sampleIds, studyIds, namespaceAttributes)) + .thenReturn(expectedNamespaceAttributeCounts); + + List result = + namespaceAttributeService.fetchNamespaceAttributeCountsBySampleIds( + sampleIds, studyIds, namespaceAttributes); + + Assert.assertEquals(expectedNamespaceAttributeCounts, result); + } +} diff --git a/src/test/java/org/cbioportal/legacy/service/impl/NamespaceDataServiceImplTest.java b/src/test/java/org/cbioportal/legacy/service/impl/NamespaceDataServiceImplTest.java new file mode 100644 index 00000000000..2578cd8f838 --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/service/impl/NamespaceDataServiceImplTest.java @@ -0,0 +1,125 @@ +package org.cbioportal.legacy.service.impl; + +import static org.mockito.Mockito.when; + +import java.util.*; +import org.cbioportal.legacy.model.NamespaceAttribute; +import org.cbioportal.legacy.model.NamespaceData; +import org.cbioportal.legacy.model.NamespaceDataCount; +import org.cbioportal.legacy.model.NamespaceDataCountItem; +import org.cbioportal.legacy.persistence.NamespaceRepository; +import org.cbioportal.legacy.web.parameter.NamespaceDataFilter; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnitRunner; + +@RunWith(MockitoJUnitRunner.class) +public class NamespaceDataServiceImplTest extends BaseServiceImplTest { + + @InjectMocks private NamespaceDataServiceImpl namespaceDataService; + + @Mock private NamespaceRepository namespaceRepository; + + @Test + public void fetchNamespaceData() { + + List namespaceDataFilters = new ArrayList<>(); + NamespaceDataFilter namespaceDataFilter = new NamespaceDataFilter(); + namespaceDataFilter.setOuterKey(NAMESPACE_OUTER_KEY_1); + namespaceDataFilter.setInnerKey(NAMESPACE_OUTER_KEY_1); + namespaceDataFilters.add(namespaceDataFilter); + List expectedNamespaceDataList = new ArrayList<>(); + NamespaceData namespaceData = new NamespaceData(); + expectedNamespaceDataList.add(namespaceData); + + when(namespaceRepository.getNamespaceData( + Arrays.asList(STUDY_ID), + Arrays.asList(SAMPLE_ID1, SAMPLE_ID2, SAMPLE_ID3), + namespaceDataFilter.getOuterKey(), + namespaceDataFilter.getInnerKey())) + .thenReturn(expectedNamespaceDataList); + + List result = + namespaceDataService.fetchNamespaceData( + Arrays.asList(STUDY_ID), + Arrays.asList(SAMPLE_ID1, SAMPLE_ID2, SAMPLE_ID3), + namespaceDataFilters); + + Assert.assertEquals(expectedNamespaceDataList, result); + } + + @Test + public void fetchNamespaceDataForComparison() { + + NamespaceAttribute namespaceAttribute = new NamespaceAttribute(); + namespaceAttribute.setOuterKey(NAMESPACE_OUTER_KEY_1); + namespaceAttribute.setInnerKey(NAMESPACE_OUTER_KEY_1); + List expectedNamespaceDataList = new ArrayList<>(); + NamespaceData namespaceData = new NamespaceData(); + expectedNamespaceDataList.add(namespaceData); + + when(namespaceRepository.getNamespaceDataForComparison( + Arrays.asList(STUDY_ID), + Arrays.asList(SAMPLE_ID1, SAMPLE_ID2, SAMPLE_ID3), + namespaceAttribute.getOuterKey(), + namespaceAttribute.getInnerKey(), + CATEGORY_VALUE_1)) + .thenReturn(expectedNamespaceDataList); + + List result = + namespaceDataService.fetchNamespaceDataForComparison( + Arrays.asList(STUDY_ID), + Arrays.asList(SAMPLE_ID1, SAMPLE_ID2, SAMPLE_ID3), + namespaceAttribute, + Arrays.asList(CATEGORY_VALUE_1)); + + Assert.assertEquals(expectedNamespaceDataList, result); + } + + @Test + public void fetchNamespaceDataCounts() { + + NamespaceAttribute namespaceAttribute1 = new NamespaceAttribute(); + namespaceAttribute1.setOuterKey(NAMESPACE_OUTER_KEY_1); + namespaceAttribute1.setInnerKey(NAMESPACE_INNER_KEY_1); + NamespaceDataCount namespaceDataCount1 = new NamespaceDataCount(); + namespaceDataCount1.setValue("value1"); + namespaceDataCount1.setCount(1); + namespaceDataCount1.setTotalCount(5); + NamespaceDataCount namespaceDataCount2 = new NamespaceDataCount(); + namespaceDataCount2.setValue("value2"); + namespaceDataCount2.setCount(3); + namespaceDataCount2.setTotalCount(6); + + when(namespaceRepository.getNamespaceDataCounts( + Arrays.asList(STUDY_ID, STUDY_ID, STUDY_ID), + Arrays.asList(SAMPLE_ID1, SAMPLE_ID2, SAMPLE_ID3), + NAMESPACE_OUTER_KEY_1, + NAMESPACE_INNER_KEY_1)) + .thenReturn(Arrays.asList(namespaceDataCount1, namespaceDataCount2)); + + List result = + namespaceDataService.fetchNamespaceDataCounts( + Arrays.asList(STUDY_ID, STUDY_ID, STUDY_ID), + Arrays.asList(SAMPLE_ID1, SAMPLE_ID2, SAMPLE_ID3), + Arrays.asList(namespaceAttribute1)); + + Assert.assertEquals(1, result.size()); + NamespaceDataCountItem counts1 = result.get(0); + Assert.assertEquals(NAMESPACE_OUTER_KEY_1, counts1.getOuterKey()); + Assert.assertEquals(NAMESPACE_INNER_KEY_1, counts1.getInnerKey()); + List namespaceDataCounts = counts1.getCounts(); + Assert.assertEquals(2, namespaceDataCounts.size()); + NamespaceDataCount count1 = namespaceDataCounts.get(0); + Assert.assertEquals("value1", count1.getValue()); + Assert.assertEquals((Integer) 1, count1.getCount()); + Assert.assertEquals((Integer) 5, count1.getTotalCount()); + NamespaceDataCount count2 = namespaceDataCounts.get(1); + Assert.assertEquals("value2", count2.getValue()); + Assert.assertEquals((Integer) 3, count2.getCount()); + Assert.assertEquals((Integer) 6, count2.getTotalCount()); + } +} diff --git a/src/test/java/org/cbioportal/legacy/service/impl/PatientServiceImplTest.java b/src/test/java/org/cbioportal/legacy/service/impl/PatientServiceImplTest.java new file mode 100644 index 00000000000..c6603a9a39d --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/service/impl/PatientServiceImplTest.java @@ -0,0 +1,187 @@ +package org.cbioportal.legacy.service.impl; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import org.cbioportal.legacy.model.Patient; +import org.cbioportal.legacy.model.meta.BaseMeta; +import org.cbioportal.legacy.persistence.PatientRepository; +import org.cbioportal.legacy.service.StudyService; +import org.cbioportal.legacy.service.exception.PatientNotFoundException; +import org.cbioportal.legacy.service.exception.StudyNotFoundException; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.junit.MockitoJUnitRunner; +import org.springframework.test.util.ReflectionTestUtils; + +@RunWith(MockitoJUnitRunner.class) +public class PatientServiceImplTest extends BaseServiceImplTest { + + @InjectMocks private PatientServiceImpl patientService; + + @Mock private PatientRepository patientRepository; + @Mock private StudyService studyService; + + @Before + public void setup() { + ReflectionTestUtils.setField(patientService, "AUTHENTICATE", "false"); + } + + @Test + public void getAllPatients() throws Exception { + + List expectedPatientList = new ArrayList<>(); + Patient patient = new Patient(); + expectedPatientList.add(patient); + + Mockito.when( + patientRepository.getAllPatients( + KEYWORD, PROJECTION, PAGE_SIZE, PAGE_NUMBER, SORT, DIRECTION)) + .thenReturn(expectedPatientList); + + List result = + patientService.getAllPatients(KEYWORD, PROJECTION, PAGE_SIZE, PAGE_NUMBER, SORT, DIRECTION); + + Assert.assertEquals(expectedPatientList, result); + } + + @Test + public void getMetaPatients() throws Exception { + + BaseMeta expectedBaseMeta = new BaseMeta(); + + Mockito.when(patientRepository.getMetaPatients(KEYWORD)).thenReturn(expectedBaseMeta); + + BaseMeta result = patientService.getMetaPatients(KEYWORD); + + Assert.assertEquals(expectedBaseMeta, result); + } + + @Test + public void getAllPatientsInStudy() throws Exception { + + List expectedPatientList = new ArrayList<>(); + Patient patient = new Patient(); + expectedPatientList.add(patient); + + Mockito.when( + patientRepository.getAllPatientsInStudy( + STUDY_ID, PROJECTION, PAGE_SIZE, PAGE_NUMBER, SORT, DIRECTION)) + .thenReturn(expectedPatientList); + + List result = + patientService.getAllPatientsInStudy( + STUDY_ID, PROJECTION, PAGE_SIZE, PAGE_NUMBER, SORT, DIRECTION); + + Assert.assertEquals(expectedPatientList, result); + } + + @Test(expected = StudyNotFoundException.class) + public void getAllPatientsInStudyNotFound() throws Exception { + + Mockito.when(studyService.getStudy(STUDY_ID)).thenThrow(new StudyNotFoundException(STUDY_ID)); + patientService.getAllPatientsInStudy( + STUDY_ID, PROJECTION, PAGE_SIZE, PAGE_NUMBER, SORT, DIRECTION); + } + + @Test + public void getMetaPatientsInStudy() throws Exception { + + BaseMeta expectedBaseMeta = new BaseMeta(); + Mockito.when(patientRepository.getMetaPatientsInStudy(STUDY_ID)).thenReturn(expectedBaseMeta); + BaseMeta result = patientService.getMetaPatientsInStudy(STUDY_ID); + + Assert.assertEquals(expectedBaseMeta, result); + } + + @Test(expected = StudyNotFoundException.class) + public void getMetaPatientsInStudyNotFound() throws Exception { + + Mockito.when(studyService.getStudy(STUDY_ID)).thenThrow(new StudyNotFoundException(STUDY_ID)); + patientService.getMetaPatientsInStudy(STUDY_ID); + } + + @Test(expected = PatientNotFoundException.class) + public void getPatientInStudyPatientNotFound() throws Exception { + + Mockito.when(patientRepository.getPatientInStudy(STUDY_ID, PATIENT_ID_1)).thenReturn(null); + patientService.getPatientInStudy(STUDY_ID, PATIENT_ID_1); + } + + @Test(expected = StudyNotFoundException.class) + public void getPatientInStudyNotFound() throws Exception { + + Mockito.when(studyService.getStudy(STUDY_ID)).thenThrow(new StudyNotFoundException(STUDY_ID)); + patientService.getPatientInStudy(STUDY_ID, PATIENT_ID_1); + } + + @Test + public void getPatientInStudy() throws Exception { + + Patient expectedPatient = new Patient(); + Mockito.when(patientRepository.getPatientInStudy(STUDY_ID, PATIENT_ID_1)) + .thenReturn(expectedPatient); + Patient result = patientService.getPatientInStudy(STUDY_ID, PATIENT_ID_1); + + Assert.assertEquals(expectedPatient, result); + } + + @Test + public void fetchPatients() throws Exception { + + List expectedPatientList = new ArrayList<>(); + Patient patient = new Patient(); + expectedPatientList.add(patient); + + Mockito.when( + patientRepository.fetchPatients( + Arrays.asList(STUDY_ID), Arrays.asList(PATIENT_ID_1), PROJECTION)) + .thenReturn(expectedPatientList); + + List result = + patientService.fetchPatients( + Arrays.asList(STUDY_ID), Arrays.asList(PATIENT_ID_1), PROJECTION); + + Assert.assertEquals(expectedPatientList, result); + } + + @Test + public void fetchMetaPatients() throws Exception { + + BaseMeta expectedBaseMeta = new BaseMeta(); + Mockito.when( + patientRepository.fetchMetaPatients( + Arrays.asList(STUDY_ID), Arrays.asList(PATIENT_ID_1))) + .thenReturn(expectedBaseMeta); + BaseMeta result = + patientService.fetchMetaPatients(Arrays.asList(STUDY_ID), Arrays.asList(PATIENT_ID_1)); + + Assert.assertEquals(expectedBaseMeta, result); + } + + @Test + public void getPatientsOfSamples() throws Exception { + + List patients = new ArrayList<>(); + Patient patient = new Patient(); + patient.setStableId(PATIENT_ID_1); + patient.setCancerStudyIdentifier(STUDY_ID); + patients.add(patient); + + Mockito.when( + patientRepository.getPatientsOfSamples( + Arrays.asList(STUDY_ID), Arrays.asList(SAMPLE_ID1))) + .thenReturn(patients); + + List result = + patientService.getPatientsOfSamples(Arrays.asList(STUDY_ID), Arrays.asList(SAMPLE_ID1)); + + Assert.assertEquals(1, result.size()); + Assert.assertEquals(PATIENT_ID_1, result.get(0).getStableId()); + } +} diff --git a/src/test/java/org/cbioportal/legacy/service/impl/ReadPermissionServiceImplTest.java b/src/test/java/org/cbioportal/legacy/service/impl/ReadPermissionServiceImplTest.java new file mode 100644 index 00000000000..d1ce401504b --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/service/impl/ReadPermissionServiceImplTest.java @@ -0,0 +1,68 @@ +package org.cbioportal.legacy.service.impl; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.util.ArrayList; +import java.util.List; +import org.cbioportal.application.security.CancerStudyPermissionEvaluator; +import org.cbioportal.legacy.model.CancerStudy; +import org.cbioportal.legacy.utils.security.AccessLevel; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnitRunner; +import org.springframework.security.core.Authentication; +import org.springframework.test.util.ReflectionTestUtils; + +@RunWith(MockitoJUnitRunner.class) +public class ReadPermissionServiceImplTest { + + @InjectMocks private ReadPermissionServiceImpl readPermissionService; + + @Mock private CancerStudyPermissionEvaluator cancerStudyPermissionEvaluator; + + Authentication authentication; + List cancerStudies; + + @Before + public void init() { + CancerStudy cancerStudy1 = new CancerStudy(); + CancerStudy cancerStudy2 = new CancerStudy(); + cancerStudies = new ArrayList<>(); + cancerStudies.add(cancerStudy1); + cancerStudies.add(cancerStudy2); + authentication = mock(Authentication.class); + when(cancerStudyPermissionEvaluator.hasPermission(any(), any(), eq(AccessLevel.READ))) + .thenReturn(false, true); + } + + @Test + public void setReadPermissionSuccess() { + readPermissionService.setReadPermission(cancerStudies, authentication); + Assert.assertFalse(cancerStudies.get(0).getReadPermission()); + Assert.assertTrue(cancerStudies.get(1).getReadPermission()); + } + + @Test + public void setReadPermissionUnAuthenticatedPortal() { + ReflectionTestUtils.setField(readPermissionService, "cancerStudyPermissionEvaluator", null); + readPermissionService.setReadPermission(cancerStudies, authentication); + Assert.assertTrue(cancerStudies.get(0).getReadPermission()); + Assert.assertTrue(cancerStudies.get(1).getReadPermission()); + ReflectionTestUtils.setField( + readPermissionService, "cancerStudyPermissionEvaluator", cancerStudyPermissionEvaluator); + } + + @Test + public void setReadPermissionNoAuthObject() { + readPermissionService.setReadPermission(cancerStudies, null); + Assert.assertTrue(cancerStudies.get(0).getReadPermission()); + Assert.assertTrue(cancerStudies.get(1).getReadPermission()); + } +} diff --git a/src/test/java/org/cbioportal/legacy/service/impl/ReferenceGenomeGeneServiceImplTest.java b/src/test/java/org/cbioportal/legacy/service/impl/ReferenceGenomeGeneServiceImplTest.java new file mode 100644 index 00000000000..fc2b71a1fb3 --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/service/impl/ReferenceGenomeGeneServiceImplTest.java @@ -0,0 +1,110 @@ +package org.cbioportal.legacy.service.impl; + +import java.util.ArrayList; +import java.util.List; +import org.cbioportal.legacy.model.Gene; +import org.cbioportal.legacy.model.ReferenceGenome; +import org.cbioportal.legacy.model.ReferenceGenomeGene; +import org.cbioportal.legacy.persistence.ReferenceGenomeGeneRepository; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.junit.MockitoJUnitRunner; + +@RunWith(MockitoJUnitRunner.class) +public class ReferenceGenomeGeneServiceImplTest extends BaseServiceImplTest { + + @InjectMocks private ReferenceGenomeGeneServiceImpl geneService; + + @Mock private ReferenceGenomeGeneRepository geneRepository; + + @Test + public void getAllGenesByGenomeName() throws Exception { + + List expectedGeneList = new ArrayList<>(); + ReferenceGenomeGene gene = new ReferenceGenomeGene(); + gene.setEntrezGeneId(ENTREZ_GENE_ID_2); + gene.setReferenceGenomeId(REFERENCE_GENOME_ID); + expectedGeneList.add(gene); + + Mockito.when( + geneRepository.getAllGenesByGenomeName( + ReferenceGenome.HOMO_SAPIENS_DEFAULT_GENOME_NAME)) + .thenReturn(expectedGeneList); + + List result = + geneService.fetchAllReferenceGenomeGenes(ReferenceGenome.HOMO_SAPIENS_DEFAULT_GENOME_NAME); + + Assert.assertEquals(expectedGeneList, result); + } + + @Test + public void getGenesByGenomeName() throws Exception { + + List expectedGeneList = new ArrayList<>(); + ReferenceGenomeGene gene1 = new ReferenceGenomeGene(); + gene1.setEntrezGeneId(ENTREZ_GENE_ID_1); + gene1.setReferenceGenomeId(REFERENCE_GENOME_ID); + expectedGeneList.add(gene1); + ReferenceGenomeGene gene2 = new ReferenceGenomeGene(); + gene2.setEntrezGeneId(ENTREZ_GENE_ID_2); + gene2.setReferenceGenomeId(REFERENCE_GENOME_ID); + expectedGeneList.add(gene2); + List geneIds = new ArrayList<>(); + geneIds.add(ENTREZ_GENE_ID_1); + geneIds.add(ENTREZ_GENE_ID_2); + Mockito.when( + geneRepository.getGenesByGenomeName( + geneIds, ReferenceGenome.HOMO_SAPIENS_DEFAULT_GENOME_NAME)) + .thenReturn(expectedGeneList); + + List result = + geneService.fetchGenesByGenomeName( + geneIds, ReferenceGenome.HOMO_SAPIENS_DEFAULT_GENOME_NAME); + + Assert.assertEquals(expectedGeneList, result); + } + + @Test + public void getReferenceGenomeGene() throws Exception { + + Gene gene = new Gene(); + gene.setEntrezGeneId(ENTREZ_GENE_ID_1); + gene.setHugoGeneSymbol("HUGO2"); + gene.setGeneticEntityId(GENETIC_ENTITY_ID_1); + ReferenceGenomeGene expectedGene = new ReferenceGenomeGene(); + expectedGene.setEntrezGeneId(ENTREZ_GENE_ID_1); + expectedGene.setReferenceGenomeId(REFERENCE_GENOME_ID); + Mockito.when( + geneRepository.getReferenceGenomeGene( + gene.getEntrezGeneId(), ReferenceGenome.HOMO_SAPIENS_DEFAULT_GENOME_NAME)) + .thenReturn(expectedGene); + + ReferenceGenomeGene result = + geneService.getReferenceGenomeGene( + gene.getEntrezGeneId(), ReferenceGenome.HOMO_SAPIENS_DEFAULT_GENOME_NAME); + + Assert.assertEquals(expectedGene, result); + } + + @Test + public void getReferenceGenomeGeneByEntityId() throws Exception { + + ReferenceGenomeGene expectedGene = new ReferenceGenomeGene(); + expectedGene.setEntrezGeneId(ENTREZ_GENE_ID_1); + expectedGene.setReferenceGenomeId(REFERENCE_GENOME_ID); + Mockito.when( + geneRepository.getReferenceGenomeGeneByEntityId( + GENETIC_ENTITY_ID_1, ReferenceGenome.HOMO_SAPIENS_DEFAULT_GENOME_NAME)) + .thenReturn(expectedGene); + + ReferenceGenomeGene result = + geneService.getReferenceGenomeGeneByEntityId( + GENETIC_ENTITY_ID_1, ReferenceGenome.HOMO_SAPIENS_DEFAULT_GENOME_NAME); + + Assert.assertEquals(expectedGene, result); + } +} diff --git a/src/test/java/org/cbioportal/legacy/service/impl/SampleListServiceImplTest.java b/src/test/java/org/cbioportal/legacy/service/impl/SampleListServiceImplTest.java new file mode 100644 index 00000000000..195999d397c --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/service/impl/SampleListServiceImplTest.java @@ -0,0 +1,225 @@ +package org.cbioportal.legacy.service.impl; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import org.cbioportal.legacy.model.SampleList; +import org.cbioportal.legacy.model.SampleListToSampleId; +import org.cbioportal.legacy.model.meta.BaseMeta; +import org.cbioportal.legacy.persistence.SampleListRepository; +import org.cbioportal.legacy.service.StudyService; +import org.cbioportal.legacy.service.exception.SampleListNotFoundException; +import org.cbioportal.legacy.service.exception.StudyNotFoundException; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.junit.MockitoJUnitRunner; +import org.springframework.test.util.ReflectionTestUtils; + +@RunWith(MockitoJUnitRunner.class) +public class SampleListServiceImplTest extends BaseServiceImplTest { + + @InjectMocks private SampleListServiceImpl sampleListService; + + @Mock private SampleListRepository sampleListRepository; + @Mock private StudyService studyService; + + @Before + public void setup() { + ReflectionTestUtils.setField(sampleListService, "AUTHENTICATE", "false"); + } + + @Test + public void getAllSampleLists() throws Exception { + + List expectedSampleLists = new ArrayList<>(); + SampleList sampleList = new SampleList(); + sampleList.setListId(1); + expectedSampleLists.add(sampleList); + + List expectedSampleListSampleIds = new ArrayList<>(); + SampleListToSampleId sampleListSampleId = new SampleListToSampleId(); + sampleListSampleId.setSampleListId(1); + sampleListSampleId.setSampleId(SAMPLE_ID1); + expectedSampleListSampleIds.add(sampleListSampleId); + + Mockito.when(sampleListRepository.getSampleListSampleIds(Arrays.asList(1))) + .thenReturn(expectedSampleListSampleIds); + + Mockito.when( + sampleListRepository.getAllSampleLists( + "DETAILED", PAGE_SIZE, PAGE_NUMBER, SORT, DIRECTION)) + .thenReturn(expectedSampleLists); + + List result = + sampleListService.getAllSampleLists("DETAILED", PAGE_SIZE, PAGE_NUMBER, SORT, DIRECTION); + + Assert.assertEquals(expectedSampleLists, result); + Assert.assertEquals((Integer) 1, expectedSampleLists.get(0).getSampleCount()); + } + + @Test + public void getMetaSampleLists() throws Exception { + + BaseMeta expectedBaseMeta = new BaseMeta(); + + Mockito.when(sampleListRepository.getMetaSampleLists()).thenReturn(expectedBaseMeta); + + BaseMeta result = sampleListService.getMetaSampleLists(); + + Assert.assertEquals(expectedBaseMeta, result); + } + + @Test(expected = SampleListNotFoundException.class) + public void getSampleListNotFound() throws Exception { + + Mockito.when(sampleListRepository.getSampleList(SAMPLE_LIST_ID)).thenReturn(null); + + sampleListService.getSampleList(SAMPLE_LIST_ID); + } + + @Test + public void getSampleList() throws Exception { + + SampleList expectedSampleList = new SampleList(); + expectedSampleList.setListId(1); + + Mockito.when(sampleListRepository.getSampleList(SAMPLE_LIST_ID)).thenReturn(expectedSampleList); + + List expectedSampleListSampleIds = new ArrayList<>(); + SampleListToSampleId sampleListSampleId = new SampleListToSampleId(); + sampleListSampleId.setSampleListId(1); + sampleListSampleId.setSampleId(SAMPLE_ID1); + expectedSampleListSampleIds.add(sampleListSampleId); + + Mockito.when(sampleListRepository.getSampleListSampleIds(Arrays.asList(1))) + .thenReturn(expectedSampleListSampleIds); + + SampleList result = sampleListService.getSampleList(SAMPLE_LIST_ID); + + Assert.assertEquals(expectedSampleList, result); + Assert.assertEquals((Integer) 1, result.getSampleCount()); + } + + @Test + public void getAllSampleListsInStudy() throws Exception { + + List expectedSampleLists = new ArrayList<>(); + SampleList sampleList = new SampleList(); + sampleList.setListId(1); + expectedSampleLists.add(sampleList); + + List expectedSampleListSampleIds = new ArrayList<>(); + SampleListToSampleId sampleListSampleId = new SampleListToSampleId(); + sampleListSampleId.setSampleListId(1); + sampleListSampleId.setSampleId(SAMPLE_ID1); + expectedSampleListSampleIds.add(sampleListSampleId); + + Mockito.when(sampleListRepository.getSampleListSampleIds(Arrays.asList(1))) + .thenReturn(expectedSampleListSampleIds); + + Mockito.when( + sampleListRepository.getAllSampleListsInStudies( + Arrays.asList(STUDY_ID), "DETAILED", PAGE_SIZE, PAGE_NUMBER, SORT, DIRECTION)) + .thenReturn(expectedSampleLists); + + List result = + sampleListService.getAllSampleListsInStudy( + STUDY_ID, "DETAILED", PAGE_SIZE, PAGE_NUMBER, SORT, DIRECTION); + + Assert.assertEquals(expectedSampleLists, result); + Assert.assertEquals((Integer) 1, expectedSampleLists.get(0).getSampleCount()); + } + + @Test(expected = StudyNotFoundException.class) + public void getAllSampleListsInStudyNotFound() throws Exception { + + Mockito.when(studyService.getStudy(STUDY_ID)).thenThrow(new StudyNotFoundException(STUDY_ID)); + sampleListService.getAllSampleListsInStudy( + STUDY_ID, "DETAILED", PAGE_SIZE, PAGE_NUMBER, SORT, DIRECTION); + } + + @Test + public void getMetaSampleListsInStudy() throws Exception { + + BaseMeta expectedBaseMeta = new BaseMeta(); + + Mockito.when(sampleListRepository.getMetaSampleListsInStudy(STUDY_ID)) + .thenReturn(expectedBaseMeta); + + BaseMeta result = sampleListService.getMetaSampleListsInStudy(STUDY_ID); + + Assert.assertEquals(expectedBaseMeta, result); + } + + @Test(expected = StudyNotFoundException.class) + public void getMetaSampleListsInStudyNotFound() throws Exception { + + Mockito.when(studyService.getStudy(STUDY_ID)).thenThrow(new StudyNotFoundException(STUDY_ID)); + sampleListService.getMetaSampleListsInStudy(STUDY_ID); + } + + @Test + public void getAllSampleIdsInSampleList() throws Exception { + + SampleList expectedSampleList = new SampleList(); + expectedSampleList.setListId(1); + + Mockito.when(sampleListRepository.getSampleList(SAMPLE_LIST_ID)).thenReturn(expectedSampleList); + + List expectedSampleListSampleIds = new ArrayList<>(); + SampleListToSampleId sampleListSampleId = new SampleListToSampleId(); + sampleListSampleId.setSampleListId(1); + sampleListSampleId.setSampleId(SAMPLE_ID1); + expectedSampleListSampleIds.add(sampleListSampleId); + + Mockito.when(sampleListRepository.getSampleListSampleIds(Arrays.asList(1))) + .thenReturn(expectedSampleListSampleIds); + + List expectedSampleIds = new ArrayList<>(); + expectedSampleIds.add(SAMPLE_ID1); + Mockito.when(sampleListRepository.getAllSampleIdsInSampleList(SAMPLE_LIST_ID)) + .thenReturn(expectedSampleIds); + List result = sampleListService.getAllSampleIdsInSampleList(SAMPLE_LIST_ID); + + Assert.assertEquals(expectedSampleIds, result); + } + + @Test(expected = SampleListNotFoundException.class) + public void getAllSampleIdsInSampleListNotFound() throws Exception { + + Mockito.when(sampleListRepository.getSampleList(SAMPLE_LIST_ID)).thenReturn(null); + sampleListService.getAllSampleIdsInSampleList(SAMPLE_LIST_ID); + } + + @Test + public void fetchSampleLists() throws Exception { + + List expectedSampleLists = new ArrayList<>(); + SampleList sampleList = new SampleList(); + sampleList.setListId(1); + expectedSampleLists.add(sampleList); + + List expectedSampleListSampleIds = new ArrayList<>(); + SampleListToSampleId sampleListSampleId = new SampleListToSampleId(); + sampleListSampleId.setSampleListId(1); + sampleListSampleId.setSampleId(SAMPLE_ID1); + expectedSampleListSampleIds.add(sampleListSampleId); + + Mockito.when(sampleListRepository.getSampleListSampleIds(Arrays.asList(1))) + .thenReturn(expectedSampleListSampleIds); + + Mockito.when(sampleListRepository.getSampleLists(Arrays.asList(SAMPLE_LIST_ID), "DETAILED")) + .thenReturn(expectedSampleLists); + + List result = + sampleListService.fetchSampleLists(Arrays.asList(SAMPLE_LIST_ID), "DETAILED"); + + Assert.assertEquals(expectedSampleLists, result); + Assert.assertEquals((Integer) 1, expectedSampleLists.get(0).getSampleCount()); + } +} diff --git a/src/test/java/org/cbioportal/legacy/service/impl/SampleServiceImplTest.java b/src/test/java/org/cbioportal/legacy/service/impl/SampleServiceImplTest.java new file mode 100644 index 00000000000..eff54c50cec --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/service/impl/SampleServiceImplTest.java @@ -0,0 +1,364 @@ +package org.cbioportal.legacy.service.impl; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; +import org.cbioportal.legacy.model.MolecularProfile; +import org.cbioportal.legacy.model.Sample; +import org.cbioportal.legacy.model.meta.BaseMeta; +import org.cbioportal.legacy.persistence.CopyNumberSegmentRepository; +import org.cbioportal.legacy.persistence.MolecularProfileRepository; +import org.cbioportal.legacy.persistence.SampleListRepository; +import org.cbioportal.legacy.persistence.SampleRepository; +import org.cbioportal.legacy.service.PatientService; +import org.cbioportal.legacy.service.StudyService; +import org.cbioportal.legacy.service.exception.PatientNotFoundException; +import org.cbioportal.legacy.service.exception.SampleNotFoundException; +import org.cbioportal.legacy.service.exception.StudyNotFoundException; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.junit.MockitoJUnitRunner; + +@RunWith(MockitoJUnitRunner.Silent.class) +public class SampleServiceImplTest extends BaseServiceImplTest { + + @InjectMocks private SampleServiceImpl sampleService; + + @Mock private SampleRepository sampleRepository; + @Mock private StudyService studyService; + @Mock private PatientService patientService; + @Mock private SampleListRepository sampleListRepository; + @Mock private CopyNumberSegmentRepository copyNumberSegmentRepository; + @Mock private MolecularProfileRepository molecularProfileRepository; + + private Sample createSample(String id) { + Sample sample = new Sample(); + sample.setStableId(id); + return sample; + } + + @Test + public void getAllSamples() { + List samples = + Arrays.asList( + createSample(SAMPLE_ID1), createSample(SAMPLE_ID2), + createSample(SAMPLE_ID3), createSample(SAMPLE_ID4)); + Mockito.when( + sampleRepository.getAllSamples( + "sample_id", null, PROJECTION, PAGE_SIZE, PAGE_NUMBER, SORT, DIRECTION)) + .thenReturn(samples); + + List result = + sampleService.getAllSamples( + "sample_id", null, PROJECTION, PAGE_SIZE, PAGE_NUMBER, SORT, DIRECTION); + List actual = result.stream().map(Sample::getStableId).collect(Collectors.toList()); + List expected = Arrays.asList(SAMPLE_ID1, SAMPLE_ID2, SAMPLE_ID3, SAMPLE_ID4); + + Assert.assertEquals(expected, actual); + } + + @Test + public void getAllMetaSamples() { + BaseMeta baseMeta = new BaseMeta(); + baseMeta.setTotalCount(4); + Mockito.when(sampleRepository.getMetaSamples("sample_id", null)).thenReturn(baseMeta); + + BaseMeta result = sampleService.getMetaSamples("sample_id", null); + Integer actual = result.getTotalCount(); + Integer expected = 4; + + Assert.assertEquals(expected, actual); + } + + @Test + public void getAllSamplesInStudy() throws Exception { + + List expectedSampleList = new ArrayList<>(); + Sample sample = new Sample(); + expectedSampleList.add(sample); + + Mockito.when( + sampleRepository.getAllSamplesInStudy( + STUDY_ID, PROJECTION, PAGE_SIZE, PAGE_NUMBER, SORT, DIRECTION)) + .thenReturn(expectedSampleList); + Mockito.when(sampleListRepository.getAllSampleIdsInSampleList(Mockito.anyString())) + .thenReturn(new ArrayList<>()); + Mockito.when( + copyNumberSegmentRepository.fetchCopyNumberSegments( + Mockito.anyList(), Mockito.anyList(), Mockito.anyString(), Mockito.anyString())) + .thenReturn(new ArrayList<>()); + + List result = + sampleService.getAllSamplesInStudy( + STUDY_ID, PROJECTION, PAGE_SIZE, PAGE_NUMBER, SORT, DIRECTION); + + Assert.assertEquals(expectedSampleList, result); + } + + @Test(expected = StudyNotFoundException.class) + public void getAllSamplesInStudyNotFound() throws Exception { + + Mockito.when(studyService.getStudy(STUDY_ID)).thenThrow(new StudyNotFoundException(STUDY_ID)); + sampleService.getAllSamplesInStudy( + STUDY_ID, PROJECTION, PAGE_SIZE, PAGE_NUMBER, SORT, DIRECTION); + } + + @Test + public void getMetaSamplesInStudy() throws Exception { + + BaseMeta expectedBaseMeta = new BaseMeta(); + Mockito.when(sampleRepository.getMetaSamplesInStudy(STUDY_ID)).thenReturn(expectedBaseMeta); + BaseMeta result = sampleService.getMetaSamplesInStudy(STUDY_ID); + + Assert.assertEquals(expectedBaseMeta, result); + } + + @Test(expected = StudyNotFoundException.class) + public void getMetaSamplesInStudyNotFound() throws Exception { + + Mockito.when(studyService.getStudy(STUDY_ID)).thenThrow(new StudyNotFoundException(STUDY_ID)); + sampleService.getMetaSamplesInStudy(STUDY_ID); + } + + @Test(expected = SampleNotFoundException.class) + public void getSampleInStudySampleNotFound() throws Exception { + + Mockito.when(sampleRepository.getSampleInStudy(STUDY_ID, SAMPLE_ID1)).thenReturn(null); + sampleService.getSampleInStudy(STUDY_ID, SAMPLE_ID1); + } + + @Test(expected = StudyNotFoundException.class) + public void getSampleInStudyNotFound() throws Exception { + + Mockito.when(studyService.getStudy(STUDY_ID)).thenThrow(new StudyNotFoundException(STUDY_ID)); + sampleService.getSampleInStudy(STUDY_ID, SAMPLE_ID1); + } + + @Test + public void getSampleInStudy() throws Exception { + + Sample expectedSample = new Sample(); + Mockito.when(sampleRepository.getSampleInStudy(STUDY_ID, SAMPLE_ID1)) + .thenReturn(expectedSample); + Mockito.when(sampleListRepository.getAllSampleIdsInSampleList(Mockito.anyString())) + .thenReturn(new ArrayList<>()); + Mockito.when( + copyNumberSegmentRepository.fetchCopyNumberSegments( + Mockito.anyList(), Mockito.anyList(), Mockito.anyString(), Mockito.anyString())) + .thenReturn(new ArrayList<>()); + + Sample result = sampleService.getSampleInStudy(STUDY_ID, SAMPLE_ID1); + + Assert.assertEquals(expectedSample, result); + } + + @Test + public void getAllSamplesOfPatientInStudy() throws Exception { + + List expectedSampleList = new ArrayList<>(); + Sample sample = new Sample(); + expectedSampleList.add(sample); + + Mockito.when( + sampleRepository.getAllSamplesOfPatientInStudy( + STUDY_ID, PATIENT_ID_1, PROJECTION, PAGE_SIZE, PAGE_NUMBER, SORT, DIRECTION)) + .thenReturn(expectedSampleList); + Mockito.when(sampleListRepository.getAllSampleIdsInSampleList(Mockito.anyString())) + .thenReturn(new ArrayList<>()); + Mockito.when( + copyNumberSegmentRepository.fetchCopyNumberSegments( + Mockito.anyList(), Mockito.anyList(), Mockito.anyString(), Mockito.anyString())) + .thenReturn(new ArrayList<>()); + + List result = + sampleService.getAllSamplesOfPatientInStudy( + STUDY_ID, PATIENT_ID_1, PROJECTION, PAGE_SIZE, PAGE_NUMBER, SORT, DIRECTION); + + Assert.assertEquals(expectedSampleList, result); + } + + @Test(expected = PatientNotFoundException.class) + public void getAllSamplesOfPatientInStudyPatientNotFound() throws Exception { + + Mockito.when(patientService.getPatientInStudy(STUDY_ID, PATIENT_ID_1)) + .thenThrow(new PatientNotFoundException(STUDY_ID, PATIENT_ID_1)); + sampleService.getAllSamplesOfPatientInStudy( + STUDY_ID, PATIENT_ID_1, PROJECTION, PAGE_SIZE, PAGE_NUMBER, SORT, DIRECTION); + } + + @Test + public void getMetaSamplesOfPatientInStudy() throws Exception { + + BaseMeta expectedBaseMeta = new BaseMeta(); + Mockito.when(sampleRepository.getMetaSamplesOfPatientInStudy(STUDY_ID, PATIENT_ID_1)) + .thenReturn(expectedBaseMeta); + BaseMeta result = sampleService.getMetaSamplesOfPatientInStudy(STUDY_ID, PATIENT_ID_1); + + Assert.assertEquals(expectedBaseMeta, result); + } + + @Test(expected = PatientNotFoundException.class) + public void getMetaSamplesOfPatientInStudyPatientNotFound() throws Exception { + + Mockito.when(patientService.getPatientInStudy(STUDY_ID, PATIENT_ID_1)) + .thenThrow(new PatientNotFoundException(STUDY_ID, PATIENT_ID_1)); + sampleService.getMetaSamplesOfPatientInStudy(STUDY_ID, PATIENT_ID_1); + } + + @Test + public void getAllSamplesOfPatientsInStudy() throws Exception { + + List expectedSampleList = new ArrayList<>(); + Sample sample = new Sample(); + expectedSampleList.add(sample); + + Mockito.when( + sampleRepository.getAllSamplesOfPatientsInStudy( + STUDY_ID, Arrays.asList(PATIENT_ID_1), PROJECTION)) + .thenReturn(expectedSampleList); + Mockito.when(sampleListRepository.getAllSampleIdsInSampleList(Mockito.anyString())) + .thenReturn(new ArrayList<>()); + Mockito.when( + copyNumberSegmentRepository.fetchCopyNumberSegments( + Mockito.anyList(), Mockito.anyList(), Mockito.anyString(), Mockito.anyString())) + .thenReturn(new ArrayList<>()); + + List result = + sampleService.getAllSamplesOfPatientsInStudy( + STUDY_ID, Arrays.asList(PATIENT_ID_1), PROJECTION); + + Assert.assertEquals(expectedSampleList, result); + } + + @Test + public void fetchSamples() throws Exception { + + List expectedSampleList = new ArrayList<>(); + Sample sample = new Sample(); + expectedSampleList.add(sample); + + Mockito.when( + sampleRepository.fetchSamples( + Arrays.asList(STUDY_ID), Arrays.asList(SAMPLE_ID1), PROJECTION)) + .thenReturn(expectedSampleList); + Mockito.when(sampleListRepository.getAllSampleIdsInSampleList(Mockito.anyString())) + .thenReturn(new ArrayList<>()); + Mockito.when( + copyNumberSegmentRepository.fetchCopyNumberSegments( + Mockito.anyList(), Mockito.anyList(), Mockito.anyString(), Mockito.anyString())) + .thenReturn(new ArrayList<>()); + + List result = + sampleService.fetchSamples(Arrays.asList(STUDY_ID), Arrays.asList(SAMPLE_ID1), PROJECTION); + + Assert.assertEquals(expectedSampleList, result); + } + + @Test + public void fetchSamplesDetailed() throws Exception { + List expectedSampleList = new ArrayList<>(); + Sample sample1 = new Sample(); + Sample sample2 = new Sample(); + expectedSampleList.add(sample1); + expectedSampleList.add(sample2); + + sample1.setCancerStudyIdentifier(STUDY_ID); + sample1.setStableId(SAMPLE_ID1); + sample1.setInternalId(SAMPLE_INTERNAL_ID); + sample2.setCancerStudyIdentifier(STUDY_ID); + sample2.setStableId(SAMPLE_ID2); + sample2.setInternalId(SAMPLE_INTERNAL_ID2); + + List expectedInternalIdList = new ArrayList<>(); + expectedInternalIdList.add(SAMPLE_INTERNAL_ID); + + Mockito.when( + sampleRepository.fetchSamples( + Arrays.asList(STUDY_ID), Arrays.asList(SAMPLE_ID1), "DETAILED")) + .thenReturn(expectedSampleList); + Mockito.when(sampleListRepository.getAllSampleIdsInSampleList(Mockito.anyString())) + .thenReturn(new ArrayList<>()); + Mockito.when( + copyNumberSegmentRepository.fetchSamplesWithCopyNumberSegments( + Mockito.anyList(), Mockito.anyList(), Mockito.any())) + .thenReturn(expectedInternalIdList); + + List expectedMolecularProfileList = new ArrayList<>(); + MolecularProfile molecularProfile = new MolecularProfile(); + molecularProfile.setCancerStudyIdentifier(STUDY_ID); + molecularProfile.setMolecularAlterationType( + MolecularProfile.MolecularAlterationType.STRUCTURAL_VARIANT); + expectedMolecularProfileList.add(molecularProfile); + + Mockito.when( + molecularProfileRepository.getMolecularProfilesInStudies( + Arrays.asList(STUDY_ID), "DETAILED")) + .thenReturn(expectedMolecularProfileList); + + List result = + sampleService.fetchSamples(Arrays.asList(STUDY_ID), Arrays.asList(SAMPLE_ID1), "DETAILED"); + Assert.assertEquals(2, result.size()); + Assert.assertTrue(result.get(0).getCopyNumberSegmentPresent()); + Assert.assertFalse(result.get(1).getCopyNumberSegmentPresent()); + } + + @Test + public void fetchSamplesBySampleListIds() throws Exception { + + List expectedSampleList = new ArrayList<>(); + Sample sample = new Sample(); + expectedSampleList.add(sample); + + Mockito.when( + sampleRepository.fetchSamplesBySampleListIds(Arrays.asList(SAMPLE_LIST_ID), PROJECTION)) + .thenReturn(expectedSampleList); + + List result = sampleService.fetchSamples(Arrays.asList(SAMPLE_LIST_ID), PROJECTION); + + Assert.assertEquals(expectedSampleList, result); + } + + @Test + public void fetchMetaSamples() throws Exception { + + BaseMeta expectedBaseMeta = new BaseMeta(); + Mockito.when( + sampleRepository.fetchMetaSamples(Arrays.asList(STUDY_ID), Arrays.asList(SAMPLE_ID1))) + .thenReturn(expectedBaseMeta); + BaseMeta result = + sampleService.fetchMetaSamples(Arrays.asList(STUDY_ID), Arrays.asList(SAMPLE_ID1)); + + Assert.assertEquals(expectedBaseMeta, result); + } + + @Test + public void fetchMetaSamplesBySampleListIds() throws Exception { + + BaseMeta expectedBaseMeta = new BaseMeta(); + Mockito.when(sampleRepository.fetchMetaSamples(Arrays.asList(SAMPLE_LIST_ID))) + .thenReturn(expectedBaseMeta); + BaseMeta result = sampleService.fetchMetaSamples(Arrays.asList(SAMPLE_LIST_ID)); + + Assert.assertEquals(expectedBaseMeta, result); + } + + @Test + public void getSamplesByInternalIds() throws Exception { + + List expectedSampleList = new ArrayList<>(); + Sample sample = new Sample(); + expectedSampleList.add(sample); + + Mockito.when(sampleRepository.getSamplesByInternalIds(Arrays.asList(SAMPLE_INTERNAL_ID))) + .thenReturn(expectedSampleList); + + List result = sampleService.getSamplesByInternalIds(Arrays.asList(SAMPLE_INTERNAL_ID)); + + Assert.assertEquals(expectedSampleList, result); + } +} diff --git a/src/test/java/org/cbioportal/legacy/service/impl/ServerStatusServiceImplTest.java b/src/test/java/org/cbioportal/legacy/service/impl/ServerStatusServiceImplTest.java new file mode 100644 index 00000000000..432ae6f82f9 --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/service/impl/ServerStatusServiceImplTest.java @@ -0,0 +1,47 @@ +package org.cbioportal.legacy.service.impl; + +import java.util.ArrayList; +import java.util.List; +import org.cbioportal.legacy.model.TypeOfCancer; +import org.cbioportal.legacy.persistence.CancerTypeRepository; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.junit.MockitoJUnitRunner; + +@RunWith(MockitoJUnitRunner.class) +public class ServerStatusServiceImplTest extends BaseServiceImplTest { + + @InjectMocks private ServerStatusServiceImpl serverStatusService; + + @Mock private CancerTypeRepository cancerTypeRepository; + + @Test + public void getServerStatusSuccess() throws Exception { + + List cancerList = new ArrayList<>(); + TypeOfCancer typeOfCancer = new TypeOfCancer(); + cancerList.add(typeOfCancer); + + Mockito.when(cancerTypeRepository.getAllCancerTypes("SUMMARY", null, null, null, null)) + .thenReturn(cancerList); + + Assert.assertEquals( + ServerStatusServiceImpl.MESSAGE_RUNNING, serverStatusService.getServerStatus().status); + } + + @Test + public void getServerStatusFailure() throws Exception { + + List cancerList = new ArrayList<>(); + + Mockito.when(cancerTypeRepository.getAllCancerTypes("SUMMARY", null, null, null, null)) + .thenReturn(cancerList); + + Assert.assertEquals( + ServerStatusServiceImpl.MESSAGE_DOWN, serverStatusService.getServerStatus().status); + } +} diff --git a/src/test/java/org/cbioportal/legacy/service/impl/SignificantCopyNumberRegionServiceImplTest.java b/src/test/java/org/cbioportal/legacy/service/impl/SignificantCopyNumberRegionServiceImplTest.java new file mode 100644 index 00000000000..e917aa7c6b2 --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/service/impl/SignificantCopyNumberRegionServiceImplTest.java @@ -0,0 +1,87 @@ +package org.cbioportal.legacy.service.impl; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import org.cbioportal.legacy.model.Gistic; +import org.cbioportal.legacy.model.GisticToGene; +import org.cbioportal.legacy.model.meta.BaseMeta; +import org.cbioportal.legacy.persistence.SignificantCopyNumberRegionRepository; +import org.cbioportal.legacy.service.StudyService; +import org.cbioportal.legacy.service.exception.StudyNotFoundException; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.junit.MockitoJUnitRunner; + +@RunWith(MockitoJUnitRunner.class) +public class SignificantCopyNumberRegionServiceImplTest extends BaseServiceImplTest { + + @InjectMocks private SignificantCopyNumberRegionServiceImpl significantCopyNumberRegionService; + + @Mock private SignificantCopyNumberRegionRepository significantCopyNumberRegionRepository; + @Mock private StudyService studyService; + + @Test + public void getSignificantCopyNumberRegions() throws Exception { + + List expectedGisticList = new ArrayList<>(); + Gistic gistic = new Gistic(); + gistic.setGisticRoiId(GISTIC_ROI_ID); + expectedGisticList.add(gistic); + + Mockito.when( + significantCopyNumberRegionRepository.getSignificantCopyNumberRegions( + STUDY_ID, PROJECTION, PAGE_SIZE, PAGE_NUMBER, SORT, DIRECTION)) + .thenReturn(expectedGisticList); + + List expectedGisticToGeneList = new ArrayList<>(); + GisticToGene gisticToGene = new GisticToGene(); + gisticToGene.setGisticRoiId(GISTIC_ROI_ID); + expectedGisticToGeneList.add(gisticToGene); + + Mockito.when( + significantCopyNumberRegionRepository.getGenesOfRegions(Arrays.asList(GISTIC_ROI_ID))) + .thenReturn(expectedGisticToGeneList); + + List result = + significantCopyNumberRegionService.getSignificantCopyNumberRegions( + STUDY_ID, PROJECTION, PAGE_SIZE, PAGE_NUMBER, SORT, DIRECTION); + + Assert.assertEquals(1, result.size()); + Assert.assertEquals(gistic, result.get(0)); + Assert.assertEquals(1, result.get(0).getGenes().size()); + Assert.assertEquals(gisticToGene, result.get(0).getGenes().get(0)); + } + + @Test(expected = StudyNotFoundException.class) + public void getSignificantCopyNumberRegionsStudyNotFound() throws Exception { + + Mockito.when(studyService.getStudy(STUDY_ID)).thenThrow(new StudyNotFoundException(STUDY_ID)); + significantCopyNumberRegionService.getSignificantCopyNumberRegions( + STUDY_ID, PROJECTION, PAGE_SIZE, PAGE_NUMBER, SORT, DIRECTION); + } + + @Test + public void getMetaSignificantCopyNumberRegions() throws Exception { + + BaseMeta expectedBaseMeta = new BaseMeta(); + Mockito.when( + significantCopyNumberRegionRepository.getMetaSignificantCopyNumberRegions(STUDY_ID)) + .thenReturn(expectedBaseMeta); + BaseMeta result = + significantCopyNumberRegionService.getMetaSignificantCopyNumberRegions(STUDY_ID); + + Assert.assertEquals(expectedBaseMeta, result); + } + + @Test(expected = StudyNotFoundException.class) + public void getMetaSignificantCopyNumberRegionsStudyNotFound() throws Exception { + + Mockito.when(studyService.getStudy(STUDY_ID)).thenThrow(new StudyNotFoundException(STUDY_ID)); + significantCopyNumberRegionService.getMetaSignificantCopyNumberRegions(STUDY_ID); + } +} diff --git a/src/test/java/org/cbioportal/legacy/service/impl/SignificantlyMutatedGeneServiceImplTest.java b/src/test/java/org/cbioportal/legacy/service/impl/SignificantlyMutatedGeneServiceImplTest.java new file mode 100644 index 00000000000..f44782944c2 --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/service/impl/SignificantlyMutatedGeneServiceImplTest.java @@ -0,0 +1,70 @@ +package org.cbioportal.legacy.service.impl; + +import java.util.ArrayList; +import java.util.List; +import org.cbioportal.legacy.model.MutSig; +import org.cbioportal.legacy.model.meta.BaseMeta; +import org.cbioportal.legacy.persistence.SignificantlyMutatedGeneRepository; +import org.cbioportal.legacy.service.StudyService; +import org.cbioportal.legacy.service.exception.StudyNotFoundException; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.junit.MockitoJUnitRunner; + +@RunWith(MockitoJUnitRunner.class) +public class SignificantlyMutatedGeneServiceImplTest extends BaseServiceImplTest { + + @InjectMocks private SignificantlyMutatedGeneServiceImpl significantlyMutatedGeneService; + + @Mock private SignificantlyMutatedGeneRepository significantlyMutatedGeneRepository; + @Mock private StudyService studyService; + + @Test + public void getSignificantlyMutatedGenes() throws Exception { + + List expectedMutSigList = new ArrayList<>(); + MutSig mutSig = new MutSig(); + expectedMutSigList.add(mutSig); + + Mockito.when( + significantlyMutatedGeneRepository.getSignificantlyMutatedGenes( + STUDY_ID, PROJECTION, PAGE_SIZE, PAGE_NUMBER, SORT, DIRECTION)) + .thenReturn(expectedMutSigList); + + List result = + significantlyMutatedGeneService.getSignificantlyMutatedGenes( + STUDY_ID, PROJECTION, PAGE_SIZE, PAGE_NUMBER, SORT, DIRECTION); + + Assert.assertEquals(expectedMutSigList, result); + } + + @Test(expected = StudyNotFoundException.class) + public void getSignificantlyMutatedGenesStudyNotFound() throws Exception { + + Mockito.when(studyService.getStudy(STUDY_ID)).thenThrow(new StudyNotFoundException(STUDY_ID)); + significantlyMutatedGeneService.getSignificantlyMutatedGenes( + STUDY_ID, PROJECTION, PAGE_SIZE, PAGE_NUMBER, SORT, DIRECTION); + } + + @Test + public void getMetaSignificantlyMutatedGenes() throws Exception { + + BaseMeta expectedBaseMeta = new BaseMeta(); + Mockito.when(significantlyMutatedGeneRepository.getMetaSignificantlyMutatedGenes(STUDY_ID)) + .thenReturn(expectedBaseMeta); + BaseMeta result = significantlyMutatedGeneService.getMetaSignificantlyMutatedGenes(STUDY_ID); + + Assert.assertEquals(expectedBaseMeta, result); + } + + @Test(expected = StudyNotFoundException.class) + public void getMetaSignificantlyMutatedGenesStudyNotFound() throws Exception { + + Mockito.when(studyService.getStudy(STUDY_ID)).thenThrow(new StudyNotFoundException(STUDY_ID)); + significantlyMutatedGeneService.getMetaSignificantlyMutatedGenes(STUDY_ID); + } +} diff --git a/src/test/java/org/cbioportal/legacy/service/impl/StaticDataTimestampServiceImplTest.java b/src/test/java/org/cbioportal/legacy/service/impl/StaticDataTimestampServiceImplTest.java new file mode 100644 index 00000000000..7fd154ce643 --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/service/impl/StaticDataTimestampServiceImplTest.java @@ -0,0 +1,34 @@ +package org.cbioportal.legacy.service.impl; + +import java.util.Collections; +import java.util.HashMap; +import org.cbioportal.legacy.model.TableTimestampPair; +import org.cbioportal.legacy.persistence.StaticDataTimeStampRepository; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.junit.MockitoJUnitRunner; + +@RunWith(MockitoJUnitRunner.class) +public class StaticDataTimestampServiceImplTest extends BaseServiceImplTest { + @InjectMocks private StaticDataTimestampServiceImpl infoService; + + @Mock private StaticDataTimeStampRepository repository; + + @Test + public void TestGetTimestamps() { + HashMap pairs = new HashMap<>(); + pairs.put("gene", "2019-11-11 08:41:15"); + TableTimestampPair pair = new TableTimestampPair(); + pair.setTableName("gene"); + pair.setUpdateTime("2019-11-11 08:41:15"); + + Mockito.when(repository.getTimestamps(Mockito.anyList())) + .thenReturn(Collections.singletonList(pair)); + + Assert.assertEquals(infoService.getTimestamps(Collections.singletonList("gene")), pairs); + } +} diff --git a/src/test/java/org/cbioportal/legacy/service/impl/StructuralVariantServiceImplTest.java b/src/test/java/org/cbioportal/legacy/service/impl/StructuralVariantServiceImplTest.java new file mode 100644 index 00000000000..e5e0655f9cb --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/service/impl/StructuralVariantServiceImplTest.java @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2018 - 2022 The Hyve B.V. + * This code is licensed under the GNU Affero General Public License (AGPL), + * version 3, or (at your option) any later version. + */ + +/* + * This file is part of cBioPortal. + * + * cBioPortal is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package org.cbioportal.legacy.service.impl; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import org.cbioportal.legacy.model.GeneFilterQuery; +import org.cbioportal.legacy.model.StructuralVariant; +import org.cbioportal.legacy.model.StructuralVariantQuery; +import org.cbioportal.legacy.persistence.StructuralVariantRepository; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.junit.MockitoJUnitRunner; + +@RunWith(MockitoJUnitRunner.class) +public class StructuralVariantServiceImplTest extends BaseServiceImplTest { + + @InjectMocks private StructuralVariantServiceImpl structuralVariantService; + + @Mock private StructuralVariantRepository structuralVariantRepository; + + List expectedStructuralVariantList = + Collections.singletonList(new StructuralVariant()); + List molecularProfileIds = Collections.singletonList("study_structural_variants"); + List sampleIds = Collections.singletonList(SAMPLE_ID1); + + @Test + public void getStructuralVariants() { + + List entrezGeneIds = Collections.singletonList(ENTREZ_GENE_ID_1); + List noStructuralVariant = Collections.emptyList(); + + Mockito.when( + structuralVariantRepository.fetchStructuralVariants( + molecularProfileIds, sampleIds, entrezGeneIds, noStructuralVariant)) + .thenReturn(expectedStructuralVariantList); + + List result = + structuralVariantService.fetchStructuralVariants( + molecularProfileIds, sampleIds, entrezGeneIds, noStructuralVariant); + + Assert.assertEquals(expectedStructuralVariantList, result); + } + + @Test + public void getStructuralVariantsByGeneFilterQueries() { + + List geneFilterQueries = new ArrayList<>(); + + Mockito.when( + structuralVariantRepository.fetchStructuralVariantsByGeneQueries( + molecularProfileIds, sampleIds, geneFilterQueries)) + .thenReturn(expectedStructuralVariantList); + + List result = + structuralVariantService.fetchStructuralVariantsByGeneQueries( + molecularProfileIds, sampleIds, geneFilterQueries); + + Assert.assertEquals(expectedStructuralVariantList, result); + } +} diff --git a/src/test/java/org/cbioportal/legacy/service/impl/StudyServiceImplTest.java b/src/test/java/org/cbioportal/legacy/service/impl/StudyServiceImplTest.java new file mode 100644 index 00000000000..ecee2c5fc27 --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/service/impl/StudyServiceImplTest.java @@ -0,0 +1,110 @@ +package org.cbioportal.legacy.service.impl; + +import static org.mockito.Mockito.when; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import org.cbioportal.legacy.model.CancerStudy; +import org.cbioportal.legacy.model.meta.BaseMeta; +import org.cbioportal.legacy.persistence.StudyRepository; +import org.cbioportal.legacy.service.CancerTypeService; +import org.cbioportal.legacy.service.ReadPermissionService; +import org.cbioportal.legacy.service.exception.StudyNotFoundException; +import org.cbioportal.legacy.utils.security.AccessLevel; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnitRunner; + +@RunWith(MockitoJUnitRunner.class) +public class StudyServiceImplTest extends BaseServiceImplTest { + + @InjectMocks private StudyServiceImpl studyService; + + @Mock private ReadPermissionService readPermissionService; + + @Mock private StudyRepository studyRepository; + @Mock private CancerTypeService cancerTypeService; + + @Test + public void getAllStudies() throws Exception { + + List expectedCancerStudyList = new ArrayList<>(); + CancerStudy cancerStudy = new CancerStudy(); + cancerStudy.setReadPermission(false); + expectedCancerStudyList.add(cancerStudy); + + when(studyRepository.getAllStudies( + KEYWORD, PROJECTION, PAGE_SIZE, PAGE_NUMBER, SORT, DIRECTION)) + .thenReturn(expectedCancerStudyList); + when(cancerTypeService.getPrimarySiteMap()).thenReturn(new HashMap<>()); + + List result = + studyService.getAllStudies( + KEYWORD, PROJECTION, PAGE_SIZE, PAGE_NUMBER, SORT, DIRECTION, null, AccessLevel.READ); + + Assert.assertEquals(expectedCancerStudyList.get(0), result.get(0)); + } + + @Test + public void getMetaStudies() throws Exception { + + BaseMeta expectedBaseMeta = new BaseMeta(); + when(studyRepository.getMetaStudies(null)).thenReturn(expectedBaseMeta); + + BaseMeta result = studyService.getMetaStudies(null); + + Assert.assertEquals(expectedBaseMeta, result); + } + + @Test(expected = StudyNotFoundException.class) + public void getStudyNotFound() throws Exception { + + when(studyRepository.getStudy(STUDY_ID, "DETAILED")).thenReturn(null); + + studyService.getStudy(STUDY_ID); + } + + @Test + public void getStudy() throws Exception { + + CancerStudy expectedCancerStudy = new CancerStudy(); + + when(studyRepository.getStudy(STUDY_ID, "DETAILED")).thenReturn(expectedCancerStudy); + + CancerStudy result = studyService.getStudy(STUDY_ID); + + Assert.assertEquals(expectedCancerStudy, result); + } + + @Test + public void fetchStudies() throws Exception { + + List expectedCancerStudyList = new ArrayList<>(); + CancerStudy cancerStudy = new CancerStudy(); + expectedCancerStudyList.add(cancerStudy); + + when(studyRepository.fetchStudies(Arrays.asList(STUDY_ID), PROJECTION)) + .thenReturn(expectedCancerStudyList); + + List result = studyService.fetchStudies(Arrays.asList(STUDY_ID), PROJECTION); + + Assert.assertEquals(expectedCancerStudyList, result); + } + + @Test + public void fetchMetaStudies() throws Exception { + + BaseMeta expectedBaseMeta = new BaseMeta(); + + when(studyRepository.fetchMetaStudies(Arrays.asList(STUDY_ID))).thenReturn(expectedBaseMeta); + + BaseMeta result = studyService.fetchMetaStudies(Arrays.asList(STUDY_ID)); + + Assert.assertEquals(expectedBaseMeta, result); + } +} diff --git a/src/test/java/org/cbioportal/legacy/service/impl/StudyViewServiceImplTest.java b/src/test/java/org/cbioportal/legacy/service/impl/StudyViewServiceImplTest.java new file mode 100644 index 00000000000..b4589d44cc0 --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/service/impl/StudyViewServiceImplTest.java @@ -0,0 +1,699 @@ +package org.cbioportal.legacy.service.impl; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyBoolean; +import static org.mockito.ArgumentMatchers.anyList; +import static org.mockito.ArgumentMatchers.anyString; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import org.apache.commons.math3.util.Pair; +import org.cbioportal.legacy.model.AlterationCountByGene; +import org.cbioportal.legacy.model.AlterationFilter; +import org.cbioportal.legacy.model.CNA; +import org.cbioportal.legacy.model.CopyNumberCountByGene; +import org.cbioportal.legacy.model.Gene; +import org.cbioportal.legacy.model.GeneMolecularData; +import org.cbioportal.legacy.model.GenePanelData; +import org.cbioportal.legacy.model.GenericAssayData; +import org.cbioportal.legacy.model.GenericAssayDataCount; +import org.cbioportal.legacy.model.GenericAssayDataCountItem; +import org.cbioportal.legacy.model.GenomicDataCount; +import org.cbioportal.legacy.model.GenomicDataCountItem; +import org.cbioportal.legacy.model.MolecularProfile; +import org.cbioportal.legacy.model.MolecularProfileCaseIdentifier; +import org.cbioportal.legacy.model.MutationEventType; +import org.cbioportal.legacy.model.NamespaceAttribute; +import org.cbioportal.legacy.model.NamespaceDataCount; +import org.cbioportal.legacy.model.NamespaceDataCountItem; +import org.cbioportal.legacy.model.util.Select; +import org.cbioportal.legacy.service.AlterationCountService; +import org.cbioportal.legacy.service.GenePanelService; +import org.cbioportal.legacy.service.GeneService; +import org.cbioportal.legacy.service.GenericAssayService; +import org.cbioportal.legacy.service.MolecularDataService; +import org.cbioportal.legacy.service.MolecularProfileService; +import org.cbioportal.legacy.service.MutationService; +import org.cbioportal.legacy.service.NamespaceDataService; +import org.cbioportal.legacy.service.SignificantCopyNumberRegionService; +import org.cbioportal.legacy.service.SignificantlyMutatedGeneService; +import org.cbioportal.legacy.service.util.MolecularProfileUtil; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.Spy; +import org.mockito.junit.MockitoJUnitRunner; +import org.springframework.boot.test.mock.mockito.MockBean; + +@RunWith(MockitoJUnitRunner.class) +public class StudyViewServiceImplTest extends BaseServiceImplTest { + + @Spy @InjectMocks private StudyViewServiceImpl studyViewService; + @Mock private MolecularProfileService molecularProfileService; + @Mock private GenePanelService genePanelService; + @Spy @MockBean private MolecularProfileUtil molecularProfileUtil; + @Mock private AlterationCountService alterationCountService; + @Mock private SignificantlyMutatedGeneService significantlyMutatedGeneService; + @Mock private SignificantCopyNumberRegionService significantCopyNumberRegionService; + @Mock private GenericAssayService genericAssayService; + @Mock private MolecularDataService molecularDataService; + @Mock private GeneService geneService; + @Mock private MutationService mutationService; + @Mock private NamespaceDataService namespaceDataService; + private AlterationFilter alterationFilter = new AlterationFilter(); + + @Test + public void getGenomicDataCounts() throws Exception { + + List molecularProfiles = new ArrayList<>(); + MolecularProfile mutationMolecularProfile = new MolecularProfile(); + mutationMolecularProfile.setCancerStudyIdentifier(BaseServiceImplTest.STUDY_ID); + mutationMolecularProfile.setStableId(BaseServiceImplTest.STUDY_ID + "_mutations"); + mutationMolecularProfile.setName("Mutations"); + mutationMolecularProfile.setMolecularAlterationType( + MolecularProfile.MolecularAlterationType.MUTATION_EXTENDED); + mutationMolecularProfile.setDatatype("MAF"); + mutationMolecularProfile.setPatientLevel(false); + molecularProfiles.add(mutationMolecularProfile); + + MolecularProfile discreteCNAMolecularProfile = new MolecularProfile(); + discreteCNAMolecularProfile.setCancerStudyIdentifier(BaseServiceImplTest.STUDY_ID); + discreteCNAMolecularProfile.setStableId(BaseServiceImplTest.STUDY_ID + "_gistic"); + discreteCNAMolecularProfile.setName("Discrete CNA"); + discreteCNAMolecularProfile.setMolecularAlterationType( + MolecularProfile.MolecularAlterationType.COPY_NUMBER_ALTERATION); + discreteCNAMolecularProfile.setDatatype("DISCRETE"); + discreteCNAMolecularProfile.setPatientLevel(false); + molecularProfiles.add(discreteCNAMolecularProfile); + + MolecularProfile patientLevelMolecularProfile = new MolecularProfile(); + patientLevelMolecularProfile.setCancerStudyIdentifier(BaseServiceImplTest.STUDY_ID); + patientLevelMolecularProfile.setStableId(BaseServiceImplTest.STUDY_ID + "_patient"); + patientLevelMolecularProfile.setName("Patient Profile"); + patientLevelMolecularProfile.setMolecularAlterationType( + MolecularProfile.MolecularAlterationType.GENERIC_ASSAY); + patientLevelMolecularProfile.setDatatype("LIMIT-VALUE"); + patientLevelMolecularProfile.setPatientLevel(true); + molecularProfiles.add(patientLevelMolecularProfile); + + List studyIds = + Arrays.asList(BaseServiceImplTest.STUDY_ID, BaseServiceImplTest.STUDY_ID); + List sampleIds = + Arrays.asList(BaseServiceImplTest.SAMPLE_ID1, BaseServiceImplTest.SAMPLE_ID2); + + List molecularProfileSampleIdentifiers = new ArrayList<>(); + molecularProfileSampleIdentifiers.add( + new MolecularProfileCaseIdentifier( + BaseServiceImplTest.SAMPLE_ID1, BaseServiceImplTest.STUDY_ID + "_mutations")); + molecularProfileSampleIdentifiers.add( + new MolecularProfileCaseIdentifier( + BaseServiceImplTest.SAMPLE_ID2, BaseServiceImplTest.STUDY_ID + "_mutations")); + molecularProfileSampleIdentifiers.add( + new MolecularProfileCaseIdentifier( + BaseServiceImplTest.SAMPLE_ID1, BaseServiceImplTest.STUDY_ID + "_gistic")); + molecularProfileSampleIdentifiers.add( + new MolecularProfileCaseIdentifier( + BaseServiceImplTest.SAMPLE_ID2, BaseServiceImplTest.STUDY_ID + "_gistic")); + molecularProfileSampleIdentifiers.add( + new MolecularProfileCaseIdentifier( + BaseServiceImplTest.SAMPLE_ID1, BaseServiceImplTest.STUDY_ID + "_patient")); + molecularProfileSampleIdentifiers.add( + new MolecularProfileCaseIdentifier( + BaseServiceImplTest.SAMPLE_ID2, BaseServiceImplTest.STUDY_ID + "_patient")); + + List genePanelDataList = new ArrayList<>(); + GenePanelData panelData1 = new GenePanelData(); + panelData1.setMolecularProfileId(BaseServiceImplTest.STUDY_ID + "_mutations"); + panelData1.setSampleId(BaseServiceImplTest.SAMPLE_ID1); + panelData1.setProfiled(true); + genePanelDataList.add(panelData1); + GenePanelData panelData2 = new GenePanelData(); + panelData2.setMolecularProfileId(BaseServiceImplTest.STUDY_ID + "_mutations"); + panelData2.setSampleId(BaseServiceImplTest.SAMPLE_ID2); + panelData2.setProfiled(true); + genePanelDataList.add(panelData2); + GenePanelData panelData3 = new GenePanelData(); + panelData3.setMolecularProfileId(BaseServiceImplTest.STUDY_ID + "_gistic"); + panelData3.setSampleId(BaseServiceImplTest.SAMPLE_ID1); + panelData3.setProfiled(true); + genePanelDataList.add(panelData3); + GenePanelData panelData4 = new GenePanelData(); + panelData4.setMolecularProfileId(BaseServiceImplTest.STUDY_ID + "_gistic"); + panelData4.setSampleId(BaseServiceImplTest.SAMPLE_ID2); + panelData4.setProfiled(true); + genePanelDataList.add(panelData4); + GenePanelData panelData5 = new GenePanelData(); + panelData5.setMolecularProfileId(BaseServiceImplTest.STUDY_ID + "_patient"); + panelData5.setSampleId(BaseServiceImplTest.SAMPLE_ID1); + panelData5.setPatientId(BaseServiceImplTest.PATIENT_ID_1); + panelData5.setProfiled(true); + genePanelDataList.add(panelData5); + GenePanelData panelData6 = new GenePanelData(); + panelData6.setMolecularProfileId(BaseServiceImplTest.STUDY_ID + "_patient"); + panelData6.setSampleId(BaseServiceImplTest.SAMPLE_ID2); + panelData6.setPatientId(BaseServiceImplTest.PATIENT_ID_1); + panelData6.setProfiled(true); + genePanelDataList.add(panelData6); + + Mockito.when(molecularProfileService.getMolecularProfilesInStudies(anyList(), anyString())) + .thenReturn(molecularProfiles); + + Mockito.when(molecularProfileService.getMolecularProfileCaseIdentifiers(studyIds, sampleIds)) + .thenReturn(molecularProfileSampleIdentifiers); + Mockito.when( + genePanelService.fetchGenePanelDataInMultipleMolecularProfiles( + molecularProfileSampleIdentifiers)) + .thenReturn(genePanelDataList); + + List expectedGenomicDataCounts = new ArrayList<>(); + GenomicDataCount expectedGenomicDataCount1 = new GenomicDataCount(); + expectedGenomicDataCount1.setCount(2); + expectedGenomicDataCount1.setValue("mutations"); + expectedGenomicDataCount1.setLabel("Mutations"); + expectedGenomicDataCounts.add(expectedGenomicDataCount1); + GenomicDataCount expectedGenomicDataCount2 = new GenomicDataCount(); + expectedGenomicDataCount2.setCount(1); + expectedGenomicDataCount2.setValue("patient"); + expectedGenomicDataCount2.setLabel("Patient Profile"); + expectedGenomicDataCounts.add(expectedGenomicDataCount2); + GenomicDataCount expectedGenomicDataCount3 = new GenomicDataCount(); + expectedGenomicDataCount3.setCount(2); + expectedGenomicDataCount3.setValue("gistic"); + expectedGenomicDataCount3.setLabel("Discrete CNA"); + expectedGenomicDataCounts.add(expectedGenomicDataCount3); + + List result = studyViewService.getGenomicDataCounts(studyIds, sampleIds); + + Assert.assertEquals(expectedGenomicDataCounts, result); + } + + @Test + public void getMutationAlterationCountByGenes() throws Exception { + + List studyIds = + Arrays.asList(BaseServiceImplTest.STUDY_ID, BaseServiceImplTest.STUDY_ID); + List sampleIds = + Arrays.asList(BaseServiceImplTest.SAMPLE_ID1, BaseServiceImplTest.SAMPLE_ID2); + + MolecularProfile molecularProfile = new MolecularProfile(); + molecularProfile.setCancerStudyIdentifier(BaseServiceImplTest.STUDY_ID); + List molecularProfileCaseIdentifiers = new ArrayList<>(); + MolecularProfileCaseIdentifier profileCaseIdentifier1 = + new MolecularProfileCaseIdentifier( + BaseServiceImplTest.SAMPLE_ID1, BaseServiceImplTest.MOLECULAR_PROFILE_ID); + molecularProfileCaseIdentifiers.add(profileCaseIdentifier1); + MolecularProfileCaseIdentifier profileCaseIdentifier2 = + new MolecularProfileCaseIdentifier( + BaseServiceImplTest.SAMPLE_ID2, BaseServiceImplTest.MOLECULAR_PROFILE_ID); + molecularProfileCaseIdentifiers.add(profileCaseIdentifier2); + Mockito.when( + molecularProfileService.getFirstMutationProfileCaseIdentifiers(studyIds, sampleIds)) + .thenReturn(molecularProfileCaseIdentifiers); + + List alterationCountByGenes = new ArrayList<>(); + AlterationCountByGene alterationCountByGene1 = new AlterationCountByGene(); + alterationCountByGene1.setEntrezGeneId(BaseServiceImplTest.ENTREZ_GENE_ID_1); + alterationCountByGene1.setHugoGeneSymbol(BaseServiceImplTest.HUGO_GENE_SYMBOL_1); + alterationCountByGene1.setTotalCount(2); + alterationCountByGene1.setNumberOfProfiledCases(2); + alterationCountByGenes.add(alterationCountByGene1); + Mockito.when( + alterationCountService.getSampleMutationGeneCounts( + molecularProfileCaseIdentifiers, Select.all(), true, false, alterationFilter)) + .thenReturn(new Pair<>(alterationCountByGenes, 2L)); + List result = + studyViewService.getMutationAlterationCountByGenes(studyIds, sampleIds, alterationFilter); + Assert.assertEquals(1, result.size()); + } + + @Test + public void getMutationCountsByGeneSpecific() { + List studyIds = + Arrays.asList(BaseServiceImplTest.STUDY_ID, BaseServiceImplTest.STUDY_ID); + List sampleIds = + Arrays.asList(BaseServiceImplTest.SAMPLE_ID1, BaseServiceImplTest.SAMPLE_ID2); + + MolecularProfile molecularProfile = new MolecularProfile(); + molecularProfile.setCancerStudyIdentifier(BaseServiceImplTest.STUDY_ID); + List molecularProfileCaseIdentifiers = new ArrayList<>(); + MolecularProfileCaseIdentifier profileCaseIdentifier1 = + new MolecularProfileCaseIdentifier( + BaseServiceImplTest.SAMPLE_ID1, BaseServiceImplTest.MOLECULAR_PROFILE_ID); + molecularProfileCaseIdentifiers.add(profileCaseIdentifier1); + MolecularProfileCaseIdentifier profileCaseIdentifier2 = + new MolecularProfileCaseIdentifier( + BaseServiceImplTest.SAMPLE_ID2, BaseServiceImplTest.MOLECULAR_PROFILE_ID); + molecularProfileCaseIdentifiers.add(profileCaseIdentifier2); + Mockito.when(molecularProfileService.getMutationProfileCaseIdentifiers(studyIds, sampleIds)) + .thenReturn(molecularProfileCaseIdentifiers); + + List hugoGeneSymbols = new ArrayList<>(); + hugoGeneSymbols.add(BaseServiceImplTest.HUGO_GENE_SYMBOL_1); + List genes = new ArrayList<>(); + Gene gene = new Gene(); + gene.setEntrezGeneId(BaseServiceImplTest.ENTREZ_GENE_ID_1); + gene.setHugoGeneSymbol(BaseServiceImplTest.HUGO_GENE_SYMBOL_1); + gene.setGeneticEntityId(BaseServiceImplTest.GENETIC_ENTITY_ID_1); + genes.add(gene); + Mockito.when(geneService.fetchGenes(hugoGeneSymbols, "HUGO_GENE_SYMBOL", "SUMMARY")) + .thenReturn(genes); + + List entrezGeneIds = new ArrayList<>(); + entrezGeneIds.add(ENTREZ_GENE_ID_1); + List alterationCountByGenes = new ArrayList<>(); + AlterationCountByGene alterationCountByGene1 = new AlterationCountByGene(); + alterationCountByGene1.setEntrezGeneId(BaseServiceImplTest.ENTREZ_GENE_ID_1); + alterationCountByGene1.setHugoGeneSymbol(BaseServiceImplTest.HUGO_GENE_SYMBOL_1); + alterationCountByGene1.setNumberOfAlteredCases(2); + alterationCountByGene1.setTotalCount(2); + alterationCountByGene1.setNumberOfProfiledCases(2); + alterationCountByGenes.add(alterationCountByGene1); + + Mockito.when( + alterationCountService.getSampleMutationGeneCounts( + anyList(), any(), anyBoolean(), anyBoolean(), any())) + .thenReturn(new Pair<>(alterationCountByGenes, 2L)); + + List> genomicDataFilters = new ArrayList<>(); + Pair genomicDataFilter = + new Pair<>(BaseServiceImplTest.HUGO_GENE_SYMBOL_1, BaseServiceImplTest.PROFILE_TYPE_1); + genomicDataFilters.add(genomicDataFilter); + + List result = + studyViewService.getMutationCountsByGeneSpecific( + studyIds, sampleIds, genomicDataFilters, alterationFilter); + Assert.assertEquals(1, result.size()); + Assert.assertEquals(1, result.get(0).getCounts().size()); + } + + @Test + public void getMutationTypeCountsByGeneSpecific() { + List studyIds = + Arrays.asList(BaseServiceImplTest.STUDY_ID, BaseServiceImplTest.STUDY_ID); + List sampleIds = + Arrays.asList(BaseServiceImplTest.SAMPLE_ID1, BaseServiceImplTest.SAMPLE_ID2); + + List hugoGeneSymbols = new ArrayList<>(); + hugoGeneSymbols.add(BaseServiceImplTest.HUGO_GENE_SYMBOL_1); + List genes = new ArrayList<>(); + Gene gene = new Gene(); + gene.setEntrezGeneId(BaseServiceImplTest.ENTREZ_GENE_ID_1); + gene.setHugoGeneSymbol(BaseServiceImplTest.HUGO_GENE_SYMBOL_1); + gene.setGeneticEntityId(BaseServiceImplTest.GENETIC_ENTITY_ID_1); + genes.add(gene); + Mockito.when(geneService.fetchGenes(hugoGeneSymbols, "HUGO_GENE_SYMBOL", "SUMMARY")) + .thenReturn(genes); + + List molecularProfiles = new ArrayList<>(); + MolecularProfile molecularProfile = new MolecularProfile(); + molecularProfile.setCancerStudyIdentifier(BaseServiceImplTest.STUDY_ID); + molecularProfile.setStableId(BaseServiceImplTest.STABLE_ID_1); + molecularProfiles.add(molecularProfile); + Mockito.when(molecularProfileService.getMolecularProfilesInStudies(studyIds, "SUMMARY")) + .thenReturn(molecularProfiles); + + Map> molecularProfileMap = new HashMap<>(); + molecularProfileMap.put(BaseServiceImplTest.PROFILE_TYPE_1, molecularProfiles); + Mockito.when( + molecularProfileUtil.categorizeMolecularProfilesByStableIdSuffixes(molecularProfiles)) + .thenReturn(molecularProfileMap); + + GenomicDataCountItem genomicDataCountItem = new GenomicDataCountItem(); + genomicDataCountItem.setHugoGeneSymbol(BaseServiceImplTest.HUGO_GENE_SYMBOL_1); + genomicDataCountItem.setProfileType(BaseServiceImplTest.PROFILE_TYPE_1); + List genomicDataCounts = new ArrayList<>(); + GenomicDataCount genomicDataCount1 = new GenomicDataCount(); + genomicDataCount1.setLabel(MutationEventType.missense_mutation.getMutationType()); + genomicDataCount1.setValue(MutationEventType.missense_mutation.getMutationType()); + genomicDataCount1.setCount(2); + genomicDataCounts.add(genomicDataCount1); + GenomicDataCount genomicDataCount2 = new GenomicDataCount(); + genomicDataCount2.setLabel(MutationEventType.splice_site_indel.getMutationType()); + genomicDataCount2.setValue(MutationEventType.splice_site_indel.getMutationType()); + genomicDataCount2.setCount(2); + genomicDataCounts.add(genomicDataCount2); + genomicDataCountItem.setCounts(genomicDataCounts); + + Mockito.when( + mutationService.getMutationCountsByType(anyList(), anyList(), anyList(), anyString())) + .thenReturn(genomicDataCountItem); + + List> genomicDataFilters = new ArrayList<>(); + Pair genomicDataFilter = + new Pair<>(BaseServiceImplTest.HUGO_GENE_SYMBOL_1, BaseServiceImplTest.PROFILE_TYPE_1); + genomicDataFilters.add(genomicDataFilter); + + List result = + studyViewService.getMutationTypeCountsByGeneSpecific( + studyIds, sampleIds, genomicDataFilters); + Assert.assertEquals(1, result.size()); + Assert.assertEquals(BaseServiceImplTest.HUGO_GENE_SYMBOL_1, result.get(0).getHugoGeneSymbol()); + Assert.assertEquals(BaseServiceImplTest.PROFILE_TYPE_1, result.get(0).getProfileType()); + Assert.assertEquals(2, result.get(0).getCounts().get(0).getCount().intValue()); + Assert.assertEquals(2, result.get(0).getCounts().get(1).getCount().intValue()); + } + + @Test + public void getStructuralVariantAlterationCountByGenes() throws Exception { + + List studyIds = + Arrays.asList(BaseServiceImplTest.STUDY_ID, BaseServiceImplTest.STUDY_ID); + List sampleIds = + Arrays.asList(BaseServiceImplTest.SAMPLE_ID1, BaseServiceImplTest.SAMPLE_ID2); + + MolecularProfile molecularProfile = new MolecularProfile(); + molecularProfile.setCancerStudyIdentifier(BaseServiceImplTest.STUDY_ID); + List molecularProfileCaseIdentifiers = new ArrayList<>(); + MolecularProfileCaseIdentifier profileCaseIdentifier1 = + new MolecularProfileCaseIdentifier( + BaseServiceImplTest.SAMPLE_ID1, BaseServiceImplTest.MOLECULAR_PROFILE_ID); + molecularProfileCaseIdentifiers.add(profileCaseIdentifier1); + MolecularProfileCaseIdentifier profileCaseIdentifier2 = + new MolecularProfileCaseIdentifier( + BaseServiceImplTest.SAMPLE_ID2, BaseServiceImplTest.MOLECULAR_PROFILE_ID); + molecularProfileCaseIdentifiers.add(profileCaseIdentifier2); + Mockito.when( + molecularProfileService.getFirstStructuralVariantProfileCaseIdentifiers( + studyIds, sampleIds)) + .thenReturn(molecularProfileCaseIdentifiers); + + List alterationCountByGenes = new ArrayList<>(); + AlterationCountByGene alterationCountByGene1 = new AlterationCountByGene(); + alterationCountByGene1.setEntrezGeneId(BaseServiceImplTest.ENTREZ_GENE_ID_1); + alterationCountByGene1.setHugoGeneSymbol(BaseServiceImplTest.HUGO_GENE_SYMBOL_1); + alterationCountByGene1.setTotalCount(2); + alterationCountByGene1.setNumberOfProfiledCases(2); + alterationCountByGenes.add(alterationCountByGene1); + Mockito.when( + alterationCountService.getSampleStructuralVariantGeneCounts( + molecularProfileCaseIdentifiers, Select.all(), true, false, alterationFilter)) + .thenReturn(new Pair<>(alterationCountByGenes, 2L)); + List result = + studyViewService.getStructuralVariantAlterationCountByGenes( + studyIds, sampleIds, alterationFilter); + Assert.assertEquals(1, result.size()); + } + + @Test + public void getCNAAlterationCountByGenes() throws Exception { + + List studyIds = + Arrays.asList(BaseServiceImplTest.STUDY_ID, BaseServiceImplTest.STUDY_ID); + List sampleIds = + Arrays.asList(BaseServiceImplTest.SAMPLE_ID1, BaseServiceImplTest.SAMPLE_ID2); + List CNA_TYPES_AMP_AND_HOMDEL = + Collections.unmodifiableList(Arrays.asList(CNA.AMP, CNA.HOMDEL)); + + MolecularProfile molecularProfile = new MolecularProfile(); + molecularProfile.setCancerStudyIdentifier(BaseServiceImplTest.STUDY_ID); + List molecularProfileCaseIdentifiers = new ArrayList<>(); + MolecularProfileCaseIdentifier profileCaseIdentifier1 = + new MolecularProfileCaseIdentifier( + BaseServiceImplTest.SAMPLE_ID1, BaseServiceImplTest.MOLECULAR_PROFILE_ID); + molecularProfileCaseIdentifiers.add(profileCaseIdentifier1); + MolecularProfileCaseIdentifier profileCaseIdentifier2 = + new MolecularProfileCaseIdentifier( + BaseServiceImplTest.SAMPLE_ID2, BaseServiceImplTest.MOLECULAR_PROFILE_ID); + molecularProfileCaseIdentifiers.add(profileCaseIdentifier2); + Mockito.when( + molecularProfileService.getFirstDiscreteCNAProfileCaseIdentifiers(studyIds, sampleIds)) + .thenReturn(molecularProfileCaseIdentifiers); + + List alterationCountByGenes = new ArrayList<>(); + CopyNumberCountByGene alterationCountByGene1 = new CopyNumberCountByGene(); + alterationCountByGene1.setEntrezGeneId(BaseServiceImplTest.ENTREZ_GENE_ID_1); + alterationCountByGene1.setHugoGeneSymbol(BaseServiceImplTest.HUGO_GENE_SYMBOL_1); + alterationCountByGene1.setTotalCount(2); + alterationCountByGene1.setNumberOfProfiledCases(2); + alterationCountByGene1.setAlteration(2); + alterationCountByGenes.add(alterationCountByGene1); + + Mockito.when( + alterationCountService.getSampleCnaGeneCounts( + anyList(), + any(Select.class), + anyBoolean(), + anyBoolean(), + any(AlterationFilter.class))) + .thenReturn(new Pair<>(alterationCountByGenes, 2L)); + List result = + studyViewService.getCNAAlterationCountByGenes(studyIds, sampleIds, alterationFilter); + Assert.assertEquals(1, result.size()); + } + + @Test + public void getCNAAlterationCountByGeneSpecific() throws Exception { + + List sampleIds = + Arrays.asList( + BaseServiceImplTest.SAMPLE_ID1, + BaseServiceImplTest.SAMPLE_ID2, + BaseServiceImplTest.SAMPLE_ID3); + List studyIds = Collections.nCopies(3, BaseServiceImplTest.STUDY_ID); + List> genomicDataFilters = new ArrayList<>(); + Pair genomicDataFilter1 = + new Pair<>(BaseServiceImplTest.HUGO_GENE_SYMBOL_1, BaseServiceImplTest.PROFILE_TYPE_1); + Pair genomicDataFilter2 = + new Pair<>(BaseServiceImplTest.HUGO_GENE_SYMBOL_2, BaseServiceImplTest.PROFILE_TYPE_2); + genomicDataFilters.add(genomicDataFilter1); + genomicDataFilters.add(genomicDataFilter2); + + List molecularProfiles = new ArrayList<>(); + MolecularProfile molecularProfile = new MolecularProfile(); + molecularProfile.setCancerStudyIdentifier(BaseServiceImplTest.STUDY_ID); + molecularProfile.setStableId( + BaseServiceImplTest.STUDY_ID + "_" + BaseServiceImplTest.MOLECULAR_PROFILE_ID_A); + molecularProfiles.add(molecularProfile); + + Mockito.when(molecularProfileService.getMolecularProfilesInStudies(studyIds, "SUMMARY")) + .thenReturn(molecularProfiles); + + Map> molecularProfileMap = new HashMap<>(); + molecularProfileMap.put(BaseServiceImplTest.PROFILE_TYPE_1, molecularProfiles); + molecularProfileMap.put(BaseServiceImplTest.PROFILE_TYPE_2, molecularProfiles); + + Mockito.when( + molecularProfileUtil.categorizeMolecularProfilesByStableIdSuffixes(molecularProfiles)) + .thenReturn(molecularProfileMap); + + List genes = new ArrayList<>(); + Gene gene1 = new Gene(); + gene1.setEntrezGeneId(BaseServiceImplTest.ENTREZ_GENE_ID_1); + gene1.setHugoGeneSymbol(BaseServiceImplTest.HUGO_GENE_SYMBOL_1); + Gene gene2 = new Gene(); + gene2.setEntrezGeneId(BaseServiceImplTest.ENTREZ_GENE_ID_2); + gene2.setHugoGeneSymbol(BaseServiceImplTest.HUGO_GENE_SYMBOL_2); + genes.add(gene1); + genes.add(gene2); + + Mockito.when(geneService.fetchGenes(anyList(), anyString(), anyString())).thenReturn(genes); + + List geneMolecularData = new ArrayList<>(); + GeneMolecularData geneMolecularData1 = new GeneMolecularData(); + geneMolecularData1.setValue("-2"); + GeneMolecularData geneMolecularData2 = new GeneMolecularData(); + geneMolecularData2.setValue("-2"); + GeneMolecularData geneMolecularData3 = new GeneMolecularData(); + geneMolecularData3.setValue("2"); + GeneMolecularData geneMolecularData4 = new GeneMolecularData(); + geneMolecularData4.setValue("2"); + geneMolecularData.add(geneMolecularData1); + geneMolecularData.add(geneMolecularData2); + geneMolecularData.add(geneMolecularData3); + geneMolecularData.add(geneMolecularData4); + + Mockito.when( + molecularDataService.getMolecularDataInMultipleMolecularProfiles( + anyList(), anyList(), anyList(), anyString())) + .thenReturn(geneMolecularData); + + List result = + studyViewService.getCNAAlterationCountsByGeneSpecific( + studyIds, sampleIds, genomicDataFilters); + Assert.assertEquals(2, result.size()); + Assert.assertEquals(BaseServiceImplTest.HUGO_GENE_SYMBOL_1, result.get(0).getHugoGeneSymbol()); + Assert.assertEquals(BaseServiceImplTest.PROFILE_TYPE_1, result.get(0).getProfileType()); + Assert.assertEquals(2, result.get(0).getCounts().get(0).getCount().intValue()); + Assert.assertEquals(2, result.get(0).getCounts().get(1).getCount().intValue()); + Assert.assertEquals(BaseServiceImplTest.HUGO_GENE_SYMBOL_2, result.get(1).getHugoGeneSymbol()); + Assert.assertEquals(BaseServiceImplTest.PROFILE_TYPE_2, result.get(1).getProfileType()); + Assert.assertEquals(2, result.get(1).getCounts().get(0).getCount().intValue()); + Assert.assertEquals(2, result.get(1).getCounts().get(1).getCount().intValue()); + } + + @Test + public void fetchGenericAssayDataCounts() throws Exception { + + List stableIds = + Arrays.asList(BaseServiceImplTest.STABLE_ID_1, BaseServiceImplTest.STABLE_ID_2); + List molecularProfileIds = + Collections.nCopies( + 3, BaseServiceImplTest.STUDY_ID + "_" + BaseServiceImplTest.MOLECULAR_PROFILE_ID_A); + List sampleIds = + Arrays.asList( + BaseServiceImplTest.SAMPLE_ID1, + BaseServiceImplTest.SAMPLE_ID2, + BaseServiceImplTest.SAMPLE_ID3); + List studyIds = Collections.nCopies(3, BaseServiceImplTest.STUDY_ID); + List profileTypes = Arrays.asList(BaseServiceImplTest.MOLECULAR_PROFILE_ID_A); + + List gaDataList = new ArrayList<>(); + GenericAssayData gaData1 = new GenericAssayData(); + gaData1.setGenericAssayStableId(BaseServiceImplTest.STABLE_ID_1); + gaData1.setSampleId(BaseServiceImplTest.SAMPLE_ID1); + gaData1.setValue(BaseServiceImplTest.CATEGORY_VALUE_1); + gaDataList.add(gaData1); + + GenericAssayData gaData2 = new GenericAssayData(); + gaData2.setGenericAssayStableId(BaseServiceImplTest.STABLE_ID_1); + gaData2.setSampleId(BaseServiceImplTest.SAMPLE_ID2); + gaData2.setValue(BaseServiceImplTest.CATEGORY_VALUE_1); + gaDataList.add(gaData2); + + GenericAssayData gaData3 = new GenericAssayData(); + gaData3.setGenericAssayStableId(BaseServiceImplTest.STABLE_ID_1); + gaData3.setSampleId(BaseServiceImplTest.SAMPLE_ID3); + gaData3.setValue(BaseServiceImplTest.CATEGORY_VALUE_2); + gaDataList.add(gaData3); + + GenericAssayData gaData4 = new GenericAssayData(); + gaData4.setGenericAssayStableId(BaseServiceImplTest.STABLE_ID_2); + gaData4.setSampleId(BaseServiceImplTest.SAMPLE_ID1); + gaData4.setValue(BaseServiceImplTest.CATEGORY_VALUE_1); + gaDataList.add(gaData4); + + GenericAssayData gaData5 = new GenericAssayData(); + gaData5.setGenericAssayStableId(BaseServiceImplTest.STABLE_ID_2); + gaData5.setSampleId(BaseServiceImplTest.SAMPLE_ID2); + gaData5.setValue(BaseServiceImplTest.EMPTY_VALUE_1); + gaDataList.add(gaData5); + + GenericAssayData gaData6 = new GenericAssayData(); + gaData6.setGenericAssayStableId(BaseServiceImplTest.STABLE_ID_2); + gaData6.setSampleId(BaseServiceImplTest.SAMPLE_ID3); + gaData6.setValue(BaseServiceImplTest.EMPTY_VALUE_2); + gaDataList.add(gaData6); + + Mockito.when( + genericAssayService.fetchGenericAssayData( + molecularProfileIds, sampleIds, stableIds, "SUMMARY")) + .thenReturn(gaDataList); + + List molecularProfiles = new ArrayList<>(); + MolecularProfile molecularProfile = new MolecularProfile(); + molecularProfile.setCancerStudyIdentifier(BaseServiceImplTest.STUDY_ID); + molecularProfile.setStableId( + BaseServiceImplTest.STUDY_ID + "_" + BaseServiceImplTest.MOLECULAR_PROFILE_ID_A); + molecularProfiles.add(molecularProfile); + + Mockito.when(molecularProfileService.getMolecularProfilesInStudies(studyIds, "SUMMARY")) + .thenReturn(molecularProfiles); + + List expectedCountItems = new ArrayList<>(); + GenericAssayDataCountItem countItem1 = new GenericAssayDataCountItem(); + countItem1.setStableId(BaseServiceImplTest.STABLE_ID_1); + GenericAssayDataCount count1 = new GenericAssayDataCount(); + count1.setValue(BaseServiceImplTest.CATEGORY_VALUE_1); + count1.setCount(2); + GenericAssayDataCount count2 = new GenericAssayDataCount(); + count2.setValue(BaseServiceImplTest.CATEGORY_VALUE_2); + count2.setCount(1); + countItem1.setCounts(Arrays.asList(count1, count2)); + expectedCountItems.add(countItem1); + + GenericAssayDataCountItem countItem2 = new GenericAssayDataCountItem(); + countItem2.setStableId(BaseServiceImplTest.STABLE_ID_2); + GenericAssayDataCount count3 = new GenericAssayDataCount(); + count3.setValue(BaseServiceImplTest.CATEGORY_VALUE_1); + count3.setCount(1); + GenericAssayDataCount count4 = new GenericAssayDataCount(); + count4.setValue("NA"); + count4.setCount(2); + countItem2.setCounts(Arrays.asList(count3, count4)); + expectedCountItems.add(countItem2); + + List result = + studyViewService.fetchGenericAssayDataCounts(sampleIds, studyIds, stableIds, profileTypes); + + Assert.assertEquals(2, result.size()); + + GenericAssayDataCountItem item1 = result.get(0); + Assert.assertEquals(BaseServiceImplTest.STABLE_ID_1, item1.getStableId()); + GenericAssayDataCount countInItem1 = item1.getCounts().get(0); + Assert.assertEquals(BaseServiceImplTest.CATEGORY_VALUE_1, countInItem1.getValue()); + Assert.assertEquals((Integer) 2, countInItem1.getCount()); + GenericAssayDataCount countInItem2 = item1.getCounts().get(1); + Assert.assertEquals(BaseServiceImplTest.CATEGORY_VALUE_2, countInItem2.getValue()); + Assert.assertEquals((Integer) 1, countInItem2.getCount()); + + GenericAssayDataCountItem item2 = result.get(1); + Assert.assertEquals(BaseServiceImplTest.STABLE_ID_2, item2.getStableId()); + GenericAssayDataCount countInItem3 = item2.getCounts().get(0); + Assert.assertEquals(BaseServiceImplTest.CATEGORY_VALUE_1, countInItem3.getValue()); + Assert.assertEquals((Integer) 1, countInItem3.getCount()); + GenericAssayDataCount countInItem4 = item2.getCounts().get(1); + Assert.assertEquals(BaseServiceImplTest.EMPTY_VALUE_2, countInItem4.getValue()); + Assert.assertEquals((Integer) 2, countInItem4.getCount()); + } + + @Test + public void fetchNamespaceDataCounts() { + + NamespaceAttribute namespaceAttribute1 = + new NamespaceAttribute( + BaseServiceImplTest.NAMESPACE_OUTER_KEY_1, BaseServiceImplTest.NAMESPACE_INNER_KEY_1); + NamespaceAttribute namespaceAttribute2 = + new NamespaceAttribute( + BaseServiceImplTest.NAMESPACE_OUTER_KEY_2, BaseServiceImplTest.NAMESPACE_INNER_KEY_2); + + List namespaceAttributes = + Arrays.asList(namespaceAttribute1, namespaceAttribute2); + List sampleIds = + Arrays.asList( + BaseServiceImplTest.SAMPLE_ID1, + BaseServiceImplTest.SAMPLE_ID2, + BaseServiceImplTest.SAMPLE_ID3); + List studyIds = Collections.nCopies(3, BaseServiceImplTest.STUDY_ID); + + List expectedCountItems = new ArrayList<>(); + NamespaceDataCountItem countItem1 = new NamespaceDataCountItem(); + countItem1.setOuterKey(BaseServiceImplTest.NAMESPACE_OUTER_KEY_1); + countItem1.setInnerKey(BaseServiceImplTest.NAMESPACE_INNER_KEY_1); + NamespaceDataCount count1 = new NamespaceDataCount(); + count1.setValue(BaseServiceImplTest.CATEGORY_VALUE_1); + count1.setCount(2); + NamespaceDataCount count2 = new NamespaceDataCount(); + count2.setValue(BaseServiceImplTest.CATEGORY_VALUE_2); + count2.setCount(1); + countItem1.setCounts(Arrays.asList(count1, count2)); + expectedCountItems.add(countItem1); + + NamespaceDataCountItem countItem2 = new NamespaceDataCountItem(); + countItem2.setOuterKey(BaseServiceImplTest.NAMESPACE_OUTER_KEY_2); + countItem2.setInnerKey(BaseServiceImplTest.NAMESPACE_INNER_KEY_2); + NamespaceDataCount count3 = new NamespaceDataCount(); + count2.setValue(BaseServiceImplTest.CATEGORY_VALUE_1); + count2.setCount(1); + NamespaceDataCount count4 = new NamespaceDataCount(); + count2.setValue(BaseServiceImplTest.CATEGORY_VALUE_2); + count2.setCount(2); + countItem1.setCounts(Arrays.asList(count3, count4)); + expectedCountItems.add(countItem2); + + Mockito.when( + namespaceDataService.fetchNamespaceDataCounts(sampleIds, studyIds, namespaceAttributes)) + .thenReturn(expectedCountItems); + + List result = + studyViewService.fetchNamespaceDataCounts(sampleIds, studyIds, namespaceAttributes); + + Assert.assertEquals(expectedCountItems, result); + } +} diff --git a/src/test/java/org/cbioportal/legacy/service/impl/TreatmentServiceImplTest.java b/src/test/java/org/cbioportal/legacy/service/impl/TreatmentServiceImplTest.java new file mode 100644 index 00000000000..bc300e20b89 --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/service/impl/TreatmentServiceImplTest.java @@ -0,0 +1,383 @@ +package org.cbioportal.legacy.service.impl; + +import java.util.*; +import java.util.stream.Collectors; +import org.cbioportal.legacy.model.ClinicalEventKeyCode; +import org.cbioportal.legacy.model.ClinicalEventSample; +import org.cbioportal.legacy.model.PatientTreatmentRow; +import org.cbioportal.legacy.model.SampleTreatmentRow; +import org.cbioportal.legacy.model.TemporalRelation; +import org.cbioportal.legacy.model.Treatment; +import org.cbioportal.legacy.persistence.TreatmentRepository; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.junit.MockitoJUnitRunner; + +@RunWith(MockitoJUnitRunner.class) +public class TreatmentServiceImplTest { + + private static final String STUDY_ID = "cancer_study"; + + @InjectMocks private TreatmentServiceImpl treatmentService; + + @Mock private TreatmentRepository treatmentRepository; + + @Test + public void getAllPatientTreatmentRows() { + mockSamplesByPatient(makeSample("S0", "P0", 5)); + mockTreatments(makeTreatment("madeupanib", "P0", 0, 10)); + + PatientTreatmentRow rowA = + makePatientRow( + "madeupanib", 1, Collections.singletonList("S0"), Collections.singletonList("P0")); + List expected = Collections.singletonList(rowA); + List actual = + treatmentService.getAllPatientTreatmentRows(null, null, ClinicalEventKeyCode.Agent); + + Assert.assertEquals(new HashSet<>(expected), new HashSet<>(actual)); + } + + @Test + public void getAllPatientTreatmentRowsOneSampleTwoTreatmentsOnePatient() { + mockTreatments( + makeTreatment("madeupanib", "P0", 0, 10), makeTreatment("fakedrugazol", "P0", 0, 10)); + mockSamplesByPatient(makeSample("S0", "P0", 5)); + + PatientTreatmentRow rowA = + makePatientRow( + "fakedrugazol", 1, Collections.singletonList("S0"), Collections.singletonList("P0")); + PatientTreatmentRow rowB = + makePatientRow( + "madeupanib", 1, Collections.singletonList("S0"), Collections.singletonList("P0")); + List expected = Arrays.asList(rowA, rowB); + List actual = + treatmentService.getAllPatientTreatmentRows(null, null, ClinicalEventKeyCode.Agent); + + Assert.assertEquals(new HashSet<>(expected), new HashSet<>(actual)); + } + + @Test + public void getAllPatientTreatmentRowsTwoSamplesOnePatientOneTreatment() { + mockTreatments(makeTreatment("fakedrugazol", "P0", 0, 10)); + mockSamplesByPatient(makeSample("S0", "P0", 5), makeSample("S1", "P0", 10)); + + // even though there are two samples, you expect a count of 1, + // because this is from the patient level, and both samples are for the same patient + PatientTreatmentRow rowA = + makePatientRow("fakedrugazol", 1, Arrays.asList("S0", "S1"), Arrays.asList("P0", "P0")); + List expected = Collections.singletonList(rowA); + List actual = + treatmentService.getAllPatientTreatmentRows(null, null, ClinicalEventKeyCode.Agent); + + Assert.assertEquals(new HashSet<>(expected), new HashSet<>(actual)); + } + + @Test + public void getAllPatientTreatmentRowsTwoSamplesTwoPatientsTwoTreatments() { + mockTreatments( + makeTreatment("fakedrugazol", "P0", 0, 10), makeTreatment("fakedrugazol", "P1", 0, 10)); + mockSamplesByPatient(makeSample("S0", "P0", 5), makeSample("S1", "P1", 10)); + + // now there are two patients, so you expect a count of two + PatientTreatmentRow rowA = + makePatientRow("fakedrugazol", 2, Arrays.asList("S0", "S1"), Arrays.asList("P0", "P1")); + List expected = Collections.singletonList(rowA); + List actual = + treatmentService.getAllPatientTreatmentRows(null, null, ClinicalEventKeyCode.Agent); + + Assert.assertEquals(new HashSet<>(expected), new HashSet<>(actual)); + } + + @Test + public void getAllPatientTreatmentRowsTwoSamplesTwoPatientsTwoDifferentTreatments() { + mockTreatments( + makeTreatment("fakedrugazol", "P0", 0, 10), makeTreatment("madeupanib", "P1", 0, 10)); + mockSamplesByPatient(makeSample("S0", "P0", 5), makeSample("S1", "P1", 10)); + + PatientTreatmentRow rowA = + makePatientRow( + "fakedrugazol", 1, Collections.singletonList("S0"), Collections.singletonList("P0")); + PatientTreatmentRow rowB = + makePatientRow( + "madeupanib", 1, Collections.singletonList("S1"), Collections.singletonList("P1")); + List expected = Arrays.asList(rowA, rowB); + List actual = + treatmentService.getAllPatientTreatmentRows(null, null, ClinicalEventKeyCode.Agent); + + Assert.assertEquals(new HashSet<>(expected), new HashSet<>(actual)); + } + + @Test + public void getAllSampleTreatmentRowsOneSampleBef0reOneTreatment() { + mockTreatmentsByPatient(makeTreatment("fabricatin", "P0", 10, 20)); + mockSamplesByPatient(makeSample("S0", "P0", 5)); + + SampleTreatmentRow rowA = + makeSampleRow( + TemporalRelation.Pre, + "fabricatin", + 1, + Collections.singletonList("S0"), + Collections.singletonList("P0")); + List expected = Collections.singletonList(rowA); + List actual = + treatmentService.getAllSampleTreatmentRows(null, null, ClinicalEventKeyCode.Agent); + + Assert.assertEquals(new HashSet<>(expected), new HashSet<>(actual)); + } + + @Test + public void getAllSampleTreatmentRowsOneSampleAfterOneTreatment() { + mockTreatmentsByPatient(makeTreatment("fabricatin", "P0", 10, 20)); + mockSamplesByPatient(makeSample("S0", "P0", 25)); + + SampleTreatmentRow rowA = + makeSampleRow( + TemporalRelation.Post, + "fabricatin", + 1, + Collections.singletonList("S0"), + Collections.singletonList("P0")); + List expected = Collections.singletonList(rowA); + List actual = + treatmentService.getAllSampleTreatmentRows(null, null, ClinicalEventKeyCode.Agent); + + Assert.assertEquals(new HashSet<>(expected), new HashSet<>(actual)); + } + + @Test + public void getAllSampleTreatmentRowsOneSampleBeforeOneSampleAfterOneTreatment() { + mockTreatmentsByPatient(makeTreatment("fabricatin", "P0", 10, 20)); + mockSamplesByPatient(makeSample("S0", "P0", 5), makeSample("S1", "P0", 25)); + + SampleTreatmentRow rowA = + makeSampleRow( + TemporalRelation.Post, + "fabricatin", + 1, + Collections.singletonList("S1"), + Collections.singletonList("P0")); + SampleTreatmentRow rowB = + makeSampleRow( + TemporalRelation.Pre, + "fabricatin", + 1, + Collections.singletonList("S0"), + Collections.singletonList("P0")); + List expected = Arrays.asList(rowA, rowB); + List actual = + treatmentService.getAllSampleTreatmentRows(null, null, ClinicalEventKeyCode.Agent); + + Assert.assertEquals(new HashSet<>(expected), new HashSet<>(actual)); + } + + @Test + public void getAllSampleTreatmentRowsThreeSamplesTwoTreatmentsSameDrug() { + mockTreatmentsByPatient( + makeTreatment("fabricatin", "P0", 10, 20), makeTreatment("fabricatin", "P0", 30, 40)); + mockSamplesByPatient( + makeSample("S0", "P0", 5), makeSample("S1", "P0", 25), makeSample("S2", "P0", 45)); + + SampleTreatmentRow rowA = + makeSampleRow( + TemporalRelation.Post, + "fabricatin", + 2, + Arrays.asList("S1", "S2"), + Arrays.asList("P0", "P0")); + SampleTreatmentRow rowB = + makeSampleRow( + TemporalRelation.Pre, + "fabricatin", + 1, + Collections.singletonList("S0"), + Collections.singletonList("P0")); + List expected = Arrays.asList(rowA, rowB); + List actual = + treatmentService.getAllSampleTreatmentRows(null, null, ClinicalEventKeyCode.Agent); + + Assert.assertEquals(new HashSet<>(expected), new HashSet<>(actual)); + } + + @Test + public void getAllSampleTreatmentRowsThreeSamplesTwoTreatmentsDifferentDrug() { + mockTreatmentsByPatient( + makeTreatment("fabricatin", "P0", 10, 20), makeTreatment("fauxan", "P0", 30, 40)); + mockSamplesByPatient( + makeSample("S0", "P0", 5), makeSample("S1", "P0", 25), makeSample("S2", "P0", 45)); + + // Keep in mind, adding a second drug that has samples that appear before and after it + // adds two rows to the result: pre and post + SampleTreatmentRow rowA = + makeSampleRow( + TemporalRelation.Post, + "fabricatin", + 2, + Arrays.asList("S1", "S2"), + Arrays.asList("P0", "P0")); + SampleTreatmentRow rowB = + makeSampleRow( + TemporalRelation.Pre, + "fabricatin", + 1, + Collections.singletonList("S0"), + Collections.singletonList("P0")); + SampleTreatmentRow rowC = + makeSampleRow( + TemporalRelation.Pre, + "fauxan", + 2, + Arrays.asList("S0", "S1"), + Arrays.asList("P0", "P0")); + SampleTreatmentRow rowD = + makeSampleRow( + TemporalRelation.Post, + "fauxan", + 1, + Collections.singletonList("S2"), + Collections.singletonList("P0")); + List expected = Arrays.asList(rowA, rowB, rowC, rowD); + List actual = + treatmentService.getAllSampleTreatmentRows(null, null, ClinicalEventKeyCode.Agent); + + Assert.assertEquals(new HashSet<>(expected), new HashSet<>(actual)); + } + + @Test + public void getAllSampleTreatmentRowsTwoPatients() { + mockTreatmentsByPatient( + makeTreatment("fabricatin", "P0", 10, 20), + makeTreatment("fabricatin", "P1", 10, 20), + makeTreatment("fauxan", "P0", 30, 40), + makeTreatment("fauxan", "P1", 30, 40)); + mockSamplesByPatient( + makeSample("S0", "P0", 5), + makeSample("S1", "P0", 25), + makeSample("S2", "P0", 45), + makeSample("S3", "P1", 5), + makeSample("S4", "P1", 25), + makeSample("S5", "P1", 45)); + + // Keep in mind, adding a second drug that has samples that appear before and after it + // adds two rows to the result: pre and post + SampleTreatmentRow rowA = + makeSampleRow( + TemporalRelation.Post, + "fabricatin", + 4, + Arrays.asList("S1", "S2", "S4", "S5"), + Arrays.asList("P0", "P0", "P1", "P1")); + SampleTreatmentRow rowB = + makeSampleRow( + TemporalRelation.Pre, + "fabricatin", + 2, + Arrays.asList("S0", "S3"), + Arrays.asList("P0", "P1")); + SampleTreatmentRow rowC = + makeSampleRow( + TemporalRelation.Pre, + "fauxan", + 4, + Arrays.asList("S0", "S1", "S3", "S4"), + Arrays.asList("P0", "P0", "P1", "P1")); + SampleTreatmentRow rowD = + makeSampleRow( + TemporalRelation.Post, + "fauxan", + 2, + Arrays.asList("S2", "S5"), + Arrays.asList("P0", "P1")); + List expected = Arrays.asList(rowA, rowB, rowC, rowD); + List actual = + treatmentService.getAllSampleTreatmentRows(null, null, ClinicalEventKeyCode.Agent); + + Assert.assertEquals(new HashSet<>(expected), new HashSet<>(actual)); + } + + private void mockTreatmentsByPatient(Treatment... treatments) { + Map> treatmentsByPatient = + Arrays.stream(treatments).collect(Collectors.groupingBy(Treatment::getPatientId)); + Mockito.when( + treatmentRepository.getTreatmentsByPatientId( + Mockito.any(), Mockito.any(), Mockito.any())) + .thenReturn(treatmentsByPatient); + } + + private void mockTreatments(Treatment... treatments) { + Mockito.when(treatmentRepository.getTreatments(Mockito.any(), Mockito.any(), Mockito.any())) + .thenReturn(Arrays.stream(treatments).collect(Collectors.toList())); + } + + private void mockSamplesByPatient(ClinicalEventSample... samples) { + Map> samplesByPatient = + Arrays.stream(samples).collect(Collectors.groupingBy(ClinicalEventSample::getPatientId)); + Mockito.when(treatmentRepository.getSamplesByPatientId(Mockito.any(), Mockito.any())) + .thenReturn(samplesByPatient); + Mockito.when(treatmentRepository.getShallowSamplesByPatientId(Mockito.any(), Mockito.any())) + .thenReturn(samplesByPatient); + } + + private Treatment makeTreatment(String treatment, String patientId, Integer start, Integer stop) { + Treatment t = new Treatment(); + t.setTreatment(treatment); + t.setStudyId(STUDY_ID); + t.setPatientId(patientId); + t.setStart(start); + t.setStop(stop); + return t; + } + + private ClinicalEventSample makeSample(String sampleId, String patientId, Integer timeTaken) { + ClinicalEventSample s = new ClinicalEventSample(); + s.setSampleId(sampleId); + s.setPatientId(patientId); + s.setStudyId(STUDY_ID); + s.setTimeTaken(timeTaken); + return s; + } + + private SampleTreatmentRow makeSampleRow( + TemporalRelation time, + String treatment, + int count, + List samples, + List patients) { + List clinicalSamples = + samples.stream() + .map( + s -> { + ClinicalEventSample sample = new ClinicalEventSample(); + sample.setSampleId(s); + sample.setStudyId(STUDY_ID); + return sample; + }) + .collect(Collectors.toList()); + for (int i = 0; i < clinicalSamples.size(); i++) { + clinicalSamples.get(i).setPatientId(patients.get(i)); + } + return new SampleTreatmentRow(time, treatment, count, new HashSet<>(clinicalSamples)); + } + + private PatientTreatmentRow makePatientRow( + String treatment, int count, List samples, List patients) { + List clinicalSamples = + samples.stream() + .map( + s -> { + ClinicalEventSample sample = new ClinicalEventSample(); + sample.setSampleId(s); + sample.setStudyId(STUDY_ID); + return sample; + }) + .collect(Collectors.toList()); + for (int i = 0; i < clinicalSamples.size(); i++) { + clinicalSamples.get(i).setPatientId(patients.get(i)); + } + return new PatientTreatmentRow(treatment, count, new HashSet<>(clinicalSamples)); + } +} diff --git a/src/test/java/org/cbioportal/legacy/service/impl/UuidDataAccessTokenServiceImplTest.java b/src/test/java/org/cbioportal/legacy/service/impl/UuidDataAccessTokenServiceImplTest.java new file mode 100644 index 00000000000..fbe77596418 --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/service/impl/UuidDataAccessTokenServiceImplTest.java @@ -0,0 +1,209 @@ +/* + * Copyright (c) 2018 Memorial Sloan-Kettering Cancer Center. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS + * FOR A PARTICULAR PURPOSE. The software and documentation provided hereunder + * is on an "as is" basis, and Memorial Sloan-Kettering Cancer Center has no + * obligations to provide maintenance, support, updates, enhancements or + * modifications. In no event shall Memorial Sloan-Kettering Cancer Center be + * liable to any party for direct, indirect, special, incidental or + * consequential damages, including lost profits, arising out of the use of this + * software and its documentation, even if Memorial Sloan-Kettering Cancer + * Center has been advised of the possibility of such damage. + */ + +/* + * Copyright 2002-2018 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * This file is part of cBioPortal. + * + * cBioPortal is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package org.cbioportal.legacy.service.impl; + +// TODO package org.cbioportal.security.spring.authentication.token; + +import java.util.*; +import org.cbioportal.legacy.model.DataAccessToken; +import org.cbioportal.legacy.persistence.DataAccessTokenRepository; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit4.SpringRunner; + +@TestPropertySource( + properties = { + "dat.jwt.secret_key = +NbopXzb/AIQNrVEGzxzP5CF42e5drvrXTQot3gfW/s=", + "dat.uuid.max_number_per_user = 1", + "dat.ttl_seconds = 2" + }, + inheritLocations = false) +@ContextConfiguration(classes = UuidDataAccessTokenServiceImplTestConfiguration.class) +@RunWith(SpringRunner.class) +public class UuidDataAccessTokenServiceImplTest { + + @Autowired + private UuidDataAccessTokenServiceImplTestConfiguration + uuidDataAccessTokenServiceImplTestConfiguration; + + @Autowired private DataAccessTokenRepository dataAccessTokenRepository; + + @Autowired + @Qualifier("uuidDataAccessTokenServiceImpl") + private UuidDataAccessTokenServiceImpl uuidDataAccessTokenServiceImpl; + + @Value("${dat.ttl_seconds}") + private int datTtlSeconds; + + /* Test for creating a token when autoexpire is on + * tests that new token is created/MaxNumberTokensExcceededException is not thrown + * deletedToken should be the oldest token + */ + @Test + public void testAutoExpireCreateTokenWhenLimitReached() { + // Testing for service with limit 1 token + uuidDataAccessTokenServiceImplTestConfiguration.resetAddedDataAccessToken(); + uuidDataAccessTokenServiceImplTestConfiguration.resetDeletedDataAccessToken(); + DataAccessToken newDataAccessToken = + uuidDataAccessTokenServiceImpl.createDataAccessToken( + UuidDataAccessTokenServiceImplTestConfiguration.MOCK_USERNAME_WITH_ONE_TOKEN); + Date expectedExpirationDate = getExpectedExpirationDate(); + String deletedDataAccessToken = + uuidDataAccessTokenServiceImplTestConfiguration.getDeletedDataAccessToken(); + DataAccessToken createdDataAccessToken = + uuidDataAccessTokenServiceImplTestConfiguration.getAddedDataAccessToken(); + if (createdDataAccessTokenWithWrongInformation( + createdDataAccessToken, + UuidDataAccessTokenServiceImplTestConfiguration.MOCK_USERNAME_WITH_ONE_TOKEN, + expectedExpirationDate)) { + Assert.fail( + "Created token (Username: " + + createdDataAccessToken.getUsername() + + ", Expiration: " + + createdDataAccessToken.getExpiration() + + ") differs from expected (Username: " + + UuidDataAccessTokenServiceImplTestConfiguration.MOCK_USERNAME_WITH_ONE_TOKEN + + ", Expiration: " + + expectedExpirationDate.toString() + + ")"); + } + if (deletedDataAccessToken + != uuidDataAccessTokenServiceImplTestConfiguration.OLDEST_TOKEN_UUID) { + Assert.fail( + "Expired token: " + + deletedDataAccessToken + + ", expected to expire token:" + + uuidDataAccessTokenServiceImplTestConfiguration.OLDEST_TOKEN_UUID); + } + } + + private Date getExpectedExpirationDate() { + Calendar calendar = Calendar.getInstance(); + calendar.add(Calendar.SECOND, datTtlSeconds); + Date expectedExpirationDate = calendar.getTime(); + return expectedExpirationDate; + } + + private boolean createdDataAccessTokenWithWrongInformation( + DataAccessToken createdDataAccessToken, + String expectedUsername, + Date expectedExpirationDate) { + boolean createdDataAccessTokenWithWrongInformation = false; + if (createdDataAccessToken.getUsername() != expectedUsername) { + createdDataAccessTokenWithWrongInformation = true; + } + if (Math.abs( + createdDataAccessToken.getExpiration().getTime() - expectedExpirationDate.getTime()) + > UuidDataAccessTokenServiceImplTestConfiguration + .MAXIMUM_TIME_DIFFERENCE_BETWEEN_CREATED_AND_EXPECTED_TOKEN) { + createdDataAccessTokenWithWrongInformation = true; + } + return createdDataAccessTokenWithWrongInformation; + } + + /* Tests validation of a token which is not in the repository + * Should return false + */ + @Test + public void validateNonexistantTokenTest() { + Boolean nonexistantTokenIsValid = + uuidDataAccessTokenServiceImpl.isValid( + UuidDataAccessTokenServiceImplTestConfiguration.NONEXISTENT_TOKEN_STRING); + if (nonexistantTokenIsValid) { + Assert.fail("Validation of nonexistant token returned true, expected false."); + } + } + + /* Tests validation of a token when there is a failure retrieving the token + * Should return false + */ + @Test + public void validateFailedToGetToken() { + Boolean failedToGetTokenIsValid = + uuidDataAccessTokenServiceImpl.isValid( + UuidDataAccessTokenServiceImplTestConfiguration.FAIL_TO_GET_TOKEN_STRING); + if (failedToGetTokenIsValid) { + Assert.fail("Validation of token that we failed to look up returned true, expected false."); + } + } + + /* Tests validation of a token which has expired + * Mock is configured to test a token with expiration date 100000 seconds before current time + * Should return false + */ + @Test + public void validateExpiredTokenTest() { + Boolean expiredTokenIsValid = + uuidDataAccessTokenServiceImpl.isValid( + UuidDataAccessTokenServiceImplTestConfiguration.EXPIRED_TOKEN_STRING); + if (expiredTokenIsValid) { + Assert.fail("Validation of expired token returned true, expected false"); + } + } + + /* Tests validation of a valid token + * Mock is configured to test a token with expiration date 100000 seconds after current time + * Should return true + */ + @Test + public void validateValidTokenTest() { + Boolean validTokenIsValid = + uuidDataAccessTokenServiceImpl.isValid( + UuidDataAccessTokenServiceImplTestConfiguration.VALID_TOKEN_STRING); + if (!validTokenIsValid) { + Assert.fail("Validation of valid token returned false, expected true."); + } + } +} diff --git a/src/test/java/org/cbioportal/legacy/service/impl/UuidDataAccessTokenServiceImplTestConfiguration.java b/src/test/java/org/cbioportal/legacy/service/impl/UuidDataAccessTokenServiceImplTestConfiguration.java new file mode 100644 index 00000000000..ec6d9fcc9f5 --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/service/impl/UuidDataAccessTokenServiceImplTestConfiguration.java @@ -0,0 +1,202 @@ +/* + * Copyright (c) 2018 Memorial Sloan-Kettering Cancer Center. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS + * FOR A PARTICULAR PURPOSE. The software and documentation provided hereunder + * is on an "as is" basis, and Memorial Sloan-Kettering Cancer Center has no + * obligations to provide maintenance, support, updates, enhancements or + * modifications. In no event shall Memorial Sloan-Kettering Cancer Center be + * liable to any party for direct, indirect, special, incidental or + * consequential damages, including lost profits, arising out of the use of this + * software and its documentation, even if Memorial Sloan-Kettering Cancer + * Center has been advised of the possibility of such damage. + */ + +/* + * Copyright 2002-2018 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * This file is part of cBioPortal. + * + * cBioPortal is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package org.cbioportal.legacy.service.impl; + +// TODO package org.cbioportal.security.spring.authentication.token; + +import java.util.*; +import org.cbioportal.legacy.model.DataAccessToken; +import org.cbioportal.legacy.persistence.DataAccessTokenRepository; +import org.mockito.ArgumentMatchers; +import org.mockito.Mockito; +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; +import org.springframework.boot.test.context.TestConfiguration; +import org.springframework.context.annotation.Bean; + +@TestConfiguration +public class UuidDataAccessTokenServiceImplTestConfiguration { + + public static String MOCK_USERNAME = "MOCK_USER"; + public static String MOCK_USERNAME_WITH_ONE_TOKEN = "MOCK_USER_WITH_ONE_TOKEN"; + public static String MOCK_USERNAME_WITH_FIVE_TOKENS = "MOCK_USER_WITH_FIVE_TOKENS"; + public static String NONEXISTENT_TOKEN_STRING = "NONEXISTENT_TOKEN_STRING"; + public static String FAIL_TO_GET_TOKEN_STRING = "FAIL_TO_GET_TOKEN_STRING"; + public static String EXPIRED_TOKEN_STRING = "EXPIRED_TOKEN_STRING"; + public static String VALID_TOKEN_STRING = "VALID_TOKEN_STRING"; + public static String OLDEST_TOKEN_UUID = "OLDEST_TOKEN_UUID"; + public static String NEWEST_TOKEN_UUID = "NEWEST_TOKEN_UUID"; + + public static int MAXIMUM_TIME_DIFFERENCE_BETWEEN_CREATED_AND_EXPECTED_TOKEN = 5000; + + private List dataAccessTokenListForMockUserWithOneToken = + makeDataAccessTokenListForMockUserWithOneToken(); + private List dataAccessTokenListForMockUserWithFiveTokens = + makeDataAccessTokenListForMockUserWithFiveTokens(); + + DataAccessToken addedDataAccessToken = null; + String deletedDataAccessToken = null; + + @Bean + public UuidDataAccessTokenServiceImpl uuidDataAccessTokenServiceImpl() { + return new UuidDataAccessTokenServiceImpl(); + } + + @Bean + public DataAccessTokenRepository dataAccessTokenRepository() { + Answer dataAccessTokenRepositoryCreateTokenAnswer = + new Answer() { + public Void answer(InvocationOnMock addTokenInvocation) { + addedDataAccessToken = (DataAccessToken) addTokenInvocation.getArguments()[0]; + return null; + } + }; + Answer dataAccessTokenRepositoryDeleteTokenAnswer = + new Answer() { + public Void answer(InvocationOnMock deleteTokenInvocation) { + deletedDataAccessToken = (String) deleteTokenInvocation.getArguments()[0]; + return null; + } + }; + DataAccessTokenRepository dataAccessTokenRepository = + Mockito.mock(DataAccessTokenRepository.class); + Mockito.when(dataAccessTokenRepository.getDataAccessToken(FAIL_TO_GET_TOKEN_STRING)) + .thenThrow(new RuntimeException("Fail to get this token")); + Mockito.when(dataAccessTokenRepository.getDataAccessToken(NONEXISTENT_TOKEN_STRING)) + .thenReturn(null); + Mockito.when(dataAccessTokenRepository.getDataAccessToken(EXPIRED_TOKEN_STRING)) + .thenReturn(makeExpiredDataAccessToken()); + Mockito.when(dataAccessTokenRepository.getDataAccessToken(VALID_TOKEN_STRING)) + .thenReturn(makeValidDataAccessToken()); + Mockito.when( + dataAccessTokenRepository.getAllDataAccessTokensForUsername( + MOCK_USERNAME_WITH_ONE_TOKEN)) + .thenReturn(dataAccessTokenListForMockUserWithOneToken); + Mockito.when( + dataAccessTokenRepository.getAllDataAccessTokensForUsername( + MOCK_USERNAME_WITH_FIVE_TOKENS)) + .thenReturn(sortByExpiration(dataAccessTokenListForMockUserWithFiveTokens)); + Mockito.doAnswer(dataAccessTokenRepositoryDeleteTokenAnswer) + .when(dataAccessTokenRepository) + .removeDataAccessToken(ArgumentMatchers.anyString()); + Mockito.doAnswer(dataAccessTokenRepositoryCreateTokenAnswer) + .when(dataAccessTokenRepository) + .addDataAccessToken(ArgumentMatchers.any(DataAccessToken.class)); + return dataAccessTokenRepository; + } + + private DataAccessToken makeDataAccessToken(String username, int offsetSeconds) { + String uuid = UUID.randomUUID().toString(); + DataAccessToken dataAccessToken = makeDataAccessToken(uuid, username, offsetSeconds); + return dataAccessToken; + } + + private DataAccessToken makeDataAccessToken(String uuid, String username, int offsetSeconds) { + Calendar calendar = Calendar.getInstance(); + Date creationDate = calendar.getTime(); + calendar.add(Calendar.SECOND, offsetSeconds); + Date expirationDate = calendar.getTime(); + DataAccessToken dataAccessToken = + new DataAccessToken(uuid, username, expirationDate, creationDate); + return dataAccessToken; + } + + private DataAccessToken makeExpiredDataAccessToken() { + return makeDataAccessToken(MOCK_USERNAME, -100000); + } + + private DataAccessToken makeValidDataAccessToken() { + return makeDataAccessToken(MOCK_USERNAME, 100000); + } + + private List makeDataAccessTokenListForMockUserWithOneToken() { + List dataAccessTokenListForMockUserWithOneToken = + new ArrayList(); + dataAccessTokenListForMockUserWithOneToken.add( + makeDataAccessToken(OLDEST_TOKEN_UUID, MOCK_USERNAME_WITH_ONE_TOKEN, -150000)); + return dataAccessTokenListForMockUserWithOneToken; + } + + private List makeDataAccessTokenListForMockUserWithFiveTokens() { + List dataAccessTokenListForMockUserWithFiveTokens = + new ArrayList(); + dataAccessTokenListForMockUserWithFiveTokens.add( + makeDataAccessToken(MOCK_USERNAME_WITH_FIVE_TOKENS, 86400)); + dataAccessTokenListForMockUserWithFiveTokens.add( + makeDataAccessToken(MOCK_USERNAME_WITH_FIVE_TOKENS, 172800)); + dataAccessTokenListForMockUserWithFiveTokens.add( + makeDataAccessToken(MOCK_USERNAME_WITH_FIVE_TOKENS, 529200)); + dataAccessTokenListForMockUserWithFiveTokens.add( + makeDataAccessToken(OLDEST_TOKEN_UUID, MOCK_USERNAME_WITH_FIVE_TOKENS, 45000)); + dataAccessTokenListForMockUserWithFiveTokens.add( + makeDataAccessToken(NEWEST_TOKEN_UUID, MOCK_USERNAME_WITH_FIVE_TOKENS, 1000000)); + return dataAccessTokenListForMockUserWithFiveTokens; + } + + private List sortByExpiration(List dataAccessTokenList) { + dataAccessTokenList.sort(Comparator.comparing(DataAccessToken::getExpiration)); + return dataAccessTokenList; + } + + public DataAccessToken getAddedDataAccessToken() { + return addedDataAccessToken; + } + + public void resetAddedDataAccessToken() { + addedDataAccessToken = null; + } + + public String getDeletedDataAccessToken() { + return deletedDataAccessToken; + } + + public void resetDeletedDataAccessToken() { + deletedDataAccessToken = null; + } +} diff --git a/src/test/java/org/cbioportal/legacy/service/impl/UuidDataAccessTokenServiceImplTestFiveTokenLimit.java b/src/test/java/org/cbioportal/legacy/service/impl/UuidDataAccessTokenServiceImplTestFiveTokenLimit.java new file mode 100644 index 00000000000..aa4c8aa8ee6 --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/service/impl/UuidDataAccessTokenServiceImplTestFiveTokenLimit.java @@ -0,0 +1,155 @@ +/* + * Copyright (c) 2018 Memorial Sloan-Kettering Cancer Center. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS + * FOR A PARTICULAR PURPOSE. The software and documentation provided hereunder + * is on an "as is" basis, and Memorial Sloan-Kettering Cancer Center has no + * obligations to provide maintenance, support, updates, enhancements or + * modifications. In no event shall Memorial Sloan-Kettering Cancer Center be + * liable to any party for direct, indirect, special, incidental or + * consequential damages, including lost profits, arising out of the use of this + * software and its documentation, even if Memorial Sloan-Kettering Cancer + * Center has been advised of the possibility of such damage. + */ + +/* + * Copyright 2002-2018 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * This file is part of cBioPortal. + * + * cBioPortal is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package org.cbioportal.legacy.service.impl; + +// TODO package org.cbioportal.security.spring.authentication.token; + +import java.util.*; +import org.cbioportal.legacy.model.DataAccessToken; +import org.cbioportal.legacy.persistence.DataAccessTokenRepository; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit4.SpringRunner; + +@TestPropertySource( + properties = { + "dat.jwt.secret_key = +NbopXzb/AIQNrVEGzxzP5CF42e5drvrXTQot3gfW/s=", + "dat.uuid.max_number_per_user = 5", + "dat.ttl_seconds = 2" + }, + inheritLocations = false) +@ContextConfiguration(classes = UuidDataAccessTokenServiceImplTestConfiguration.class) +@RunWith(SpringRunner.class) +public class UuidDataAccessTokenServiceImplTestFiveTokenLimit { + + @Autowired + private UuidDataAccessTokenServiceImplTestConfiguration + uuidDataAccessTokenServiceImplTestConfiguration; + + @Autowired private DataAccessTokenRepository dataAccessTokenRepository; + + @Autowired + @Qualifier("uuidDataAccessTokenServiceImpl") + private UuidDataAccessTokenServiceImpl uuidDataAccessTokenServiceImpl; + + @Value("${dat.ttl_seconds}") + private int datTtlSeconds; + + /* Test for creating a token when autoexpire is on + * tests that new token is created/MaxNumberTokensExcceededException is not thrown + * deletedToken should be the oldest token + */ + @Test + public void testAutoExpireCreateTokenWhenLimitReached() { + uuidDataAccessTokenServiceImplTestConfiguration.resetAddedDataAccessToken(); + uuidDataAccessTokenServiceImplTestConfiguration.resetDeletedDataAccessToken(); + // Testing for service with limit 5 tokens + DataAccessToken newDataAccessToken = + uuidDataAccessTokenServiceImpl.createDataAccessToken( + UuidDataAccessTokenServiceImplTestConfiguration.MOCK_USERNAME_WITH_FIVE_TOKENS); + Date expectedExpirationDate = getExpectedExpirationDate(); + String deletedDataAccessToken = + uuidDataAccessTokenServiceImplTestConfiguration.getDeletedDataAccessToken(); + DataAccessToken createdDataAccessToken = + uuidDataAccessTokenServiceImplTestConfiguration.getAddedDataAccessToken(); + if (createdDataAccessTokenWithWrongInformation( + createdDataAccessToken, + UuidDataAccessTokenServiceImplTestConfiguration.MOCK_USERNAME_WITH_FIVE_TOKENS, + expectedExpirationDate)) { + Assert.fail( + "Created token (Username: " + + createdDataAccessToken.getUsername() + + ", Expiration: " + + createdDataAccessToken.getExpiration() + + ") differs from expected (Username: " + + UuidDataAccessTokenServiceImplTestConfiguration.MOCK_USERNAME_WITH_FIVE_TOKENS + + ", Expiration: " + + expectedExpirationDate.toString() + + ")"); + } + if (deletedDataAccessToken + != uuidDataAccessTokenServiceImplTestConfiguration.OLDEST_TOKEN_UUID) { + Assert.fail( + "Expired token: " + + deletedDataAccessToken + + ", expected to expire token:" + + uuidDataAccessTokenServiceImplTestConfiguration.OLDEST_TOKEN_UUID); + } + } + + private Date getExpectedExpirationDate() { + Calendar calendar = Calendar.getInstance(); + calendar.add(Calendar.SECOND, datTtlSeconds); + Date expectedExpirationDate = calendar.getTime(); + return expectedExpirationDate; + } + + private boolean createdDataAccessTokenWithWrongInformation( + DataAccessToken createdDataAccessToken, + String expectedUsername, + Date expectedExpirationDate) { + boolean createdDataAccessTokenWithWrongInformation = false; + if (createdDataAccessToken.getUsername() != expectedUsername) { + createdDataAccessTokenWithWrongInformation = true; + } + if (Math.abs( + createdDataAccessToken.getExpiration().getTime() - expectedExpirationDate.getTime()) + > UuidDataAccessTokenServiceImplTestConfiguration + .MAXIMUM_TIME_DIFFERENCE_BETWEEN_CREATED_AND_EXPECTED_TOKEN) { + createdDataAccessTokenWithWrongInformation = true; + } + return createdDataAccessTokenWithWrongInformation; + } +} diff --git a/src/test/java/org/cbioportal/legacy/service/impl/VariantCountServiceImplTest.java b/src/test/java/org/cbioportal/legacy/service/impl/VariantCountServiceImplTest.java new file mode 100644 index 00000000000..8296945e6e4 --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/service/impl/VariantCountServiceImplTest.java @@ -0,0 +1,68 @@ +package org.cbioportal.legacy.service.impl; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import org.cbioportal.legacy.model.MolecularProfile; +import org.cbioportal.legacy.model.SampleList; +import org.cbioportal.legacy.model.VariantCount; +import org.cbioportal.legacy.model.meta.MutationMeta; +import org.cbioportal.legacy.persistence.VariantCountRepository; +import org.cbioportal.legacy.service.MolecularProfileService; +import org.cbioportal.legacy.service.MutationService; +import org.cbioportal.legacy.service.SampleListService; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.junit.MockitoJUnitRunner; + +@RunWith(MockitoJUnitRunner.Silent.class) +public class VariantCountServiceImplTest extends BaseServiceImplTest { + + @InjectMocks private VariantCountServiceImpl variantCountService; + + @Mock private VariantCountRepository variantCountRepository; + @Mock private MutationService mutationService; + @Mock private MolecularProfileService molecularProfileService; + @Mock private SampleListService sampleListService; + + @Test + public void fetchVariantCounts() throws Exception { + + MolecularProfile molecularProfile = new MolecularProfile(); + molecularProfile.setCancerStudyIdentifier(STUDY_ID); + molecularProfile.setMolecularAlterationType( + MolecularProfile.MolecularAlterationType.MUTATION_EXTENDED); + Mockito.when(molecularProfileService.getMolecularProfile(MOLECULAR_PROFILE_ID)) + .thenReturn(molecularProfile); + + MutationMeta mutationMeta = new MutationMeta(); + mutationMeta.setSampleCount(5); + Mockito.when( + mutationService.fetchMetaMutationsInMolecularProfile(MOLECULAR_PROFILE_ID, null, null)) + .thenReturn(mutationMeta); + + SampleList sampleList = new SampleList(); + sampleList.setSampleCount(5); + Mockito.when(sampleListService.getSampleList(STUDY_ID + "_sequenced")).thenReturn(sampleList); + + List expectedVariantCounts = new ArrayList<>(); + VariantCount variantCount = new VariantCount(); + expectedVariantCounts.add(variantCount); + + Mockito.when( + variantCountRepository.fetchVariantCounts( + MOLECULAR_PROFILE_ID, Arrays.asList(ENTREZ_GENE_ID_1), Arrays.asList(KEYWORD))) + .thenReturn(expectedVariantCounts); + + List result = + variantCountService.fetchVariantCounts( + MOLECULAR_PROFILE_ID, Arrays.asList(ENTREZ_GENE_ID_1), Arrays.asList(KEYWORD)); + + Assert.assertEquals(expectedVariantCounts, result); + Assert.assertEquals((Integer) 5, result.get(0).getNumberOfSamples()); + } +} diff --git a/src/test/java/org/cbioportal/legacy/service/impl/ViolinPlotServiceImplTest.java b/src/test/java/org/cbioportal/legacy/service/impl/ViolinPlotServiceImplTest.java new file mode 100644 index 00000000000..2cc24424528 --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/service/impl/ViolinPlotServiceImplTest.java @@ -0,0 +1,156 @@ +package org.cbioportal.legacy.service.impl; + +import static java.util.stream.Collectors.toSet; + +import java.math.BigDecimal; +import java.util.*; +import org.cbioportal.legacy.model.ClinicalData; +import org.cbioportal.legacy.model.ClinicalViolinPlotData; +import org.cbioportal.legacy.model.Sample; +import org.cbioportal.legacy.web.parameter.StudyViewFilter; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.junit.MockitoJUnitRunner; + +@RunWith(MockitoJUnitRunner.Silent.class) +public class ViolinPlotServiceImplTest { + private static final String[][] FGA_VALUES = + new String[][] { + new String[] {"0.1", "0.5", "0.2", "0.351", "0.44", "0.87", "0.75", "0.9", "0.2", "0.25"}, + new String[] {"0.62", "0.451", "0.224", "1.0", "0.95"}, + new String[] { + "0.91", "0.3", "0.15", "0.42", "0.951", "0.724", "0.6", "0.45", "0.11", "0.1", "0.5", + "0.2", "0.351" + }, + new String[] {"0.44", "0.87"}, + new String[] { + "0.75", "0.9", "0.2", "0.25", "0.62", "0.451", "0.224", "1.0", "0.95", "0.91" + }, + new String[] {"0.3"}, + new String[] {"0.15", "0.42", "0.951", "0.724", "0.6", "0.45", "0.11"} + }; + + private static final String[] EXPECTED_ROW_CATEGORIES = new String[] {}; + + @InjectMocks private ViolinPlotServiceImpl violinPlotService; + + @Test + public void getClinicalViolinPlotData() throws Exception { + List sampleClinicalData = new ArrayList<>(); + List filteredSamples = new ArrayList<>(); + for (int j = 0; j < FGA_VALUES.length; j++) { + for (int i = 0; i < FGA_VALUES[j].length; i++) { + ClinicalData num = new ClinicalData(); + num.setAttrId("FRACTION_GENOME_ALTERED"); + num.setAttrValue(FGA_VALUES[j][i]); + num.setStudyId("test_study_id"); + num.setSampleId("test_sample_id_" + i + "_" + j); + num.setUniqueSampleKey("test_sample_id_" + i + "_" + j); + sampleClinicalData.add(num); + + ClinicalData cat = new ClinicalData(); + cat.setAttrId("CANCER_TYPE_DETAILED"); + cat.setAttrValue("cancer_type_" + j); + cat.setStudyId("test_study_id"); + cat.setSampleId("test_sample_id_" + i + "_" + j); + cat.setUniqueSampleKey("test_sample_id_" + i + "_" + j); + sampleClinicalData.add(cat); + + Sample s = new Sample(); + s.setUniqueSampleKey("test_sample_id_" + i + "_" + j); + filteredSamples.add(s); + } + } + + final int NUM_CURVE_POINTS = 100; + Set sampleIdsSet = + filteredSamples.stream().map(s -> s.getInternalId()).collect(toSet()); + ClinicalViolinPlotData result = + violinPlotService.getClinicalViolinPlotData( + sampleClinicalData, + sampleIdsSet, + new BigDecimal(0), + new BigDecimal(1), + new BigDecimal(NUM_CURVE_POINTS), + false, + new BigDecimal(1), + new StudyViewFilter()); + + // sort the rows so that they're in the same order as FGA_VALUES so that it's easy to access + // them in order for the test + result + .getRows() + .sort( + (a, b) -> { + return a.getCategory().compareTo(b.getCategory()); + }); + + Assert.assertEquals(FGA_VALUES.length, result.getRows().size()); + Assert.assertEquals( + NUM_CURVE_POINTS, + result + .getRows() + .get(0) + .getCurveData() + .size()); // curve data of the right count when there's enough points + Assert.assertEquals( + 0, + result.getRows().get(1).getCurveData().size()); // no curve data when there's too few points + Assert.assertEquals( + FGA_VALUES[1].length, + result + .getRows() + .get(1) + .getIndividualPoints() + .size()); // all data as individual points when theres few + Assert.assertEquals( + NUM_CURVE_POINTS, + result + .getRows() + .get(2) + .getCurveData() + .size()); // curve data of the right count when there's enough points + Assert.assertEquals( + 0, + result.getRows().get(3).getCurveData().size()); // no curve data when there's too few points + Assert.assertEquals( + FGA_VALUES[3].length, + result + .getRows() + .get(3) + .getIndividualPoints() + .size()); // all data as individual points when theres few + Assert.assertEquals( + NUM_CURVE_POINTS, + result + .getRows() + .get(4) + .getCurveData() + .size()); // curve data of the right count when there's enough points + Assert.assertEquals( + 0, + result.getRows().get(5).getCurveData().size()); // no curve data when there's too few points + Assert.assertEquals( + FGA_VALUES[5].length, + result + .getRows() + .get(5) + .getIndividualPoints() + .size()); // all data as individual points when theres few + Assert.assertEquals( + 0, + result.getRows().get(6).getCurveData().size()); // no curve data when there's too few points + Assert.assertEquals( + FGA_VALUES[6].length, + result + .getRows() + .get(6) + .getIndividualPoints() + .size()); // all data as individual points when theres few + Assert.assertEquals( + "ClinicalViolinPlotData{rows=[ClinicalViolinPlotRowData{category='cancer_type_0', numSamples=10, curveData=[2.0603650520008255E-20, 2.490647719181926E-16, 1.1076076652208455E-12, 1.8120288948454348E-9, 1.090560598843556E-6, 2.4145711384344356E-4, 0.019666891667884497, 0.5893007095578116, 6.4959656626929885, 26.342439739976722, 39.29830220022416, 21.567365526222503, 4.354376002067154, 0.323415093753096, 0.008840819153424564, 8.731643281319479E-4, 0.057805819777250377, 1.5672594138804623, 15.632131348621245, 57.35893005962437, 77.42695132836181, 38.48374585923057, 7.92423207121134, 9.01350402771472, 29.824276510741445, 38.28024971198188, 18.082259808682327, 3.142225532171844, 0.20087576275102062, 0.004726772934205448, 5.411635860928458E-4, 0.03503823201531945, 0.9027413660709811, 8.556410917840077, 29.83495870707217, 38.27055558846335, 18.05966172025932, 3.1351619223612133, 0.20023152249979403, 0.005909899633813545, 0.0699456171757767, 1.490902145686011, 11.697572211073982, 33.763533100833605, 35.85136402095853, 14.006118947628552, 2.098902804893868, 1.84169440953853, 12.824311118235457, 34.85448215358368, 34.85446738862994, 12.822241970960828, 1.7353017488632785, 0.08639558680953024, 0.001582390369583597, 1.0662062442117748E-5, 2.642861048615092E-8, 2.4099773276986683E-11, 8.08457327535297E-15, 9.977156040356584E-19, 4.529621834615629E-23, 7.565238860446793E-28, 1.0718685085686528E-31, 1.299713343010475E-26, 6.060567016595081E-22, 1.0396435331670962E-17, 6.560866081409529E-14, 1.5231525710557055E-10, 1.300861799974408E-7, 4.087186278743814E-5, 0.004724145017579533, 0.20087575767268165, 3.1422255317310923, 18.082259453513366, 38.280143563482106, 29.812605783325406, 8.541454563824558, 0.9002626876575123, 0.03490697255455146, 4.979215825253348E-4, 2.886267512257377E-6, 7.619593216682073E-5, 0.0078106380228383536, 0.2945614709023054, 4.086762339314846, 20.866706525926265, 39.486371749494865, 31.405574658411524, 28.441263369046265, 39.94087916293252, 26.364537728689402, 6.496245229664247, 0.5893020106991916, 0.019666893895645545, 2.414571152466279E-4, 1.0905605991686674E-6, 1.812028894873151E-9, 1.1076076652216555E-12, 2.4906477191819726E-16, 2.0603650520008884E-20], boxData=ClinicalViolinPlotBoxData{whiskerLower=0.1, whiskerUpper=0.9, median=0.39549999999999996, q1=0.2, q3=0.78}, individualPoints=[]}, ClinicalViolinPlotRowData{category='cancer_type_1', numSamples=5, curveData=[], boxData=ClinicalViolinPlotBoxData{whiskerLower=0.224, whiskerUpper=1.0, median=0.62, q1=0.3375, q3=0.975}, individualPoints=[ClinicalViolinPlotIndividualPoint{sampleId='test_sample_id_2_1', studyId='test_study_id', value=0.224}, ClinicalViolinPlotIndividualPoint{sampleId='test_sample_id_3_1', studyId='test_study_id', value=1.0}, ClinicalViolinPlotIndividualPoint{sampleId='test_sample_id_4_1', studyId='test_study_id', value=0.95}, ClinicalViolinPlotIndividualPoint{sampleId='test_sample_id_0_1', studyId='test_study_id', value=0.62}, ClinicalViolinPlotIndividualPoint{sampleId='test_sample_id_1_1', studyId='test_study_id', value=0.451}]}, ClinicalViolinPlotRowData{category='cancer_type_2', numSamples=13, curveData=[2.0604349714417075E-20, 2.4908751857701826E-16, 1.1078798994931478E-12, 1.8132274927165033E-9, 1.0925019751422748E-6, 2.4261389568468555E-4, 0.019920462163832454, 0.6097487405937532, 7.102575977934906, 32.96267917619901, 65.87787308350975, 60.848297696187764, 26.365137919687257, 11.721512020481352, 27.842869938204167, 39.062416249449676, 20.41667808368713, 4.699084133526758, 8.092697255277999, 28.686653690486928, 38.71329545117342, 19.224419685158946, 3.511984692095103, 0.23602473900518278, 0.005838842523441374, 6.836869426203608E-4, 0.0420534243691329, 1.031672546850052, 9.310858665390146, 30.913142031226013, 37.75789402231517, 17.00052871466201, 3.7071181023371595, 8.726945242806329, 29.83877369156282, 38.27058700048275, 18.059668660116213, 3.136262373779872, 0.26531165553642155, 1.4209179865630728, 11.337277869403325, 33.45324934951163, 37.69048995607363, 26.291739969127615, 36.06418308407382, 35.807699035046355, 13.892282505285074, 3.699216335820821, 12.92503186350542, 34.856446537583444, 34.85448136906267, 12.822242007455431, 1.735301748949051, 0.08639563718213138, 0.001600778251844697, 0.0024799667201574832, 0.12198972410744431, 2.2170584992135836, 14.823019097938793, 36.45874389002913, 32.98923568628809, 10.981162633265924, 1.3447139541348578, 0.06057829108126272, 0.0010039443608221134, 6.1290835423397E-6, 4.0013852695867196E-6, 7.057096490584219E-4, 0.04594516388423852, 1.100421531585217, 9.695804992159552, 31.427814626145288, 37.47572226043353, 16.43960424960614, 2.653005947433887, 0.15750364422145563, 0.0034399213092719486, 2.76383382224506E-5, 8.169225128672376E-8, 8.88291118889242E-11, 3.5533282719167566E-14, 5.031913846093932E-17, 2.424772067091923E-13, 4.796959342481572E-10, 3.4911352431404435E-7, 9.347012578266495E-5, 0.009206286776276391, 0.33358129436224565, 4.446562704058479, 21.804895004152677, 39.342873190143955, 26.38262037695624, 10.297268206509107, 20.98356751811011, 39.078206388966755, 27.497337388621183, 7.121233546216458, 0.6784671743735528, 0.02377979084850563, 3.066145357775355E-4], boxData=ClinicalViolinPlotBoxData{whiskerLower=0.1, whiskerUpper=0.951, median=0.42, q1=0.175, q3=0.6619999999999999}, individualPoints=[]}, ClinicalViolinPlotRowData{category='cancer_type_3', numSamples=2, curveData=[], boxData=ClinicalViolinPlotBoxData{whiskerLower=0.44, whiskerUpper=0.87, median=0.655, q1=0.44, q3=0.87}, individualPoints=[ClinicalViolinPlotIndividualPoint{sampleId='test_sample_id_0_3', studyId='test_study_id', value=0.44}, ClinicalViolinPlotIndividualPoint{sampleId='test_sample_id_1_3', studyId='test_study_id', value=0.87}]}, ClinicalViolinPlotRowData{category='cancer_type_4', numSamples=10, curveData=[2.925101346412698E-84, 7.047326918847208E-76, 6.2461647820480575E-68, 2.0366104799983836E-60, 2.4429131610500767E-53, 1.0779871957744748E-46, 1.7499461861510412E-40, 1.0450601867428694E-34, 2.2959553094837114E-29, 1.8556286783192092E-24, 5.517270022518955E-20, 6.034800548564917E-16, 2.428326734129904E-12, 3.5946519073313903E-9, 1.957546564696557E-6, 3.921688697608263E-4, 0.02890295167045124, 0.7836898183811377, 7.822518053870328, 28.93425860883489, 42.41505870517847, 39.039761397420484, 43.30054281995553, 36.90344839886546, 37.3018866669242, 39.012685837114354, 18.108635475219785, 3.1425749272248065, 0.20087746035344534, 0.00472414807007391, 4.087186480061479E-5, 1.300861804858761E-7, 1.5231525714916123E-10, 6.560866081552088E-14, 1.0396444702718048E-17, 2.401813560688031E-19, 2.253213032113778E-15, 7.795931015163072E-12, 9.922914255174207E-9, 4.646393721258539E-6, 8.003838098203277E-4, 0.05072080066123851, 1.1824408475626524, 10.140941225977224, 31.995037636972278, 37.13577597396173, 15.856520709161023, 2.4907423957196735, 0.14393129906586433, 0.003059758820145182, 2.3929006278898765E-5, 6.884424635652973E-8, 7.286453085144085E-11, 5.0629959529312694E-14, 5.885062782719107E-11, 5.723966796249049E-8, 2.0480882189325674E-5, 0.0026959121195483347, 0.13054742829045168, 2.325607550461973, 15.240880389500784, 36.74423405658725, 32.58921211630563, 10.633201436234723, 1.2763204846816174, 0.05635869859959091, 9.155196933961355E-4, 5.471318963429264E-6, 1.4211429893991378E-7, 4.0871872515380816E-5, 0.004724145017582428, 0.20087575767268165, 3.1422255317310923, 18.082259453513366, 38.280143563482106, 29.812605783325406, 8.541454563824558, 0.9002626876575122, 0.03490697255437616, 4.979212215706467E-4, 2.6128507715759102E-6, 5.044212246476146E-9, 4.5066541275640675E-10, 3.289502369812991E-7, 8.917622163190966E-5, 0.008930374186319114, 0.3326213733402558, 4.687957296745932, 26.013928432023253, 61.103242586623175, 65.68892703656729, 32.97824827968543, 11.793099318468258, 23.350427210600866, 39.46524983902706, 25.165326772772932, 6.338629923434066, 5.854227137880277, 23.971264111864187, 39.49547451323124], boxData=ClinicalViolinPlotBoxData{whiskerLower=0.2, whiskerUpper=1.0, median=0.685, q1=0.2435, q3=0.92}, individualPoints=[]}, ClinicalViolinPlotRowData{category='cancer_type_5', numSamples=1, curveData=[], boxData=ClinicalViolinPlotBoxData{whiskerLower=0.3, whiskerUpper=0.3, median=0.3, q1=0.3, q3=0.3}, individualPoints=[ClinicalViolinPlotIndividualPoint{sampleId='test_sample_id_0_5', studyId='test_study_id', value=0.3}]}, ClinicalViolinPlotRowData{category='cancer_type_6', numSamples=7, curveData=[], boxData=ClinicalViolinPlotBoxData{whiskerLower=0.11, whiskerUpper=0.951, median=0.45, q1=0.15, q3=0.724}, individualPoints=[ClinicalViolinPlotIndividualPoint{sampleId='test_sample_id_1_6', studyId='test_study_id', value=0.42}, ClinicalViolinPlotIndividualPoint{sampleId='test_sample_id_2_6', studyId='test_study_id', value=0.951}, ClinicalViolinPlotIndividualPoint{sampleId='test_sample_id_3_6', studyId='test_study_id', value=0.724}, ClinicalViolinPlotIndividualPoint{sampleId='test_sample_id_4_6', studyId='test_study_id', value=0.6}, ClinicalViolinPlotIndividualPoint{sampleId='test_sample_id_0_6', studyId='test_study_id', value=0.15}, ClinicalViolinPlotIndividualPoint{sampleId='test_sample_id_5_6', studyId='test_study_id', value=0.45}, ClinicalViolinPlotIndividualPoint{sampleId='test_sample_id_6_6', studyId='test_study_id', value=0.11}]}], axisStart=0.0, axisEnd=1.0}", + result.toString()); + } +} diff --git a/src/test/java/org/cbioportal/legacy/service/util/AlterationCountServiceUtilTest.java b/src/test/java/org/cbioportal/legacy/service/util/AlterationCountServiceUtilTest.java new file mode 100644 index 00000000000..0b94cf01ad8 --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/service/util/AlterationCountServiceUtilTest.java @@ -0,0 +1,434 @@ +package org.cbioportal.legacy.service.util; + +import static org.junit.Assert.*; + +import java.math.BigDecimal; +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import org.apache.commons.math3.util.Pair; +import org.cbioportal.legacy.model.AlterationCountByGene; +import org.cbioportal.legacy.model.AlterationCountByStructuralVariant; +import org.cbioportal.legacy.model.CopyNumberCountByGene; +import org.cbioportal.legacy.model.Gistic; +import org.cbioportal.legacy.model.GisticToGene; +import org.cbioportal.legacy.model.MolecularProfile; +import org.cbioportal.legacy.model.MutSig; +import org.junit.Test; + +public class AlterationCountServiceUtilTest { + + @Test + public void testComputeTotalProfiledCount() { + // Test with gene panel data + boolean hasGenePanelData = true; + int alterationsProfiledCount = 5; + int sampleProfileCountWithoutGenePanelData = 10; + int totalProfiledCount = 20; + + int result = + AlterationCountServiceUtil.computeTotalProfiledCount( + hasGenePanelData, + alterationsProfiledCount, + sampleProfileCountWithoutGenePanelData, + totalProfiledCount); + assertEquals(15, result); + + // Test without gene panel data + hasGenePanelData = false; + result = + AlterationCountServiceUtil.computeTotalProfiledCount( + hasGenePanelData, + alterationsProfiledCount, + sampleProfileCountWithoutGenePanelData, + totalProfiledCount); + assertEquals(10, result); + + // Test with zero profiled count + hasGenePanelData = true; + alterationsProfiledCount = 0; + sampleProfileCountWithoutGenePanelData = 0; + result = + AlterationCountServiceUtil.computeTotalProfiledCount( + hasGenePanelData, + alterationsProfiledCount, + sampleProfileCountWithoutGenePanelData, + totalProfiledCount); + assertEquals(20, result); + } + + @Test + public void testUpdateAlterationCountsWithMutSigQValue() { + AlterationCountByGene count1 = new AlterationCountByGene(); + count1.setHugoGeneSymbol("hugo1"); + + AlterationCountByGene count2 = new AlterationCountByGene(); + count2.setHugoGeneSymbol("hugo2"); + + List counts = Arrays.asList(count1, count2); + + MutSig mutSig1 = new MutSig(); + mutSig1.setHugoGeneSymbol("hugo1"); + mutSig1.setqValue(BigDecimal.valueOf(0.01)); + + Map mutSigs = new HashMap<>(); + mutSigs.put("hugo1", mutSig1); + + List result = + AlterationCountServiceUtil.updateAlterationCountsWithMutSigQValue(counts, mutSigs); + + assertEquals(BigDecimal.valueOf(0.01), result.get(0).getqValue()); + assertEquals(null, result.get(1).getqValue()); + } + + @Test + public void testUpdateAlterationCountsWithCNASigQValue() { + CopyNumberCountByGene count1 = new CopyNumberCountByGene(); + count1.setHugoGeneSymbol("hugo1"); + count1.setAlteration(2); + + CopyNumberCountByGene count2 = new CopyNumberCountByGene(); + count2.setHugoGeneSymbol("hugo2"); + count2.setAlteration(-2); + + List counts = Arrays.asList(count1, count2); + + Gistic gistic1 = new Gistic(); + gistic1.setqValue(BigDecimal.valueOf(0.01)); + + Map, Gistic> gisticMap = new HashMap<>(); + gisticMap.put(Pair.create("hugo1", 2), gistic1); + + List result = + AlterationCountServiceUtil.updateAlterationCountsWithCNASigQValue(counts, gisticMap); + + assertEquals(BigDecimal.valueOf(0.01), result.get(0).getqValue()); + assertEquals(null, result.get(1).getqValue()); + } + + @Test + public void testGetFirstMolecularProfileGroupedByStudy() { + MolecularProfile profile1 = new MolecularProfile(); + profile1.setCancerStudyIdentifier("study1"); + profile1.setMolecularProfileId(1); + + MolecularProfile profile2 = new MolecularProfile(); + profile2.setCancerStudyIdentifier("study1"); + profile2.setMolecularProfileId(2); + + MolecularProfile profile3 = new MolecularProfile(); + profile3.setCancerStudyIdentifier("study2"); + profile3.setMolecularProfileId(3); + + List profiles = Arrays.asList(profile1, profile2, profile3); + + List result = + AlterationCountServiceUtil.getFirstMolecularProfileGroupedByStudy(profiles); + + assertEquals(2, result.size()); + + MolecularProfile resultProfile1 = + result.stream() + .filter(profile -> profile.getCancerStudyIdentifier().equals("study1")) + .findFirst() + .orElse(null); + assertEquals(Integer.valueOf(1), resultProfile1.getMolecularProfileId()); + + MolecularProfile resultProfile2 = + result.stream() + .filter(profile -> profile.getCancerStudyIdentifier().equals("study2")) + .findFirst() + .orElse(null); + assertEquals(Integer.valueOf(3), resultProfile2.getMolecularProfileId()); + } + + @Test + public void testCombineAlterationCountsWithConflictingHugoSymbols() { + AlterationCountByGene count1 = new AlterationCountByGene(); + count1.setHugoGeneSymbol("hugo1"); + count1.setNumberOfAlteredCases(5); + count1.setTotalCount(10); + + AlterationCountByGene count2 = new AlterationCountByGene(); + count2.setHugoGeneSymbol("hugo1"); + count2.setNumberOfAlteredCases(3); + count2.setTotalCount(6); + + AlterationCountByGene count3 = new AlterationCountByGene(); + count3.setHugoGeneSymbol("hugo2"); + count3.setNumberOfAlteredCases(2); + count3.setTotalCount(4); + + List counts = Arrays.asList(count1, count2, count3); + + List combinedCounts = + AlterationCountServiceUtil.combineAlterationCountsWithConflictingHugoSymbols(counts); + + assertEquals(2, combinedCounts.size()); + + AlterationCountByGene combinedCount1 = + combinedCounts.stream() + .filter(count -> count.getHugoGeneSymbol().equals("hugo1")) + .findFirst() + .orElse(null); + assertEquals(8, combinedCount1.getNumberOfAlteredCases().intValue()); + assertEquals(16, combinedCount1.getTotalCount().intValue()); + + AlterationCountByGene combinedCount2 = + combinedCounts.stream() + .filter(count -> count.getHugoGeneSymbol().equals("hugo2")) + .findFirst() + .orElse(null); + assertEquals(2, combinedCount2.getNumberOfAlteredCases().intValue()); + assertEquals(4, combinedCount2.getTotalCount().intValue()); + } + + @Test + public void testCombineCopyNumberCountsWithConflictingHugoSymbols() { + CopyNumberCountByGene count1 = new CopyNumberCountByGene(); + count1.setHugoGeneSymbol("hugo1"); + count1.setAlteration(1); + count1.setNumberOfAlteredCases(5); + count1.setTotalCount(10); + + CopyNumberCountByGene count2 = new CopyNumberCountByGene(); + count2.setHugoGeneSymbol("hugo1"); + count2.setAlteration(1); + count2.setNumberOfAlteredCases(3); + count2.setTotalCount(6); + + CopyNumberCountByGene count3 = new CopyNumberCountByGene(); + count3.setHugoGeneSymbol("hugo2"); + count3.setAlteration(2); + count3.setNumberOfAlteredCases(2); + count3.setTotalCount(4); + + List counts = Arrays.asList(count1, count2, count3); + + List result = + AlterationCountServiceUtil.combineCopyNumberCountsWithConflictingHugoSymbols(counts); + + assertEquals(2, result.size()); + + CopyNumberCountByGene combinedCount1 = + result.stream().filter(c -> c.getHugoGeneSymbol().equals("hugo1")).findFirst().orElse(null); + assertEquals(8, combinedCount1.getNumberOfAlteredCases().intValue()); + assertEquals(16, combinedCount1.getTotalCount().intValue()); + + CopyNumberCountByGene combinedCount2 = + result.stream().filter(c -> c.getHugoGeneSymbol().equals("hugo2")).findFirst().orElse(null); + assertEquals(2, combinedCount2.getNumberOfAlteredCases().intValue()); + assertEquals(4, combinedCount2.getTotalCount().intValue()); + } + + @Test + public void testHasGenePanelData() { + // Test with Whole Exome Sequencing and other panels + Set genePanelIds1 = Set.of("WES", "panel1"); + assertTrue(AlterationCountServiceUtil.hasGenePanelData(genePanelIds1)); + + // Test with only Whole Exome Sequencing + Set genePanelIds2 = Set.of("WES"); + assertFalse(AlterationCountServiceUtil.hasGenePanelData(genePanelIds2)); + + // Test with other panels + Set genePanelIds3 = Set.of("panel1", "panel2"); + assertTrue(AlterationCountServiceUtil.hasGenePanelData(genePanelIds3)); + + // Test with empty set + Set genePanelIds4 = Set.of(); + assertFalse(AlterationCountServiceUtil.hasGenePanelData(genePanelIds4)); + } + + @Test + public void testSetupGisticMap() { + // Single Gistic with amplification + Gistic gistic1 = new Gistic(); + gistic1.setAmp(true); + gistic1.setqValue(BigDecimal.valueOf(0.01)); + GisticToGene gene1 = new GisticToGene(); + gene1.setHugoGeneSymbol("hugo1"); + gistic1.setGenes(List.of(gene1)); + + // Single Gistic without amplification + Gistic gistic2 = new Gistic(); + gistic2.setAmp(false); + gistic2.setqValue(BigDecimal.valueOf(0.02)); + GisticToGene gene2 = new GisticToGene(); + gene2.setHugoGeneSymbol("hugo2"); + gistic2.setGenes(List.of(gene2)); + + // Multiple Gistics for the same gene with different qValues + Gistic gistic3 = new Gistic(); + gistic3.setAmp(true); + gistic3.setqValue(BigDecimal.valueOf(0.03)); + GisticToGene gene3 = new GisticToGene(); + gene3.setHugoGeneSymbol("hugo1"); + gistic3.setGenes(List.of(gene3)); + + List gisticList = List.of(gistic1, gistic2, gistic3); + Map, Gistic> gisticMap = new HashMap<>(); + + AlterationCountServiceUtil.setupGisticMap(gisticList, gisticMap); + + assertEquals(2, gisticMap.size()); + assertTrue(gisticMap.containsKey(Pair.create("hugo1", 2))); + assertTrue(gisticMap.containsKey(Pair.create("hugo2", -2))); + assertEquals( + gistic1, + gisticMap.get( + Pair.create("hugo1", 2))); // gistic1 should be chosen over gistic3 due to lower qValue + assertEquals(gistic2, gisticMap.get(Pair.create("hugo2", -2))); + } + + @Test + public void testSetupAlterationGeneCountsMapWithAlterationCountByGene() { + AlterationCountByGene datum1 = new AlterationCountByGene(); + datum1.setHugoGeneSymbol("hugo1"); + datum1.setTotalCount(1); + datum1.setNumberOfAlteredCases(1); + datum1.setNumberOfProfiledCases(1); + datum1.setMatchingGenePanelIds(new HashSet<>(Arrays.asList("panel1"))); + + AlterationCountByGene datum2 = new AlterationCountByGene(); + datum2.setHugoGeneSymbol("hugo1"); + datum2.setTotalCount(2); + datum2.setNumberOfAlteredCases(2); + datum2.setNumberOfProfiledCases(2); + datum2.setMatchingGenePanelIds(new HashSet<>(Arrays.asList("panel2"))); + + AlterationCountByGene datum3 = new AlterationCountByGene(); + datum3.setHugoGeneSymbol("hugo2"); + datum3.setTotalCount(3); + datum3.setNumberOfAlteredCases(3); + datum3.setNumberOfProfiledCases(3); + datum3.setMatchingGenePanelIds(new HashSet<>(Arrays.asList("panel3"))); + + List studyAlterationCountByGenes = Arrays.asList(datum1, datum2, datum3); + Map totalResult = new HashMap<>(); + + AlterationCountServiceUtil.setupAlterationGeneCountsMap( + studyAlterationCountByGenes, totalResult); + + assertEquals(2, totalResult.size()); + assertTrue(totalResult.containsKey("hugo1")); + assertTrue(totalResult.containsKey("hugo2")); + + AlterationCountByGene result1 = totalResult.get("hugo1"); + assertEquals(3L, (long) result1.getTotalCount()); + assertEquals(3L, (long) result1.getNumberOfAlteredCases()); + assertEquals(3L, (long) result1.getNumberOfProfiledCases()); + assertTrue(result1.getMatchingGenePanelIds().contains("panel1")); + assertTrue(result1.getMatchingGenePanelIds().contains("panel2")); + + AlterationCountByGene result2 = totalResult.get("hugo2"); + assertEquals(3L, (long) result2.getTotalCount()); + assertEquals(3L, (long) result2.getNumberOfAlteredCases()); + assertEquals(3L, (long) result2.getNumberOfProfiledCases()); + assertTrue(result2.getMatchingGenePanelIds().contains("panel3")); + } + + @Test + public void testSetupAlterationGeneCountsMapWithAlterationCountByStructuralVariant() { + AlterationCountByStructuralVariant datum1 = new AlterationCountByStructuralVariant(); + datum1.setGene1HugoGeneSymbol("hugo1"); + datum1.setGene2HugoGeneSymbol("hugo2"); + datum1.setTotalCount(1); + datum1.setNumberOfAlteredCases(1); + datum1.setNumberOfProfiledCases(1); + datum1.setMatchingGenePanelIds(new HashSet<>(Arrays.asList("panel1"))); + + AlterationCountByStructuralVariant datum2 = new AlterationCountByStructuralVariant(); + datum2.setGene1HugoGeneSymbol("hugo1"); + datum2.setGene2HugoGeneSymbol("hugo2"); + datum2.setTotalCount(2); + datum2.setNumberOfAlteredCases(2); + datum2.setNumberOfProfiledCases(2); + datum2.setMatchingGenePanelIds(new HashSet<>(Arrays.asList("panel2"))); + + AlterationCountByStructuralVariant datum3 = new AlterationCountByStructuralVariant(); + datum3.setGene1HugoGeneSymbol("hugo3"); + datum3.setGene2HugoGeneSymbol("hugo4"); + datum3.setTotalCount(3); + datum3.setNumberOfAlteredCases(3); + datum3.setNumberOfProfiledCases(3); + datum3.setMatchingGenePanelIds(new HashSet<>(Arrays.asList("panel3"))); + + List studyAlterationCountByGenes = + Arrays.asList(datum1, datum2, datum3); + Map totalResult = new HashMap<>(); + + AlterationCountServiceUtil.setupAlterationGeneCountsMap( + studyAlterationCountByGenes, totalResult); + + assertEquals(2, totalResult.size()); + assertTrue(totalResult.containsKey("hugo1::hugo2")); + assertTrue(totalResult.containsKey("hugo3::hugo4")); + + AlterationCountByStructuralVariant result1 = totalResult.get("hugo1::hugo2"); + assertEquals(3L, (long) result1.getTotalCount()); + assertEquals(3L, (long) result1.getNumberOfAlteredCases()); + assertEquals(3L, (long) result1.getNumberOfProfiledCases()); + assertTrue(result1.getMatchingGenePanelIds().contains("panel1")); + assertTrue(result1.getMatchingGenePanelIds().contains("panel2")); + + AlterationCountByStructuralVariant result2 = totalResult.get("hugo3::hugo4"); + assertEquals(3L, (long) result2.getTotalCount()); + assertEquals(3L, (long) result2.getNumberOfAlteredCases()); + assertEquals(3L, (long) result2.getNumberOfProfiledCases()); + assertTrue(result2.getMatchingGenePanelIds().contains("panel3")); + } + + @Test + public void testSetupAlterationGeneCountsMapWithCopyNumberCountByGene() { + CopyNumberCountByGene datum1 = new CopyNumberCountByGene(); + datum1.setEntrezGeneId(1); + datum1.setAlteration(2); + datum1.setTotalCount(1); + datum1.setNumberOfAlteredCases(1); + datum1.setNumberOfProfiledCases(1); + datum1.setMatchingGenePanelIds(new HashSet<>(Arrays.asList("panel1"))); + + CopyNumberCountByGene datum2 = new CopyNumberCountByGene(); + datum2.setEntrezGeneId(1); + datum2.setAlteration(2); + datum2.setTotalCount(2); + datum2.setNumberOfAlteredCases(2); + datum2.setNumberOfProfiledCases(2); + datum2.setMatchingGenePanelIds(new HashSet<>(Arrays.asList("panel2"))); + + CopyNumberCountByGene datum3 = new CopyNumberCountByGene(); + datum3.setEntrezGeneId(2); + datum3.setAlteration(-2); + datum3.setTotalCount(3); + datum3.setNumberOfAlteredCases(3); + datum3.setNumberOfProfiledCases(3); + datum3.setMatchingGenePanelIds(new HashSet<>(Arrays.asList("panel3"))); + + List studyAlterationCountByGenes = Arrays.asList(datum1, datum2, datum3); + Map totalResult = new HashMap<>(); + + AlterationCountServiceUtil.setupAlterationGeneCountsMap( + studyAlterationCountByGenes, totalResult); + + assertEquals(2, totalResult.size()); + assertTrue(totalResult.containsKey("12")); + assertTrue(totalResult.containsKey("2-2")); + + CopyNumberCountByGene result1 = totalResult.get("12"); + assertEquals(3L, (long) result1.getTotalCount()); + assertEquals(3L, (long) result1.getNumberOfAlteredCases()); + assertEquals(3L, (long) result1.getNumberOfProfiledCases()); + assertTrue(result1.getMatchingGenePanelIds().contains("panel1")); + assertTrue(result1.getMatchingGenePanelIds().contains("panel2")); + + CopyNumberCountByGene result2 = totalResult.get("2-2"); + assertEquals(3L, (long) result2.getTotalCount()); + assertEquals(3L, (long) result2.getNumberOfAlteredCases()); + assertEquals(3L, (long) result2.getNumberOfProfiledCases()); + assertTrue(result2.getMatchingGenePanelIds().contains("panel3")); + } +} diff --git a/src/test/java/org/cbioportal/legacy/service/util/AlterationEnrichmentUtilTest.java b/src/test/java/org/cbioportal/legacy/service/util/AlterationEnrichmentUtilTest.java new file mode 100644 index 00000000000..2a7088fd97e --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/service/util/AlterationEnrichmentUtilTest.java @@ -0,0 +1,208 @@ +package org.cbioportal.legacy.service.util; + +import java.math.BigDecimal; +import java.util.*; +import org.apache.commons.math3.util.Pair; +import org.cbioportal.legacy.model.AlterationCountByGene; +import org.cbioportal.legacy.model.AlterationEnrichment; +import org.cbioportal.legacy.model.Gene; +import org.cbioportal.legacy.model.MolecularProfileCaseIdentifier; +import org.cbioportal.legacy.service.GeneService; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.*; +import org.mockito.junit.MockitoJUnitRunner; + +@RunWith(MockitoJUnitRunner.class) +public class AlterationEnrichmentUtilTest { + + @InjectMocks private AlterationEnrichmentUtil alterationEnrichmentUtil; + + @Mock private FisherExactTestCalculator fisherExactTestCalculator; + @Mock private GeneService geneService; + @Mock private ProfiledCasesCounter profiledCasesCounter; + + @Test + public void createAlterationEnrichments() throws Exception { + + // create molecularProfileCaseSet1, molecularProfileCaseSet2 list of entities + MolecularProfileCaseIdentifier molecularProfileCase1 = new MolecularProfileCaseIdentifier(); + molecularProfileCase1.setCaseId("sample_id_1"); + molecularProfileCase1.setMolecularProfileId("test1_cna"); + MolecularProfileCaseIdentifier molecularProfileCase2 = new MolecularProfileCaseIdentifier(); + molecularProfileCase2.setCaseId("sample_id_2"); + molecularProfileCase2.setMolecularProfileId("test2_cna"); + List molecularProfileCaseSet1 = new ArrayList<>(); + molecularProfileCaseSet1.add(molecularProfileCase1); + molecularProfileCaseSet1.add(molecularProfileCase2); + + MolecularProfileCaseIdentifier molecularProfileCase3 = new MolecularProfileCaseIdentifier(); + molecularProfileCase3.setCaseId("sample_id_3"); + molecularProfileCase3.setMolecularProfileId("test3_cna"); + MolecularProfileCaseIdentifier molecularProfileCase4 = new MolecularProfileCaseIdentifier(); + molecularProfileCase4.setCaseId("sample_id_4"); + molecularProfileCase4.setMolecularProfileId("test4_cna"); + List molecularProfileCaseSet2 = new ArrayList<>(); + molecularProfileCaseSet2.add(molecularProfileCase3); + molecularProfileCaseSet2.add(molecularProfileCase4); + + MolecularProfileCaseIdentifier molecularProfileCase5 = new MolecularProfileCaseIdentifier(); + molecularProfileCase3.setCaseId("sample_id_5"); + molecularProfileCase3.setMolecularProfileId("test5_cna"); + MolecularProfileCaseIdentifier molecularProfileCase6 = new MolecularProfileCaseIdentifier(); + molecularProfileCase4.setCaseId("sample_id_6"); + molecularProfileCase4.setMolecularProfileId("test6_cna"); + List molecularProfileCaseSet3 = new ArrayList<>(); + molecularProfileCaseSet3.add(molecularProfileCase5); + molecularProfileCaseSet3.add(molecularProfileCase6); + + Map> groupMolecularProfileCaseSets = + new HashMap>(); + groupMolecularProfileCaseSets.put("group1", molecularProfileCaseSet1); + groupMolecularProfileCaseSets.put("group2", molecularProfileCaseSet2); + + AlterationCountByGene alterationSampleCountByGene1 = new AlterationCountByGene(); + alterationSampleCountByGene1.setEntrezGeneId(2); + alterationSampleCountByGene1.setNumberOfAlteredCases(1); + alterationSampleCountByGene1.setNumberOfProfiledCases(2); + AlterationCountByGene alterationSampleCount1ByGene1 = new AlterationCountByGene(); + alterationSampleCount1ByGene1.setEntrezGeneId(3); + alterationSampleCount1ByGene1.setNumberOfAlteredCases(0); + alterationSampleCount1ByGene1.setNumberOfProfiledCases(2); + + AlterationCountByGene alterationSampleCountByGene2 = new AlterationCountByGene(); + alterationSampleCountByGene2.setEntrezGeneId(3); + alterationSampleCountByGene2.setNumberOfAlteredCases(2); + alterationSampleCountByGene2.setNumberOfProfiledCases(2); + AlterationCountByGene alterationSampleCount1ByGene2 = new AlterationCountByGene(); + alterationSampleCount1ByGene2.setEntrezGeneId(2); + alterationSampleCount1ByGene2.setNumberOfAlteredCases(0); + alterationSampleCount1ByGene2.setNumberOfProfiledCases(2); + + List genes = new ArrayList<>(); + Gene gene1 = new Gene(); + gene1.setEntrezGeneId(2); + gene1.setHugoGeneSymbol("HUGO2"); + gene1.setGeneticEntityId(2); + genes.add(gene1); + Gene gene2 = new Gene(); + gene2.setEntrezGeneId(3); + gene2.setHugoGeneSymbol("HUGO3"); + gene2.setGeneticEntityId(3); + genes.add(gene2); + + Mockito.when(geneService.fetchGenes(Arrays.asList("2", "3"), "ENTREZ_GENE_ID", "SUMMARY")) + .thenReturn(genes); + + Map, Long>> mutationCountsbyEntrezGeneIdAndGroup = + new HashMap<>(); + mutationCountsbyEntrezGeneIdAndGroup.put( + "group1", + new Pair, Long>( + Arrays.asList(alterationSampleCountByGene1, alterationSampleCount1ByGene1), 0L)); + mutationCountsbyEntrezGeneIdAndGroup.put( + "group2", + new Pair, Long>( + Arrays.asList(alterationSampleCountByGene2, alterationSampleCount1ByGene2), 0L)); + + // START: for 2 groups + + Mockito.when(fisherExactTestCalculator.getTwoTailedPValue(1, 1, 2, 0)).thenReturn(1.0); + Mockito.when(fisherExactTestCalculator.getTwoTailedPValue(2, 0, 0, 2)).thenReturn(0.3); + + List result = + alterationEnrichmentUtil.createAlterationEnrichments(mutationCountsbyEntrezGeneIdAndGroup); + + Assert.assertEquals(2, result.size()); + AlterationEnrichment alterationEnrichment1 = result.get(0); + Assert.assertEquals((Integer) 2, alterationEnrichment1.getEntrezGeneId()); + Assert.assertEquals("HUGO2", alterationEnrichment1.getHugoGeneSymbol()); + Assert.assertEquals(null, alterationEnrichment1.getCytoband()); + Assert.assertEquals(2, alterationEnrichment1.getCounts().size()); + Assert.assertEquals(new BigDecimal("1.0"), alterationEnrichment1.getpValue()); + alterationEnrichment1 + .getCounts() + .forEach( + countSummary -> { + if (countSummary.getName().equals("group2")) { + Assert.assertEquals((Integer) 0, countSummary.getAlteredCount()); + } else if (countSummary.getName().equals("group1")) { + Assert.assertEquals((Integer) 1, countSummary.getAlteredCount()); + } + }); + + AlterationEnrichment alterationEnrichment2 = result.get(1); + Assert.assertEquals((Integer) 3, alterationEnrichment2.getEntrezGeneId()); + Assert.assertEquals("HUGO3", alterationEnrichment2.getHugoGeneSymbol()); + Assert.assertEquals(null, alterationEnrichment2.getCytoband()); + Assert.assertEquals(2, alterationEnrichment2.getCounts().size()); + Assert.assertEquals(new BigDecimal("0.3"), alterationEnrichment2.getpValue()); + alterationEnrichment2 + .getCounts() + .forEach( + countSummary -> { + if (countSummary.getName().equals("group2")) { + Assert.assertEquals((Integer) 2, countSummary.getAlteredCount()); + } else if (countSummary.getName().equals("group1")) { + Assert.assertEquals((Integer) 0, countSummary.getAlteredCount()); + } + }); + + // END: for 2 groups + + // START: for 3 groups + + groupMolecularProfileCaseSets.put("group3", molecularProfileCaseSet3); + mutationCountsbyEntrezGeneIdAndGroup.put( + "group3", + new Pair, Long>( + Arrays.asList(alterationSampleCountByGene1, alterationSampleCountByGene2), 0L)); + + result = + alterationEnrichmentUtil.createAlterationEnrichments(mutationCountsbyEntrezGeneIdAndGroup); + + Assert.assertEquals(2, result.size()); + alterationEnrichment1 = result.get(0); + Assert.assertEquals((Integer) 2, alterationEnrichment1.getEntrezGeneId()); + Assert.assertEquals("HUGO2", alterationEnrichment1.getHugoGeneSymbol()); + Assert.assertEquals(null, alterationEnrichment1.getCytoband()); + Assert.assertEquals(3, alterationEnrichment1.getCounts().size()); + + Assert.assertEquals(new BigDecimal("0.4723665527410149"), alterationEnrichment1.getpValue()); + alterationEnrichment1 + .getCounts() + .forEach( + countSummary -> { + if (countSummary.getName().equals("group3")) { + Assert.assertEquals((Integer) 1, countSummary.getAlteredCount()); + } else if (countSummary.getName().equals("group2")) { + Assert.assertEquals((Integer) 0, countSummary.getAlteredCount()); + } else if (countSummary.getName().equals("group1")) { + Assert.assertEquals((Integer) 1, countSummary.getAlteredCount()); + } + }); + + alterationEnrichment2 = result.get(1); + Assert.assertEquals((Integer) 3, alterationEnrichment2.getEntrezGeneId()); + Assert.assertEquals("HUGO3", alterationEnrichment2.getHugoGeneSymbol()); + Assert.assertEquals(null, alterationEnrichment2.getCytoband()); + Assert.assertEquals(3, alterationEnrichment2.getCounts().size()); + + Assert.assertEquals(new BigDecimal("0.04978706836786395"), alterationEnrichment2.getpValue()); + alterationEnrichment2 + .getCounts() + .forEach( + countSummary -> { + if (countSummary.getName().equals("group3")) { + Assert.assertEquals((Integer) 2, countSummary.getAlteredCount()); + } else if (countSummary.getName().equals("group2")) { + Assert.assertEquals((Integer) 2, countSummary.getAlteredCount()); + } else if (countSummary.getName().equals("group1")) { + Assert.assertEquals((Integer) 0, countSummary.getAlteredCount()); + } + }); + + // END: for 3 groups + } +} diff --git a/src/test/java/org/cbioportal/legacy/service/util/CoExpressionAsyncMethodsTest.java b/src/test/java/org/cbioportal/legacy/service/util/CoExpressionAsyncMethodsTest.java new file mode 100644 index 00000000000..bdd03a3b86a --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/service/util/CoExpressionAsyncMethodsTest.java @@ -0,0 +1,120 @@ +package org.cbioportal.legacy.service.util; + +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Objects; +import java.util.concurrent.CompletableFuture; +import java.util.stream.Collectors; +import org.cbioportal.legacy.model.CoExpression; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.junit.MockitoJUnitRunner; + +@RunWith(MockitoJUnitRunner.class) +public class CoExpressionAsyncMethodsTest { + + private static final double THRESHOLD = 0.3; + + @InjectMocks private CoExpressionAsyncMethods asyncMethods; + + @Test + public void computeGeneCoExpressions() throws Exception { + + List> futures = new ArrayList<>(); + List> allValuesA = createAllValuesA(); + List valuesB = createValuesB(); + + CompletableFuture future1 = + asyncMethods.computeCoExpression("2", allValuesA.get(0), valuesB, THRESHOLD); + CompletableFuture future2 = + asyncMethods.computeCoExpression("3", allValuesA.get(1), valuesB, THRESHOLD); + CompletableFuture future3 = + asyncMethods.computeCoExpression("4", allValuesA.get(2), valuesB, THRESHOLD); + + futures.add(future1); + futures.add(future2); + futures.add(future3); + List result = + futures.stream() + .filter(Objects::nonNull) + .map(CompletableFuture::join) + .collect(Collectors.toList()); + + Assert.assertEquals(2, result.size()); + CoExpression coExpression1 = result.get(0); + Assert.assertEquals("2", coExpression1.getGeneticEntityId()); + Assert.assertEquals(new BigDecimal("0.5"), coExpression1.getSpearmansCorrelation()); + Assert.assertEquals(new BigDecimal("0.6666666666666667"), coExpression1.getpValue()); + CoExpression coExpression2 = result.get(1); + Assert.assertEquals("3", coExpression2.getGeneticEntityId()); + Assert.assertEquals( + new BigDecimal("0.8660254037844386"), coExpression2.getSpearmansCorrelation()); + Assert.assertEquals(new BigDecimal("0.3333333333333333"), coExpression2.getpValue()); + } + + @Test + public void computeGenesetCoExpressions() throws Exception { + + List> futures = new ArrayList<>(); + List> allValuesA = createAllValuesA(); + List valuesB = createValuesB(); + + CompletableFuture future1 = + asyncMethods.computeCoExpression( + "KEGG_DNA_REPLICATION", allValuesA.get(1), valuesB, THRESHOLD); + CompletableFuture future2 = + asyncMethods.computeCoExpression( + "BIOCARTA_ASBCELL_PATHWAY", allValuesA.get(0), valuesB, THRESHOLD); + CompletableFuture future3 = + asyncMethods.computeCoExpression( + "REACTOME_DIGESTION_OF_DIETARY_CARBOHYDRATE", allValuesA.get(2), valuesB, THRESHOLD); + + futures.add(future1); + futures.add(future2); + futures.add(future3); + List result = + futures.stream() + .filter(Objects::nonNull) + .map(CompletableFuture::join) + .collect(Collectors.toList()); + + Assert.assertEquals(2, result.size()); + CoExpression coExpression1 = result.get(0); + Assert.assertEquals("KEGG_DNA_REPLICATION", coExpression1.getGeneticEntityId()); + Assert.assertEquals( + new BigDecimal("0.8660254037844386"), coExpression1.getSpearmansCorrelation()); + Assert.assertEquals(new BigDecimal("0.3333333333333333"), coExpression1.getpValue()); + CoExpression coExpression2 = result.get(1); + Assert.assertEquals("BIOCARTA_ASBCELL_PATHWAY", coExpression2.getGeneticEntityId()); + Assert.assertEquals(new BigDecimal("0.5"), coExpression2.getSpearmansCorrelation()); + Assert.assertEquals(new BigDecimal("0.6666666666666667"), coExpression2.getpValue()); + } + + private List> createAllValuesA() { + List> allValuesA = new ArrayList<>(); + List valuesA1 = new ArrayList<>(); + valuesA1.add("2"); + valuesA1.add("3"); + valuesA1.add("2"); + allValuesA.add(valuesA1); + List valuesA2 = new ArrayList<>(); + valuesA2.add("1.1"); + valuesA2.add("5"); + valuesA2.add("3"); + allValuesA.add(valuesA2); + List valuesA3 = new ArrayList<>(); + valuesA3.add("1"); + valuesA3.add("4"); + valuesA3.add("0"); + allValuesA.add(valuesA3); + return allValuesA; + } + + private List createValuesB() { + return new ArrayList<>(Arrays.asList("2.1", "3", "3")); + } +} diff --git a/src/test/java/org/cbioportal/legacy/service/util/JwtUtilsTest.java b/src/test/java/org/cbioportal/legacy/service/util/JwtUtilsTest.java new file mode 100644 index 00000000000..3a984c26b80 --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/service/util/JwtUtilsTest.java @@ -0,0 +1,156 @@ +/* + * Copyright (c) 2018 Memorial Sloan-Kettering Cancer Center. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS + * FOR A PARTICULAR PURPOSE. The software and documentation provided hereunder + * is on an "as is" basis, and Memorial Sloan-Kettering Cancer Center has no + * obligations to provide maintenance, support, updates, enhancements or + * modifications. In no event shall Memorial Sloan-Kettering Cancer Center be + * liable to any party for direct, indirect, special, incidental or + * consequential damages, including lost profits, arising out of the use of this + * software and its documentation, even if Memorial Sloan-Kettering Cancer + * Center has been advised of the possibility of such damage. + */ + +/* + * Copyright 2002-2018 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * This file is part of cBioPortal. + * + * cBioPortal is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package org.cbioportal.legacy.service.util; + +// TODO package org.cbioportal.security.spring.authentication.token; + +import java.util.*; +import org.cbioportal.legacy.service.exception.InvalidDataAccessTokenException; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit4.SpringRunner; + +@TestPropertySource( + properties = { + "dat.jwt.secret_key = +NbopXzb/AIQNrVEGzxzP5CF42e5drvrXTQot3gfW/s=", + "dat.ttl_seconds = 2" + }, + inheritLocations = false) +@ContextConfiguration(classes = JwtUtilsTestConfiguration.class) +@RunWith(SpringRunner.class) +public class JwtUtilsTest { + + /* Several tests in this class rely on proper singing of tokens using the key embedded in the TestPropertySource annotation above. If that value is changed, the expected values should also be recomputed. + */ + @Autowired private JwtUtils jwtUtils; + + private static final String TEST_SUBJECT = "testSubject"; + private static final long TEST_TOKEN_EXPIRATION_MILLISECONDS = 2000L; + + @Test + public void createTokenTest() { + String token = jwtUtils.createToken(TEST_SUBJECT).getToken(); + if (token.isEmpty()) { + Assert.fail("token was empty"); + } + if (!token.matches("^\\S+\\.\\S+\\.\\S+$")) { + Assert.fail("generated token does not have proper format"); + } + } + + @Test(expected = IllegalArgumentException.class) + public void createInvalidTokenTest() { + String token = jwtUtils.createToken("").getToken(); + } + + @Test + public void validateValidTokenTest() throws InvalidDataAccessTokenException { + String token = jwtUtils.createToken(TEST_SUBJECT).getToken(); + jwtUtils.validate(token); // when token is valid, there will be no exception thrown + } + + @Test(expected = InvalidDataAccessTokenException.class) + public void validateBadSignatureTokenTest() throws InvalidDataAccessTokenException { + String token = jwtUtils.createToken(TEST_SUBJECT).getToken(); + int finalDividerIndex = token.lastIndexOf("."); + String badSignature = ""; + for (int i = 0; i < token.length() - finalDividerIndex - 1; i++) { + badSignature = badSignature + "A"; + } + String badSignatureToken = token.substring(0, finalDividerIndex + 1) + badSignature; + jwtUtils.validate(badSignatureToken); + } + + @Test(expected = InvalidDataAccessTokenException.class) + public void validateExpiredTokenTest() + throws InvalidDataAccessTokenException, InterruptedException { + String token = jwtUtils.createToken(TEST_SUBJECT).getToken(); + Thread.sleep( + TEST_TOKEN_EXPIRATION_MILLISECONDS + + 10L); // NOTE: sleep time must be adequate to allow created token to expire + jwtUtils.validate(token); + } + + @Test + public void extractSubjectTest() throws InvalidDataAccessTokenException { + String token = jwtUtils.createToken(TEST_SUBJECT).getToken(); + String extractedSubject = jwtUtils.extractSubject(token); + if (extractedSubject.isEmpty() || !extractedSubject.equals(TEST_SUBJECT)) { + Assert.fail("extracted subject does not match expected value"); + } + } + + @Test + public void extractExpirationDateTest() throws InvalidDataAccessTokenException { + Date now = new Date(); + long nowTime = now.getTime(); + String token = jwtUtils.createToken(TEST_SUBJECT).getToken(); + Date extractedExpirationDate = jwtUtils.extractExpirationDate(token); + long expirationTime = extractedExpirationDate.getTime(); + long timeDifference = expirationTime - nowTime; + if (extractedExpirationDate == null + || timeDifference > TEST_TOKEN_EXPIRATION_MILLISECONDS + 10L + || timeDifference < 0) { + Assert.fail("extracted expiration date is not in the expected range"); + } + } + + @Test + public void extractPropertiesTest() throws InvalidDataAccessTokenException { + String token = jwtUtils.createToken(TEST_SUBJECT).getToken(); + Map extractedProperties = jwtUtils.extractProperties(token); + if (extractedProperties == null || extractedProperties.keySet().size() < 3) { + Assert.fail("extracted properties is not large enough (at least 3 keys were expected)"); + } + } +} diff --git a/src/test/java/org/cbioportal/service/util/JwtUtilsTestConfiguration.java b/src/test/java/org/cbioportal/legacy/service/util/JwtUtilsTestConfiguration.java similarity index 92% rename from src/test/java/org/cbioportal/service/util/JwtUtilsTestConfiguration.java rename to src/test/java/org/cbioportal/legacy/service/util/JwtUtilsTestConfiguration.java index 5322922a2d6..bd31f1fb6d4 100644 --- a/src/test/java/org/cbioportal/service/util/JwtUtilsTestConfiguration.java +++ b/src/test/java/org/cbioportal/legacy/service/util/JwtUtilsTestConfiguration.java @@ -44,10 +44,11 @@ * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . -*/ + */ + +package org.cbioportal.legacy.service.util; -package org.cbioportal.service.util; -//TODO package org.cbioportal.security.spring.authentication.token; +// TODO package org.cbioportal.security.spring.authentication.token; import org.springframework.boot.test.context.TestConfiguration; import org.springframework.context.annotation.Bean; @@ -55,8 +56,8 @@ @TestConfiguration public class JwtUtilsTestConfiguration { - @Bean - public JwtUtils jwtUtils() { - return new JwtUtils(); - } + @Bean + public JwtUtils jwtUtils() { + return new JwtUtils(); + } } diff --git a/src/test/java/org/cbioportal/legacy/service/util/MolecularProfileUtilTest.java b/src/test/java/org/cbioportal/legacy/service/util/MolecularProfileUtilTest.java new file mode 100644 index 00000000000..d0ed0088a78 --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/service/util/MolecularProfileUtilTest.java @@ -0,0 +1,244 @@ +package org.cbioportal.legacy.service.util; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Optional; +import java.util.function.Predicate; +import org.cbioportal.legacy.model.MolecularProfile; +import org.cbioportal.legacy.model.MolecularProfileCaseIdentifier; +import org.cbioportal.legacy.service.impl.BaseServiceImplTest; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.junit.MockitoJUnitRunner; + +@RunWith(MockitoJUnitRunner.class) +public class MolecularProfileUtilTest { + @InjectMocks private MolecularProfileUtil molecularProfileUtil; + + @Test + public void getFirstFilteredMolecularProfileCaseIdentifiers() { + + MolecularProfile mutationMolecularProfile = new MolecularProfile(); + mutationMolecularProfile.setCancerStudyIdentifier(BaseServiceImplTest.STUDY_ID); + mutationMolecularProfile.setStableId(BaseServiceImplTest.STUDY_ID + "_mutations"); + mutationMolecularProfile.setMolecularAlterationType( + MolecularProfile.MolecularAlterationType.MUTATION_EXTENDED); + mutationMolecularProfile.setDatatype("MAF"); + + MolecularProfile structuralVariantMolecularProfile = new MolecularProfile(); + structuralVariantMolecularProfile.setCancerStudyIdentifier(BaseServiceImplTest.STUDY_ID); + structuralVariantMolecularProfile.setStableId( + BaseServiceImplTest.STUDY_ID + "_structural_variants"); + structuralVariantMolecularProfile.setMolecularAlterationType( + MolecularProfile.MolecularAlterationType.STRUCTURAL_VARIANT); + structuralVariantMolecularProfile.setDatatype("SV"); + + MolecularProfile discreteCNAMolecularProfile = new MolecularProfile(); + discreteCNAMolecularProfile.setCancerStudyIdentifier(BaseServiceImplTest.STUDY_ID); + discreteCNAMolecularProfile.setStableId(BaseServiceImplTest.STUDY_ID + "_gistic"); + discreteCNAMolecularProfile.setMolecularAlterationType( + MolecularProfile.MolecularAlterationType.COPY_NUMBER_ALTERATION); + discreteCNAMolecularProfile.setDatatype("DISCRETE"); + + MolecularProfile linearCNAMolecularProfile = new MolecularProfile(); + linearCNAMolecularProfile.setCancerStudyIdentifier(BaseServiceImplTest.STUDY_ID); + linearCNAMolecularProfile.setStableId(BaseServiceImplTest.STUDY_ID + "_linear_CNA"); + linearCNAMolecularProfile.setMolecularAlterationType( + MolecularProfile.MolecularAlterationType.COPY_NUMBER_ALTERATION); + linearCNAMolecularProfile.setDatatype("CONTINUOUS"); + + MolecularProfile continuousMRNAMolecularProfile = new MolecularProfile(); + continuousMRNAMolecularProfile.setCancerStudyIdentifier(BaseServiceImplTest.STUDY_ID); + continuousMRNAMolecularProfile.setStableId(BaseServiceImplTest.STUDY_ID + "_rna_seq_mrna"); + continuousMRNAMolecularProfile.setMolecularAlterationType( + MolecularProfile.MolecularAlterationType.MRNA_EXPRESSION); + continuousMRNAMolecularProfile.setDatatype("CONTINUOUS"); + + MolecularProfile discreteMRNAMolecularProfile = new MolecularProfile(); + discreteMRNAMolecularProfile.setCancerStudyIdentifier(BaseServiceImplTest.STUDY_ID); + discreteMRNAMolecularProfile.setStableId( + BaseServiceImplTest.STUDY_ID + "_rna_seq_mrna_median_Zscores"); + discreteMRNAMolecularProfile.setMolecularAlterationType( + MolecularProfile.MolecularAlterationType.MRNA_EXPRESSION); + discreteMRNAMolecularProfile.setDatatype("DISCRETE"); + + List studyIds = + Arrays.asList( + BaseServiceImplTest.STUDY_ID, + BaseServiceImplTest.STUDY_ID, + BaseServiceImplTest.STUDY_ID); + List sampleIds = + Arrays.asList( + BaseServiceImplTest.SAMPLE_ID1, + BaseServiceImplTest.SAMPLE_ID2, + BaseServiceImplTest.SAMPLE_ID3); + + List result = + molecularProfileUtil.getFirstFilteredMolecularProfileCaseIdentifiers( + new ArrayList<>(), studyIds, sampleIds, Optional.empty()); + // no molecular profiles + Assert.assertEquals(0, result.size()); + + List allMolecularProfiles = + Arrays.asList( + mutationMolecularProfile, + structuralVariantMolecularProfile, + discreteCNAMolecularProfile, + linearCNAMolecularProfile, + continuousMRNAMolecularProfile, + discreteMRNAMolecularProfile); + result = + molecularProfileUtil.getFirstFilteredMolecularProfileCaseIdentifiers( + allMolecularProfiles, studyIds, sampleIds, Optional.empty()); + // all molecular profiles + // return would 3(6 profiles X 3 samples) + Assert.assertEquals("all profiles", 3, result.size()); + + // filtered mutation profile case identifiers + result = + molecularProfileUtil.getFirstFilteredMolecularProfileCaseIdentifiers( + allMolecularProfiles, + studyIds, + sampleIds, + Optional.of(molecularProfileUtil.isMutationProfile)); + Assert.assertEquals("mutation profile case identifiers", 3, result.size()); + + // filtered discrete CNA profile case identifiers + result = + molecularProfileUtil.getFirstFilteredMolecularProfileCaseIdentifiers( + allMolecularProfiles, + studyIds, + sampleIds, + Optional.of(molecularProfileUtil.isDiscreteCNAMolecularProfile)); + Assert.assertEquals("discrete CNA profile case identifiers", 3, result.size()); + + // filtered structural variant profile case identifiers + result = + molecularProfileUtil.getFirstFilteredMolecularProfileCaseIdentifiers( + allMolecularProfiles, + studyIds, + sampleIds, + Optional.of(molecularProfileUtil.isStructuralVariantMolecularProfile)); + Assert.assertEquals("structural variant profile case identifiers", 3, result.size()); + } + + @Test + public void getFilteredMolecularProfileCaseIdentifiers() { + + MolecularProfile mutationMolecularProfile = new MolecularProfile(); + mutationMolecularProfile.setCancerStudyIdentifier(BaseServiceImplTest.STUDY_ID); + mutationMolecularProfile.setStableId(BaseServiceImplTest.STUDY_ID + "_mutations"); + mutationMolecularProfile.setMolecularAlterationType( + MolecularProfile.MolecularAlterationType.MUTATION_EXTENDED); + mutationMolecularProfile.setDatatype("MAF"); + + MolecularProfile structuralVariantMolecularProfile = new MolecularProfile(); + structuralVariantMolecularProfile.setCancerStudyIdentifier(BaseServiceImplTest.STUDY_ID); + structuralVariantMolecularProfile.setStableId( + BaseServiceImplTest.STUDY_ID + "_structural_variants"); + structuralVariantMolecularProfile.setMolecularAlterationType( + MolecularProfile.MolecularAlterationType.STRUCTURAL_VARIANT); + structuralVariantMolecularProfile.setDatatype("SV"); + + MolecularProfile discreteCNAMolecularProfile = new MolecularProfile(); + discreteCNAMolecularProfile.setCancerStudyIdentifier(BaseServiceImplTest.STUDY_ID); + discreteCNAMolecularProfile.setStableId(BaseServiceImplTest.STUDY_ID + "_gistic"); + discreteCNAMolecularProfile.setMolecularAlterationType( + MolecularProfile.MolecularAlterationType.COPY_NUMBER_ALTERATION); + discreteCNAMolecularProfile.setDatatype("DISCRETE"); + + MolecularProfile linearCNAMolecularProfile = new MolecularProfile(); + linearCNAMolecularProfile.setCancerStudyIdentifier(BaseServiceImplTest.STUDY_ID); + linearCNAMolecularProfile.setStableId(BaseServiceImplTest.STUDY_ID + "_linear_CNA"); + linearCNAMolecularProfile.setMolecularAlterationType( + MolecularProfile.MolecularAlterationType.COPY_NUMBER_ALTERATION); + linearCNAMolecularProfile.setDatatype("CONTINUOUS"); + + MolecularProfile continuousMRNAMolecularProfile = new MolecularProfile(); + continuousMRNAMolecularProfile.setCancerStudyIdentifier(BaseServiceImplTest.STUDY_ID); + continuousMRNAMolecularProfile.setStableId(BaseServiceImplTest.STUDY_ID + "_rna_seq_mrna"); + continuousMRNAMolecularProfile.setMolecularAlterationType( + MolecularProfile.MolecularAlterationType.MRNA_EXPRESSION); + continuousMRNAMolecularProfile.setDatatype("CONTINUOUS"); + + MolecularProfile discreteMRNAMolecularProfile = new MolecularProfile(); + discreteMRNAMolecularProfile.setCancerStudyIdentifier(BaseServiceImplTest.STUDY_ID); + discreteMRNAMolecularProfile.setStableId( + BaseServiceImplTest.STUDY_ID + "_rna_seq_mrna_median_Zscores"); + discreteMRNAMolecularProfile.setMolecularAlterationType( + MolecularProfile.MolecularAlterationType.MRNA_EXPRESSION); + discreteMRNAMolecularProfile.setDatatype("DISCRETE"); + + List studyIds = + Arrays.asList( + BaseServiceImplTest.STUDY_ID, + BaseServiceImplTest.STUDY_ID, + BaseServiceImplTest.STUDY_ID); + List sampleIds = + Arrays.asList( + BaseServiceImplTest.SAMPLE_ID1, + BaseServiceImplTest.SAMPLE_ID2, + BaseServiceImplTest.SAMPLE_ID3); + + List result = + molecularProfileUtil.getFilteredMolecularProfileCaseIdentifiers( + new ArrayList<>(), studyIds, sampleIds, Optional.empty()); + // no molecular profiles + Assert.assertEquals(0, result.size()); + + List allMolecularProfiles = + Arrays.asList( + mutationMolecularProfile, + structuralVariantMolecularProfile, + discreteCNAMolecularProfile, + linearCNAMolecularProfile, + continuousMRNAMolecularProfile, + discreteMRNAMolecularProfile); + result = + molecularProfileUtil.getFilteredMolecularProfileCaseIdentifiers( + allMolecularProfiles, studyIds, sampleIds, Optional.empty()); + // all molecular profiles + // return would 18(6 profiles X 3 samples) instead of 24(8 profiles X 3 samples) + Assert.assertEquals("all profiles", 18, result.size()); + + // filtered mutation profile case identifiers + result = + molecularProfileUtil.getFilteredMolecularProfileCaseIdentifiers( + allMolecularProfiles, + studyIds, + sampleIds, + Optional.of(molecularProfileUtil.isMutationProfile)); + Assert.assertEquals("mutation profile case identifiers", 3, result.size()); + + // filtered discrete CNA profile case identifiers + result = + molecularProfileUtil.getFilteredMolecularProfileCaseIdentifiers( + allMolecularProfiles, + studyIds, + sampleIds, + Optional.of(molecularProfileUtil.isDiscreteCNAMolecularProfile)); + Assert.assertEquals("discrete CNA profile case identifiers", 3, result.size()); + + // filtered structural variant profile case identifiers + result = + molecularProfileUtil.getFilteredMolecularProfileCaseIdentifiers( + allMolecularProfiles, + studyIds, + sampleIds, + Optional.of(molecularProfileUtil.isStructuralVariantMolecularProfile)); + Assert.assertEquals("structural variant profile case identifiers", 3, result.size()); + + // filtered MRNA expression profile case identifiers (multiple molecular profiles) + Predicate isMRNAProfile = + m -> + m.getMolecularAlterationType() + .equals(MolecularProfile.MolecularAlterationType.MRNA_EXPRESSION); + result = + molecularProfileUtil.getFilteredMolecularProfileCaseIdentifiers( + allMolecularProfiles, studyIds, sampleIds, Optional.of(isMRNAProfile)); + Assert.assertEquals("structural variant profile case identifiers", 6, result.size()); + } +} diff --git a/src/test/java/org/cbioportal/legacy/service/util/ProfiledCasesCounterTest.java b/src/test/java/org/cbioportal/legacy/service/util/ProfiledCasesCounterTest.java new file mode 100644 index 00000000000..f8b95ba54bb --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/service/util/ProfiledCasesCounterTest.java @@ -0,0 +1,136 @@ +package org.cbioportal.legacy.service.util; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import org.cbioportal.legacy.model.AlterationCountByGene; +import org.cbioportal.legacy.model.GenePanel; +import org.cbioportal.legacy.model.GenePanelData; +import org.cbioportal.legacy.model.GenePanelToGene; +import org.cbioportal.legacy.service.GenePanelService; +import org.cbioportal.legacy.service.SampleListService; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.junit.MockitoJUnitRunner; + +@RunWith(MockitoJUnitRunner.class) +public class ProfiledCasesCounterTest { + + private static final String GENE_PANEL_ID_1 = "gene_panel_id_1"; + private static final String GENE_PANEL_ID_2 = "gene_panel_id_2"; + private static final Integer ENTREZ_GENE_ID_1 = 1; + private static final Integer ENTREZ_GENE_ID_2 = 2; + private static final Integer ENTREZ_GENE_ID_3 = 3; + private static final Integer ENTREZ_GENE_ID_4 = 4; + private static final String SAMPLE_ID_1 = "sample_id_1"; + private static final String SAMPLE_ID_2 = "sample_id_2"; + private static final String SAMPLE_ID_3 = "sample_id_3"; + private static final String PATIENT_ID_1 = "patient_id_1"; + private static final String PATIENT_ID_2 = "patient_id_2"; + + @InjectMocks private ProfiledCasesCounter profiledSamplesCounter; + + @Mock private SampleListService sampleListService; + @Mock private GenePanelService genePanelService; + + @Test + public void calculate() { + + List genePanelDataList = new ArrayList<>(); + GenePanelData genePanelData1 = new GenePanelData(); + genePanelData1.setGenePanelId(GENE_PANEL_ID_1); + genePanelData1.setProfiled(true); + genePanelData1.setSampleId(SAMPLE_ID_1); + genePanelData1.setPatientId(PATIENT_ID_1); + genePanelDataList.add(genePanelData1); + GenePanelData genePanelData2 = new GenePanelData(); + genePanelData2.setGenePanelId(GENE_PANEL_ID_2); + genePanelData2.setProfiled(true); + genePanelData2.setSampleId(SAMPLE_ID_2); + genePanelData2.setPatientId(PATIENT_ID_1); + genePanelDataList.add(genePanelData2); + GenePanelData genePanelData3 = new GenePanelData(); + genePanelData3.setProfiled(true); + genePanelData3.setSampleId(SAMPLE_ID_3); + genePanelData3.setPatientId(PATIENT_ID_2); + genePanelDataList.add(genePanelData3); + + List genePanels = new ArrayList<>(); + GenePanel genePanel1 = new GenePanel(); + genePanel1.setStableId(GENE_PANEL_ID_1); + List genes1 = new ArrayList<>(); + GenePanelToGene genePanelToGene1 = new GenePanelToGene(); + genePanelToGene1.setEntrezGeneId(ENTREZ_GENE_ID_1); + genes1.add(genePanelToGene1); + GenePanelToGene genePanelToGene2 = new GenePanelToGene(); + genePanelToGene2.setEntrezGeneId(ENTREZ_GENE_ID_2); + genes1.add(genePanelToGene2); + genePanel1.setGenes(genes1); + genePanels.add(genePanel1); + GenePanel genePanel2 = new GenePanel(); + genePanel2.setStableId(GENE_PANEL_ID_2); + List genes2 = new ArrayList<>(); + GenePanelToGene genePanelToGene3 = new GenePanelToGene(); + genePanelToGene3.setEntrezGeneId(ENTREZ_GENE_ID_1); + genes2.add(genePanelToGene3); + GenePanelToGene genePanelToGene4 = new GenePanelToGene(); + genePanelToGene4.setEntrezGeneId(ENTREZ_GENE_ID_4); + genes2.add(genePanelToGene4); + genePanel2.setGenes(genes2); + genePanels.add(genePanel2); + + Mockito.when( + genePanelService.fetchGenePanels( + Arrays.asList(GENE_PANEL_ID_2, GENE_PANEL_ID_1), "DETAILED")) + .thenReturn(genePanels); + + List alterationCounts = new ArrayList<>(); + AlterationCountByGene alterationCount1 = new AlterationCountByGene(); + alterationCount1.setEntrezGeneId(ENTREZ_GENE_ID_1); + alterationCounts.add(alterationCount1); + AlterationCountByGene alterationCount2 = new AlterationCountByGene(); + alterationCount2.setEntrezGeneId(ENTREZ_GENE_ID_2); + alterationCounts.add(alterationCount2); + AlterationCountByGene alterationCount3 = new AlterationCountByGene(); + alterationCount3.setEntrezGeneId(ENTREZ_GENE_ID_3); + alterationCounts.add(alterationCount3); + + profiledSamplesCounter.calculate( + alterationCounts, genePanelDataList, false, profiledSamplesCounter.sampleUniqueIdentifier); + + // GENE_ID_1: in panel1(S1) + panel2(S2) + no_panel(S3) = 3 samples + Assert.assertEquals(Integer.valueOf(3), alterationCounts.get(0).getNumberOfProfiledCases()); + // GENE_ID_2: in panel1(S1) + no_panel(S3) = 2 samples + Assert.assertEquals(Integer.valueOf(2), alterationCounts.get(1).getNumberOfProfiledCases()); + // GENE_ID_3: off-panel gene, only counts no_panel samples = 1 sample + Assert.assertEquals(Integer.valueOf(1), alterationCounts.get(2).getNumberOfProfiledCases()); + + profiledSamplesCounter.calculate( + alterationCounts, genePanelDataList, false, profiledSamplesCounter.patientUniqueIdentifier); + + // GENE_ID_1: covers patient1 + patient2 = 2 patients + Assert.assertEquals(Integer.valueOf(2), alterationCounts.get(0).getNumberOfProfiledCases()); + // GENE_ID_2: covers patient1 + patient2 = 2 patients + Assert.assertEquals(Integer.valueOf(2), alterationCounts.get(1).getNumberOfProfiledCases()); + // GENE_ID_3: off-panel gene, only patient2 = 1 patient + Assert.assertEquals(Integer.valueOf(1), alterationCounts.get(2).getNumberOfProfiledCases()); + + profiledSamplesCounter.calculate( + alterationCounts, genePanelDataList, true, profiledSamplesCounter.patientUniqueIdentifier); + + Assert.assertEquals(4, alterationCounts.size()); + // GENE_ID_1: patient1 + patient2 = 2 patients + Assert.assertEquals(Integer.valueOf(2), alterationCounts.get(0).getNumberOfProfiledCases()); + // GENE_ID_2: patient1 + patient2 = 2 patients + Assert.assertEquals(Integer.valueOf(2), alterationCounts.get(1).getNumberOfProfiledCases()); + // GENE_ID_3: off-panel gene, only patient2 = 1 patient + Assert.assertEquals(Integer.valueOf(1), alterationCounts.get(2).getNumberOfProfiledCases()); + // GENE_ID_4: added from gene panel, patient1 + patient2 = 2 patients + Assert.assertEquals(Integer.valueOf(2), alterationCounts.get(3).getNumberOfProfiledCases()); + Assert.assertEquals(ENTREZ_GENE_ID_4, alterationCounts.get(3).getEntrezGeneId()); + } +} diff --git a/src/test/java/org/cbioportal/legacy/service/util/StudyViewColumnarServiceUtilTest.java b/src/test/java/org/cbioportal/legacy/service/util/StudyViewColumnarServiceUtilTest.java new file mode 100644 index 00000000000..87bdad32309 --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/service/util/StudyViewColumnarServiceUtilTest.java @@ -0,0 +1,361 @@ +package org.cbioportal.legacy.service.util; + +import static org.junit.Assert.*; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import org.cbioportal.legacy.model.CaseListDataCount; +import org.cbioportal.legacy.model.ClinicalAttribute; +import org.cbioportal.legacy.model.ClinicalDataCount; +import org.cbioportal.legacy.model.ClinicalDataCountItem; +import org.cbioportal.legacy.model.GenomicDataCount; +import org.cbioportal.legacy.model.GenomicDataCountItem; +import org.cbioportal.legacy.web.parameter.GenomicDataFilter; +import org.junit.Assert; +import org.junit.Test; + +public class StudyViewColumnarServiceUtilTest { + + @Test + public void testMergeClinicalDataCounts() { + + // first two counts are for same value (value1) and so should be + // merged + + ClinicalDataCount count1 = new ClinicalDataCount(); + count1.setAttributeId("attr1"); + count1.setValue("value1"); + count1.setCount(1); + + ClinicalDataCount count2 = new ClinicalDataCount(); + count2.setAttributeId("attr1"); + count2.setValue("value1"); + count2.setCount(2); + + ClinicalDataCount count3 = new ClinicalDataCount(); + count3.setAttributeId("attr1"); + count3.setValue("value3"); + count3.setCount(6); + + ClinicalDataCount count4 = new ClinicalDataCount(); + count4.setAttributeId("attr1"); + count4.setValue("value3"); + count4.setCount(4); + + ClinicalDataCount count5 = new ClinicalDataCount(); + count5.setAttributeId("attr1"); + count5.setValue("value2"); + count5.setCount(4); + + ClinicalDataCountItem item = new ClinicalDataCountItem(); + item.setAttributeId("attr1"); + item.setCounts(Arrays.asList(count1, count2, count3, count4, count5)); + + List items = Collections.singletonList(item); + + // Call the method under test + List mergedItems = + StudyViewColumnarServiceUtil.mergeClinicalDataCounts(items); + + // it merged three count items to 2 + Optional mergedCount = + mergedItems.get(0).getCounts().stream() + .filter(count -> count.getValue().equals("value1")) + .findFirst(); + Assert.assertEquals(3, mergedCount.get().getCount().intValue()); + + Optional mergedCount2 = + mergedItems.get(0).getCounts().stream() + .filter(count -> count.getValue().equals("value2")) + .findFirst(); + Assert.assertEquals(4, mergedCount2.get().getCount().intValue()); + + Optional mergedCount3 = + mergedItems.get(0).getCounts().stream() + .filter(count -> count.getValue().equals("value3")) + .findFirst(); + Assert.assertEquals(10, mergedCount3.get().getCount().intValue()); + } + + @Test + public void testAddClinicalDataCountsForMissingAttributes() { + ClinicalDataCountItem existingItem = new ClinicalDataCountItem(); + existingItem.setAttributeId("attr1"); + ClinicalDataCount existingCount = new ClinicalDataCount(); + existingCount.setCount(5); + existingCount.setValue("value1"); + existingCount.setAttributeId("attr1"); + existingItem.setCounts(Collections.singletonList(existingCount)); + + List counts = Collections.singletonList(existingItem); + + // we're gonna create two attributes which will not be represented in the passed result set + // test whether addClinicalDataCountsForMissingAttributes restores them + + ClinicalAttribute missingAttributeSample = new ClinicalAttribute(); + missingAttributeSample.setAttrId("attr2"); + missingAttributeSample.setPatientAttribute(false); + + ClinicalAttribute missingAttributePatient = new ClinicalAttribute(); + missingAttributePatient.setAttrId("attr3"); + missingAttributePatient.setPatientAttribute(true); + + List attributes = + Arrays.asList(missingAttributeSample, missingAttributePatient); + + List result = + StudyViewColumnarServiceUtil.addClinicalDataCountsForMissingAttributes( + counts, attributes, 10, 20); + + assertEquals(3, result.size()); + + Optional addedItemSample = + result.stream().filter(item -> item.getAttributeId().equals("attr2")).findFirst(); + + assertTrue(addedItemSample.isPresent()); + assertEquals(1, addedItemSample.get().getCounts().size()); + assertEquals("NA", addedItemSample.get().getCounts().get(0).getValue()); + assertEquals(10, addedItemSample.get().getCounts().get(0).getCount().intValue()); + + Optional addedItemPatient = + result.stream().filter(item -> item.getAttributeId().equals("attr3")).findFirst(); + + assertTrue(addedItemPatient.isPresent()); + assertEquals(1, addedItemPatient.get().getCounts().size()); + assertEquals("NA", addedItemPatient.get().getCounts().get(0).getValue()); + assertEquals(20, addedItemPatient.get().getCounts().get(0).getCount().intValue()); + } + + @Test + public void testMergeGenomicDataCounts() { + GenomicDataCount count1 = new GenomicDataCount(); + count1.setValue("value1"); + count1.setLabel("label1"); + count1.setCount(1); + + GenomicDataCount count2 = new GenomicDataCount(); + count2.setValue("value1"); + count2.setLabel("label1"); + count2.setCount(2); + + GenomicDataCount count3 = new GenomicDataCount(); + count3.setValue("value2"); + count3.setLabel("label2"); + count3.setCount(3); + + List counts = Arrays.asList(count1, count2, count3); + + List mergedCounts = + StudyViewColumnarServiceUtil.mergeGenomicDataCounts(counts); + + assertEquals(2, mergedCounts.size()); + + GenomicDataCount mergedCount1 = + mergedCounts.stream() + .filter(count -> count.getValue().equals("value1")) + .findFirst() + .orElse(null); + assertEquals(3, mergedCount1.getCount().intValue()); + assertEquals("label1", mergedCount1.getLabel()); + + GenomicDataCount mergedCount2 = + mergedCounts.stream() + .filter(count -> count.getValue().equals("value2")) + .findFirst() + .orElse(null); + assertEquals(3, mergedCount2.getCount().intValue()); + assertEquals("label2", mergedCount2.getLabel()); + } + + @Test + public void testMergeCaseListCounts() { + CaseListDataCount count1 = new CaseListDataCount(); + count1.setValue("value1"); + count1.setLabel("label1"); + count1.setCount(1); + + CaseListDataCount count2 = new CaseListDataCount(); + count2.setValue("value1"); + count2.setLabel("label1"); + count2.setCount(2); + + CaseListDataCount count3 = new CaseListDataCount(); + count3.setValue("value2"); + count3.setLabel("label2"); + count3.setCount(3); + + List counts = Arrays.asList(count1, count2, count3); + + List mergedCounts = StudyViewColumnarServiceUtil.mergeCaseListCounts(counts); + + assertEquals(2, mergedCounts.size()); + + CaseListDataCount mergedCount1 = + mergedCounts.stream() + .filter(count -> count.getValue().equals("value1")) + .findFirst() + .orElse(null); + assertEquals(3, mergedCount1.getCount().intValue()); + assertEquals("label1", mergedCount1.getLabel()); + + CaseListDataCount mergedCount2 = + mergedCounts.stream() + .filter(count -> count.getValue().equals("value2")) + .findFirst() + .orElse(null); + assertEquals(3, mergedCount2.getCount().intValue()); + assertEquals("label2", mergedCount2.getLabel()); + } + + @Test + public void testNormalizeDataCounts() { + ClinicalDataCount count1 = new ClinicalDataCount(); + count1.setAttributeId("attr1"); + count1.setValue("TRUE"); + count1.setCount(1); + + ClinicalDataCount count2 = new ClinicalDataCount(); + count2.setAttributeId("attr1"); + count2.setValue("True"); + count2.setCount(2); + + ClinicalDataCount count3 = new ClinicalDataCount(); + count3.setAttributeId("attr1"); + count3.setValue("true"); + count3.setCount(3); + + ClinicalDataCount count4 = new ClinicalDataCount(); + count4.setAttributeId("attr1"); + count4.setValue("FALSE"); + count4.setCount(4); + + ClinicalDataCount count5 = new ClinicalDataCount(); + count5.setAttributeId("attr1"); + count5.setValue("False"); + count5.setCount(5); + + List dataCounts = Arrays.asList(count1, count2, count3, count4, count5); + + List normalizedDataCounts = + StudyViewColumnarServiceUtil.normalizeDataCounts(dataCounts); + + assertEquals(2, normalizedDataCounts.size()); + + // should be null because it prioritizes lower case over upper case + ClinicalDataCount trueCountNullCheck = + normalizedDataCounts.stream() + .filter(count -> count.getValue().equals("True")) + .findFirst() + .orElse(null); + assertEquals(null, trueCountNullCheck); + + ClinicalDataCount trueCount = + normalizedDataCounts.stream() + .filter(count -> count.getValue().equals("true")) + .findFirst() + .orElse(null); + assertEquals(6, trueCount.getCount().intValue()); + + // should be null because it prioritizes lower case over upper case + ClinicalDataCount falseCountNullCheck = + normalizedDataCounts.stream() + .filter(count -> count.getValue().equals("FALSE")) + .findFirst() + .orElse(null); + assertEquals(null, falseCountNullCheck); + + ClinicalDataCount falseCount = + normalizedDataCounts.stream() + .filter(count -> count.getValue().equals("False")) + .findFirst() + .orElse(null); + assertEquals(9, falseCount.getCount().intValue()); + } + + @Test + public void testCreateGenomicDataCountItemFromMutationCounts() { + GenomicDataFilter genomicDataFilter = new GenomicDataFilter(); + genomicDataFilter.setHugoGeneSymbol("hugo1"); + + Map counts1 = + Map.of( + "mutatedCount", 5, + "notMutatedCount", 10, + "notProfiledCount", 15); + + GenomicDataCountItem item1 = + StudyViewColumnarServiceUtil.createGenomicDataCountItemFromMutationCounts( + genomicDataFilter, counts1); + + assertEquals("hugo1", item1.getHugoGeneSymbol()); + assertEquals("mutations", item1.getProfileType()); + + assertEquals(3, item1.getCounts().size()); + + GenomicDataCount mutatedCount1 = + item1.getCounts().stream() + .filter(count -> count.getValue().equals("MUTATED")) + .findFirst() + .orElse(null); + assertNotNull(mutatedCount1); + assertEquals(5, mutatedCount1.getCount().intValue()); + + GenomicDataCount notMutatedCount1 = + item1.getCounts().stream() + .filter(count -> count.getValue().equals("NOT_MUTATED")) + .findFirst() + .orElse(null); + assertNotNull(notMutatedCount1); + assertEquals(10, notMutatedCount1.getCount().intValue()); + + GenomicDataCount notProfiledCount1 = + item1.getCounts().stream() + .filter(count -> count.getValue().equals("NOT_PROFILED")) + .findFirst() + .orElse(null); + assertNotNull(notProfiledCount1); + assertEquals(15, notProfiledCount1.getCount().intValue()); + + // Test case where a count equals 0 + Map counts2 = + Map.of( + "mutatedCount", 5, + "notMutatedCount", 0, + "notProfiledCount", 5); + + GenomicDataCountItem item2 = + StudyViewColumnarServiceUtil.createGenomicDataCountItemFromMutationCounts( + genomicDataFilter, counts2); + + assertEquals("hugo1", item2.getHugoGeneSymbol()); + assertEquals("mutations", item2.getProfileType()); + + assertEquals(2, item2.getCounts().size()); + + GenomicDataCount mutatedCount2 = + item2.getCounts().stream() + .filter(count -> count.getValue().equals("MUTATED")) + .findFirst() + .orElse(null); + assertNotNull(mutatedCount2); + assertEquals(5, mutatedCount2.getCount().intValue()); + + GenomicDataCount notMutatedCount2 = + item2.getCounts().stream() + .filter(count -> count.getValue().equals("NOT_MUTATED")) + .findFirst() + .orElse(null); + assertNull(notMutatedCount2); + + GenomicDataCount notProfiledCount2 = + item2.getCounts().stream() + .filter(count -> count.getValue().equals("NOT_PROFILED")) + .findFirst() + .orElse(null); + assertNotNull(notProfiledCount2); + assertEquals(5, notProfiledCount2.getCount().intValue()); + } +} diff --git a/src/test/java/org/cbioportal/legacy/utils/config/PropertyConditionTest.java b/src/test/java/org/cbioportal/legacy/utils/config/PropertyConditionTest.java new file mode 100644 index 00000000000..94089366bc8 --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/utils/config/PropertyConditionTest.java @@ -0,0 +1,100 @@ +package org.cbioportal.legacy.utils.config; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.when; + +import java.util.HashMap; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Answers; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnitRunner; +import org.springframework.context.annotation.ConditionContext; +import org.springframework.core.type.AnnotatedTypeMetadata; + +@RunWith(MockitoJUnitRunner.class) +public class PropertyConditionTest { + + @Mock private AnnotatedTypeMetadata metadata; + + @Mock(answer = Answers.RETURNS_DEEP_STUBS) + private ConditionContext context; + + private HashMap attributes; + private PropertyCondition propertyCondition; + + @Before + public void init() { + attributes = new HashMap(); + attributes.put("name", "requested_prop"); + attributes.put("havingValue", "requested_value"); + attributes.put("matchIfMissing", false); + attributes.put("isNot", false); + propertyCondition = new PropertyCondition(); + } + + @Test + public void matchesSuccess() { + attributes.put("name", "requested_prop"); + attributes.put("havingValue", "requested_value"); + attributes.put("matchIfMissing", false); + when(metadata.getAnnotationAttributes(any())).thenReturn(attributes); + when(context.getEnvironment().getProperty(eq("requested_prop"))).thenReturn("requested_value"); + Assert.assertTrue(propertyCondition.matches(context, metadata)); + } + + @Test + public void matchesFailWrongValue() { + attributes.put("name", "requested_prop"); + attributes.put("havingValue", "requested_value"); + attributes.put("matchIfMissing", false); + when(metadata.getAnnotationAttributes(any())).thenReturn(attributes); + when(context.getEnvironment().getProperty(eq("requested_prop"))).thenReturn("different_value"); + Assert.assertFalse(propertyCondition.matches(context, metadata)); + } + + @Test + public void matchesFailNullValue() { + attributes.put("name", "requested_prop"); + attributes.put("havingValue", "requested_value"); + attributes.put("matchIfMissing", false); + when(metadata.getAnnotationAttributes(any())).thenReturn(attributes); + when(context.getEnvironment().getProperty(eq("requested_prop"))).thenReturn(null); + Assert.assertFalse(propertyCondition.matches(context, metadata)); + } + + @Test + public void matchesSuccessNullValueAndMatchIfMissing() { + attributes.put("name", "requested_prop"); + attributes.put("havingValue", "requested_value"); + attributes.put("matchIfMissing", true); + when(metadata.getAnnotationAttributes(any())).thenReturn(attributes); + when(context.getEnvironment().getProperty(eq("requested_prop"))).thenReturn(null); + Assert.assertTrue(propertyCondition.matches(context, metadata)); + } + + @Test + public void matchesSuccessIsNot() { + attributes.put("name", "requested_prop"); + attributes.put("havingValue", "requested_value"); + attributes.put("matchIfMissing", false); + attributes.put("isNot", true); + when(metadata.getAnnotationAttributes(any())).thenReturn(attributes); + when(context.getEnvironment().getProperty(eq("requested_prop"))).thenReturn("different_value"); + Assert.assertTrue(propertyCondition.matches(context, metadata)); + } + + @Test + public void matchesSuccessMultipleValues() { + attributes.put("name", "requested_prop"); + attributes.put("havingValue", new String[] {"requested_value_1", "requested_value_2"}); + attributes.put("matchIfMissing", false); + when(metadata.getAnnotationAttributes(any())).thenReturn(attributes); + when(context.getEnvironment().getProperty(eq("requested_prop"))) + .thenReturn("requested_value_2"); + Assert.assertTrue(propertyCondition.matches(context, metadata)); + } +} diff --git a/src/test/java/org/cbioportal/legacy/web/AlterationDriverAnnotationControllerTest.java b/src/test/java/org/cbioportal/legacy/web/AlterationDriverAnnotationControllerTest.java new file mode 100644 index 00000000000..8122c2bc12e --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/web/AlterationDriverAnnotationControllerTest.java @@ -0,0 +1,72 @@ +package org.cbioportal.legacy.web; + +import static org.mockito.ArgumentMatchers.anyList; +import static org.mockito.Mockito.when; +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; + +import com.fasterxml.jackson.databind.ObjectMapper; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import org.cbioportal.legacy.model.CustomDriverAnnotationReport; +import org.cbioportal.legacy.service.AlterationDriverAnnotationService; +import org.cbioportal.legacy.web.config.TestConfig; +import org.hamcrest.Matchers; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mockito; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; +import org.springframework.security.test.context.support.WithMockUser; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.result.MockMvcResultMatchers; + +@RunWith(SpringJUnit4ClassRunner.class) +@WebMvcTest(AlterationDriverAnnotationController.class) +@ContextConfiguration(classes = {AlterationDriverAnnotationController.class, TestConfig.class}) +public class AlterationDriverAnnotationControllerTest { + + private ObjectMapper objectMapper = new ObjectMapper(); + + @MockBean private AlterationDriverAnnotationService alterationDriverAnnotationService; + + @Autowired private MockMvc mockMvc; + + @Before + public void setUp() { + Mockito.reset(alterationDriverAnnotationService); + } + + @Test + @WithMockUser + public void fetchCustomDriverAnnotationReport() throws Exception { + CustomDriverAnnotationReport report = + new CustomDriverAnnotationReport(true, new HashSet<>(Arrays.asList("a", "b"))); + when(alterationDriverAnnotationService.getCustomDriverAnnotationProps(anyList())) + .thenReturn(report); + + List body = new ArrayList<>(Collections.singletonList("molecularProfileId1")); + mockMvc + .perform( + MockMvcRequestBuilders.post("/api/custom-driver-annotation-report/fetch") + .with(csrf()) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(body))) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect( + MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.jsonPath("$.hasBinary", Matchers.equalTo(true))) + .andExpect(MockMvcResultMatchers.jsonPath("$.tiers", Matchers.hasSize(2))) + .andExpect(MockMvcResultMatchers.jsonPath("$.tiers[0]", Matchers.equalTo("a"))) + .andExpect(MockMvcResultMatchers.jsonPath("$.tiers[1]", Matchers.equalTo("b"))); + } +} diff --git a/src/test/java/org/cbioportal/legacy/web/AlterationEnrichmentControllerTest.java b/src/test/java/org/cbioportal/legacy/web/AlterationEnrichmentControllerTest.java new file mode 100644 index 00000000000..13ad53eee77 --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/web/AlterationEnrichmentControllerTest.java @@ -0,0 +1,437 @@ +package org.cbioportal.legacy.web; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.argThat; +import static org.mockito.Mockito.when; +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; + +import com.fasterxml.jackson.databind.ObjectMapper; +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import org.cbioportal.legacy.model.AlterationEnrichment; +import org.cbioportal.legacy.model.AlterationFilter; +import org.cbioportal.legacy.model.CNA; +import org.cbioportal.legacy.model.CountSummary; +import org.cbioportal.legacy.model.MolecularProfileCaseIdentifier; +import org.cbioportal.legacy.model.MutationEventType; +import org.cbioportal.legacy.service.AlterationEnrichmentService; +import org.cbioportal.legacy.web.config.TestConfig; +import org.cbioportal.legacy.web.parameter.MolecularProfileCasesGroupAndAlterationTypeFilter; +import org.cbioportal.legacy.web.parameter.MolecularProfileCasesGroupFilter; +import org.cbioportal.legacy.web.util.AlterationFilterMockitoArgumentMatcher; +import org.hamcrest.Matchers; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.ArgumentMatcher; +import org.mockito.Mockito; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; +import org.springframework.security.test.context.support.WithMockUser; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.result.MockMvcResultMatchers; + +@RunWith(SpringJUnit4ClassRunner.class) +@WebMvcTest(AlterationEnrichmentControllerTest.class) +@ContextConfiguration(classes = {AlterationEnrichmentController.class, TestConfig.class}) +public class AlterationEnrichmentControllerTest { + + private static final int TEST_ENTREZ_GENE_ID_1 = 1; + private static final String TEST_HUGO_GENE_SYMBOL_1 = "test_hugo_gene_symbol_1"; + private static final String TEST_CYTOBAND_1 = "test_cytoband_1"; + private static final int TEST_NUMBER_OF_SAMPLES_ALTERED_IN_SET_1 = 1; + private static final int TEST_NUMBER_OF_SAMPLES_UNALTERED_IN_SET_1 = 1; + private static final BigDecimal TEST_P_VALUE_1 = new BigDecimal(1.1); + private static final int TEST_ENTREZ_GENE_ID_2 = 2; + private static final String TEST_HUGO_GENE_SYMBOL_2 = "test_hugo_gene_symbol_2"; + private static final String TEST_CYTOBAND_2 = "test_cytoband_2"; + private static final int TEST_NUMBER_OF_SAMPLES_ALTERED_IN_SET_2 = 2; + private static final int TEST_NUMBER_OF_SAMPLES_UNALTERED_IN_SET_2 = 2; + private static final BigDecimal TEST_P_VALUE_2 = new BigDecimal(2.1); + private static final int TEST_NUMBER_OF_SAMPLES_PROFILED_IN_SET_1 = 1; + private static final int TEST_NUMBER_OF_SAMPLES_PROFILED_IN_SET_2 = 1; + + @MockBean private AlterationEnrichmentService alterationEnrichmentService; + + @Autowired private MockMvc mockMvc; + + private ObjectMapper objectMapper = new ObjectMapper(); + private ArrayList alterationEnrichments; + Map mutationTypes; + Map cnaTypes; + + private MolecularProfileCasesGroupAndAlterationTypeFilter filter; + + private static class caseIdMatcher implements ArgumentMatcher { + @Override + public boolean matches(Map map) { + Map> e = + (Map>) map; + return e.containsKey("altered group") + && e.containsKey("unaltered group") + && e.get("altered group").size() == 1 + && e.get("unaltered group").size() == 1 + && e.get("altered group").get(0).getCaseId().equals("test_sample_id_1") + && e.get("unaltered group").get(0).getCaseId().equals("test_sample_id_2"); + } + } + + @Before + public void setUp() throws Exception { + Mockito.reset(alterationEnrichmentService); + + alterationEnrichments = new ArrayList<>(); + AlterationEnrichment alterationEnrichment1 = new AlterationEnrichment(); + CountSummary alterationEnrichment1Set1Count = new CountSummary(); + CountSummary alterationEnrichment1Set2Count = new CountSummary(); + alterationEnrichment1.setEntrezGeneId(TEST_ENTREZ_GENE_ID_1); + alterationEnrichment1.setHugoGeneSymbol(TEST_HUGO_GENE_SYMBOL_1); + alterationEnrichment1.setCytoband(TEST_CYTOBAND_1); + alterationEnrichment1.setpValue(TEST_P_VALUE_1); + alterationEnrichment1Set1Count.setAlteredCount(TEST_NUMBER_OF_SAMPLES_ALTERED_IN_SET_1); + alterationEnrichment1Set1Count.setProfiledCount(TEST_NUMBER_OF_SAMPLES_PROFILED_IN_SET_1); + alterationEnrichment1Set2Count.setAlteredCount(TEST_NUMBER_OF_SAMPLES_UNALTERED_IN_SET_1); + alterationEnrichment1Set2Count.setProfiledCount(TEST_NUMBER_OF_SAMPLES_PROFILED_IN_SET_2); + alterationEnrichment1.setCounts( + Arrays.asList(alterationEnrichment1Set1Count, alterationEnrichment1Set2Count)); + alterationEnrichments.add(alterationEnrichment1); + + AlterationEnrichment alterationEnrichment2 = new AlterationEnrichment(); + CountSummary alterationEnrichment2Set1Count = new CountSummary(); + CountSummary alterationEnrichment2Set2Count = new CountSummary(); + alterationEnrichment2.setEntrezGeneId(TEST_ENTREZ_GENE_ID_2); + alterationEnrichment2.setHugoGeneSymbol(TEST_HUGO_GENE_SYMBOL_2); + alterationEnrichment2.setCytoband(TEST_CYTOBAND_2); + alterationEnrichment2.setpValue(TEST_P_VALUE_2); + alterationEnrichment2Set1Count.setAlteredCount(TEST_NUMBER_OF_SAMPLES_ALTERED_IN_SET_2); + alterationEnrichment2Set1Count.setProfiledCount(TEST_NUMBER_OF_SAMPLES_PROFILED_IN_SET_1); + alterationEnrichment2Set2Count.setAlteredCount(TEST_NUMBER_OF_SAMPLES_UNALTERED_IN_SET_2); + alterationEnrichment2Set2Count.setProfiledCount(TEST_NUMBER_OF_SAMPLES_PROFILED_IN_SET_2); + alterationEnrichment2.setCounts( + Arrays.asList(alterationEnrichment2Set1Count, alterationEnrichment2Set2Count)); + alterationEnrichments.add(alterationEnrichment2); + + MolecularProfileCaseIdentifier entity1 = new MolecularProfileCaseIdentifier(); + entity1.setCaseId("test_sample_id_1"); + entity1.setMolecularProfileId("test_1_mutations"); + MolecularProfileCaseIdentifier entity2 = new MolecularProfileCaseIdentifier(); + entity2.setCaseId("test_sample_id_2"); + entity2.setMolecularProfileId("test_2_mutations"); + + MolecularProfileCasesGroupFilter casesGroup1 = new MolecularProfileCasesGroupFilter(); + casesGroup1.setName("altered group"); + casesGroup1.setMolecularProfileCaseIdentifiers(Arrays.asList(entity1)); + + MolecularProfileCasesGroupFilter casesGroup2 = new MolecularProfileCasesGroupFilter(); + casesGroup2.setName("unaltered group"); + casesGroup2.setMolecularProfileCaseIdentifiers(Arrays.asList(entity2)); + + filter = new MolecularProfileCasesGroupAndAlterationTypeFilter(); + filter.setMolecularProfileCasesGroupFilter(Arrays.asList(casesGroup1, casesGroup2)); + + filter.setAlterationEventTypes(new AlterationFilter()); + + mutationTypes = new HashMap<>(); + cnaTypes = new HashMap<>(); + } + + @Test + @WithMockUser + public void fetchAlterationEnrichmentsAllTypes() throws Exception { + + when(alterationEnrichmentService.getAlterationEnrichments( + argThat(new caseIdMatcher()), + any(), + argThat(new AlterationFilterMockitoArgumentMatcher("ALL", "ALL")))) + .thenReturn(alterationEnrichments); + + mutationTypes.put(MutationEventType.missense_mutation, true); + mutationTypes.put(MutationEventType.feature_truncation, true); + cnaTypes.put(CNA.AMP, true); + cnaTypes.put(CNA.HOMDEL, true); + + filter.getAlterationEventTypes().setMutationEventTypes(mutationTypes); + filter.getAlterationEventTypes().setCopyNumberAlterationEventTypes(cnaTypes); + + mockMvc + .perform( + MockMvcRequestBuilders.post("/api/alteration-enrichments/fetch") + .with(csrf()) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(filter))) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect( + MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.jsonPath("$", Matchers.hasSize(2))) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].entrezGeneId").value(TEST_ENTREZ_GENE_ID_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].hugoGeneSymbol").value(TEST_HUGO_GENE_SYMBOL_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].cytoband").value(TEST_CYTOBAND_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].counts[0].alteredCount") + .value(TEST_NUMBER_OF_SAMPLES_ALTERED_IN_SET_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].counts[1].alteredCount") + .value(TEST_NUMBER_OF_SAMPLES_UNALTERED_IN_SET_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].pValue").value(TEST_P_VALUE_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].counts[0].profiledCount") + .value(TEST_NUMBER_OF_SAMPLES_PROFILED_IN_SET_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].counts[1].profiledCount") + .value(TEST_NUMBER_OF_SAMPLES_PROFILED_IN_SET_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].entrezGeneId").value(TEST_ENTREZ_GENE_ID_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].hugoGeneSymbol").value(TEST_HUGO_GENE_SYMBOL_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].cytoband").value(TEST_CYTOBAND_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].counts[0].alteredCount") + .value(TEST_NUMBER_OF_SAMPLES_ALTERED_IN_SET_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].counts[1].alteredCount") + .value(TEST_NUMBER_OF_SAMPLES_UNALTERED_IN_SET_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].pValue").value(TEST_P_VALUE_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].counts[0].profiledCount") + .value(TEST_NUMBER_OF_SAMPLES_PROFILED_IN_SET_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].counts[1].profiledCount") + .value(TEST_NUMBER_OF_SAMPLES_PROFILED_IN_SET_2)); + } + + @Test + @WithMockUser + public void fetchAlterationEnrichmentsNoTypes() throws Exception { + + when(alterationEnrichmentService.getAlterationEnrichments( + argThat(new caseIdMatcher()), + any(), + argThat(new AlterationFilterMockitoArgumentMatcher("EMPTY", "EMPTY")))) + .thenReturn(alterationEnrichments); + + mutationTypes.put(MutationEventType.missense_mutation, false); + mutationTypes.put(MutationEventType.feature_truncation, false); + cnaTypes.put(CNA.AMP, false); + cnaTypes.put(CNA.HOMDEL, false); + + filter.getAlterationEventTypes().setMutationEventTypes(mutationTypes); + filter.getAlterationEventTypes().setCopyNumberAlterationEventTypes(cnaTypes); + + mockMvc + .perform( + MockMvcRequestBuilders.post("/api/alteration-enrichments/fetch") + .with(csrf()) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(filter))) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect( + MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.jsonPath("$", Matchers.hasSize(2))) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].entrezGeneId").value(TEST_ENTREZ_GENE_ID_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].hugoGeneSymbol").value(TEST_HUGO_GENE_SYMBOL_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].cytoband").value(TEST_CYTOBAND_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].counts[0].alteredCount") + .value(TEST_NUMBER_OF_SAMPLES_ALTERED_IN_SET_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].counts[1].alteredCount") + .value(TEST_NUMBER_OF_SAMPLES_UNALTERED_IN_SET_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].pValue").value(TEST_P_VALUE_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].counts[0].profiledCount") + .value(TEST_NUMBER_OF_SAMPLES_PROFILED_IN_SET_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].counts[1].profiledCount") + .value(TEST_NUMBER_OF_SAMPLES_PROFILED_IN_SET_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].entrezGeneId").value(TEST_ENTREZ_GENE_ID_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].hugoGeneSymbol").value(TEST_HUGO_GENE_SYMBOL_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].cytoband").value(TEST_CYTOBAND_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].counts[0].alteredCount") + .value(TEST_NUMBER_OF_SAMPLES_ALTERED_IN_SET_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].counts[1].alteredCount") + .value(TEST_NUMBER_OF_SAMPLES_UNALTERED_IN_SET_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].pValue").value(TEST_P_VALUE_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].counts[0].profiledCount") + .value(TEST_NUMBER_OF_SAMPLES_PROFILED_IN_SET_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].counts[1].profiledCount") + .value(TEST_NUMBER_OF_SAMPLES_PROFILED_IN_SET_2)); + } + + @Test + @WithMockUser + public void fetchAlterationEnrichmentsAllMutationTypesDeselected() throws Exception { + + when(alterationEnrichmentService.getAlterationEnrichments( + argThat(new caseIdMatcher()), + any(), + argThat(new AlterationFilterMockitoArgumentMatcher("EMPTY", "ALL")))) + .thenReturn(alterationEnrichments); + + mutationTypes.put(MutationEventType.missense_mutation, false); + mutationTypes.put(MutationEventType.feature_truncation, false); + cnaTypes.put(CNA.AMP, true); + cnaTypes.put(CNA.HOMDEL, true); + + filter.getAlterationEventTypes().setMutationEventTypes(mutationTypes); + filter.getAlterationEventTypes().setCopyNumberAlterationEventTypes(cnaTypes); + + mockMvc + .perform( + MockMvcRequestBuilders.post("/api/alteration-enrichments/fetch") + .with(csrf()) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(filter))) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect( + MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.jsonPath("$", Matchers.hasSize(2))) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].entrezGeneId").value(TEST_ENTREZ_GENE_ID_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].hugoGeneSymbol").value(TEST_HUGO_GENE_SYMBOL_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].cytoband").value(TEST_CYTOBAND_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].counts[0].alteredCount") + .value(TEST_NUMBER_OF_SAMPLES_ALTERED_IN_SET_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].counts[1].alteredCount") + .value(TEST_NUMBER_OF_SAMPLES_UNALTERED_IN_SET_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].pValue").value(TEST_P_VALUE_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].counts[0].profiledCount") + .value(TEST_NUMBER_OF_SAMPLES_PROFILED_IN_SET_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].counts[1].profiledCount") + .value(TEST_NUMBER_OF_SAMPLES_PROFILED_IN_SET_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].entrezGeneId").value(TEST_ENTREZ_GENE_ID_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].hugoGeneSymbol").value(TEST_HUGO_GENE_SYMBOL_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].cytoband").value(TEST_CYTOBAND_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].counts[0].alteredCount") + .value(TEST_NUMBER_OF_SAMPLES_ALTERED_IN_SET_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].counts[1].alteredCount") + .value(TEST_NUMBER_OF_SAMPLES_UNALTERED_IN_SET_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].pValue").value(TEST_P_VALUE_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].counts[0].profiledCount") + .value(TEST_NUMBER_OF_SAMPLES_PROFILED_IN_SET_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].counts[1].profiledCount") + .value(TEST_NUMBER_OF_SAMPLES_PROFILED_IN_SET_2)); + } + + @Test + @WithMockUser + public void fetchAlterationEnrichmentsAllCnaTypesDeselected() throws Exception { + + when(alterationEnrichmentService.getAlterationEnrichments( + argThat(new caseIdMatcher()), + any(), + argThat(new AlterationFilterMockitoArgumentMatcher("ALL", "EMPTY")))) + .thenReturn(alterationEnrichments); + + mutationTypes.put(MutationEventType.missense_mutation, true); + mutationTypes.put(MutationEventType.feature_truncation, true); + cnaTypes.put(CNA.AMP, false); + cnaTypes.put(CNA.HOMDEL, false); + + filter.getAlterationEventTypes().setMutationEventTypes(mutationTypes); + filter.getAlterationEventTypes().setCopyNumberAlterationEventTypes(cnaTypes); + + mockMvc + .perform( + MockMvcRequestBuilders.post("/api/alteration-enrichments/fetch") + .with(csrf()) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(filter))) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect( + MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.jsonPath("$", Matchers.hasSize(2))); + } + + @Test + @WithMockUser + public void fetchAlterationEnrichmentsSubsetTypes() throws Exception { + + when(alterationEnrichmentService.getAlterationEnrichments( + argThat(new caseIdMatcher()), + any(), + argThat(new AlterationFilterMockitoArgumentMatcher("SOME", "SOME")))) + .thenReturn(alterationEnrichments); + + mutationTypes.put(MutationEventType.missense_mutation, false); + mutationTypes.put(MutationEventType.feature_truncation, true); + cnaTypes.put(CNA.AMP, false); + cnaTypes.put(CNA.HOMDEL, true); + + filter.getAlterationEventTypes().setMutationEventTypes(mutationTypes); + filter.getAlterationEventTypes().setCopyNumberAlterationEventTypes(cnaTypes); + + mockMvc + .perform( + MockMvcRequestBuilders.post("/api/alteration-enrichments/fetch") + .with(csrf()) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(filter))) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect( + MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.jsonPath("$", Matchers.hasSize(2))) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].entrezGeneId").value(TEST_ENTREZ_GENE_ID_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].hugoGeneSymbol").value(TEST_HUGO_GENE_SYMBOL_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].cytoband").value(TEST_CYTOBAND_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].counts[0].alteredCount") + .value(TEST_NUMBER_OF_SAMPLES_ALTERED_IN_SET_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].counts[1].alteredCount") + .value(TEST_NUMBER_OF_SAMPLES_UNALTERED_IN_SET_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].pValue").value(TEST_P_VALUE_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].counts[0].profiledCount") + .value(TEST_NUMBER_OF_SAMPLES_PROFILED_IN_SET_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].counts[1].profiledCount") + .value(TEST_NUMBER_OF_SAMPLES_PROFILED_IN_SET_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].entrezGeneId").value(TEST_ENTREZ_GENE_ID_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].hugoGeneSymbol").value(TEST_HUGO_GENE_SYMBOL_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].cytoband").value(TEST_CYTOBAND_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].counts[0].alteredCount") + .value(TEST_NUMBER_OF_SAMPLES_ALTERED_IN_SET_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].counts[1].alteredCount") + .value(TEST_NUMBER_OF_SAMPLES_UNALTERED_IN_SET_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].pValue").value(TEST_P_VALUE_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].counts[0].profiledCount") + .value(TEST_NUMBER_OF_SAMPLES_PROFILED_IN_SET_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].counts[1].profiledCount") + .value(TEST_NUMBER_OF_SAMPLES_PROFILED_IN_SET_2)); + } +} diff --git a/src/test/java/org/cbioportal/legacy/web/CacheControllerTest.java b/src/test/java/org/cbioportal/legacy/web/CacheControllerTest.java new file mode 100644 index 00000000000..ca114909e85 --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/web/CacheControllerTest.java @@ -0,0 +1,105 @@ +package org.cbioportal.legacy.web; + +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; + +import org.cbioportal.legacy.service.CacheService; +import org.cbioportal.legacy.web.config.TestConfig; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; +import org.springframework.security.test.context.support.WithMockUser; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.util.ReflectionTestUtils; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.result.MockMvcResultMatchers; + +@RunWith(SpringJUnit4ClassRunner.class) +@WebMvcTest(CacheController.class) +@ContextConfiguration(classes = {CacheController.class, TestConfig.class}) +@TestPropertySource( + properties = {"cache.endpoint.enabled=true", "cache.endpoint.api-key=correct-key"}) +public class CacheControllerTest { + + @Autowired private MockMvc mockMvc; + + @MockBean private CacheService cacheService; + + @Autowired private CacheController cacheController; + + @Test + @WithMockUser + public void clearAllCachesNoKeyProvided() throws Exception { + mockMvc + .perform(MockMvcRequestBuilders.delete("/api/cache").with(csrf())) + .andExpect(MockMvcResultMatchers.status().isBadRequest()); + verify(cacheService, never()).clearCaches(true); + } + + @Test + @WithMockUser + public void clearAllCachesUnauthorized() throws Exception { + mockMvc + .perform( + MockMvcRequestBuilders.delete("/api/cache") + .with(csrf()) + .header("X-API-KEY", "incorrect-key")) + .andExpect(MockMvcResultMatchers.status().isUnauthorized()) + .andExpect( + MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.TEXT_PLAIN_VALUE)); + verify(cacheService, never()).clearCaches(true); + } + + @Test + @WithMockUser + public void clearAllCachesSuccess() throws Exception { + mockMvc + .perform( + MockMvcRequestBuilders.delete("/api/cache") + .with(csrf()) + .header("X-API-KEY", "correct-key")) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect( + MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.TEXT_PLAIN_VALUE)); + verify(cacheService, times(1)).clearCaches(true); + } + + @Test + @WithMockUser + public void clearAllCachesDisabled() throws Exception { + ReflectionTestUtils.setField(cacheController, "cacheEndpointEnabled", false); + mockMvc + .perform( + MockMvcRequestBuilders.delete("/api/cache") + .with(csrf()) + .header("X-API-KEY", "correct-key")) + .andExpect(MockMvcResultMatchers.status().isNotFound()) + .andExpect( + MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.TEXT_PLAIN_VALUE)); + verify(cacheService, never()).clearCaches(true); + ReflectionTestUtils.setField(cacheController, "cacheEndpointEnabled", true); + } + + @Test + @WithMockUser + public void clearAllCachesSkipSpringManaged() throws Exception { + mockMvc + .perform( + MockMvcRequestBuilders.delete("/api/cache") + .param("springManagedCache", "false") + .with(csrf()) + .header("X-API-KEY", "correct-key")) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect( + MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.TEXT_PLAIN_VALUE)); + verify(cacheService, times(1)).clearCaches(false); + } +} diff --git a/src/test/java/org/cbioportal/legacy/web/CacheStatsControllerTest.java b/src/test/java/org/cbioportal/legacy/web/CacheStatsControllerTest.java new file mode 100644 index 00000000000..6d7ef3f4467 --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/web/CacheStatsControllerTest.java @@ -0,0 +1,112 @@ +package org.cbioportal.legacy.web; + +import java.util.ArrayList; +import java.util.List; +import org.cbioportal.legacy.service.CacheStatisticsService; +import org.cbioportal.legacy.service.exception.CacheNotFoundException; +import org.cbioportal.legacy.web.config.TestConfig; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mockito; +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; +import org.springframework.security.test.context.support.WithMockUser; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.result.MockMvcResultMatchers; + +@RunWith(SpringJUnit4ClassRunner.class) +@WebMvcTest +@ContextConfiguration(classes = {CacheStatsController.class, TestConfig.class}) +@TestPropertySource(properties = "persistence.cache_type=redis") +public class CacheStatsControllerTest { + + public static final String VALID_CACHE_ALIAS = "GeneralRepositoryCache"; + public static final String INVALID_CACHE_ALIAS = "InvalidCacheForTesting"; + + @Autowired private MockMvc mockMvc; + + @MockBean public CacheStatisticsService cacheStatisticsService; + + @Before + public void setUp() throws Exception { + Mockito.when(cacheStatisticsService.getKeyCountsPerClass(Mockito.anyString())) + .thenAnswer( + new Answer>() { + public List answer(InvocationOnMock invocation) + throws CacheNotFoundException { + Object[] args = invocation.getArguments(); + String cacheAlias = (String) args[0]; + if (VALID_CACHE_ALIAS.equals(cacheAlias)) { + return new ArrayList(); + } + throw new CacheNotFoundException(cacheAlias); + } + }); + Mockito.when(cacheStatisticsService.getKeysInCache(Mockito.anyString())) + .thenAnswer( + new Answer>() { + public List answer(InvocationOnMock invocation) + throws CacheNotFoundException { + Object[] args = invocation.getArguments(); + String cacheAlias = (String) args[0]; + if (VALID_CACHE_ALIAS.equals(cacheAlias)) { + return new ArrayList(); + } + throw new CacheNotFoundException(cacheAlias); + } + }); + } + + @Test + @WithMockUser + public void testGetKeysInCache() throws Exception { + mockMvc + .perform( + MockMvcRequestBuilders.get("/api/" + VALID_CACHE_ALIAS + "/keysInCache") + .accept(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect( + MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)); + } + + @Test + @WithMockUser + public void testGetKeysInInvalidCache() throws Exception { + mockMvc + .perform( + MockMvcRequestBuilders.get("/api/" + INVALID_CACHE_ALIAS + "/keysInCache") + .accept(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.status().isNotFound()); + } + + @Test + @WithMockUser + public void testGetKeyCountsPerClass() throws Exception { + mockMvc + .perform( + MockMvcRequestBuilders.get("/api/" + VALID_CACHE_ALIAS + "/keyCountsPerClass") + .accept(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect( + MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)); + } + + @Test + @WithMockUser + public void testGetKeyCountsPerClassInvalidCache() throws Exception { + mockMvc + .perform( + MockMvcRequestBuilders.get("/api/" + INVALID_CACHE_ALIAS + "/keyCountsPerClass") + .accept(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.status().isNotFound()); + } +} diff --git a/src/test/java/org/cbioportal/legacy/web/CancerTypeControllerTest.java b/src/test/java/org/cbioportal/legacy/web/CancerTypeControllerTest.java new file mode 100644 index 00000000000..0babafd0071 --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/web/CancerTypeControllerTest.java @@ -0,0 +1,151 @@ +package org.cbioportal.legacy.web; + +import java.util.ArrayList; +import java.util.List; +import org.cbioportal.legacy.model.TypeOfCancer; +import org.cbioportal.legacy.model.meta.BaseMeta; +import org.cbioportal.legacy.service.CancerTypeService; +import org.cbioportal.legacy.service.exception.CancerTypeNotFoundException; +import org.cbioportal.legacy.web.config.TestConfig; +import org.cbioportal.legacy.web.parameter.HeaderKeyConstants; +import org.hamcrest.Matchers; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mockito; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; +import org.springframework.security.test.context.support.WithMockUser; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.result.MockMvcResultMatchers; + +@RunWith(SpringJUnit4ClassRunner.class) +@WebMvcTest +@ContextConfiguration(classes = {CancerTypeController.class, TestConfig.class}) +public class CancerTypeControllerTest { + + private static final String TEST_TYPE_OF_CANCER_ID_1 = "test_type_of_cancer_id_1"; + private static final String TEST_NAME_1 = "test_type_of_cancer_name_1"; + private static final String TEST_DEDICATED_COLOR_1 = "test_dedicated_color_1"; + private static final String TEST_SHORT_NAME_1 = "test_type_of_cancer_short_name_1"; + private static final String TEST_PARENT_1 = "test_parent_1"; + private static final String TEST_TYPE_OF_CANCER_ID_2 = "test_type_of_cancer_id_2"; + private static final String TEST_NAME_2 = "test_type_of_cancer_name_2"; + private static final String TEST_DEDICATED_COLOR_2 = "test_dedicated_color_2"; + private static final String TEST_SHORT_NAME_2 = "test_type_of_cancer_short_name_2"; + private static final String TEST_PARENT_2 = "test_parent_2"; + + @Autowired private MockMvc mockMvc; + + @MockBean public CancerTypeService cancerTypeService; + + @Test + @WithMockUser + public void getAllCancerTypesDefaultProjection() throws Exception { + + List typeOfCancerList = new ArrayList<>(); + TypeOfCancer typeOfCancer1 = new TypeOfCancer(); + typeOfCancer1.setTypeOfCancerId(TEST_TYPE_OF_CANCER_ID_1); + typeOfCancer1.setName(TEST_NAME_1); + typeOfCancer1.setDedicatedColor(TEST_DEDICATED_COLOR_1); + typeOfCancer1.setShortName(TEST_SHORT_NAME_1); + typeOfCancer1.setParent(TEST_PARENT_1); + typeOfCancerList.add(typeOfCancer1); + TypeOfCancer typeOfCancer2 = new TypeOfCancer(); + typeOfCancer2.setTypeOfCancerId(TEST_TYPE_OF_CANCER_ID_2); + typeOfCancer2.setName(TEST_NAME_2); + typeOfCancer2.setDedicatedColor(TEST_DEDICATED_COLOR_2); + typeOfCancer2.setShortName(TEST_SHORT_NAME_2); + typeOfCancer2.setParent(TEST_PARENT_2); + typeOfCancerList.add(typeOfCancer2); + + Mockito.when( + cancerTypeService.getAllCancerTypes( + Mockito.any(), Mockito.any(), Mockito.any(), Mockito.any(), Mockito.any())) + .thenReturn(typeOfCancerList); + + mockMvc + .perform(MockMvcRequestBuilders.get("/api/cancer-types").accept(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect( + MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.jsonPath("$", Matchers.hasSize(2))) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].cancerTypeId").value(TEST_TYPE_OF_CANCER_ID_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].name").value(TEST_NAME_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].dedicatedColor").value(TEST_DEDICATED_COLOR_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].shortName").value(TEST_SHORT_NAME_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].parent").value(TEST_PARENT_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].cancerTypeId").value(TEST_TYPE_OF_CANCER_ID_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].name").value(TEST_NAME_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].dedicatedColor").value(TEST_DEDICATED_COLOR_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].shortName").value(TEST_SHORT_NAME_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].parent").value(TEST_PARENT_2)); + } + + @Test + @WithMockUser + public void getAllCancerTypesMetaProjection() throws Exception { + + BaseMeta baseMeta = new BaseMeta(); + baseMeta.setTotalCount(2); + + Mockito.when(cancerTypeService.getMetaCancerTypes()).thenReturn(baseMeta); + + mockMvc + .perform(MockMvcRequestBuilders.get("/api/cancer-types").param("projection", "META")) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect(MockMvcResultMatchers.header().string(HeaderKeyConstants.TOTAL_COUNT, "2")); + } + + @Test + @WithMockUser + public void getCancerTypeNotFound() throws Exception { + + Mockito.when(cancerTypeService.getCancerType(Mockito.anyString())) + .thenThrow(new CancerTypeNotFoundException("cancer_type_id")); + + mockMvc + .perform( + MockMvcRequestBuilders.get("/api/cancer-types/cancer_type_id") + .accept(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.status().isNotFound()) + .andExpect( + MockMvcResultMatchers.jsonPath("$.message") + .value("Cancer type not found: cancer_type_id")); + } + + @Test + @WithMockUser + public void getCancerType() throws Exception { + + TypeOfCancer typeOfCancer = new TypeOfCancer(); + typeOfCancer.setTypeOfCancerId(TEST_TYPE_OF_CANCER_ID_1); + typeOfCancer.setName(TEST_NAME_1); + typeOfCancer.setDedicatedColor(TEST_DEDICATED_COLOR_1); + typeOfCancer.setShortName(TEST_SHORT_NAME_1); + typeOfCancer.setParent(TEST_PARENT_1); + + Mockito.when(cancerTypeService.getCancerType(Mockito.anyString())).thenReturn(typeOfCancer); + + mockMvc + .perform( + MockMvcRequestBuilders.get("/api/cancer-types/cancer_type_id") + .accept(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect( + MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.jsonPath("$.cancerTypeId").value(TEST_TYPE_OF_CANCER_ID_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$.name").value(TEST_NAME_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$.dedicatedColor").value(TEST_DEDICATED_COLOR_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$.shortName").value(TEST_SHORT_NAME_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$.parent").value(TEST_PARENT_1)); + } +} diff --git a/src/test/java/org/cbioportal/legacy/web/ClinicalAttributeControllerTest.java b/src/test/java/org/cbioportal/legacy/web/ClinicalAttributeControllerTest.java new file mode 100644 index 00000000000..6655d135e1c --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/web/ClinicalAttributeControllerTest.java @@ -0,0 +1,313 @@ +package org.cbioportal.legacy.web; + +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; + +import com.fasterxml.jackson.databind.ObjectMapper; +import java.util.ArrayList; +import java.util.List; +import org.cbioportal.legacy.model.ClinicalAttribute; +import org.cbioportal.legacy.model.meta.BaseMeta; +import org.cbioportal.legacy.service.ClinicalAttributeService; +import org.cbioportal.legacy.service.exception.ClinicalAttributeNotFoundException; +import org.cbioportal.legacy.web.config.TestConfig; +import org.cbioportal.legacy.web.parameter.HeaderKeyConstants; +import org.hamcrest.Matchers; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mockito; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; +import org.springframework.security.test.context.support.WithMockUser; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.result.MockMvcResultMatchers; + +@RunWith(SpringJUnit4ClassRunner.class) +@WebMvcTest +@ContextConfiguration(classes = {ClinicalAttributeController.class, TestConfig.class}) +public class ClinicalAttributeControllerTest { + + private static final String TEST_ATTR_ID_1 = "test_attr_id_1"; + private static final int TEST_CANCER_STUDY_ID_1 = 1; + private static final String TEST_CANCER_STUDY_IDENTIFIER_1 = "test_study_1"; + private static final String TEST_SAMPLE_ID_1 = "test_sample_id_1"; + private static final String TEST_DATATYPE_1 = "test_datatype_1"; + private static final String TEST_DESCRIPTION_1 = "test_description_1"; + private static final String TEST_DISPLAY_NAME_1 = "test_display_name_1"; + private static final boolean TEST_PATIENT_ATTRIBUTE_1 = true; + private static final String TEST_PRIORITY_1 = "test_priority_1"; + private static final Integer TEST_ATTRIBUTE_COUNT_1 = 3; + private static final String TEST_ATTR_ID_2 = "test_attr_id_2"; + private static final int TEST_CANCER_STUDY_ID_2 = 2; + private static final String TEST_CANCER_STUDY_IDENTIFIER_2 = "test_study_2"; + private static final String TEST_SAMPLE_ID_2 = "test_sample_id_2"; + private static final String TEST_DATATYPE_2 = "test_datatype_2"; + private static final String TEST_DESCRIPTION_2 = "test_description_2"; + private static final String TEST_DISPLAY_NAME_2 = "test_display_name_2"; + private static final boolean TEST_PATIENT_ATTRIBUTE_2 = false; + private static final String TEST_PRIORITY_2 = "test_priority_2"; + private static final Integer TEST_ATTRIBUTE_COUNT_2 = 1; + + @MockBean private ClinicalAttributeService clinicalAttributeService; + + private ObjectMapper objectMapper = new ObjectMapper(); + + @Autowired private MockMvc mockMvc; + + @Test + @WithMockUser + public void getAllClinicalAttributesDefaultProjection() throws Exception { + + List clinicalAttributes = createExampleClinicalAttributes(); + + Mockito.when( + clinicalAttributeService.getAllClinicalAttributes( + Mockito.any(), Mockito.any(), Mockito.any(), Mockito.any(), Mockito.any())) + .thenReturn(clinicalAttributes); + + mockMvc + .perform( + MockMvcRequestBuilders.get("/api/clinical-attributes") + .accept(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect( + MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.jsonPath("$", Matchers.hasSize(2))) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].cancerStudyId").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].clinicalAttributeId").value(TEST_ATTR_ID_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].studyId").value(TEST_CANCER_STUDY_IDENTIFIER_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].datatype").value(TEST_DATATYPE_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].displayName").value(TEST_DISPLAY_NAME_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].patientAttribute").value(TEST_PATIENT_ATTRIBUTE_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].description").value(TEST_DESCRIPTION_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].priority").value(TEST_PRIORITY_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].cancerStudyId").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].clinicalAttributeId").value(TEST_ATTR_ID_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].studyId").value(TEST_CANCER_STUDY_IDENTIFIER_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].datatype").value(TEST_DATATYPE_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].displayName").value(TEST_DISPLAY_NAME_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].patientAttribute").value(TEST_PATIENT_ATTRIBUTE_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].description").value(TEST_DESCRIPTION_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].priority").value(TEST_PRIORITY_2)); + } + + @Test + @WithMockUser + public void getAllClinicalAttributesMetaProjection() throws Exception { + + BaseMeta baseMeta = new BaseMeta(); + baseMeta.setTotalCount(2); + + Mockito.when(clinicalAttributeService.getMetaClinicalAttributes()).thenReturn(baseMeta); + + mockMvc + .perform(MockMvcRequestBuilders.get("/api/clinical-attributes").param("projection", "META")) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect(MockMvcResultMatchers.header().string(HeaderKeyConstants.TOTAL_COUNT, "2")); + } + + @Test + @WithMockUser + public void getAllClinicalAttributesInStudyDefaultProjection() throws Exception { + + List clinicalAttributes = createExampleClinicalAttributes(); + + Mockito.when( + clinicalAttributeService.getAllClinicalAttributesInStudy( + Mockito.any(), + Mockito.any(), + Mockito.any(), + Mockito.any(), + Mockito.any(), + Mockito.any())) + .thenReturn(clinicalAttributes); + + mockMvc + .perform( + MockMvcRequestBuilders.get("/api/studies/test_study_id/clinical-attributes") + .accept(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect( + MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.jsonPath("$", Matchers.hasSize(2))) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].cancerStudyId").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].clinicalAttributeId").value(TEST_ATTR_ID_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].studyId").value(TEST_CANCER_STUDY_IDENTIFIER_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].datatype").value(TEST_DATATYPE_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].displayName").value(TEST_DISPLAY_NAME_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].patientAttribute").value(TEST_PATIENT_ATTRIBUTE_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].description").value(TEST_DESCRIPTION_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].priority").value(TEST_PRIORITY_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].cancerStudyId").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].clinicalAttributeId").value(TEST_ATTR_ID_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].studyId").value(TEST_CANCER_STUDY_IDENTIFIER_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].datatype").value(TEST_DATATYPE_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].displayName").value(TEST_DISPLAY_NAME_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].patientAttribute").value(TEST_PATIENT_ATTRIBUTE_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].description").value(TEST_DESCRIPTION_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].priority").value(TEST_PRIORITY_2)); + } + + @Test + @WithMockUser + public void getAllClinicalAttributesInStudyMetaProjection() throws Exception { + + BaseMeta baseMeta = new BaseMeta(); + baseMeta.setTotalCount(2); + + Mockito.when(clinicalAttributeService.getMetaClinicalAttributesInStudy(Mockito.anyString())) + .thenReturn(baseMeta); + + mockMvc + .perform( + MockMvcRequestBuilders.get("/api/studies/test_study_id/clinical-attributes") + .param("projection", "META")) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect(MockMvcResultMatchers.header().string(HeaderKeyConstants.TOTAL_COUNT, "2")); + } + + @Test + @WithMockUser + public void getClinicalAttributeInStudyNotFound() throws Exception { + + Mockito.when( + clinicalAttributeService.getClinicalAttribute(Mockito.anyString(), Mockito.anyString())) + .thenThrow( + new ClinicalAttributeNotFoundException("test_study_id", "test_clinical_attribute_id")); + + mockMvc + .perform( + MockMvcRequestBuilders.get( + "/api/studies/test_study_id/clinical-attributes/test_clinical_attribute_id") + .accept(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.status().isNotFound()) + .andExpect( + MockMvcResultMatchers.jsonPath("$.message") + .value( + "Clinical attribute not found in study test_study_id: test_clinical_attribute_id")); + } + + @Test + @WithMockUser + public void getClinicalAttributeInStudy() throws Exception { + + ClinicalAttribute clinicalAttribute = new ClinicalAttribute(); + clinicalAttribute.setAttrId(TEST_ATTR_ID_1); + clinicalAttribute.setCancerStudyId(TEST_CANCER_STUDY_ID_1); + clinicalAttribute.setCancerStudyIdentifier(TEST_CANCER_STUDY_IDENTIFIER_1); + clinicalAttribute.setDatatype(TEST_DATATYPE_1); + clinicalAttribute.setDescription(TEST_DESCRIPTION_1); + clinicalAttribute.setDisplayName(TEST_DISPLAY_NAME_1); + clinicalAttribute.setPatientAttribute(TEST_PATIENT_ATTRIBUTE_1); + clinicalAttribute.setPriority(TEST_PRIORITY_1); + + Mockito.when( + clinicalAttributeService.getClinicalAttribute(Mockito.anyString(), Mockito.anyString())) + .thenReturn(clinicalAttribute); + + mockMvc + .perform( + MockMvcRequestBuilders.get( + "/api/studies/test_study_id/clinical-attributes/test_clinical_attribute_id") + .accept(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect( + MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.jsonPath("$.cancerStudyId").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$.clinicalAttributeId").value(TEST_ATTR_ID_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$.studyId").value(TEST_CANCER_STUDY_IDENTIFIER_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$.datatype").value(TEST_DATATYPE_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$.displayName").value(TEST_DISPLAY_NAME_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$.patientAttribute").value(TEST_PATIENT_ATTRIBUTE_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$.description").value(TEST_DESCRIPTION_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$.priority").value(TEST_PRIORITY_1)); + } + + @Test + @WithMockUser + public void fetchClinicalAttributes() throws Exception { + + List clinicalAttributes = createExampleClinicalAttributes(); + + Mockito.when( + clinicalAttributeService.fetchClinicalAttributes( + Mockito.anyList(), Mockito.anyString())) + .thenReturn(clinicalAttributes); + + List studyIds = new ArrayList<>(); + studyIds.add("study_id_1"); + studyIds.add("study_id_2"); + + mockMvc + .perform( + MockMvcRequestBuilders.post("/api/clinical-attributes/fetch") + .with(csrf()) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(studyIds))) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect( + MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.jsonPath("$", Matchers.hasSize(2))) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].cancerStudyId").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].clinicalAttributeId").value(TEST_ATTR_ID_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].studyId").value(TEST_CANCER_STUDY_IDENTIFIER_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].datatype").value(TEST_DATATYPE_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].displayName").value(TEST_DISPLAY_NAME_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].patientAttribute").value(TEST_PATIENT_ATTRIBUTE_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].description").value(TEST_DESCRIPTION_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].priority").value(TEST_PRIORITY_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].cancerStudyId").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].clinicalAttributeId").value(TEST_ATTR_ID_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].studyId").value(TEST_CANCER_STUDY_IDENTIFIER_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].datatype").value(TEST_DATATYPE_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].displayName").value(TEST_DISPLAY_NAME_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].patientAttribute").value(TEST_PATIENT_ATTRIBUTE_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].description").value(TEST_DESCRIPTION_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].priority").value(TEST_PRIORITY_2)); + } + + private List createExampleClinicalAttributes() { + + List clinicalAttributeList = new ArrayList<>(); + ClinicalAttribute clinicalAttribute1 = new ClinicalAttribute(); + clinicalAttribute1.setAttrId(TEST_ATTR_ID_1); + clinicalAttribute1.setCancerStudyId(TEST_CANCER_STUDY_ID_1); + clinicalAttribute1.setCancerStudyIdentifier(TEST_CANCER_STUDY_IDENTIFIER_1); + clinicalAttribute1.setDatatype(TEST_DATATYPE_1); + clinicalAttribute1.setDescription(TEST_DESCRIPTION_1); + clinicalAttribute1.setDisplayName(TEST_DISPLAY_NAME_1); + clinicalAttribute1.setPatientAttribute(TEST_PATIENT_ATTRIBUTE_1); + clinicalAttribute1.setPriority(TEST_PRIORITY_1); + clinicalAttributeList.add(clinicalAttribute1); + ClinicalAttribute clinicalAttribute2 = new ClinicalAttribute(); + clinicalAttribute2.setAttrId(TEST_ATTR_ID_2); + clinicalAttribute2.setCancerStudyId(TEST_CANCER_STUDY_ID_2); + clinicalAttribute2.setCancerStudyIdentifier(TEST_CANCER_STUDY_IDENTIFIER_2); + clinicalAttribute2.setDatatype(TEST_DATATYPE_2); + clinicalAttribute2.setDescription(TEST_DESCRIPTION_2); + clinicalAttribute2.setDisplayName(TEST_DISPLAY_NAME_2); + clinicalAttribute2.setPatientAttribute(TEST_PATIENT_ATTRIBUTE_2); + clinicalAttribute2.setPriority(TEST_PRIORITY_2); + clinicalAttributeList.add(clinicalAttribute2); + return clinicalAttributeList; + } +} diff --git a/src/test/java/org/cbioportal/legacy/web/ClinicalAttributeCountControllerTest.java b/src/test/java/org/cbioportal/legacy/web/ClinicalAttributeCountControllerTest.java new file mode 100644 index 00000000000..90de5ab45eb --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/web/ClinicalAttributeCountControllerTest.java @@ -0,0 +1,133 @@ +package org.cbioportal.legacy.web; + +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; + +import com.fasterxml.jackson.databind.ObjectMapper; +import java.util.ArrayList; +import java.util.List; +import org.cbioportal.legacy.model.ClinicalAttributeCount; +import org.cbioportal.legacy.service.ClinicalAttributeService; +import org.cbioportal.legacy.web.config.TestConfig; +import org.cbioportal.legacy.web.parameter.ClinicalAttributeCountFilter; +import org.cbioportal.legacy.web.parameter.SampleIdentifier; +import org.hamcrest.Matchers; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mockito; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; +import org.springframework.security.test.context.support.WithMockUser; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.result.MockMvcResultMatchers; + +@RunWith(SpringJUnit4ClassRunner.class) +@WebMvcTest +@ContextConfiguration(classes = {ClinicalAttributeCountController.class, TestConfig.class}) +public class ClinicalAttributeCountControllerTest { + + private static final String TEST_ATTR_ID_1 = "test_attr_id_1"; + private static final String TEST_CANCER_STUDY_IDENTIFIER_1 = "test_study_1"; + private static final String TEST_SAMPLE_ID_1 = "test_sample_id_1"; + private static final Integer TEST_ATTRIBUTE_COUNT_1 = 3; + private static final String TEST_ATTR_ID_2 = "test_attr_id_2"; + private static final String TEST_SAMPLE_ID_2 = "test_sample_id_2"; + private static final Integer TEST_ATTRIBUTE_COUNT_2 = 1; + + @MockBean private ClinicalAttributeService clinicalAttributeService; + + private ObjectMapper objectMapper = new ObjectMapper(); + + @Autowired private MockMvc mockMvc; + + @Test + @WithMockUser + public void getClinicalAttributeCountsBySampleIds() throws Exception { + + List clinicalAttributes = new ArrayList<>(); + ClinicalAttributeCount clinicalAttributeCount1 = new ClinicalAttributeCount(); + clinicalAttributeCount1.setAttrId(TEST_ATTR_ID_1); + clinicalAttributeCount1.setCount(TEST_ATTRIBUTE_COUNT_1); + clinicalAttributes.add(clinicalAttributeCount1); + ClinicalAttributeCount clinicalAttributeCount2 = new ClinicalAttributeCount(); + clinicalAttributeCount2.setAttrId(TEST_ATTR_ID_2); + clinicalAttributeCount2.setCount(TEST_ATTRIBUTE_COUNT_2); + clinicalAttributes.add(clinicalAttributeCount2); + + Mockito.when( + clinicalAttributeService.getClinicalAttributeCountsBySampleIds( + Mockito.any(), Mockito.any())) + .thenReturn(clinicalAttributes); + + ClinicalAttributeCountFilter clinicalAttributeCountFilter = new ClinicalAttributeCountFilter(); + List sampleIdentifierList = new ArrayList<>(); + SampleIdentifier sampleIdentifier1 = new SampleIdentifier(); + sampleIdentifier1.setSampleId(TEST_SAMPLE_ID_1); + sampleIdentifier1.setStudyId(TEST_CANCER_STUDY_IDENTIFIER_1); + sampleIdentifierList.add(sampleIdentifier1); + SampleIdentifier sampleIdentifier2 = new SampleIdentifier(); + sampleIdentifier2.setSampleId(TEST_SAMPLE_ID_2); + sampleIdentifier2.setStudyId(TEST_CANCER_STUDY_IDENTIFIER_1); + sampleIdentifierList.add(sampleIdentifier2); + clinicalAttributeCountFilter.setSampleIdentifiers(sampleIdentifierList); + + mockMvc + .perform( + MockMvcRequestBuilders.post("/api/clinical-attributes/counts/fetch") + .with(csrf()) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(clinicalAttributeCountFilter))) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect( + MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.jsonPath("$", Matchers.hasSize(2))) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].clinicalAttributeId").value(TEST_ATTR_ID_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].count").value(TEST_ATTRIBUTE_COUNT_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].clinicalAttributeId").value(TEST_ATTR_ID_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].count").value(TEST_ATTRIBUTE_COUNT_2)); + } + + @Test + @WithMockUser + public void getClinicalAttributeCountsBySampleListId() throws Exception { + + List clinicalAttributes = new ArrayList<>(); + ClinicalAttributeCount clinicalAttributeCount1 = new ClinicalAttributeCount(); + clinicalAttributeCount1.setAttrId(TEST_ATTR_ID_1); + clinicalAttributeCount1.setCount(TEST_ATTRIBUTE_COUNT_1); + clinicalAttributes.add(clinicalAttributeCount1); + ClinicalAttributeCount clinicalAttributeCount2 = new ClinicalAttributeCount(); + clinicalAttributeCount2.setAttrId(TEST_ATTR_ID_2); + clinicalAttributeCount2.setCount(TEST_ATTRIBUTE_COUNT_2); + clinicalAttributes.add(clinicalAttributeCount2); + + Mockito.when( + clinicalAttributeService.getClinicalAttributeCountsBySampleListId(Mockito.anyString())) + .thenReturn(clinicalAttributes); + + ClinicalAttributeCountFilter clinicalAttributeCountFilter = new ClinicalAttributeCountFilter(); + clinicalAttributeCountFilter.setSampleListId("test_sample_list_id"); + + mockMvc + .perform( + MockMvcRequestBuilders.post("/api/clinical-attributes/counts/fetch") + .with(csrf()) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(clinicalAttributeCountFilter)) + .param("projection", "DETAILED")) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect( + MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.jsonPath("$", Matchers.hasSize(2))) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].clinicalAttributeId").value(TEST_ATTR_ID_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].count").value(TEST_ATTRIBUTE_COUNT_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].clinicalAttributeId").value(TEST_ATTR_ID_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].count").value(TEST_ATTRIBUTE_COUNT_2)); + } +} diff --git a/src/test/java/org/cbioportal/legacy/web/ClinicalDataControllerTest.java b/src/test/java/org/cbioportal/legacy/web/ClinicalDataControllerTest.java new file mode 100644 index 00000000000..ca0954b87f6 --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/web/ClinicalDataControllerTest.java @@ -0,0 +1,389 @@ +package org.cbioportal.legacy.web; + +import static org.mockito.Mockito.*; +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; + +import com.fasterxml.jackson.databind.ObjectMapper; +import java.util.ArrayList; +import java.util.List; +import org.cbioportal.legacy.model.ClinicalData; +import org.cbioportal.legacy.model.meta.BaseMeta; +import org.cbioportal.legacy.service.ClinicalDataService; +import org.cbioportal.legacy.web.config.CustomObjectMapper; +import org.cbioportal.legacy.web.config.TestConfig; +import org.cbioportal.legacy.web.parameter.ClinicalDataIdentifier; +import org.cbioportal.legacy.web.parameter.ClinicalDataMultiStudyFilter; +import org.cbioportal.legacy.web.parameter.ClinicalDataSingleStudyFilter; +import org.cbioportal.legacy.web.parameter.HeaderKeyConstants; +import org.hamcrest.Matchers; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; +import org.springframework.security.test.context.support.WithMockUser; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.result.MockMvcResultMatchers; + +@RunWith(SpringJUnit4ClassRunner.class) +@WebMvcTest +@ContextConfiguration(classes = {ClinicalDataController.class, TestConfig.class}) +public class ClinicalDataControllerTest { + + private static final String TEST_ATTR_ID_1 = "test_attr_id_1"; + private static final String TEST_ATTR_VALUE_1 = "test_attr_value_1"; + private static final int TEST_INTERNAL_ID_1 = 1; + private static final String TEST_ATTR_ID_2 = "test_attr_id_2"; + private static final String TEST_ATTR_VALUE_2 = "test_attr_value_2"; + private static final int TEST_INTERNAL_ID_2 = 2; + + @MockBean private ClinicalDataService clinicalDataService; + + private ObjectMapper objectMapper = new CustomObjectMapper(); + + @Autowired private MockMvc mockMvc; + + @Test + @WithMockUser + public void getAllClinicalDataOfSampleInStudyDefaultProjection() throws Exception { + + List sampleClinicalDataList = new ArrayList<>(); + ClinicalData sampleClinicalData1 = new ClinicalData(); + sampleClinicalData1.setAttrId(TEST_ATTR_ID_1); + sampleClinicalData1.setAttrValue(TEST_ATTR_VALUE_1); + sampleClinicalData1.setInternalId(TEST_INTERNAL_ID_1); + sampleClinicalDataList.add(sampleClinicalData1); + ClinicalData sampleClinicalData2 = new ClinicalData(); + sampleClinicalData2.setAttrId(TEST_ATTR_ID_2); + sampleClinicalData2.setAttrValue(TEST_ATTR_VALUE_2); + sampleClinicalData2.setInternalId(TEST_INTERNAL_ID_2); + sampleClinicalDataList.add(sampleClinicalData2); + when(clinicalDataService.getAllClinicalDataOfSampleInStudy( + any(), any(), any(), any(), any(), any(), any(), any())) + .thenReturn(sampleClinicalDataList); + + mockMvc + .perform( + MockMvcRequestBuilders.get( + "/api/studies/test_study_id/samples/test_sample_id/clinical-data") + .accept(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect( + MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.jsonPath("$", Matchers.hasSize(2))) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].clinicalAttributeId").value(TEST_ATTR_ID_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].value").value(TEST_ATTR_VALUE_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].internalId").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].sample").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].clinicalAttribute").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].clinicalAttributeId").value(TEST_ATTR_ID_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].value").value(TEST_ATTR_VALUE_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].internalId").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].sample").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].clinicalAttribute").doesNotExist()); + } + + @Test + @WithMockUser + public void getAllClinicalDataOfSampleInStudyMetaProjection() throws Exception { + + BaseMeta baseMeta = new BaseMeta(); + baseMeta.setTotalCount(2); + + when(clinicalDataService.getMetaSampleClinicalData(any(), any(), any())).thenReturn(baseMeta); + + mockMvc + .perform( + MockMvcRequestBuilders.get( + "/api/studies/test_study_id/samples/test_sample_id/clinical-data") + .param("projection", "META")) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect(MockMvcResultMatchers.header().string(HeaderKeyConstants.TOTAL_COUNT, "2")); + } + + @Test + @WithMockUser + public void getAllClinicalDataOfPatientInStudyDefaultProjection() throws Exception { + + List patientClinicalDataList = new ArrayList<>(); + ClinicalData patientClinicalData1 = new ClinicalData(); + patientClinicalData1.setAttrId(TEST_ATTR_ID_1); + patientClinicalData1.setAttrValue(TEST_ATTR_VALUE_1); + patientClinicalData1.setInternalId(TEST_INTERNAL_ID_1); + patientClinicalDataList.add(patientClinicalData1); + ClinicalData patientClinicalData2 = new ClinicalData(); + patientClinicalData2.setAttrId(TEST_ATTR_ID_2); + patientClinicalData2.setAttrValue(TEST_ATTR_VALUE_2); + patientClinicalData2.setInternalId(TEST_INTERNAL_ID_2); + patientClinicalDataList.add(patientClinicalData2); + when(clinicalDataService.getAllClinicalDataOfPatientInStudy( + any(), any(), any(), any(), any(), any(), any(), any())) + .thenReturn(patientClinicalDataList); + + mockMvc + .perform( + MockMvcRequestBuilders.get( + "/api/studies/test_study_id/patients/test_patient_id/clinical-data") + .accept(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect( + MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.jsonPath("$", Matchers.hasSize(2))) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].clinicalAttributeId").value(TEST_ATTR_ID_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].value").value(TEST_ATTR_VALUE_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].internalId").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].patient").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].clinicalAttribute").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].clinicalAttributeId").value(TEST_ATTR_ID_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].value").value(TEST_ATTR_VALUE_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].internalId").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].patient").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].clinicalAttribute").doesNotExist()); + } + + @Test + @WithMockUser + public void getAllClinicalDataOfPatientInStudyMetaProjection() throws Exception { + + BaseMeta baseMeta = new BaseMeta(); + baseMeta.setTotalCount(2); + + when(clinicalDataService.getMetaPatientClinicalData(any(), any(), any())).thenReturn(baseMeta); + + mockMvc + .perform( + MockMvcRequestBuilders.get( + "/api/studies/test_study_id/patients/test_patient_id/clinical-data") + .param("projection", "META")) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect(MockMvcResultMatchers.header().string(HeaderKeyConstants.TOTAL_COUNT, "2")); + } + + @Test + @WithMockUser + public void getAllClinicalDataInStudyDefaultProjection() throws Exception { + + List patientClinicalDataList = new ArrayList<>(); + ClinicalData patientClinicalData1 = new ClinicalData(); + patientClinicalData1.setAttrId(TEST_ATTR_ID_1); + patientClinicalData1.setAttrValue(TEST_ATTR_VALUE_1); + patientClinicalData1.setInternalId(TEST_INTERNAL_ID_1); + patientClinicalDataList.add(patientClinicalData1); + ClinicalData patientClinicalData2 = new ClinicalData(); + patientClinicalData2.setAttrId(TEST_ATTR_ID_2); + patientClinicalData2.setAttrValue(TEST_ATTR_VALUE_2); + patientClinicalData2.setInternalId(TEST_INTERNAL_ID_2); + patientClinicalDataList.add(patientClinicalData2); + when(clinicalDataService.getAllClinicalDataInStudy( + any(), any(), any(), any(), any(), any(), any(), any())) + .thenReturn(patientClinicalDataList); + + mockMvc + .perform( + MockMvcRequestBuilders.get("/api/studies/test_study_id/clinical-data") + .param("clinicalDataType", "PATIENT") + .accept(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect( + MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.jsonPath("$", Matchers.hasSize(2))) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].clinicalAttributeId").value(TEST_ATTR_ID_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].value").value(TEST_ATTR_VALUE_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].internalId").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].patient").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].clinicalAttribute").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].clinicalAttributeId").value(TEST_ATTR_ID_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].value").value(TEST_ATTR_VALUE_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].internalId").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].patient").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].clinicalAttribute").doesNotExist()); + } + + @Test + @WithMockUser + public void getAllClinicalDataInStudyMetaProjection() throws Exception { + + BaseMeta baseMeta = new BaseMeta(); + baseMeta.setTotalCount(2); + + when(clinicalDataService.getMetaAllClinicalData(any(), any(), any())).thenReturn(baseMeta); + + mockMvc + .perform( + MockMvcRequestBuilders.get("/api/studies/test_study_id/clinical-data") + .param("projection", "META") + .param("clinicalDataType", "PATIENT")) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect(MockMvcResultMatchers.header().string(HeaderKeyConstants.TOTAL_COUNT, "2")); + } + + @Test + @WithMockUser + public void fetchClinicalDataInStudyDefaultProjection() throws Exception { + + List patientClinicalDataList = new ArrayList<>(); + ClinicalData patientClinicalData1 = new ClinicalData(); + patientClinicalData1.setAttrId(TEST_ATTR_ID_1); + patientClinicalData1.setAttrValue(TEST_ATTR_VALUE_1); + patientClinicalData1.setInternalId(TEST_INTERNAL_ID_1); + patientClinicalDataList.add(patientClinicalData1); + ClinicalData patientClinicalData2 = new ClinicalData(); + patientClinicalData2.setAttrId(TEST_ATTR_ID_2); + patientClinicalData2.setAttrValue(TEST_ATTR_VALUE_2); + patientClinicalData2.setInternalId(TEST_INTERNAL_ID_2); + patientClinicalDataList.add(patientClinicalData2); + when(clinicalDataService.fetchAllClinicalDataInStudy(any(), any(), any(), any(), any())) + .thenReturn(patientClinicalDataList); + + List ids = new ArrayList<>(); + ids.add("test_sample_id_1"); + ids.add("test_sample_id_2"); + ClinicalDataSingleStudyFilter clinicalDataSingleStudyFilter = + new ClinicalDataSingleStudyFilter(); + clinicalDataSingleStudyFilter.setIds(ids); + + mockMvc + .perform( + MockMvcRequestBuilders.post("/api/studies/test_study_id/clinical-data/fetch") + .with(csrf()) + .param("clinicalDataType", "SAMPLE") + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(clinicalDataSingleStudyFilter))) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect( + MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.jsonPath("$", Matchers.hasSize(2))) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].clinicalAttributeId").value(TEST_ATTR_ID_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].value").value(TEST_ATTR_VALUE_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].internalId").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].patient").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].clinicalAttribute").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].clinicalAttributeId").value(TEST_ATTR_ID_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].value").value(TEST_ATTR_VALUE_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].internalId").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].patient").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].clinicalAttribute").doesNotExist()); + } + + @Test + @WithMockUser + public void fetchClinicalDataInStudyMetaProjection() throws Exception { + + BaseMeta baseMeta = new BaseMeta(); + baseMeta.setTotalCount(2); + + when(clinicalDataService.fetchMetaClinicalDataInStudy(any(), any(), any(), any())) + .thenReturn(baseMeta); + + List ids = new ArrayList<>(); + ids.add("test_sample_id_1"); + ids.add("test_sample_id_2"); + ClinicalDataSingleStudyFilter clinicalDataSingleStudyFilter = + new ClinicalDataSingleStudyFilter(); + clinicalDataSingleStudyFilter.setIds(ids); + + mockMvc + .perform( + MockMvcRequestBuilders.post("/api/studies/test_study_id/clinical-data/fetch") + .with(csrf()) + .param("projection", "META") + .param("clinicalDataType", "SAMPLE") + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(clinicalDataSingleStudyFilter))) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect(MockMvcResultMatchers.header().string(HeaderKeyConstants.TOTAL_COUNT, "2")); + } + + @Test + @WithMockUser + public void fetchClinicalDataDefaultProjection() throws Exception { + + List patientClinicalDataList = new ArrayList<>(); + ClinicalData patientClinicalData1 = new ClinicalData(); + patientClinicalData1.setAttrId(TEST_ATTR_ID_1); + patientClinicalData1.setAttrValue(TEST_ATTR_VALUE_1); + patientClinicalData1.setInternalId(TEST_INTERNAL_ID_1); + patientClinicalDataList.add(patientClinicalData1); + ClinicalData patientClinicalData2 = new ClinicalData(); + patientClinicalData2.setAttrId(TEST_ATTR_ID_2); + patientClinicalData2.setAttrValue(TEST_ATTR_VALUE_2); + patientClinicalData2.setInternalId(TEST_INTERNAL_ID_2); + patientClinicalDataList.add(patientClinicalData2); + when(clinicalDataService.fetchClinicalData(any(), any(), any(), any(), any())) + .thenReturn(patientClinicalDataList); + + List clinicalDataIdentifiers = new ArrayList<>(); + ClinicalDataIdentifier clinicalDataIdentifier1 = new ClinicalDataIdentifier(); + clinicalDataIdentifier1.setStudyId("test_study1"); + clinicalDataIdentifier1.setEntityId("test_patient1"); + clinicalDataIdentifiers.add(clinicalDataIdentifier1); + ClinicalDataIdentifier clinicalDataIdentifier2 = new ClinicalDataIdentifier(); + clinicalDataIdentifier2.setStudyId("test_study2"); + clinicalDataIdentifier2.setEntityId("test_patient2"); + clinicalDataIdentifiers.add(clinicalDataIdentifier2); + ClinicalDataMultiStudyFilter clinicalDataMultiStudyFilter = new ClinicalDataMultiStudyFilter(); + clinicalDataMultiStudyFilter.setIdentifiers(clinicalDataIdentifiers); + + mockMvc + .perform( + MockMvcRequestBuilders.post("/api/clinical-data/fetch") + .with(csrf()) + .param("clinicalDataType", "PATIENT") + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(clinicalDataMultiStudyFilter))) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect( + MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.jsonPath("$", Matchers.hasSize(2))) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].clinicalAttributeId").value(TEST_ATTR_ID_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].value").value(TEST_ATTR_VALUE_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].internalId").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].patient").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].clinicalAttribute").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].clinicalAttributeId").value(TEST_ATTR_ID_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].value").value(TEST_ATTR_VALUE_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].internalId").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].patient").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].clinicalAttribute").doesNotExist()); + } + + @Test + @WithMockUser + public void fetchClinicalDataMetaProjection() throws Exception { + + BaseMeta baseMeta = new BaseMeta(); + baseMeta.setTotalCount(2); + + when(clinicalDataService.fetchMetaClinicalData(any(), any(), any(), any())) + .thenReturn(baseMeta); + + List clinicalDataIdentifiers = new ArrayList<>(); + ClinicalDataIdentifier clinicalDataIdentifier1 = new ClinicalDataIdentifier(); + clinicalDataIdentifier1.setStudyId("test_study1"); + clinicalDataIdentifier1.setEntityId("test_patient1"); + clinicalDataIdentifiers.add(clinicalDataIdentifier1); + ClinicalDataIdentifier clinicalDataIdentifier2 = new ClinicalDataIdentifier(); + clinicalDataIdentifier2.setStudyId("test_study2"); + clinicalDataIdentifier2.setEntityId("test_patient2"); + clinicalDataIdentifiers.add(clinicalDataIdentifier2); + ClinicalDataMultiStudyFilter clinicalDataMultiStudyFilter = new ClinicalDataMultiStudyFilter(); + clinicalDataMultiStudyFilter.setIdentifiers(clinicalDataIdentifiers); + + mockMvc + .perform( + MockMvcRequestBuilders.post("/api/clinical-data/fetch") + .with(csrf()) + .param("projection", "META") + .param("clinicalDataType", "PATIENT") + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(clinicalDataMultiStudyFilter))) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect(MockMvcResultMatchers.header().string(HeaderKeyConstants.TOTAL_COUNT, "2")); + } +} diff --git a/src/test/java/org/cbioportal/legacy/web/ClinicalDataEnrichmentControllerTest.java b/src/test/java/org/cbioportal/legacy/web/ClinicalDataEnrichmentControllerTest.java new file mode 100644 index 00000000000..a52b839d95d --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/web/ClinicalDataEnrichmentControllerTest.java @@ -0,0 +1,285 @@ +package org.cbioportal.legacy.web; + +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; + +import com.fasterxml.jackson.databind.ObjectMapper; +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import org.cbioportal.legacy.model.ClinicalAttribute; +import org.cbioportal.legacy.model.ClinicalDataEnrichment; +import org.cbioportal.legacy.model.Sample; +import org.cbioportal.legacy.service.ClinicalAttributeService; +import org.cbioportal.legacy.service.SampleService; +import org.cbioportal.legacy.web.config.TestConfig; +import org.cbioportal.legacy.web.parameter.Group; +import org.cbioportal.legacy.web.parameter.GroupFilter; +import org.cbioportal.legacy.web.parameter.SampleIdentifier; +import org.cbioportal.legacy.web.util.ClinicalDataEnrichmentUtil; +import org.hamcrest.Matchers; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mockito; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; +import org.springframework.security.test.context.support.WithMockUser; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.result.MockMvcResultMatchers; + +@RunWith(SpringJUnit4ClassRunner.class) +@WebMvcTest +@ContextConfiguration(classes = {ClinicalDataEnrichmentController.class, TestConfig.class}) +public class ClinicalDataEnrichmentControllerTest { + + public static final String STUDY_ID1 = "study_id1"; + public static final String STUDY_ID2 = "study_id2"; + public static final String SAMPLE_ID1 = "sample_id1"; + public static final String SAMPLE_ID2 = "sample_id2"; + public static final String SAMPLE_ID3 = "sample_id3"; + public static final String SAMPLE_ID4 = "sample_id4"; + public static final String SAMPLE_ID5 = "sample_id5"; + public static final String PATIENT_ID1 = "patient_id1"; + public static final String PATIENT_ID2 = "patient_id2"; + public static final String PATIENT_ID3 = "patient_id3"; + public static final String PATIENT_ID4 = "patient_id4"; + public static final String PATIENT_ID5 = "patient_id5"; + + public static final String CLINICAL_ATTRIBUTE_ID_1 = "attribute_id1"; + public static final String CLINICAL_ATTRIBUTE_ID_2 = "attribute_id2"; + public static final String CLINICAL_ATTRIBUTE_ID_3 = "attribute_id3"; + public static final String CLINICAL_ATTRIBUTE_ID_4 = "attribute_id4"; + + @MockBean private ClinicalDataEnrichmentUtil clinicalDataEnrichmentUtil; + + @MockBean private ClinicalAttributeService clinicalAttributeService; + + @MockBean private SampleService sampleService; + + @Autowired private MockMvc mockMvc; + + private ObjectMapper objectMapper = new ObjectMapper(); + + @Test + @WithMockUser + public void fetchClinicalDataCounts() throws Exception { + + SampleIdentifier sampleIdentifier1 = new SampleIdentifier(); + sampleIdentifier1.setSampleId(SAMPLE_ID1); + sampleIdentifier1.setStudyId(STUDY_ID1); + SampleIdentifier sampleIdentifier2 = new SampleIdentifier(); + sampleIdentifier2.setSampleId(SAMPLE_ID2); + sampleIdentifier2.setStudyId(STUDY_ID1); + SampleIdentifier sampleIdentifier3 = new SampleIdentifier(); + sampleIdentifier3.setSampleId(SAMPLE_ID3); + sampleIdentifier3.setStudyId(STUDY_ID2); + SampleIdentifier sampleIdentifier4 = new SampleIdentifier(); + sampleIdentifier4.setSampleId(SAMPLE_ID4); + sampleIdentifier4.setStudyId(STUDY_ID2); + SampleIdentifier sampleIdentifier5 = new SampleIdentifier(); + sampleIdentifier5.setSampleId(SAMPLE_ID5); + sampleIdentifier5.setStudyId(STUDY_ID2); + + Sample sample1 = new Sample(); + sample1.setStableId(SAMPLE_ID1); + sample1.setPatientStableId(PATIENT_ID1); + sample1.setCancerStudyIdentifier(STUDY_ID1); + + Sample sample2 = new Sample(); + sample2.setStableId(SAMPLE_ID2); + sample2.setPatientStableId(PATIENT_ID2); + sample2.setCancerStudyIdentifier(STUDY_ID1); + + Sample sample3 = new Sample(); + sample3.setStableId(SAMPLE_ID3); + sample3.setPatientStableId(PATIENT_ID3); + sample3.setCancerStudyIdentifier(STUDY_ID2); + + Sample sample4 = new Sample(); + sample4.setStableId(SAMPLE_ID4); + sample4.setPatientStableId(PATIENT_ID4); + sample4.setCancerStudyIdentifier(STUDY_ID2); + + Sample sample5 = new Sample(); + sample5.setStableId(SAMPLE_ID5); + sample5.setPatientStableId(PATIENT_ID5); + sample5.setCancerStudyIdentifier(STUDY_ID2); + + ClinicalAttribute attribute1 = new ClinicalAttribute(); + attribute1.setAttrId(CLINICAL_ATTRIBUTE_ID_1); + attribute1.setDatatype("STRING"); + attribute1.setPatientAttribute(false); + + ClinicalAttribute attribute2 = new ClinicalAttribute(); + attribute2.setAttrId(CLINICAL_ATTRIBUTE_ID_2); + attribute2.setDatatype("STRING"); + attribute2.setPatientAttribute(true); + + ClinicalAttribute attribute3 = new ClinicalAttribute(); + attribute3.setAttrId(CLINICAL_ATTRIBUTE_ID_3); + attribute3.setDatatype("NUMBER"); + attribute3.setPatientAttribute(true); + + ClinicalAttribute attribute4 = new ClinicalAttribute(); + attribute4.setAttrId(CLINICAL_ATTRIBUTE_ID_4); + attribute4.setDatatype("NUMBER"); + attribute4.setPatientAttribute(true); + + GroupFilter groupFilter = new GroupFilter(); + List groups = new ArrayList(); + groupFilter.setGroups(groups); + + mockMvc + .perform( + MockMvcRequestBuilders.post("/api/clinical-data-enrichments/fetch") + .accept(MediaType.APPLICATION_JSON) + .with(csrf()) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(groupFilter))) + .andExpect(MockMvcResultMatchers.status().isBadRequest()) + .andExpect( + MockMvcResultMatchers.jsonPath("$.message") + .value("interceptedGroupFilter size must be between 2 and 2147483647")); + + Group group1 = new Group(); + group1.setName("1"); + List sampleIdentifiers1 = new ArrayList(); + group1.setSampleIdentifiers(sampleIdentifiers1); + groups.add(group1); + + // "groups[0].sampleIdentifiers size must be between 1 and 10000000" + mockMvc + .perform( + MockMvcRequestBuilders.post("/api/clinical-data-enrichments/fetch") + .accept(MediaType.APPLICATION_JSON) + .with(csrf()) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(groupFilter))) + .andExpect(MockMvcResultMatchers.status().isBadRequest()); + + // "groups size must be between 2 and 2147483647" + mockMvc + .perform( + MockMvcRequestBuilders.post("/api/clinical-data-enrichments/fetch") + .accept(MediaType.APPLICATION_JSON) + .with(csrf()) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(groupFilter))) + .andExpect(MockMvcResultMatchers.status().isBadRequest()); + + Group group2 = new Group(); + group2.setName("1"); + List sampleIdentifiers2 = new ArrayList(); + group2.setSampleIdentifiers(sampleIdentifiers2); + groups.add(group2); + + group1.setSampleIdentifiers(Arrays.asList(sampleIdentifier1, sampleIdentifier2)); + + mockMvc + .perform( + MockMvcRequestBuilders.post("/api/clinical-data-enrichments/fetch") + .accept(MediaType.APPLICATION_JSON) + .with(csrf()) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(groupFilter))) + .andExpect(MockMvcResultMatchers.status().isBadRequest()) + .andExpect( + MockMvcResultMatchers.jsonPath("$.message") + .value("interceptedGroupFilter size must be between 1 and 10000000")); + + group2.setSampleIdentifiers( + new ArrayList( + Arrays.asList(sampleIdentifier3, sampleIdentifier4, sampleIdentifier5))); + + // when all are invalid samples + mockMvc + .perform( + MockMvcRequestBuilders.post("/api/clinical-data-enrichments/fetch") + .accept(MediaType.APPLICATION_JSON) + .with(csrf()) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(groupFilter))) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect(MockMvcResultMatchers.jsonPath("$", Matchers.hasSize(0))); + + Mockito.when( + sampleService.fetchSamples(Mockito.anyList(), Mockito.anyList(), Mockito.anyString())) + .thenReturn(Arrays.asList(sample1, sample2, sample3, sample4, sample5)); + + List attributes = Arrays.asList(attribute1, attribute3); + + Mockito.when( + clinicalAttributeService.fetchClinicalAttributes( + Arrays.asList(STUDY_ID2, STUDY_ID1), "SUMMARY")) + .thenReturn(attributes); + + List> groupedSamples = new ArrayList>(); + groupedSamples.add(Arrays.asList(sample1, sample2)); + groupedSamples.add(Arrays.asList(sample3, sample4, sample5)); + + // [{"score":4.999999999999999,"method":"Chi-squared + // Test","pValue":0.08208499862670093,"qValue":null},{"clinicalAttribute":{"attrId":"attribute_id2","displayName":null,"description":null,"datatype":"STRING","patientAttribute":true,"priority":null,"cancerStudyId":null,"cancerStudyIdentifier":null},"score":4.999999999999999,"method":"Chi-squared + // Test","pValue":0.08208499862670093,"qValue":null}] + + // [{"score":0.08771942638231253,"method":"Kruskal Wallis + // Test","pValue":0.7670968826920188,"qValue":null},{"clinicalAttribute":{"attrId":"attribute_id4","displayName":null,"description":null,"datatype":"NUMBER","patientAttribute":true,"priority":null,"cancerStudyId":null,"cancerStudyIdentifier":null},"score":0.7894737138614459,"method":"Kruskal + // Wallis Test","pValue":0.3742593665040995,"qValue":null}] + + ClinicalDataEnrichment clinicalDataEnrichment1 = new ClinicalDataEnrichment(); + clinicalDataEnrichment1.setClinicalAttribute(attribute1); + clinicalDataEnrichment1.setMethod("Chi-squared Test"); + clinicalDataEnrichment1.setpValue(new BigDecimal("0.08208499862670093")); + clinicalDataEnrichment1.setScore(new BigDecimal("4.999999999999999")); + + ClinicalDataEnrichment clinicalDataEnrichment = new ClinicalDataEnrichment(); + clinicalDataEnrichment.setClinicalAttribute(attribute3); + clinicalDataEnrichment.setMethod("Kruskal Wallis Test"); + clinicalDataEnrichment.setpValue(new BigDecimal("0.7670968826920188")); + clinicalDataEnrichment.setScore(new BigDecimal("0.08771942638231253")); + + Mockito.when( + clinicalDataEnrichmentUtil.createEnrichmentsForCategoricalData( + attributes, groupedSamples)) + .thenReturn(Arrays.asList(clinicalDataEnrichment1)); + + Mockito.when( + clinicalDataEnrichmentUtil.createEnrichmentsForNumericData(attributes, groupedSamples)) + .thenReturn(Arrays.asList(clinicalDataEnrichment)); + + mockMvc + .perform( + MockMvcRequestBuilders.post("/api/clinical-data-enrichments/fetch") + .accept(MediaType.APPLICATION_JSON) + .with(csrf()) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(groupFilter))) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect(MockMvcResultMatchers.jsonPath("$", Matchers.hasSize(2))) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].clinicalAttribute.clinicalAttributeId") + .value(clinicalDataEnrichment1.getClinicalAttribute().getAttrId())) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].score").value(clinicalDataEnrichment1.getScore())) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].pValue") + .value(clinicalDataEnrichment1.getpValue())) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].method") + .value(clinicalDataEnrichment1.getMethod())) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].clinicalAttribute.clinicalAttributeId") + .value(clinicalDataEnrichment.getClinicalAttribute().getAttrId())) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].score").value(clinicalDataEnrichment.getScore())) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].pValue").value(clinicalDataEnrichment.getpValue())) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].method") + .value(clinicalDataEnrichment.getMethod())); + } +} diff --git a/src/test/java/org/cbioportal/legacy/web/ClinicalEventControllerTest.java b/src/test/java/org/cbioportal/legacy/web/ClinicalEventControllerTest.java new file mode 100644 index 00000000000..f68a5857230 --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/web/ClinicalEventControllerTest.java @@ -0,0 +1,356 @@ +package org.cbioportal.legacy.web; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyList; +import static org.mockito.Mockito.when; +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; + +import com.fasterxml.jackson.databind.ObjectMapper; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import org.cbioportal.legacy.model.ClinicalEvent; +import org.cbioportal.legacy.model.ClinicalEventData; +import org.cbioportal.legacy.model.meta.BaseMeta; +import org.cbioportal.legacy.service.ClinicalEventService; +import org.cbioportal.legacy.web.config.TestConfig; +import org.cbioportal.legacy.web.parameter.ClinicalEventAttributeRequest; +import org.cbioportal.legacy.web.parameter.ClinicalEventRequest; +import org.cbioportal.legacy.web.parameter.HeaderKeyConstants; +import org.cbioportal.legacy.web.parameter.PatientIdentifier; +import org.hamcrest.Matchers; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mockito; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; +import org.springframework.security.test.context.support.WithMockUser; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.result.MockMvcResultMatchers; + +@RunWith(SpringJUnit4ClassRunner.class) +@WebMvcTest +@ContextConfiguration(classes = {ClinicalEventController.class, TestConfig.class}) +public class ClinicalEventControllerTest { + + private static final long TEST_CLINICAL_EVENT_ID_1 = 1L; + private static final String TEST_CANCER_STUDY_IDENTIFIER_1 = "test_study_1"; + private static final String TEST_PATIENT_ID_1 = "test_patient_id_1"; + private static final String TEST_EVENT_TYPE_1 = "test_event_type_1"; + private static final int TEST_START_DATE_1 = 123; + private static final int TEST_END_DATE_1 = 136; + private static final String TEST_KEY_1 = "test_key_1"; + private static final String TEST_VALUE_1 = "test_value_1"; + private static final String TEST_KEY_2 = "test_key_2"; + private static final String TEST_VALUE_2 = "test_value_2"; + private static final long TEST_CLINICAL_EVENT_ID_2 = 2L; + private static final String TEST_PATIENT_ID_2 = "test_patient_id_2"; + private static final String TEST_EVENT_TYPE_2 = "test_event_type_2"; + private static final int TEST_START_DATE_2 = 223; + private static final int TEST_END_DATE_2 = 236; + private static final String TEST_KEY_3 = "test_key_3"; + private static final String TEST_VALUE_3 = "test_value_3"; + private static final String TEST_KEY_4 = "test_key_4"; + private static final String TEST_VALUE_4 = "test_value_4"; + private static final String TEST_UNIQUE_PATIENT_KEY_1 = "test_unique_patient_key_1"; + private static final String TEST_UNIQUE_PATIENT_KEY_2 = "test_unique_patient_key_2"; + + private final ObjectMapper objectMapper = new ObjectMapper(); + + @MockBean private ClinicalEventService clinicalEventService; + + @Autowired private MockMvc mockMvc; + + @Test + @WithMockUser + public void getAllClinicalEventsOfPatientInStudy() throws Exception { + + List clinicalEventList = createExampleClinicalEventList(); + + when(clinicalEventService.getAllClinicalEventsOfPatientInStudy( + any(), any(), any(), any(), any(), any(), any())) + .thenReturn(clinicalEventList); + + mockMvc + .perform( + MockMvcRequestBuilders.get( + "/api/studies/test_study_id/patients/test_patient_id/clinical-events") + .accept(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect( + MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.jsonPath("$", Matchers.hasSize(2))) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].clinicalEventId").doesNotExist()) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].studyId").value(TEST_CANCER_STUDY_IDENTIFIER_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].patientId").value(TEST_PATIENT_ID_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].eventType").value(TEST_EVENT_TYPE_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].startNumberOfDaysSinceDiagnosis") + .value(TEST_START_DATE_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].endNumberOfDaysSinceDiagnosis") + .value(TEST_END_DATE_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].attributes[0].key").value(TEST_KEY_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].attributes[0].value").value(TEST_VALUE_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].attributes[1].key").value(TEST_KEY_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].attributes[1].value").value(TEST_VALUE_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].clinicalEventId").doesNotExist()) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].studyId").value(TEST_CANCER_STUDY_IDENTIFIER_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].patientId").value(TEST_PATIENT_ID_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].eventType").value(TEST_EVENT_TYPE_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].startNumberOfDaysSinceDiagnosis") + .value(TEST_START_DATE_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].endNumberOfDaysSinceDiagnosis") + .value(TEST_END_DATE_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].attributes[0].key").value(TEST_KEY_3)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].attributes[0].value").value(TEST_VALUE_3)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].attributes[1].key").value(TEST_KEY_4)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].attributes[1].value").value(TEST_VALUE_4)); + } + + @Test + @WithMockUser + public void getAllClinicalEventsOfPatientInStudyMetaProjection() throws Exception { + + BaseMeta baseMeta = new BaseMeta(); + baseMeta.setTotalCount(2); + + when(clinicalEventService.getMetaPatientClinicalEvents( + Mockito.anyString(), Mockito.anyString())) + .thenReturn(baseMeta); + + mockMvc + .perform( + MockMvcRequestBuilders.get( + "/api/studies/test_study_id/patients/test_patient_id/clinical-events") + .param("projection", "META")) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect(MockMvcResultMatchers.header().string(HeaderKeyConstants.TOTAL_COUNT, "2")); + } + + @Test + @WithMockUser + public void getAllClinicalEventsInStudy() throws Exception { + + List clinicalEventList = createExampleClinicalEventList(); + + when(clinicalEventService.getAllClinicalEventsInStudy(any(), any(), any(), any(), any(), any())) + .thenReturn(clinicalEventList); + + mockMvc + .perform( + MockMvcRequestBuilders.get("/api/studies/test_study_id/clinical-events") + .accept(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect( + MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.jsonPath("$", Matchers.hasSize(2))) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].clinicalEventId").doesNotExist()) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].studyId").value(TEST_CANCER_STUDY_IDENTIFIER_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].patientId").value(TEST_PATIENT_ID_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].eventType").value(TEST_EVENT_TYPE_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].startNumberOfDaysSinceDiagnosis") + .value(TEST_START_DATE_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].endNumberOfDaysSinceDiagnosis") + .value(TEST_END_DATE_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].attributes[0].key").value(TEST_KEY_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].attributes[0].value").value(TEST_VALUE_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].attributes[1].key").value(TEST_KEY_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].attributes[1].value").value(TEST_VALUE_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].clinicalEventId").doesNotExist()) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].studyId").value(TEST_CANCER_STUDY_IDENTIFIER_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].patientId").value(TEST_PATIENT_ID_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].eventType").value(TEST_EVENT_TYPE_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].startNumberOfDaysSinceDiagnosis") + .value(TEST_START_DATE_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].endNumberOfDaysSinceDiagnosis") + .value(TEST_END_DATE_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].attributes[0].key").value(TEST_KEY_3)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].attributes[0].value").value(TEST_VALUE_3)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].attributes[1].key").value(TEST_KEY_4)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].attributes[1].value").value(TEST_VALUE_4)); + } + + @Test + @WithMockUser + public void getAllClinicalEventsInStudyMetaProjection() throws Exception { + + BaseMeta baseMeta = new BaseMeta(); + baseMeta.setTotalCount(2); + + when(clinicalEventService.getMetaClinicalEvents(Mockito.anyString())).thenReturn(baseMeta); + + mockMvc + .perform( + MockMvcRequestBuilders.get("/api/studies/test_study_id/clinical-events") + .param("projection", "META")) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect(MockMvcResultMatchers.header().string(HeaderKeyConstants.TOTAL_COUNT, "2")); + } + + @Test + @WithMockUser + public void fetchClinicalEventsMetaReturnsOkForValidRequest() throws Exception { + List clinicalEventList = createExampleClinicalEventMetaList(); + when(clinicalEventService.getClinicalEventsMeta(anyList(), anyList(), anyList())) + .thenReturn(clinicalEventList); + + PatientIdentifier patientIdentifier1 = new PatientIdentifier(); + ClinicalEventAttributeRequest clinicalEventAttributeRequest = + new ClinicalEventAttributeRequest(); + ClinicalEventRequest clinicalEventRequest = new ClinicalEventRequest(); + clinicalEventRequest.setEventType(TEST_EVENT_TYPE_1); + clinicalEventRequest.setAttributes(new ArrayList<>()); + clinicalEventAttributeRequest.setClinicalEventRequests(Set.of(clinicalEventRequest)); + clinicalEventAttributeRequest.setPatientIdentifiers( + Collections.singletonList(patientIdentifier1)); + + mockMvc + .perform( + MockMvcRequestBuilders.post("/api/clinical-events-meta/fetch") + .with(csrf()) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(clinicalEventAttributeRequest))) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect( + MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.jsonPath("$", Matchers.hasSize(2))) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].clinicalEventId").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].eventType").value(TEST_EVENT_TYPE_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].uniquePatientKey") + .value(TEST_UNIQUE_PATIENT_KEY_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].attributes[0].key").value(TEST_KEY_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].attributes[0].value").value(TEST_VALUE_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].attributes[1].key").value(TEST_KEY_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].attributes[1].value").value(TEST_VALUE_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].clinicalEventId").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].eventType").value(TEST_EVENT_TYPE_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].uniquePatientKey") + .value(TEST_UNIQUE_PATIENT_KEY_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].attributes[0].key").value(TEST_KEY_3)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].attributes[0].value").value(TEST_VALUE_3)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].attributes[1].key").value(TEST_KEY_4)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].attributes[1].value").value(TEST_VALUE_4)); + } + + @Test + @WithMockUser + public void fetchClinicalEventsMetaReturnsBadRequestForInvalidRequest() throws Exception { + + ClinicalEventAttributeRequest clinicalEventAttributeRequest = + new ClinicalEventAttributeRequest(); + clinicalEventAttributeRequest.setClinicalEventRequests(new HashSet<>()); + clinicalEventAttributeRequest.setPatientIdentifiers(new ArrayList<>()); + + mockMvc + .perform( + MockMvcRequestBuilders.post("/api/clinical-events-meta/fetch") + .with(csrf()) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(clinicalEventAttributeRequest))) + .andExpect(MockMvcResultMatchers.status().isBadRequest()); + } + + private final List createExampleClinicalEventList() { + List clinicalEventList = new ArrayList<>(); + ClinicalEvent clinicalEvent1 = new ClinicalEvent(); + clinicalEvent1.setClinicalEventId(TEST_CLINICAL_EVENT_ID_1); + clinicalEvent1.setStudyId(TEST_CANCER_STUDY_IDENTIFIER_1); + clinicalEvent1.setPatientId(TEST_PATIENT_ID_1); + clinicalEvent1.setEventType(TEST_EVENT_TYPE_1); + clinicalEvent1.setStartDate(TEST_START_DATE_1); + clinicalEvent1.setStopDate(TEST_END_DATE_1); + List clinicalEventDataList1 = new ArrayList<>(); + ClinicalEventData clinicalEventData1 = new ClinicalEventData(); + clinicalEventData1.setClinicalEventId(TEST_CLINICAL_EVENT_ID_1); + clinicalEventData1.setKey(TEST_KEY_1); + clinicalEventData1.setValue(TEST_VALUE_1); + clinicalEventDataList1.add(clinicalEventData1); + ClinicalEventData clinicalEventData2 = new ClinicalEventData(); + clinicalEventData2.setClinicalEventId(TEST_CLINICAL_EVENT_ID_1); + clinicalEventData2.setKey(TEST_KEY_2); + clinicalEventData2.setValue(TEST_VALUE_2); + clinicalEventDataList1.add(clinicalEventData2); + clinicalEvent1.setAttributes(clinicalEventDataList1); + clinicalEventList.add(clinicalEvent1); + ClinicalEvent clinicalEvent2 = new ClinicalEvent(); + clinicalEvent2.setClinicalEventId(TEST_CLINICAL_EVENT_ID_2); + clinicalEvent2.setStudyId(TEST_CANCER_STUDY_IDENTIFIER_1); + clinicalEvent2.setPatientId(TEST_PATIENT_ID_2); + clinicalEvent2.setEventType(TEST_EVENT_TYPE_2); + clinicalEvent2.setStartDate(TEST_START_DATE_2); + clinicalEvent2.setStopDate(TEST_END_DATE_2); + List clinicalEventDataList2 = new ArrayList<>(); + ClinicalEventData clinicalEventData3 = new ClinicalEventData(); + clinicalEventData3.setClinicalEventId(TEST_CLINICAL_EVENT_ID_2); + clinicalEventData3.setKey(TEST_KEY_3); + clinicalEventData3.setValue(TEST_VALUE_3); + clinicalEventDataList2.add(clinicalEventData3); + ClinicalEventData clinicalEventData4 = new ClinicalEventData(); + clinicalEventData4.setClinicalEventId(TEST_CLINICAL_EVENT_ID_2); + clinicalEventData4.setKey(TEST_KEY_4); + clinicalEventData4.setValue(TEST_VALUE_4); + clinicalEventDataList2.add(clinicalEventData4); + clinicalEvent2.setAttributes(clinicalEventDataList2); + clinicalEventList.add(clinicalEvent2); + return clinicalEventList; + } + + private final List createExampleClinicalEventMetaList() { + List clinicalEventList = new ArrayList<>(); + ClinicalEvent clinicalEvent1 = new ClinicalEvent(); + clinicalEvent1.setUniquePatientKey(TEST_UNIQUE_PATIENT_KEY_1); + clinicalEvent1.setEventType(TEST_EVENT_TYPE_1); + List clinicalEventDataList1 = new ArrayList<>(); + ClinicalEventData clinicalEventData1 = new ClinicalEventData(); + clinicalEventData1.setClinicalEventId(TEST_CLINICAL_EVENT_ID_1); + clinicalEventData1.setKey(TEST_KEY_1); + clinicalEventData1.setValue(TEST_VALUE_1); + clinicalEventDataList1.add(clinicalEventData1); + ClinicalEventData clinicalEventData2 = new ClinicalEventData(); + clinicalEventData2.setClinicalEventId(TEST_CLINICAL_EVENT_ID_1); + clinicalEventData2.setKey(TEST_KEY_2); + clinicalEventData2.setValue(TEST_VALUE_2); + clinicalEventDataList1.add(clinicalEventData2); + clinicalEvent1.setAttributes(clinicalEventDataList1); + clinicalEventList.add(clinicalEvent1); + ClinicalEvent clinicalEvent2 = new ClinicalEvent(); + clinicalEvent2.setUniquePatientKey(TEST_UNIQUE_PATIENT_KEY_2); + clinicalEvent2.setEventType(TEST_EVENT_TYPE_2); + List clinicalEventDataList2 = new ArrayList<>(); + ClinicalEventData clinicalEventData3 = new ClinicalEventData(); + clinicalEventData3.setClinicalEventId(TEST_CLINICAL_EVENT_ID_2); + clinicalEventData3.setKey(TEST_KEY_3); + clinicalEventData3.setValue(TEST_VALUE_3); + clinicalEventDataList2.add(clinicalEventData3); + ClinicalEventData clinicalEventData4 = new ClinicalEventData(); + clinicalEventData4.setClinicalEventId(TEST_CLINICAL_EVENT_ID_2); + clinicalEventData4.setKey(TEST_KEY_4); + clinicalEventData4.setValue(TEST_VALUE_4); + clinicalEventDataList2.add(clinicalEventData4); + clinicalEvent2.setAttributes(clinicalEventDataList2); + clinicalEventList.add(clinicalEvent2); + return clinicalEventList; + } +} diff --git a/src/test/java/org/cbioportal/legacy/web/CoExpressionControllerTest.java b/src/test/java/org/cbioportal/legacy/web/CoExpressionControllerTest.java new file mode 100644 index 00000000000..0bcb7949ac7 --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/web/CoExpressionControllerTest.java @@ -0,0 +1,104 @@ +package org.cbioportal.legacy.web; + +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; + +import com.fasterxml.jackson.databind.ObjectMapper; +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import org.cbioportal.legacy.model.CoExpression; +import org.cbioportal.legacy.model.EntityType; +import org.cbioportal.legacy.service.CoExpressionService; +import org.cbioportal.legacy.web.config.TestConfig; +import org.cbioportal.legacy.web.parameter.CoExpressionFilter; +import org.hamcrest.Matchers; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mockito; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; +import org.springframework.security.test.context.support.WithMockUser; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.result.MockMvcResultMatchers; + +@RunWith(SpringJUnit4ClassRunner.class) +@WebMvcTest +@ContextConfiguration(classes = {CoExpressionController.class, TestConfig.class}) +public class CoExpressionControllerTest { + + private static final String TEST_ENTREZ_GENE_ID_1 = "1"; + private static final BigDecimal TEST_SPEARMANS_CORRELATION_1 = new BigDecimal(2.1); + private static final BigDecimal TEST_P_VALUE_1 = new BigDecimal(0.33); + private static final String TEST_ENTREZ_GENE_ID_2 = "2"; + private static final BigDecimal TEST_SPEARMANS_CORRELATION_2 = new BigDecimal(4.1); + private static final BigDecimal TEST_P_VALUE_2 = new BigDecimal(0.66); + + @MockBean private CoExpressionService coExpressionService; + + private ObjectMapper objectMapper = new ObjectMapper(); + + @Autowired private MockMvc mockMvc; + + @Test + @WithMockUser + public void fetchMolecularProfileCoExpressions() throws Exception { + + List coExpressionList = new ArrayList<>(); + CoExpression coExpression1 = new CoExpression(); + coExpression1.setGeneticEntityId(TEST_ENTREZ_GENE_ID_1); + coExpression1.setSpearmansCorrelation(TEST_SPEARMANS_CORRELATION_1); + coExpression1.setpValue(TEST_P_VALUE_1); + coExpressionList.add(coExpression1); + CoExpression coExpression2 = new CoExpression(); + coExpression2.setGeneticEntityId(TEST_ENTREZ_GENE_ID_2); + coExpression2.setSpearmansCorrelation(TEST_SPEARMANS_CORRELATION_2); + coExpression2.setpValue(TEST_P_VALUE_2); + coExpressionList.add(coExpression2); + + Mockito.when( + coExpressionService.fetchCoExpressions( + Mockito.anyString(), + Mockito.any(EntityType.class), + Mockito.anyList(), + Mockito.anyString(), + Mockito.anyString(), + Mockito.anyDouble())) + .thenReturn(coExpressionList); + + CoExpressionFilter coExpressionFilter = new CoExpressionFilter(); + coExpressionFilter.setSampleIds(Arrays.asList("test_sample_id")); + coExpressionFilter.setEntrezGeneId(1); + + mockMvc + .perform( + MockMvcRequestBuilders.post("/api/molecular-profiles/co-expressions/fetch") + .with(csrf()) + .param("molecularProfileIdA", "test_molecular_profile_id") + .param("molecularProfileIdB", "test_molecular_profile_id") + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(coExpressionFilter))) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect( + MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.jsonPath("$", Matchers.hasSize(2))) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].geneticEntityId").value(TEST_ENTREZ_GENE_ID_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].spearmansCorrelation") + .value(TEST_SPEARMANS_CORRELATION_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].pValue").value(TEST_P_VALUE_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].geneticEntityId").value(TEST_ENTREZ_GENE_ID_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].spearmansCorrelation") + .value(TEST_SPEARMANS_CORRELATION_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].pValue").value(TEST_P_VALUE_2)); + } +} diff --git a/src/test/java/org/cbioportal/legacy/web/CopyNumberSegmentControllerTest.java b/src/test/java/org/cbioportal/legacy/web/CopyNumberSegmentControllerTest.java new file mode 100644 index 00000000000..ca619c014a4 --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/web/CopyNumberSegmentControllerTest.java @@ -0,0 +1,246 @@ +package org.cbioportal.legacy.web; + +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; + +import com.fasterxml.jackson.databind.ObjectMapper; +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.List; +import org.cbioportal.legacy.model.CopyNumberSeg; +import org.cbioportal.legacy.model.meta.BaseMeta; +import org.cbioportal.legacy.service.CopyNumberSegmentService; +import org.cbioportal.legacy.web.config.TestConfig; +import org.cbioportal.legacy.web.parameter.HeaderKeyConstants; +import org.cbioportal.legacy.web.parameter.SampleIdentifier; +import org.hamcrest.Matchers; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mockito; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; +import org.springframework.security.test.context.support.WithMockUser; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.result.MockMvcResultMatchers; +import org.springframework.web.context.WebApplicationContext; + +@RunWith(SpringJUnit4ClassRunner.class) +@WebMvcTest +@ContextConfiguration(classes = {CopyNumberSegmentController.class, TestConfig.class}) +public class CopyNumberSegmentControllerTest { + + private static final int TEST_SAMPLE_ID_1 = 1; + private static final String TEST_SAMPLE_STABLE_ID_1 = "test_sample_stable_id_1"; + private static final int TEST_CANCER_STUDY_ID_1 = 1; + private static final String TEST_CANCER_STUDY_IDENTIFIER_1 = "test_study_1"; + private static final Long TEST_SEG_ID_1 = 1L; + private static final String TEST_CHR_1 = "test_chr_1"; + private static final Integer TEST_START_1 = 15; + private static final Integer TEST_END_1 = 20; + private static final Integer TEST_NUM_PROBES_1 = 3; + private static final BigDecimal TEST_SEGMENT_MEAN_1 = new BigDecimal(0.2); + private static final int TEST_SAMPLE_ID_2 = 2; + private static final String TEST_SAMPLE_STABLE_ID_2 = "test_sample_stable_id_2"; + private static final int TEST_CANCER_STUDY_ID_2 = 2; + private static final String TEST_CANCER_STUDY_IDENTIFIER_2 = "test_study_2"; + private static final Long TEST_SEG_ID_2 = 2L; + private static final String TEST_CHR_2 = "test_chr_2"; + private static final Integer TEST_START_2 = 25; + private static final Integer TEST_END_2 = 34; + private static final Integer TEST_NUM_PROBES_2 = 5; + private static final BigDecimal TEST_SEGMENT_MEAN_2 = new BigDecimal(0.4); + + private WebApplicationContext wac; + + @MockBean private CopyNumberSegmentService copyNumberSegmentService; + + private ObjectMapper objectMapper = new ObjectMapper(); + + @Autowired private MockMvc mockMvc; + + @Test + @WithMockUser + public void getCopyNumberSegmentsInSampleInStudyDefaultProjection() throws Exception { + + List copyNumberSegList = createExampleCopyNumberSegs(); + + Mockito.when( + copyNumberSegmentService.getCopyNumberSegmentsInSampleInStudy( + Mockito.any(), + Mockito.any(), + Mockito.any(), + Mockito.any(), + Mockito.any(), + Mockito.any(), + Mockito.any(), + Mockito.any())) + .thenReturn(copyNumberSegList); + + mockMvc + .perform( + MockMvcRequestBuilders.get( + "/api/studies/test_study_id/samples/test_sample_id/copy-number-segments") + .accept(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect( + MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.jsonPath("$", Matchers.hasSize(2))) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].segId").doesNotExist()) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].studyId").value(TEST_CANCER_STUDY_IDENTIFIER_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].sampleId").value(TEST_SAMPLE_STABLE_ID_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].chromosome").value(TEST_CHR_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].start").value(TEST_START_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].end").value(TEST_END_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].numberOfProbes").value(TEST_NUM_PROBES_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].segmentMean").value(TEST_SEGMENT_MEAN_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].segId").doesNotExist()) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].studyId").value(TEST_CANCER_STUDY_IDENTIFIER_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].sampleId").value(TEST_SAMPLE_STABLE_ID_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].chromosome").value(TEST_CHR_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].start").value(TEST_START_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].end").value(TEST_END_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].numberOfProbes").value(TEST_NUM_PROBES_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].segmentMean").value(TEST_SEGMENT_MEAN_2)); + } + + @Test + @WithMockUser + public void getCopyNumberSegmentsInSampleInStudyMetaProjection() throws Exception { + + BaseMeta baseMeta = new BaseMeta(); + baseMeta.setTotalCount(2); + + Mockito.when( + copyNumberSegmentService.getMetaCopyNumberSegmentsInSampleInStudy( + Mockito.any(), Mockito.any(), Mockito.any())) + .thenReturn(baseMeta); + + mockMvc + .perform( + MockMvcRequestBuilders.get( + "/api/studies/test_study_id/samples/test_sample_id/copy-number-segments") + .param("projection", "META")) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect(MockMvcResultMatchers.header().string(HeaderKeyConstants.TOTAL_COUNT, "2")); + } + + @Test + @WithMockUser + public void fetchCopyNumberSegmentsDefaultProjection() throws Exception { + + List copyNumberSegList = createExampleCopyNumberSegs(); + + Mockito.when( + copyNumberSegmentService.fetchCopyNumberSegments( + Mockito.any(), Mockito.any(), Mockito.any(), Mockito.any())) + .thenReturn(copyNumberSegList); + + List sampleIdentifiers = new ArrayList<>(); + SampleIdentifier sampleIdentifier1 = new SampleIdentifier(); + sampleIdentifier1.setStudyId(TEST_CANCER_STUDY_IDENTIFIER_1); + sampleIdentifier1.setSampleId(TEST_SAMPLE_STABLE_ID_1); + sampleIdentifiers.add(sampleIdentifier1); + SampleIdentifier sampleIdentifier2 = new SampleIdentifier(); + sampleIdentifier2.setStudyId(TEST_CANCER_STUDY_IDENTIFIER_1); + sampleIdentifier2.setSampleId(TEST_SAMPLE_STABLE_ID_2); + sampleIdentifiers.add(sampleIdentifier2); + + mockMvc + .perform( + MockMvcRequestBuilders.post("/api/copy-number-segments/fetch") + .with(csrf()) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(sampleIdentifiers))) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect( + MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.jsonPath("$", Matchers.hasSize(2))) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].segId").doesNotExist()) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].studyId").value(TEST_CANCER_STUDY_IDENTIFIER_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].sampleId").value(TEST_SAMPLE_STABLE_ID_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].chromosome").value(TEST_CHR_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].start").value(TEST_START_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].end").value(TEST_END_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].numberOfProbes").value(TEST_NUM_PROBES_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].segmentMean").value(TEST_SEGMENT_MEAN_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].segId").doesNotExist()) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].studyId").value(TEST_CANCER_STUDY_IDENTIFIER_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].sampleId").value(TEST_SAMPLE_STABLE_ID_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].chromosome").value(TEST_CHR_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].start").value(TEST_START_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].end").value(TEST_END_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].numberOfProbes").value(TEST_NUM_PROBES_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].segmentMean").value(TEST_SEGMENT_MEAN_2)); + } + + @Test + @WithMockUser + public void fetchCopyNumberSegmentsMetaProjection() throws Exception { + + BaseMeta baseMeta = new BaseMeta(); + baseMeta.setTotalCount(2); + + Mockito.when( + copyNumberSegmentService.fetchMetaCopyNumberSegments( + Mockito.any(), Mockito.any(), Mockito.any())) + .thenReturn(baseMeta); + + List sampleIdentifiers = new ArrayList<>(); + SampleIdentifier sampleIdentifier1 = new SampleIdentifier(); + sampleIdentifier1.setStudyId(TEST_CANCER_STUDY_IDENTIFIER_1); + sampleIdentifier1.setSampleId(TEST_SAMPLE_STABLE_ID_1); + sampleIdentifiers.add(sampleIdentifier1); + SampleIdentifier sampleIdentifier2 = new SampleIdentifier(); + sampleIdentifier2.setStudyId(TEST_CANCER_STUDY_IDENTIFIER_1); + sampleIdentifier2.setSampleId(TEST_SAMPLE_STABLE_ID_2); + sampleIdentifiers.add(sampleIdentifier2); + + mockMvc + .perform( + MockMvcRequestBuilders.post("/api/copy-number-segments/fetch") + .with(csrf()) + .param("projection", "META") + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(sampleIdentifiers))) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect(MockMvcResultMatchers.header().string(HeaderKeyConstants.TOTAL_COUNT, "2")); + } + + private List createExampleCopyNumberSegs() { + List copyNumberSegList = new ArrayList<>(); + CopyNumberSeg copyNumberSeg1 = new CopyNumberSeg(); + copyNumberSeg1.setSegId(TEST_SEG_ID_1); + copyNumberSeg1.setCancerStudyId(TEST_CANCER_STUDY_ID_1); + copyNumberSeg1.setCancerStudyIdentifier(TEST_CANCER_STUDY_IDENTIFIER_1); + copyNumberSeg1.setSampleId(TEST_SAMPLE_ID_1); + copyNumberSeg1.setSampleStableId(TEST_SAMPLE_STABLE_ID_1); + copyNumberSeg1.setChr(TEST_CHR_1); + copyNumberSeg1.setStart(TEST_START_1); + copyNumberSeg1.setEnd(TEST_END_1); + copyNumberSeg1.setNumProbes(TEST_NUM_PROBES_1); + copyNumberSeg1.setSegmentMean(TEST_SEGMENT_MEAN_1); + copyNumberSegList.add(copyNumberSeg1); + CopyNumberSeg copyNumberSeg2 = new CopyNumberSeg(); + copyNumberSeg2.setSegId(TEST_SEG_ID_2); + copyNumberSeg2.setCancerStudyId(TEST_CANCER_STUDY_ID_2); + copyNumberSeg2.setCancerStudyIdentifier(TEST_CANCER_STUDY_IDENTIFIER_2); + copyNumberSeg2.setSampleId(TEST_SAMPLE_ID_2); + copyNumberSeg2.setSampleStableId(TEST_SAMPLE_STABLE_ID_2); + copyNumberSeg2.setChr(TEST_CHR_2); + copyNumberSeg2.setStart(TEST_START_2); + copyNumberSeg2.setEnd(TEST_END_2); + copyNumberSeg2.setNumProbes(TEST_NUM_PROBES_2); + copyNumberSeg2.setSegmentMean(TEST_SEGMENT_MEAN_2); + copyNumberSegList.add(copyNumberSeg2); + return copyNumberSegList; + } +} diff --git a/src/test/java/org/cbioportal/legacy/web/CosmicCountControllerTest.java b/src/test/java/org/cbioportal/legacy/web/CosmicCountControllerTest.java new file mode 100644 index 00000000000..5cf1870f5d8 --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/web/CosmicCountControllerTest.java @@ -0,0 +1,97 @@ +package org.cbioportal.legacy.web; + +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; + +import com.fasterxml.jackson.databind.ObjectMapper; +import java.util.ArrayList; +import java.util.List; +import org.cbioportal.legacy.model.CosmicMutation; +import org.cbioportal.legacy.service.CosmicCountService; +import org.cbioportal.legacy.web.config.TestConfig; +import org.hamcrest.Matchers; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mockito; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; +import org.springframework.security.test.context.support.WithMockUser; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.result.MockMvcResultMatchers; + +@RunWith(SpringJUnit4ClassRunner.class) +@WebMvcTest +@ContextConfiguration(classes = {CosmicCountController.class, TestConfig.class}) +public class CosmicCountControllerTest { + + private static final String TEST_COSMIC_MUTATION_ID_1 = "test_cosmic_mutation_id_1"; + private static final String TEST_PROTEIN_CHANGE_1 = "test_protein_change_1"; + private static final String TEST_KEYWORD_1 = "test_keyword_1"; + private static final int TEST_COUNT_1 = 1; + private static final String TEST_COSMIC_MUTATION_ID_2 = "test_cosmic_mutation_id_2"; + private static final String TEST_PROTEIN_CHANGE_2 = "test_protein_change_2"; + private static final String TEST_KEYWORD_2 = "test_keyword_2"; + private static final int TEST_COUNT_2 = 2; + + @MockBean private CosmicCountService cosmicCountService; + + private ObjectMapper objectMapper = new ObjectMapper(); + + @Autowired private MockMvc mockMvc; + + @Test + @WithMockUser + public void fetchCosmicCounts() throws Exception { + + List cosmicMutationList = new ArrayList<>(); + CosmicMutation cosmicMutation1 = new CosmicMutation(); + cosmicMutation1.setCosmicMutationId(TEST_COSMIC_MUTATION_ID_1); + cosmicMutation1.setProteinChange(TEST_PROTEIN_CHANGE_1); + cosmicMutation1.setKeyword(TEST_KEYWORD_1); + cosmicMutation1.setCount(TEST_COUNT_1); + cosmicMutationList.add(cosmicMutation1); + CosmicMutation cosmicMutation2 = new CosmicMutation(); + cosmicMutation2.setCosmicMutationId(TEST_COSMIC_MUTATION_ID_2); + cosmicMutation2.setProteinChange(TEST_PROTEIN_CHANGE_2); + cosmicMutation2.setKeyword(TEST_KEYWORD_2); + cosmicMutation2.setCount(TEST_COUNT_2); + cosmicMutationList.add(cosmicMutation2); + + Mockito.when(cosmicCountService.fetchCosmicCountsByKeywords(Mockito.anyList())) + .thenReturn(cosmicMutationList); + + List keywords = new ArrayList<>(); + keywords.add(TEST_KEYWORD_1); + keywords.add(TEST_KEYWORD_2); + + mockMvc + .perform( + MockMvcRequestBuilders.post("/api/cosmic-counts/fetch") + .with(csrf()) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(keywords))) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect( + MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.jsonPath("$", Matchers.hasSize(2))) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].cosmicMutationId") + .value(TEST_COSMIC_MUTATION_ID_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].proteinChange").value(TEST_PROTEIN_CHANGE_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].keyword").value(TEST_KEYWORD_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].count").value(TEST_COUNT_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].cosmicMutationId") + .value(TEST_COSMIC_MUTATION_ID_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].proteinChange").value(TEST_PROTEIN_CHANGE_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].keyword").value(TEST_KEYWORD_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].count").value(TEST_COUNT_2)); + } +} diff --git a/src/test/java/org/cbioportal/legacy/web/DataAccessTokenControllerTest.java b/src/test/java/org/cbioportal/legacy/web/DataAccessTokenControllerTest.java new file mode 100644 index 00000000000..3d350cd8523 --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/web/DataAccessTokenControllerTest.java @@ -0,0 +1,360 @@ +/* + * This file is part of cBioPortal. + * + * cBioPortal is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package org.cbioportal.legacy.web; + +import static org.mockito.Mockito.*; +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; + +import com.fasterxml.jackson.databind.ObjectMapper; +import jakarta.servlet.http.HttpSession; +import org.cbioportal.legacy.model.DataAccessToken; +import org.cbioportal.legacy.service.DataAccessTokenService; +import org.cbioportal.legacy.service.exception.TokenNotFoundException; +import org.cbioportal.legacy.web.config.DataAccessTokenControllerTestConfig; +import org.cbioportal.legacy.web.config.TestConfig; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.ArgumentMatchers; +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; +import org.springframework.mock.web.MockHttpSession; +import org.springframework.security.test.context.support.WithMockUser; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.MvcResult; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.result.MockMvcResultMatchers; + +@TestPropertySource( + properties = { + "download_group=PLACEHOLDER_ROLE", + }) +@RunWith(SpringJUnit4ClassRunner.class) +@WebMvcTest +@ContextConfiguration( + classes = { + DataAccessTokenController.class, + TestConfig.class, + DataAccessTokenControllerTestConfig.class + }) +public class DataAccessTokenControllerTest { + + public static final String MOCK_USER = "MOCK_USER"; + public static final String MOCK_PASSWORD = "MOCK_PASSWORD"; + public static final String VALID_TOKEN_STRING = "VALID_TOKEN"; + public static final String NONEXISTENT_TOKEN_STRING = "NONEXISTENT_TOKEN"; + public static final String NOT_FOUND_ERROR_MESSAGE = "Specified token cannot be found"; + public static final DataAccessToken MOCK_TOKEN_INFO = new DataAccessToken(VALID_TOKEN_STRING); + + private ObjectMapper objectMapper = new ObjectMapper(); + + @MockBean private DataAccessTokenService tokenService; + + @Autowired private MockMvc mockMvc; + + public String receivedArgument = null; + + public void resetReceivedArgument() { + this.receivedArgument = null; + } + + private HttpSession getSession(String user, String password) throws Exception { + return mockMvc + .perform( + MockMvcRequestBuilders.post("/j_spring_security_check") + .with(csrf()) + .param("j_username", user) + .param("j_password", password)) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andReturn() + .getRequest() + .getSession(); + } + + /* Tests mapping for GET /data-access-tokens/{token} + * Test for valid token - checks returned response type is 200 success + */ + @Test + @WithMockUser() + public void getTokenInfoForValidTokenTest() throws Exception { + when(tokenService.getDataAccessTokenInfo(VALID_TOKEN_STRING)).thenReturn(MOCK_TOKEN_INFO); + HttpSession session = getSession(MOCK_USER, MOCK_PASSWORD); + mockMvc + .perform( + MockMvcRequestBuilders.get("/api/data-access-tokens/" + VALID_TOKEN_STRING) + .session((MockHttpSession) session) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andReturn(); + } + + /* Tests mapping for GET /data-access-tokens/{token} + * Test for nonexistent token - checks returned response type is 404 not found + * Checks response for correct error message + */ + @Test + @WithMockUser + public void getTokenInfoForNonexistentTokenTest() throws Exception { + doThrow(new TokenNotFoundException()) + .when(tokenService) + .getDataAccessTokenInfo(NONEXISTENT_TOKEN_STRING); + HttpSession session = getSession(MOCK_USER, MOCK_PASSWORD); + MvcResult result = + mockMvc + .perform( + MockMvcRequestBuilders.get("/api/data-access-tokens/" + NONEXISTENT_TOKEN_STRING) + .session((MockHttpSession) session) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.status().isNotFound()) + .andReturn(); + if (!result.getResponse().getContentAsString().contains(NOT_FOUND_ERROR_MESSAGE)) { + Assert.fail( + "Returned response did not contain expected error message. Expected response: '" + + NOT_FOUND_ERROR_MESSAGE + + "' Returned response: '" + + result.getResponse().getContentAsString() + + "'"); + } + } + + /* Tests mapping for DELETE /data-access-tokens/{token} + * Test that proper service method was called + */ + @Test + @WithMockUser + public void revokeValidTokenTest() throws Exception { + resetReceivedArgument(); + Answer tokenServiceRevokeTokenAnswer = + new Answer() { + public Void answer(InvocationOnMock revokeTokenInvocation) { + receivedArgument = (String) revokeTokenInvocation.getArguments()[0]; + return null; + } + }; + doAnswer(tokenServiceRevokeTokenAnswer) + .when(tokenService) + .revokeDataAccessToken(ArgumentMatchers.anyString()); + HttpSession session = getSession(MOCK_USER, MOCK_PASSWORD); + MvcResult result = + mockMvc + .perform( + MockMvcRequestBuilders.delete("/api/data-access-tokens/" + VALID_TOKEN_STRING) + .with(csrf()) + .session((MockHttpSession) session) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andReturn(); + if (!receivedArgument.equals(VALID_TOKEN_STRING)) { + Assert.fail( + "Unexpected argument passed to service class. Expected argument: " + + VALID_TOKEN_STRING + + " Received argument: " + + receivedArgument); + } + } + + /* Tests mapping for GET /data-access-tokens/{token} + * Test for nonexistent token - checks returned response type is 404 not found + * Checks response for correct error message + */ + @Test + @WithMockUser + public void revokeNonexistentTokenTest() throws Exception { + resetReceivedArgument(); + doThrow(new TokenNotFoundException()) + .when(tokenService) + .revokeDataAccessToken(NONEXISTENT_TOKEN_STRING); + ; + HttpSession session = getSession(MOCK_USER, MOCK_PASSWORD); + MvcResult result = + mockMvc + .perform( + MockMvcRequestBuilders.delete("/api/data-access-tokens/" + NONEXISTENT_TOKEN_STRING) + .with(csrf()) + .session((MockHttpSession) session) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.status().isNotFound()) + .andReturn(); + if (!result.getResponse().getContentAsString().contains(NOT_FOUND_ERROR_MESSAGE)) { + Assert.fail( + "Returned response did not contain expected error message. Expected response: '" + + NOT_FOUND_ERROR_MESSAGE + + "' Returned response: '" + + result.getResponse().getContentAsString() + + "'"); + } + } + + /* Tests mapping for POST /data-access-tokens + * Tests for 201 (CREATED) response code + */ + @Test + @WithMockUser(username = MOCK_USER, password = MOCK_PASSWORD, authorities = "PLACEHOLDER_ROLE") + public void createTokenValidUserTest() throws Exception { + when(tokenService.createDataAccessToken(ArgumentMatchers.anyString())) + .thenReturn(MOCK_TOKEN_INFO); + HttpSession session = getSession(MOCK_USER, MOCK_PASSWORD); + MvcResult result = + mockMvc + .perform( + MockMvcRequestBuilders.post("/api/data-access-tokens") + .with(csrf()) + .session((MockHttpSession) session) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.status().isCreated()) + .andReturn(); + } + + @Test + @WithMockUser(username = MOCK_USER, password = MOCK_PASSWORD, authorities = "PLACEHOLDER_ROLE") + public void createTokenValidUserTestWithUserRole() throws Exception { + when(tokenService.createDataAccessToken(ArgumentMatchers.anyString())) + .thenReturn(MOCK_TOKEN_INFO); + HttpSession session = getSession(MOCK_USER, MOCK_PASSWORD); + MvcResult result = + mockMvc + .perform( + MockMvcRequestBuilders.post("/api/data-access-tokens") + .with(csrf()) + .session((MockHttpSession) session) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.status().isCreated()) + .andReturn(); + } + + @Test + @WithMockUser + public void createTokenUnauthorizedUserTestWithUserRole() throws Exception { + when(tokenService.createDataAccessToken(ArgumentMatchers.anyString())) + .thenReturn(MOCK_TOKEN_INFO); + HttpSession session = getSession(MOCK_USER, MOCK_PASSWORD); + MvcResult result = + mockMvc + .perform( + MockMvcRequestBuilders.post("/api/data-access-tokens") + .with(csrf()) + .session((MockHttpSession) session) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.status().isUnauthorized()) + .andReturn(); + } + + /* Tests mapping for DELETE /data-access-tokens + * Checks response status code is 200 success + * Checks that correct username argument is passed to service class + */ + @Test + @WithMockUser(username = MOCK_USER, password = MOCK_PASSWORD, authorities = "PLACEHOLDER_ROLE") + public void revokeAllTokensForUserTest() throws Exception { + resetReceivedArgument(); + Answer tokenServiceRevokeAllTokensAnswer = + new Answer() { + public Void answer(InvocationOnMock revokeAllTokensInvocation) { + receivedArgument = (String) revokeAllTokensInvocation.getArguments()[0]; + return null; + } + }; + doAnswer(tokenServiceRevokeAllTokensAnswer) + .when(tokenService) + .revokeAllDataAccessTokens(ArgumentMatchers.anyString()); + HttpSession session = getSession(MOCK_USER, MOCK_PASSWORD); + MvcResult result = + mockMvc + .perform( + MockMvcRequestBuilders.delete("/api/data-access-tokens") + .with(csrf()) + .session((MockHttpSession) session) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andReturn(); + if (!receivedArgument.equals(MOCK_USER)) { + Assert.fail( + "Unexpected argument passed to service class. Expected argument: " + + MOCK_USER + + " Received argument: " + + receivedArgument); + } + } + + /* Tests mapping for GET /data-access-tokens + * Checks response status code is 200 success + * Checks that correct username argument is passed to service class + */ + @Test + @WithMockUser(username = MOCK_USER, password = MOCK_PASSWORD, authorities = "PLACEHOLDER_ROLE") + public void getAllTokensForUserTest() throws Exception { + resetReceivedArgument(); + Answer tokenServiceGetAllTokensAnswer = + new Answer() { + public Void answer(InvocationOnMock getAllTokensInvocation) { + receivedArgument = (String) getAllTokensInvocation.getArguments()[0]; + return null; + } + }; + doAnswer(tokenServiceGetAllTokensAnswer) + .when(tokenService) + .getAllDataAccessTokens(ArgumentMatchers.anyString()); + HttpSession session = getSession(MOCK_USER, MOCK_PASSWORD); + MvcResult result = + mockMvc + .perform( + MockMvcRequestBuilders.get("/api/data-access-tokens") + .session((MockHttpSession) session) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andReturn(); + if (!receivedArgument.equals(MOCK_USER)) { + Assert.fail( + "Unexpected argument passed to service class. Expected argument: " + + MOCK_USER + + " Received argument: " + + receivedArgument); + } + } + + @Test + public void createTokenNotLoggedIn() throws Exception { + when(tokenService.createDataAccessToken(ArgumentMatchers.anyString())) + .thenReturn(MOCK_TOKEN_INFO); + MvcResult result = + mockMvc + .perform( + MockMvcRequestBuilders.post("/api/data-access-tokens") + .with(csrf()) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.status().isUnauthorized()) + .andReturn(); + } +} diff --git a/src/test/java/org/cbioportal/legacy/web/DiscreteCopyNumberControllerTest.java b/src/test/java/org/cbioportal/legacy/web/DiscreteCopyNumberControllerTest.java new file mode 100644 index 00000000000..36518038984 --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/web/DiscreteCopyNumberControllerTest.java @@ -0,0 +1,405 @@ +package org.cbioportal.legacy.web; + +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; + +import com.fasterxml.jackson.databind.ObjectMapper; +import java.util.ArrayList; +import java.util.List; +import org.cbioportal.legacy.model.DiscreteCopyNumberData; +import org.cbioportal.legacy.model.Gene; +import org.cbioportal.legacy.model.meta.BaseMeta; +import org.cbioportal.legacy.service.DiscreteCopyNumberService; +import org.cbioportal.legacy.web.config.TestConfig; +import org.cbioportal.legacy.web.parameter.DiscreteCopyNumberEventType; +import org.cbioportal.legacy.web.parameter.DiscreteCopyNumberFilter; +import org.cbioportal.legacy.web.parameter.HeaderKeyConstants; +import org.hamcrest.Matchers; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mockito; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; +import org.springframework.security.test.context.support.WithMockUser; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.result.MockMvcResultMatchers; + +@RunWith(SpringJUnit4ClassRunner.class) +@WebMvcTest +@ContextConfiguration(classes = {DiscreteCopyNumberController.class, TestConfig.class}) +public class DiscreteCopyNumberControllerTest { + + private static final String TEST_MOLECULAR_PROFILE_STABLE_ID_1 = + "test_molecular_profile_stable_id_1"; + private static final String TEST_SAMPLE_STABLE_ID_1 = "test_sample_stable_id_1"; + private static final int TEST_ENTREZ_GENE_ID_1 = 1; + private static final int TEST_ALTERATION_1 = 1; + private static final String TEST_ANNOTATION_JSON_1 = + "{\"columnName\":{\"fieldName\":\"fieldValue\"}}"; + private static final String TEST_HUGO_GENE_SYMBOL_1 = "test_hugo_gene_symbol_1"; + private static final String TEST_TYPE_1 = "test_type_1"; + private static final String TEST_CYTOBAND_1 = "test_cytoband_1"; + private static final String TEST_CHROMOSOME_1 = "test_chromosome_1"; + private static final String TEST_MOLECULAR_PROFILE_STABLE_ID_2 = + "test_molecular_profile_stable_id_2"; + private static final String TEST_SAMPLE_STABLE_ID_2 = "test_sample_stable_id_2"; + private static final int TEST_ENTREZ_GENE_ID_2 = 2; + private static final int TEST_ALTERATION_2 = 2; + private static final String TEST_HUGO_GENE_SYMBOL_2 = "test_hugo_gene_symbol_2"; + private static final String TEST_TYPE_2 = "test_type_2"; + private static final String TEST_CYTOBAND_2 = "test_cytoband_2"; + private static final String TEST_CHROMOSOME_2 = "test_chromosome_2"; + private static final String TEST_SAMPLE_LIST_ID = "test_sample_list_id"; + private static final int TEST_NUMBER_OF_SAMPLES_1 = 6; + private static final int TEST_NUMBER_OF_SAMPLES_WITH_ALTERATION_IN_GENE_1 = 4; + private static final int TEST_NUMBER_OF_SAMPLES_2 = 10; + private static final int TEST_NUMBER_OF_SAMPLES_WITH_ALTERATION_IN_GENE_2 = 8; + + @MockBean private DiscreteCopyNumberService discreteCopyNumberService; + + private ObjectMapper objectMapper = new ObjectMapper(); + + @Autowired private MockMvc mockMvc; + + @Test + @WithMockUser + public void getDiscreteCopyNumbersInMolecularProfileBySampleListIdDefaultProjection() + throws Exception { + + List discreteCopyNumberDataList = createExampleDiscreteCopyNumberData(); + + Mockito.when( + discreteCopyNumberService.getDiscreteCopyNumbersInMolecularProfileBySampleListId( + Mockito.any(), Mockito.any(), Mockito.any(), Mockito.any(), Mockito.any())) + .thenReturn(discreteCopyNumberDataList); + + mockMvc + .perform( + MockMvcRequestBuilders.get( + "/api/molecular-profiles/test_molecular_profile_id/discrete-copy-number") + .param("sampleListId", TEST_SAMPLE_LIST_ID) + .param( + "discreteCopyNumberEventType", + DiscreteCopyNumberEventType.HOMDEL_AND_AMP.name()) + .accept(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect( + MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.jsonPath("$", Matchers.hasSize(2))) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].molecularProfileId") + .value(TEST_MOLECULAR_PROFILE_STABLE_ID_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].sampleId").value(TEST_SAMPLE_STABLE_ID_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].entrezGeneId").value(TEST_ENTREZ_GENE_ID_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].alteration").value(TEST_ALTERATION_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].namespaceColumns.columnName.fieldName") + .value("fieldValue")) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].gene").doesNotExist()) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].molecularProfileId") + .value(TEST_MOLECULAR_PROFILE_STABLE_ID_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].sampleId").value(TEST_SAMPLE_STABLE_ID_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].entrezGeneId").value(TEST_ENTREZ_GENE_ID_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].alteration").value(TEST_ALTERATION_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].gene").doesNotExist()); + } + + @Test + @WithMockUser + public void getDiscreteCopyNumbersWithoutAnnotationJson() throws Exception { + + List discreteCopyNumberDataList = createExampleDiscreteCopyNumberData(); + discreteCopyNumberDataList.get(0).setAnnotationJson(null); + Mockito.when( + discreteCopyNumberService.getDiscreteCopyNumbersInMolecularProfileBySampleListId( + Mockito.any(), Mockito.any(), Mockito.any(), Mockito.any(), Mockito.any())) + .thenReturn(discreteCopyNumberDataList); + + mockMvc + .perform( + MockMvcRequestBuilders.get( + "/api/molecular-profiles/test_molecular_profile_id/discrete-copy-number") + .param("sampleListId", TEST_SAMPLE_LIST_ID) + .param( + "discreteCopyNumberEventType", + DiscreteCopyNumberEventType.HOMDEL_AND_AMP.name()) + .accept(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect( + MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.jsonPath("$", Matchers.hasSize(2))) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].namespaceColumns").doesNotExist()); + } + + @Test + @WithMockUser + public void getDiscreteCopyNumbersInMolecularProfileBySampleListIdDetailedProjection() + throws Exception { + + List discreteCopyNumberDataList = + createExampleDiscreteCopyNumberDataWithGenes(); + + Mockito.when( + discreteCopyNumberService.getDiscreteCopyNumbersInMolecularProfileBySampleListId( + Mockito.any(), Mockito.any(), Mockito.any(), Mockito.any(), Mockito.any())) + .thenReturn(discreteCopyNumberDataList); + + mockMvc + .perform( + MockMvcRequestBuilders.get( + "/api/molecular-profiles/test_molecular_profile_id/discrete-copy-number") + .param("sampleListId", TEST_SAMPLE_LIST_ID) + .param( + "discreteCopyNumberEventType", + DiscreteCopyNumberEventType.HOMDEL_AND_AMP.name()) + .param("projection", "DETAILED") + .accept(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect( + MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.jsonPath("$", Matchers.hasSize(2))) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].molecularProfileId") + .value(TEST_MOLECULAR_PROFILE_STABLE_ID_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].sampleId").value(TEST_SAMPLE_STABLE_ID_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].entrezGeneId").value(TEST_ENTREZ_GENE_ID_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].alteration").value(TEST_ALTERATION_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].gene.entrezGeneId").value(TEST_ENTREZ_GENE_ID_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].gene.hugoGeneSymbol") + .value(TEST_HUGO_GENE_SYMBOL_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].gene.type").value(TEST_TYPE_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].molecularProfileId") + .value(TEST_MOLECULAR_PROFILE_STABLE_ID_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].sampleId").value(TEST_SAMPLE_STABLE_ID_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].entrezGeneId").value(TEST_ENTREZ_GENE_ID_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].alteration").value(TEST_ALTERATION_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].gene.entrezGeneId").value(TEST_ENTREZ_GENE_ID_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].gene.hugoGeneSymbol") + .value(TEST_HUGO_GENE_SYMBOL_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].gene.type").value(TEST_TYPE_2)); + } + + @Test + @WithMockUser + public void getDiscreteCopyNumbersInMolecularProfileBySampleListIdMetaProjection() + throws Exception { + + BaseMeta baseMeta = new BaseMeta(); + baseMeta.setTotalCount(2); + + Mockito.when( + discreteCopyNumberService.getMetaDiscreteCopyNumbersInMolecularProfileBySampleListId( + Mockito.any(), Mockito.any(), Mockito.any(), Mockito.any())) + .thenReturn(baseMeta); + + mockMvc + .perform( + MockMvcRequestBuilders.get( + "/api/molecular-profiles/test_molecular_profile_id/discrete-copy-number") + .param("sampleListId", TEST_SAMPLE_LIST_ID) + .param( + "discreteCopyNumberEventType", + DiscreteCopyNumberEventType.HOMDEL_AND_AMP.name()) + .param("projection", "META")) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect(MockMvcResultMatchers.header().string(HeaderKeyConstants.TOTAL_COUNT, "2")); + } + + @Test + @WithMockUser + public void fetchDiscreteCopyNumbersInMolecularProfileDefaultProjection() throws Exception { + + List discreteCopyNumberDataList = createExampleDiscreteCopyNumberData(); + + Mockito.when( + discreteCopyNumberService.fetchDiscreteCopyNumbersInMolecularProfile( + Mockito.anyString(), + Mockito.anyList(), + Mockito.anyList(), + Mockito.anyList(), + Mockito.anyString())) + .thenReturn(discreteCopyNumberDataList); + + DiscreteCopyNumberFilter discreteCopyNumberFilter = createDiscreteCopyNumberFilter(); + + mockMvc + .perform( + MockMvcRequestBuilders.post( + "/api/molecular-profiles/test_molecular_profile_id/discrete-copy-number/fetch") + .with(csrf()) + .param( + "discreteCopyNumberEventType", + DiscreteCopyNumberEventType.HOMDEL_AND_AMP.name()) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(discreteCopyNumberFilter))) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect( + MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.jsonPath("$", Matchers.hasSize(2))) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].molecularProfileId") + .value(TEST_MOLECULAR_PROFILE_STABLE_ID_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].sampleId").value(TEST_SAMPLE_STABLE_ID_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].entrezGeneId").value(TEST_ENTREZ_GENE_ID_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].alteration").value(TEST_ALTERATION_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].gene").doesNotExist()) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].molecularProfileId") + .value(TEST_MOLECULAR_PROFILE_STABLE_ID_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].sampleId").value(TEST_SAMPLE_STABLE_ID_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].entrezGeneId").value(TEST_ENTREZ_GENE_ID_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].alteration").value(TEST_ALTERATION_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].gene").doesNotExist()); + } + + @Test + @WithMockUser + public void fetchDiscreteCopyNumbersInMolecularProfileDetailedProjection() throws Exception { + + List discreteCopyNumberDataList = + createExampleDiscreteCopyNumberDataWithGenes(); + + Mockito.when( + discreteCopyNumberService.fetchDiscreteCopyNumbersInMolecularProfile( + Mockito.anyString(), + Mockito.anyList(), + Mockito.anyList(), + Mockito.anyList(), + Mockito.anyString())) + .thenReturn(discreteCopyNumberDataList); + + DiscreteCopyNumberFilter discreteCopyNumberFilter = createDiscreteCopyNumberFilter(); + + mockMvc + .perform( + MockMvcRequestBuilders.post( + "/api/molecular-profiles/test_molecular_profile_id/discrete-copy-number/fetch") + .with(csrf()) + .param( + "discreteCopyNumberEventType", + DiscreteCopyNumberEventType.HOMDEL_AND_AMP.name()) + .param("projection", "DETAILED") + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(discreteCopyNumberFilter))) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect( + MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.jsonPath("$", Matchers.hasSize(2))) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].molecularProfileId") + .value(TEST_MOLECULAR_PROFILE_STABLE_ID_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].sampleId").value(TEST_SAMPLE_STABLE_ID_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].entrezGeneId").value(TEST_ENTREZ_GENE_ID_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].alteration").value(TEST_ALTERATION_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].gene.entrezGeneId").value(TEST_ENTREZ_GENE_ID_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].gene.hugoGeneSymbol") + .value(TEST_HUGO_GENE_SYMBOL_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].gene.type").value(TEST_TYPE_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].molecularProfileId") + .value(TEST_MOLECULAR_PROFILE_STABLE_ID_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].sampleId").value(TEST_SAMPLE_STABLE_ID_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].entrezGeneId").value(TEST_ENTREZ_GENE_ID_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].alteration").value(TEST_ALTERATION_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].gene.entrezGeneId").value(TEST_ENTREZ_GENE_ID_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].gene.hugoGeneSymbol") + .value(TEST_HUGO_GENE_SYMBOL_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].gene.type").value(TEST_TYPE_2)); + } + + @Test + @WithMockUser + public void fetchDiscreteCopyNumbersInMolecularProfileMetaProjection() throws Exception { + + BaseMeta baseMeta = new BaseMeta(); + baseMeta.setTotalCount(2); + + Mockito.when( + discreteCopyNumberService.fetchMetaDiscreteCopyNumbersInMolecularProfile( + Mockito.anyString(), Mockito.anyList(), Mockito.anyList(), Mockito.anyList())) + .thenReturn(baseMeta); + + DiscreteCopyNumberFilter discreteCopyNumberFilter = createDiscreteCopyNumberFilter(); + + mockMvc + .perform( + MockMvcRequestBuilders.post( + "/api/molecular-profiles/test_molecular_profile_id/discrete-copy-number/fetch") + .with(csrf()) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(discreteCopyNumberFilter)) + .param( + "discreteCopyNumberEventType", + DiscreteCopyNumberEventType.HOMDEL_AND_AMP.name()) + .param("projection", "META")) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect(MockMvcResultMatchers.header().string(HeaderKeyConstants.TOTAL_COUNT, "2")); + } + + private DiscreteCopyNumberFilter createDiscreteCopyNumberFilter() { + + List sampleIds = new ArrayList<>(); + sampleIds.add(TEST_SAMPLE_STABLE_ID_1); + sampleIds.add(TEST_SAMPLE_STABLE_ID_2); + + List entrezGeneIds = new ArrayList<>(); + entrezGeneIds.add(TEST_ENTREZ_GENE_ID_1); + entrezGeneIds.add(TEST_ENTREZ_GENE_ID_2); + + DiscreteCopyNumberFilter discreteCopyNumberFilter = new DiscreteCopyNumberFilter(); + discreteCopyNumberFilter.setEntrezGeneIds(entrezGeneIds); + discreteCopyNumberFilter.setSampleIds(sampleIds); + return discreteCopyNumberFilter; + } + + private List createExampleDiscreteCopyNumberData() { + + List discreteCopyNumberDataList = new ArrayList<>(); + DiscreteCopyNumberData discreteCopyNumberData1 = new DiscreteCopyNumberData(); + discreteCopyNumberData1.setMolecularProfileId(TEST_MOLECULAR_PROFILE_STABLE_ID_1); + discreteCopyNumberData1.setSampleId(TEST_SAMPLE_STABLE_ID_1); + discreteCopyNumberData1.setEntrezGeneId(TEST_ENTREZ_GENE_ID_1); + discreteCopyNumberData1.setAlteration(TEST_ALTERATION_1); + discreteCopyNumberDataList.add(discreteCopyNumberData1); + discreteCopyNumberData1.setAnnotationJson(TEST_ANNOTATION_JSON_1); + DiscreteCopyNumberData discreteCopyNumberData2 = new DiscreteCopyNumberData(); + discreteCopyNumberData2.setMolecularProfileId(TEST_MOLECULAR_PROFILE_STABLE_ID_2); + discreteCopyNumberData2.setSampleId(TEST_SAMPLE_STABLE_ID_2); + discreteCopyNumberData2.setEntrezGeneId(TEST_ENTREZ_GENE_ID_2); + discreteCopyNumberData2.setAlteration(TEST_ALTERATION_2); + discreteCopyNumberDataList.add(discreteCopyNumberData2); + return discreteCopyNumberDataList; + } + + private List createExampleDiscreteCopyNumberDataWithGenes() { + + List discreteCopyNumberDataList = createExampleDiscreteCopyNumberData(); + Gene gene1 = new Gene(); + gene1.setEntrezGeneId(TEST_ENTREZ_GENE_ID_1); + gene1.setHugoGeneSymbol(TEST_HUGO_GENE_SYMBOL_1); + gene1.setType(TEST_TYPE_1); + discreteCopyNumberDataList.get(0).setGene(gene1); + Gene gene2 = new Gene(); + gene2.setEntrezGeneId(TEST_ENTREZ_GENE_ID_2); + gene2.setHugoGeneSymbol(TEST_HUGO_GENE_SYMBOL_2); + gene2.setType(TEST_TYPE_2); + discreteCopyNumberDataList.get(1).setGene(gene2); + return discreteCopyNumberDataList; + } +} diff --git a/src/test/java/org/cbioportal/legacy/web/DiscreteCopyNumberCountControllerTest.java b/src/test/java/org/cbioportal/legacy/web/DiscreteCopyNumberCountControllerTest.java new file mode 100644 index 00000000000..ded9575f696 --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/web/DiscreteCopyNumberCountControllerTest.java @@ -0,0 +1,132 @@ +package org.cbioportal.legacy.web; + +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; + +import com.fasterxml.jackson.databind.ObjectMapper; +import java.util.ArrayList; +import java.util.List; +import org.cbioportal.legacy.model.CopyNumberCount; +import org.cbioportal.legacy.service.DiscreteCopyNumberService; +import org.cbioportal.legacy.web.config.TestConfig; +import org.cbioportal.legacy.web.parameter.CopyNumberCountIdentifier; +import org.hamcrest.Matchers; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mockito; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; +import org.springframework.security.test.context.support.WithMockUser; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.result.MockMvcResultMatchers; + +@RunWith(SpringJUnit4ClassRunner.class) +@WebMvcTest +@ContextConfiguration(classes = {DiscreteCopyNumberCountController.class, TestConfig.class}) +public class DiscreteCopyNumberCountControllerTest { + + private static final String TEST_MOLECULAR_PROFILE_STABLE_ID_1 = + "test_molecular_profile_stable_id_1"; + private static final String TEST_SAMPLE_STABLE_ID_1 = "test_sample_stable_id_1"; + private static final int TEST_ENTREZ_GENE_ID_1 = 1; + private static final int TEST_ALTERATION_1 = 1; + private static final String TEST_HUGO_GENE_SYMBOL_1 = "test_hugo_gene_symbol_1"; + private static final String TEST_TYPE_1 = "test_type_1"; + private static final String TEST_CYTOBAND_1 = "test_cytoband_1"; + private static final String TEST_CHROMOSOME_1 = "test_chromosome_1"; + private static final String TEST_MOLECULAR_PROFILE_STABLE_ID_2 = + "test_molecular_profile_stable_id_2"; + private static final String TEST_SAMPLE_STABLE_ID_2 = "test_sample_stable_id_2"; + private static final int TEST_ENTREZ_GENE_ID_2 = 2; + private static final int TEST_ALTERATION_2 = 2; + private static final String TEST_HUGO_GENE_SYMBOL_2 = "test_hugo_gene_symbol_2"; + private static final String TEST_TYPE_2 = "test_type_2"; + private static final String TEST_CYTOBAND_2 = "test_cytoband_2"; + private static final String TEST_CHROMOSOME_2 = "test_chromosome_2"; + private static final String TEST_SAMPLE_LIST_ID = "test_sample_list_id"; + private static final int TEST_NUMBER_OF_SAMPLES_1 = 6; + private static final int TEST_NUMBER_OF_SAMPLES_WITH_ALTERATION_IN_GENE_1 = 4; + private static final int TEST_NUMBER_OF_SAMPLES_2 = 10; + private static final int TEST_NUMBER_OF_SAMPLES_WITH_ALTERATION_IN_GENE_2 = 8; + + @MockBean private DiscreteCopyNumberService discreteCopyNumberService; + + private ObjectMapper objectMapper = new ObjectMapper(); + + @Autowired private MockMvc mockMvc; + + @Test + @WithMockUser + public void fetchCopyNumberCounts() throws Exception { + + List copyNumberCountList = new ArrayList<>(); + CopyNumberCount copyNumberCount1 = new CopyNumberCount(); + copyNumberCount1.setMolecularProfileId(TEST_MOLECULAR_PROFILE_STABLE_ID_1); + copyNumberCount1.setEntrezGeneId(TEST_ENTREZ_GENE_ID_1); + copyNumberCount1.setAlteration(TEST_ALTERATION_1); + copyNumberCount1.setNumberOfSamples(TEST_NUMBER_OF_SAMPLES_1); + copyNumberCount1.setNumberOfSamplesWithAlterationInGene( + TEST_NUMBER_OF_SAMPLES_WITH_ALTERATION_IN_GENE_1); + copyNumberCountList.add(copyNumberCount1); + CopyNumberCount copyNumberCount2 = new CopyNumberCount(); + copyNumberCount2.setMolecularProfileId(TEST_MOLECULAR_PROFILE_STABLE_ID_1); + copyNumberCount2.setEntrezGeneId(TEST_ENTREZ_GENE_ID_2); + copyNumberCount2.setAlteration(TEST_ALTERATION_2); + copyNumberCount2.setNumberOfSamples(TEST_NUMBER_OF_SAMPLES_2); + copyNumberCount2.setNumberOfSamplesWithAlterationInGene( + TEST_NUMBER_OF_SAMPLES_WITH_ALTERATION_IN_GENE_2); + copyNumberCountList.add(copyNumberCount2); + + Mockito.when( + discreteCopyNumberService.fetchCopyNumberCounts( + Mockito.anyString(), Mockito.anyList(), Mockito.anyList())) + .thenReturn(copyNumberCountList); + + List copyNumberCountIdentifiers = new ArrayList<>(); + CopyNumberCountIdentifier copyNumberCountIdentifier1 = new CopyNumberCountIdentifier(); + copyNumberCountIdentifier1.setEntrezGeneId(TEST_ENTREZ_GENE_ID_1); + copyNumberCountIdentifier1.setAlteration(TEST_ALTERATION_1); + copyNumberCountIdentifiers.add(copyNumberCountIdentifier1); + CopyNumberCountIdentifier copyNumberCountIdentifier2 = new CopyNumberCountIdentifier(); + copyNumberCountIdentifier2.setEntrezGeneId(TEST_ENTREZ_GENE_ID_2); + copyNumberCountIdentifier2.setAlteration(TEST_ALTERATION_2); + copyNumberCountIdentifiers.add(copyNumberCountIdentifier2); + + mockMvc + .perform( + MockMvcRequestBuilders.post( + "/api/molecular-profiles/test_molecular_profile_id/discrete-copy-number-counts/fetch") + .with(csrf()) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(copyNumberCountIdentifiers))) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect( + MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.jsonPath("$", Matchers.hasSize(2))) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].entrezGeneId").value(TEST_ENTREZ_GENE_ID_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].molecularProfileId") + .value(TEST_MOLECULAR_PROFILE_STABLE_ID_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].alteration").value(TEST_ALTERATION_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].numberOfSamples").value(TEST_NUMBER_OF_SAMPLES_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].numberOfSamplesWithAlterationInGene") + .value(TEST_NUMBER_OF_SAMPLES_WITH_ALTERATION_IN_GENE_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].entrezGeneId").value(TEST_ENTREZ_GENE_ID_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].molecularProfileId") + .value(TEST_MOLECULAR_PROFILE_STABLE_ID_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].alteration").value(TEST_ALTERATION_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].numberOfSamples").value(TEST_NUMBER_OF_SAMPLES_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].numberOfSamplesWithAlterationInGene") + .value(TEST_NUMBER_OF_SAMPLES_WITH_ALTERATION_IN_GENE_2)); + } +} diff --git a/src/test/java/org/cbioportal/legacy/web/DocRedirectControllerTest.java b/src/test/java/org/cbioportal/legacy/web/DocRedirectControllerTest.java new file mode 100644 index 00000000000..591c778ada9 --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/web/DocRedirectControllerTest.java @@ -0,0 +1,56 @@ +package org.cbioportal.legacy.web; + +import com.fasterxml.jackson.databind.ObjectMapper; +import org.cbioportal.legacy.web.config.TestConfig; +import org.junit.Before; +import org.junit.Ignore; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.result.MockMvcResultMatchers; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import org.springframework.web.context.WebApplicationContext; + +@RunWith(SpringJUnit4ClassRunner.class) +@WebMvcTest +@ContextConfiguration(classes = {DocRedirectController.class, TestConfig.class}) +@Ignore +// TODO: Had to disable docredirect Controller +public class DocRedirectControllerTest { + @Autowired private WebApplicationContext wac; + + private ObjectMapper objectMapper = new ObjectMapper(); + + private MockMvc mockMvc; + + @Before + public void setUp() throws Exception { + mockMvc = MockMvcBuilders.webAppContextSetup(wac).build(); + } + + @Test + public void shouldRedirectForDocs() throws Exception { + mockMvc + .perform(MockMvcRequestBuilders.get("/api-docs")) + .andExpect(MockMvcResultMatchers.status().is3xxRedirection()) + .andExpect(MockMvcResultMatchers.redirectedUrl("/api/v2/api-docs?group=default")); + } + + @Test + public void shouldRedirectForUI() throws Exception { + mockMvc + .perform(MockMvcRequestBuilders.get("/")) + .andExpect(MockMvcResultMatchers.status().is3xxRedirection()) + .andExpect(MockMvcResultMatchers.redirectedUrl("/api/swagger-ui/index.html?group=default")); + + mockMvc + .perform(MockMvcRequestBuilders.get("/swagger-ui.html")) + .andExpect(MockMvcResultMatchers.status().is3xxRedirection()) + .andExpect(MockMvcResultMatchers.redirectedUrl("/api/swagger-ui/index.html?group=default")); + } +} diff --git a/src/test/java/org/cbioportal/legacy/web/ExpressionEnrichmentControllerTest.java b/src/test/java/org/cbioportal/legacy/web/ExpressionEnrichmentControllerTest.java new file mode 100644 index 00000000000..a600a3204b5 --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/web/ExpressionEnrichmentControllerTest.java @@ -0,0 +1,240 @@ +package org.cbioportal.legacy.web; + +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; + +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.List; +import org.cbioportal.legacy.model.EnrichmentType; +import org.cbioportal.legacy.model.GenericAssayEnrichment; +import org.cbioportal.legacy.model.GenomicEnrichment; +import org.cbioportal.legacy.model.GroupStatistics; +import org.cbioportal.legacy.service.ExpressionEnrichmentService; +import org.cbioportal.legacy.web.config.TestConfig; +import org.hamcrest.Matchers; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mockito; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; +import org.springframework.security.test.context.support.WithMockUser; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.result.MockMvcResultMatchers; + +@RunWith(SpringJUnit4ClassRunner.class) +@WebMvcTest +@ContextConfiguration(classes = {ExpressionEnrichmentController.class, TestConfig.class}) +public class ExpressionEnrichmentControllerTest { + + private static final int TEST_ENTREZ_GENE_ID_1 = 1; + private static final String TEST_HUGO_GENE_SYMBOL_1 = "test_hugo_gene_symbol_1"; + private static final String TEST_CYTOBAND_1 = "test_cytoband_1"; + private static final BigDecimal TEST_MEAN_EXPRESSION_IN_ALTERED_GROUP_1 = new BigDecimal(2.3); + private static final BigDecimal TEST_MEAN_EXPRESSION_IN_UNALTERED_GROUP_1 = new BigDecimal(2.4); + private static final BigDecimal TEST_STANDARD_DEVIATION_IN_ALTERED_GROUP_1 = new BigDecimal(2.1); + private static final BigDecimal TEST_STANDARD_DEVIATION_IN_UNALTERED_GROUP_1 = + new BigDecimal(2.6); + private static final BigDecimal TEST_P_VALUE_1 = new BigDecimal(1.1); + private static final int TEST_ENTREZ_GENE_ID_2 = 2; + private static final String TEST_HUGO_GENE_SYMBOL_2 = "test_hugo_gene_symbol_2"; + private static final String TEST_CYTOBAND_2 = "test_cytoband_2"; + private static final BigDecimal TEST_MEAN_EXPRESSION_IN_ALTERED_GROUP_2 = new BigDecimal(2.7); + private static final BigDecimal TEST_MEAN_EXPRESSION_IN_UNALTERED_GROUP_2 = new BigDecimal(2.8); + private static final BigDecimal TEST_STANDARD_DEVIATION_IN_ALTERED_GROUP_2 = new BigDecimal(2.9); + private static final BigDecimal TEST_STANDARD_DEVIATION_IN_UNALTERED_GROUP_2 = + new BigDecimal(3.1); + private static final BigDecimal TEST_P_VALUE_2 = new BigDecimal(2.1); + + @MockBean private ExpressionEnrichmentService expressionEnrichmentService; + + @Autowired private MockMvc mockMvc; + + @Test + @WithMockUser + public void fetchGenomicEnrichments() throws Exception { + + List expressionEnrichments = new ArrayList<>(); + GenomicEnrichment expressionEnrichment1 = new GenomicEnrichment(); + expressionEnrichment1.setEntrezGeneId(TEST_ENTREZ_GENE_ID_1); + expressionEnrichment1.setHugoGeneSymbol(TEST_HUGO_GENE_SYMBOL_1); + expressionEnrichment1.setCytoband(TEST_CYTOBAND_1); + List groupStatistics1 = new ArrayList<>(); + GroupStatistics alteredGroupStats1 = new GroupStatistics(); + alteredGroupStats1.setName("altered samples"); + alteredGroupStats1.setMeanExpression(TEST_MEAN_EXPRESSION_IN_ALTERED_GROUP_1); + alteredGroupStats1.setStandardDeviation(TEST_STANDARD_DEVIATION_IN_ALTERED_GROUP_1); + groupStatistics1.add(alteredGroupStats1); + GroupStatistics unalteredGroupStats1 = new GroupStatistics(); + unalteredGroupStats1.setName("unaltered samples"); + unalteredGroupStats1.setMeanExpression(TEST_MEAN_EXPRESSION_IN_UNALTERED_GROUP_1); + unalteredGroupStats1.setStandardDeviation(TEST_STANDARD_DEVIATION_IN_UNALTERED_GROUP_1); + groupStatistics1.add(unalteredGroupStats1); + expressionEnrichment1.setpValue(TEST_P_VALUE_1); + expressionEnrichments.add(expressionEnrichment1); + expressionEnrichment1.setGroupsStatistics(groupStatistics1); + + GenomicEnrichment expressionEnrichment2 = new GenomicEnrichment(); + expressionEnrichment2.setEntrezGeneId(TEST_ENTREZ_GENE_ID_2); + expressionEnrichment2.setHugoGeneSymbol(TEST_HUGO_GENE_SYMBOL_2); + expressionEnrichment2.setCytoband(TEST_CYTOBAND_2); + List groupStatistics2 = new ArrayList<>(); + GroupStatistics alteredGroupStats2 = new GroupStatistics(); + alteredGroupStats2.setName("altered samples"); + alteredGroupStats2.setMeanExpression(TEST_MEAN_EXPRESSION_IN_ALTERED_GROUP_2); + alteredGroupStats2.setStandardDeviation(TEST_STANDARD_DEVIATION_IN_ALTERED_GROUP_2); + groupStatistics2.add(alteredGroupStats2); + GroupStatistics unalteredGroupStats2 = new GroupStatistics(); + unalteredGroupStats2.setName("unaltered samples"); + unalteredGroupStats2.setMeanExpression(TEST_MEAN_EXPRESSION_IN_UNALTERED_GROUP_2); + unalteredGroupStats2.setStandardDeviation(TEST_STANDARD_DEVIATION_IN_UNALTERED_GROUP_2); + groupStatistics2.add(unalteredGroupStats2); + expressionEnrichment2.setGroupsStatistics(groupStatistics2); + expressionEnrichment2.setpValue(TEST_P_VALUE_2); + expressionEnrichments.add(expressionEnrichment2); + + Mockito.when( + expressionEnrichmentService.getGenomicEnrichments( + Mockito.anyString(), Mockito.anyMap(), Mockito.any(EnrichmentType.class))) + .thenReturn(expressionEnrichments); + + mockMvc + .perform( + MockMvcRequestBuilders.post("/api/expression-enrichments/fetch") + .accept(MediaType.APPLICATION_JSON) + .with(csrf()) + .contentType(MediaType.APPLICATION_JSON) + .content( + "[{\"molecularProfileCaseIdentifiers\":[{\"caseId\":\"TCGA-OR-A5JH-01\",\"molecularProfileId\":\"acc_tcga_pan_can_atlas_2018_rna_seq_v2_mrna\"},{\"caseId\":\"TCGA-OR-A5K2-01\",\"molecularProfileId\":\"acc_tcga_pan_can_atlas_2018_rna_seq_v2_mrna\"}],\"name\":\"altered\"}," + + "{\"molecularProfileCaseIdentifiers\":[{\"caseId\":\"TCGA-OR-A5LN-01\",\"molecularProfileId\":\"acc_tcga_pan_can_atlas_2018_rna_seq_v2_mrna\"},{\"caseId\":\"TCGA-OR-A5LS-01\",\"molecularProfileId\":\"acc_tcga_pan_can_atlas_2018_rna_seq_v2_mrna\"}],\"name\":\"unaltered\"}]")) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect( + MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.jsonPath("$", Matchers.hasSize(2))) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].entrezGeneId").value(TEST_ENTREZ_GENE_ID_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].hugoGeneSymbol").value(TEST_HUGO_GENE_SYMBOL_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].cytoband").value(TEST_CYTOBAND_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].groupsStatistics[0].meanExpression") + .value(TEST_MEAN_EXPRESSION_IN_ALTERED_GROUP_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].groupsStatistics[0].standardDeviation") + .value(TEST_STANDARD_DEVIATION_IN_ALTERED_GROUP_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].groupsStatistics[1].meanExpression") + .value(TEST_MEAN_EXPRESSION_IN_UNALTERED_GROUP_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].groupsStatistics[1].standardDeviation") + .value(TEST_STANDARD_DEVIATION_IN_UNALTERED_GROUP_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].pValue").value(TEST_P_VALUE_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].entrezGeneId").value(TEST_ENTREZ_GENE_ID_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].hugoGeneSymbol").value(TEST_HUGO_GENE_SYMBOL_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].cytoband").value(TEST_CYTOBAND_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].groupsStatistics[0].meanExpression") + .value(TEST_MEAN_EXPRESSION_IN_ALTERED_GROUP_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].groupsStatistics[0].standardDeviation") + .value(TEST_STANDARD_DEVIATION_IN_ALTERED_GROUP_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].groupsStatistics[1].meanExpression") + .value(TEST_MEAN_EXPRESSION_IN_UNALTERED_GROUP_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].groupsStatistics[1].standardDeviation") + .value(TEST_STANDARD_DEVIATION_IN_UNALTERED_GROUP_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].pValue").value(TEST_P_VALUE_2)); + } + + @Test + @WithMockUser + public void fetchGenericAssayEnrichments() throws Exception { + + List genericAssayEnrichments = new ArrayList<>(); + GenericAssayEnrichment genericAssayEnrichment1 = new GenericAssayEnrichment(); + genericAssayEnrichment1.setStableId(TEST_HUGO_GENE_SYMBOL_1); + List groupStatistics1 = new ArrayList<>(); + GroupStatistics alteredGroupStats1 = new GroupStatistics(); + alteredGroupStats1.setName("altered samples"); + alteredGroupStats1.setMeanExpression(TEST_MEAN_EXPRESSION_IN_ALTERED_GROUP_1); + alteredGroupStats1.setStandardDeviation(TEST_STANDARD_DEVIATION_IN_ALTERED_GROUP_1); + groupStatistics1.add(alteredGroupStats1); + GroupStatistics unalteredGroupStats1 = new GroupStatistics(); + unalteredGroupStats1.setName("unaltered samples"); + unalteredGroupStats1.setMeanExpression(TEST_MEAN_EXPRESSION_IN_UNALTERED_GROUP_1); + unalteredGroupStats1.setStandardDeviation(TEST_STANDARD_DEVIATION_IN_UNALTERED_GROUP_1); + groupStatistics1.add(unalteredGroupStats1); + genericAssayEnrichment1.setpValue(TEST_P_VALUE_1); + genericAssayEnrichments.add(genericAssayEnrichment1); + genericAssayEnrichment1.setGroupsStatistics(groupStatistics1); + + GenericAssayEnrichment genericAssayEnrichment2 = new GenericAssayEnrichment(); + genericAssayEnrichment2.setStableId(TEST_HUGO_GENE_SYMBOL_2); + List groupStatistics2 = new ArrayList<>(); + GroupStatistics alteredGroupStats2 = new GroupStatistics(); + alteredGroupStats2.setName("altered samples"); + alteredGroupStats2.setMeanExpression(TEST_MEAN_EXPRESSION_IN_ALTERED_GROUP_2); + alteredGroupStats2.setStandardDeviation(TEST_STANDARD_DEVIATION_IN_ALTERED_GROUP_2); + groupStatistics2.add(alteredGroupStats2); + GroupStatistics unalteredGroupStats2 = new GroupStatistics(); + unalteredGroupStats2.setName("unaltered samples"); + unalteredGroupStats2.setMeanExpression(TEST_MEAN_EXPRESSION_IN_UNALTERED_GROUP_2); + unalteredGroupStats2.setStandardDeviation(TEST_STANDARD_DEVIATION_IN_UNALTERED_GROUP_2); + groupStatistics2.add(unalteredGroupStats2); + genericAssayEnrichment2.setGroupsStatistics(groupStatistics2); + genericAssayEnrichment2.setpValue(TEST_P_VALUE_2); + genericAssayEnrichments.add(genericAssayEnrichment2); + + Mockito.when( + expressionEnrichmentService.getGenericAssayNumericalEnrichments( + Mockito.anyString(), Mockito.anyMap(), Mockito.any(EnrichmentType.class))) + .thenReturn(genericAssayEnrichments); + + mockMvc + .perform( + MockMvcRequestBuilders.post("/api/generic-assay-enrichments/fetch") + .with(csrf()) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + .content( + "[{\"molecularProfileCaseIdentifiers\":[{\"caseId\":\"TCGA-OR-A5JH-01\",\"molecularProfileId\":\"acc_tcga_pan_can_atlas_2018_rna_seq_v2_mrna\"},{\"caseId\":\"TCGA-OR-A5K2-01\",\"molecularProfileId\":\"acc_tcga_pan_can_atlas_2018_rna_seq_v2_mrna\"}],\"name\":\"altered\"}," + + "{\"molecularProfileCaseIdentifiers\":[{\"caseId\":\"TCGA-OR-A5LN-01\",\"molecularProfileId\":\"acc_tcga_pan_can_atlas_2018_rna_seq_v2_mrna\"},{\"caseId\":\"TCGA-OR-A5LS-01\",\"molecularProfileId\":\"acc_tcga_pan_can_atlas_2018_rna_seq_v2_mrna\"}],\"name\":\"unaltered\"}]")) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect( + MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.jsonPath("$", Matchers.hasSize(2))) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].stableId").value(TEST_HUGO_GENE_SYMBOL_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].groupsStatistics[0].meanExpression") + .value(TEST_MEAN_EXPRESSION_IN_ALTERED_GROUP_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].groupsStatistics[0].standardDeviation") + .value(TEST_STANDARD_DEVIATION_IN_ALTERED_GROUP_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].groupsStatistics[1].meanExpression") + .value(TEST_MEAN_EXPRESSION_IN_UNALTERED_GROUP_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].groupsStatistics[1].standardDeviation") + .value(TEST_STANDARD_DEVIATION_IN_UNALTERED_GROUP_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].pValue").value(TEST_P_VALUE_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].stableId").value(TEST_HUGO_GENE_SYMBOL_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].groupsStatistics[0].meanExpression") + .value(TEST_MEAN_EXPRESSION_IN_ALTERED_GROUP_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].groupsStatistics[0].standardDeviation") + .value(TEST_STANDARD_DEVIATION_IN_ALTERED_GROUP_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].groupsStatistics[1].meanExpression") + .value(TEST_MEAN_EXPRESSION_IN_UNALTERED_GROUP_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].groupsStatistics[1].standardDeviation") + .value(TEST_STANDARD_DEVIATION_IN_UNALTERED_GROUP_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].pValue").value(TEST_P_VALUE_2)); + } +} diff --git a/src/test/java/org/cbioportal/legacy/web/GeneControllerTest.java b/src/test/java/org/cbioportal/legacy/web/GeneControllerTest.java new file mode 100644 index 00000000000..95867008be4 --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/web/GeneControllerTest.java @@ -0,0 +1,235 @@ +package org.cbioportal.legacy.web; + +import static org.mockito.ArgumentMatchers.eq; +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; + +import com.fasterxml.jackson.databind.ObjectMapper; +import java.util.ArrayList; +import java.util.List; +import org.cbioportal.legacy.model.Gene; +import org.cbioportal.legacy.model.meta.BaseMeta; +import org.cbioportal.legacy.service.GeneService; +import org.cbioportal.legacy.service.exception.GeneNotFoundException; +import org.cbioportal.legacy.web.config.TestConfig; +import org.cbioportal.legacy.web.parameter.HeaderKeyConstants; +import org.hamcrest.Matchers; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mockito; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; +import org.springframework.security.test.context.support.WithMockUser; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.result.MockMvcResultMatchers; + +@RunWith(SpringJUnit4ClassRunner.class) +@WebMvcTest +@ContextConfiguration(classes = {GeneService.class, GeneController.class, TestConfig.class}) +public class GeneControllerTest { + + public static final int ENTREZ_GENE_ID_1 = 1; + public static final String HUGO_GENE_SYMBOL_1 = "hugo_gene_symbol_1"; + public static final String TYPE_1 = "type_1"; + public static final String CYTOBAND_1 = "cytoband_1"; + public static final String CHROMOSOME_1 = "chromosome_1"; + public static final int ENTREZ_GENE_ID_2 = 2; + public static final String HUGO_GENE_SYMBOL_2 = "hugo_gene_symbol_2"; + public static final String TYPE_2 = "type_2"; + public static final String CYTOBAND_2 = "cytoband_2"; + public static final String CHROMOSOME_2 = "chromosome_2"; + public static final String ALIAS_1 = "alias_1"; + public static final String ALIAS_2 = "alias_2"; + + @MockBean private GeneService geneService; + + private ObjectMapper objectMapper = new ObjectMapper(); + + @Autowired private MockMvc mockMvc; + + @Test + @WithMockUser + public void getAllGenesDefaultProjection() throws Exception { + + List geneList = createGeneList(); + + Mockito.when( + geneService.getAllGenes( + Mockito.any(), + Mockito.any(), + Mockito.any(), + Mockito.any(), + Mockito.any(), + Mockito.any(), + Mockito.any())) + .thenReturn(geneList); + + mockMvc + .perform(MockMvcRequestBuilders.get("/api/genes").accept(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect( + MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.jsonPath("$", Matchers.hasSize(2))) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].entrezGeneId").value(ENTREZ_GENE_ID_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].hugoGeneSymbol").value(HUGO_GENE_SYMBOL_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].type").value(TYPE_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].entrezGeneId").value(ENTREZ_GENE_ID_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].hugoGeneSymbol").value(HUGO_GENE_SYMBOL_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].type").value(TYPE_2)); + } + + @Test + @WithMockUser + public void getAllGenesMetaProjection() throws Exception { + + BaseMeta baseMeta = new BaseMeta(); + baseMeta.setTotalCount(ENTREZ_GENE_ID_2); + + Mockito.when(geneService.getMetaGenes(Mockito.any(), Mockito.any())).thenReturn(baseMeta); + + mockMvc + .perform(MockMvcRequestBuilders.get("/api/genes").param("projection", "META")) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect(MockMvcResultMatchers.header().string(HeaderKeyConstants.TOTAL_COUNT, "2")); + } + + @Test + @WithMockUser + public void getGeneNotFound() throws Exception { + + Mockito.when(geneService.getGene(eq("test_gene_id"))) + .thenThrow(new GeneNotFoundException("test_gene_id")); + + mockMvc + .perform( + MockMvcRequestBuilders.get("/api/genes/test_gene_id") + .accept(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.status().isNotFound()) + .andExpect( + MockMvcResultMatchers.jsonPath("$.message").value("Gene not found: test_gene_id")); + } + + @Test + @WithMockUser + public void getGene() throws Exception { + + List geneList = new ArrayList<>(); + Gene gene = new Gene(); + gene.setEntrezGeneId(ENTREZ_GENE_ID_1); + gene.setHugoGeneSymbol(HUGO_GENE_SYMBOL_1); + gene.setType(TYPE_1); + geneList.add(gene); + + Mockito.when(geneService.getGene(Mockito.anyString())).thenReturn(gene); + + mockMvc + .perform( + MockMvcRequestBuilders.get("/api/genes/test_gene_id") + .accept(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect( + MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.jsonPath("$.entrezGeneId").value(ENTREZ_GENE_ID_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$.hugoGeneSymbol").value(HUGO_GENE_SYMBOL_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$.type").value(TYPE_1)); + } + + @Test + @WithMockUser + public void getAliasesOfGene() throws Exception { + + List aliasList = new ArrayList<>(); + aliasList.add(ALIAS_1); + aliasList.add(ALIAS_2); + + Mockito.when(geneService.getAliasesOfGene(Mockito.anyString())).thenReturn(aliasList); + + mockMvc + .perform( + MockMvcRequestBuilders.get("/api/genes/test_gene_id/aliases") + .accept(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect( + MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.jsonPath("$", Matchers.hasSize(2))) + .andExpect(MockMvcResultMatchers.jsonPath("$[0]").value(ALIAS_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1]").value(ALIAS_2)); + } + + @Test + @WithMockUser + public void fetchGenesDefaultProjection() throws Exception { + + List geneList = createGeneList(); + + Mockito.when( + geneService.fetchGenes(Mockito.anyList(), Mockito.anyString(), Mockito.anyString())) + .thenReturn(geneList); + + List geneIds = new ArrayList<>(); + geneIds.add(Integer.toString(ENTREZ_GENE_ID_1)); + geneIds.add(HUGO_GENE_SYMBOL_2); + + mockMvc + .perform( + MockMvcRequestBuilders.post("/api/genes/fetch") + .with(csrf()) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(geneIds))) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect( + MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.jsonPath("$", Matchers.hasSize(2))) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].entrezGeneId").value(ENTREZ_GENE_ID_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].hugoGeneSymbol").value(HUGO_GENE_SYMBOL_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].type").value(TYPE_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].entrezGeneId").value(ENTREZ_GENE_ID_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].hugoGeneSymbol").value(HUGO_GENE_SYMBOL_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].type").value(TYPE_2)); + } + + @Test + @WithMockUser + public void fetchGenesMetaProjection() throws Exception { + + BaseMeta baseMeta = new BaseMeta(); + baseMeta.setTotalCount(2); + + Mockito.when(geneService.fetchMetaGenes(Mockito.anyList(), Mockito.anyString())) + .thenReturn(baseMeta); + + List geneIds = new ArrayList<>(); + geneIds.add(Integer.toString(ENTREZ_GENE_ID_1)); + geneIds.add(HUGO_GENE_SYMBOL_2); + + mockMvc + .perform( + MockMvcRequestBuilders.post("/api/genes/fetch") + .with(csrf()) + .param("projection", "META") + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(geneIds))) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect(MockMvcResultMatchers.header().string(HeaderKeyConstants.TOTAL_COUNT, "2")); + } + + private List createGeneList() { + List geneList = new ArrayList<>(); + Gene gene1 = new Gene(); + gene1.setEntrezGeneId(ENTREZ_GENE_ID_1); + gene1.setHugoGeneSymbol(HUGO_GENE_SYMBOL_1); + gene1.setType(TYPE_1); + geneList.add(gene1); + Gene gene2 = new Gene(); + gene2.setEntrezGeneId(ENTREZ_GENE_ID_2); + gene2.setHugoGeneSymbol(HUGO_GENE_SYMBOL_2); + gene2.setType(TYPE_2); + geneList.add(gene2); + return geneList; + } +} diff --git a/src/test/java/org/cbioportal/legacy/web/GenePanelControllerTest.java b/src/test/java/org/cbioportal/legacy/web/GenePanelControllerTest.java new file mode 100644 index 00000000000..13662282080 --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/web/GenePanelControllerTest.java @@ -0,0 +1,225 @@ +package org.cbioportal.legacy.web; + +import com.fasterxml.jackson.databind.ObjectMapper; +import java.util.ArrayList; +import java.util.List; +import org.cbioportal.legacy.model.GenePanel; +import org.cbioportal.legacy.model.GenePanelToGene; +import org.cbioportal.legacy.model.meta.BaseMeta; +import org.cbioportal.legacy.service.GenePanelService; +import org.cbioportal.legacy.service.exception.GenePanelNotFoundException; +import org.cbioportal.legacy.web.config.TestConfig; +import org.cbioportal.legacy.web.parameter.HeaderKeyConstants; +import org.hamcrest.Matchers; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mockito; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; +import org.springframework.security.test.context.support.WithMockUser; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.result.MockMvcResultMatchers; + +@RunWith(SpringJUnit4ClassRunner.class) +@WebMvcTest +@ContextConfiguration(classes = {GenePanelController.class, TestConfig.class}) +public class GenePanelControllerTest { + + private static final String TEST_GENE_PANEL_ID_1 = "test_gene_panel_id_1"; + private static final int TEST_INTERNAL_ID_1 = 1; + private static final String TEST_DESCRIPTION_1 = "test_description_1"; + private static final String TEST_SAMPLE_ID_1 = "test_sample_id_1"; + private static final String TEST_PATIENT_ID_1 = "test_patient_id_1"; + private static final String TEST_STUDY_ID_1 = "test_study_id_1"; + private static final String TEST_MOLECULAR_PROFILE_ID_1 = "test_molecular_profile_id_1"; + private static final int TEST_ENTREZ_GENE_ID_1 = 100; + private static final String TEST_HUGO_GENE_SYMBOL_1 = "test_hugo_gene_symbol_1"; + private static final int TEST_ENTREZ_GENE_ID_2 = 200; + private static final String TEST_HUGO_GENE_SYMBOL_2 = "test_hugo_gene_symbol_2"; + private static final String TEST_GENE_PANEL_ID_2 = "test_gene_panel_id_2"; + private static final int TEST_INTERNAL_ID_2 = 2; + private static final String TEST_DESCRIPTION_2 = "test_description_2"; + private static final String TEST_SAMPLE_ID_2 = "test_sample_id_2"; + private static final String TEST_PATIENT_ID_2 = "test_patient_id_2"; + private static final String TEST_STUDY_ID_2 = "test_study_id_2"; + private static final String TEST_MOLECULAR_PROFILE_ID_2 = "test_molecular_profile_id_2"; + private static final int TEST_ENTREZ_GENE_ID_3 = 300; + private static final String TEST_HUGO_GENE_SYMBOL_3 = "test_hugo_gene_symbol_3"; + private static final int TEST_ENTREZ_GENE_ID_4 = 400; + private static final String TEST_HUGO_GENE_SYMBOL_4 = "test_hugo_gene_symbol_4"; + private static final String TEST_SAMPLE_LIST_ID = "test_sample_list_id"; + + @MockBean private GenePanelService genePanelService; + + private ObjectMapper objectMapper = new ObjectMapper(); + + @Autowired private MockMvc mockMvc; + + @Test + @WithMockUser + public void getAllGenePanelsDetailedProjection() throws Exception { + + List genePanelList = new ArrayList<>(); + GenePanel genePanel1 = new GenePanel(); + genePanel1.setStableId(TEST_GENE_PANEL_ID_1); + genePanel1.setInternalId(TEST_INTERNAL_ID_1); + genePanel1.setDescription(TEST_DESCRIPTION_1); + List genePanelToGeneList1 = new ArrayList<>(); + GenePanelToGene genePanelToGene1 = new GenePanelToGene(); + genePanelToGene1.setGenePanelId(TEST_GENE_PANEL_ID_1); + genePanelToGene1.setEntrezGeneId(TEST_ENTREZ_GENE_ID_1); + genePanelToGene1.setHugoGeneSymbol(TEST_HUGO_GENE_SYMBOL_1); + genePanelToGeneList1.add(genePanelToGene1); + GenePanelToGene genePanelToGene2 = new GenePanelToGene(); + genePanelToGene2.setGenePanelId(TEST_GENE_PANEL_ID_1); + genePanelToGene2.setEntrezGeneId(TEST_ENTREZ_GENE_ID_2); + genePanelToGene2.setHugoGeneSymbol(TEST_HUGO_GENE_SYMBOL_2); + genePanelToGeneList1.add(genePanelToGene2); + genePanel1.setGenes(genePanelToGeneList1); + genePanelList.add(genePanel1); + GenePanel genePanel2 = new GenePanel(); + genePanel2.setStableId(TEST_GENE_PANEL_ID_2); + genePanel2.setInternalId(TEST_INTERNAL_ID_2); + genePanel2.setDescription(TEST_DESCRIPTION_2); + List genePanelToGeneList2 = new ArrayList<>(); + GenePanelToGene genePanelToGene3 = new GenePanelToGene(); + genePanelToGene3.setGenePanelId(TEST_GENE_PANEL_ID_2); + genePanelToGene3.setEntrezGeneId(TEST_ENTREZ_GENE_ID_3); + genePanelToGene3.setHugoGeneSymbol(TEST_HUGO_GENE_SYMBOL_3); + genePanelToGeneList2.add(genePanelToGene3); + GenePanelToGene genePanelToGene4 = new GenePanelToGene(); + genePanelToGene4.setGenePanelId(TEST_GENE_PANEL_ID_2); + genePanelToGene4.setEntrezGeneId(TEST_ENTREZ_GENE_ID_4); + genePanelToGene4.setHugoGeneSymbol(TEST_HUGO_GENE_SYMBOL_4); + genePanelToGeneList2.add(genePanelToGene4); + genePanel2.setGenes(genePanelToGeneList2); + genePanelList.add(genePanel2); + + Mockito.when( + genePanelService.getAllGenePanels( + Mockito.any(), Mockito.any(), Mockito.any(), Mockito.any(), Mockito.any())) + .thenReturn(genePanelList); + + mockMvc + .perform(MockMvcRequestBuilders.get("/api/gene-panels/").accept(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect( + MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.jsonPath("$", Matchers.hasSize(2))) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].stableId").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].internalId").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].genePanelId").value(TEST_GENE_PANEL_ID_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].description").value(TEST_DESCRIPTION_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].genes[0].entrezGeneId") + .value(TEST_ENTREZ_GENE_ID_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].genes[0].hugoGeneSymbol") + .value(TEST_HUGO_GENE_SYMBOL_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].genes[1].entrezGeneId") + .value(TEST_ENTREZ_GENE_ID_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].genes[1].hugoGeneSymbol") + .value(TEST_HUGO_GENE_SYMBOL_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].stableId").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].internalId").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].genePanelId").value(TEST_GENE_PANEL_ID_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].description").value(TEST_DESCRIPTION_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].genes[0].entrezGeneId") + .value(TEST_ENTREZ_GENE_ID_3)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].genes[0].hugoGeneSymbol") + .value(TEST_HUGO_GENE_SYMBOL_3)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].genes[1].entrezGeneId") + .value(TEST_ENTREZ_GENE_ID_4)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].genes[1].hugoGeneSymbol") + .value(TEST_HUGO_GENE_SYMBOL_4)); + } + + @Test + @WithMockUser + public void getAllGenePanelsMetaProjection() throws Exception { + + BaseMeta baseMeta = new BaseMeta(); + baseMeta.setTotalCount(2); + + Mockito.when(genePanelService.getMetaGenePanels()).thenReturn(baseMeta); + + mockMvc + .perform(MockMvcRequestBuilders.get("/api/gene-panels/").param("projection", "META")) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect(MockMvcResultMatchers.header().string(HeaderKeyConstants.TOTAL_COUNT, "2")); + } + + @Test + @WithMockUser + public void getGenePanelNotFound() throws Exception { + + Mockito.when(genePanelService.getGenePanel(Mockito.anyString())) + .thenThrow(new GenePanelNotFoundException("test_gene_panel_id")); + + mockMvc + .perform( + MockMvcRequestBuilders.get("/api/gene-panels/test_gene_panel_id") + .accept(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.status().isNotFound()) + .andExpect( + MockMvcResultMatchers.jsonPath("$.message") + .value("Gene panel not found: test_gene_panel_id")); + } + + @Test + @WithMockUser + public void getGenePanel() throws Exception { + + GenePanel genePanel = new GenePanel(); + genePanel.setStableId(TEST_GENE_PANEL_ID_1); + genePanel.setInternalId(TEST_INTERNAL_ID_1); + genePanel.setDescription(TEST_DESCRIPTION_1); + List genePanelToGeneList = new ArrayList<>(); + GenePanelToGene genePanelToGene1 = new GenePanelToGene(); + genePanelToGene1.setGenePanelId(TEST_GENE_PANEL_ID_1); + genePanelToGene1.setEntrezGeneId(TEST_ENTREZ_GENE_ID_1); + genePanelToGene1.setHugoGeneSymbol(TEST_HUGO_GENE_SYMBOL_1); + genePanelToGeneList.add(genePanelToGene1); + GenePanelToGene genePanelToGene2 = new GenePanelToGene(); + genePanelToGene2.setGenePanelId(TEST_GENE_PANEL_ID_1); + genePanelToGene2.setEntrezGeneId(TEST_ENTREZ_GENE_ID_2); + genePanelToGene2.setHugoGeneSymbol(TEST_HUGO_GENE_SYMBOL_2); + genePanelToGeneList.add(genePanelToGene2); + genePanel.setGenes(genePanelToGeneList); + + Mockito.when(genePanelService.getGenePanel(Mockito.anyString())).thenReturn(genePanel); + + mockMvc + .perform( + MockMvcRequestBuilders.get("/api/gene-panels/test_gene_panel_id") + .accept(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect( + MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.jsonPath("$.stableId").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$.internalId").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$.genePanelId").value(TEST_GENE_PANEL_ID_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$.description").value(TEST_DESCRIPTION_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$.genes[0].entrezGeneId").value(TEST_ENTREZ_GENE_ID_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$.genes[0].hugoGeneSymbol") + .value(TEST_HUGO_GENE_SYMBOL_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$.genes[1].entrezGeneId").value(TEST_ENTREZ_GENE_ID_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$.genes[1].hugoGeneSymbol") + .value(TEST_HUGO_GENE_SYMBOL_2)); + } +} diff --git a/src/test/java/org/cbioportal/legacy/web/GenePanelDataControllerTest.java b/src/test/java/org/cbioportal/legacy/web/GenePanelDataControllerTest.java new file mode 100644 index 00000000000..514eedb5536 --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/web/GenePanelDataControllerTest.java @@ -0,0 +1,185 @@ +package org.cbioportal.legacy.web; + +import com.fasterxml.jackson.databind.ObjectMapper; +import java.util.ArrayList; +import java.util.List; +import org.cbioportal.legacy.model.GenePanelData; +import org.cbioportal.legacy.service.GenePanelService; +import org.cbioportal.legacy.web.config.TestConfig; +import org.cbioportal.legacy.web.parameter.GenePanelDataFilter; +import org.cbioportal.legacy.web.parameter.GenePanelDataMultipleStudyFilter; +import org.cbioportal.legacy.web.parameter.SampleMolecularIdentifier; +import org.hamcrest.Matchers; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mockito; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; +import org.springframework.security.test.context.support.WithMockUser; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.result.MockMvcResultMatchers; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import org.springframework.web.context.WebApplicationContext; + +@RunWith(SpringJUnit4ClassRunner.class) +@WebMvcTest +@ContextConfiguration(classes = {GenePanelDataController.class, TestConfig.class}) +public class GenePanelDataControllerTest { + + private static final String TEST_GENE_PANEL_ID_1 = "test_gene_panel_id_1"; + private static final int TEST_INTERNAL_ID_1 = 1; + private static final String TEST_DESCRIPTION_1 = "test_description_1"; + private static final String TEST_SAMPLE_ID_1 = "test_sample_id_1"; + private static final String TEST_PATIENT_ID_1 = "test_patient_id_1"; + private static final String TEST_STUDY_ID_1 = "test_study_id_1"; + private static final String TEST_MOLECULAR_PROFILE_ID_1 = "test_molecular_profile_id_1"; + private static final int TEST_ENTREZ_GENE_ID_1 = 100; + private static final String TEST_HUGO_GENE_SYMBOL_1 = "test_hugo_gene_symbol_1"; + private static final int TEST_ENTREZ_GENE_ID_2 = 200; + private static final String TEST_HUGO_GENE_SYMBOL_2 = "test_hugo_gene_symbol_2"; + private static final String TEST_GENE_PANEL_ID_2 = "test_gene_panel_id_2"; + private static final int TEST_INTERNAL_ID_2 = 2; + private static final String TEST_DESCRIPTION_2 = "test_description_2"; + private static final String TEST_SAMPLE_ID_2 = "test_sample_id_2"; + private static final String TEST_PATIENT_ID_2 = "test_patient_id_2"; + private static final String TEST_STUDY_ID_2 = "test_study_id_2"; + private static final String TEST_MOLECULAR_PROFILE_ID_2 = "test_molecular_profile_id_2"; + private static final int TEST_ENTREZ_GENE_ID_3 = 300; + private static final String TEST_HUGO_GENE_SYMBOL_3 = "test_hugo_gene_symbol_3"; + private static final int TEST_ENTREZ_GENE_ID_4 = 400; + private static final String TEST_HUGO_GENE_SYMBOL_4 = "test_hugo_gene_symbol_4"; + private static final String TEST_SAMPLE_LIST_ID = "test_sample_list_id"; + + @Autowired private WebApplicationContext wac; + + @MockBean private GenePanelService genePanelService; + + private ObjectMapper objectMapper = new ObjectMapper(); + + private MockMvc mockMvc; + + @Before + public void setUp() throws Exception { + + Mockito.reset(genePanelService); + mockMvc = MockMvcBuilders.webAppContextSetup(wac).build(); + } + + @Test + @WithMockUser + public void getGenePanelData() throws Exception { + + List genePanelDataList = createExampleGenePanelData(); + + Mockito.when(genePanelService.getGenePanelData(Mockito.anyString(), Mockito.anyString())) + .thenReturn(genePanelDataList); + + GenePanelDataFilter genePanelDataFilter = new GenePanelDataFilter(); + genePanelDataFilter.setSampleListId(TEST_SAMPLE_LIST_ID); + + mockMvc + .perform( + MockMvcRequestBuilders.post( + "/api/molecular-profiles/test_molecular_profile_id/gene-panel-data/fetch") + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(genePanelDataFilter))) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect( + MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.jsonPath("$", Matchers.hasSize(2))) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].molecularProfileId") + .value(TEST_MOLECULAR_PROFILE_ID_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].sampleId").value(TEST_SAMPLE_ID_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].genePanelId").value(TEST_GENE_PANEL_ID_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].patientId").value(TEST_PATIENT_ID_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].studyId").value(TEST_STUDY_ID_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].profiled").value(true)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].molecularProfileId") + .value(TEST_MOLECULAR_PROFILE_ID_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].sampleId").value(TEST_SAMPLE_ID_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].genePanelId").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].patientId").value(TEST_PATIENT_ID_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].studyId").value(TEST_STUDY_ID_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].profiled").value(true)); + } + + @Test + @WithMockUser + public void fetchGenePanelData() throws Exception { + + List genePanelDataList = createExampleGenePanelData(); + + Mockito.when(genePanelService.fetchGenePanelDataInMultipleMolecularProfiles(Mockito.anyList())) + .thenReturn(genePanelDataList); + + List sampleMolecularIdentifiers = new ArrayList<>(); + SampleMolecularIdentifier sampleMolecularIdentifier1 = new SampleMolecularIdentifier(); + sampleMolecularIdentifier1.setMolecularProfileId(TEST_MOLECULAR_PROFILE_ID_1); + sampleMolecularIdentifier1.setSampleId(TEST_SAMPLE_ID_1); + sampleMolecularIdentifiers.add(sampleMolecularIdentifier1); + SampleMolecularIdentifier sampleMolecularIdentifier2 = new SampleMolecularIdentifier(); + sampleMolecularIdentifier2.setMolecularProfileId(TEST_MOLECULAR_PROFILE_ID_2); + sampleMolecularIdentifier2.setSampleId(TEST_SAMPLE_ID_2); + sampleMolecularIdentifiers.add(sampleMolecularIdentifier2); + GenePanelDataMultipleStudyFilter genePanelDataMultipleStudyFilter = + new GenePanelDataMultipleStudyFilter(); + genePanelDataMultipleStudyFilter.setSampleMolecularIdentifiers(sampleMolecularIdentifiers); + + mockMvc + .perform( + MockMvcRequestBuilders.post("/api/gene-panel-data/fetch") + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(genePanelDataMultipleStudyFilter))) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect( + MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.jsonPath("$", Matchers.hasSize(2))) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].molecularProfileId") + .value(TEST_MOLECULAR_PROFILE_ID_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].sampleId").value(TEST_SAMPLE_ID_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].genePanelId").value(TEST_GENE_PANEL_ID_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].patientId").value(TEST_PATIENT_ID_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].studyId").value(TEST_STUDY_ID_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].profiled").value(true)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].molecularProfileId") + .value(TEST_MOLECULAR_PROFILE_ID_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].sampleId").value(TEST_SAMPLE_ID_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].genePanelId").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].patientId").value(TEST_PATIENT_ID_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].studyId").value(TEST_STUDY_ID_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].profiled").value(true)); + } + + private List createExampleGenePanelData() { + + List genePanelDataList = new ArrayList<>(); + GenePanelData genePanelData1 = new GenePanelData(); + genePanelData1.setGenePanelId(TEST_GENE_PANEL_ID_1); + genePanelData1.setSampleId(TEST_SAMPLE_ID_1); + genePanelData1.setMolecularProfileId(TEST_MOLECULAR_PROFILE_ID_1); + genePanelData1.setPatientId(TEST_PATIENT_ID_1); + genePanelData1.setStudyId(TEST_STUDY_ID_1); + genePanelData1.setProfiled(true); + genePanelDataList.add(genePanelData1); + GenePanelData genePanelData2 = new GenePanelData(); + genePanelData2.setSampleId(TEST_SAMPLE_ID_2); + genePanelData2.setMolecularProfileId(TEST_MOLECULAR_PROFILE_ID_2); + genePanelData2.setPatientId(TEST_PATIENT_ID_2); + genePanelData2.setStudyId(TEST_STUDY_ID_2); + genePanelData2.setProfiled(true); + genePanelDataList.add(genePanelData2); + return genePanelDataList; + } +} diff --git a/src/test/java/org/cbioportal/legacy/web/GenericAssayControllerTest.java b/src/test/java/org/cbioportal/legacy/web/GenericAssayControllerTest.java new file mode 100644 index 00000000000..88e30839df4 --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/web/GenericAssayControllerTest.java @@ -0,0 +1,204 @@ +package org.cbioportal.legacy.web; + +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; + +import com.fasterxml.jackson.databind.ObjectMapper; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import org.cbioportal.legacy.model.meta.GenericAssayMeta; +import org.cbioportal.legacy.service.GenericAssayService; +import org.cbioportal.legacy.web.config.TestConfig; +import org.cbioportal.legacy.web.parameter.GenericAssayMetaFilter; +import org.hamcrest.Matchers; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mockito; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; +import org.springframework.security.test.context.support.WithMockUser; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.result.MockMvcResultMatchers; + +@RunWith(SpringJUnit4ClassRunner.class) +@WebMvcTest +@ContextConfiguration(classes = {GenericAssayController.class, TestConfig.class}) +public class GenericAssayControllerTest { + + private static final String PROF_ID = "test_prof_id"; + private static final String ENTITY_TYPE = "test_type"; + public static final String GENERIC_ASSAY_STABLE_ID_1 = "genericAssayStableId1"; + public static final String GENERIC_ASSAY_STABLE_ID_2 = "genericAssayStableId2"; + public static final String GENERIC_ASSAY_STABLE_ID_3 = "genericAssayStableId3"; + public static final String GENERIC_ASSAY_STABLE_ID_4 = "genericAssayStableId4"; + private static final String SAMPLE_ID = "test_sample_stable_id_1"; + private static final String VALUE_1 = "0.25"; + private static final String VALUE_2 = "-0.75"; + private static final String VALUE_3 = ""; + private static final String VALUE_4 = "NA"; + private static final String TEST_NAME = "name"; + private static final String TEST_NAME_VALUE = "test_name"; + private static final String TEST_DESCRIPTION = "description"; + private static final String TEST_DESCRIPTION_VALUE = "test_description"; + private static final HashMap GENERIC_ENTITY_META_PROPERTIES = + new HashMap() { + { + put(TEST_NAME, TEST_NAME_VALUE); + put(TEST_DESCRIPTION, TEST_DESCRIPTION_VALUE); + } + }; + + @MockBean private GenericAssayService genericAssayService; + + @Autowired private MockMvc mockMvc; + + private ObjectMapper objectMapper = new ObjectMapper(); + + @Test + @WithMockUser + public void testGenericAssayMetaGetMolecularProfileId() throws Exception { + List genericAssayMetaItems = createGenericAssayMetaItemsList(); + + Mockito.when( + genericAssayService.getGenericAssayMetaByStableIdsAndMolecularIds( + Mockito.any(), Mockito.any(), Mockito.any())) + .thenReturn(genericAssayMetaItems); + + mockMvc + .perform( + MockMvcRequestBuilders.get("/api/generic-assay-meta/" + PROF_ID) + .accept(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect( + MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.jsonPath("$", Matchers.hasSize(2))) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].entityType").value(ENTITY_TYPE)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].stableId").value(GENERIC_ASSAY_STABLE_ID_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].entityType").value(ENTITY_TYPE)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].stableId").value(GENERIC_ASSAY_STABLE_ID_2)) + .andExpect( + MockMvcResultMatchers.jsonPath( + "$[1].genericEntityMetaProperties", Matchers.hasKey(TEST_NAME))) + .andExpect( + MockMvcResultMatchers.jsonPath( + "$[1].genericEntityMetaProperties", Matchers.hasValue(TEST_NAME_VALUE))) + .andExpect( + MockMvcResultMatchers.jsonPath( + "$[1].genericEntityMetaProperties", Matchers.hasKey(TEST_DESCRIPTION))) + .andExpect( + MockMvcResultMatchers.jsonPath( + "$[1].genericEntityMetaProperties", Matchers.hasValue(TEST_DESCRIPTION_VALUE))); + } + + @Test + @WithMockUser + public void testGenericAssayMetaGetGenericAssayStableId() throws Exception { + List genericAssayMetaSingleItem = createGenericAssayMetaSingleItem(); + + Mockito.when( + genericAssayService.getGenericAssayMetaByStableIdsAndMolecularIds( + Mockito.any(), Mockito.any(), Mockito.any())) + .thenReturn(genericAssayMetaSingleItem); + + mockMvc + .perform( + MockMvcRequestBuilders.get( + "/api/generic-assay-meta/generic-assay/" + GENERIC_ASSAY_STABLE_ID_2) + .accept(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect( + MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.jsonPath("$", Matchers.hasSize(1))) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].entityType").value(ENTITY_TYPE)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].stableId").value(GENERIC_ASSAY_STABLE_ID_2)) + .andExpect( + MockMvcResultMatchers.jsonPath( + "$[0].genericEntityMetaProperties", Matchers.hasKey(TEST_NAME))) + .andExpect( + MockMvcResultMatchers.jsonPath( + "$[0].genericEntityMetaProperties", Matchers.hasValue(TEST_NAME_VALUE))) + .andExpect( + MockMvcResultMatchers.jsonPath( + "$[0].genericEntityMetaProperties", Matchers.hasKey(TEST_DESCRIPTION))) + .andExpect( + MockMvcResultMatchers.jsonPath( + "$[0].genericEntityMetaProperties", Matchers.hasValue(TEST_DESCRIPTION_VALUE))); + } + + @Test + @WithMockUser + public void testGenericAssayMetaFetch() throws Exception { + List genericAssayMetaItems = createGenericAssayMetaItemsList(); + List genericAssayStableIds = + Arrays.asList(GENERIC_ASSAY_STABLE_ID_1, GENERIC_ASSAY_STABLE_ID_2); + GenericAssayMetaFilter genericAssayMetaFilter = new GenericAssayMetaFilter(); + genericAssayMetaFilter.setGenericAssayStableIds(genericAssayStableIds); + + Mockito.when( + genericAssayService.getGenericAssayMetaByStableIdsAndMolecularIds( + Mockito.any(), Mockito.any(), Mockito.any())) + .thenReturn(genericAssayMetaItems); + + mockMvc + .perform( + MockMvcRequestBuilders.post("/api/generic_assay_meta/fetch") + .with(csrf()) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(genericAssayMetaFilter))) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect( + MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.jsonPath("$", Matchers.hasSize(2))) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].entityType").value(ENTITY_TYPE)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].stableId").value(GENERIC_ASSAY_STABLE_ID_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].entityType").value(ENTITY_TYPE)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].stableId").value(GENERIC_ASSAY_STABLE_ID_2)) + .andExpect( + MockMvcResultMatchers.jsonPath( + "$[1].genericEntityMetaProperties", Matchers.hasKey(TEST_NAME))) + .andExpect( + MockMvcResultMatchers.jsonPath( + "$[1].genericEntityMetaProperties", Matchers.hasValue(TEST_NAME_VALUE))) + .andExpect( + MockMvcResultMatchers.jsonPath( + "$[1].genericEntityMetaProperties", Matchers.hasKey(TEST_DESCRIPTION))) + .andExpect( + MockMvcResultMatchers.jsonPath( + "$[1].genericEntityMetaProperties", Matchers.hasValue(TEST_DESCRIPTION_VALUE))); + } + + private List createGenericAssayMetaSingleItem() { + + List genericAssayMetaItems = new ArrayList<>(); + + GenericAssayMeta item2 = + new GenericAssayMeta( + ENTITY_TYPE, GENERIC_ASSAY_STABLE_ID_2, GENERIC_ENTITY_META_PROPERTIES); + genericAssayMetaItems.add(item2); + + return genericAssayMetaItems; + } + + private List createGenericAssayMetaItemsList() { + + List genericAssayMetaItems = new ArrayList<>(); + + GenericAssayMeta item1 = new GenericAssayMeta(ENTITY_TYPE, GENERIC_ASSAY_STABLE_ID_1); + genericAssayMetaItems.add(item1); + + GenericAssayMeta item2 = + new GenericAssayMeta( + ENTITY_TYPE, GENERIC_ASSAY_STABLE_ID_2, GENERIC_ENTITY_META_PROPERTIES); + genericAssayMetaItems.add(item2); + + return genericAssayMetaItems; + } +} diff --git a/src/test/java/org/cbioportal/legacy/web/GenericAssayDataControllerTest.java b/src/test/java/org/cbioportal/legacy/web/GenericAssayDataControllerTest.java new file mode 100644 index 00000000000..f36875b6bf4 --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/web/GenericAssayDataControllerTest.java @@ -0,0 +1,241 @@ +package org.cbioportal.legacy.web; + +import com.fasterxml.jackson.databind.ObjectMapper; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import org.cbioportal.legacy.model.GenericAssayData; +import org.cbioportal.legacy.service.GenericAssayService; +import org.cbioportal.legacy.web.config.TestConfig; +import org.cbioportal.legacy.web.parameter.GenericAssayDataMultipleStudyFilter; +import org.cbioportal.legacy.web.parameter.GenericAssayFilter; +import org.cbioportal.legacy.web.parameter.SampleMolecularIdentifier; +import org.hamcrest.Matchers; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mockito; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.result.MockMvcResultMatchers; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import org.springframework.web.context.WebApplicationContext; + +@RunWith(SpringJUnit4ClassRunner.class) +@WebMvcTest +@ContextConfiguration(classes = {GenericAssayDataController.class, TestConfig.class}) +public class GenericAssayDataControllerTest { + + private static final String PROF_ID = "test_prof_id"; + private static final String ENTITY_TYPE = "test_type"; + public static final String GENERIC_ASSAY_STABLE_ID_1 = "genericAssayStableId1"; + public static final String GENERIC_ASSAY_STABLE_ID_2 = "genericAssayStableId2"; + public static final String GENERIC_ASSAY_STABLE_ID_3 = "genericAssayStableId3"; + public static final String GENERIC_ASSAY_STABLE_ID_4 = "genericAssayStableId4"; + private static final String SAMPLE_ID = "test_sample_stable_id_1"; + private static final String VALUE_1 = "0.25"; + private static final String VALUE_2 = "-0.75"; + private static final String VALUE_3 = ""; + private static final String VALUE_4 = "NA"; + private static final String TEST_NAME = "name"; + private static final String TEST_NAME_VALUE = "test_name"; + private static final String TEST_DESCRIPTION = "description"; + private static final String TEST_DESCRIPTION_VALUE = "test_description"; + private static final HashMap GENERIC_ENTITY_META_PROPERTIES = + new HashMap() { + { + put(TEST_NAME, TEST_NAME_VALUE); + put(TEST_DESCRIPTION, TEST_DESCRIPTION_VALUE); + } + }; + + @Autowired private WebApplicationContext wac; + + @MockBean private GenericAssayService genericAssayService; + @Autowired private MockMvc mockMvc; + + private ObjectMapper objectMapper = new ObjectMapper(); + + @Before + public void setUp() throws Exception { + + Mockito.reset(genericAssayService); + mockMvc = MockMvcBuilders.webAppContextSetup(wac).build(); + } + + @Test + public void testGenericAssayDataFetch() throws Exception { + List genericAssayDataItems = createGenericAssayDataItemsList(); + Mockito.when( + genericAssayService.fetchGenericAssayData( + Mockito.anyString(), Mockito.anyList(), Mockito.anyList(), Mockito.anyString())) + .thenReturn(genericAssayDataItems); + + GenericAssayFilter genericAssayDataFilter = new GenericAssayFilter(); + genericAssayDataFilter.setSampleIds(Arrays.asList(SAMPLE_ID)); + genericAssayDataFilter.setGenericAssayStableIds( + Arrays.asList( + GENERIC_ASSAY_STABLE_ID_1, + GENERIC_ASSAY_STABLE_ID_2, + GENERIC_ASSAY_STABLE_ID_3, + GENERIC_ASSAY_STABLE_ID_4)); + + mockMvc + .perform( + MockMvcRequestBuilders.post("/api/generic_assay_data/" + PROF_ID + "/fetch") + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(genericAssayDataFilter))) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect( + MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.jsonPath("$", Matchers.hasSize(2))) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].molecularProfileId").value(PROF_ID)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].genericAssayStableId") + .value(GENERIC_ASSAY_STABLE_ID_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].sampleId").value(SAMPLE_ID)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].value").value(VALUE_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].molecularProfileId").value(PROF_ID)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].genericAssayStableId") + .value(GENERIC_ASSAY_STABLE_ID_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].sampleId").value(SAMPLE_ID)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].value").value(VALUE_2)); + } + + @Test + public void testGenericAssayDataFetchInMultipleMolecularProfiles() throws Exception { + List genericAssayDataItems = createGenericAssayDataItemsList(); + GenericAssayDataMultipleStudyFilter genericAssayDataMultipleStudyFilter = + new GenericAssayDataMultipleStudyFilter(); + genericAssayDataMultipleStudyFilter.setSampleMolecularIdentifiers( + createSampleMolecularIdentifiers()); + + Mockito.when( + genericAssayService.fetchGenericAssayData( + Mockito.anyList(), Mockito.any(), Mockito.any(), Mockito.any())) + .thenReturn(genericAssayDataItems); + + mockMvc + .perform( + MockMvcRequestBuilders.post("/api/generic_assay_data/fetch") + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(genericAssayDataMultipleStudyFilter))) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect( + MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.jsonPath("$", Matchers.hasSize(2))) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].molecularProfileId").value(PROF_ID)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].genericAssayStableId") + .value(GENERIC_ASSAY_STABLE_ID_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].sampleId").value(SAMPLE_ID)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].value").value(VALUE_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].molecularProfileId").value(PROF_ID)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].genericAssayStableId") + .value(GENERIC_ASSAY_STABLE_ID_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].sampleId").value(SAMPLE_ID)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].value").value(VALUE_2)); + } + + public void testGenericAssayDataGet() throws Exception { + List genericAssayDataItems = createGenericAssayDataItemsList(); + Mockito.when( + genericAssayService.fetchGenericAssayData( + Mockito.anyString(), Mockito.anyList(), Mockito.anyList(), Mockito.anyString())) + .thenReturn(genericAssayDataItems); + + mockMvc + .perform( + MockMvcRequestBuilders.get( + "/api/generic-assay-data/" + + PROF_ID + + "/generic-assay/" + + GENERIC_ASSAY_STABLE_ID_1) + .accept(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect( + MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.jsonPath("$", Matchers.hasSize(2))) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].molecularProfileId").value(PROF_ID)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].genericAssayStableId") + .value(GENERIC_ASSAY_STABLE_ID_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].sampleId").value(SAMPLE_ID)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].value").value(VALUE_1)); + } + + private List createGenericAssayDataItemsList() { + + List genericAssayDataItems = new ArrayList<>(); + + GenericAssayData item1 = new GenericAssayData(); + item1.setGenericAssayStableId(GENERIC_ASSAY_STABLE_ID_1); + item1.setMolecularProfileId(PROF_ID); + item1.setSampleId(SAMPLE_ID); + item1.setValue(VALUE_1); + genericAssayDataItems.add(item1); + + GenericAssayData item2 = new GenericAssayData(); + item2.setGenericAssayStableId(GENERIC_ASSAY_STABLE_ID_2); + item2.setMolecularProfileId(PROF_ID); + item2.setSampleId(SAMPLE_ID); + item2.setValue(VALUE_2); + genericAssayDataItems.add(item2); + + // This item should be filtered out in api result + GenericAssayData item3 = new GenericAssayData(); + item3.setGenericAssayStableId(GENERIC_ASSAY_STABLE_ID_3); + item3.setMolecularProfileId(PROF_ID); + item3.setSampleId(SAMPLE_ID); + item3.setValue(VALUE_3); + genericAssayDataItems.add(item3); + + // This item should be filtered out in api result + GenericAssayData item4 = new GenericAssayData(); + item4.setGenericAssayStableId(GENERIC_ASSAY_STABLE_ID_4); + item4.setMolecularProfileId(PROF_ID); + item4.setSampleId(SAMPLE_ID); + item4.setValue(VALUE_4); + genericAssayDataItems.add(item4); + + return genericAssayDataItems; + } + + private List createSampleMolecularIdentifiers() { + + List sampleMolecularIdentifiers = new ArrayList<>(); + + SampleMolecularIdentifier identifier1 = new SampleMolecularIdentifier(); + identifier1.setSampleId(SAMPLE_ID); + identifier1.setMolecularProfileId(GENERIC_ASSAY_STABLE_ID_1); + sampleMolecularIdentifiers.add(identifier1); + + SampleMolecularIdentifier identifier2 = new SampleMolecularIdentifier(); + identifier2.setSampleId(SAMPLE_ID); + identifier2.setMolecularProfileId(GENERIC_ASSAY_STABLE_ID_2); + sampleMolecularIdentifiers.add(identifier2); + + SampleMolecularIdentifier identifier3 = new SampleMolecularIdentifier(); + identifier3.setSampleId(SAMPLE_ID); + identifier3.setMolecularProfileId(GENERIC_ASSAY_STABLE_ID_3); + sampleMolecularIdentifiers.add(identifier3); + + SampleMolecularIdentifier identifier4 = new SampleMolecularIdentifier(); + identifier4.setSampleId(SAMPLE_ID); + identifier4.setMolecularProfileId(GENERIC_ASSAY_STABLE_ID_4); + sampleMolecularIdentifiers.add(identifier4); + + return sampleMolecularIdentifiers; + } +} diff --git a/src/test/java/org/cbioportal/legacy/web/GenesetControllerTest.java b/src/test/java/org/cbioportal/legacy/web/GenesetControllerTest.java new file mode 100644 index 00000000000..e2415d86844 --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/web/GenesetControllerTest.java @@ -0,0 +1,110 @@ +package org.cbioportal.legacy.web; + +import java.util.ArrayList; +import java.util.List; +import org.cbioportal.legacy.model.Geneset; +import org.cbioportal.legacy.service.GenesetService; +import org.cbioportal.legacy.web.config.TestConfig; +import org.hamcrest.Matchers; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mockito; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; +import org.springframework.security.test.context.support.WithMockUser; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.result.MockMvcResultMatchers; + +@RunWith(SpringJUnit4ClassRunner.class) +@WebMvcTest +@ContextConfiguration(classes = {GenesetController.class, TestConfig.class}) +public class GenesetControllerTest { + + public static final String GENESET_ID_1 = "geneset_id_1"; + private static final Integer INTERNAL_ID_1 = 1; + private static final String DESCRIPTION_1 = "description 1"; + private static final String REF_LINK_1 = "http://link1"; + public static final String GENESET_ID_2 = "geneset_id_2"; + private static final Integer INTERNAL_ID_2 = 2; + private static final String DESCRIPTION_2 = "description 2"; + private static final String REF_LINK_2 = "http://link2"; + + @MockBean private GenesetService genesetService; + + @Autowired private MockMvc mockMvc; + + @Test + @WithMockUser + public void getAllGenesets() throws Exception { + + List genesetList = createGenesetList(); + Mockito.when( + genesetService.getAllGenesets(Mockito.anyString(), Mockito.anyInt(), Mockito.anyInt())) + .thenReturn(genesetList); + + mockMvc + .perform(MockMvcRequestBuilders.get("/api/genesets").accept(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect( + MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.jsonPath("$", Matchers.hasSize(2))) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].internalId").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].representativeScore").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].genesetId").value(GENESET_ID_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].name").value(GENESET_ID_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].description").value(DESCRIPTION_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].refLink").value(REF_LINK_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].internalId").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].representativeScore").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].genesetId").value(GENESET_ID_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].name").value(GENESET_ID_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].description").value(DESCRIPTION_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].refLink").value(REF_LINK_2)); + } + + @Test + @WithMockUser + public void getGeneset() throws Exception { + + Geneset geneset = createGenesetList().get(0); + Mockito.when(genesetService.getGeneset(Mockito.anyString())).thenReturn(geneset); + + // test /genesets/{genesetId} + mockMvc + .perform( + MockMvcRequestBuilders.get("/api/genesets/test_geneset_id") + .accept(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect( + MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.jsonPath("$.internalId").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$.genesetId").value(GENESET_ID_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$.name").value(GENESET_ID_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$.description").value(DESCRIPTION_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$.refLink").value(REF_LINK_1)); + } + + private List createGenesetList() { + List genesetList = new ArrayList<>(); + Geneset geneset1 = new Geneset(); + geneset1.setInternalId(INTERNAL_ID_1); + geneset1.setGenesetId(GENESET_ID_1); + geneset1.setName(GENESET_ID_1); + geneset1.setDescription(DESCRIPTION_1); + geneset1.setRefLink(REF_LINK_1); + genesetList.add(geneset1); + Geneset geneset2 = new Geneset(); + geneset2.setInternalId(INTERNAL_ID_2); + geneset2.setGenesetId(GENESET_ID_2); + geneset2.setName(GENESET_ID_2); + geneset2.setDescription(DESCRIPTION_2); + geneset2.setRefLink(REF_LINK_2); + genesetList.add(geneset2); + return genesetList; + } +} diff --git a/src/test/java/org/cbioportal/legacy/web/GenesetCorrelationControllerTest.java b/src/test/java/org/cbioportal/legacy/web/GenesetCorrelationControllerTest.java new file mode 100644 index 00000000000..6e131f5a3e2 --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/web/GenesetCorrelationControllerTest.java @@ -0,0 +1,102 @@ +package org.cbioportal.legacy.web; + +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; + +import java.util.ArrayList; +import java.util.List; +import org.cbioportal.legacy.model.GenesetCorrelation; +import org.cbioportal.legacy.service.GenesetCorrelationService; +import org.cbioportal.legacy.web.config.TestConfig; +import org.hamcrest.Matchers; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mockito; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; +import org.springframework.security.test.context.support.WithMockUser; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.result.MockMvcResultMatchers; + +@RunWith(SpringJUnit4ClassRunner.class) +@WebMvcTest +@ContextConfiguration(classes = {GenesetCorrelationController.class, TestConfig.class}) +public class GenesetCorrelationControllerTest { + + private static final String PROF_ID = "test_prof_id"; + private static final String QUERY_GENESET_ID = "test_geneset_Id"; + private static final int ENTREZ_GENE_ID_1 = 1; + private static final String HUGO_GENE_SYMBOL_1 = "Hugo1"; + private static final double CORR_1 = 0.5; + private static final int ENTREZ_GENE_ID_2 = 2; + private static final String HUGO_GENE_SYMBOL_2 = "Hugo2"; + private static final double CORR_2 = -0.7; + private static final String EXPR_PROF_ID = "expr_prof_id1"; + private static final String ZSCORE_PROF_ID = "zscore_prof_id1"; + + @Autowired private MockMvc mockMvc; + + @MockBean public GenesetCorrelationService genesetCorrelationService; + + @Test + @WithMockUser + public void fetchCorrelatedGenes() throws Exception { + + List correlationsForGeneset = createGenesetCorrelationList(); + Mockito.when( + genesetCorrelationService.fetchCorrelatedGenes( + Mockito.anyString(), Mockito.anyString(), Mockito.anyDouble())) + .thenReturn(correlationsForGeneset); + + mockMvc + .perform( + MockMvcRequestBuilders.post( + "/api/genesets/" + QUERY_GENESET_ID + "/expression-correlation/fetch") + .with(csrf()) + .param("geneticProfileId", PROF_ID) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect( + MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.jsonPath("$", Matchers.hasSize(2))) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].entrezGeneId").value(ENTREZ_GENE_ID_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].hugoGeneSymbol").value(HUGO_GENE_SYMBOL_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].correlationValue").value(CORR_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].expressionGeneticProfileId").value(EXPR_PROF_ID)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].zScoreGeneticProfileId").value(ZSCORE_PROF_ID)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].entrezGeneId").value(ENTREZ_GENE_ID_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].hugoGeneSymbol").value(HUGO_GENE_SYMBOL_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].correlationValue").value(CORR_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].expressionGeneticProfileId").value(EXPR_PROF_ID)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].zScoreGeneticProfileId").value(ZSCORE_PROF_ID)); + } + + private List createGenesetCorrelationList() { + + List genesetCorrelationList = new ArrayList<>(); + GenesetCorrelation gsc1 = new GenesetCorrelation(); + gsc1.setEntrezGeneId(ENTREZ_GENE_ID_1); + gsc1.setHugoGeneSymbol(HUGO_GENE_SYMBOL_1); + gsc1.setCorrelationValue(CORR_1); + gsc1.setExpressionMolecularProfileId(EXPR_PROF_ID); + gsc1.setzScoreMolecularProfileId(ZSCORE_PROF_ID); + genesetCorrelationList.add(gsc1); + GenesetCorrelation gsc2 = new GenesetCorrelation(); + gsc2.setEntrezGeneId(ENTREZ_GENE_ID_2); + gsc2.setHugoGeneSymbol(HUGO_GENE_SYMBOL_2); + gsc2.setCorrelationValue(CORR_2); + gsc2.setExpressionMolecularProfileId(EXPR_PROF_ID); + gsc2.setzScoreMolecularProfileId(ZSCORE_PROF_ID); + genesetCorrelationList.add(gsc2); + return genesetCorrelationList; + } +} diff --git a/src/test/java/org/cbioportal/legacy/web/GenesetDataControllerTest.java b/src/test/java/org/cbioportal/legacy/web/GenesetDataControllerTest.java new file mode 100644 index 00000000000..f17c70172fe --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/web/GenesetDataControllerTest.java @@ -0,0 +1,149 @@ +package org.cbioportal.legacy.web; + +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; + +import com.fasterxml.jackson.databind.ObjectMapper; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import org.cbioportal.legacy.model.GenesetMolecularData; +import org.cbioportal.legacy.service.GenesetDataService; +import org.cbioportal.legacy.web.config.TestConfig; +import org.cbioportal.legacy.web.parameter.GenesetDataFilterCriteria; +import org.hamcrest.Matchers; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mockito; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; +import org.springframework.security.test.context.support.WithMockUser; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.result.MockMvcResultMatchers; + +@RunWith(SpringJUnit4ClassRunner.class) +@WebMvcTest +@ContextConfiguration(classes = {GenesetDataController.class, TestConfig.class}) +public class GenesetDataControllerTest { + + private static final String PROF_ID = "test_prof_id"; + private static final String SAMPLE_LIST_ID = "test_sample_list_id"; + public static final String GENESET_ID_1 = "geneset_id_1"; + private static final String SAMPLE_STABLE_ID_1 = "test_sample_stable_id_1"; + private static final String VALUE_1 = "0.845"; + public static final String GENESET_ID_2 = "geneset_id_2"; + private static final String VALUE_2 = "-0.457"; + + @MockBean private GenesetDataService genesetDataService; + + private ObjectMapper objectMapper = new ObjectMapper(); + + @Autowired private MockMvc mockMvc; + + @Test + @WithMockUser + public void fetchGeneticDataItemsWithSampleIds() throws Exception { + List genesetDataItems = createGenesetDataItemsList(); + + String geneticProfileId = PROF_ID; + List sampleIds = Arrays.asList(SAMPLE_STABLE_ID_1); + List genesetIds = Arrays.asList(GENESET_ID_1, GENESET_ID_2); + + Mockito.when(genesetDataService.fetchGenesetData(geneticProfileId, sampleIds, genesetIds)) + .thenReturn(genesetDataItems); + + GenesetDataFilterCriteria genesetDataFilterCriteria = new GenesetDataFilterCriteria(); + genesetDataFilterCriteria.setSampleIds(sampleIds); + genesetDataFilterCriteria.setGenesetIds(genesetIds); + + mockMvc + .perform( + MockMvcRequestBuilders.post( + "/api/genetic-profiles/" + geneticProfileId + "/geneset-genetic-data/fetch") + .with(csrf()) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(genesetDataFilterCriteria))) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect( + MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.jsonPath("$", Matchers.hasSize(2))) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].geneticProfileId").value(geneticProfileId)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].genesetId").value(GENESET_ID_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].sampleId").value(SAMPLE_STABLE_ID_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].value").value(VALUE_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].geneticProfileId").value(geneticProfileId)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].genesetId").value(GENESET_ID_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].sampleId").value(SAMPLE_STABLE_ID_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].value").value(VALUE_2)); + } + + @Test + @WithMockUser + public void fetchGeneticDataItemsWithSampleListId() throws Exception { + List genesetDataItems = createGenesetDataItemsList(); + genesetDataItems.addAll(createGenesetDataItemsList()); + + String geneticProfileId = PROF_ID; + String sampleListId = SAMPLE_LIST_ID; + List genesetIds = Arrays.asList(GENESET_ID_1, GENESET_ID_2); + + Mockito.when(genesetDataService.fetchGenesetData(geneticProfileId, sampleListId, genesetIds)) + .thenReturn(genesetDataItems); + + GenesetDataFilterCriteria genesetDataFilterCriteria = new GenesetDataFilterCriteria(); + genesetDataFilterCriteria.setSampleListId(sampleListId); + genesetDataFilterCriteria.setGenesetIds(genesetIds); + + mockMvc + .perform( + MockMvcRequestBuilders.post( + "/api/genetic-profiles/" + geneticProfileId + "/geneset-genetic-data/fetch") + .with(csrf()) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(genesetDataFilterCriteria))) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect( + MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.jsonPath("$", Matchers.hasSize(4))) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].geneticProfileId").value(geneticProfileId)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].genesetId").value(GENESET_ID_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].sampleId").value(SAMPLE_STABLE_ID_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].value").value(VALUE_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].geneticProfileId").value(geneticProfileId)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].genesetId").value(GENESET_ID_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].sampleId").value(SAMPLE_STABLE_ID_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].value").value(VALUE_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[2].geneticProfileId").value(geneticProfileId)) + .andExpect(MockMvcResultMatchers.jsonPath("$[2].genesetId").value(GENESET_ID_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[2].sampleId").value(SAMPLE_STABLE_ID_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[2].value").value(VALUE_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[3].geneticProfileId").value(geneticProfileId)) + .andExpect(MockMvcResultMatchers.jsonPath("$[3].genesetId").value(GENESET_ID_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[3].sampleId").value(SAMPLE_STABLE_ID_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[3].value").value(VALUE_2)); + } + + private List createGenesetDataItemsList() { + + List genesetDataItems = new ArrayList<>(); + GenesetMolecularData gsItem1 = new GenesetMolecularData(); + gsItem1.setGenesetId(GENESET_ID_1); + gsItem1.setMolecularProfileId(PROF_ID); + gsItem1.setSampleId(SAMPLE_STABLE_ID_1); + gsItem1.setValue(VALUE_1); + genesetDataItems.add(gsItem1); + GenesetMolecularData gsItem2 = new GenesetMolecularData(); + gsItem2.setGenesetId(GENESET_ID_2); + gsItem2.setMolecularProfileId(PROF_ID); + gsItem2.setSampleId(SAMPLE_STABLE_ID_1); + gsItem2.setValue(VALUE_2); + genesetDataItems.add(gsItem2); + return genesetDataItems; + } +} diff --git a/src/test/java/org/cbioportal/legacy/web/GenesetHierarchyControllerTest.java b/src/test/java/org/cbioportal/legacy/web/GenesetHierarchyControllerTest.java new file mode 100644 index 00000000000..5b7a0880ea1 --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/web/GenesetHierarchyControllerTest.java @@ -0,0 +1,145 @@ +package org.cbioportal.legacy.web; + +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import org.cbioportal.legacy.model.Geneset; +import org.cbioportal.legacy.model.GenesetHierarchyInfo; +import org.cbioportal.legacy.service.GenesetHierarchyService; +import org.cbioportal.legacy.web.config.TestConfig; +import org.hamcrest.Matchers; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mockito; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; +import org.springframework.security.test.context.support.WithMockUser; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.result.MockMvcResultMatchers; + +@RunWith(SpringJUnit4ClassRunner.class) +@WebMvcTest +@ContextConfiguration(classes = {GenesetHierarchyController.class, TestConfig.class}) +public class GenesetHierarchyControllerTest { + + private static final String PROF_ID = "test_prof_id"; + public static final String GENESET_ID1 = "geneset_id1"; + public static final String GENESET_ID2 = "geneset_id2"; + + @MockBean private GenesetHierarchyService genesetHierarchyService; + + @Autowired private MockMvc mockMvc; + + @Test + @WithMockUser + public void fetchGenesetHierarchyInfo() throws Exception { + List genesetHierarchyInfoList = createGenesetHierarchyInfoList(); + Mockito.when( + genesetHierarchyService.fetchGenesetHierarchyInfo( + Mockito.anyString(), Mockito.anyInt(), Mockito.anyDouble(), Mockito.anyDouble())) + .thenReturn(genesetHierarchyInfoList); + + mockMvc + .perform( + MockMvcRequestBuilders.post("/api/geneset-hierarchy/fetch") + .with(csrf()) + .param("geneticProfileId", PROF_ID) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect( + MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.jsonPath("$", Matchers.hasSize(4))) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].nodeId").value(1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].nodeName").value("Root node")) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].parentNodeName").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].nodeId").value(2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].nodeName").value("sub node A")) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].parentNodeName").value("Root node")) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].genesets").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$[2].nodeId").value(4)) + .andExpect(MockMvcResultMatchers.jsonPath("$[2].nodeName").value("parent node 1")) + .andExpect(MockMvcResultMatchers.jsonPath("$[2].parentNodeName").value("sub node A")) + .andExpect(MockMvcResultMatchers.jsonPath("$[2].genesets", Matchers.hasSize(2))) + .andExpect(MockMvcResultMatchers.jsonPath("$[2].genesets[0].internalId").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$[2].genesets[0].genesetId").value(GENESET_ID1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[2].genesets[0].representativeScore").value(0.1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[2].genesets[0].representativePvalue").value(0.054)) + .andExpect(MockMvcResultMatchers.jsonPath("$[2].genesets[1].internalId").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$[2].genesets[1].genesetId").value(GENESET_ID2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[2].genesets[1].representativeScore").value(0.8)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[2].genesets[1].representativePvalue").value(0.04)) + .andExpect(MockMvcResultMatchers.jsonPath("$[3].nodeId").value(5)) + .andExpect(MockMvcResultMatchers.jsonPath("$[3].nodeName").value("parent node 2")) + .andExpect(MockMvcResultMatchers.jsonPath("$[3].parentNodeName").value("sub node A")) + .andExpect(MockMvcResultMatchers.jsonPath("$[3].genesets", Matchers.hasSize(1))) + .andExpect(MockMvcResultMatchers.jsonPath("$[3].genesets[0].internalId").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$[3].genesets[0].genesetId").value(GENESET_ID2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[3].genesets[0].representativeScore").value(0.8)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[3].genesets[0].representativePvalue").value(0.04)); + } + + private List createGenesetHierarchyInfoList() { + + List genesetHierarchyInfoList = new ArrayList<>(); + + // hierarchy nodes, parents and genesets: + List hierarchySuperNodes = new ArrayList(); + GenesetHierarchyInfo node1 = new GenesetHierarchyInfo(); + node1.setNodeId(1); + node1.setNodeName("Root node"); + hierarchySuperNodes.add(node1); + GenesetHierarchyInfo node2 = new GenesetHierarchyInfo(); + node2.setNodeId(2); + node2.setNodeName("sub node A"); + node2.setParentId(1); + node2.setParentNodeName(node1.getNodeName()); + hierarchySuperNodes.add(node2); + + Geneset geneset1 = new Geneset(); + geneset1.setGenesetId(GENESET_ID1); + geneset1.setDescription(GENESET_ID1); + geneset1.setName(GENESET_ID1); + geneset1.setRepresentativeScore(0.1); + geneset1.setRepresentativePvalue(0.054); + Geneset geneset2 = new Geneset(); + geneset2.setGenesetId(GENESET_ID2); + geneset2.setDescription(GENESET_ID2); + geneset2.setName(GENESET_ID2); + geneset2.setRepresentativeScore(0.8); + geneset2.setRepresentativePvalue(0.04); + + List hierarchyParents = new ArrayList(); + GenesetHierarchyInfo parentNode1 = new GenesetHierarchyInfo(); + parentNode1.setNodeId(4); + parentNode1.setNodeName("parent node 1"); + parentNode1.setParentId(2); + parentNode1.setParentNodeName(node2.getNodeName()); + parentNode1.setGenesets(Arrays.asList(geneset1, geneset2)); + hierarchyParents.add(parentNode1); + GenesetHierarchyInfo parentNode2 = new GenesetHierarchyInfo(); + parentNode2.setNodeId(5); + parentNode2.setNodeName("parent node 2"); + parentNode2.setParentId(2); + parentNode2.setParentNodeName(node2.getNodeName()); + parentNode2.setGenesets(Arrays.asList(geneset2)); + hierarchyParents.add(parentNode2); + + genesetHierarchyInfoList.addAll(hierarchySuperNodes); + genesetHierarchyInfoList.addAll(hierarchyParents); + return genesetHierarchyInfoList; + } +} diff --git a/src/test/java/org/cbioportal/legacy/web/InfoControllerTest.java b/src/test/java/org/cbioportal/legacy/web/InfoControllerTest.java new file mode 100644 index 00000000000..a25b6497ffc --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/web/InfoControllerTest.java @@ -0,0 +1,44 @@ +package org.cbioportal.legacy.web; + +import org.cbioportal.legacy.web.config.TestConfig; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.http.MediaType; +import org.springframework.security.test.context.support.WithMockUser; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.result.MockMvcResultMatchers; + +@RunWith(SpringJUnit4ClassRunner.class) +@WebMvcTest +@ContextConfiguration(classes = {InfoController.class, TestConfig.class}) +@TestPropertySource( + properties = { + "portal.version=test_portal_version", + "db.version=test_db_version", + "derived_table.version=test_derived_table_version" + }) +public class InfoControllerTest { + + @Autowired private MockMvc mockMvc; + + @Test + @WithMockUser + public void getInfo() throws Exception { + mockMvc + .perform(MockMvcRequestBuilders.get("/api/info").accept(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect( + MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.jsonPath("$.portalVersion").value("test_portal_version")) + .andExpect(MockMvcResultMatchers.jsonPath("$.dbVersion").value("test_db_version")) + .andExpect( + MockMvcResultMatchers.jsonPath("$.derivedTableVersion") + .value("test_derived_table_version")); + } +} diff --git a/src/test/java/org/cbioportal/legacy/web/MolecularDataControllerTest.java b/src/test/java/org/cbioportal/legacy/web/MolecularDataControllerTest.java new file mode 100644 index 00000000000..d8b349401e0 --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/web/MolecularDataControllerTest.java @@ -0,0 +1,265 @@ +package org.cbioportal.legacy.web; + +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; + +import com.fasterxml.jackson.databind.ObjectMapper; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import org.cbioportal.legacy.model.GeneMolecularData; +import org.cbioportal.legacy.service.MolecularDataService; +import org.cbioportal.legacy.web.config.TestConfig; +import org.cbioportal.legacy.web.parameter.HeaderKeyConstants; +import org.cbioportal.legacy.web.parameter.MolecularDataFilter; +import org.cbioportal.legacy.web.parameter.MolecularDataMultipleStudyFilter; +import org.hamcrest.Matchers; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mockito; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; +import org.springframework.security.test.context.support.WithMockUser; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.result.MockMvcResultMatchers; + +@RunWith(SpringJUnit4ClassRunner.class) +@WebMvcTest +@ContextConfiguration(classes = {MolecularDataController.class, TestConfig.class}) +public class MolecularDataControllerTest { + + private static final String TEST_MOLECULAR_PROFILE_STABLE_ID_1 = + "test_molecular_profile_stable_id_1"; + private static final String TEST_SAMPLE_STABLE_ID_1 = "test_sample_stable_id_1"; + private static final int TEST_ENTREZ_GENE_ID_1 = 1; + private static final String TEST_VALUE_1 = "2.3"; + private static final String TEST_MOLECULAR_PROFILE_STABLE_ID_2 = + "test_molecular_profile_stable_id_2"; + private static final String TEST_SAMPLE_STABLE_ID_2 = "test_sample_stable_id_2"; + private static final int TEST_ENTREZ_GENE_ID_2 = 2; + private static final String TEST_VALUE_2 = "2.4"; + private static final String TEST_SAMPLE_LIST_ID = "test_sample_list_id"; + + @MockBean private MolecularDataService molecularDataService; + + private ObjectMapper objectMapper = new ObjectMapper(); + + @Autowired private MockMvc mockMvc; + + @Test + @WithMockUser + public void getAllMolecularDataInMolecularProfileSummaryProjection() throws Exception { + + List geneMolecularDataList = createExampleMolecularData(); + + Mockito.when( + molecularDataService.getMolecularData( + Mockito.anyString(), Mockito.anyString(), Mockito.anyList(), Mockito.anyString())) + .thenReturn(geneMolecularDataList); + + mockMvc + .perform( + MockMvcRequestBuilders.get( + "/api/molecular-profiles/test_molecular_profile_id/molecular-data") + .param("sampleListId", TEST_SAMPLE_LIST_ID) + .param("entrezGeneId", "1") + .accept(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect( + MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.jsonPath("$", Matchers.hasSize(2))) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].molecularProfileId") + .value(TEST_MOLECULAR_PROFILE_STABLE_ID_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].sampleId").value(TEST_SAMPLE_STABLE_ID_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].entrezGeneId").value(TEST_ENTREZ_GENE_ID_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].value").value(2.3)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].gene").doesNotExist()) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].molecularProfileId") + .value(TEST_MOLECULAR_PROFILE_STABLE_ID_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].sampleId").value(TEST_SAMPLE_STABLE_ID_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].entrezGeneId").value(TEST_ENTREZ_GENE_ID_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].value").value(2.4)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].gene").doesNotExist()); + } + + @Test + @WithMockUser + public void getAllMolecularDataInMolecularProfileMetaProjection() throws Exception { + + List geneMolecularDataList = createExampleMolecularData(); + GeneMolecularData geneMolecularData1 = new GeneMolecularData(); + geneMolecularDataList.add(geneMolecularData1); + GeneMolecularData geneMolecularData2 = new GeneMolecularData(); + geneMolecularDataList.add(geneMolecularData2); + + Mockito.when( + molecularDataService.getMolecularData( + Mockito.anyString(), Mockito.anyString(), Mockito.anyList(), Mockito.anyString())) + .thenReturn(geneMolecularDataList); + + mockMvc + .perform( + MockMvcRequestBuilders.get( + "/api/molecular-profiles/test_molecular_profile_id/molecular-data") + .param("sampleListId", TEST_SAMPLE_LIST_ID) + .param("entrezGeneId", "1") + .param("projection", "META")) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect(MockMvcResultMatchers.header().string(HeaderKeyConstants.TOTAL_COUNT, "2")); + } + + @Test + @WithMockUser + public void fetchAllMolecularDataInMolecularProfileSummaryProjection() throws Exception { + + List geneMolecularDataList = createExampleMolecularData(); + + Mockito.when( + molecularDataService.fetchMolecularData( + Mockito.anyString(), Mockito.anyList(), Mockito.anyList(), Mockito.anyString())) + .thenReturn(geneMolecularDataList); + + MolecularDataFilter molecularDataFilter = createMolecularDataFilter(); + + mockMvc + .perform( + MockMvcRequestBuilders.post( + "/api/molecular-profiles/test_molecular_profile_id/molecular-data/fetch") + .with(csrf()) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(molecularDataFilter))) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect( + MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.jsonPath("$", Matchers.hasSize(2))) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].molecularProfileId") + .value(TEST_MOLECULAR_PROFILE_STABLE_ID_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].sampleId").value(TEST_SAMPLE_STABLE_ID_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].entrezGeneId").value(TEST_ENTREZ_GENE_ID_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].value").value(2.3)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].gene").doesNotExist()) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].molecularProfileId") + .value(TEST_MOLECULAR_PROFILE_STABLE_ID_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].sampleId").value(TEST_SAMPLE_STABLE_ID_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].entrezGeneId").value(TEST_ENTREZ_GENE_ID_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].value").value(2.4)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].gene").doesNotExist()); + } + + @Test + @WithMockUser + public void fetchAllMolecularDataInMolecularProfileMetaProjection() throws Exception { + + List geneMolecularDataList = createExampleMolecularData(); + GeneMolecularData geneMolecularData1 = new GeneMolecularData(); + geneMolecularDataList.add(geneMolecularData1); + GeneMolecularData geneMolecularData2 = new GeneMolecularData(); + geneMolecularDataList.add(geneMolecularData2); + + Mockito.when( + molecularDataService.fetchMolecularData( + Mockito.anyString(), Mockito.anyList(), Mockito.anyList(), Mockito.anyString())) + .thenReturn(geneMolecularDataList); + + MolecularDataFilter molecularDataFilter = createMolecularDataFilter(); + + mockMvc + .perform( + MockMvcRequestBuilders.post( + "/api/molecular-profiles/test_molecular_profile_id/molecular-data/fetch") + .with(csrf()) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(molecularDataFilter)) + .param("projection", "META")) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect(MockMvcResultMatchers.header().string(HeaderKeyConstants.TOTAL_COUNT, "2")); + } + + @Test + @WithMockUser + public void fetchMolecularDataInMultipleMolecularProfiles() throws Exception { + + List geneMolecularDataList = createExampleMolecularData(); + + Mockito.when( + molecularDataService.getMolecularDataInMultipleMolecularProfiles( + Mockito.any(), Mockito.any(), Mockito.any(), Mockito.any())) + .thenReturn(geneMolecularDataList); + + MolecularDataMultipleStudyFilter molecularDataMultipleStudyFilter = + new MolecularDataMultipleStudyFilter(); + molecularDataMultipleStudyFilter.setMolecularProfileIds( + Arrays.asList(TEST_MOLECULAR_PROFILE_STABLE_ID_1, TEST_MOLECULAR_PROFILE_STABLE_ID_2)); + molecularDataMultipleStudyFilter.setEntrezGeneIds( + Arrays.asList(TEST_ENTREZ_GENE_ID_1, TEST_ENTREZ_GENE_ID_2)); + + mockMvc + .perform( + MockMvcRequestBuilders.post("/api/molecular-data/fetch") + .with(csrf()) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(molecularDataMultipleStudyFilter))) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect( + MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.jsonPath("$", Matchers.hasSize(2))) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].molecularProfileId") + .value(TEST_MOLECULAR_PROFILE_STABLE_ID_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].sampleId").value(TEST_SAMPLE_STABLE_ID_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].entrezGeneId").value(TEST_ENTREZ_GENE_ID_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].value").value(2.3)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].gene").doesNotExist()) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].molecularProfileId") + .value(TEST_MOLECULAR_PROFILE_STABLE_ID_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].sampleId").value(TEST_SAMPLE_STABLE_ID_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].entrezGeneId").value(TEST_ENTREZ_GENE_ID_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].value").value(2.4)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].gene").doesNotExist()); + } + + private List createExampleMolecularData() { + + List geneMolecularDataList = new ArrayList<>(); + GeneMolecularData geneMolecularData1 = new GeneMolecularData(); + geneMolecularData1.setMolecularProfileId(TEST_MOLECULAR_PROFILE_STABLE_ID_1); + geneMolecularData1.setSampleId(TEST_SAMPLE_STABLE_ID_1); + geneMolecularData1.setEntrezGeneId(TEST_ENTREZ_GENE_ID_1); + geneMolecularData1.setValue(TEST_VALUE_1); + geneMolecularDataList.add(geneMolecularData1); + GeneMolecularData geneMolecularData2 = new GeneMolecularData(); + geneMolecularData2.setMolecularProfileId(TEST_MOLECULAR_PROFILE_STABLE_ID_2); + geneMolecularData2.setSampleId(TEST_SAMPLE_STABLE_ID_2); + geneMolecularData2.setEntrezGeneId(TEST_ENTREZ_GENE_ID_2); + geneMolecularData2.setValue(TEST_VALUE_2); + geneMolecularDataList.add(geneMolecularData2); + return geneMolecularDataList; + } + + private MolecularDataFilter createMolecularDataFilter() { + + List sampleIds = new ArrayList<>(); + sampleIds.add(TEST_SAMPLE_STABLE_ID_1); + sampleIds.add(TEST_SAMPLE_STABLE_ID_2); + + List entrezGeneIds = new ArrayList<>(); + entrezGeneIds.add(TEST_ENTREZ_GENE_ID_1); + entrezGeneIds.add(TEST_ENTREZ_GENE_ID_2); + + MolecularDataFilter molecularDataFilter = new MolecularDataFilter(); + molecularDataFilter.setEntrezGeneIds(entrezGeneIds); + molecularDataFilter.setSampleIds(sampleIds); + return molecularDataFilter; + } +} diff --git a/src/test/java/org/cbioportal/legacy/web/MolecularProfileControllerTest.java b/src/test/java/org/cbioportal/legacy/web/MolecularProfileControllerTest.java new file mode 100644 index 00000000000..8ef4aceaeab --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/web/MolecularProfileControllerTest.java @@ -0,0 +1,417 @@ +package org.cbioportal.legacy.web; + +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; + +import com.fasterxml.jackson.databind.ObjectMapper; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import org.cbioportal.legacy.model.CancerStudy; +import org.cbioportal.legacy.model.MolecularProfile; +import org.cbioportal.legacy.model.meta.BaseMeta; +import org.cbioportal.legacy.service.MolecularProfileService; +import org.cbioportal.legacy.service.exception.MolecularProfileNotFoundException; +import org.cbioportal.legacy.web.config.TestConfig; +import org.cbioportal.legacy.web.parameter.HeaderKeyConstants; +import org.cbioportal.legacy.web.parameter.MolecularProfileFilter; +import org.hamcrest.Matchers; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mockito; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; +import org.springframework.security.test.context.support.WithMockUser; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.result.MockMvcResultMatchers; + +@RunWith(SpringJUnit4ClassRunner.class) +@WebMvcTest +@ContextConfiguration(classes = {MolecularProfileController.class, TestConfig.class}) +public class MolecularProfileControllerTest { + + private static final int TEST_MOLECULAR_PROFILE_ID_1 = 1; + private static final String TEST_STABLE_ID_1 = "test_stable_id_1"; + private static final int TEST_CANCER_STUDY_ID_1 = 1; + private static final String TEST_STUDY_IDENTIFIER_1 = "test_study_identifier_1"; + private static final MolecularProfile.MolecularAlterationType TEST_MOLECULAR_ALTERATION_TYPE_1 = + MolecularProfile.MolecularAlterationType.MUTATION_EXTENDED; + private static final String TEST_DATATYPE_1 = "MAF"; + private static final String TEST_NAME_1 = "test_name_1"; + private static final String TEST_DESCRIPTION_1 = "test_description_1"; + private static final boolean TEST_SHOW_PROFILE_IN_ANALYSIS_TAB_1 = true; + private static final String TEST_CANCER_STUDY_IDENTIFIER_1 = "test_study_1"; + private static final String TEST_TYPE_OF_CANCER_ID_1 = "test_type_of_cancer_id_1"; + private static final String TEST_STUDY_NAME_1 = "test_study_name_1"; + private static final String TEST_SHORT_NAME_1 = "test_short_name_1"; + private static final String TEST_STUDY_DESCRIPTION_1 = "test_study_description_1"; + private static final Float TEST_STUDY_PIVOT_THRESHOLD_1 = 0.1f; + private static final String TEST_STUDY_SORTORDER_1 = "ASC"; + private static final String TEST_GENERIC_ASSAY_TYPE_1 = "test_generic_assay_type_1"; + + private static final int TEST_MOLECULAR_PROFILE_ID_2 = 2; + private static final String TEST_STABLE_ID_2 = "test_stable_id_2"; + private static final int TEST_CANCER_STUDY_ID_2 = 2; + private static final String TEST_STUDY_IDENTIFIER_2 = "test_study_identifier_2"; + private static final MolecularProfile.MolecularAlterationType TEST_MOLECULAR_ALTERATION_TYPE_2 = + MolecularProfile.MolecularAlterationType.COPY_NUMBER_ALTERATION; + private static final String TEST_DATATYPE_2 = "CONTINUOUS"; + private static final String TEST_NAME_2 = "test_name_2"; + private static final String TEST_DESCRIPTION_2 = "test_description_2"; + private static final boolean TEST_SHOW_PROFILE_IN_ANALYSIS_TAB_2 = false; + private static final Float TEST_STUDY_PIVOT_THRESHOLD_2 = 0.2f; + private static final String TEST_STUDY_SORTORDER_2 = "DESC"; + private static final String TEST_GENERIC_ASSAY_TYPE_2 = "test_generic_assay_type_2"; + + @MockBean private MolecularProfileService molecularProfileService; + + private ObjectMapper objectMapper = new ObjectMapper(); + + @Autowired private MockMvc mockMvc; + + @Test + @WithMockUser + public void getAllMolecularProfilesDefaultProjection() throws Exception { + + List molecularProfileList = createExampleMolecularProfiles(); + + Mockito.when( + molecularProfileService.getAllMolecularProfiles( + Mockito.any(), Mockito.any(), Mockito.any(), Mockito.any(), Mockito.any())) + .thenReturn(molecularProfileList); + + mockMvc + .perform( + MockMvcRequestBuilders.get("/api/molecular-profiles") + .accept(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect( + MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.jsonPath("$", Matchers.hasSize(2))) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].stableId").doesNotExist()) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].molecularProfileId").value(TEST_STABLE_ID_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].studyId").value(TEST_STUDY_IDENTIFIER_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].molecularAlterationType") + .value(TEST_MOLECULAR_ALTERATION_TYPE_1.toString())) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].datatype").value(TEST_DATATYPE_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].genericAssayType") + .value(TEST_GENERIC_ASSAY_TYPE_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].name").value(TEST_NAME_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].description").value(TEST_DESCRIPTION_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].showProfileInAnalysisTab") + .value(TEST_SHOW_PROFILE_IN_ANALYSIS_TAB_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].pivotThreshold") + .value(TEST_STUDY_PIVOT_THRESHOLD_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].sortOrder").value(TEST_STUDY_SORTORDER_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].stableId").doesNotExist()) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].molecularProfileId").value(TEST_STABLE_ID_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].studyId").value(TEST_STUDY_IDENTIFIER_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].molecularAlterationType") + .value(TEST_MOLECULAR_ALTERATION_TYPE_2.toString())) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].datatype").value(TEST_DATATYPE_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].genericAssayType") + .value(TEST_GENERIC_ASSAY_TYPE_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].name").value(TEST_NAME_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].description").value(TEST_DESCRIPTION_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].showProfileInAnalysisTab") + .value(TEST_SHOW_PROFILE_IN_ANALYSIS_TAB_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].pivotThreshold") + .value(TEST_STUDY_PIVOT_THRESHOLD_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].sortOrder").value(TEST_STUDY_SORTORDER_2)); + } + + @Test + @WithMockUser + public void getAllMolecularProfilesMetaProjection() throws Exception { + + BaseMeta baseMeta = new BaseMeta(); + baseMeta.setTotalCount(2); + + Mockito.when(molecularProfileService.getMetaMolecularProfiles()).thenReturn(baseMeta); + + mockMvc + .perform(MockMvcRequestBuilders.get("/api/molecular-profiles").param("projection", "META")) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect(MockMvcResultMatchers.header().string(HeaderKeyConstants.TOTAL_COUNT, "2")); + } + + @Test + @WithMockUser + public void getMolecularProfileNotFound() throws Exception { + + Mockito.when(molecularProfileService.getMolecularProfile(Mockito.anyString())) + .thenThrow(new MolecularProfileNotFoundException("test_molecular_profile_id")); + + mockMvc + .perform( + MockMvcRequestBuilders.get("/api/molecular-profiles/test_molecular_profile_id") + .accept(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.status().isNotFound()) + .andExpect( + MockMvcResultMatchers.jsonPath("$.message") + .value("Molecular profile not found: test_molecular_profile_id")); + } + + @Test + @WithMockUser + public void getMolecularProfile() throws Exception { + + MolecularProfile molecularProfile = new MolecularProfile(); + molecularProfile.setMolecularProfileId(TEST_MOLECULAR_PROFILE_ID_1); + molecularProfile.setStableId(TEST_STABLE_ID_1); + molecularProfile.setCancerStudyId(TEST_CANCER_STUDY_ID_1); + molecularProfile.setCancerStudyIdentifier(TEST_STUDY_IDENTIFIER_1); + molecularProfile.setMolecularAlterationType(TEST_MOLECULAR_ALTERATION_TYPE_1); + molecularProfile.setDatatype(TEST_DATATYPE_1); + molecularProfile.setGenericAssayType(TEST_GENERIC_ASSAY_TYPE_1); + molecularProfile.setName(TEST_NAME_1); + molecularProfile.setDescription(TEST_DESCRIPTION_1); + molecularProfile.setShowProfileInAnalysisTab(TEST_SHOW_PROFILE_IN_ANALYSIS_TAB_1); + molecularProfile.setPivotThreshold(TEST_STUDY_PIVOT_THRESHOLD_1); + molecularProfile.setSortOrder(TEST_STUDY_SORTORDER_1); + CancerStudy cancerStudy = new CancerStudy(); + cancerStudy.setCancerStudyId(TEST_CANCER_STUDY_ID_1); + cancerStudy.setCancerStudyIdentifier(TEST_CANCER_STUDY_IDENTIFIER_1); + cancerStudy.setTypeOfCancerId(TEST_TYPE_OF_CANCER_ID_1); + cancerStudy.setName(TEST_STUDY_NAME_1); + cancerStudy.setDescription(TEST_STUDY_DESCRIPTION_1); + molecularProfile.setCancerStudy(cancerStudy); + + Mockito.when(molecularProfileService.getMolecularProfile(Mockito.anyString())) + .thenReturn(molecularProfile); + + mockMvc + .perform( + MockMvcRequestBuilders.get("/api/molecular-profiles/test_molecular_profile_id") + .accept(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect( + MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.jsonPath("$.stableId").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$.molecularProfileId").value(TEST_STABLE_ID_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$.studyId").value(TEST_STUDY_IDENTIFIER_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$.molecularAlterationType") + .value(TEST_MOLECULAR_ALTERATION_TYPE_1.toString())) + .andExpect(MockMvcResultMatchers.jsonPath("$.datatype").value(TEST_DATATYPE_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$.genericAssayType").value(TEST_GENERIC_ASSAY_TYPE_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$.name").value(TEST_NAME_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$.description").value(TEST_DESCRIPTION_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$.showProfileInAnalysisTab") + .value(TEST_SHOW_PROFILE_IN_ANALYSIS_TAB_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$.pivotThreshold").value(TEST_STUDY_PIVOT_THRESHOLD_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$.sortOrder").value(TEST_STUDY_SORTORDER_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$.study.cancerStudyId").doesNotExist()) + .andExpect( + MockMvcResultMatchers.jsonPath("$.study.studyId").value(TEST_CANCER_STUDY_IDENTIFIER_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$.study.description").value(TEST_STUDY_DESCRIPTION_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$.study.name").value(TEST_STUDY_NAME_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$.study.cancerTypeId").value(TEST_TYPE_OF_CANCER_ID_1)); + } + + @Test + @WithMockUser + public void getAllMolecularProfilesInStudyDefaultProjection() throws Exception { + + List molecularProfileList = createExampleMolecularProfiles(); + + Mockito.when( + molecularProfileService.getAllMolecularProfilesInStudy( + Mockito.any(), + Mockito.any(), + Mockito.any(), + Mockito.any(), + Mockito.any(), + Mockito.any())) + .thenReturn(molecularProfileList); + + mockMvc + .perform( + MockMvcRequestBuilders.get("/api/studies/test_study_id/molecular-profiles") + .accept(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect( + MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.jsonPath("$", Matchers.hasSize(2))) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].stableId").doesNotExist()) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].molecularProfileId").value(TEST_STABLE_ID_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].studyId").value(TEST_STUDY_IDENTIFIER_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].molecularAlterationType") + .value(TEST_MOLECULAR_ALTERATION_TYPE_1.toString())) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].datatype").value(TEST_DATATYPE_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].genericAssayType") + .value(TEST_GENERIC_ASSAY_TYPE_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].name").value(TEST_NAME_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].description").value(TEST_DESCRIPTION_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].showProfileInAnalysisTab") + .value(TEST_SHOW_PROFILE_IN_ANALYSIS_TAB_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].pivotThreshold") + .value(TEST_STUDY_PIVOT_THRESHOLD_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].sortOrder").value(TEST_STUDY_SORTORDER_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].stableId").doesNotExist()) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].molecularProfileId").value(TEST_STABLE_ID_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].studyId").value(TEST_STUDY_IDENTIFIER_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].molecularAlterationType") + .value(TEST_MOLECULAR_ALTERATION_TYPE_2.toString())) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].datatype").value(TEST_DATATYPE_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].genericAssayType") + .value(TEST_GENERIC_ASSAY_TYPE_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].name").value(TEST_NAME_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].description").value(TEST_DESCRIPTION_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].showProfileInAnalysisTab") + .value(TEST_SHOW_PROFILE_IN_ANALYSIS_TAB_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].pivotThreshold") + .value(TEST_STUDY_PIVOT_THRESHOLD_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].sortOrder").value(TEST_STUDY_SORTORDER_2)); + } + + @Test + @WithMockUser + public void getAllMolecularProfilesInStudyMetaProjection() throws Exception { + + BaseMeta baseMeta = new BaseMeta(); + baseMeta.setTotalCount(2); + + Mockito.when(molecularProfileService.getMetaMolecularProfilesInStudy(Mockito.anyString())) + .thenReturn(baseMeta); + + mockMvc + .perform( + MockMvcRequestBuilders.get("/api/studies/test_study_id/molecular-profiles") + .param("projection", "META")) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect(MockMvcResultMatchers.header().string(HeaderKeyConstants.TOTAL_COUNT, "2")); + } + + @Test + @WithMockUser + public void fetchMolecularProfiles() throws Exception { + + List molecularProfileList = createExampleMolecularProfiles(); + + Mockito.when( + molecularProfileService.getMolecularProfilesInStudies( + Mockito.anyList(), Mockito.anyString())) + .thenReturn(molecularProfileList); + + MolecularProfileFilter molecularProfileFilter = new MolecularProfileFilter(); + molecularProfileFilter.setStudyIds( + Arrays.asList(TEST_STUDY_IDENTIFIER_1, TEST_STUDY_IDENTIFIER_2)); + + mockMvc + .perform( + MockMvcRequestBuilders.post("/api/molecular-profiles/fetch") + .with(csrf()) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(molecularProfileFilter))) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect( + MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.jsonPath("$", Matchers.hasSize(2))) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].stableId").doesNotExist()) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].molecularProfileId").value(TEST_STABLE_ID_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].studyId").value(TEST_STUDY_IDENTIFIER_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].molecularAlterationType") + .value(TEST_MOLECULAR_ALTERATION_TYPE_1.toString())) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].datatype").value(TEST_DATATYPE_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].genericAssayType") + .value(TEST_GENERIC_ASSAY_TYPE_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].name").value(TEST_NAME_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].description").value(TEST_DESCRIPTION_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].showProfileInAnalysisTab") + .value(TEST_SHOW_PROFILE_IN_ANALYSIS_TAB_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].pivotThreshold") + .value(TEST_STUDY_PIVOT_THRESHOLD_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].sortOrder").value(TEST_STUDY_SORTORDER_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].stableId").doesNotExist()) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].molecularProfileId").value(TEST_STABLE_ID_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].studyId").value(TEST_STUDY_IDENTIFIER_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].molecularAlterationType") + .value(TEST_MOLECULAR_ALTERATION_TYPE_2.toString())) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].datatype").value(TEST_DATATYPE_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].genericAssayType") + .value(TEST_GENERIC_ASSAY_TYPE_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].name").value(TEST_NAME_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].description").value(TEST_DESCRIPTION_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].showProfileInAnalysisTab") + .value(TEST_SHOW_PROFILE_IN_ANALYSIS_TAB_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].pivotThreshold") + .value(TEST_STUDY_PIVOT_THRESHOLD_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].sortOrder").value(TEST_STUDY_SORTORDER_2)); + } + + private List createExampleMolecularProfiles() { + + List molecularProfileList = new ArrayList<>(); + MolecularProfile molecularProfile1 = new MolecularProfile(); + molecularProfile1.setMolecularProfileId(TEST_MOLECULAR_PROFILE_ID_1); + molecularProfile1.setStableId(TEST_STABLE_ID_1); + molecularProfile1.setCancerStudyId(TEST_CANCER_STUDY_ID_1); + molecularProfile1.setCancerStudyIdentifier(TEST_STUDY_IDENTIFIER_1); + molecularProfile1.setMolecularAlterationType(TEST_MOLECULAR_ALTERATION_TYPE_1); + molecularProfile1.setDatatype(TEST_DATATYPE_1); + molecularProfile1.setGenericAssayType(TEST_GENERIC_ASSAY_TYPE_1); + molecularProfile1.setName(TEST_NAME_1); + molecularProfile1.setDescription(TEST_DESCRIPTION_1); + molecularProfile1.setShowProfileInAnalysisTab(TEST_SHOW_PROFILE_IN_ANALYSIS_TAB_1); + molecularProfile1.setPivotThreshold(TEST_STUDY_PIVOT_THRESHOLD_1); + molecularProfile1.setSortOrder(TEST_STUDY_SORTORDER_1); + molecularProfileList.add(molecularProfile1); + + MolecularProfile molecularProfile2 = new MolecularProfile(); + molecularProfile2.setMolecularProfileId(TEST_MOLECULAR_PROFILE_ID_2); + molecularProfile2.setStableId(TEST_STABLE_ID_2); + molecularProfile2.setCancerStudyId(TEST_CANCER_STUDY_ID_2); + molecularProfile2.setCancerStudyIdentifier(TEST_STUDY_IDENTIFIER_2); + molecularProfile2.setMolecularAlterationType(TEST_MOLECULAR_ALTERATION_TYPE_2); + molecularProfile2.setDatatype(TEST_DATATYPE_2); + molecularProfile2.setGenericAssayType(TEST_GENERIC_ASSAY_TYPE_2); + molecularProfile2.setName(TEST_NAME_2); + molecularProfile2.setDescription(TEST_DESCRIPTION_2); + molecularProfile2.setShowProfileInAnalysisTab(TEST_SHOW_PROFILE_IN_ANALYSIS_TAB_2); + molecularProfile2.setPivotThreshold(TEST_STUDY_PIVOT_THRESHOLD_2); + molecularProfile2.setSortOrder(TEST_STUDY_SORTORDER_2); + molecularProfileList.add(molecularProfile2); + return molecularProfileList; + } +} diff --git a/src/test/java/org/cbioportal/legacy/web/MrnaPercentileControllerTest.java b/src/test/java/org/cbioportal/legacy/web/MrnaPercentileControllerTest.java new file mode 100644 index 00000000000..6150a44bf58 --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/web/MrnaPercentileControllerTest.java @@ -0,0 +1,105 @@ +package org.cbioportal.legacy.web; + +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; + +import com.fasterxml.jackson.databind.ObjectMapper; +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.List; +import org.cbioportal.legacy.model.MrnaPercentile; +import org.cbioportal.legacy.service.MrnaPercentileService; +import org.cbioportal.legacy.web.config.TestConfig; +import org.hamcrest.Matchers; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mockito; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; +import org.springframework.security.test.context.support.WithMockUser; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.result.MockMvcResultMatchers; + +@RunWith(SpringJUnit4ClassRunner.class) +@WebMvcTest +@ContextConfiguration(classes = {MrnaPercentileController.class, TestConfig.class}) +public class MrnaPercentileControllerTest { + + private static final String TEST_MOLECULAR_PROFILE_STABLE_ID = + "test_molecular_profile_stable_id_1"; + private static final String TEST_SAMPLE_STABLE_ID = "test_sample_stable_id_1"; + private static final int TEST_ENTREZ_GENE_ID_1 = 1; + private static final int TEST_ENTREZ_GENE_ID_2 = 2; + private static final BigDecimal TEST_Z_SCORE_1 = new BigDecimal(0.1); + private static final BigDecimal TEST_PERCENTILE_1 = new BigDecimal(50.33); + private static final BigDecimal TEST_Z_SCORE_2 = new BigDecimal(0.2); + private static final BigDecimal TEST_PERCENTILE_2 = new BigDecimal(80.01); + + @MockBean private MrnaPercentileService mrnaPercentileService; + + private ObjectMapper objectMapper = new ObjectMapper(); + + @Autowired private MockMvc mockMvc; + + @Test + @WithMockUser + public void fetchMrnaPercentile() throws Exception { + + List mrnaPercentileList = new ArrayList<>(); + MrnaPercentile mrnaPercentile1 = new MrnaPercentile(); + mrnaPercentile1.setMolecularProfileId(TEST_MOLECULAR_PROFILE_STABLE_ID); + mrnaPercentile1.setSampleId(TEST_SAMPLE_STABLE_ID); + mrnaPercentile1.setEntrezGeneId(TEST_ENTREZ_GENE_ID_1); + mrnaPercentile1.setzScore(TEST_Z_SCORE_1); + mrnaPercentile1.setPercentile(TEST_PERCENTILE_1); + mrnaPercentileList.add(mrnaPercentile1); + MrnaPercentile mrnaPercentile2 = new MrnaPercentile(); + mrnaPercentile2.setMolecularProfileId(TEST_MOLECULAR_PROFILE_STABLE_ID); + mrnaPercentile2.setSampleId(TEST_SAMPLE_STABLE_ID); + mrnaPercentile2.setEntrezGeneId(TEST_ENTREZ_GENE_ID_2); + mrnaPercentile2.setzScore(TEST_Z_SCORE_2); + mrnaPercentile2.setPercentile(TEST_PERCENTILE_2); + mrnaPercentileList.add(mrnaPercentile2); + + Mockito.when( + mrnaPercentileService.fetchMrnaPercentile( + Mockito.anyString(), Mockito.anyString(), Mockito.anyList())) + .thenReturn(mrnaPercentileList); + + List entrezGeneIds = new ArrayList<>(); + entrezGeneIds.add(TEST_ENTREZ_GENE_ID_1); + entrezGeneIds.add(TEST_ENTREZ_GENE_ID_2); + + mockMvc + .perform( + MockMvcRequestBuilders.post( + "/api/molecular-profiles/test_molecular_profile_id/mrna-percentile/fetch") + .with(csrf()) + .param("sampleId", TEST_SAMPLE_STABLE_ID) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(entrezGeneIds))) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect( + MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.jsonPath("$", Matchers.hasSize(2))) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].entrezGeneId").value(TEST_ENTREZ_GENE_ID_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].molecularProfileId") + .value(TEST_MOLECULAR_PROFILE_STABLE_ID)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].sampleId").value(TEST_SAMPLE_STABLE_ID)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].zScore").value(TEST_Z_SCORE_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].percentile").value(TEST_PERCENTILE_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].entrezGeneId").value(TEST_ENTREZ_GENE_ID_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].molecularProfileId") + .value(TEST_MOLECULAR_PROFILE_STABLE_ID)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].sampleId").value(TEST_SAMPLE_STABLE_ID)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].zScore").value(TEST_Z_SCORE_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].percentile").value(TEST_PERCENTILE_2)); + } +} diff --git a/src/test/java/org/cbioportal/legacy/web/MutationControllerTest.java b/src/test/java/org/cbioportal/legacy/web/MutationControllerTest.java new file mode 100644 index 00000000000..f499fbbd160 --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/web/MutationControllerTest.java @@ -0,0 +1,1207 @@ +package org.cbioportal.legacy.web; + +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; + +import com.fasterxml.jackson.databind.ObjectMapper; +import java.util.ArrayList; +import java.util.List; +import org.cbioportal.legacy.model.AlleleSpecificCopyNumber; +import org.cbioportal.legacy.model.Gene; +import org.cbioportal.legacy.model.Mutation; +import org.cbioportal.legacy.model.MutationCountByPosition; +import org.cbioportal.legacy.model.meta.MutationMeta; +import org.cbioportal.legacy.service.MutationService; +import org.cbioportal.legacy.web.config.TestConfig; +import org.cbioportal.legacy.web.parameter.HeaderKeyConstants; +import org.cbioportal.legacy.web.parameter.MutationFilter; +import org.cbioportal.legacy.web.parameter.MutationMultipleStudyFilter; +import org.cbioportal.legacy.web.parameter.MutationPositionIdentifier; +import org.cbioportal.legacy.web.parameter.SampleMolecularIdentifier; +import org.hamcrest.Matchers; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mockito; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; +import org.springframework.security.test.context.support.WithMockUser; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.result.MockMvcResultMatchers; + +@RunWith(SpringJUnit4ClassRunner.class) +@WebMvcTest +@ContextConfiguration( + classes = {MutationController.class, MutationCountController.class, TestConfig.class}) +public class MutationControllerTest { + + private static final String TEST_MOLECULAR_PROFILE_STABLE_ID_1 = + "test_molecular_profile_stable_id_1"; + private static final int TEST_SAMPLE_ID_1 = 1; + private static final String TEST_SAMPLE_STABLE_ID_1 = "test_sample_stable_id_1"; + private static final int TEST_ENTREZ_GENE_ID_1 = 1; + private static final String TEST_CENTER_1 = "test_center_1"; + private static final String TEST_MUTATION_STATUS_1 = "test_mutation_status_1"; + private static final String TEST_VALIDATION_STATUS_1 = "test_validation_status_1"; + private static final int TEST_TUMOR_ALT_COUNT_1 = 1; + private static final int TEST_TUMOR_REF_COUNT_1 = 1; + private static final int TEST_NORMAL_ALT_COUNT_1 = 1; + private static final int TEST_NORMAL_REF_COUNT_1 = 1; + private static final String TEST_AMINO_ACID_CHANGE_1 = "test_amino_acid_change_1"; + private static final long TEST_START_POSITION_1 = 1L; + private static final long TEST_END_POSITION_1 = 1L; + private static final String TEST_REFERENCE_ALLELE_1 = "test_reference_allele_1"; + private static final String TEST_TUMOR_SEQ_ALLELE_1 = "test_tumor_seq_allele_1"; + private static final String TEST_PROTEIN_CHANGE_1 = "test_protein_change_1"; + private static final String TEST_MUTATION_TYPE_1 = "test_mutation_type_1"; + private static final String TEST_NCBI_BUILD_1 = "test_ncbi_build_1"; + private static final String TEST_VARIANT_TYPE_1 = "test_variant_type_1"; + private static final String TEST_MUTATION_REFSEQ_MRNA_ID_1 = "test_mutation_refseq_mrna_id_1"; + private static final int TEST_MUTATION_PROTEIN_POS_START_1 = 1; + private static final int TEST_MUTATION_PROTEIN_POS_END_1 = 1; + private static final String TEST_KEYWORD_1 = "test_keyword_1"; + private static final String TEST_HUGO_GENE_SYMBOL_1 = "test_hugo_gene_symbol_1"; + private static final String TEST_TYPE_1 = "test_type_1"; + private static final String TEST_CYTOBAND_1 = "test_cytoband_1"; + private static final String TEST_CHROMOSOME_1 = "test_chromosome_1"; + private static final int TEST_ASCN_INTEGER_COPY_NUMBER_1 = 3; + private static final String TEST_ASCN_METHOD_1 = "FACETS"; + private static final double TEST_CCF_EXPECTED_COPIES_UPPER_1 = 1.25; + private static final double TEST_CCF_EXPECTED_COPIES_1 = 1.75; + private static final String TEST_CLONAL_1 = "CLONAL"; + private static final int TEST_MINOR_COPY_NUMBER_1 = 2; + private static final int TEST_EXPECTED_ALT_COPIES_1 = 1; + private static final int TEST_TOTAL_COPY_NUMBER_1 = 4; + private static final int TEST_MOLECULAR_PROFILE_ID_2 = 2; + private static final String TEST_MOLECULAR_PROFILE_STABLE_ID_2 = + "test_molecular_profile_stable_id_2"; + private static final int TEST_SAMPLE_ID_2 = 2; + private static final String TEST_SAMPLE_STABLE_ID_2 = "test_sample_stable_id_2"; + private static final int TEST_ENTREZ_GENE_ID_2 = 2; + private static final String TEST_CENTER_2 = "test_center_2"; + private static final String TEST_MUTATION_STATUS_2 = "test_mutation_status_2"; + private static final String TEST_VALIDATION_STATUS_2 = "test_validation_status_2"; + private static final int TEST_TUMOR_ALT_COUNT_2 = 2; + private static final int TEST_TUMOR_REF_COUNT_2 = 2; + private static final int TEST_NORMAL_ALT_COUNT_2 = 2; + private static final int TEST_NORMAL_REF_COUNT_2 = 2; + private static final String TEST_AMINO_ACID_CHANGE_2 = "test_amino_acid_change_2"; + private static final long TEST_START_POSITION_2 = 2L; + private static final long TEST_END_POSITION_2 = 2L; + private static final String TEST_REFERENCE_ALLELE_2 = "test_reference_allele_2"; + private static final String TEST_TUMOR_SEQ_ALLELE_2 = "test_tumor_seq_allele_2"; + private static final String TEST_PROTEIN_CHANGE_2 = "test_protein_change_2"; + private static final String TEST_MUTATION_TYPE_2 = "test_mutation_type_2"; + private static final String TEST_NCBI_BUILD_2 = "test_ncbi_build_2"; + private static final String TEST_VARIANT_TYPE_2 = "test_variant_type_2"; + private static final String TEST_MUTATION_REFSEQ_MRNA_ID_2 = "test_MUTATION_refseq_mrna_id_2"; + private static final int TEST_MUTATION_PROTEIN_POS_START_2 = 2; + private static final int TEST_MUTATION_PROTEIN_POS_END_2 = 2; + private static final String TEST_KEYWORD_2 = "test_keyword_2"; + private static final String TEST_HUGO_GENE_SYMBOL_2 = "test_hugo_gene_symbol_2"; + private static final String TEST_TYPE_2 = "test_type_2"; + private static final String TEST_CYTOBAND_2 = "test_cytoband_2"; + private static final String TEST_CHROMOSOME_2 = "test_chromosome_2"; + private static final int TEST_MUTATION_COUNT_1 = 100; + private static final int TEST_MUTATION_COUNT_2 = 200; + private static final String TEST_SAMPLE_LIST_ID = "test_sample_list_id"; + private static final String TEST_DRIVER_FILTER_1 = "test_driver_filter_1"; + private static final String TEST_DRIVER_FILTER_ANNOTATION_1 = "test_driver_filter_annotation_1"; + private static final String TEST_DRIVER_TIERS_FILTER_1 = "test_driver_tiers_filter_1"; + private static final String TEST_DRIVER_TIERS_FILTER_ANNOTATION_1 = + "test_driver_tiers_filter_annotation_1"; + private static final String TEST_DRIVER_FILTER_2 = "test_driver_filter_2"; + private static final String TEST_DRIVER_FILTER_ANNOTATION_2 = "test_driver_filter_annotation_2"; + private static final String TEST_DRIVER_TIERS_FILTER_2 = "test_driver_tiers_filter_2"; + private static final String TEST_DRIVER_TIERS_FILTER_ANNOTATION_2 = + "test_driver_tiers_filter_annotation_2"; + private static final int TEST_ASCN_INTEGER_COPY_NUMBER_2 = 2; + private static final String TEST_ASCN_METHOD_2 = "ASCN_METHOD2"; + private static final double TEST_CCF_EXPECTED_COPIES_UPPER_2 = 1.5; + private static final double TEST_CCF_EXPECTED_COPIES_2 = 1.95; + private static final String TEST_CLONAL_2 = "SUBCLONAL"; + private static final int TEST_MINOR_COPY_NUMBER_2 = 1; + private static final int TEST_EXPECTED_ALT_COPIES_2 = 1; + private static final int TEST_TOTAL_COPY_NUMBER_2 = 2; + private static final String NAME_SPACE_COLUMNS = + "{\"columnName\":{\"fieldName\":\"fieldValue\"}}"; + + @MockBean private MutationService mutationService; + + private ObjectMapper objectMapper = new ObjectMapper(); + + @Autowired private MockMvc mockMvc; + + @Test + @WithMockUser + public void getMutationsInMolecularProfileBySampleListIdDefaultProjection() throws Exception { + + List mutationList = createExampleMutations(); + + Mockito.when( + mutationService.getMutationsInMolecularProfileBySampleListId( + Mockito.any(), + Mockito.any(), + Mockito.any(), + Mockito.anyBoolean(), + Mockito.any(), + Mockito.any(), + Mockito.any(), + Mockito.any(), + Mockito.any())) + .thenReturn(mutationList); + + mockMvc + .perform( + MockMvcRequestBuilders.get( + "/api/molecular-profiles/test_molecular_profile_id/mutations") + .param("sampleListId", TEST_SAMPLE_LIST_ID) + .accept(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect( + MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.jsonPath("$", Matchers.hasSize(2))) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].molecularProfileId") + .value(TEST_MOLECULAR_PROFILE_STABLE_ID_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].sampleId").value(TEST_SAMPLE_STABLE_ID_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].entrezGeneId").value(TEST_ENTREZ_GENE_ID_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].center").value(TEST_CENTER_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].mutationStatus").value(TEST_MUTATION_STATUS_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].validationStatus").value(TEST_VALIDATION_STATUS_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].tumorAltCount").value(TEST_TUMOR_ALT_COUNT_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].tumorRefCount").value(TEST_TUMOR_REF_COUNT_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].normalAltCount").value(TEST_NORMAL_ALT_COUNT_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].normalRefCount").value(TEST_NORMAL_REF_COUNT_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].aminoAcidChange").value(TEST_AMINO_ACID_CHANGE_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].startPosition").value((int) TEST_START_POSITION_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].endPosition").value((int) TEST_END_POSITION_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].referenceAllele").value(TEST_REFERENCE_ALLELE_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].variantAllele").value(TEST_TUMOR_SEQ_ALLELE_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].proteinChange").value(TEST_PROTEIN_CHANGE_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].mutationType").value(TEST_MUTATION_TYPE_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].driverFilter").value(TEST_DRIVER_FILTER_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].driverFilterAnnotation") + .value(TEST_DRIVER_FILTER_ANNOTATION_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].driverTiersFilter") + .value(TEST_DRIVER_TIERS_FILTER_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].driverTiersFilterAnnotation") + .value(TEST_DRIVER_TIERS_FILTER_ANNOTATION_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].ncbiBuild").value(TEST_NCBI_BUILD_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].variantType").value(TEST_VARIANT_TYPE_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].refseqMrnaId") + .value(TEST_MUTATION_REFSEQ_MRNA_ID_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].proteinPosStart") + .value(TEST_MUTATION_PROTEIN_POS_START_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].proteinPosEnd") + .value(TEST_MUTATION_PROTEIN_POS_END_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].keyword").value(TEST_KEYWORD_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].gene").doesNotExist()) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].namespaceColumns.columnName.fieldName") + .value("fieldValue")) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].molecularProfileId") + .value(TEST_MOLECULAR_PROFILE_STABLE_ID_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].sampleId").value(TEST_SAMPLE_STABLE_ID_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].entrezGeneId").value(TEST_ENTREZ_GENE_ID_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].center").value(TEST_CENTER_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].mutationStatus").value(TEST_MUTATION_STATUS_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].validationStatus").value(TEST_VALIDATION_STATUS_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].tumorAltCount").value(TEST_TUMOR_ALT_COUNT_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].tumorRefCount").value(TEST_TUMOR_REF_COUNT_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].normalAltCount").value(TEST_NORMAL_ALT_COUNT_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].normalRefCount").value(TEST_NORMAL_REF_COUNT_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].aminoAcidChange").value(TEST_AMINO_ACID_CHANGE_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].startPosition").value((int) TEST_START_POSITION_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].endPosition").value((int) TEST_END_POSITION_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].referenceAllele").value(TEST_REFERENCE_ALLELE_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].variantAllele").value(TEST_TUMOR_SEQ_ALLELE_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].proteinChange").value(TEST_PROTEIN_CHANGE_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].mutationType").value(TEST_MUTATION_TYPE_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].driverFilter").value(TEST_DRIVER_FILTER_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].driverFilterAnnotation") + .value(TEST_DRIVER_FILTER_ANNOTATION_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].driverTiersFilter") + .value(TEST_DRIVER_TIERS_FILTER_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].driverTiersFilterAnnotation") + .value(TEST_DRIVER_TIERS_FILTER_ANNOTATION_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].ncbiBuild").value(TEST_NCBI_BUILD_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].variantType").value(TEST_VARIANT_TYPE_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].refseqMrnaId") + .value(TEST_MUTATION_REFSEQ_MRNA_ID_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].proteinPosStart") + .value(TEST_MUTATION_PROTEIN_POS_START_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].proteinPosEnd") + .value(TEST_MUTATION_PROTEIN_POS_END_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].keyword").value(TEST_KEYWORD_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].gene").doesNotExist()) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].namespaceColumns.columnName.fieldName") + .value("fieldValue")); + } + + @Test + @WithMockUser + public void getMutationsInMolecularProfileBySampleListIdDetailedProjection() throws Exception { + + List mutationList = createExampleMutationsWithGeneAndAlleleSpecificCopyNumber(); + + Mockito.when( + mutationService.getMutationsInMolecularProfileBySampleListId( + Mockito.any(), + Mockito.any(), + Mockito.any(), + Mockito.anyBoolean(), + Mockito.any(), + Mockito.any(), + Mockito.any(), + Mockito.any(), + Mockito.any())) + .thenReturn(mutationList); + + mockMvc + .perform( + MockMvcRequestBuilders.get( + "/api/molecular-profiles/test_molecular_profile_id/mutations") + .param("sampleListId", TEST_SAMPLE_LIST_ID) + .param("projection", "DETAILED") + .accept(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect( + MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.jsonPath("$", Matchers.hasSize(2))) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].molecularProfileId") + .value(TEST_MOLECULAR_PROFILE_STABLE_ID_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].sampleId").value(TEST_SAMPLE_STABLE_ID_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].entrezGeneId").value(TEST_ENTREZ_GENE_ID_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].center").value(TEST_CENTER_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].mutationStatus").value(TEST_MUTATION_STATUS_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].validationStatus").value(TEST_VALIDATION_STATUS_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].tumorAltCount").value(TEST_TUMOR_ALT_COUNT_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].tumorRefCount").value(TEST_TUMOR_REF_COUNT_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].normalAltCount").value(TEST_NORMAL_ALT_COUNT_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].normalRefCount").value(TEST_NORMAL_REF_COUNT_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].aminoAcidChange").value(TEST_AMINO_ACID_CHANGE_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].startPosition").value((int) TEST_START_POSITION_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].endPosition").value((int) TEST_END_POSITION_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].referenceAllele").value(TEST_REFERENCE_ALLELE_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].variantAllele").value(TEST_TUMOR_SEQ_ALLELE_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].proteinChange").value(TEST_PROTEIN_CHANGE_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].mutationType").value(TEST_MUTATION_TYPE_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].driverFilter").value(TEST_DRIVER_FILTER_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].driverFilterAnnotation") + .value(TEST_DRIVER_FILTER_ANNOTATION_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].driverTiersFilter") + .value(TEST_DRIVER_TIERS_FILTER_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].driverTiersFilterAnnotation") + .value(TEST_DRIVER_TIERS_FILTER_ANNOTATION_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].ncbiBuild").value(TEST_NCBI_BUILD_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].variantType").value(TEST_VARIANT_TYPE_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].refseqMrnaId") + .value(TEST_MUTATION_REFSEQ_MRNA_ID_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].proteinPosStart") + .value(TEST_MUTATION_PROTEIN_POS_START_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].proteinPosEnd") + .value(TEST_MUTATION_PROTEIN_POS_END_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].keyword").value(TEST_KEYWORD_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].gene.entrezGeneId").value(TEST_ENTREZ_GENE_ID_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].gene.hugoGeneSymbol") + .value(TEST_HUGO_GENE_SYMBOL_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].gene.type").value(TEST_TYPE_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].alleleSpecificCopyNumber.ascnIntegerCopyNumber") + .value(TEST_ASCN_INTEGER_COPY_NUMBER_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].alleleSpecificCopyNumber.ascnMethod") + .value(TEST_ASCN_METHOD_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].alleleSpecificCopyNumber.ccfExpectedCopiesUpper") + .value(TEST_CCF_EXPECTED_COPIES_UPPER_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].alleleSpecificCopyNumber.ccfExpectedCopies") + .value(TEST_CCF_EXPECTED_COPIES_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].alleleSpecificCopyNumber.clonal") + .value(TEST_CLONAL_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].alleleSpecificCopyNumber.minorCopyNumber") + .value(TEST_MINOR_COPY_NUMBER_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].alleleSpecificCopyNumber.expectedAltCopies") + .value(TEST_EXPECTED_ALT_COPIES_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].alleleSpecificCopyNumber.totalCopyNumber") + .value(TEST_TOTAL_COPY_NUMBER_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].molecularProfileId") + .value(TEST_MOLECULAR_PROFILE_STABLE_ID_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].sampleId").value(TEST_SAMPLE_STABLE_ID_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].entrezGeneId").value(TEST_ENTREZ_GENE_ID_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].center").value(TEST_CENTER_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].mutationStatus").value(TEST_MUTATION_STATUS_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].validationStatus").value(TEST_VALIDATION_STATUS_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].tumorAltCount").value(TEST_TUMOR_ALT_COUNT_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].tumorRefCount").value(TEST_TUMOR_REF_COUNT_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].normalAltCount").value(TEST_NORMAL_ALT_COUNT_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].normalRefCount").value(TEST_NORMAL_REF_COUNT_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].aminoAcidChange").value(TEST_AMINO_ACID_CHANGE_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].startPosition").value((int) TEST_START_POSITION_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].endPosition").value((int) TEST_END_POSITION_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].referenceAllele").value(TEST_REFERENCE_ALLELE_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].variantAllele").value(TEST_TUMOR_SEQ_ALLELE_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].proteinChange").value(TEST_PROTEIN_CHANGE_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].mutationType").value(TEST_MUTATION_TYPE_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].driverFilter").value(TEST_DRIVER_FILTER_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].driverFilterAnnotation") + .value(TEST_DRIVER_FILTER_ANNOTATION_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].driverTiersFilter") + .value(TEST_DRIVER_TIERS_FILTER_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].driverTiersFilterAnnotation") + .value(TEST_DRIVER_TIERS_FILTER_ANNOTATION_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].ncbiBuild").value(TEST_NCBI_BUILD_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].variantType").value(TEST_VARIANT_TYPE_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].refseqMrnaId") + .value(TEST_MUTATION_REFSEQ_MRNA_ID_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].proteinPosStart") + .value(TEST_MUTATION_PROTEIN_POS_START_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].proteinPosEnd") + .value(TEST_MUTATION_PROTEIN_POS_END_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].keyword").value(TEST_KEYWORD_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].gene.entrezGeneId").value(TEST_ENTREZ_GENE_ID_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].gene.hugoGeneSymbol") + .value(TEST_HUGO_GENE_SYMBOL_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].gene.type").value(TEST_TYPE_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].alleleSpecificCopyNumber.ascnIntegerCopyNumber") + .value(TEST_ASCN_INTEGER_COPY_NUMBER_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].alleleSpecificCopyNumber.ascnMethod") + .value(TEST_ASCN_METHOD_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].alleleSpecificCopyNumber.ccfExpectedCopiesUpper") + .value(TEST_CCF_EXPECTED_COPIES_UPPER_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].alleleSpecificCopyNumber.ccfExpectedCopies") + .value(TEST_CCF_EXPECTED_COPIES_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].alleleSpecificCopyNumber.clonal") + .value(TEST_CLONAL_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].alleleSpecificCopyNumber.minorCopyNumber") + .value(TEST_MINOR_COPY_NUMBER_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].alleleSpecificCopyNumber.expectedAltCopies") + .value(TEST_EXPECTED_ALT_COPIES_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].alleleSpecificCopyNumber.totalCopyNumber") + .value(TEST_TOTAL_COPY_NUMBER_2)); + } + + @Test + @WithMockUser + public void getMutationsInMolecularProfileBySampleListIdMetaProjection() throws Exception { + + MutationMeta mutationMeta = new MutationMeta(); + mutationMeta.setTotalCount(2); + mutationMeta.setSampleCount(3); + + Mockito.when( + mutationService.getMetaMutationsInMolecularProfileBySampleListId( + Mockito.any(), Mockito.any(), Mockito.any())) + .thenReturn(mutationMeta); + + mockMvc + .perform( + MockMvcRequestBuilders.get( + "/api/molecular-profiles/test_molecular_profile_id/mutations") + .param("sampleListId", TEST_SAMPLE_LIST_ID) + .param("projection", "META")) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect(MockMvcResultMatchers.header().string(HeaderKeyConstants.TOTAL_COUNT, "2")) + .andExpect(MockMvcResultMatchers.header().string(HeaderKeyConstants.SAMPLE_COUNT, "3")); + } + + @Test + @WithMockUser + public void fetchMutationsInMultipleMolecularProfiles() throws Exception { + + List mutationList = createExampleMutations(); + + Mockito.when( + mutationService.getMutationsInMultipleMolecularProfiles( + Mockito.any(), + Mockito.any(), + Mockito.any(), + Mockito.any(), + Mockito.any(), + Mockito.any(), + Mockito.any(), + Mockito.any())) + .thenReturn(mutationList); + + List sampleMolecularIdentifiers = new ArrayList<>(); + SampleMolecularIdentifier sampleMolecularIdentifier1 = new SampleMolecularIdentifier(); + sampleMolecularIdentifier1.setMolecularProfileId(TEST_MOLECULAR_PROFILE_STABLE_ID_1); + sampleMolecularIdentifier1.setSampleId(TEST_SAMPLE_STABLE_ID_1); + sampleMolecularIdentifiers.add(sampleMolecularIdentifier1); + SampleMolecularIdentifier sampleMolecularIdentifier2 = new SampleMolecularIdentifier(); + sampleMolecularIdentifier2.setMolecularProfileId(TEST_MOLECULAR_PROFILE_STABLE_ID_2); + sampleMolecularIdentifier2.setSampleId(TEST_SAMPLE_STABLE_ID_2); + sampleMolecularIdentifiers.add(sampleMolecularIdentifier2); + MutationMultipleStudyFilter mutationMultipleStudyFilter = new MutationMultipleStudyFilter(); + mutationMultipleStudyFilter.setSampleMolecularIdentifiers(sampleMolecularIdentifiers); + + mockMvc + .perform( + MockMvcRequestBuilders.post("/api/mutations/fetch") + .with(csrf()) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(mutationMultipleStudyFilter))) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect( + MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.jsonPath("$", Matchers.hasSize(2))) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].molecularProfileId") + .value(TEST_MOLECULAR_PROFILE_STABLE_ID_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].sampleId").value(TEST_SAMPLE_STABLE_ID_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].entrezGeneId").value(TEST_ENTREZ_GENE_ID_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].center").value(TEST_CENTER_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].mutationStatus").value(TEST_MUTATION_STATUS_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].validationStatus").value(TEST_VALIDATION_STATUS_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].tumorAltCount").value(TEST_TUMOR_ALT_COUNT_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].tumorRefCount").value(TEST_TUMOR_REF_COUNT_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].normalAltCount").value(TEST_NORMAL_ALT_COUNT_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].normalRefCount").value(TEST_NORMAL_REF_COUNT_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].aminoAcidChange").value(TEST_AMINO_ACID_CHANGE_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].startPosition").value((int) TEST_START_POSITION_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].endPosition").value((int) TEST_END_POSITION_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].referenceAllele").value(TEST_REFERENCE_ALLELE_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].variantAllele").value(TEST_TUMOR_SEQ_ALLELE_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].proteinChange").value(TEST_PROTEIN_CHANGE_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].mutationType").value(TEST_MUTATION_TYPE_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].driverFilter").value(TEST_DRIVER_FILTER_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].driverFilterAnnotation") + .value(TEST_DRIVER_FILTER_ANNOTATION_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].driverTiersFilter") + .value(TEST_DRIVER_TIERS_FILTER_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].driverTiersFilterAnnotation") + .value(TEST_DRIVER_TIERS_FILTER_ANNOTATION_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].ncbiBuild").value(TEST_NCBI_BUILD_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].variantType").value(TEST_VARIANT_TYPE_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].refseqMrnaId") + .value(TEST_MUTATION_REFSEQ_MRNA_ID_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].proteinPosStart") + .value(TEST_MUTATION_PROTEIN_POS_START_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].proteinPosEnd") + .value(TEST_MUTATION_PROTEIN_POS_END_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].keyword").value(TEST_KEYWORD_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].gene").doesNotExist()) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].molecularProfileId") + .value(TEST_MOLECULAR_PROFILE_STABLE_ID_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].sampleId").value(TEST_SAMPLE_STABLE_ID_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].entrezGeneId").value(TEST_ENTREZ_GENE_ID_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].center").value(TEST_CENTER_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].mutationStatus").value(TEST_MUTATION_STATUS_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].validationStatus").value(TEST_VALIDATION_STATUS_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].tumorAltCount").value(TEST_TUMOR_ALT_COUNT_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].tumorRefCount").value(TEST_TUMOR_REF_COUNT_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].normalAltCount").value(TEST_NORMAL_ALT_COUNT_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].normalRefCount").value(TEST_NORMAL_REF_COUNT_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].aminoAcidChange").value(TEST_AMINO_ACID_CHANGE_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].startPosition").value((int) TEST_START_POSITION_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].endPosition").value((int) TEST_END_POSITION_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].referenceAllele").value(TEST_REFERENCE_ALLELE_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].variantAllele").value(TEST_TUMOR_SEQ_ALLELE_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].proteinChange").value(TEST_PROTEIN_CHANGE_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].mutationType").value(TEST_MUTATION_TYPE_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].driverFilter").value(TEST_DRIVER_FILTER_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].driverFilterAnnotation") + .value(TEST_DRIVER_FILTER_ANNOTATION_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].driverTiersFilter") + .value(TEST_DRIVER_TIERS_FILTER_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].driverTiersFilterAnnotation") + .value(TEST_DRIVER_TIERS_FILTER_ANNOTATION_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].ncbiBuild").value(TEST_NCBI_BUILD_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].variantType").value(TEST_VARIANT_TYPE_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].refseqMrnaId") + .value(TEST_MUTATION_REFSEQ_MRNA_ID_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].proteinPosStart") + .value(TEST_MUTATION_PROTEIN_POS_START_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].proteinPosEnd") + .value(TEST_MUTATION_PROTEIN_POS_END_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].keyword").value(TEST_KEYWORD_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].gene").doesNotExist()); + } + + @Test + @WithMockUser + public void fetchMutationsInMolecularProfileDefaultProjection() throws Exception { + + List mutationList = createExampleMutations(); + + Mockito.when( + mutationService.fetchMutationsInMolecularProfile( + Mockito.any(), + Mockito.any(), + Mockito.any(), + Mockito.anyBoolean(), + Mockito.any(), + Mockito.any(), + Mockito.any(), + Mockito.any(), + Mockito.any())) + .thenReturn(mutationList); + + List sampleIds = new ArrayList<>(); + sampleIds.add(TEST_SAMPLE_STABLE_ID_1); + sampleIds.add(TEST_SAMPLE_STABLE_ID_2); + MutationFilter mutationFilter = new MutationFilter(); + mutationFilter.setSampleIds(sampleIds); + + mockMvc + .perform( + MockMvcRequestBuilders.post( + "/api/molecular-profiles/test_molecular_profile_id/mutations/fetch") + .with(csrf()) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(mutationFilter))) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect( + MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.jsonPath("$", Matchers.hasSize(2))) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].molecularProfileId") + .value(TEST_MOLECULAR_PROFILE_STABLE_ID_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].sampleId").value(TEST_SAMPLE_STABLE_ID_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].entrezGeneId").value(TEST_ENTREZ_GENE_ID_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].center").value(TEST_CENTER_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].mutationStatus").value(TEST_MUTATION_STATUS_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].validationStatus").value(TEST_VALIDATION_STATUS_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].tumorAltCount").value(TEST_TUMOR_ALT_COUNT_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].tumorRefCount").value(TEST_TUMOR_REF_COUNT_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].normalAltCount").value(TEST_NORMAL_ALT_COUNT_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].normalRefCount").value(TEST_NORMAL_REF_COUNT_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].aminoAcidChange").value(TEST_AMINO_ACID_CHANGE_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].startPosition").value((int) TEST_START_POSITION_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].endPosition").value((int) TEST_END_POSITION_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].referenceAllele").value(TEST_REFERENCE_ALLELE_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].variantAllele").value(TEST_TUMOR_SEQ_ALLELE_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].proteinChange").value(TEST_PROTEIN_CHANGE_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].mutationType").value(TEST_MUTATION_TYPE_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].driverFilter").value(TEST_DRIVER_FILTER_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].driverFilterAnnotation") + .value(TEST_DRIVER_FILTER_ANNOTATION_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].driverTiersFilter") + .value(TEST_DRIVER_TIERS_FILTER_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].driverTiersFilterAnnotation") + .value(TEST_DRIVER_TIERS_FILTER_ANNOTATION_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].ncbiBuild").value(TEST_NCBI_BUILD_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].variantType").value(TEST_VARIANT_TYPE_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].refseqMrnaId") + .value(TEST_MUTATION_REFSEQ_MRNA_ID_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].proteinPosStart") + .value(TEST_MUTATION_PROTEIN_POS_START_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].proteinPosEnd") + .value(TEST_MUTATION_PROTEIN_POS_END_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].keyword").value(TEST_KEYWORD_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].gene").doesNotExist()) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].molecularProfileId") + .value(TEST_MOLECULAR_PROFILE_STABLE_ID_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].sampleId").value(TEST_SAMPLE_STABLE_ID_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].entrezGeneId").value(TEST_ENTREZ_GENE_ID_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].center").value(TEST_CENTER_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].mutationStatus").value(TEST_MUTATION_STATUS_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].validationStatus").value(TEST_VALIDATION_STATUS_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].tumorAltCount").value(TEST_TUMOR_ALT_COUNT_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].tumorRefCount").value(TEST_TUMOR_REF_COUNT_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].normalAltCount").value(TEST_NORMAL_ALT_COUNT_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].normalRefCount").value(TEST_NORMAL_REF_COUNT_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].aminoAcidChange").value(TEST_AMINO_ACID_CHANGE_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].startPosition").value((int) TEST_START_POSITION_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].endPosition").value((int) TEST_END_POSITION_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].referenceAllele").value(TEST_REFERENCE_ALLELE_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].variantAllele").value(TEST_TUMOR_SEQ_ALLELE_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].proteinChange").value(TEST_PROTEIN_CHANGE_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].mutationType").value(TEST_MUTATION_TYPE_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].driverFilter").value(TEST_DRIVER_FILTER_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].driverFilterAnnotation") + .value(TEST_DRIVER_FILTER_ANNOTATION_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].driverTiersFilter") + .value(TEST_DRIVER_TIERS_FILTER_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].driverTiersFilterAnnotation") + .value(TEST_DRIVER_TIERS_FILTER_ANNOTATION_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].ncbiBuild").value(TEST_NCBI_BUILD_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].variantType").value(TEST_VARIANT_TYPE_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].refseqMrnaId") + .value(TEST_MUTATION_REFSEQ_MRNA_ID_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].proteinPosStart") + .value(TEST_MUTATION_PROTEIN_POS_START_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].proteinPosEnd") + .value(TEST_MUTATION_PROTEIN_POS_END_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].keyword").value(TEST_KEYWORD_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].gene").doesNotExist()); + } + + @Test + @WithMockUser + public void fetchMutationsInMolecularProfileDetailedProjection() throws Exception { + + List mutationList = createExampleMutationsWithGeneAndAlleleSpecificCopyNumber(); + + Mockito.when( + mutationService.fetchMutationsInMolecularProfile( + Mockito.any(), + Mockito.any(), + Mockito.any(), + Mockito.anyBoolean(), + Mockito.any(), + Mockito.any(), + Mockito.any(), + Mockito.any(), + Mockito.any())) + .thenReturn(mutationList); + + List sampleIds = new ArrayList<>(); + sampleIds.add(TEST_SAMPLE_STABLE_ID_1); + sampleIds.add(TEST_SAMPLE_STABLE_ID_2); + MutationFilter mutationFilter = new MutationFilter(); + mutationFilter.setSampleIds(sampleIds); + + mockMvc + .perform( + MockMvcRequestBuilders.post( + "/api/molecular-profiles/test_molecular_profile_id/mutations/fetch") + .with(csrf()) + .param("projection", "DETAILED") + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(mutationFilter))) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect( + MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.jsonPath("$", Matchers.hasSize(2))) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].molecularProfileId") + .value(TEST_MOLECULAR_PROFILE_STABLE_ID_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].sampleId").value(TEST_SAMPLE_STABLE_ID_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].entrezGeneId").value(TEST_ENTREZ_GENE_ID_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].center").value(TEST_CENTER_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].mutationStatus").value(TEST_MUTATION_STATUS_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].validationStatus").value(TEST_VALIDATION_STATUS_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].tumorAltCount").value(TEST_TUMOR_ALT_COUNT_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].tumorRefCount").value(TEST_TUMOR_REF_COUNT_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].normalAltCount").value(TEST_NORMAL_ALT_COUNT_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].normalRefCount").value(TEST_NORMAL_REF_COUNT_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].aminoAcidChange").value(TEST_AMINO_ACID_CHANGE_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].startPosition").value((int) TEST_START_POSITION_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].endPosition").value((int) TEST_END_POSITION_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].referenceAllele").value(TEST_REFERENCE_ALLELE_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].variantAllele").value(TEST_TUMOR_SEQ_ALLELE_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].proteinChange").value(TEST_PROTEIN_CHANGE_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].mutationType").value(TEST_MUTATION_TYPE_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].driverFilter").value(TEST_DRIVER_FILTER_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].driverFilterAnnotation") + .value(TEST_DRIVER_FILTER_ANNOTATION_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].driverTiersFilter") + .value(TEST_DRIVER_TIERS_FILTER_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].driverTiersFilterAnnotation") + .value(TEST_DRIVER_TIERS_FILTER_ANNOTATION_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].ncbiBuild").value(TEST_NCBI_BUILD_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].variantType").value(TEST_VARIANT_TYPE_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].refseqMrnaId") + .value(TEST_MUTATION_REFSEQ_MRNA_ID_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].proteinPosStart") + .value(TEST_MUTATION_PROTEIN_POS_START_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].proteinPosEnd") + .value(TEST_MUTATION_PROTEIN_POS_END_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].keyword").value(TEST_KEYWORD_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].gene.entrezGeneId").value(TEST_ENTREZ_GENE_ID_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].gene.hugoGeneSymbol") + .value(TEST_HUGO_GENE_SYMBOL_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].gene.type").value(TEST_TYPE_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].alleleSpecificCopyNumber.ascnIntegerCopyNumber") + .value(TEST_ASCN_INTEGER_COPY_NUMBER_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].alleleSpecificCopyNumber.ascnMethod") + .value(TEST_ASCN_METHOD_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].alleleSpecificCopyNumber.ccfExpectedCopiesUpper") + .value(TEST_CCF_EXPECTED_COPIES_UPPER_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].alleleSpecificCopyNumber.ccfExpectedCopies") + .value(TEST_CCF_EXPECTED_COPIES_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].alleleSpecificCopyNumber.clonal") + .value(TEST_CLONAL_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].alleleSpecificCopyNumber.minorCopyNumber") + .value(TEST_MINOR_COPY_NUMBER_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].alleleSpecificCopyNumber.expectedAltCopies") + .value(TEST_EXPECTED_ALT_COPIES_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].alleleSpecificCopyNumber.totalCopyNumber") + .value(TEST_TOTAL_COPY_NUMBER_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].molecularProfileId") + .value(TEST_MOLECULAR_PROFILE_STABLE_ID_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].sampleId").value(TEST_SAMPLE_STABLE_ID_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].entrezGeneId").value(TEST_ENTREZ_GENE_ID_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].center").value(TEST_CENTER_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].mutationStatus").value(TEST_MUTATION_STATUS_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].validationStatus").value(TEST_VALIDATION_STATUS_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].tumorAltCount").value(TEST_TUMOR_ALT_COUNT_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].tumorRefCount").value(TEST_TUMOR_REF_COUNT_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].normalAltCount").value(TEST_NORMAL_ALT_COUNT_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].normalRefCount").value(TEST_NORMAL_REF_COUNT_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].aminoAcidChange").value(TEST_AMINO_ACID_CHANGE_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].startPosition").value((int) TEST_START_POSITION_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].endPosition").value((int) TEST_END_POSITION_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].referenceAllele").value(TEST_REFERENCE_ALLELE_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].variantAllele").value(TEST_TUMOR_SEQ_ALLELE_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].proteinChange").value(TEST_PROTEIN_CHANGE_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].mutationType").value(TEST_MUTATION_TYPE_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].driverFilter").value(TEST_DRIVER_FILTER_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].driverFilterAnnotation") + .value(TEST_DRIVER_FILTER_ANNOTATION_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].driverTiersFilter") + .value(TEST_DRIVER_TIERS_FILTER_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].driverTiersFilterAnnotation") + .value(TEST_DRIVER_TIERS_FILTER_ANNOTATION_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].ncbiBuild").value(TEST_NCBI_BUILD_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].variantType").value(TEST_VARIANT_TYPE_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].refseqMrnaId") + .value(TEST_MUTATION_REFSEQ_MRNA_ID_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].proteinPosStart") + .value(TEST_MUTATION_PROTEIN_POS_START_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].proteinPosEnd") + .value(TEST_MUTATION_PROTEIN_POS_END_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].keyword").value(TEST_KEYWORD_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].gene.entrezGeneId").value(TEST_ENTREZ_GENE_ID_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].gene.hugoGeneSymbol") + .value(TEST_HUGO_GENE_SYMBOL_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].gene.type").value(TEST_TYPE_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].alleleSpecificCopyNumber.ascnIntegerCopyNumber") + .value(TEST_ASCN_INTEGER_COPY_NUMBER_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].alleleSpecificCopyNumber.ascnMethod") + .value(TEST_ASCN_METHOD_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].alleleSpecificCopyNumber.ccfExpectedCopiesUpper") + .value(TEST_CCF_EXPECTED_COPIES_UPPER_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].alleleSpecificCopyNumber.ccfExpectedCopies") + .value(TEST_CCF_EXPECTED_COPIES_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].alleleSpecificCopyNumber.clonal") + .value(TEST_CLONAL_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].alleleSpecificCopyNumber.minorCopyNumber") + .value(TEST_MINOR_COPY_NUMBER_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].alleleSpecificCopyNumber.expectedAltCopies") + .value(TEST_EXPECTED_ALT_COPIES_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].alleleSpecificCopyNumber.totalCopyNumber") + .value(TEST_TOTAL_COPY_NUMBER_2)); + } + + @Test + @WithMockUser + public void fetchMutationsInMolecularProfileMetaProjection() throws Exception { + + MutationMeta mutationMeta = new MutationMeta(); + mutationMeta.setTotalCount(2); + mutationMeta.setSampleCount(3); + + Mockito.when( + mutationService.fetchMetaMutationsInMolecularProfile( + Mockito.any(), Mockito.any(), Mockito.any())) + .thenReturn(mutationMeta); + + List sampleIds = new ArrayList<>(); + sampleIds.add(TEST_SAMPLE_STABLE_ID_1); + sampleIds.add(TEST_SAMPLE_STABLE_ID_2); + MutationFilter mutationFilter = new MutationFilter(); + mutationFilter.setSampleIds(sampleIds); + + mockMvc + .perform( + MockMvcRequestBuilders.post( + "/api/molecular-profiles/test_molecular_profile_id/mutations/fetch") + .with(csrf()) + .param("projection", "META") + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(mutationFilter))) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect(MockMvcResultMatchers.header().string(HeaderKeyConstants.TOTAL_COUNT, "2")) + .andExpect(MockMvcResultMatchers.header().string(HeaderKeyConstants.SAMPLE_COUNT, "3")); + } + + @Test + @WithMockUser + public void fetchMutationCountsByPosition() throws Exception { + + List mutationCountByPositionList = new ArrayList<>(); + MutationCountByPosition mutationCountByPosition1 = new MutationCountByPosition(); + mutationCountByPosition1.setEntrezGeneId(TEST_ENTREZ_GENE_ID_1); + mutationCountByPosition1.setProteinPosStart(TEST_MUTATION_PROTEIN_POS_START_1); + mutationCountByPosition1.setProteinPosEnd(TEST_MUTATION_PROTEIN_POS_END_1); + mutationCountByPosition1.setCount(TEST_MUTATION_COUNT_1); + mutationCountByPositionList.add(mutationCountByPosition1); + MutationCountByPosition mutationCountByPosition2 = new MutationCountByPosition(); + mutationCountByPosition2.setEntrezGeneId(TEST_ENTREZ_GENE_ID_2); + mutationCountByPosition2.setProteinPosStart(TEST_MUTATION_PROTEIN_POS_START_2); + mutationCountByPosition2.setProteinPosEnd(TEST_MUTATION_PROTEIN_POS_END_2); + mutationCountByPosition2.setCount(TEST_MUTATION_COUNT_2); + mutationCountByPositionList.add(mutationCountByPosition2); + + Mockito.when( + mutationService.fetchMutationCountsByPosition( + Mockito.anyList(), Mockito.anyList(), Mockito.anyList())) + .thenReturn(mutationCountByPositionList); + + List mutationPositionIdentifiers = new ArrayList<>(); + MutationPositionIdentifier mutationPositionIdentifier1 = new MutationPositionIdentifier(); + mutationPositionIdentifier1.setEntrezGeneId(TEST_ENTREZ_GENE_ID_1); + mutationPositionIdentifier1.setProteinPosStart(TEST_MUTATION_PROTEIN_POS_START_1); + mutationPositionIdentifier1.setProteinPosEnd(TEST_MUTATION_PROTEIN_POS_END_1); + mutationPositionIdentifiers.add(mutationPositionIdentifier1); + MutationPositionIdentifier mutationPositionIdentifier2 = new MutationPositionIdentifier(); + mutationPositionIdentifier2.setEntrezGeneId(TEST_ENTREZ_GENE_ID_2); + mutationPositionIdentifier2.setProteinPosStart(TEST_MUTATION_PROTEIN_POS_START_2); + mutationPositionIdentifier2.setProteinPosEnd(TEST_MUTATION_PROTEIN_POS_END_2); + mutationPositionIdentifiers.add(mutationPositionIdentifier2); + + mockMvc + .perform( + MockMvcRequestBuilders.post("/api/mutation-counts-by-position/fetch") + .with(csrf()) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(mutationPositionIdentifiers))) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect( + MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.jsonPath("$", Matchers.hasSize(2))) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].entrezGeneId").value(TEST_ENTREZ_GENE_ID_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].proteinPosStart") + .value(TEST_MUTATION_PROTEIN_POS_START_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].proteinPosEnd") + .value(TEST_MUTATION_PROTEIN_POS_END_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].count").value(TEST_MUTATION_COUNT_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].entrezGeneId").value(TEST_ENTREZ_GENE_ID_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].proteinPosStart") + .value(TEST_MUTATION_PROTEIN_POS_START_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].proteinPosEnd") + .value(TEST_MUTATION_PROTEIN_POS_END_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].count").value(TEST_MUTATION_COUNT_2)); + } + + private List createExampleMutations() { + + List mutationList = new ArrayList<>(); + Mutation mutation1 = new Mutation(); + mutation1.setMolecularProfileId(TEST_MOLECULAR_PROFILE_STABLE_ID_1); + mutation1.setSampleId(TEST_SAMPLE_STABLE_ID_1); + mutation1.setEntrezGeneId(TEST_ENTREZ_GENE_ID_1); + mutation1.setCenter(TEST_CENTER_1); + mutation1.setMutationStatus(TEST_MUTATION_STATUS_1); + mutation1.setValidationStatus(TEST_VALIDATION_STATUS_1); + mutation1.setTumorAltCount(TEST_TUMOR_ALT_COUNT_1); + mutation1.setTumorRefCount(TEST_TUMOR_REF_COUNT_1); + mutation1.setNormalAltCount(TEST_NORMAL_ALT_COUNT_1); + mutation1.setNormalRefCount(TEST_NORMAL_REF_COUNT_1); + mutation1.setAminoAcidChange(TEST_AMINO_ACID_CHANGE_1); + mutation1.setStartPosition(TEST_START_POSITION_1); + mutation1.setEndPosition(TEST_END_POSITION_1); + mutation1.setReferenceAllele(TEST_REFERENCE_ALLELE_1); + mutation1.setTumorSeqAllele(TEST_TUMOR_SEQ_ALLELE_1); + mutation1.setProteinChange(TEST_PROTEIN_CHANGE_1); + mutation1.setMutationType(TEST_MUTATION_TYPE_1); + mutation1.setDriverFilter(TEST_DRIVER_FILTER_1); + mutation1.setDriverFilterAnnotation(TEST_DRIVER_FILTER_ANNOTATION_1); + mutation1.setDriverTiersFilter(TEST_DRIVER_TIERS_FILTER_1); + mutation1.setDriverTiersFilterAnnotation(TEST_DRIVER_TIERS_FILTER_ANNOTATION_1); + mutation1.setNcbiBuild(TEST_NCBI_BUILD_1); + mutation1.setVariantType(TEST_VARIANT_TYPE_1); + mutation1.setRefseqMrnaId(TEST_MUTATION_REFSEQ_MRNA_ID_1); + mutation1.setProteinPosStart(TEST_MUTATION_PROTEIN_POS_START_1); + mutation1.setProteinPosEnd(TEST_MUTATION_PROTEIN_POS_END_1); + mutation1.setKeyword(TEST_KEYWORD_1); + mutation1.setAnnotationJSON(NAME_SPACE_COLUMNS); + mutationList.add(mutation1); + Mutation mutation2 = new Mutation(); + mutation2.setMolecularProfileId(TEST_MOLECULAR_PROFILE_STABLE_ID_2); + mutation2.setSampleId(TEST_SAMPLE_STABLE_ID_2); + mutation2.setEntrezGeneId(TEST_ENTREZ_GENE_ID_2); + mutation2.setCenter(TEST_CENTER_2); + mutation2.setMutationStatus(TEST_MUTATION_STATUS_2); + mutation2.setValidationStatus(TEST_VALIDATION_STATUS_2); + mutation2.setTumorAltCount(TEST_TUMOR_ALT_COUNT_2); + mutation2.setTumorRefCount(TEST_TUMOR_REF_COUNT_2); + mutation2.setNormalAltCount(TEST_NORMAL_ALT_COUNT_2); + mutation2.setNormalRefCount(TEST_NORMAL_REF_COUNT_2); + mutation2.setAminoAcidChange(TEST_AMINO_ACID_CHANGE_2); + mutation2.setStartPosition(TEST_START_POSITION_2); + mutation2.setEndPosition(TEST_END_POSITION_2); + mutation2.setReferenceAllele(TEST_REFERENCE_ALLELE_2); + mutation2.setTumorSeqAllele(TEST_TUMOR_SEQ_ALLELE_2); + mutation2.setProteinChange(TEST_PROTEIN_CHANGE_2); + mutation2.setMutationType(TEST_MUTATION_TYPE_2); + mutation2.setDriverFilter(TEST_DRIVER_FILTER_2); + mutation2.setDriverFilterAnnotation(TEST_DRIVER_FILTER_ANNOTATION_2); + mutation2.setDriverTiersFilter(TEST_DRIVER_TIERS_FILTER_2); + mutation2.setDriverTiersFilterAnnotation(TEST_DRIVER_TIERS_FILTER_ANNOTATION_2); + mutation2.setNcbiBuild(TEST_NCBI_BUILD_2); + mutation2.setVariantType(TEST_VARIANT_TYPE_2); + mutation2.setRefseqMrnaId(TEST_MUTATION_REFSEQ_MRNA_ID_2); + mutation2.setProteinPosStart(TEST_MUTATION_PROTEIN_POS_START_2); + mutation2.setProteinPosEnd(TEST_MUTATION_PROTEIN_POS_END_2); + mutation2.setKeyword(TEST_KEYWORD_2); + mutation2.setAnnotationJSON(NAME_SPACE_COLUMNS); + mutationList.add(mutation2); + + return mutationList; + } + + private List createExampleMutationsWithGeneAndAlleleSpecificCopyNumber() { + + List mutationList = createExampleMutations(); + Gene gene1 = new Gene(); + gene1.setEntrezGeneId(TEST_ENTREZ_GENE_ID_1); + gene1.setHugoGeneSymbol(TEST_HUGO_GENE_SYMBOL_1); + gene1.setType(TEST_TYPE_1); + AlleleSpecificCopyNumber alleleSpecificCopyNumber1 = new AlleleSpecificCopyNumber(); + alleleSpecificCopyNumber1.setAscnIntegerCopyNumber(3); + alleleSpecificCopyNumber1.setAscnMethod("FACETS"); + alleleSpecificCopyNumber1.setCcfExpectedCopiesUpper(1.25f); + alleleSpecificCopyNumber1.setCcfExpectedCopies(1.75f); + alleleSpecificCopyNumber1.setClonal("CLONAL"); + alleleSpecificCopyNumber1.setMinorCopyNumber(2); + alleleSpecificCopyNumber1.setExpectedAltCopies(1); + alleleSpecificCopyNumber1.setTotalCopyNumber(4); + mutationList.get(0).setGene(gene1); + mutationList.get(0).setAlleleSpecificCopyNumber(alleleSpecificCopyNumber1); + Gene gene2 = new Gene(); + gene2.setEntrezGeneId(TEST_ENTREZ_GENE_ID_2); + gene2.setHugoGeneSymbol(TEST_HUGO_GENE_SYMBOL_2); + gene2.setType(TEST_TYPE_2); + AlleleSpecificCopyNumber alleleSpecificCopyNumber2 = new AlleleSpecificCopyNumber(); + alleleSpecificCopyNumber2.setAscnIntegerCopyNumber(2); + alleleSpecificCopyNumber2.setAscnMethod("ASCN_METHOD2"); + alleleSpecificCopyNumber2.setCcfExpectedCopiesUpper(1.5f); + alleleSpecificCopyNumber2.setCcfExpectedCopies(1.95f); + alleleSpecificCopyNumber2.setClonal("SUBCLONAL"); + alleleSpecificCopyNumber2.setMinorCopyNumber(1); + alleleSpecificCopyNumber2.setExpectedAltCopies(1); + alleleSpecificCopyNumber2.setTotalCopyNumber(2); + mutationList.get(1).setGene(gene2); + mutationList.get(1).setAlleleSpecificCopyNumber(alleleSpecificCopyNumber2); + return mutationList; + } +} diff --git a/src/test/java/org/cbioportal/legacy/web/MutationCountControllerTest.java b/src/test/java/org/cbioportal/legacy/web/MutationCountControllerTest.java new file mode 100644 index 00000000000..d0bb38da2a5 --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/web/MutationCountControllerTest.java @@ -0,0 +1,110 @@ +package org.cbioportal.legacy.web; + +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; + +import com.fasterxml.jackson.databind.ObjectMapper; +import java.util.ArrayList; +import java.util.List; +import org.cbioportal.legacy.model.MutationCountByPosition; +import org.cbioportal.legacy.service.MutationService; +import org.cbioportal.legacy.web.config.TestConfig; +import org.cbioportal.legacy.web.parameter.MutationPositionIdentifier; +import org.hamcrest.Matchers; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mockito; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; +import org.springframework.security.test.context.support.WithMockUser; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.result.MockMvcResultMatchers; + +@RunWith(SpringJUnit4ClassRunner.class) +@WebMvcTest +@ContextConfiguration(classes = {MutationCountController.class, TestConfig.class}) +public class MutationCountControllerTest { + + private static final int TEST_ENTREZ_GENE_ID_1 = 1; + private static final int TEST_ONCOTATOR_PROTEIN_POS_START_1 = 1; + private static final int TEST_ONCOTATOR_PROTEIN_POS_END_1 = 1; + private static final int TEST_ENTREZ_GENE_ID_2 = 2; + private static final int TEST_ONCOTATOR_PROTEIN_POS_START_2 = 2; + private static final int TEST_ONCOTATOR_PROTEIN_POS_END_2 = 2; + private static final int TEST_MUTATION_COUNT_1 = 100; + private static final int TEST_MUTATION_COUNT_2 = 200; + + @MockBean private MutationService mutationService; + + private ObjectMapper objectMapper = new ObjectMapper(); + + @Autowired private MockMvc mockMvc; + + @Test + @WithMockUser + public void fetchMutationCountsByPosition() throws Exception { + + List mutationCountByPositionList = new ArrayList<>(); + MutationCountByPosition mutationCountByPosition1 = new MutationCountByPosition(); + mutationCountByPosition1.setEntrezGeneId(TEST_ENTREZ_GENE_ID_1); + mutationCountByPosition1.setProteinPosStart(TEST_ONCOTATOR_PROTEIN_POS_START_1); + mutationCountByPosition1.setProteinPosEnd(TEST_ONCOTATOR_PROTEIN_POS_END_1); + mutationCountByPosition1.setCount(TEST_MUTATION_COUNT_1); + mutationCountByPositionList.add(mutationCountByPosition1); + MutationCountByPosition mutationCountByPosition2 = new MutationCountByPosition(); + mutationCountByPosition2.setEntrezGeneId(TEST_ENTREZ_GENE_ID_2); + mutationCountByPosition2.setProteinPosStart(TEST_ONCOTATOR_PROTEIN_POS_START_2); + mutationCountByPosition2.setProteinPosEnd(TEST_ONCOTATOR_PROTEIN_POS_END_2); + mutationCountByPosition2.setCount(TEST_MUTATION_COUNT_2); + mutationCountByPositionList.add(mutationCountByPosition2); + + Mockito.when( + mutationService.fetchMutationCountsByPosition( + Mockito.anyList(), Mockito.anyList(), Mockito.anyList())) + .thenReturn(mutationCountByPositionList); + + List mutationPositionIdentifiers = new ArrayList<>(); + MutationPositionIdentifier mutationPositionIdentifier1 = new MutationPositionIdentifier(); + mutationPositionIdentifier1.setEntrezGeneId(TEST_ENTREZ_GENE_ID_1); + mutationPositionIdentifier1.setProteinPosStart(TEST_ONCOTATOR_PROTEIN_POS_START_1); + mutationPositionIdentifier1.setProteinPosEnd(TEST_ONCOTATOR_PROTEIN_POS_END_1); + mutationPositionIdentifiers.add(mutationPositionIdentifier1); + MutationPositionIdentifier mutationPositionIdentifier2 = new MutationPositionIdentifier(); + mutationPositionIdentifier2.setEntrezGeneId(TEST_ENTREZ_GENE_ID_2); + mutationPositionIdentifier2.setProteinPosStart(TEST_ONCOTATOR_PROTEIN_POS_START_2); + mutationPositionIdentifier2.setProteinPosEnd(TEST_ONCOTATOR_PROTEIN_POS_END_2); + mutationPositionIdentifiers.add(mutationPositionIdentifier2); + + mockMvc + .perform( + MockMvcRequestBuilders.post("/api/mutation-counts-by-position/fetch") + .with(csrf()) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(mutationPositionIdentifiers))) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect( + MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.jsonPath("$", Matchers.hasSize(2))) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].entrezGeneId").value(TEST_ENTREZ_GENE_ID_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].proteinPosStart") + .value(TEST_ONCOTATOR_PROTEIN_POS_START_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].proteinPosEnd") + .value(TEST_ONCOTATOR_PROTEIN_POS_END_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].count").value(TEST_MUTATION_COUNT_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].entrezGeneId").value(TEST_ENTREZ_GENE_ID_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].proteinPosStart") + .value(TEST_ONCOTATOR_PROTEIN_POS_START_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].proteinPosEnd") + .value(TEST_ONCOTATOR_PROTEIN_POS_END_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].count").value(TEST_MUTATION_COUNT_2)); + } +} diff --git a/src/test/java/org/cbioportal/legacy/web/MutationSpectrumControllerTest.java b/src/test/java/org/cbioportal/legacy/web/MutationSpectrumControllerTest.java new file mode 100644 index 00000000000..39d538595bc --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/web/MutationSpectrumControllerTest.java @@ -0,0 +1,122 @@ +package org.cbioportal.legacy.web; + +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; + +import com.fasterxml.jackson.databind.ObjectMapper; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import org.cbioportal.legacy.model.MutationSpectrum; +import org.cbioportal.legacy.service.MutationSpectrumService; +import org.cbioportal.legacy.web.config.TestConfig; +import org.cbioportal.legacy.web.parameter.MutationSpectrumFilter; +import org.hamcrest.Matchers; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mockito; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; +import org.springframework.security.test.context.support.WithMockUser; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.result.MockMvcResultMatchers; + +@RunWith(SpringJUnit4ClassRunner.class) +@WebMvcTest +@ContextConfiguration(classes = {MutationSpectrumController.class, TestConfig.class}) +public class MutationSpectrumControllerTest { + + private static final String TEST_MOLECULAR_PROFILE_ID = "test_molecular_profile_id"; + private static final String TEST_SAMPLE_ID_1 = "test_sample_id_1"; + private static final String TEST_SAMPLE_ID_2 = "test_sample_id_2"; + private static final int TEST_C_TO_A_1 = 1; + private static final int TEST_C_TO_G_1 = 2; + private static final int TEST_C_TO_T_1 = 3; + private static final int TEST_T_TO_A_1 = 4; + private static final int TEST_T_TO_C_1 = 5; + private static final int TEST_T_TO_G_1 = 6; + private static final int TEST_C_TO_A_2 = 3; + private static final int TEST_C_TO_G_2 = 4; + private static final int TEST_C_TO_T_2 = 5; + private static final int TEST_T_TO_A_2 = 6; + private static final int TEST_T_TO_C_2 = 1; + private static final int TEST_T_TO_G_2 = 2; + + @MockBean private MutationSpectrumService mutationSpectrumService; + + private ObjectMapper objectMapper = new ObjectMapper(); + + @Autowired private MockMvc mockMvc; + + @Test + @WithMockUser + public void fetchMutationSpectrums() throws Exception { + + List mutationSpectrumList = new ArrayList<>(); + MutationSpectrum mutationSpectrum1 = new MutationSpectrum(); + mutationSpectrum1.setMolecularProfileId(TEST_MOLECULAR_PROFILE_ID); + mutationSpectrum1.setSampleId(TEST_SAMPLE_ID_1); + mutationSpectrum1.setCtoA(TEST_C_TO_A_1); + mutationSpectrum1.setCtoG(TEST_C_TO_G_1); + mutationSpectrum1.setCtoT(TEST_C_TO_T_1); + mutationSpectrum1.setTtoA(TEST_T_TO_A_1); + mutationSpectrum1.setTtoC(TEST_T_TO_C_1); + mutationSpectrum1.setTtoG(TEST_T_TO_G_1); + mutationSpectrumList.add(mutationSpectrum1); + MutationSpectrum mutationSpectrum2 = new MutationSpectrum(); + mutationSpectrum2.setMolecularProfileId(TEST_MOLECULAR_PROFILE_ID); + mutationSpectrum2.setSampleId(TEST_SAMPLE_ID_2); + mutationSpectrum2.setCtoA(TEST_C_TO_A_2); + mutationSpectrum2.setCtoG(TEST_C_TO_G_2); + mutationSpectrum2.setCtoT(TEST_C_TO_T_2); + mutationSpectrum2.setTtoA(TEST_T_TO_A_2); + mutationSpectrum2.setTtoC(TEST_T_TO_C_2); + mutationSpectrum2.setTtoG(TEST_T_TO_G_2); + mutationSpectrumList.add(mutationSpectrum2); + + Mockito.when( + mutationSpectrumService.fetchMutationSpectrums( + TEST_MOLECULAR_PROFILE_ID, Arrays.asList(TEST_SAMPLE_ID_1, TEST_SAMPLE_ID_2))) + .thenReturn(mutationSpectrumList); + + MutationSpectrumFilter mutationSpectrumFilter = new MutationSpectrumFilter(); + mutationSpectrumFilter.setSampleIds(Arrays.asList(TEST_SAMPLE_ID_1, TEST_SAMPLE_ID_2)); + + mockMvc + .perform( + MockMvcRequestBuilders.post( + "/api/molecular-profiles/test_molecular_profile_id/mutation-spectrums/fetch") + .with(csrf()) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(mutationSpectrumFilter))) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect( + MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.jsonPath("$", Matchers.hasSize(2))) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].molecularProfileId") + .value(TEST_MOLECULAR_PROFILE_ID)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].sampleId").value(TEST_SAMPLE_ID_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].CtoA").value(TEST_C_TO_A_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].CtoG").value(TEST_C_TO_G_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].CtoT").value(TEST_C_TO_T_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].TtoA").value(TEST_T_TO_A_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].TtoC").value(TEST_T_TO_C_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].TtoG").value(TEST_T_TO_G_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].molecularProfileId") + .value(TEST_MOLECULAR_PROFILE_ID)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].sampleId").value(TEST_SAMPLE_ID_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].CtoA").value(TEST_C_TO_A_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].CtoG").value(TEST_C_TO_G_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].CtoT").value(TEST_C_TO_T_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].TtoA").value(TEST_T_TO_A_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].TtoC").value(TEST_T_TO_C_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].TtoG").value(TEST_T_TO_G_2)); + } +} diff --git a/src/test/java/org/cbioportal/legacy/web/NamespaceAttributeControllerTest.java b/src/test/java/org/cbioportal/legacy/web/NamespaceAttributeControllerTest.java new file mode 100644 index 00000000000..abc9be543d1 --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/web/NamespaceAttributeControllerTest.java @@ -0,0 +1,96 @@ +package org.cbioportal.legacy.web; + +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; + +import com.fasterxml.jackson.databind.ObjectMapper; +import java.util.ArrayList; +import java.util.List; +import org.cbioportal.legacy.model.NamespaceAttribute; +import org.cbioportal.legacy.service.NamespaceAttributeService; +import org.cbioportal.legacy.web.config.TestConfig; +import org.hamcrest.Matchers; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mockito; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; +import org.springframework.security.test.context.support.WithMockUser; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.result.MockMvcResultMatchers; + +@RunWith(SpringJUnit4ClassRunner.class) +@WebMvcTest +@ContextConfiguration(classes = {NamespaceAttributeController.class, TestConfig.class}) +public class NamespaceAttributeControllerTest { + + private static final String TEST_OUTER_KEY_1 = "test_outer_key_1"; + private static final String TEST_INNER_KEY_1 = "test_inner_key_1"; + private static final String TEST_OUTER_KEY_2 = "test_outer_key_2"; + private static final String TEST_INNER_KEY_2 = "test_inner_key_2"; + + @MockBean private NamespaceAttributeService namespaceAttributeService; + + private ObjectMapper objectMapper = new ObjectMapper(); + + @Autowired private MockMvc mockMvc; + + @Test + @WithMockUser + public void fetchNamespaceAttributes() throws Exception { + + List namespaceAttributes = createExampleNamespaceAttributes(); + + Mockito.when(namespaceAttributeService.fetchNamespaceAttributes(Mockito.anyList())) + .thenReturn(namespaceAttributes); + + List studyIds = new ArrayList<>(); + studyIds.add("study_id_1"); + studyIds.add("study_id_2"); + + mockMvc + .perform( + MockMvcRequestBuilders.post("/api/namespace-attributes/fetch") + .with(csrf()) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(studyIds))) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect( + MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.jsonPath("$", Matchers.hasSize(2))) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].outerKey").value(TEST_OUTER_KEY_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].innerKey").value(TEST_INNER_KEY_1)); + } + + @Test + @WithMockUser + public void fetchNamespaceAttributesEmptyBody() throws Exception { + mockMvc + .perform( + MockMvcRequestBuilders.post("/api/namespace-attributes/fetch") + .with(csrf()) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + .content("")) + .andExpect(MockMvcResultMatchers.status().isBadRequest()); + } + + private List createExampleNamespaceAttributes() { + + List namespaceAttributes = new ArrayList<>(); + NamespaceAttribute namespaceAttribute1 = new NamespaceAttribute(); + namespaceAttribute1.setOuterKey(TEST_OUTER_KEY_1); + namespaceAttribute1.setInnerKey(TEST_INNER_KEY_1); + namespaceAttributes.add(namespaceAttribute1); + NamespaceAttribute namespaceAttribute2 = new NamespaceAttribute(); + namespaceAttribute2.setOuterKey(TEST_OUTER_KEY_2); + namespaceAttribute2.setInnerKey(TEST_INNER_KEY_2); + namespaceAttributes.add(namespaceAttribute2); + return namespaceAttributes; + } +} diff --git a/src/test/java/org/cbioportal/legacy/web/NamespaceAttributeCountControllerTest.java b/src/test/java/org/cbioportal/legacy/web/NamespaceAttributeCountControllerTest.java new file mode 100644 index 00000000000..a772764f3ac --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/web/NamespaceAttributeCountControllerTest.java @@ -0,0 +1,127 @@ +package org.cbioportal.legacy.web; + +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; + +import com.fasterxml.jackson.databind.ObjectMapper; +import java.util.ArrayList; +import java.util.List; +import org.cbioportal.legacy.model.NamespaceAttribute; +import org.cbioportal.legacy.model.NamespaceAttributeCount; +import org.cbioportal.legacy.service.NamespaceAttributeService; +import org.cbioportal.legacy.web.config.TestConfig; +import org.cbioportal.legacy.web.parameter.NamespaceAttributeCountFilter; +import org.cbioportal.legacy.web.parameter.SampleIdentifier; +import org.hamcrest.Matchers; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mockito; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; +import org.springframework.security.test.context.support.WithMockUser; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.result.MockMvcResultMatchers; + +@RunWith(SpringJUnit4ClassRunner.class) +@WebMvcTest +@ContextConfiguration(classes = {NamespaceAttributeCountController.class, TestConfig.class}) +public class NamespaceAttributeCountControllerTest { + + private static final String TEST_OUTER_KEY_1 = "test_outer_key_1"; + private static final String TEST_INNER_KEY_1 = "test_inner_key_1"; + private static final String TEST_CANCER_STUDY_IDENTIFIER_1 = "test_study_1"; + private static final String TEST_SAMPLE_ID_1 = "test_sample_id_1"; + private static final Integer TEST_COUNT_1 = 1; + private static final String TEST_OUTER_KEY_2 = "test_outer_key_2"; + private static final String TEST_INNER_KEY_2 = "test_inner_key_2"; + private static final String TEST_CANCER_STUDY_IDENTIFIER_2 = "test_study_2"; + private static final String TEST_SAMPLE_ID_2 = "test_sample_id_2"; + private static final Integer TEST_COUNT_2 = 2; + + @MockBean private NamespaceAttributeService namespaceAttributeService; + + private ObjectMapper objectMapper = new ObjectMapper(); + + @Autowired private MockMvc mockMvc; + + @Test + @WithMockUser + public void getNamespaceAttributeCountsBySampleIds() throws Exception { + + List namespaceAttributeCounts = + createExampleNamespaceAttributeCounts(); + + Mockito.when( + namespaceAttributeService.fetchNamespaceAttributeCountsBySampleIds( + Mockito.any(), Mockito.any(), Mockito.any())) + .thenReturn(namespaceAttributeCounts); + + NamespaceAttributeCountFilter namespaceAttributeCountFilter = + createExampleNamespaceAttributeCountFilter(); + + mockMvc + .perform( + MockMvcRequestBuilders.post("/api/namespace-attributes/counts/fetch") + .with(csrf()) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(namespaceAttributeCountFilter))) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect( + MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.jsonPath("$", Matchers.hasSize(2))) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].outerKey").value(TEST_OUTER_KEY_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].innerKey").value(TEST_INNER_KEY_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].count").value(TEST_COUNT_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].outerKey").value(TEST_OUTER_KEY_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].innerKey").value(TEST_INNER_KEY_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].count").value(TEST_COUNT_2)); + } + + private List createExampleNamespaceAttributeCounts() { + + List namespaceAttributeCounts = new ArrayList<>(); + NamespaceAttributeCount namespaceAttributeCount1 = new NamespaceAttributeCount(); + namespaceAttributeCount1.setOuterKey(TEST_OUTER_KEY_1); + namespaceAttributeCount1.setInnerKey(TEST_INNER_KEY_1); + namespaceAttributeCount1.setCount(TEST_COUNT_1); + namespaceAttributeCounts.add(namespaceAttributeCount1); + NamespaceAttributeCount namespaceAttributeCount2 = new NamespaceAttributeCount(); + namespaceAttributeCount2.setOuterKey(TEST_OUTER_KEY_2); + namespaceAttributeCount2.setInnerKey(TEST_INNER_KEY_2); + namespaceAttributeCount2.setCount(TEST_COUNT_2); + namespaceAttributeCounts.add(namespaceAttributeCount2); + return namespaceAttributeCounts; + } + + private NamespaceAttributeCountFilter createExampleNamespaceAttributeCountFilter() { + + NamespaceAttributeCountFilter namespaceAttributeCountFilter = + new NamespaceAttributeCountFilter(); + List sampleIdentifierList = new ArrayList<>(); + SampleIdentifier sampleIdentifier1 = new SampleIdentifier(); + sampleIdentifier1.setSampleId(TEST_SAMPLE_ID_1); + sampleIdentifier1.setStudyId(TEST_CANCER_STUDY_IDENTIFIER_1); + sampleIdentifierList.add(sampleIdentifier1); + SampleIdentifier sampleIdentifier2 = new SampleIdentifier(); + sampleIdentifier2.setSampleId(TEST_SAMPLE_ID_2); + sampleIdentifier2.setStudyId(TEST_CANCER_STUDY_IDENTIFIER_2); + sampleIdentifierList.add(sampleIdentifier2); + namespaceAttributeCountFilter.setSampleIdentifiers(sampleIdentifierList); + List namespaceAttributes = new ArrayList<>(); + NamespaceAttribute namespaceAttribute1 = new NamespaceAttribute(); + namespaceAttribute1.setOuterKey(TEST_OUTER_KEY_1); + namespaceAttribute1.setInnerKey(TEST_INNER_KEY_1); + namespaceAttributes.add(namespaceAttribute1); + NamespaceAttribute namespaceAttribute2 = new NamespaceAttribute(); + namespaceAttribute2.setOuterKey(TEST_OUTER_KEY_2); + namespaceAttribute2.setInnerKey(TEST_INNER_KEY_2); + namespaceAttributes.add(namespaceAttribute2); + namespaceAttributeCountFilter.setNamespaceAttributes(namespaceAttributes); + return namespaceAttributeCountFilter; + } +} diff --git a/src/test/java/org/cbioportal/legacy/web/NamespaceDataControllerTest.java b/src/test/java/org/cbioportal/legacy/web/NamespaceDataControllerTest.java new file mode 100644 index 00000000000..ab5180f34c9 --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/web/NamespaceDataControllerTest.java @@ -0,0 +1,130 @@ +package org.cbioportal.legacy.web; + +import static org.mockito.Mockito.*; +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; + +import com.fasterxml.jackson.databind.ObjectMapper; +import java.util.ArrayList; +import java.util.List; +import org.cbioportal.legacy.model.NamespaceAttribute; +import org.cbioportal.legacy.model.NamespaceData; +import org.cbioportal.legacy.service.NamespaceDataService; +import org.cbioportal.legacy.web.config.CustomObjectMapper; +import org.cbioportal.legacy.web.config.TestConfig; +import org.cbioportal.legacy.web.parameter.NamespaceComparisonFilter; +import org.cbioportal.legacy.web.parameter.SampleIdentifier; +import org.hamcrest.Matchers; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; +import org.springframework.security.test.context.support.WithMockUser; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.result.MockMvcResultMatchers; + +@RunWith(SpringJUnit4ClassRunner.class) +@WebMvcTest +@ContextConfiguration(classes = {NamespaceDataController.class, TestConfig.class}) +public class NamespaceDataControllerTest { + + private static final String TEST_OUTER_KEY_1 = "test_outer_key_1"; + private static final String TEST_INNER_KEY_1 = "test_inner_key_1"; + private static final String TEST_ATTR_VALUE_1 = "test_attr_value_1"; + private static final String TEST_ATTR_VALUE_2 = "test_attr_value_2"; + private static final String TEST_CANCER_STUDY_IDENTIFIER_1 = "test_study_1"; + private static final String TEST_SAMPLE_ID_1 = "test_sample_id_1"; + private static final String TEST_OUTER_KEY_2 = "test_outer_key_2"; + private static final String TEST_INNER_KEY_2 = "test_inner_key_2"; + private static final String TEST_CANCER_STUDY_IDENTIFIER_2 = "test_study_2"; + private static final String TEST_SAMPLE_ID_2 = "test_sample_id_2"; + + @MockBean private NamespaceDataService namespaceDataService; + + private ObjectMapper objectMapper = new CustomObjectMapper(); + + @Autowired private MockMvc mockMvc; + + @Test + @WithMockUser + public void fetchNamespaceDataForComparison() throws Exception { + + List namespaceData = createExampleNamespaceData(); + + when(namespaceDataService.fetchNamespaceDataForComparison(any(), any(), any(), any())) + .thenReturn(namespaceData); + + NamespaceComparisonFilter namespaceComparisonFilter = createExampleNamespaceComparisonFilter(); + + mockMvc + .perform( + MockMvcRequestBuilders.post("/api/namespace-data/fetch") + .with(csrf()) + .param("namespaceDataType", "PATIENT") + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(namespaceComparisonFilter))) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect( + MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.jsonPath("$", Matchers.hasSize(2))) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].outerKey").value(TEST_OUTER_KEY_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].innerKey").value(TEST_INNER_KEY_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].attrValue").value(TEST_ATTR_VALUE_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].sampleId").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].patientId").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].studyId").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].outerKey").value(TEST_OUTER_KEY_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].innerKey").value(TEST_INNER_KEY_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].attrValue").value(TEST_ATTR_VALUE_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].sampleId").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].patientId").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].studyId").doesNotExist()); + } + + private List createExampleNamespaceData() { + + List namespaceData = new ArrayList<>(); + NamespaceData namespaceData1 = new NamespaceData(); + namespaceData1.setOuterKey(TEST_OUTER_KEY_1); + namespaceData1.setInnerKey(TEST_INNER_KEY_1); + String attrValue1 = TEST_ATTR_VALUE_1; + namespaceData1.setAttrValue(attrValue1); + namespaceData.add(namespaceData1); + NamespaceData namespaceData2 = new NamespaceData(); + namespaceData2.setOuterKey(TEST_OUTER_KEY_2); + namespaceData2.setInnerKey(TEST_INNER_KEY_2); + String attrValue2 = TEST_ATTR_VALUE_2; + namespaceData2.setAttrValue(attrValue2); + namespaceData.add(namespaceData2); + return namespaceData; + } + + private NamespaceComparisonFilter createExampleNamespaceComparisonFilter() { + + NamespaceComparisonFilter namespaceComparisonFilter = new NamespaceComparisonFilter(); + List sampleIdentifierList = new ArrayList<>(); + SampleIdentifier sampleIdentifier1 = new SampleIdentifier(); + sampleIdentifier1.setSampleId(TEST_SAMPLE_ID_1); + sampleIdentifier1.setStudyId(TEST_CANCER_STUDY_IDENTIFIER_1); + sampleIdentifierList.add(sampleIdentifier1); + SampleIdentifier sampleIdentifier2 = new SampleIdentifier(); + sampleIdentifier2.setSampleId(TEST_SAMPLE_ID_2); + sampleIdentifier2.setStudyId(TEST_CANCER_STUDY_IDENTIFIER_2); + sampleIdentifierList.add(sampleIdentifier2); + namespaceComparisonFilter.setSampleIdentifiers(sampleIdentifierList); + NamespaceAttribute namespaceAttribute = new NamespaceAttribute(); + namespaceAttribute.setOuterKey(TEST_OUTER_KEY_1); + namespaceAttribute.setInnerKey(TEST_INNER_KEY_1); + namespaceComparisonFilter.setNamespaceAttribute(namespaceAttribute); + List values = new ArrayList<>(); + values.add(TEST_ATTR_VALUE_1); + values.add(TEST_ATTR_VALUE_2); + namespaceComparisonFilter.setValues(values); + return namespaceComparisonFilter; + } +} diff --git a/src/test/java/org/cbioportal/legacy/web/PatientControllerTest.java b/src/test/java/org/cbioportal/legacy/web/PatientControllerTest.java new file mode 100644 index 00000000000..56055e3d9f8 --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/web/PatientControllerTest.java @@ -0,0 +1,351 @@ +package org.cbioportal.legacy.web; + +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; + +import com.fasterxml.jackson.databind.ObjectMapper; +import java.util.ArrayList; +import java.util.List; +import org.cbioportal.legacy.model.CancerStudy; +import org.cbioportal.legacy.model.Patient; +import org.cbioportal.legacy.model.meta.BaseMeta; +import org.cbioportal.legacy.service.PatientService; +import org.cbioportal.legacy.service.exception.PatientNotFoundException; +import org.cbioportal.legacy.web.config.TestConfig; +import org.cbioportal.legacy.web.parameter.HeaderKeyConstants; +import org.cbioportal.legacy.web.parameter.PatientFilter; +import org.cbioportal.legacy.web.parameter.PatientIdentifier; +import org.hamcrest.Matchers; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mockito; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; +import org.springframework.security.test.context.support.WithMockUser; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.result.MockMvcResultMatchers; + +@RunWith(SpringJUnit4ClassRunner.class) +@WebMvcTest +@ContextConfiguration(classes = {PatientController.class, TestConfig.class}) +public class PatientControllerTest { + + private static final int TEST_INTERNAL_ID_1 = 1; + private static final String TEST_STABLE_ID_1 = "test_stable_id_1"; + private static final int TEST_CANCER_STUDY_ID_1 = 1; + private static final String TEST_CANCER_STUDY_IDENTIFIER_1 = "test_study_1"; + private static final int TEST_INTERNAL_ID_2 = 2; + private static final String TEST_STABLE_ID_2 = "test_stable_id_2"; + private static final int TEST_CANCER_STUDY_ID_2 = 2; + private static final String TEST_CANCER_STUDY_IDENTIFIER_2 = "test_study_2"; + private static final String TEST_TYPE_OF_CANCER_ID_1 = "test_type_of_cancer_id_1"; + private static final String TEST_NAME_1 = "test_name_1"; + private static final String TEST_SHORT_NAME_1 = "test_short_name_1"; + private static final String TEST_DESCRIPTION_1 = "test_description_1"; + + @MockBean private PatientService patientService; + + private ObjectMapper objectMapper = new ObjectMapper(); + + @Autowired private MockMvc mockMvc; + + @Test + @WithMockUser + public void getAllPatientsDefaultProjection() throws Exception { + + List patientList = createExamplePatients(); + + Mockito.when( + patientService.getAllPatients( + Mockito.any(), + Mockito.any(), + Mockito.any(), + Mockito.any(), + Mockito.any(), + Mockito.any())) + .thenReturn(patientList); + + mockMvc + .perform(MockMvcRequestBuilders.get("/api/patients").accept(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect( + MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.jsonPath("$", Matchers.hasSize(2))) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].internalId").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].patientId").value(TEST_STABLE_ID_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].studyId").value(TEST_CANCER_STUDY_IDENTIFIER_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].cancerStudyIdentifier").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].cancerStudy").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].internalId").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].patientId").value(TEST_STABLE_ID_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].studyId").value(TEST_CANCER_STUDY_IDENTIFIER_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].cancerStudyIdentifier").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].cancerStudy").doesNotExist()); + } + + @Test + @WithMockUser + public void getAllPatientsMetaProjection() throws Exception { + + BaseMeta baseMeta = new BaseMeta(); + baseMeta.setTotalCount(2); + + Mockito.when(patientService.getMetaPatients(Mockito.any())).thenReturn(baseMeta); + + mockMvc + .perform(MockMvcRequestBuilders.get("/api/patients").param("projection", "META")) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect(MockMvcResultMatchers.header().string(HeaderKeyConstants.TOTAL_COUNT, "2")); + } + + @Test + @WithMockUser + public void getAllPatientsInStudyDefaultProjection() throws Exception { + + List patientList = createExamplePatients(); + + Mockito.when( + patientService.getAllPatientsInStudy( + Mockito.any(), + Mockito.any(), + Mockito.any(), + Mockito.any(), + Mockito.any(), + Mockito.any())) + .thenReturn(patientList); + + mockMvc + .perform( + MockMvcRequestBuilders.get("/api/studies/test_study_id/patients") + .accept(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect( + MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.jsonPath("$", Matchers.hasSize(2))) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].internalId").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].patientId").value(TEST_STABLE_ID_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].studyId").value(TEST_CANCER_STUDY_IDENTIFIER_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].cancerStudyIdentifier").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].cancerStudy").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].internalId").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].patientId").value(TEST_STABLE_ID_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].studyId").value(TEST_CANCER_STUDY_IDENTIFIER_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].cancerStudyIdentifier").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].cancerStudy").doesNotExist()); + } + + @Test + @WithMockUser + public void getAllPatientsInStudyMetaProjection() throws Exception { + + BaseMeta baseMeta = new BaseMeta(); + baseMeta.setTotalCount(2); + + Mockito.when(patientService.getMetaPatientsInStudy(Mockito.anyString())).thenReturn(baseMeta); + + mockMvc + .perform( + MockMvcRequestBuilders.get("/api/studies/test_study_id/patients") + .param("projection", "META")) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect(MockMvcResultMatchers.header().string(HeaderKeyConstants.TOTAL_COUNT, "2")); + } + + @Test + @WithMockUser + public void getPatientInStudyNotFound() throws Exception { + + Mockito.when(patientService.getPatientInStudy(Mockito.anyString(), Mockito.anyString())) + .thenThrow(new PatientNotFoundException("test_study_id", "test_patient_id")); + + mockMvc + .perform( + MockMvcRequestBuilders.get("/api/studies/test_study_id/patients/test_patient_id") + .accept(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.status().isNotFound()) + .andExpect( + MockMvcResultMatchers.jsonPath("$.message") + .value("Patient not found in study test_study_id: test_patient_id")); + } + + @Test + @WithMockUser + public void getPatientInStudy() throws Exception { + + Patient patient = new Patient(); + patient.setInternalId(TEST_INTERNAL_ID_1); + patient.setStableId(TEST_STABLE_ID_1); + patient.setCancerStudyId(TEST_CANCER_STUDY_ID_1); + patient.setCancerStudyIdentifier(TEST_CANCER_STUDY_IDENTIFIER_1); + CancerStudy cancerStudy = new CancerStudy(); + cancerStudy.setCancerStudyId(TEST_CANCER_STUDY_ID_1); + cancerStudy.setCancerStudyIdentifier(TEST_CANCER_STUDY_IDENTIFIER_1); + cancerStudy.setTypeOfCancerId(TEST_TYPE_OF_CANCER_ID_1); + cancerStudy.setName(TEST_NAME_1); + cancerStudy.setDescription(TEST_DESCRIPTION_1); + patient.setCancerStudy(cancerStudy); + + Mockito.when(patientService.getPatientInStudy(Mockito.anyString(), Mockito.anyString())) + .thenReturn(patient); + + mockMvc + .perform( + MockMvcRequestBuilders.get("/api/studies/test_study_id/patients/test_patient_id") + .accept(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect( + MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.jsonPath("$.internalId").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$.patientId").value(TEST_STABLE_ID_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$.studyId").value(TEST_CANCER_STUDY_IDENTIFIER_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$.cancerStudyIdentifier").doesNotExist()); + } + + @Test + @WithMockUser + public void fetchPatientsDefaultProjection() throws Exception { + + List patientList = createExamplePatients(); + + Mockito.when( + patientService.fetchPatients(Mockito.anyList(), Mockito.anyList(), Mockito.anyString())) + .thenReturn(patientList); + + PatientFilter patientFilter = new PatientFilter(); + List patientIdentifiers = new ArrayList<>(); + PatientIdentifier patientIdentifier1 = new PatientIdentifier(); + patientIdentifier1.setStudyId(TEST_CANCER_STUDY_IDENTIFIER_1); + patientIdentifier1.setPatientId(TEST_STABLE_ID_1); + patientIdentifiers.add(patientIdentifier1); + PatientIdentifier patientIdentifier2 = new PatientIdentifier(); + patientIdentifier2.setStudyId(TEST_CANCER_STUDY_IDENTIFIER_2); + patientIdentifier2.setPatientId(TEST_STABLE_ID_2); + patientIdentifiers.add(patientIdentifier2); + patientFilter.setPatientIdentifiers(patientIdentifiers); + + mockMvc + .perform( + MockMvcRequestBuilders.post("/api/patients/fetch") + .with(csrf()) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(patientFilter))) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect( + MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.jsonPath("$", Matchers.hasSize(2))) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].internalId").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].patientId").value(TEST_STABLE_ID_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].studyId").value(TEST_CANCER_STUDY_IDENTIFIER_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].cancerStudyIdentifier").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].cancerStudy").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].internalId").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].patientId").value(TEST_STABLE_ID_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].studyId").value(TEST_CANCER_STUDY_IDENTIFIER_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].cancerStudyIdentifier").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].cancerStudy").doesNotExist()); + } + + @Test + @WithMockUser + public void fetchPatientsByUniquePatientKeysDefaultProjection() throws Exception { + + List patientList = createExamplePatients(); + + Mockito.when( + patientService.fetchPatients(Mockito.anyList(), Mockito.anyList(), Mockito.anyString())) + .thenReturn(patientList); + + PatientFilter patientFilter = new PatientFilter(); + List uniquePatientKeys = new ArrayList<>(); + uniquePatientKeys.add("dGVzdF9zdGFibGVfaWRfMTp0ZXN0X3N0dWR5XzE"); + uniquePatientKeys.add("dGVzdF9zdGFibGVfaWRfMjp0ZXN0X3N0dWR5XzI"); + patientFilter.setUniquePatientKeys(uniquePatientKeys); + + mockMvc + .perform( + MockMvcRequestBuilders.post("/api/patients/fetch") + .with(csrf()) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(patientFilter))) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect( + MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.jsonPath("$", Matchers.hasSize(2))) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].internalId").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].patientId").value(TEST_STABLE_ID_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].studyId").value(TEST_CANCER_STUDY_IDENTIFIER_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].cancerStudyIdentifier").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].cancerStudy").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].internalId").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].patientId").value(TEST_STABLE_ID_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].studyId").value(TEST_CANCER_STUDY_IDENTIFIER_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].cancerStudyIdentifier").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].cancerStudy").doesNotExist()); + } + + @Test + @WithMockUser + public void fetchPatientsMetaProjection() throws Exception { + + BaseMeta baseMeta = new BaseMeta(); + baseMeta.setTotalCount(2); + + Mockito.when(patientService.fetchMetaPatients(Mockito.anyList(), Mockito.anyList())) + .thenReturn(baseMeta); + + PatientFilter patientFilter = new PatientFilter(); + List patientIdentifiers = new ArrayList<>(); + PatientIdentifier patientIdentifier1 = new PatientIdentifier(); + patientIdentifier1.setStudyId(TEST_CANCER_STUDY_IDENTIFIER_1); + patientIdentifier1.setPatientId(TEST_STABLE_ID_1); + patientIdentifiers.add(patientIdentifier1); + PatientIdentifier patientIdentifier2 = new PatientIdentifier(); + patientIdentifier2.setStudyId(TEST_CANCER_STUDY_IDENTIFIER_1); + patientIdentifier2.setPatientId(TEST_STABLE_ID_2); + patientIdentifiers.add(patientIdentifier2); + patientFilter.setPatientIdentifiers(patientIdentifiers); + + mockMvc + .perform( + MockMvcRequestBuilders.post("/api/patients/fetch") + .with(csrf()) + .param("projection", "META") + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(patientFilter))) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect(MockMvcResultMatchers.header().string(HeaderKeyConstants.TOTAL_COUNT, "2")); + } + + private List createExamplePatients() { + + List patientList = new ArrayList<>(); + Patient patient1 = new Patient(); + patient1.setInternalId(TEST_INTERNAL_ID_1); + patient1.setStableId(TEST_STABLE_ID_1); + patient1.setCancerStudyId(TEST_CANCER_STUDY_ID_1); + patient1.setCancerStudyIdentifier(TEST_CANCER_STUDY_IDENTIFIER_1); + patientList.add(patient1); + Patient patient2 = new Patient(); + patient2.setInternalId(TEST_INTERNAL_ID_2); + patient2.setStableId(TEST_STABLE_ID_2); + patient2.setCancerStudyId(TEST_CANCER_STUDY_ID_2); + patient2.setCancerStudyIdentifier(TEST_CANCER_STUDY_IDENTIFIER_2); + patientList.add(patient2); + return patientList; + } +} diff --git a/src/test/java/org/cbioportal/legacy/web/ReferenceGenomeGeneControllerTest.java b/src/test/java/org/cbioportal/legacy/web/ReferenceGenomeGeneControllerTest.java new file mode 100644 index 00000000000..66df1927da8 --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/web/ReferenceGenomeGeneControllerTest.java @@ -0,0 +1,193 @@ +package org.cbioportal.legacy.web; + +import static org.mockito.Mockito.times; +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; + +import com.fasterxml.jackson.databind.ObjectMapper; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import org.cbioportal.legacy.model.ReferenceGenomeGene; +import org.cbioportal.legacy.service.GeneMemoizerService; +import org.cbioportal.legacy.service.ReferenceGenomeGeneService; +import org.cbioportal.legacy.web.config.TestConfig; +import org.hamcrest.Matchers; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mockito; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; +import org.springframework.security.test.context.support.WithMockUser; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.result.MockMvcResultMatchers; + +@RunWith(SpringJUnit4ClassRunner.class) +@WebMvcTest +@ContextConfiguration(classes = {ReferenceGenomeGeneController.class, TestConfig.class}) +public class ReferenceGenomeGeneControllerTest { + + public static final String CYTOBAND_1 = "cytoband_1"; + public static final int LENGTH_1 = 100; + public static final String CHROMOSOME_1 = "chromosome_1"; + public static final String CYTOBAND_2 = "cytoband_2"; + public static final int LENGTH_2 = 200; + public static final String CHROMOSOME_2 = "chromosome_2"; + public static final int REFERENCE_GENOME_ID = 1; + public static final int ENTREZ_GENE_ID_1 = 1; + public static final int ENTREZ_GENE_ID_2 = 2; + + private static final ReferenceGenomeGene gene = new ReferenceGenomeGene(); + + static { + gene.setEntrezGeneId(ENTREZ_GENE_ID_1); + gene.setReferenceGenomeId(REFERENCE_GENOME_ID); + gene.setCytoband(CYTOBAND_1); + gene.setChromosome(CHROMOSOME_1); + } + + @MockBean private ReferenceGenomeGeneService referenceGenomeGeneService; + + @MockBean private GeneMemoizerService geneMemoizerService; + + private ObjectMapper objectMapper = new ObjectMapper(); + + @Autowired private MockMvc mockMvc; + + @Test + @WithMockUser + public void getAllReferenceGenesFromCache() throws Exception { + Mockito.when(geneMemoizerService.fetchGenes(Mockito.anyString())) + .thenReturn(Collections.singletonList(gene)); + Mockito.when(referenceGenomeGeneService.fetchAllReferenceGenomeGenes(Mockito.anyString())) + .thenReturn(Collections.singletonList(gene)); + + mockMvc + .perform( + MockMvcRequestBuilders.get("/api/reference-genome-genes/hg19") + .accept(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect( + MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].entrezGeneId").value(ENTREZ_GENE_ID_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].referenceGenomeId").value(REFERENCE_GENOME_ID)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].cytoband").value(CYTOBAND_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].chromosome").value(CHROMOSOME_1)); + + // The service is not called because the data is already cached + Mockito.verify(referenceGenomeGeneService, times(0)) + .fetchAllReferenceGenomeGenes(Mockito.anyString()); + // The cache is not changed + Mockito.verify(geneMemoizerService, times(0)) + .cacheGenes(Mockito.anyList(), Mockito.anyString()); + } + + @Test + @WithMockUser + public void getAllReferenceGenesNoCache() throws Exception { + Mockito.when(geneMemoizerService.fetchGenes(Mockito.anyString())).thenReturn(null); + Mockito.when(referenceGenomeGeneService.fetchAllReferenceGenomeGenes(Mockito.anyString())) + .thenReturn(Collections.singletonList(gene)); + + mockMvc + .perform( + MockMvcRequestBuilders.get("/api/reference-genome-genes/hg19") + .accept(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect( + MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].entrezGeneId").value(ENTREZ_GENE_ID_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].referenceGenomeId").value(REFERENCE_GENOME_ID)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].cytoband").value(CYTOBAND_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].chromosome").value(CHROMOSOME_1)); + + // The service is called because the cache is invalid + Mockito.verify(referenceGenomeGeneService, times(1)) + .fetchAllReferenceGenomeGenes(Mockito.anyString()); + // The response is added to the cache + Mockito.verify(geneMemoizerService, times(1)) + .cacheGenes(Mockito.anyList(), Mockito.anyString()); + } + + @Test + @WithMockUser + public void getGene() throws Exception { + Mockito.when( + referenceGenomeGeneService.getReferenceGenomeGene( + Mockito.anyInt(), Mockito.anyString())) + .thenReturn(gene); + + mockMvc + .perform( + MockMvcRequestBuilders.get("/api/reference-genome-genes/hg19/1") + .accept(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect( + MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.jsonPath("$.entrezGeneId").value(ENTREZ_GENE_ID_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$.referenceGenomeId").value(REFERENCE_GENOME_ID)) + .andExpect(MockMvcResultMatchers.jsonPath("$.cytoband").value(CYTOBAND_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$.chromosome").value(CHROMOSOME_1)); + } + + @Test + @WithMockUser + public void fetchGenesDefaultProjection() throws Exception { + + List geneList = createGeneList(); + + Mockito.when( + referenceGenomeGeneService.fetchGenesByGenomeName( + Mockito.anyList(), Mockito.anyString())) + .thenReturn(geneList); + + List geneIds = new ArrayList<>(); + geneIds.add(Integer.toString(ENTREZ_GENE_ID_1)); + geneIds.add(Integer.toString(ENTREZ_GENE_ID_2)); + + mockMvc + .perform( + MockMvcRequestBuilders.post("/api/reference-genome-genes/hg19/fetch") + .with(csrf()) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(geneIds))) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect( + MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.jsonPath("$", Matchers.hasSize(2))) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].entrezGeneId").value(ENTREZ_GENE_ID_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].referenceGenomeId").value(REFERENCE_GENOME_ID)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].cytoband").value(CYTOBAND_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].chromosome").value(CHROMOSOME_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].entrezGeneId").value(ENTREZ_GENE_ID_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].referenceGenomeId").value(REFERENCE_GENOME_ID)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].cytoband").value(CYTOBAND_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].chromosome").value(CHROMOSOME_2)); + } + + private List createGeneList() { + List geneList = new ArrayList<>(); + ReferenceGenomeGene gene1 = new ReferenceGenomeGene(); + gene1.setEntrezGeneId(ENTREZ_GENE_ID_1); + gene1.setCytoband(CYTOBAND_1); + gene1.setReferenceGenomeId(REFERENCE_GENOME_ID); + gene1.setChromosome(CHROMOSOME_1); + geneList.add(gene1); + ReferenceGenomeGene gene2 = new ReferenceGenomeGene(); + gene2.setEntrezGeneId(ENTREZ_GENE_ID_2); + gene2.setReferenceGenomeId(REFERENCE_GENOME_ID); + gene2.setCytoband(CYTOBAND_2); + gene2.setChromosome(CHROMOSOME_2); + geneList.add(gene2); + return geneList; + } +} diff --git a/src/test/java/org/cbioportal/legacy/web/ResourceDataControllerTest.java b/src/test/java/org/cbioportal/legacy/web/ResourceDataControllerTest.java new file mode 100644 index 00000000000..930e50ebc84 --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/web/ResourceDataControllerTest.java @@ -0,0 +1,165 @@ +package org.cbioportal.legacy.web; + +import com.fasterxml.jackson.databind.ObjectMapper; +import java.util.Arrays; +import java.util.List; +import org.cbioportal.legacy.model.ResourceData; +import org.cbioportal.legacy.service.ResourceDataService; +import org.cbioportal.legacy.web.config.TestConfig; +import org.hamcrest.Matchers; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mockito; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; +import org.springframework.security.test.context.support.WithMockUser; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.result.MockMvcResultMatchers; + +@RunWith(SpringJUnit4ClassRunner.class) +@WebMvcTest +@ContextConfiguration(classes = {ResourceDataController.class, TestConfig.class}) +public class ResourceDataControllerTest { + + @MockBean private ResourceDataService resourceDataService; + + private ObjectMapper objectMapper = new ObjectMapper(); + + @Autowired private MockMvc mockMvc; + + @Test + @WithMockUser + public void getAllResourceDataOfSampleInStudy() throws Exception { + + String resourceDatasJson = + "[" + + " {" + + " \"sampleId\": \"TCGA-OR-A5J1-01\"," + + " \"patientId\": \"TCGA-OR-A5J1\"," + + " \"studyId\": \"test_study_id\"," + + " \"resourceId\": \"PATHOLOGY_SLIDE\"," + + " \"url\": \"http://url-to-slide-sample1\"" + + " }" + + "]"; + + List resourceDataList = + Arrays.asList(objectMapper.readValue(resourceDatasJson, ResourceData[].class)); + + Mockito.when( + resourceDataService.getAllResourceDataOfSampleInStudy( + Mockito.any(), + Mockito.any(), + Mockito.any(), + Mockito.any(), + Mockito.any(), + Mockito.any(), + Mockito.any(), + Mockito.any())) + .thenReturn(resourceDataList); + + mockMvc + .perform( + MockMvcRequestBuilders.get( + "/api/studies/test_study_id/samples/test_sample_id/resource-data") + .accept(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect( + MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.jsonPath("$", Matchers.hasSize(1))) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].sampleId").value("TCGA-OR-A5J1-01")) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].patientId").value("TCGA-OR-A5J1")) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].studyId").value("test_study_id")) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].resourceId").value("PATHOLOGY_SLIDE")) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].url").value("http://url-to-slide-sample1")); + } + + @Test + @WithMockUser + public void getAllResourceDataOfPatientInStudy() throws Exception { + + String resourceDatasJson = + "[" + + " {" + + " \"patientId\": \"TCGA-OR-A5J1\"," + + " \"studyId\": \"test_study_id\"," + + " \"resourceId\": \"PATIENT_NOTES\"," + + " \"url\": \"http://url-to-notes-patient1.txt\"" + + " }" + + "]"; + + List resourceDataList = + Arrays.asList(objectMapper.readValue(resourceDatasJson, ResourceData[].class)); + + Mockito.when( + resourceDataService.getAllResourceDataOfPatientInStudy( + Mockito.any(), + Mockito.any(), + Mockito.any(), + Mockito.any(), + Mockito.any(), + Mockito.any(), + Mockito.any(), + Mockito.any())) + .thenReturn(resourceDataList); + + mockMvc + .perform( + MockMvcRequestBuilders.get( + "/api/studies/test_study_id/patients/test_sample_id/resource-data") + .accept(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect( + MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.jsonPath("$", Matchers.hasSize(1))) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].patientId").value("TCGA-OR-A5J1")) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].studyId").value("test_study_id")) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].resourceId").value("PATIENT_NOTES")) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].url").value("http://url-to-notes-patient1.txt")); + } + + @Test + @WithMockUser + public void getAllClinicalDataInStudy() throws Exception { + + String resourceDatasJson = + "[" + + " {" + + " \"studyId\": \"test_study_id\"," + + " \"resourceId\": \"STUDY_SPONSORS\"," + + " \"url\": \"http://url-to-sponsors.txt\"" + + " }" + + "]"; + + List resourceDataList = + Arrays.asList(objectMapper.readValue(resourceDatasJson, ResourceData[].class)); + + Mockito.when( + resourceDataService.getAllResourceDataForStudy( + Mockito.any(), + Mockito.any(), + Mockito.any(), + Mockito.any(), + Mockito.any(), + Mockito.any(), + Mockito.any())) + .thenReturn(resourceDataList); + + mockMvc + .perform( + MockMvcRequestBuilders.get("/api/studies/test_study_id/resource-data") + .accept(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect( + MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.jsonPath("$", Matchers.hasSize(1))) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].studyId").value("test_study_id")) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].resourceId").value("STUDY_SPONSORS")) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].url").value("http://url-to-sponsors.txt")); + } +} diff --git a/src/test/java/org/cbioportal/legacy/web/ResourceDefinitionControllerTest.java b/src/test/java/org/cbioportal/legacy/web/ResourceDefinitionControllerTest.java new file mode 100644 index 00000000000..4ddd57614af --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/web/ResourceDefinitionControllerTest.java @@ -0,0 +1,141 @@ +package org.cbioportal.legacy.web; + +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import com.fasterxml.jackson.databind.ObjectMapper; +import java.util.Arrays; +import java.util.List; +import org.cbioportal.legacy.model.ResourceDefinition; +import org.cbioportal.legacy.service.ResourceDefinitionService; +import org.cbioportal.legacy.web.config.TestConfig; +import org.hamcrest.Matchers; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mockito; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; +import org.springframework.security.test.context.support.WithMockUser; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.result.MockMvcResultMatchers; + +@RunWith(SpringJUnit4ClassRunner.class) +@WebMvcTest +@ContextConfiguration(classes = {ResourceDefinitionController.class, TestConfig.class}) +public class ResourceDefinitionControllerTest { + + @MockBean private ResourceDefinitionService resourceDefinitionService; + + private ObjectMapper objectMapper = new ObjectMapper(); + + @Autowired private MockMvc mockMvc; + + @Test + @WithMockUser + public void getAllResourceDefinitionsInStudy() throws Exception { + + String resourceDefinitionsJson = + "[" + + " {" + + " \"resourceId\": \"PATHOLOGY_SLIDE\"," + + " \"displayName\": \"Pathology Slide\"," + + " \"description\": \"The pathology slide for the sample\"," + + " \"resourceType\": \"SAMPLE\"," + + " \"priority\": \"1\"," + + " \"openByDefault\": true," + + " \"cancerStudyIdentifier\": \"test_study_id\"" + + " }," + + " {" + + " \"resourceId\": \"PATIENT_NOTES\"," + + " \"displayName\": \"Patient Notes\"," + + " \"description\": \"Notes about the patient\"," + + " \"resourceType\": \"PATIENT\"," + + " \"priority\": \"2\"," + + " \"openByDefault\": false," + + " \"cancerStudyIdentifier\": \"test_study_id\"" + + " }," + + " {" + + " \"resourceId\": \"STUDY_SPONSORS\"," + + " \"displayName\": \"Study Sponsors\"," + + " \"description\": \"Sponsors of this study\"," + + " \"resourceType\": \"STUDY\"," + + " \"priority\": \"3\"," + + " \"openByDefault\": true," + + " \"cancerStudyIdentifier\": \"test_study_id\"" + + " }" + + "]"; + + List resourceDefinitions = + Arrays.asList(objectMapper.readValue(resourceDefinitionsJson, ResourceDefinition[].class)); + + Mockito.when( + resourceDefinitionService.getAllResourceDefinitionsInStudy( + Mockito.any(), + Mockito.any(), + Mockito.any(), + Mockito.any(), + Mockito.any(), + Mockito.any())) + .thenReturn(resourceDefinitions); + + mockMvc + .perform( + MockMvcRequestBuilders.get("/api/studies/test_study_id/resource-definitions") + .accept(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect( + MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andExpect(MockMvcResultMatchers.jsonPath("$", Matchers.hasSize(3))) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].resourceId").value("PATHOLOGY_SLIDE")) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].studyId").value("test_study_id")) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].resourceType").value("SAMPLE")) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].resourceId").value("PATIENT_NOTES")) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].resourceType").value("PATIENT")) + .andExpect(MockMvcResultMatchers.jsonPath("$[2].resourceId").value("STUDY_SPONSORS")) + .andExpect(MockMvcResultMatchers.jsonPath("$[2].resourceType").value("STUDY")); + ; + } + + @Test + @WithMockUser + public void getResourceDefinitionInStudy() throws Exception { + + String resourceDefinition = + "{" + + " \"resourceId\": \"PATHOLOGY_SLIDE\"," + + " \"displayName\": \"Pathology Slide\"," + + " \"description\": \"The pathology slide for the sample\"," + + " \"resourceType\": \"SAMPLE\"," + + " \"priority\": \"1\"," + + " \"openByDefault\": true," + + " \"cancerStudyIdentifier\": \"test_study_id\"" + + " }"; + + ResourceDefinition resourceDefinitions = + objectMapper.readValue(resourceDefinition, ResourceDefinition.class); + + Mockito.when( + resourceDefinitionService.getResourceDefinition( + Mockito.anyString(), Mockito.anyString())) + .thenReturn(resourceDefinitions); + + mockMvc + .perform( + MockMvcRequestBuilders.get( + "/api/studies/test_study_id/resource-definitions/PATHOLOGY_SLIDE") + .accept(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect( + MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andExpect(MockMvcResultMatchers.jsonPath("resourceId").value("PATHOLOGY_SLIDE")) + .andExpect(MockMvcResultMatchers.jsonPath("studyId").value("test_study_id")) + .andExpect(MockMvcResultMatchers.jsonPath("resourceType").value("SAMPLE")); + ; + } +} diff --git a/src/test/java/org/cbioportal/legacy/web/SampleControllerTest.java b/src/test/java/org/cbioportal/legacy/web/SampleControllerTest.java new file mode 100644 index 00000000000..ad44682567c --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/web/SampleControllerTest.java @@ -0,0 +1,441 @@ +package org.cbioportal.legacy.web; + +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; + +import com.fasterxml.jackson.databind.ObjectMapper; +import java.util.ArrayList; +import java.util.List; +import org.cbioportal.legacy.model.Sample; +import org.cbioportal.legacy.model.meta.BaseMeta; +import org.cbioportal.legacy.service.SampleListService; +import org.cbioportal.legacy.service.SampleService; +import org.cbioportal.legacy.service.StudyService; +import org.cbioportal.legacy.service.exception.SampleNotFoundException; +import org.cbioportal.legacy.web.config.TestConfig; +import org.cbioportal.legacy.web.parameter.HeaderKeyConstants; +import org.cbioportal.legacy.web.parameter.SampleFilter; +import org.cbioportal.legacy.web.parameter.SampleIdentifier; +import org.hamcrest.Matchers; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mockito; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; +import org.springframework.security.test.context.support.WithMockUser; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.result.MockMvcResultMatchers; + +@RunWith(SpringJUnit4ClassRunner.class) +@WebMvcTest +@ContextConfiguration(classes = {SampleController.class, TestConfig.class}) +public class SampleControllerTest { + + private static final int TEST_INTERNAL_ID_1 = 1; + private static final String TEST_STABLE_ID_1 = "test_stable_id_1"; + private static final int TEST_PATIENT_ID_1 = 1; + private static final String TEST_PATIENT_STABLE_ID_1 = "test_patient_stable_id_1"; + private static final String TEST_CANCER_STUDY_IDENTIFIER_1 = "test_study_1"; + private static final int TEST_INTERNAL_ID_2 = 2; + private static final String TEST_STABLE_ID_2 = "test_stable_id_2"; + private static final int TEST_PATIENT_ID_2 = 2; + private static final String TEST_PATIENT_STABLE_ID_2 = "test_patient_stable_id_2"; + + @MockBean private SampleService sampleService; + + @MockBean private SampleListService sampleListService; + + @MockBean private StudyService studyService; + + private ObjectMapper objectMapper = new ObjectMapper(); + + @Autowired private MockMvc mockMvc; + + @Test + @WithMockUser + public void getAllSamplesInStudyDefaultProjection() throws Exception { + + List sampleList = createExampleSamples(); + + Mockito.when( + sampleService.getAllSamplesInStudy( + Mockito.any(), + Mockito.any(), + Mockito.any(), + Mockito.any(), + Mockito.any(), + Mockito.any())) + .thenReturn(sampleList); + + mockMvc + .perform( + MockMvcRequestBuilders.get("/api/studies/test_study_id/samples") + .accept(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect( + MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.jsonPath("$", Matchers.hasSize(2))) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].internalId").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].sampleId").value(TEST_STABLE_ID_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].patientId").value(TEST_PATIENT_STABLE_ID_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].patientStableId").doesNotExist()) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].sampleType") + .value(Sample.SampleType.PRIMARY_SOLID_TUMOR.getValue())) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].studyId").value(TEST_CANCER_STUDY_IDENTIFIER_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].patient").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].internalId").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].sampleId").value(TEST_STABLE_ID_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].patientId").value(TEST_PATIENT_STABLE_ID_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].patientStableId").doesNotExist()) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].sampleType") + .value(Sample.SampleType.PRIMARY_SOLID_TUMOR.getValue())) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].studyId").value(TEST_CANCER_STUDY_IDENTIFIER_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].patient").doesNotExist()); + } + + @Test + @WithMockUser + public void getAllSamplesInStudyMetaProjection() throws Exception { + + BaseMeta baseMeta = new BaseMeta(); + baseMeta.setTotalCount(2); + + Mockito.when(sampleService.getMetaSamplesInStudy(Mockito.anyString())).thenReturn(baseMeta); + + mockMvc + .perform( + MockMvcRequestBuilders.get("/api/studies/test_study_id/samples") + .param("projection", "META")) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect(MockMvcResultMatchers.header().string(HeaderKeyConstants.TOTAL_COUNT, "2")); + } + + @Test + @WithMockUser + public void getSampleInStudyNotFound() throws Exception { + + Mockito.when(sampleService.getSampleInStudy(Mockito.anyString(), Mockito.anyString())) + .thenThrow(new SampleNotFoundException("test_study_id", "test_sample_id")); + + mockMvc + .perform( + MockMvcRequestBuilders.get("/api/studies/test_study_id/samples/test_sample_id") + .accept(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.status().isNotFound()) + .andExpect( + MockMvcResultMatchers.jsonPath("$.message") + .value("Sample not found in study test_study_id: test_sample_id")); + } + + @Test + @WithMockUser + public void getAllSamples() throws Exception { + List samples = createExampleSamples(); + + Mockito.when( + sampleService.getAllSamples( + Mockito.any(), + Mockito.any(), + Mockito.any(), + Mockito.any(), + Mockito.any(), + Mockito.any(), + Mockito.any())) + .thenReturn(samples); + + mockMvc + .perform(MockMvcRequestBuilders.get("/api/samples").accept(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect( + MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.jsonPath("$", Matchers.hasSize(2))) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].internalId").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].sampleId").value(TEST_STABLE_ID_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].patientId").value(TEST_PATIENT_STABLE_ID_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].patientStableId").doesNotExist()) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].sampleType") + .value(Sample.SampleType.PRIMARY_SOLID_TUMOR.getValue())) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].studyId").value(TEST_CANCER_STUDY_IDENTIFIER_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].patient").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].internalId").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].sampleId").value(TEST_STABLE_ID_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].patientId").value(TEST_PATIENT_STABLE_ID_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].patientStableId").doesNotExist()) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].sampleType") + .value(Sample.SampleType.PRIMARY_SOLID_TUMOR.getValue())) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].studyId").value(TEST_CANCER_STUDY_IDENTIFIER_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].patient").doesNotExist()); + } + + @Test + @WithMockUser + public void getSampleInStudy() throws Exception { + + Sample sample = new Sample(); + sample.setInternalId(TEST_INTERNAL_ID_1); + sample.setStableId(TEST_STABLE_ID_1); + sample.setPatientId(TEST_PATIENT_ID_1); + sample.setPatientStableId(TEST_PATIENT_STABLE_ID_1); + sample.setSampleType(Sample.SampleType.PRIMARY_SOLID_TUMOR); + sample.setCancerStudyIdentifier(TEST_CANCER_STUDY_IDENTIFIER_1); + + Mockito.when(sampleService.getSampleInStudy(Mockito.anyString(), Mockito.anyString())) + .thenReturn(sample); + + mockMvc + .perform( + MockMvcRequestBuilders.get("/api/studies/test_study_id/samples/test_sample_id") + .accept(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect( + MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.jsonPath("$.internalId").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$.sampleId").value(TEST_STABLE_ID_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$.patientId").value(TEST_PATIENT_STABLE_ID_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$.patientStableId").doesNotExist()) + .andExpect( + MockMvcResultMatchers.jsonPath("$.sampleType") + .value(Sample.SampleType.PRIMARY_SOLID_TUMOR.getValue())) + .andExpect( + MockMvcResultMatchers.jsonPath("$.studyId").value(TEST_CANCER_STUDY_IDENTIFIER_1)); + } + + @Test + @WithMockUser + public void getAllSamplesOfPatientInStudyDefaultProjection() throws Exception { + + List sampleList = createExampleSamples(); + + Mockito.when( + sampleService.getAllSamplesOfPatientInStudy( + Mockito.any(), + Mockito.any(), + Mockito.any(), + Mockito.any(), + Mockito.any(), + Mockito.any(), + Mockito.any())) + .thenReturn(sampleList); + + mockMvc + .perform( + MockMvcRequestBuilders.get( + "/api/studies/test_study_id/patients/test_patient_id/samples") + .accept(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect( + MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.jsonPath("$", Matchers.hasSize(2))) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].internalId").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].sampleId").value(TEST_STABLE_ID_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].patientId").value(TEST_PATIENT_STABLE_ID_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].patientStableId").doesNotExist()) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].sampleType") + .value(Sample.SampleType.PRIMARY_SOLID_TUMOR.getValue())) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].studyId").value(TEST_CANCER_STUDY_IDENTIFIER_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].patient").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].internalId").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].sampleId").value(TEST_STABLE_ID_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].patientId").value(TEST_PATIENT_STABLE_ID_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].patientStableId").doesNotExist()) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].sampleType") + .value(Sample.SampleType.PRIMARY_SOLID_TUMOR.getValue())) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].studyId").value(TEST_CANCER_STUDY_IDENTIFIER_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].patient").doesNotExist()); + } + + @Test + @WithMockUser + public void getAllSamplesOfPatientInStudyMetaProjection() throws Exception { + + BaseMeta baseMeta = new BaseMeta(); + baseMeta.setTotalCount(2); + + Mockito.when( + sampleService.getMetaSamplesOfPatientInStudy(Mockito.anyString(), Mockito.anyString())) + .thenReturn(baseMeta); + + mockMvc + .perform( + MockMvcRequestBuilders.get( + "/api/studies/test_study_id/patients/test_patient_id/samples") + .param("projection", "META")) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect(MockMvcResultMatchers.header().string(HeaderKeyConstants.TOTAL_COUNT, "2")); + } + + @Test + @WithMockUser + public void fetchSamplesDefaultProjection() throws Exception { + + List sampleList = createExampleSamples(); + + Mockito.when( + sampleService.fetchSamples(Mockito.anyList(), Mockito.anyList(), Mockito.anyString())) + .thenReturn(sampleList); + + SampleFilter sampleFilter = new SampleFilter(); + List sampleIdentifiers = new ArrayList<>(); + SampleIdentifier sampleIdentifier1 = new SampleIdentifier(); + sampleIdentifier1.setStudyId(TEST_CANCER_STUDY_IDENTIFIER_1); + sampleIdentifier1.setSampleId(TEST_STABLE_ID_1); + sampleIdentifiers.add(sampleIdentifier1); + SampleIdentifier sampleIdentifier2 = new SampleIdentifier(); + sampleIdentifier2.setStudyId(TEST_CANCER_STUDY_IDENTIFIER_1); + sampleIdentifier2.setSampleId(TEST_STABLE_ID_2); + sampleIdentifiers.add(sampleIdentifier2); + sampleFilter.setSampleIdentifiers(sampleIdentifiers); + + mockMvc + .perform( + MockMvcRequestBuilders.post("/api/samples/fetch") + .with(csrf()) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(sampleFilter))) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect( + MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.jsonPath("$", Matchers.hasSize(2))) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].internalId").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].sampleId").value(TEST_STABLE_ID_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].patientId").value(TEST_PATIENT_STABLE_ID_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].patientStableId").doesNotExist()) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].sampleType") + .value(Sample.SampleType.PRIMARY_SOLID_TUMOR.getValue())) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].studyId").value(TEST_CANCER_STUDY_IDENTIFIER_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].patient").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].internalId").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].sampleId").value(TEST_STABLE_ID_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].patientId").value(TEST_PATIENT_STABLE_ID_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].patientStableId").doesNotExist()) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].sampleType") + .value(Sample.SampleType.PRIMARY_SOLID_TUMOR.getValue())) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].studyId").value(TEST_CANCER_STUDY_IDENTIFIER_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].patient").doesNotExist()); + } + + @Test + @WithMockUser + public void fetchSamplesByUniqueSampleKeysDefaultProjection() throws Exception { + + List sampleList = createExampleSamples(); + + Mockito.when( + sampleService.fetchSamples(Mockito.anyList(), Mockito.anyList(), Mockito.anyString())) + .thenReturn(sampleList); + + SampleFilter sampleFilter = new SampleFilter(); + List uniqueSampleKeys = new ArrayList<>(); + uniqueSampleKeys.add("dGVzdF9zdGFibGVfaWRfMTp0ZXN0X3N0dWR5XzE"); + uniqueSampleKeys.add("dGVzdF9zdGFibGVfaWRfMjp0ZXN0X3N0dWR5XzE"); + sampleFilter.setUniqueSampleKeys(uniqueSampleKeys); + + mockMvc + .perform( + MockMvcRequestBuilders.post("/api/samples/fetch") + .with(csrf()) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(sampleFilter))) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect( + MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.jsonPath("$", Matchers.hasSize(2))) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].internalId").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].sampleId").value(TEST_STABLE_ID_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].patientId").value(TEST_PATIENT_STABLE_ID_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].patientStableId").doesNotExist()) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].sampleType") + .value(Sample.SampleType.PRIMARY_SOLID_TUMOR.getValue())) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].studyId").value(TEST_CANCER_STUDY_IDENTIFIER_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].patient").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].internalId").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].sampleId").value(TEST_STABLE_ID_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].patientId").value(TEST_PATIENT_STABLE_ID_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].patientStableId").doesNotExist()) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].sampleType") + .value(Sample.SampleType.PRIMARY_SOLID_TUMOR.getValue())) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].studyId").value(TEST_CANCER_STUDY_IDENTIFIER_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].patient").doesNotExist()); + } + + @Test + @WithMockUser + public void fetchSamplesMetaProjection() throws Exception { + + BaseMeta baseMeta = new BaseMeta(); + baseMeta.setTotalCount(2); + + Mockito.when(sampleService.fetchMetaSamples(Mockito.anyList(), Mockito.anyList())) + .thenReturn(baseMeta); + + SampleFilter sampleFilter = new SampleFilter(); + List sampleIdentifiers = new ArrayList<>(); + SampleIdentifier sampleIdentifier1 = new SampleIdentifier(); + sampleIdentifier1.setStudyId(TEST_CANCER_STUDY_IDENTIFIER_1); + sampleIdentifier1.setSampleId(TEST_STABLE_ID_1); + sampleIdentifiers.add(sampleIdentifier1); + SampleIdentifier sampleIdentifier2 = new SampleIdentifier(); + sampleIdentifier2.setStudyId(TEST_CANCER_STUDY_IDENTIFIER_1); + sampleIdentifier2.setSampleId(TEST_STABLE_ID_2); + sampleIdentifiers.add(sampleIdentifier2); + sampleFilter.setSampleIdentifiers(sampleIdentifiers); + + mockMvc + .perform( + MockMvcRequestBuilders.post("/api/samples/fetch") + .with(csrf()) + .param("projection", "META") + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(sampleFilter))) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect(MockMvcResultMatchers.header().string(HeaderKeyConstants.TOTAL_COUNT, "2")); + } + + private List createExampleSamples() { + + List sampleList = new ArrayList<>(); + Sample sample1 = new Sample(); + sample1.setInternalId(TEST_INTERNAL_ID_1); + sample1.setStableId(TEST_STABLE_ID_1); + sample1.setPatientId(TEST_PATIENT_ID_1); + sample1.setPatientStableId(TEST_PATIENT_STABLE_ID_1); + sample1.setSampleType(Sample.SampleType.PRIMARY_SOLID_TUMOR); + sample1.setCancerStudyIdentifier(TEST_CANCER_STUDY_IDENTIFIER_1); + sampleList.add(sample1); + Sample sample2 = new Sample(); + sample2.setInternalId(TEST_INTERNAL_ID_2); + sample2.setStableId(TEST_STABLE_ID_2); + sample2.setPatientId(TEST_PATIENT_ID_2); + sample2.setPatientStableId(TEST_PATIENT_STABLE_ID_2); + sample2.setSampleType(Sample.SampleType.PRIMARY_SOLID_TUMOR); + sample2.setCancerStudyIdentifier(TEST_CANCER_STUDY_IDENTIFIER_1); + sampleList.add(sample2); + return sampleList; + } +} diff --git a/src/test/java/org/cbioportal/legacy/web/SampleListControllerTest.java b/src/test/java/org/cbioportal/legacy/web/SampleListControllerTest.java new file mode 100644 index 00000000000..2611874df09 --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/web/SampleListControllerTest.java @@ -0,0 +1,376 @@ +package org.cbioportal.legacy.web; + +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; + +import com.fasterxml.jackson.databind.ObjectMapper; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import org.cbioportal.legacy.model.CancerStudy; +import org.cbioportal.legacy.model.SampleList; +import org.cbioportal.legacy.model.meta.BaseMeta; +import org.cbioportal.legacy.service.SampleListService; +import org.cbioportal.legacy.service.exception.SampleListNotFoundException; +import org.cbioportal.legacy.web.config.TestConfig; +import org.cbioportal.legacy.web.parameter.HeaderKeyConstants; +import org.hamcrest.Matchers; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mockito; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; +import org.springframework.security.test.context.support.WithMockUser; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.result.MockMvcResultMatchers; + +@RunWith(SpringJUnit4ClassRunner.class) +@WebMvcTest +@ContextConfiguration(classes = {SampleListController.class, TestConfig.class}) +public class SampleListControllerTest { + + private static final int TEST_LIST_ID_1 = 1; + private static final String TEST_STABLE_ID_1 = "test_stable_id_1"; + private static final int TEST_CANCER_STUDY_ID_1 = 1; + private static final String TEST_STUDY_IDENTIFIER_1 = "test_study_identifier_1"; + private static final String TEST_CATEGORY_1 = "test_datatype_1"; + private static final String TEST_NAME_1 = "test_name_1"; + private static final String TEST_DESCRIPTION_1 = "test_description_1"; + private static final String TEST_CANCER_STUDY_IDENTIFIER_1 = "test_study_1"; + private static final String TEST_TYPE_OF_CANCER_ID_1 = "test_type_of_cancer_id_1"; + private static final String TEST_STUDY_NAME_1 = "test_study_name_1"; + private static final String TEST_SHORT_NAME_1 = "test_short_name_1"; + private static final String TEST_STUDY_DESCRIPTION_1 = "test_study_description_1"; + private static final int TEST_SAMPLE_COUNT_1 = 10; + private static final int TEST_LIST_ID_2 = 2; + private static final String TEST_STABLE_ID_2 = "test_stable_id_2"; + private static final int TEST_CANCER_STUDY_ID_2 = 2; + private static final String TEST_STUDY_IDENTIFIER_2 = "test_study_identifier_2"; + private static final String TEST_CATEGORY_2 = "test_datatype_2"; + private static final String TEST_NAME_2 = "test_name_2"; + private static final String TEST_DESCRIPTION_2 = "test_description_2"; + private static final String TEST_SAMPLE_ID_1 = "test_sample_id_1"; + private static final String TEST_SAMPLE_ID_2 = "test_sample_id_2"; + + @MockBean private SampleListService sampleListService; + + private ObjectMapper objectMapper = new ObjectMapper(); + + @Autowired private MockMvc mockMvc; + + @Test + @WithMockUser + public void getAllSampleListsDefaultProjection() throws Exception { + + List sampleLists = createExampleSampleLists(); + + Mockito.when( + sampleListService.getAllSampleLists( + Mockito.any(), Mockito.any(), Mockito.any(), Mockito.any(), Mockito.any())) + .thenReturn(sampleLists); + + mockMvc + .perform(MockMvcRequestBuilders.get("/api/sample-lists").accept(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect( + MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.jsonPath("$", Matchers.hasSize(2))) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].listId").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].sampleListId").value(TEST_STABLE_ID_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].studyId").value(TEST_STUDY_IDENTIFIER_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].category").value(TEST_CATEGORY_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].name").value(TEST_NAME_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].description").value(TEST_DESCRIPTION_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].listId").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].sampleListId").value(TEST_STABLE_ID_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].studyId").value(TEST_STUDY_IDENTIFIER_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].category").value(TEST_CATEGORY_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].name").value(TEST_NAME_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].description").value(TEST_DESCRIPTION_2)); + } + + @Test + @WithMockUser + public void getAllSampleListsDetailedProjection() throws Exception { + + List sampleLists = new ArrayList<>(); + sampleLists.add(createExampleSampleListWithStudy()); + + Mockito.when( + sampleListService.getAllSampleLists( + Mockito.any(), Mockito.any(), Mockito.any(), Mockito.any(), Mockito.any())) + .thenReturn(sampleLists); + + mockMvc + .perform( + MockMvcRequestBuilders.get("/api/sample-lists") + .param("projection", "DETAILED") + .accept(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect( + MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.jsonPath("$", Matchers.hasSize(1))) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].listId").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].sampleListId").value(TEST_STABLE_ID_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].studyId").value(TEST_STUDY_IDENTIFIER_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].category").value(TEST_CATEGORY_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].name").value(TEST_NAME_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].description").value(TEST_DESCRIPTION_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].sampleCount").value(TEST_SAMPLE_COUNT_1)); + } + + @Test + @WithMockUser + public void getAllSampleListsMetaProjection() throws Exception { + + BaseMeta baseMeta = new BaseMeta(); + baseMeta.setTotalCount(2); + + Mockito.when(sampleListService.getMetaSampleLists()).thenReturn(baseMeta); + + mockMvc + .perform(MockMvcRequestBuilders.get("/api/sample-lists").param("projection", "META")) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect(MockMvcResultMatchers.header().string(HeaderKeyConstants.TOTAL_COUNT, "2")); + } + + @Test + @WithMockUser + public void getSampleListNotFound() throws Exception { + + Mockito.when(sampleListService.getSampleList(Mockito.anyString())) + .thenThrow(new SampleListNotFoundException("test_sample_list_id")); + + mockMvc + .perform( + MockMvcRequestBuilders.get("/api/sample-lists/test_sample_list_id") + .accept(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.status().isNotFound()) + .andExpect( + MockMvcResultMatchers.jsonPath("$.message") + .value("Sample list not found: test_sample_list_id")); + } + + @Test + @WithMockUser + public void getSampleList() throws Exception { + + SampleList sampleList = createExampleSampleListWithStudy(); + + Mockito.when(sampleListService.getSampleList(Mockito.anyString())).thenReturn(sampleList); + + mockMvc + .perform( + MockMvcRequestBuilders.get("/api/sample-lists/test_sample_list_id") + .accept(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect( + MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.jsonPath("$.listId").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$.sampleListId").value(TEST_STABLE_ID_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$.studyId").value(TEST_STUDY_IDENTIFIER_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$.category").value(TEST_CATEGORY_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$.name").value(TEST_NAME_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$.description").value(TEST_DESCRIPTION_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$.sampleCount").value(TEST_SAMPLE_COUNT_1)); + } + + @Test + @WithMockUser + public void getAllSampleListsInStudyDefaultProjection() throws Exception { + + List sampleLists = createExampleSampleLists(); + + Mockito.when( + sampleListService.getAllSampleListsInStudy( + Mockito.any(), + Mockito.any(), + Mockito.any(), + Mockito.any(), + Mockito.any(), + Mockito.any())) + .thenReturn(sampleLists); + + mockMvc + .perform( + MockMvcRequestBuilders.get("/api/studies/test_study_id/sample-lists") + .accept(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect( + MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.jsonPath("$", Matchers.hasSize(2))) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].listId").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].sampleListId").value(TEST_STABLE_ID_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].studyId").value(TEST_STUDY_IDENTIFIER_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].category").value(TEST_CATEGORY_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].name").value(TEST_NAME_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].description").value(TEST_DESCRIPTION_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].listId").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].sampleListId").value(TEST_STABLE_ID_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].studyId").value(TEST_STUDY_IDENTIFIER_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].category").value(TEST_CATEGORY_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].name").value(TEST_NAME_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].description").value(TEST_DESCRIPTION_2)); + } + + @Test + @WithMockUser + public void getAllSampleListsInStudyDetailedProjection() throws Exception { + + List sampleLists = new ArrayList<>(); + sampleLists.add(createExampleSampleListWithStudy()); + + Mockito.when( + sampleListService.getAllSampleListsInStudy( + Mockito.any(), + Mockito.any(), + Mockito.any(), + Mockito.any(), + Mockito.any(), + Mockito.any())) + .thenReturn(sampleLists); + + mockMvc + .perform( + MockMvcRequestBuilders.get("/api/studies/test_study_id/sample-lists") + .param("projection", "DETAILED") + .accept(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect( + MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.jsonPath("$", Matchers.hasSize(1))) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].listId").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].sampleListId").value(TEST_STABLE_ID_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].studyId").value(TEST_STUDY_IDENTIFIER_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].category").value(TEST_CATEGORY_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].name").value(TEST_NAME_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].description").value(TEST_DESCRIPTION_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].sampleCount").value(TEST_SAMPLE_COUNT_1)); + } + + @Test + @WithMockUser + public void getAllSampleListsInStudyMetaProjection() throws Exception { + + BaseMeta baseMeta = new BaseMeta(); + baseMeta.setTotalCount(2); + + Mockito.when(sampleListService.getMetaSampleListsInStudy(Mockito.anyString())) + .thenReturn(baseMeta); + + mockMvc + .perform( + MockMvcRequestBuilders.get("/api/studies/test_study_id/sample-lists") + .param("projection", "META")) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect(MockMvcResultMatchers.header().string(HeaderKeyConstants.TOTAL_COUNT, "2")); + } + + @Test + @WithMockUser + public void getAllSampleIdsInSampleList() throws Exception { + + List sampleIds = new ArrayList<>(); + sampleIds.add(TEST_SAMPLE_ID_1); + sampleIds.add(TEST_SAMPLE_ID_2); + + Mockito.when(sampleListService.getAllSampleIdsInSampleList(Mockito.anyString())) + .thenReturn(sampleIds); + + mockMvc + .perform( + MockMvcRequestBuilders.get("/api/sample-lists/test_sample_list_id/sample-ids") + .accept(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect( + MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.jsonPath("$", Matchers.hasSize(2))) + .andExpect(MockMvcResultMatchers.jsonPath("$[0]").value(TEST_SAMPLE_ID_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1]").value(TEST_SAMPLE_ID_2)); + } + + @Test + @WithMockUser + public void fetchSampleLists() throws Exception { + + List sampleLists = createExampleSampleLists(); + + Mockito.when(sampleListService.fetchSampleLists(Mockito.anyList(), Mockito.anyString())) + .thenReturn(sampleLists); + + mockMvc + .perform( + MockMvcRequestBuilders.post("/api/sample-lists/fetch") + .with(csrf()) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + .content( + objectMapper.writeValueAsString( + Arrays.asList(TEST_STABLE_ID_1, TEST_STABLE_ID_2)))) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect( + MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.jsonPath("$", Matchers.hasSize(2))) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].listId").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].sampleListId").value(TEST_STABLE_ID_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].studyId").value(TEST_STUDY_IDENTIFIER_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].category").value(TEST_CATEGORY_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].name").value(TEST_NAME_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].description").value(TEST_DESCRIPTION_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].listId").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].sampleListId").value(TEST_STABLE_ID_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].studyId").value(TEST_STUDY_IDENTIFIER_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].category").value(TEST_CATEGORY_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].name").value(TEST_NAME_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].description").value(TEST_DESCRIPTION_2)); + } + + private List createExampleSampleLists() { + + List sampleLists = new ArrayList<>(); + SampleList sampleList1 = new SampleList(); + sampleList1.setListId(TEST_LIST_ID_1); + sampleList1.setStableId(TEST_STABLE_ID_1); + sampleList1.setCancerStudyId(TEST_CANCER_STUDY_ID_1); + sampleList1.setCancerStudyIdentifier(TEST_STUDY_IDENTIFIER_1); + sampleList1.setCategory(TEST_CATEGORY_1); + sampleList1.setName(TEST_NAME_1); + sampleList1.setDescription(TEST_DESCRIPTION_1); + sampleLists.add(sampleList1); + SampleList sampleList2 = new SampleList(); + sampleList2.setListId(TEST_LIST_ID_2); + sampleList2.setStableId(TEST_STABLE_ID_2); + sampleList2.setCancerStudyId(TEST_CANCER_STUDY_ID_2); + sampleList2.setCancerStudyIdentifier(TEST_STUDY_IDENTIFIER_2); + sampleList2.setCategory(TEST_CATEGORY_2); + sampleList2.setName(TEST_NAME_2); + sampleList2.setDescription(TEST_DESCRIPTION_2); + sampleLists.add(sampleList2); + return sampleLists; + } + + private SampleList createExampleSampleListWithStudy() { + + SampleList sampleList = new SampleList(); + sampleList.setListId(TEST_LIST_ID_1); + sampleList.setStableId(TEST_STABLE_ID_1); + sampleList.setCancerStudyId(TEST_CANCER_STUDY_ID_1); + sampleList.setCancerStudyIdentifier(TEST_STUDY_IDENTIFIER_1); + sampleList.setCategory(TEST_CATEGORY_1); + sampleList.setName(TEST_NAME_1); + sampleList.setDescription(TEST_DESCRIPTION_1); + sampleList.setSampleCount(TEST_SAMPLE_COUNT_1); + CancerStudy cancerStudy = new CancerStudy(); + cancerStudy.setCancerStudyId(TEST_CANCER_STUDY_ID_1); + cancerStudy.setCancerStudyIdentifier(TEST_CANCER_STUDY_IDENTIFIER_1); + cancerStudy.setTypeOfCancerId(TEST_TYPE_OF_CANCER_ID_1); + cancerStudy.setName(TEST_STUDY_NAME_1); + cancerStudy.setDescription(TEST_STUDY_DESCRIPTION_1); + sampleList.setCancerStudy(cancerStudy); + return sampleList; + } +} diff --git a/src/test/java/org/cbioportal/legacy/web/ServerStatusControllerTest.java b/src/test/java/org/cbioportal/legacy/web/ServerStatusControllerTest.java new file mode 100644 index 00000000000..4254215d510 --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/web/ServerStatusControllerTest.java @@ -0,0 +1,39 @@ +package org.cbioportal.legacy.web; + +import org.cbioportal.legacy.service.ServerStatusService; +import org.junit.Before; +import org.junit.Ignore; +import org.junit.runner.RunWith; +import org.mockito.Mockito; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.TestConfiguration; +import org.springframework.context.annotation.Bean; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.web.WebAppConfiguration; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import org.springframework.web.context.WebApplicationContext; + +@Ignore +@RunWith(SpringJUnit4ClassRunner.class) +@WebAppConfiguration +@ContextConfiguration("/applicationContext-web-test.xml") +@TestConfiguration +public class ServerStatusControllerTest { + + @Autowired private WebApplicationContext wac; + + private MockMvc mockMvc; + + @Before + public void setUp() throws Exception { + mockMvc = MockMvcBuilders.webAppContextSetup(wac).build(); + } + + @Bean + public static ServerStatusService serverStatusService() { + ServerStatusService serverStatusServiceMock = Mockito.mock(ServerStatusService.class); + return serverStatusServiceMock; + } +} diff --git a/src/test/java/org/cbioportal/legacy/web/SessionServiceControllerTest.java b/src/test/java/org/cbioportal/legacy/web/SessionServiceControllerTest.java new file mode 100644 index 00000000000..7ca101468dd --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/web/SessionServiceControllerTest.java @@ -0,0 +1,110 @@ +package org.cbioportal.legacy.web; + +import java.util.List; +import org.cbioportal.legacy.service.util.SessionServiceRequestHandler; +import org.cbioportal.legacy.utils.removeme.Session; +import org.cbioportal.legacy.web.config.TestConfig; +import org.cbioportal.legacy.web.parameter.SampleIdentifier; +import org.cbioportal.legacy.web.util.StudyViewFilterApplier; +import org.hamcrest.Matchers; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mockito; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; +import org.springframework.security.test.context.support.WithMockUser; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.result.MockMvcResultMatchers; + +@RunWith(SpringJUnit4ClassRunner.class) +@WebMvcTest +@ContextConfiguration(classes = {SessionServiceController.class, TestConfig.class}) +public class SessionServiceControllerTest { + + @MockBean SessionServiceRequestHandler sessionServiceRequestHandler; + + @MockBean StudyViewFilterApplier studyViewFilterApplier; + + SampleIdentifier sampleIdentifier1 = new SampleIdentifier(); + + { + sampleIdentifier1.setStudyId("STUDY_1"); + } + + SampleIdentifier sampleIdentifier2 = new SampleIdentifier(); + + { + sampleIdentifier2.setStudyId("STUDY_2"); + } + + @Autowired private MockMvc mockMvc; + + @Test + @WithMockUser + public void testStaticVirtualStudy() throws Exception { + Mockito.when( + sessionServiceRequestHandler.getSessionDataJson( + Session.SessionType.virtual_study, "123")) + .thenReturn( + """ + { + "id": "123", + "data": { + "name": "Test", + "studies": [ + { "id": "STUDY_N", "samples": [ "S1", "S2" ] } + ] + } + } + """); + + // Should not be used + Mockito.when(studyViewFilterApplier.apply(Mockito.any())) + .thenReturn(List.of(sampleIdentifier1, sampleIdentifier2)); + + mockMvc + .perform( + MockMvcRequestBuilders.get("/api/session/virtual_study/123") + .accept(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect(MockMvcResultMatchers.jsonPath("$.data.studies", Matchers.hasSize(1))) + .andExpect(MockMvcResultMatchers.jsonPath("$.data.studies[0].id").value("STUDY_N")); + Mockito.verify(studyViewFilterApplier, Mockito.never()).apply(Mockito.any()); + } + + @Test + @WithMockUser + public void testDynamicVirtualStudy() throws Exception { + Mockito.when( + sessionServiceRequestHandler.getSessionDataJson( + Session.SessionType.virtual_study, "123")) + .thenReturn( + """ + { + "id": "123", + "data": { + "name": "Test", + "dynamic": true + } + } + """); + + Mockito.when(studyViewFilterApplier.apply(Mockito.any())) + .thenReturn(List.of(sampleIdentifier1, sampleIdentifier2)); + + mockMvc + .perform( + MockMvcRequestBuilders.get("/api/session/virtual_study/123") + .accept(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect(MockMvcResultMatchers.jsonPath("$.data.studies", Matchers.hasSize(2))) + .andExpect( + MockMvcResultMatchers.jsonPath("$.data.studies[*].id") + .value(Matchers.containsInAnyOrder("STUDY_1", "STUDY_2"))); + } +} diff --git a/src/test/java/org/cbioportal/legacy/web/SignificantCopyNumberRegionControllerTest.java b/src/test/java/org/cbioportal/legacy/web/SignificantCopyNumberRegionControllerTest.java new file mode 100644 index 00000000000..45811f54db7 --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/web/SignificantCopyNumberRegionControllerTest.java @@ -0,0 +1,193 @@ +package org.cbioportal.legacy.web; + +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.List; +import org.cbioportal.legacy.model.Gistic; +import org.cbioportal.legacy.model.GisticToGene; +import org.cbioportal.legacy.model.meta.BaseMeta; +import org.cbioportal.legacy.service.SignificantCopyNumberRegionService; +import org.cbioportal.legacy.web.config.TestConfig; +import org.cbioportal.legacy.web.parameter.HeaderKeyConstants; +import org.hamcrest.Matchers; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mockito; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; +import org.springframework.security.test.context.support.WithMockUser; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.result.MockMvcResultMatchers; + +@RunWith(SpringJUnit4ClassRunner.class) +@WebMvcTest +@ContextConfiguration(classes = {SignificantCopyNumberRegionController.class, TestConfig.class}) +public class SignificantCopyNumberRegionControllerTest { + + private static final Long TEST_GISTIC_ROI_ID_1 = 1L; + private static final String TEST_CANCER_STUDY_IDENTIFIER_1 = "test_study_1"; + private static final int TEST_CHROMOSOME_1 = 1; + private static final String TEST_CYTOBAND_1 = "1q1.1"; + private static final int TEST_WIDE_PEAK_START_1 = 123; + private static final int TEST_WIDE_PEAK_END_1 = 136; + private static final BigDecimal TEST_Q_VALUE_1 = new BigDecimal(0.1); + private static final Boolean TEST_AMP_1 = false; + private static final int TEST_ENTREZ_GENE_ID_1 = 1; + private static final String TEST_HUGO_GENE_SYMBOL_1 = "test_hugo_gene_symbol_1"; + private static final int TEST_ENTREZ_GENE_ID_2 = 2; + private static final String TEST_HUGO_GENE_SYMBOL_2 = "test_hugo_gene_symbol_2"; + private static final Long TEST_GISTIC_ROI_ID_2 = 2L; + private static final int TEST_CHROMOSOME_2 = 2; + private static final String TEST_CYTOBAND_2 = "2q1.1"; + private static final int TEST_WIDE_PEAK_START_2 = 223; + private static final int TEST_WIDE_PEAK_END_2 = 236; + private static final BigDecimal TEST_Q_VALUE_2 = new BigDecimal(0.2); + private static final Boolean TEST_AMP_2 = true; + private static final int TEST_ENTREZ_GENE_ID_3 = 3; + private static final String TEST_HUGO_GENE_SYMBOL_3 = "test_hugo_gene_symbol_3"; + private static final int TEST_ENTREZ_GENE_ID_4 = 4; + private static final String TEST_HUGO_GENE_SYMBOL_4 = "test_hugo_gene_symbol_4"; + + @MockBean private SignificantCopyNumberRegionService significantCopyNumberRegionService; + + @Autowired private MockMvc mockMvc; + + @Test + @WithMockUser + public void getSignificantCopyNumberRegions() throws Exception { + + List gisticList = new ArrayList<>(); + Gistic gistic1 = new Gistic(); + gistic1.setGisticRoiId(TEST_GISTIC_ROI_ID_1); + gistic1.setCancerStudyId(TEST_CANCER_STUDY_IDENTIFIER_1); + gistic1.setChromosome(TEST_CHROMOSOME_1); + gistic1.setCytoband(TEST_CYTOBAND_1); + gistic1.setWidePeakStart(TEST_WIDE_PEAK_START_1); + gistic1.setWidePeakEnd(TEST_WIDE_PEAK_END_1); + gistic1.setqValue(TEST_Q_VALUE_1); + gistic1.setAmp(TEST_AMP_1); + List gisticToGeneList1 = new ArrayList<>(); + GisticToGene gisticToGene1 = new GisticToGene(); + gisticToGene1.setGisticRoiId(TEST_GISTIC_ROI_ID_1); + gisticToGene1.setEntrezGeneId(TEST_ENTREZ_GENE_ID_1); + gisticToGene1.setHugoGeneSymbol(TEST_HUGO_GENE_SYMBOL_1); + gisticToGeneList1.add(gisticToGene1); + GisticToGene gisticToGene2 = new GisticToGene(); + gisticToGene2.setGisticRoiId(TEST_GISTIC_ROI_ID_1); + gisticToGene2.setEntrezGeneId(TEST_ENTREZ_GENE_ID_2); + gisticToGene2.setHugoGeneSymbol(TEST_HUGO_GENE_SYMBOL_2); + gisticToGeneList1.add(gisticToGene2); + gistic1.setGenes(gisticToGeneList1); + gisticList.add(gistic1); + Gistic gistic2 = new Gistic(); + gistic2.setGisticRoiId(TEST_GISTIC_ROI_ID_2); + gistic2.setCancerStudyId(TEST_CANCER_STUDY_IDENTIFIER_1); + gistic2.setChromosome(TEST_CHROMOSOME_2); + gistic2.setCytoband(TEST_CYTOBAND_2); + gistic2.setWidePeakStart(TEST_WIDE_PEAK_START_2); + gistic2.setWidePeakEnd(TEST_WIDE_PEAK_END_2); + gistic2.setqValue(TEST_Q_VALUE_2); + gistic2.setAmp(TEST_AMP_2); + List gisticToGeneList2 = new ArrayList<>(); + GisticToGene gisticToGene3 = new GisticToGene(); + gisticToGene3.setGisticRoiId(TEST_GISTIC_ROI_ID_2); + gisticToGene3.setEntrezGeneId(TEST_ENTREZ_GENE_ID_3); + gisticToGene3.setHugoGeneSymbol(TEST_HUGO_GENE_SYMBOL_3); + gisticToGeneList2.add(gisticToGene3); + GisticToGene gisticToGene4 = new GisticToGene(); + gisticToGene4.setGisticRoiId(TEST_GISTIC_ROI_ID_2); + gisticToGene4.setEntrezGeneId(TEST_ENTREZ_GENE_ID_4); + gisticToGene4.setHugoGeneSymbol(TEST_HUGO_GENE_SYMBOL_4); + gisticToGeneList2.add(gisticToGene4); + gistic2.setGenes(gisticToGeneList2); + gisticList.add(gistic2); + + Mockito.when( + significantCopyNumberRegionService.getSignificantCopyNumberRegions( + Mockito.any(), + Mockito.any(), + Mockito.any(), + Mockito.any(), + Mockito.any(), + Mockito.any())) + .thenReturn(gisticList); + + mockMvc + .perform( + MockMvcRequestBuilders.get("/api/studies/test_study_id/significant-copy-number-regions") + .accept(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect( + MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.jsonPath("$", Matchers.hasSize(2))) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].gisticRoiId").doesNotExist()) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].studyId").value(TEST_CANCER_STUDY_IDENTIFIER_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].chromosome").value(TEST_CHROMOSOME_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].cytoband").value(TEST_CYTOBAND_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].widePeakStart").value(TEST_WIDE_PEAK_START_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].widePeakEnd").value(TEST_WIDE_PEAK_END_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].qValue").value(TEST_Q_VALUE_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].amp").value(TEST_AMP_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].genes[0].entrezGeneId") + .value(TEST_ENTREZ_GENE_ID_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].genes[0].hugoGeneSymbol") + .value(TEST_HUGO_GENE_SYMBOL_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].genes[1].entrezGeneId") + .value(TEST_ENTREZ_GENE_ID_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].genes[1].hugoGeneSymbol") + .value(TEST_HUGO_GENE_SYMBOL_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].gisticRoiId").doesNotExist()) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].studyId").value(TEST_CANCER_STUDY_IDENTIFIER_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].chromosome").value(TEST_CHROMOSOME_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].cytoband").value(TEST_CYTOBAND_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].widePeakStart").value(TEST_WIDE_PEAK_START_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].widePeakEnd").value(TEST_WIDE_PEAK_END_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].qValue").value(TEST_Q_VALUE_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].amp").value(TEST_AMP_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].genes[0].entrezGeneId") + .value(TEST_ENTREZ_GENE_ID_3)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].genes[0].hugoGeneSymbol") + .value(TEST_HUGO_GENE_SYMBOL_3)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].genes[1].entrezGeneId") + .value(TEST_ENTREZ_GENE_ID_4)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].genes[1].hugoGeneSymbol") + .value(TEST_HUGO_GENE_SYMBOL_4)); + } + + @Test + @WithMockUser + public void getSignificantCopyNumberRegionsMetaProjection() throws Exception { + + BaseMeta baseMeta = new BaseMeta(); + baseMeta.setTotalCount(2); + + Mockito.when( + significantCopyNumberRegionService.getMetaSignificantCopyNumberRegions( + Mockito.anyString())) + .thenReturn(baseMeta); + + mockMvc + .perform( + MockMvcRequestBuilders.get("/api/studies/test_study_id/significant-copy-number-regions") + .param("projection", "META")) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect(MockMvcResultMatchers.header().string(HeaderKeyConstants.TOTAL_COUNT, "2")); + } +} diff --git a/src/test/java/org/cbioportal/legacy/web/SignificantlyMutatedGenesControllerTest.java b/src/test/java/org/cbioportal/legacy/web/SignificantlyMutatedGenesControllerTest.java new file mode 100644 index 00000000000..d1f3b0f0bb7 --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/web/SignificantlyMutatedGenesControllerTest.java @@ -0,0 +1,144 @@ +package org.cbioportal.legacy.web; + +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.List; +import org.cbioportal.legacy.model.MutSig; +import org.cbioportal.legacy.model.meta.BaseMeta; +import org.cbioportal.legacy.service.SignificantlyMutatedGeneService; +import org.cbioportal.legacy.web.config.TestConfig; +import org.cbioportal.legacy.web.parameter.HeaderKeyConstants; +import org.hamcrest.Matchers; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mockito; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; +import org.springframework.security.test.context.support.WithMockUser; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.result.MockMvcResultMatchers; + +@RunWith(SpringJUnit4ClassRunner.class) +@WebMvcTest +@ContextConfiguration(classes = {SignificantlyMutatedGenesController.class, TestConfig.class}) +public class SignificantlyMutatedGenesControllerTest { + + private static final int TEST_CANCER_STUDY_ID_1 = 1; + private static final String TEST_CANCER_STUDY_IDENTIFIER_1 = "test_study_1"; + private static final int TEST_ENTREZ_GENE_ID_1 = 1; + private static final String TEST_HUGO_GENE_SYMBOL_1 = "test_hugo_gene_symbol_1"; + private static final int TEST_RANK_1 = 1; + private static final int TEST_NUMBASESCOVERED_1 = 1; + private static final int TEST_NUMMUTATIONS_1 = 1; + private static final BigDecimal TEST_P_VALUE_1 = new BigDecimal(0.1); + private static final BigDecimal TEST_Q_VALUE_1 = new BigDecimal(0.1); + private static final int TEST_ENTREZ_GENE_ID_2 = 2; + private static final String TEST_HUGO_GENE_SYMBOL_2 = "test_hugo_gene_symbol_2"; + private static final int TEST_RANK_2 = 2; + private static final int TEST_NUMBASESCOVERED_2 = 2; + private static final int TEST_NUMMUTATIONS_2 = 2; + private static final BigDecimal TEST_P_VALUE_2 = new BigDecimal(0.2); + private static final BigDecimal TEST_Q_VALUE_2 = new BigDecimal(0.2); + + @MockBean private SignificantlyMutatedGeneService significantlyMutatedGeneService; + + @Autowired private MockMvc mockMvc; + + @Test + @WithMockUser + public void getSignificantlyMutatedGenesDefaultProjection() throws Exception { + + List mutSigList = new ArrayList<>(); + MutSig mutSig1 = new MutSig(); + mutSig1.setCancerStudyId(TEST_CANCER_STUDY_ID_1); + mutSig1.setCancerStudyIdentifier(TEST_CANCER_STUDY_IDENTIFIER_1); + mutSig1.setEntrezGeneId(TEST_ENTREZ_GENE_ID_1); + mutSig1.setHugoGeneSymbol(TEST_HUGO_GENE_SYMBOL_1); + mutSig1.setRank(TEST_RANK_1); + mutSig1.setNumbasescovered(TEST_NUMBASESCOVERED_1); + mutSig1.setNummutations(TEST_NUMMUTATIONS_1); + mutSig1.setpValue(TEST_P_VALUE_1); + mutSig1.setqValue(TEST_Q_VALUE_1); + mutSigList.add(mutSig1); + MutSig mutSig2 = new MutSig(); + mutSig2.setCancerStudyId(TEST_CANCER_STUDY_ID_1); + mutSig2.setCancerStudyIdentifier(TEST_CANCER_STUDY_IDENTIFIER_1); + mutSig2.setEntrezGeneId(TEST_ENTREZ_GENE_ID_2); + mutSig2.setHugoGeneSymbol(TEST_HUGO_GENE_SYMBOL_2); + mutSig2.setRank(TEST_RANK_2); + mutSig2.setNumbasescovered(TEST_NUMBASESCOVERED_2); + mutSig2.setNummutations(TEST_NUMMUTATIONS_2); + mutSig2.setpValue(TEST_P_VALUE_2); + mutSig2.setqValue(TEST_Q_VALUE_2); + mutSigList.add(mutSig2); + + Mockito.when( + significantlyMutatedGeneService.getSignificantlyMutatedGenes( + Mockito.any(), + Mockito.any(), + Mockito.any(), + Mockito.any(), + Mockito.any(), + Mockito.any())) + .thenReturn(mutSigList); + + mockMvc + .perform( + MockMvcRequestBuilders.get("/api/studies/test_study_id/significantly-mutated-genes") + .accept(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect( + MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.jsonPath("$", Matchers.hasSize(2))) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].cancerStudyId").doesNotExist()) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].studyId").value(TEST_CANCER_STUDY_IDENTIFIER_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].entrezGeneId").value(TEST_ENTREZ_GENE_ID_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].hugoGeneSymbol").value(TEST_HUGO_GENE_SYMBOL_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].numbasescovered").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].nummutations").doesNotExist()) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].numberOfMutations").value(TEST_NUMMUTATIONS_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].rank").value(TEST_RANK_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].pValue").value(TEST_P_VALUE_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].qValue").value(TEST_Q_VALUE_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].cancerStudyId").doesNotExist()) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].studyId").value(TEST_CANCER_STUDY_IDENTIFIER_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].entrezGeneId").value(TEST_ENTREZ_GENE_ID_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].hugoGeneSymbol").value(TEST_HUGO_GENE_SYMBOL_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].numbasescovered").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].nummutations").doesNotExist()) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].numberOfMutations").value(TEST_NUMMUTATIONS_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].rank").value(TEST_RANK_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].pValue").value(TEST_P_VALUE_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].qValue").value(TEST_Q_VALUE_2)); + } + + @Test + @WithMockUser + public void getSignificantlyMutatedGenesMetaProjection() throws Exception { + + BaseMeta baseMeta = new BaseMeta(); + baseMeta.setTotalCount(2); + + Mockito.when( + significantlyMutatedGeneService.getMetaSignificantlyMutatedGenes(Mockito.anyString())) + .thenReturn(baseMeta); + + mockMvc + .perform( + MockMvcRequestBuilders.get("/api/studies/test_study_id/significantly-mutated-genes") + .param("projection", "META")) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect(MockMvcResultMatchers.header().string(HeaderKeyConstants.TOTAL_COUNT, "2")); + } +} diff --git a/src/test/java/org/cbioportal/legacy/web/StaticDataTimestampControllerTest.java b/src/test/java/org/cbioportal/legacy/web/StaticDataTimestampControllerTest.java new file mode 100644 index 00000000000..214b13ef2eb --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/web/StaticDataTimestampControllerTest.java @@ -0,0 +1,41 @@ +package org.cbioportal.legacy.web; + +import java.util.HashMap; +import org.cbioportal.legacy.service.StaticDataTimestampService; +import org.cbioportal.legacy.web.config.TestConfig; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mockito; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; +import org.springframework.security.test.context.support.WithMockUser; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.result.MockMvcResultMatchers; + +@RunWith(SpringJUnit4ClassRunner.class) +@WebMvcTest +@ContextConfiguration(classes = {StaticDataTimestampController.class, TestConfig.class}) +public class StaticDataTimestampControllerTest { + + @MockBean private StaticDataTimestampService service; + + @Autowired private MockMvc mockMvc; + + @Test + @WithMockUser + public void getAllTimestamps() throws Exception { + HashMap pairs = new HashMap<>(); + pairs.put("gene", "1997-08-13 22:00:00"); + Mockito.when(service.getTimestamps(Mockito.anyList())).thenReturn(pairs); + + mockMvc + .perform(MockMvcRequestBuilders.get("/api/timestamps").accept(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect(MockMvcResultMatchers.jsonPath("$.gene").value("1997-08-13 22:00:00")); + } +} diff --git a/src/test/java/org/cbioportal/legacy/web/StructuralVariantControllerTest.java b/src/test/java/org/cbioportal/legacy/web/StructuralVariantControllerTest.java new file mode 100644 index 00000000000..fc1398c8c9b --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/web/StructuralVariantControllerTest.java @@ -0,0 +1,676 @@ +/* + * Copyright (c) 2018 - 2022 The Hyve B.V. + * This code is licensed under the GNU Affero General Public License (AGPL), + * version 3, or (at your option) any later version. + */ + +/* + * This file is part of cBioPortal. + * + * cBioPortal is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package org.cbioportal.legacy.web; + +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ObjectNode; +import java.util.ArrayList; +import java.util.List; +import org.cbioportal.legacy.model.StructuralVariant; +import org.cbioportal.legacy.model.StructuralVariantQuery; +import org.cbioportal.legacy.model.StructuralVariantSpecialValue; +import org.cbioportal.legacy.service.StructuralVariantService; +import org.cbioportal.legacy.web.config.TestConfig; +import org.cbioportal.legacy.web.parameter.SampleMolecularIdentifier; +import org.cbioportal.legacy.web.parameter.StructuralVariantFilter; +import org.hamcrest.Matchers; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; +import org.mockito.Mockito; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; +import org.springframework.security.test.context.support.WithMockUser; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.result.MockMvcResultMatchers; + +@RunWith(SpringJUnit4ClassRunner.class) +@WebMvcTest +@ContextConfiguration(classes = {StructuralVariantController.class, TestConfig.class}) +public class StructuralVariantControllerTest { + + private static final String TEST_GENETIC_PROFILE_STABLE_ID_1 = "test_genetic_profile_stable_id_1"; + private static final String TEST_SAMPLE_ID_1 = "test_sample_id_1"; + private static final String TEST_PATIENT_ID_1 = "test_patient_id_1"; + private static final String TEST_STUDY_ID_1 = "test_study_id_1"; + // Sample and Patient key are retrieved after response is given back + // TEST_UNIQUE_SAMPLE_KEY_1 decoded: test_sample_id_1:test_study_id_1 + private static final String TEST_UNIQUE_SAMPLE_KEY_1 = + "dGVzdF9zYW1wbGVfaWRfMTp0ZXN0X3N0dWR5X2lkXzE"; + // TEST_UNIQUE_PATIENT_KEY_1 decoded: test_patient_id_1:test_study_id_1 + private static final String TEST_UNIQUE_PATIENT_KEY_1 = + "dGVzdF9wYXRpZW50X2lkXzE6dGVzdF9zdHVkeV9pZF8x"; + private static final Integer TEST_SITE1_ENTREZ_GENE_ID_1 = 1; + private static final String TEST_SITE1_HUGO_SYMBOL_1 = "test_site1_hugo_symbol_1"; + private static final String TEST_SITE1_ENSEMBL_TRANSCRIPT_ID_1 = + "test_site1_ensembl_transcript_id_1"; + private static final String TEST_SITE1_CHROMOSOME_1 = "test_site1_chromosome_1"; + private static final String TEST_SITE1_REGION = "exon"; + private static final Integer TEST_SITE1_REGION_NUMBER = -1; + private static final String TEST_SITE1_CONTIG = "q13.4"; + private static final Integer TEST_SITE1_POSITION_1 = 1; + private static final String TEST_SITE1_DESCRIPTION_1 = "test_site1_description_1"; + private static final Integer TEST_SITE2_ENTREZ_GENE_ID_1 = 1; + private static final String TEST_SITE2_HUGO_SYMBOL_1 = "test_site2_hugo_symbol_1"; + private static final String TEST_SITE2_ENSEMBL_TRANSCRIPT_ID_1 = + "test_site2_ensembl_transcript_id_1"; + private static final String TEST_SITE2_CHROMOSOME_1 = "test_site2_chromosome_1"; + private static final String TEST_SITE2_REGION = "intron"; + private static final Integer TEST_SITE2_REGION_NUMBER = -1; + private static final String TEST_SITE2_CONTIG = "p13.1"; + private static final Integer TEST_SITE2_POSITION_1 = 1; + private static final String TEST_SITE2_DESCRIPTION_1 = "test_site2_description_1"; + private static final String TEST_SITE2_EFFECT_ON_FRAME_1 = "test_site2_effect_on_frame_1"; + private static final String TEST_NCBI_BUILD_1 = "test_ncbi_build_1"; + private static final String TEST_DNA_SUPPORT_1 = "test_dna_support_1"; + private static final String TEST_RNA_SUPPORT_1 = "test_rna_support_1"; + private static final Integer TEST_NORMAL_READ_COUNT_1 = 1; + private static final Integer TEST_TUMOR_READ_COUNT_1 = 1; + private static final Integer TEST_NORMAL_VARIANT_COUNT_1 = 1; + private static final Integer TEST_TUMOR_VARIANT_COUNT_1 = 1; + private static final Integer TEST_NORMAL_PAIRED_END_READ_COUNT_1 = 1; + private static final Integer TEST_TUMOR_PAIRED_END_READ_COUNT_1 = 1; + private static final Integer TEST_NORMAL_SPLIT_READ_COUNT_1 = 1; + private static final Integer TEST_TUMOR_SPLIT_READ_COUNT_1 = 1; + private static final String TEST_ANNOTATION_1 = "test_annotation_1"; + private static final String TEST_BREAKPOINT_TYPE_1 = "test_breakpoint_type_1"; + private static final String TEST_CONNECTION_TYPE_1 = "test_connection_type_1"; + private static final String TEST_EVENT_INFO_1 = "test_event_info_1"; + private static final String TEST_VARIANT_CLASS_1 = "test_variant_class_1"; + private static final Integer TEST_LENGTH_1 = 1; + private static final String TEST_COMMENTS_1 = "test_comments_1"; + private static final String TEST_DRIVER_FILTER_1 = "test_driver_filter_1"; + private static final String TEST_DRIVER_FILTER_ANN_1 = "test_driver_filter_ann_1"; + private static final String TEST_DRIVER_TIERS_FILTER_1 = "test_driver_tiers_filter_1"; + private static final String TEST_DRIVER_TIERS_FILTER_ANN_1 = "test_driver_tiers_filter_ann_1"; + private static final String TEST_SV_STATUS = "SOMATIC"; + private static final String TEST_ANNOTATION_JSON_1 = + "{\"columnName\":{\"fieldName\":\"fieldValue\"}}"; + + @MockBean private StructuralVariantService structuralVariantService; + + @Autowired private MockMvc mockMvc; + + private ObjectMapper objectMapper = new ObjectMapper(); + + @Test + @WithMockUser + public void fetchStructuralVariantsMolecularProfileId() throws Exception { + + List structuralVariant = createExampleStructuralVariant(); + + Mockito.when( + structuralVariantService.fetchStructuralVariants( + Mockito.anyList(), Mockito.anyList(), Mockito.anyList(), Mockito.any())) + .thenReturn(structuralVariant); + + StructuralVariantFilter structuralVariantFilter = + createStructuralVariantFilterMolecularProfileId(); + + mockMvc + .perform( + MockMvcRequestBuilders.post("/api/structural-variant/fetch") + .with(csrf()) + .accept(MediaType.parseMediaType("application/json;charset=UTF-8")) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(structuralVariantFilter))) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect( + MockMvcResultMatchers.content() + .contentType(MediaType.parseMediaType("application/json;charset=UTF-8"))) + .andExpect(MockMvcResultMatchers.jsonPath("$", Matchers.hasSize(1))) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].molecularProfileId") + .value(TEST_GENETIC_PROFILE_STABLE_ID_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].sampleId").value(TEST_SAMPLE_ID_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].patientId").value(TEST_PATIENT_ID_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].studyId").value(TEST_STUDY_ID_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].uniqueSampleKey").value(TEST_UNIQUE_SAMPLE_KEY_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].uniquePatientKey") + .value(TEST_UNIQUE_PATIENT_KEY_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].site1EntrezGeneId") + .value((int) TEST_SITE1_ENTREZ_GENE_ID_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].site1HugoSymbol").value(TEST_SITE1_HUGO_SYMBOL_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].site1EnsemblTranscriptId") + .value(TEST_SITE1_ENSEMBL_TRANSCRIPT_ID_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].site1Chromosome").value(TEST_SITE1_CHROMOSOME_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].site1Region").value(TEST_SITE1_REGION)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].site1RegionNumber") + .value(TEST_SITE1_REGION_NUMBER)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].site1Contig").value(TEST_SITE1_CONTIG)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].site1Position").value(TEST_SITE1_POSITION_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].site1Description").value(TEST_SITE1_DESCRIPTION_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].site2EntrezGeneId") + .value((int) TEST_SITE2_ENTREZ_GENE_ID_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].site2HugoSymbol").value(TEST_SITE2_HUGO_SYMBOL_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].site2EnsemblTranscriptId") + .value(TEST_SITE2_ENSEMBL_TRANSCRIPT_ID_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].site2Chromosome").value(TEST_SITE2_CHROMOSOME_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].site2Region").value(TEST_SITE2_REGION)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].site2RegionNumber") + .value(TEST_SITE2_REGION_NUMBER)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].site2Contig").value(TEST_SITE2_CONTIG)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].site2Position").value(TEST_SITE2_POSITION_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].site2Description").value(TEST_SITE2_DESCRIPTION_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].site2EffectOnFrame") + .value(TEST_SITE2_EFFECT_ON_FRAME_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].ncbiBuild").value(TEST_NCBI_BUILD_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].dnaSupport").value(TEST_DNA_SUPPORT_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].rnaSupport").value(TEST_RNA_SUPPORT_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].normalReadCount").value(TEST_NORMAL_READ_COUNT_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].tumorReadCount").value(TEST_TUMOR_READ_COUNT_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].normalVariantCount") + .value(TEST_NORMAL_VARIANT_COUNT_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].tumorVariantCount") + .value(TEST_TUMOR_VARIANT_COUNT_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].normalPairedEndReadCount") + .value(TEST_NORMAL_PAIRED_END_READ_COUNT_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].tumorPairedEndReadCount") + .value(TEST_TUMOR_PAIRED_END_READ_COUNT_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].normalSplitReadCount") + .value(TEST_NORMAL_SPLIT_READ_COUNT_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].tumorSplitReadCount") + .value(TEST_TUMOR_SPLIT_READ_COUNT_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].annotation").value(TEST_ANNOTATION_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].breakpointType").value(TEST_BREAKPOINT_TYPE_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].connectionType").value(TEST_CONNECTION_TYPE_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].eventInfo").value(TEST_EVENT_INFO_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].variantClass").value(TEST_VARIANT_CLASS_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].length").value(TEST_LENGTH_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].comments").value(TEST_COMMENTS_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].driverFilter").value(TEST_DRIVER_FILTER_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].driverFilterAnn").value(TEST_DRIVER_FILTER_ANN_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].driverTiersFilter") + .value(TEST_DRIVER_TIERS_FILTER_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].driverTiersFilterAnn") + .value(TEST_DRIVER_TIERS_FILTER_ANN_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].svStatus").value(TEST_SV_STATUS)); + } + + @Test + @WithMockUser + public void fetchStructuralVariantsSampleMolecularIdentifier() throws Exception { + + List structuralVariant = createExampleStructuralVariant(); + + Mockito.when( + structuralVariantService.fetchStructuralVariants( + Mockito.anyList(), Mockito.anyList(), Mockito.anyList(), Mockito.any())) + .thenReturn(structuralVariant); + + StructuralVariantFilter structuralVariantFilter = + createStructuralVariantFilterSampleMolecularIdentifier(); + + mockMvc + .perform( + MockMvcRequestBuilders.post("/api/structural-variant/fetch") + .with(csrf()) + .accept(MediaType.parseMediaType("application/json;charset=UTF-8")) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(structuralVariantFilter))) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect( + MockMvcResultMatchers.content() + .contentType(MediaType.parseMediaType("application/json;charset=UTF-8"))) + .andExpect(MockMvcResultMatchers.jsonPath("$", Matchers.hasSize(1))) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].molecularProfileId") + .value(TEST_GENETIC_PROFILE_STABLE_ID_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].sampleId").value(TEST_SAMPLE_ID_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].patientId").value(TEST_PATIENT_ID_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].studyId").value(TEST_STUDY_ID_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].uniqueSampleKey").value(TEST_UNIQUE_SAMPLE_KEY_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].uniquePatientKey") + .value(TEST_UNIQUE_PATIENT_KEY_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].site1EntrezGeneId") + .value((int) TEST_SITE1_ENTREZ_GENE_ID_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].site1HugoSymbol").value(TEST_SITE1_HUGO_SYMBOL_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].site1EnsemblTranscriptId") + .value(TEST_SITE1_ENSEMBL_TRANSCRIPT_ID_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].site1Chromosome").value(TEST_SITE1_CHROMOSOME_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].site1Region").value(TEST_SITE1_REGION)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].site1RegionNumber") + .value(TEST_SITE1_REGION_NUMBER)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].site1Contig").value(TEST_SITE1_CONTIG)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].site1Position").value(TEST_SITE1_POSITION_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].site1Description").value(TEST_SITE1_DESCRIPTION_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].site2EntrezGeneId") + .value((int) TEST_SITE2_ENTREZ_GENE_ID_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].site2HugoSymbol").value(TEST_SITE2_HUGO_SYMBOL_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].site2EnsemblTranscriptId") + .value(TEST_SITE2_ENSEMBL_TRANSCRIPT_ID_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].site2Chromosome").value(TEST_SITE2_CHROMOSOME_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].site2Region").value(TEST_SITE2_REGION)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].site2RegionNumber") + .value(TEST_SITE2_REGION_NUMBER)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].site2Contig").value(TEST_SITE2_CONTIG)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].site2Position").value(TEST_SITE2_POSITION_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].site2Description").value(TEST_SITE2_DESCRIPTION_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].site2EffectOnFrame") + .value(TEST_SITE2_EFFECT_ON_FRAME_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].ncbiBuild").value(TEST_NCBI_BUILD_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].dnaSupport").value(TEST_DNA_SUPPORT_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].rnaSupport").value(TEST_RNA_SUPPORT_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].normalReadCount").value(TEST_NORMAL_READ_COUNT_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].tumorReadCount").value(TEST_TUMOR_READ_COUNT_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].normalVariantCount") + .value(TEST_NORMAL_VARIANT_COUNT_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].tumorVariantCount") + .value(TEST_TUMOR_VARIANT_COUNT_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].normalPairedEndReadCount") + .value(TEST_NORMAL_PAIRED_END_READ_COUNT_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].tumorPairedEndReadCount") + .value(TEST_TUMOR_PAIRED_END_READ_COUNT_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].normalSplitReadCount") + .value(TEST_NORMAL_SPLIT_READ_COUNT_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].tumorSplitReadCount") + .value(TEST_TUMOR_SPLIT_READ_COUNT_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].annotation").value(TEST_ANNOTATION_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].breakpointType").value(TEST_BREAKPOINT_TYPE_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].connectionType").value(TEST_CONNECTION_TYPE_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].eventInfo").value(TEST_EVENT_INFO_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].variantClass").value(TEST_VARIANT_CLASS_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].length").value(TEST_LENGTH_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].comments").value(TEST_COMMENTS_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].driverFilter").value(TEST_DRIVER_FILTER_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].driverFilterAnn").value(TEST_DRIVER_FILTER_ANN_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].driverTiersFilter") + .value(TEST_DRIVER_TIERS_FILTER_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].driverTiersFilterAnn") + .value(TEST_DRIVER_TIERS_FILTER_ANN_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].svStatus").value(TEST_SV_STATUS)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].namespaceColumns.columnName.fieldName") + .value("fieldValue")); + } + + @Test + @WithMockUser + public void fetchStructuralVariantsBothMolecularProfileIdAndSampleMolecularIdentifier() + throws Exception { + + List structuralVariant = createExampleStructuralVariant(); + + Mockito.when( + structuralVariantService.fetchStructuralVariants( + Mockito.anyList(), Mockito.anyList(), Mockito.anyList(), Mockito.any())) + .thenReturn(structuralVariant); + + StructuralVariantFilter structuralVariantFilter = + createStructuralVariantFilterMolecularProfileIdAndSampleMolecularIdentifier(); + + mockMvc + .perform( + MockMvcRequestBuilders.post("/api/structural-variant/fetch") + .with(csrf()) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(structuralVariantFilter))) + .andExpect(MockMvcResultMatchers.status().isBadRequest()) + .andExpect( + MockMvcResultMatchers.jsonPath("$.message") + .value("interceptedStructuralVariantFilter must be true")); + } + + @Test + @WithMockUser + public void fetchStructuralVariantsWithBothEntrezIdsAndStructVariantIdsReturnsStatusOk() + throws Exception { + String structuralVariantFilter = + createStructuralVariantFilterWithEntrezIdAndStructuralVariantJson(); + mockMvc + .perform( + MockMvcRequestBuilders.post("/api/structural-variant/fetch") + .with(csrf()) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + .content(structuralVariantFilter)) + .andExpect(MockMvcResultMatchers.status().isOk()); + } + + @Test + @WithMockUser + public void fetchStructuralVariantsWithStructuralVariantSpecialQueryValues() throws Exception { + + List structuralVariant = createExampleStructuralVariant(); + + ArgumentCaptor> structVarIdCaptor = + ArgumentCaptor.forClass(ArrayList.class); + Mockito.when( + structuralVariantService.fetchStructuralVariants( + Mockito.anyList(), Mockito.anyList(), Mockito.any(), Mockito.any())) + .thenReturn(structuralVariant); + + String structuralVariantFilterJson = + createStructuralVariantFilterWithStructuralVariantWildcard(); + mockMvc + .perform( + MockMvcRequestBuilders.post("/api/structural-variant/fetch") + .with(csrf()) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + .content(structuralVariantFilterJson)) + .andExpect(MockMvcResultMatchers.status().isOk()); + + Mockito.verify(structuralVariantService) + .fetchStructuralVariants( + Mockito.anyList(), Mockito.anyList(), Mockito.any(), structVarIdCaptor.capture()); + + List capturedStructVarIds = structVarIdCaptor.getValue(); + Assert.assertEquals(capturedStructVarIds.size(), 2); + + Assert.assertEquals( + capturedStructVarIds.get(0).getGene1().getSpecialValue(), + StructuralVariantSpecialValue.ANY_GENE); + Assert.assertNull(capturedStructVarIds.get(0).getGene1().getEntrezId()); + Assert.assertEquals(capturedStructVarIds.get(0).getGene2().getEntrezId(), (Integer) 2); + Assert.assertNull(capturedStructVarIds.get(0).getGene2().getSpecialValue()); + + Assert.assertNull(capturedStructVarIds.get(1).getGene1().getSpecialValue()); + Assert.assertEquals(capturedStructVarIds.get(1).getGene1().getEntrezId(), (Integer) 1); + Assert.assertNull(capturedStructVarIds.get(1).getGene2().getEntrezId()); + Assert.assertEquals( + capturedStructVarIds.get(1).getGene2().getSpecialValue(), + StructuralVariantSpecialValue.NO_GENE); + } + + @Test + @WithMockUser + public void + fetchStructuralVariantsWithStructuralVariantIdWithNoIdAndSpecialValueReturnsBadRequest() + throws Exception { + + List structuralVariant = createExampleStructuralVariant(); + + Mockito.when( + structuralVariantService.fetchStructuralVariants( + Mockito.anyList(), Mockito.anyList(), Mockito.any(), Mockito.any())) + .thenReturn(structuralVariant); + + String structuralVariantFilterJson = + createStructuralVariantFilterWithEmptyStructuralVariantId(); + mockMvc + .perform( + MockMvcRequestBuilders.post("/api/structural-variant/fetch") + .with(csrf()) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + .content(structuralVariantFilterJson)) + .andExpect(MockMvcResultMatchers.status().isBadRequest()) + .andExpect( + MockMvcResultMatchers.jsonPath("$.message") + .value( + "interceptedStructuralVariantFilter " + + "Should contain only one EntrezId, hugoSymbol or specialValue.")); + } + + private List createExampleStructuralVariant() { + + List structuralVariantList = new ArrayList<>(); + StructuralVariant structuralVariant1 = new StructuralVariant(); + structuralVariant1.setMolecularProfileId(TEST_GENETIC_PROFILE_STABLE_ID_1); + structuralVariant1.setSampleId(TEST_SAMPLE_ID_1); + structuralVariant1.setPatientId(TEST_PATIENT_ID_1); + structuralVariant1.setStudyId(TEST_STUDY_ID_1); + structuralVariant1.setUniqueSampleKey(TEST_UNIQUE_SAMPLE_KEY_1); + structuralVariant1.setUniquePatientKey(TEST_UNIQUE_PATIENT_KEY_1); + structuralVariant1.setSite1EntrezGeneId(TEST_SITE1_ENTREZ_GENE_ID_1); + structuralVariant1.setSite1HugoSymbol(TEST_SITE1_HUGO_SYMBOL_1); + structuralVariant1.setSite1EnsemblTranscriptId(TEST_SITE1_ENSEMBL_TRANSCRIPT_ID_1); + structuralVariant1.setSite1Chromosome(TEST_SITE1_CHROMOSOME_1); + structuralVariant1.setSite1Region(TEST_SITE1_REGION); + structuralVariant1.setSite1RegionNumber(TEST_SITE1_REGION_NUMBER); + structuralVariant1.setSite1Contig(TEST_SITE1_CONTIG); + structuralVariant1.setSite1Position(TEST_SITE1_POSITION_1); + structuralVariant1.setSite1Description(TEST_SITE1_DESCRIPTION_1); + structuralVariant1.setSite2EntrezGeneId(TEST_SITE2_ENTREZ_GENE_ID_1); + structuralVariant1.setSite2HugoSymbol(TEST_SITE2_HUGO_SYMBOL_1); + structuralVariant1.setSite2EnsemblTranscriptId(TEST_SITE2_ENSEMBL_TRANSCRIPT_ID_1); + structuralVariant1.setSite2Chromosome(TEST_SITE2_CHROMOSOME_1); + structuralVariant1.setSite2Region(TEST_SITE2_REGION); + structuralVariant1.setSite2RegionNumber(TEST_SITE2_REGION_NUMBER); + structuralVariant1.setSite2Contig(TEST_SITE2_CONTIG); + structuralVariant1.setSite2Position(TEST_SITE2_POSITION_1); + structuralVariant1.setSite2Description(TEST_SITE2_DESCRIPTION_1); + structuralVariant1.setSite2EffectOnFrame(TEST_SITE2_EFFECT_ON_FRAME_1); + structuralVariant1.setNcbiBuild(TEST_NCBI_BUILD_1); + structuralVariant1.setDnaSupport(TEST_DNA_SUPPORT_1); + structuralVariant1.setRnaSupport(TEST_RNA_SUPPORT_1); + structuralVariant1.setNormalReadCount(TEST_NORMAL_READ_COUNT_1); + structuralVariant1.setTumorReadCount(TEST_TUMOR_READ_COUNT_1); + structuralVariant1.setNormalVariantCount(TEST_NORMAL_VARIANT_COUNT_1); + structuralVariant1.setTumorVariantCount(TEST_TUMOR_VARIANT_COUNT_1); + structuralVariant1.setNormalPairedEndReadCount(TEST_NORMAL_PAIRED_END_READ_COUNT_1); + structuralVariant1.setTumorPairedEndReadCount(TEST_TUMOR_PAIRED_END_READ_COUNT_1); + structuralVariant1.setNormalSplitReadCount(TEST_NORMAL_SPLIT_READ_COUNT_1); + structuralVariant1.setTumorSplitReadCount(TEST_TUMOR_SPLIT_READ_COUNT_1); + structuralVariant1.setAnnotation(TEST_ANNOTATION_1); + structuralVariant1.setBreakpointType(TEST_BREAKPOINT_TYPE_1); + structuralVariant1.setConnectionType(TEST_CONNECTION_TYPE_1); + structuralVariant1.setEventInfo(TEST_EVENT_INFO_1); + structuralVariant1.setVariantClass(TEST_VARIANT_CLASS_1); + structuralVariant1.setLength(TEST_LENGTH_1); + structuralVariant1.setComments(TEST_COMMENTS_1); + structuralVariant1.setDriverFilter(TEST_DRIVER_FILTER_1); + structuralVariant1.setDriverFilterAnn(TEST_DRIVER_FILTER_ANN_1); + structuralVariant1.setDriverTiersFilter(TEST_DRIVER_TIERS_FILTER_1); + structuralVariant1.setDriverTiersFilterAnn(TEST_DRIVER_TIERS_FILTER_ANN_1); + structuralVariant1.setSvStatus(TEST_SV_STATUS); + structuralVariant1.setAnnotationJson(TEST_ANNOTATION_JSON_1); + structuralVariantList.add(structuralVariant1); + return structuralVariantList; + } + + private StructuralVariantFilter createStructuralVariantFilterMolecularProfileId() { + + StructuralVariantFilter structuralVariantFilter = new StructuralVariantFilter(); + + List molecularProfileIds = new ArrayList<>(); + List entrezGeneIds = new ArrayList<>(); + molecularProfileIds.add(TEST_GENETIC_PROFILE_STABLE_ID_1); + entrezGeneIds.add(TEST_SITE1_ENTREZ_GENE_ID_1); + + structuralVariantFilter.setMolecularProfileIds(molecularProfileIds); + structuralVariantFilter.setEntrezGeneIds(entrezGeneIds); + return structuralVariantFilter; + } + + private StructuralVariantFilter createStructuralVariantFilterSampleMolecularIdentifier() { + + StructuralVariantFilter structuralVariantFilter = new StructuralVariantFilter(); + + List entrezGeneIds = new ArrayList<>(); + entrezGeneIds.add(TEST_SITE1_ENTREZ_GENE_ID_1); + + List sampleMolecularIdentifierList = new ArrayList<>(); + SampleMolecularIdentifier sampleMolecularIdentifier1 = new SampleMolecularIdentifier(); + sampleMolecularIdentifier1.setSampleId(TEST_SAMPLE_ID_1); + sampleMolecularIdentifier1.setMolecularProfileId(TEST_GENETIC_PROFILE_STABLE_ID_1); + sampleMolecularIdentifierList.add(sampleMolecularIdentifier1); + + structuralVariantFilter.setEntrezGeneIds(entrezGeneIds); + structuralVariantFilter.setSampleMolecularIdentifiers(sampleMolecularIdentifierList); + return structuralVariantFilter; + } + + private StructuralVariantFilter + createStructuralVariantFilterMolecularProfileIdAndSampleMolecularIdentifier() { + + StructuralVariantFilter structuralVariantFilter = new StructuralVariantFilter(); + + List molecularProfileIds = new ArrayList<>(); + List entrezGeneIds = new ArrayList<>(); + molecularProfileIds.add(TEST_GENETIC_PROFILE_STABLE_ID_1); + entrezGeneIds.add(TEST_SITE1_ENTREZ_GENE_ID_1); + + List sampleMolecularIdentifierList = new ArrayList<>(); + SampleMolecularIdentifier sampleMolecularIdentifier1 = new SampleMolecularIdentifier(); + sampleMolecularIdentifier1.setSampleId(TEST_SAMPLE_ID_1); + sampleMolecularIdentifier1.setMolecularProfileId(TEST_GENETIC_PROFILE_STABLE_ID_1); + sampleMolecularIdentifierList.add(sampleMolecularIdentifier1); + + structuralVariantFilter.setMolecularProfileIds(molecularProfileIds); + structuralVariantFilter.setEntrezGeneIds(entrezGeneIds); + structuralVariantFilter.setSampleMolecularIdentifiers(sampleMolecularIdentifierList); + return structuralVariantFilter; + } + + private String createStructuralVariantFilterWithEntrezIdAndStructuralVariantJson() + throws JsonProcessingException { + + StructuralVariantFilter structuralVariantFilter = new StructuralVariantFilter(); + + List sampleMolecularIdentifierList = new ArrayList<>(); + structuralVariantFilter.setSampleMolecularIdentifiers(sampleMolecularIdentifierList); + SampleMolecularIdentifier sampleMolecularIdentifier1 = new SampleMolecularIdentifier(); + sampleMolecularIdentifier1.setSampleId(TEST_SAMPLE_ID_1); + sampleMolecularIdentifier1.setMolecularProfileId(TEST_GENETIC_PROFILE_STABLE_ID_1); + sampleMolecularIdentifierList.add(sampleMolecularIdentifier1); + + List entrezGeneIds = new ArrayList<>(); + entrezGeneIds.add(TEST_SITE1_ENTREZ_GENE_ID_1); + structuralVariantFilter.setEntrezGeneIds(entrezGeneIds); + + ObjectNode jsonTree = objectMapper.valueToTree(structuralVariantFilter); + // Dummy entrez gene IDs: + jsonTree.put( + "structuralVariantQueries", + objectMapper.readTree("[{\"gene1\": {\"entrezId\": 1},\"gene2\": {\"entrezId\":2}}]")); + return jsonTree.toString(); + } + + private String createStructuralVariantFilterWithEmptyStructuralVariantId() + throws JsonProcessingException { + + StructuralVariantFilter structuralVariantFilter = new StructuralVariantFilter(); + + List sampleMolecularIdentifierList = new ArrayList<>(); + structuralVariantFilter.setSampleMolecularIdentifiers(sampleMolecularIdentifierList); + SampleMolecularIdentifier sampleMolecularIdentifier1 = new SampleMolecularIdentifier(); + sampleMolecularIdentifier1.setSampleId(TEST_SAMPLE_ID_1); + sampleMolecularIdentifier1.setMolecularProfileId(TEST_GENETIC_PROFILE_STABLE_ID_1); + sampleMolecularIdentifierList.add(sampleMolecularIdentifier1); + + ObjectNode jsonTree = objectMapper.valueToTree(structuralVariantFilter); + // All struct var query fields empty: + jsonTree.put( + "structuralVariantQueries", + objectMapper.readTree( + "[{\"gene1\": {\"entrezId\": null},\"gene2\": {\"entrezId\": null}}]")); + return jsonTree.toString(); + } + + private String createStructuralVariantFilterWithStructuralVariantWildcard() + throws JsonProcessingException { + + StructuralVariantFilter structuralVariantFilter = new StructuralVariantFilter(); + + List sampleMolecularIdentifierList = new ArrayList<>(); + structuralVariantFilter.setSampleMolecularIdentifiers(sampleMolecularIdentifierList); + SampleMolecularIdentifier sampleMolecularIdentifier1 = new SampleMolecularIdentifier(); + sampleMolecularIdentifier1.setSampleId(TEST_SAMPLE_ID_1); + sampleMolecularIdentifier1.setMolecularProfileId(TEST_GENETIC_PROFILE_STABLE_ID_1); + sampleMolecularIdentifierList.add(sampleMolecularIdentifier1); + + ObjectNode jsonTree = objectMapper.valueToTree(structuralVariantFilter); + // Replace with special wildcard and null oql values: + jsonTree.put( + "structuralVariantQueries", + objectMapper.readTree( + "[" + + "{\"gene1\": {\"specialValue\": \"ANY_GENE\"},\"gene2\": {\"entrezId\":2}}," + + "{\"gene1\": {\"entrezId\":1}, \"gene2\": {\"specialValue\":\"NO_GENE\"}}" + + "]")); + return jsonTree.toString(); + } +} diff --git a/src/test/java/org/cbioportal/legacy/web/StudyControllerTest.java b/src/test/java/org/cbioportal/legacy/web/StudyControllerTest.java new file mode 100644 index 00000000000..3291f95bb83 --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/web/StudyControllerTest.java @@ -0,0 +1,438 @@ +package org.cbioportal.legacy.web; + +import static org.mockito.ArgumentMatchers.eq; +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; + +import com.fasterxml.jackson.databind.ObjectMapper; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.TimeZone; +import org.cbioportal.legacy.model.CancerStudy; +import org.cbioportal.legacy.model.CancerStudyTags; +import org.cbioportal.legacy.model.TypeOfCancer; +import org.cbioportal.legacy.model.meta.BaseMeta; +import org.cbioportal.legacy.service.StudyService; +import org.cbioportal.legacy.service.exception.StudyNotFoundException; +import org.cbioportal.legacy.utils.security.AccessLevel; +import org.cbioportal.legacy.web.config.TestConfig; +import org.cbioportal.legacy.web.parameter.HeaderKeyConstants; +import org.hamcrest.Matchers; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mockito; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; +import org.springframework.security.test.context.support.WithMockUser; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.util.ReflectionTestUtils; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.result.MockMvcResultMatchers; + +@RunWith(SpringJUnit4ClassRunner.class) +@WebMvcTest +@ContextConfiguration(classes = {StudyController.class, TestConfig.class}) +public class StudyControllerTest { + + private static final int TEST_CANCER_STUDY_ID_1 = 1; + private static final String TEST_CANCER_STUDY_IDENTIFIER_1 = "test_study_1"; + private static final String TEST_TYPE_OF_CANCER_ID_1 = "test_type_of_cancer_id_1"; + private static final String TEST_NAME_1 = "test_name_1"; + private static final String TEST_DESCRIPTION_1 = "test_description_1"; + private static final boolean TEST_PUBLIC_STUDY_1 = true; + private static final String TEST_PMID_1 = "test_pmid_1"; + private static final String TEST_CITATION_1 = "test_citation_1"; + private static final String TEST_GROUPS_1 = "test_groups_1"; + private static final int TEST_STATUS_1 = 0; + private static final String TEST_DATE_1 = "2011-12-18 13:17:17"; + private static final String TEST_TAGS_1 = + "{\"Analyst\":{\"Name\":\"Jack\",\"Email\":\"jack@something.com\"},\"Load id\":35}"; + private static final int TEST_CANCER_STUDY_ID_2 = 2; + private static final String TEST_CANCER_STUDY_IDENTIFIER_2 = "test_study_2"; + private static final String TEST_TYPE_OF_CANCER_ID_2 = "test_type_of_cancer_id_2"; + private static final String TEST_NAME_2 = "test_name_2"; + private static final String TEST_DESCRIPTION_2 = "test_description_2"; + private static final boolean TEST_PUBLIC_STUDY_2 = true; + private static final String TEST_PMID_2 = "test_pmid_2"; + private static final String TEST_CITATION_2 = "test_citation_2"; + private static final String TEST_GROUPS_2 = "test_groups_2"; + private static final int TEST_STATUS_2 = 0; + private static final String TEST_DATE_2 = "2013-10-12 11:11:15"; + private static final String TEST_TAGS_2 = "{}"; + private static final String TEST_TYPE_OF_CANCER_NAME = "test_type_of_cancer_name"; + private static final String TEST_DEDICATED_COLOR = "test_dedicated_color"; + private static final String TEST_TYPE_OF_CANCER_SHORT_NAME = "test_type_of_cancer_short_name"; + private static final String TEST_PARENT = "test_parent"; + private static final String TEST_TAGS_3 = + "{\"Analyst\":{\"Name\":\"Frank\",\"Email\":\"frank@something.com\"},\"Load id\":43}"; + + @MockBean private StudyService studyService; + + @Autowired private StudyController studyController; + + private ObjectMapper objectMapper = new ObjectMapper(); + + @Autowired private MockMvc mockMvc; + + @Test + @WithMockUser + public void getAllStudiesDefaultProjection() throws Exception { + + List cancerStudyList = createExampleStudies(); + + Mockito.when( + studyService.getAllStudies( + Mockito.any(), + Mockito.any(), + Mockito.any(), + Mockito.any(), + Mockito.any(), + Mockito.any(), + Mockito.any(), + Mockito.any())) + .thenReturn(cancerStudyList); + + mockMvc + .perform(MockMvcRequestBuilders.get("/api/studies").accept(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect( + MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.jsonPath("$", Matchers.hasSize(2))) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].cancerStudyId").doesNotExist()) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].studyId").value(TEST_CANCER_STUDY_IDENTIFIER_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].citation").value(TEST_CITATION_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].description").value(TEST_DESCRIPTION_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].groups").value(TEST_GROUPS_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].importDate").value(TEST_DATE_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].name").value(TEST_NAME_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].pmid").value(TEST_PMID_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].publicStudy").value(TEST_PUBLIC_STUDY_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].status").value(TEST_STATUS_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].cancerTypeId").value(TEST_TYPE_OF_CANCER_ID_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].cancerStudyId").doesNotExist()) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].studyId").value(TEST_CANCER_STUDY_IDENTIFIER_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].citation").value(TEST_CITATION_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].description").value(TEST_DESCRIPTION_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].groups").value(TEST_GROUPS_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].importDate").value(TEST_DATE_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].name").value(TEST_NAME_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].pmid").value(TEST_PMID_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].publicStudy").value(TEST_PUBLIC_STUDY_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].status").value(TEST_STATUS_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].cancerTypeId").value(TEST_TYPE_OF_CANCER_ID_2)); + } + + @Test + @WithMockUser + public void getAllStudiesSetAccessLevelReadIsDefault() throws Exception { + + AccessLevel expectedAccessLevel = AccessLevel.READ; + Mockito.when( + studyService.getAllStudies( + Mockito.any(), + Mockito.any(), + Mockito.any(), + Mockito.any(), + Mockito.any(), + Mockito.any(), + Mockito.any(), + eq(expectedAccessLevel))) + .thenReturn(new ArrayList<>()); + + mockMvc + .perform(MockMvcRequestBuilders.get("/api/studies").accept(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.status().isOk()); + } + + @Test + @WithMockUser + public void getAllStudiesSetAccessLevelListConditionally() throws Exception { + + ReflectionTestUtils.setField(studyController, "showUnauthorizedStudiesOnHomePage", true); + + AccessLevel expectedAccessLevel = AccessLevel.LIST; + Mockito.when( + studyService.getAllStudies( + Mockito.any(), + Mockito.any(), + Mockito.any(), + Mockito.any(), + Mockito.any(), + Mockito.any(), + Mockito.any(), + eq(expectedAccessLevel))) + .thenReturn(new ArrayList<>()); + + mockMvc + .perform(MockMvcRequestBuilders.get("/api/studies").accept(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.status().isOk()); + + ReflectionTestUtils.setField(studyController, "showUnauthorizedStudiesOnHomePage", false); + } + + @Test + @WithMockUser + public void getAllStudiesMetaProjection() throws Exception { + + BaseMeta baseMeta = new BaseMeta(); + baseMeta.setTotalCount(2); + + Mockito.when(studyService.getMetaStudies(Mockito.any())).thenReturn(baseMeta); + + mockMvc + .perform(MockMvcRequestBuilders.get("/api/studies").param("projection", "META")) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect(MockMvcResultMatchers.header().string(HeaderKeyConstants.TOTAL_COUNT, "2")); + } + + @Test + @WithMockUser + public void getStudyNotFound() throws Exception { + + Mockito.when(studyService.getStudy(Mockito.anyString())) + .thenThrow(new StudyNotFoundException("test_study_id")); + + mockMvc + .perform( + MockMvcRequestBuilders.get("/api/studies/test_study_id") + .accept(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.status().isNotFound()) + .andExpect( + MockMvcResultMatchers.jsonPath("$.message").value("Study not found: test_study_id")); + } + + @Test + @WithMockUser + public void getStudy() throws Exception { + + SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + simpleDateFormat.setTimeZone(TimeZone.getTimeZone("UTC")); + + CancerStudy cancerStudy = new CancerStudy(); + cancerStudy.setCancerStudyId(TEST_CANCER_STUDY_ID_1); + cancerStudy.setCancerStudyIdentifier(TEST_CANCER_STUDY_IDENTIFIER_1); + cancerStudy.setTypeOfCancerId(TEST_TYPE_OF_CANCER_ID_1); + cancerStudy.setName(TEST_NAME_1); + cancerStudy.setDescription(TEST_DESCRIPTION_1); + cancerStudy.setPublicStudy(TEST_PUBLIC_STUDY_1); + cancerStudy.setPmid(TEST_PMID_1); + cancerStudy.setCitation(TEST_CITATION_1); + cancerStudy.setGroups(TEST_GROUPS_1); + cancerStudy.setStatus(TEST_STATUS_1); + cancerStudy.setImportDate(simpleDateFormat.parse(TEST_DATE_1)); + TypeOfCancer typeOfCancer = new TypeOfCancer(); + typeOfCancer.setTypeOfCancerId(TEST_TYPE_OF_CANCER_ID_1); + typeOfCancer.setName(TEST_TYPE_OF_CANCER_NAME); + typeOfCancer.setDedicatedColor(TEST_DEDICATED_COLOR); + typeOfCancer.setShortName(TEST_TYPE_OF_CANCER_SHORT_NAME); + typeOfCancer.setParent(TEST_PARENT); + cancerStudy.setTypeOfCancer(typeOfCancer); + + Mockito.when(studyService.getStudy(Mockito.anyString())).thenReturn(cancerStudy); + + mockMvc + .perform( + MockMvcRequestBuilders.get("/api/studies/test_study_id") + .accept(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect( + MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.jsonPath("$.cancerStudyId").doesNotExist()) + .andExpect( + MockMvcResultMatchers.jsonPath("$.studyId").value(TEST_CANCER_STUDY_IDENTIFIER_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$.citation").value(TEST_CITATION_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$.description").value(TEST_DESCRIPTION_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$.groups").value(TEST_GROUPS_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$.importDate").value(TEST_DATE_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$.name").value(TEST_NAME_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$.pmid").value(TEST_PMID_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$.publicStudy").value(TEST_PUBLIC_STUDY_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$.status").value(TEST_STATUS_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$.cancerTypeId").value(TEST_TYPE_OF_CANCER_ID_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$.cancerType.cancerTypeId") + .value(TEST_TYPE_OF_CANCER_ID_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$.cancerType.name").value(TEST_TYPE_OF_CANCER_NAME)) + .andExpect( + MockMvcResultMatchers.jsonPath("$.cancerType.dedicatedColor") + .value(TEST_DEDICATED_COLOR)) + .andExpect( + MockMvcResultMatchers.jsonPath("$.cancerType.shortName") + .value(TEST_TYPE_OF_CANCER_SHORT_NAME)) + .andExpect(MockMvcResultMatchers.jsonPath("$.cancerType.parent").value(TEST_PARENT)); + } + + @Test + @WithMockUser + public void fetchStudies() throws Exception { + + List cancerStudyList = createExampleStudies(); + + Mockito.when(studyService.fetchStudies(Mockito.anyList(), Mockito.anyString())) + .thenReturn(cancerStudyList); + + mockMvc + .perform( + MockMvcRequestBuilders.post("/api/studies/fetch") + .with(csrf()) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + .content( + objectMapper.writeValueAsString( + Arrays.asList( + TEST_CANCER_STUDY_IDENTIFIER_1, TEST_CANCER_STUDY_IDENTIFIER_2)))) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect( + MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.jsonPath("$", Matchers.hasSize(2))) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].cancerStudyId").doesNotExist()) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].studyId").value(TEST_CANCER_STUDY_IDENTIFIER_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].citation").value(TEST_CITATION_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].description").value(TEST_DESCRIPTION_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].groups").value(TEST_GROUPS_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].importDate").value(TEST_DATE_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].name").value(TEST_NAME_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].pmid").value(TEST_PMID_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].publicStudy").value(TEST_PUBLIC_STUDY_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].status").value(TEST_STATUS_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].cancerTypeId").value(TEST_TYPE_OF_CANCER_ID_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].cancerStudyId").doesNotExist()) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].studyId").value(TEST_CANCER_STUDY_IDENTIFIER_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].citation").value(TEST_CITATION_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].description").value(TEST_DESCRIPTION_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].groups").value(TEST_GROUPS_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].importDate").value(TEST_DATE_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].name").value(TEST_NAME_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].pmid").value(TEST_PMID_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].publicStudy").value(TEST_PUBLIC_STUDY_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].status").value(TEST_STATUS_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].cancerTypeId").value(TEST_TYPE_OF_CANCER_ID_2)); + } + + @Test + @WithMockUser + public void getTags() throws Exception { + AccessLevel expectedAccessLevel = AccessLevel.READ; + CancerStudyTags cancerStudyTags = new CancerStudyTags(); + cancerStudyTags.setTags(TEST_TAGS_1); + + Mockito.when(studyService.getTags(Mockito.anyString(), Mockito.eq(expectedAccessLevel))) + .thenReturn(cancerStudyTags); + + mockMvc + .perform( + MockMvcRequestBuilders.get("/api/studies/test_study_id/tags") + .accept(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect( + MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.content().string(TEST_TAGS_1)); + } + + @Test + @WithMockUser + public void getEmptyTags() throws Exception { + AccessLevel expectedAccessLevel = AccessLevel.READ; + Mockito.when(studyService.getTags(Mockito.anyString(), Mockito.eq(expectedAccessLevel))) + .thenReturn(null); + + mockMvc + .perform( + MockMvcRequestBuilders.get("/api/studies/test_study_id/tags") + .accept(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect( + MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.content().string(TEST_TAGS_2)); + } + + @Test + @WithMockUser + public void getAllTags() throws Exception { + + List cancerStudyTagsList = new ArrayList<>(); + CancerStudyTags cancerStudyTags1 = new CancerStudyTags(); + cancerStudyTags1.setCancerStudyId(TEST_CANCER_STUDY_ID_1); + cancerStudyTags1.setTags(TEST_TAGS_1); + cancerStudyTagsList.add(cancerStudyTags1); + + CancerStudyTags cancerStudyTags2 = new CancerStudyTags(); + cancerStudyTags2.setCancerStudyId(TEST_CANCER_STUDY_ID_2); + cancerStudyTags2.setTags(TEST_TAGS_3); + cancerStudyTagsList.add(cancerStudyTags2); + + Mockito.when(studyService.getTagsForMultipleStudies(Mockito.anyList())) + .thenReturn(cancerStudyTagsList); + + mockMvc + .perform( + MockMvcRequestBuilders.post("/api/studies/tags/fetch") + .with(csrf()) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + .content( + objectMapper.writeValueAsString( + Arrays.asList( + TEST_CANCER_STUDY_IDENTIFIER_1, TEST_CANCER_STUDY_IDENTIFIER_2)))) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect( + MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.jsonPath("$", Matchers.hasSize(2))) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].cancerStudyId").value(TEST_CANCER_STUDY_ID_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].tags").value(TEST_TAGS_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].cancerStudyId").value(TEST_CANCER_STUDY_ID_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].tags").value(TEST_TAGS_3)); + } + + private List createExampleStudies() throws ParseException { + + SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + simpleDateFormat.setTimeZone(TimeZone.getTimeZone("UTC")); + + List cancerStudyList = new ArrayList<>(); + CancerStudy cancerStudy1 = new CancerStudy(); + cancerStudy1.setCancerStudyId(TEST_CANCER_STUDY_ID_1); + cancerStudy1.setCancerStudyIdentifier(TEST_CANCER_STUDY_IDENTIFIER_1); + cancerStudy1.setTypeOfCancerId(TEST_TYPE_OF_CANCER_ID_1); + cancerStudy1.setName(TEST_NAME_1); + cancerStudy1.setDescription(TEST_DESCRIPTION_1); + cancerStudy1.setPublicStudy(TEST_PUBLIC_STUDY_1); + cancerStudy1.setPmid(TEST_PMID_1); + cancerStudy1.setCitation(TEST_CITATION_1); + cancerStudy1.setGroups(TEST_GROUPS_1); + cancerStudy1.setStatus(TEST_STATUS_1); + cancerStudy1.setImportDate(simpleDateFormat.parse(TEST_DATE_1)); + cancerStudyList.add(cancerStudy1); + CancerStudy cancerStudy2 = new CancerStudy(); + cancerStudy2.setCancerStudyId(TEST_CANCER_STUDY_ID_2); + cancerStudy2.setCancerStudyIdentifier(TEST_CANCER_STUDY_IDENTIFIER_2); + cancerStudy2.setTypeOfCancerId(TEST_TYPE_OF_CANCER_ID_2); + cancerStudy2.setName(TEST_NAME_2); + cancerStudy2.setDescription(TEST_DESCRIPTION_2); + cancerStudy2.setPublicStudy(TEST_PUBLIC_STUDY_2); + cancerStudy2.setPmid(TEST_PMID_2); + cancerStudy2.setCitation(TEST_CITATION_2); + cancerStudy2.setGroups(TEST_GROUPS_2); + cancerStudy2.setStatus(TEST_STATUS_2); + cancerStudy2.setImportDate(simpleDateFormat.parse(TEST_DATE_2)); + cancerStudyList.add(cancerStudy2); + return cancerStudyList; + } +} diff --git a/src/test/java/org/cbioportal/legacy/web/StudyViewControllerTest.java b/src/test/java/org/cbioportal/legacy/web/StudyViewControllerTest.java new file mode 100644 index 00000000000..58941b1905c --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/web/StudyViewControllerTest.java @@ -0,0 +1,1519 @@ +package org.cbioportal.legacy.web; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.anyList; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.anyString; +import static org.mockito.Mockito.reset; +import static org.mockito.Mockito.when; +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; + +import com.fasterxml.jackson.databind.ObjectMapper; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.cbioportal.legacy.model.AlterationCountByGene; +import org.cbioportal.legacy.model.AlterationFilter; +import org.cbioportal.legacy.model.ClinicalAttribute; +import org.cbioportal.legacy.model.ClinicalData; +import org.cbioportal.legacy.model.ClinicalDataCount; +import org.cbioportal.legacy.model.ClinicalDataCountItem; +import org.cbioportal.legacy.model.ClinicalEventTypeCount; +import org.cbioportal.legacy.model.CopyNumberCountByGene; +import org.cbioportal.legacy.model.GenericAssayDataCount; +import org.cbioportal.legacy.model.GenericAssayDataCountItem; +import org.cbioportal.legacy.model.GenomicDataCount; +import org.cbioportal.legacy.model.GenomicDataCountItem; +import org.cbioportal.legacy.model.NamespaceDataCount; +import org.cbioportal.legacy.model.NamespaceDataCountItem; +import org.cbioportal.legacy.model.Sample; +import org.cbioportal.legacy.model.SampleClinicalDataCollection; +import org.cbioportal.legacy.model.StructuralVariantFilterQuery; +import org.cbioportal.legacy.model.StructuralVariantSpecialValue; +import org.cbioportal.legacy.model.StudyViewStructuralVariantFilter; +import org.cbioportal.legacy.model.util.Select; +import org.cbioportal.legacy.persistence.AlterationRepository; +import org.cbioportal.legacy.service.AlterationCountService; +import org.cbioportal.legacy.service.ClinicalAttributeService; +import org.cbioportal.legacy.service.ClinicalDataService; +import org.cbioportal.legacy.service.ClinicalEventService; +import org.cbioportal.legacy.service.DiscreteCopyNumberService; +import org.cbioportal.legacy.service.GenePanelService; +import org.cbioportal.legacy.service.GeneService; +import org.cbioportal.legacy.service.MolecularProfileService; +import org.cbioportal.legacy.service.PatientService; +import org.cbioportal.legacy.service.SampleListService; +import org.cbioportal.legacy.service.SampleService; +import org.cbioportal.legacy.service.StudyViewService; +import org.cbioportal.legacy.service.TreatmentService; +import org.cbioportal.legacy.service.ViolinPlotService; +import org.cbioportal.legacy.service.util.ClinicalAttributeUtil; +import org.cbioportal.legacy.service.util.MolecularProfileUtil; +import org.cbioportal.legacy.utils.Encoder; +import org.cbioportal.legacy.web.config.TestConfig; +import org.cbioportal.legacy.web.parameter.ClinicalDataBinCountFilter; +import org.cbioportal.legacy.web.parameter.ClinicalDataBinFilter; +import org.cbioportal.legacy.web.parameter.ClinicalDataCountFilter; +import org.cbioportal.legacy.web.parameter.ClinicalDataFilter; +import org.cbioportal.legacy.web.parameter.GenericAssayDataCountFilter; +import org.cbioportal.legacy.web.parameter.GenericAssayDataFilter; +import org.cbioportal.legacy.web.parameter.GenomicDataCountFilter; +import org.cbioportal.legacy.web.parameter.GenomicDataFilter; +import org.cbioportal.legacy.web.parameter.NamespaceDataCountFilter; +import org.cbioportal.legacy.web.parameter.NamespaceDataFilter; +import org.cbioportal.legacy.web.parameter.SampleIdentifier; +import org.cbioportal.legacy.web.parameter.StudyViewFilter; +import org.cbioportal.legacy.web.util.ClinicalDataBinUtil; +import org.cbioportal.legacy.web.util.ClinicalDataFetcher; +import org.cbioportal.legacy.web.util.DataBinHelper; +import org.cbioportal.legacy.web.util.DataBinner; +import org.cbioportal.legacy.web.util.DiscreteDataBinner; +import org.cbioportal.legacy.web.util.LinearDataBinner; +import org.cbioportal.legacy.web.util.LogScaleDataBinner; +import org.cbioportal.legacy.web.util.ScientificSmallDataBinner; +import org.cbioportal.legacy.web.util.StudyViewFilterApplier; +import org.cbioportal.legacy.web.util.StudyViewFilterUtil; +import org.junit.Before; +import org.junit.Ignore; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; +import org.springframework.security.test.context.support.WithMockUser; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.ResultActions; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.result.MockMvcResultMatchers; + +@RunWith(SpringJUnit4ClassRunner.class) +@WebMvcTest +// TODO clean up dependencies for this test (use Mocks better) +// TODO Rework to accurately test StudyViewController +@ContextConfiguration( + classes = { + StudyViewController.class, + StudyViewFilterUtil.class, + MolecularProfileUtil.class, + ClinicalDataBinUtil.class, + DataBinner.class, + DiscreteDataBinner.class, + LinearDataBinner.class, + ScientificSmallDataBinner.class, + LogScaleDataBinner.class, + ClinicalDataBinUtil.class, + DataBinHelper.class, + TestConfig.class + }) +public class StudyViewControllerTest { + + private static final String TEST_STUDY_ID = "test_study_id"; + private static final String TEST_SAMPLE_ID_1 = "test_sample_id_1"; + private static final String TEST_SAMPLE_ID_2 = "test_sample_id_2"; + private static final String TEST_SAMPLE_ID_3 = "test_sample_id_3"; + private static final String TEST_PATIENT_ID_1 = "test_patient_id_1"; + private static final String TEST_PATIENT_ID_2 = "test_patient_id_2"; + private static final String TEST_PATIENT_ID_3 = "test_patient_id_3"; + private static final String TEST_ATTRIBUTE_ID = "test_attribute_id"; + private static final String TEST_CLINICAL_DATA_VALUE_1 = "value1"; + private static final String TEST_CLINICAL_DATA_VALUE_2 = "value2"; + private static final String TEST_CLINICAL_DATA_VALUE_3 = "3"; + private static final Integer TEST_ENTREZ_GENE_ID_1 = 1; + private static final Integer TEST_ENTREZ_GENE_ID_2 = 2; + private static final String TEST_HUGO_GENE_SYMBOL_1 = "test_hugo_gene_symbol_1"; + private static final String TEST_HUGO_GENE_SYMBOL_2 = "test_hugo_gene_symbol_2"; + private static final String TEST_CYTOBAND_1 = "test_cytoband_1"; + private static final String TEST_CYTOBAND_2 = "test_cytoband_2"; + private static final String TEST_STABLE_ID = "test_stable_id"; + private static final String TEST_GENERIC_ASSAY_DATA_VALUE_1 = "value1"; + private static final String TEST_GENERIC_ASSAY_DATA_VALUE_2 = "value2"; + private static final String TEST_CLINICAL_EVENT_TYPE = "STATUS"; + private static final Integer TEST_CLINICAL_EVENT_TYPE_COUNT = 513; + private static final String TEST_CNA_ALTERATION_NAME_1 = "test_cna_event_type_1"; + private static final String TEST_CNA_ALTERATION_NAME_2 = "test_cna_event_type_2"; + private static final String TEST_CNA_ALTERATION_VALUE_1 = "2"; + private static final String TEST_CNA_ALTERATION_VALUE_2 = "-2"; + private static final String TEST_MOLECULAR_PROFILE_TYPE = "test_molecular_profile_type"; + private static final String TEST_MUTATION_TYPE = "test_mutation_type"; + private static final String TEST_OUTER_KEY = "test_outer_key"; + private static final String TEST_INNER_KEY = "test_inner_key"; + private static final String TEST_NAMESPACE_DATA_VALUE_1 = "value1"; + private static final String TEST_NAMESPACE_DATA_VALUE_2 = "value2"; + + private List filteredSampleIdentifiers = new ArrayList<>(); + private List clinicalData = new ArrayList<>(); + private SampleClinicalDataCollection tableClinicalData; + + private ObjectMapper objectMapper = new ObjectMapper(); + + @MockBean private StudyViewFilterApplier studyViewFilterApplier; + @MockBean private ClinicalDataService clinicalDataService; + @MockBean private DiscreteCopyNumberService discreteCopyNumberService; + @MockBean private SampleService sampleService; + @MockBean private GenePanelService genePanelService; + @MockBean private ClinicalAttributeService clinicalAttributeService; + @MockBean private PatientService patientService; + + @MockBean public MolecularProfileUtil molecularProfileUtil; + + @MockBean public TreatmentService treatmentService; + + @MockBean public AlterationCountService alterationCountService; + + @MockBean public StudyViewService studyViewService; + + @MockBean public AlterationRepository alterationRepository; + + @MockBean private ClinicalDataFetcher clinicalDataFetcher; + + @MockBean private ClinicalAttributeUtil clinicalAttributeUtil; + + @MockBean private SampleListService sampleListService; + + @MockBean private MolecularProfileService molecularProfileService; + + @MockBean private ClinicalEventService clinicalEventService; + + @MockBean private GeneService geneService; + + @MockBean private ViolinPlotService violinPlotService; + + @MockBean private ClinicalDataBinUtil clinicalDataBinUtil; + + @Autowired private MockMvc mockMvc; + + private AlterationFilter alterationFilter = new AlterationFilter(); + + private ArrayList filteredSamples = new ArrayList<>(); + + private String uniqueKeySample1; + + @Before + public void setUp() throws Exception { + SampleIdentifier sampleIdentifier = new SampleIdentifier(); + sampleIdentifier.setSampleId(TEST_SAMPLE_ID_1); + sampleIdentifier.setStudyId(TEST_STUDY_ID); + filteredSampleIdentifiers.add(sampleIdentifier); + + Sample sample1 = new Sample(); + sample1.setStableId(TEST_SAMPLE_ID_1); + sample1.setPatientStableId(TEST_PATIENT_ID_1); + sample1.setCancerStudyIdentifier(TEST_STUDY_ID); + Sample sample2 = new Sample(); + sample2.setStableId(TEST_SAMPLE_ID_2); + sample2.setPatientStableId(TEST_PATIENT_ID_2); + sample2.setCancerStudyIdentifier(TEST_STUDY_ID); + filteredSamples.add(sample1); + filteredSamples.add(sample2); + + uniqueKeySample1 = Encoder.calculateBase64(TEST_SAMPLE_ID_1, TEST_STUDY_ID); + + ClinicalData clinicalData1 = new ClinicalData(); + clinicalData1.setAttrId(TEST_ATTRIBUTE_ID); + clinicalData1.setAttrValue(TEST_CLINICAL_DATA_VALUE_1); + clinicalData1.setStudyId(TEST_STUDY_ID); + clinicalData1.setSampleId(TEST_SAMPLE_ID_1); + clinicalData1.setPatientId(TEST_PATIENT_ID_1); + clinicalData.add(clinicalData1); + + ClinicalData clinicalData2 = new ClinicalData(); + clinicalData2.setAttrId(TEST_ATTRIBUTE_ID); + clinicalData2.setAttrValue(TEST_CLINICAL_DATA_VALUE_2); + clinicalData2.setStudyId(TEST_STUDY_ID); + clinicalData2.setSampleId(TEST_SAMPLE_ID_2); + clinicalData2.setPatientId(TEST_PATIENT_ID_2); + clinicalData.add(clinicalData2); + + ClinicalData clinicalData3 = new ClinicalData(); + clinicalData3.setAttrId(TEST_ATTRIBUTE_ID); + clinicalData3.setAttrValue(TEST_CLINICAL_DATA_VALUE_3); + clinicalData3.setStudyId(TEST_STUDY_ID); + clinicalData3.setSampleId(TEST_SAMPLE_ID_3); + clinicalData3.setPatientId(TEST_PATIENT_ID_3); + clinicalData.add(clinicalData3); + + Map> tableClinicalDataMap = new HashMap<>(); + tableClinicalDataMap.put( + uniqueKeySample1, List.of(clinicalData1, clinicalData2, clinicalData3)); + tableClinicalData = + SampleClinicalDataCollection.builder().withByUniqueSampleKey(tableClinicalDataMap).build(); + + reset(studyViewFilterApplier); + reset(clinicalDataService); + reset(discreteCopyNumberService); + reset(sampleService); + reset(genePanelService); + reset(sampleService); + reset(clinicalAttributeService); + reset(patientService); + } + + @Test + @WithMockUser + public void fetchClinicalDataCounts() throws Exception { + + List filteredSampleIdentifiers = new ArrayList<>(); + SampleIdentifier sampleIdentifier = new SampleIdentifier(); + sampleIdentifier.setSampleId(TEST_SAMPLE_ID_1); + sampleIdentifier.setStudyId(TEST_STUDY_ID); + filteredSampleIdentifiers.add(sampleIdentifier); + when(studyViewFilterApplier.apply(any())).thenReturn(filteredSampleIdentifiers); + + List clinicalDataCountItems = new ArrayList<>(); + ClinicalDataCountItem clinicalDataCountItem = new ClinicalDataCountItem(); + clinicalDataCountItem.setAttributeId(TEST_ATTRIBUTE_ID); + List clinicalDataCounts = new ArrayList<>(); + ClinicalDataCount clinicalDataCount1 = new ClinicalDataCount(); + clinicalDataCount1.setAttributeId(TEST_ATTRIBUTE_ID); + clinicalDataCount1.setValue(TEST_CLINICAL_DATA_VALUE_1); + clinicalDataCount1.setCount(3); + clinicalDataCounts.add(clinicalDataCount1); + ClinicalDataCount clinicalDataCount2 = new ClinicalDataCount(); + clinicalDataCount2.setAttributeId(TEST_ATTRIBUTE_ID); + clinicalDataCount2.setValue(TEST_CLINICAL_DATA_VALUE_2); + clinicalDataCount2.setCount(1); + clinicalDataCounts.add(clinicalDataCount2); + clinicalDataCountItem.setCounts(clinicalDataCounts); + clinicalDataCountItems.add(clinicalDataCountItem); + + when(clinicalDataService.fetchClinicalDataCounts(anyList(), anyList(), anyList())) + .thenReturn(clinicalDataCountItems); + + ClinicalDataCountFilter clinicalDataCountFilter = new ClinicalDataCountFilter(); + ClinicalDataFilter clinicalDataFilter = new ClinicalDataFilter(); + clinicalDataFilter.setAttributeId(TEST_ATTRIBUTE_ID); + clinicalDataCountFilter.setAttributes(Arrays.asList(clinicalDataFilter)); + StudyViewFilter studyViewFilter = new StudyViewFilter(); + studyViewFilter.setStudyIds(Arrays.asList(TEST_STUDY_ID)); + clinicalDataCountFilter.setStudyViewFilter(studyViewFilter); + + mockMvc + .perform( + MockMvcRequestBuilders.post("/api/clinical-data-counts/fetch") + .with(csrf()) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(clinicalDataCountFilter))) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect( + MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].attributeId").value(TEST_ATTRIBUTE_ID)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].counts[0].attributeId").doesNotExist()) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].counts[0].value") + .value(TEST_CLINICAL_DATA_VALUE_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].counts[0].count").value(3)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].counts[1].attributeId").doesNotExist()) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].counts[1].value") + .value(TEST_CLINICAL_DATA_VALUE_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].counts[1].count").value(1)); + } + + @Test + @WithMockUser + @Ignore + // TODO: Update Test currently out of scope of StudyViewController (need to make a new unit test + // to test ClinicalDataBinUtil) + public void fetchClinicalDataBinCounts() throws Exception { + List filteredSampleIdentifiers = new ArrayList<>(); + SampleIdentifier sampleIdentifier = new SampleIdentifier(); + sampleIdentifier.setSampleId(TEST_SAMPLE_ID_1); + sampleIdentifier.setStudyId(TEST_STUDY_ID); + filteredSampleIdentifiers.add(sampleIdentifier); + when(studyViewFilterApplier.apply(any())).thenReturn(filteredSampleIdentifiers); + + List clinicalData = new ArrayList<>(); + ClinicalData clinicalData1 = new ClinicalData(); + clinicalData1.setAttrId(TEST_ATTRIBUTE_ID); + clinicalData1.setAttrValue(TEST_CLINICAL_DATA_VALUE_1); + clinicalData1.setStudyId(TEST_STUDY_ID); + clinicalData1.setSampleId(TEST_SAMPLE_ID_1); + clinicalData1.setPatientId(TEST_PATIENT_ID_1); + clinicalData.add(clinicalData1); + ClinicalData clinicalData2 = new ClinicalData(); + clinicalData2.setAttrId(TEST_ATTRIBUTE_ID); + clinicalData2.setAttrValue(TEST_CLINICAL_DATA_VALUE_2); + clinicalData2.setStudyId(TEST_STUDY_ID); + clinicalData2.setSampleId(TEST_SAMPLE_ID_2); + clinicalData2.setPatientId(TEST_PATIENT_ID_2); + clinicalData.add(clinicalData2); + ClinicalData clinicalData3 = new ClinicalData(); + clinicalData3.setAttrId(TEST_ATTRIBUTE_ID); + clinicalData3.setAttrValue(TEST_CLINICAL_DATA_VALUE_3); + clinicalData3.setStudyId(TEST_STUDY_ID); + clinicalData3.setSampleId(TEST_SAMPLE_ID_3); + clinicalData.add(clinicalData3); + + when(clinicalDataService.fetchClinicalData( + anyList(), anyList(), anyList(), any(String.class), any(String.class))) + .thenReturn(clinicalData); + + ClinicalAttribute clinicalAttribute1 = new ClinicalAttribute(); + clinicalAttribute1.setAttrId(TEST_ATTRIBUTE_ID); + clinicalAttribute1.setPatientAttribute(false); + + when(clinicalAttributeService.getClinicalAttributesByStudyIdsAndAttributeIds( + anyList(), anyList())) + .thenReturn(Arrays.asList(clinicalAttribute1)); + + when(patientService.getPatientsOfSamples(anyList(), anyList())).thenReturn(Arrays.asList()); + + ClinicalDataBinCountFilter clinicalDataBinCountFilter = new ClinicalDataBinCountFilter(); + ClinicalDataBinFilter clinicalDataBinFilter = new ClinicalDataBinFilter(); + clinicalDataBinFilter.setAttributeId(TEST_ATTRIBUTE_ID); + clinicalDataBinFilter.setDisableLogScale(false); + clinicalDataBinCountFilter.setAttributes(Collections.singletonList(clinicalDataBinFilter)); + StudyViewFilter studyViewFilter = new StudyViewFilter(); + studyViewFilter.setStudyIds(Collections.singletonList(TEST_STUDY_ID)); + clinicalDataBinCountFilter.setStudyViewFilter(studyViewFilter); + + when(clinicalDataBinUtil.removeSelfFromFilter(any())).thenReturn(studyViewFilter); + + mockMvc + .perform( + MockMvcRequestBuilders.post("/api/clinical-data-bin-counts/fetch") + .with(csrf()) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(clinicalDataBinCountFilter))) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect( + MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].attributeId").value(TEST_ATTRIBUTE_ID)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].specialValue").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].start").value(3)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].end").value(3)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].count").value(1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].attributeId").value(TEST_ATTRIBUTE_ID)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].specialValue").value(TEST_CLINICAL_DATA_VALUE_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].start").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].end").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].count").value(1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[2].attributeId").value(TEST_ATTRIBUTE_ID)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[2].specialValue").value(TEST_CLINICAL_DATA_VALUE_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[2].start").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$[2].end").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$[2].count").value(1)); + } + + @Test + @WithMockUser + public void fetchMutatedGenes() throws Exception { + + List filteredSampleIdentifiers = new ArrayList<>(); + SampleIdentifier sampleIdentifier = new SampleIdentifier(); + sampleIdentifier.setSampleId(TEST_SAMPLE_ID_1); + sampleIdentifier.setStudyId(TEST_STUDY_ID); + filteredSampleIdentifiers.add(sampleIdentifier); + when(studyViewFilterApplier.apply(any())).thenReturn(filteredSampleIdentifiers); + + List mutationCounts = new ArrayList<>(); + AlterationCountByGene mutationCount1 = new AlterationCountByGene(); + mutationCount1.setEntrezGeneId(TEST_ENTREZ_GENE_ID_1); + mutationCount1.setHugoGeneSymbol(TEST_HUGO_GENE_SYMBOL_1); + mutationCount1.setNumberOfAlteredCases(1); + mutationCount1.setTotalCount(3); + mutationCounts.add(mutationCount1); + AlterationCountByGene mutationCount2 = new AlterationCountByGene(); + mutationCount2.setEntrezGeneId(TEST_ENTREZ_GENE_ID_2); + mutationCount2.setHugoGeneSymbol(TEST_HUGO_GENE_SYMBOL_2); + mutationCount2.setNumberOfAlteredCases(2); + mutationCount2.setTotalCount(2); + mutationCounts.add(mutationCount2); + + StudyViewFilter studyViewFilter = new StudyViewFilter(); + studyViewFilter.setStudyIds(Arrays.asList(TEST_STUDY_ID)); + + when(studyViewService.getMutationAlterationCountByGenes( + eq(Arrays.asList(TEST_STUDY_ID)), + eq(Arrays.asList(TEST_SAMPLE_ID_1)), + any(AlterationFilter.class))) + .thenReturn(mutationCounts); + + mockMvc + .perform( + MockMvcRequestBuilders.post("/api/mutated-genes/fetch") + .with(csrf()) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(studyViewFilter))) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect( + MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].entrezGeneId").value(TEST_ENTREZ_GENE_ID_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].hugoGeneSymbol").value(TEST_HUGO_GENE_SYMBOL_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].numberOfAlteredCases").value(1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].totalCount").value(3)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].entrezGeneId").value(TEST_ENTREZ_GENE_ID_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].hugoGeneSymbol").value(TEST_HUGO_GENE_SYMBOL_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].numberOfAlteredCases").value(2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].totalCount").value(2)); + } + + @Test + @WithMockUser + public void fetchFusionGenes() throws Exception { + + List filteredSampleIdentifiers = new ArrayList<>(); + SampleIdentifier sampleIdentifier = new SampleIdentifier(); + sampleIdentifier.setSampleId(TEST_SAMPLE_ID_1); + sampleIdentifier.setStudyId(TEST_STUDY_ID); + filteredSampleIdentifiers.add(sampleIdentifier); + when(studyViewFilterApplier.apply(any())).thenReturn(filteredSampleIdentifiers); + + List structuralVariantCounts = new ArrayList<>(); + AlterationCountByGene structuralVariantCount1 = new AlterationCountByGene(); + structuralVariantCount1.setEntrezGeneId(TEST_ENTREZ_GENE_ID_1); + structuralVariantCount1.setHugoGeneSymbol(TEST_HUGO_GENE_SYMBOL_1); + structuralVariantCount1.setNumberOfAlteredCases(1); + structuralVariantCount1.setTotalCount(1); + structuralVariantCounts.add(structuralVariantCount1); + AlterationCountByGene structuralVariantCount2 = new AlterationCountByGene(); + structuralVariantCount2.setEntrezGeneId(TEST_ENTREZ_GENE_ID_2); + structuralVariantCount2.setHugoGeneSymbol(TEST_HUGO_GENE_SYMBOL_2); + structuralVariantCount2.setNumberOfAlteredCases(2); + structuralVariantCount2.setTotalCount(2); + structuralVariantCounts.add(structuralVariantCount2); + + when(studyViewService.getStructuralVariantAlterationCountByGenes( + eq(Arrays.asList(TEST_STUDY_ID)), + eq(Arrays.asList(TEST_SAMPLE_ID_1)), + any(AlterationFilter.class))) + .thenReturn(structuralVariantCounts); + + StudyViewFilter studyViewFilter = new StudyViewFilter(); + studyViewFilter.setStudyIds(Arrays.asList(TEST_STUDY_ID)); + + mockMvc + .perform( + MockMvcRequestBuilders.post("/api/structuralvariant-genes/fetch") + .with(csrf()) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(studyViewFilter))) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect( + MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].entrezGeneId").value(TEST_ENTREZ_GENE_ID_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].hugoGeneSymbol").value(TEST_HUGO_GENE_SYMBOL_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].numberOfAlteredCases").value(1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].totalCount").value(1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].entrezGeneId").value(TEST_ENTREZ_GENE_ID_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].hugoGeneSymbol").value(TEST_HUGO_GENE_SYMBOL_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].numberOfAlteredCases").value(2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].totalCount").value(2)); + } + + @Test + @WithMockUser + public void fetchCNAGenes() throws Exception { + + List filteredSampleIdentifiers = new ArrayList<>(); + SampleIdentifier sampleIdentifier = new SampleIdentifier(); + sampleIdentifier.setSampleId(TEST_SAMPLE_ID_1); + sampleIdentifier.setStudyId(TEST_STUDY_ID); + filteredSampleIdentifiers.add(sampleIdentifier); + when(studyViewFilterApplier.apply(any())).thenReturn(filteredSampleIdentifiers); + + List cnaCounts = new ArrayList<>(); + CopyNumberCountByGene cnaCount1 = new CopyNumberCountByGene(); + cnaCount1.setEntrezGeneId(TEST_ENTREZ_GENE_ID_1); + cnaCount1.setHugoGeneSymbol(TEST_HUGO_GENE_SYMBOL_1); + cnaCount1.setNumberOfAlteredCases(1); + cnaCount1.setCytoband(TEST_CYTOBAND_1); + cnaCount1.setAlteration(-2); + cnaCounts.add(cnaCount1); + CopyNumberCountByGene cnaCount2 = new CopyNumberCountByGene(); + cnaCount2.setEntrezGeneId(TEST_ENTREZ_GENE_ID_2); + cnaCount2.setHugoGeneSymbol(TEST_HUGO_GENE_SYMBOL_2); + cnaCount2.setNumberOfAlteredCases(2); + cnaCount2.setCytoband(TEST_CYTOBAND_2); + cnaCount2.setAlteration(2); + cnaCounts.add(cnaCount2); + + when(studyViewService.getCNAAlterationCountByGenes( + eq(Arrays.asList(TEST_STUDY_ID)), + eq(Arrays.asList(TEST_SAMPLE_ID_1)), + any(AlterationFilter.class))) + .thenReturn(cnaCounts); + + StudyViewFilter studyViewFilter = new StudyViewFilter(); + studyViewFilter.setStudyIds(Arrays.asList(TEST_STUDY_ID)); + + mockMvc + .perform( + MockMvcRequestBuilders.post("/api/cna-genes/fetch") + .with(csrf()) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(studyViewFilter))) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect( + MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].entrezGeneId").value(TEST_ENTREZ_GENE_ID_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].hugoGeneSymbol").value(TEST_HUGO_GENE_SYMBOL_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].numberOfAlteredCases").value(1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].cytoband").value(TEST_CYTOBAND_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].alteration").value(-2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].totalCount").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].entrezGeneId").value(TEST_ENTREZ_GENE_ID_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].hugoGeneSymbol").value(TEST_HUGO_GENE_SYMBOL_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].numberOfAlteredCases").value(2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].cytoband").value(TEST_CYTOBAND_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].alteration").value(2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].totalCount").doesNotExist()); + } + + @Test + @WithMockUser + public void fetchSampleIds() throws Exception { + + List filteredSampleIdentifiers = new ArrayList<>(); + SampleIdentifier sampleIdentifier = new SampleIdentifier(); + sampleIdentifier.setSampleId(TEST_SAMPLE_ID_1); + sampleIdentifier.setStudyId(TEST_STUDY_ID); + filteredSampleIdentifiers.add(sampleIdentifier); + + when(studyViewFilterApplier.apply(any())).thenReturn(filteredSampleIdentifiers); + when(studyViewFilterApplier.apply(any(), eq(false))).thenReturn(filteredSampleIdentifiers); + + List filteredSamples = new ArrayList<>(); + Sample sample1 = new Sample(); + sample1.setStableId(TEST_SAMPLE_ID_1); + sample1.setPatientStableId(TEST_PATIENT_ID_1); + sample1.setCancerStudyIdentifier(TEST_STUDY_ID); + filteredSamples.add(sample1); + Sample sample2 = new Sample(); + sample2.setStableId(TEST_SAMPLE_ID_2); + sample2.setPatientStableId(TEST_PATIENT_ID_2); + sample2.setCancerStudyIdentifier(TEST_STUDY_ID); + filteredSamples.add(sample2); + + when(sampleService.fetchSamples(anyList(), anyList(), anyString())).thenReturn(filteredSamples); + + StudyViewFilter studyViewFilter = new StudyViewFilter(); + studyViewFilter.setStudyIds(Arrays.asList(TEST_STUDY_ID)); + + mockMvc + .perform( + MockMvcRequestBuilders.post("/api/filtered-samples/fetch") + .with(csrf()) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(studyViewFilter))) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect( + MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].sampleId").value(TEST_SAMPLE_ID_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].patientId").value(TEST_PATIENT_ID_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].studyId").value(TEST_STUDY_ID)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].sampleId").value(TEST_SAMPLE_ID_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].patientId").value(TEST_PATIENT_ID_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].studyId").value(TEST_STUDY_ID)); + } + + @Test + @WithMockUser + public void fetchSampleCounts() throws Exception { + + SampleIdentifier sampleIdentifier2 = new SampleIdentifier(); + sampleIdentifier2.setSampleId(TEST_SAMPLE_ID_2); + sampleIdentifier2.setStudyId(TEST_STUDY_ID); + filteredSampleIdentifiers.add(sampleIdentifier2); + SampleIdentifier sampleIdentifier3 = new SampleIdentifier(); + sampleIdentifier3.setSampleId(TEST_SAMPLE_ID_3); + sampleIdentifier3.setStudyId(TEST_STUDY_ID); + filteredSampleIdentifiers.add(sampleIdentifier3); + when(studyViewFilterApplier.apply(any())).thenReturn(filteredSampleIdentifiers); + + StudyViewFilter studyViewFilter = new StudyViewFilter(); + studyViewFilter.setStudyIds(Arrays.asList(TEST_STUDY_ID)); + + List genomicDataCounts = new ArrayList<>(); + GenomicDataCount genomicDataCount1 = new GenomicDataCount(); + genomicDataCount1.setLabel("Profile 2"); + genomicDataCount1.setValue("profile_type_2"); + genomicDataCount1.setCount(1); + genomicDataCounts.add(genomicDataCount1); + GenomicDataCount genomicDataCount2 = new GenomicDataCount(); + genomicDataCount2.setLabel("Profile 1"); + genomicDataCount2.setValue("profile_type_1"); + genomicDataCount2.setCount(2); + genomicDataCounts.add(genomicDataCount2); + when(studyViewService.getGenomicDataCounts( + Arrays.asList(TEST_STUDY_ID, TEST_STUDY_ID, TEST_STUDY_ID), + Arrays.asList(TEST_SAMPLE_ID_1, TEST_SAMPLE_ID_2, TEST_SAMPLE_ID_3))) + .thenReturn(genomicDataCounts); + + mockMvc + .perform( + MockMvcRequestBuilders.post("/api/molecular-profile-sample-counts/fetch") + .with(csrf()) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(studyViewFilter))) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect( + MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].label").value("Profile 2")) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].value").value("profile_type_2")) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].count").value(1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].label").value("Profile 1")) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].value").value("profile_type_1")) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].count").value(2)); + } + + @Test + @WithMockUser + public void fetchGenomicDataCounts() throws Exception { + + when(studyViewFilterApplier.apply(any())).thenReturn(filteredSampleIdentifiers); + + List genomicDataCountItems = new ArrayList<>(); + + GenomicDataCount genomicDataCount1 = new GenomicDataCount(); + genomicDataCount1.setLabel(TEST_CNA_ALTERATION_NAME_1); + genomicDataCount1.setValue(TEST_CNA_ALTERATION_VALUE_1); + genomicDataCount1.setCount(1); + + GenomicDataCount genomicDataCount2 = new GenomicDataCount(); + genomicDataCount2.setLabel(TEST_CNA_ALTERATION_NAME_2); + genomicDataCount2.setValue(TEST_CNA_ALTERATION_VALUE_2); + genomicDataCount2.setCount(1); + + GenomicDataCountItem genomicDataCountItem1 = new GenomicDataCountItem(); + List genomicDataCounts1 = new ArrayList<>(); + genomicDataCounts1.add(genomicDataCount1); + genomicDataCounts1.add(genomicDataCount2); + genomicDataCountItem1.setHugoGeneSymbol(TEST_HUGO_GENE_SYMBOL_1); + genomicDataCountItem1.setProfileType(TEST_MOLECULAR_PROFILE_TYPE); + genomicDataCountItem1.setCounts(genomicDataCounts1); + + GenomicDataCountItem genomicDataCountItem2 = new GenomicDataCountItem(); + List genomicDataCounts2 = new ArrayList<>(); + genomicDataCounts2.add(genomicDataCount1); + genomicDataCounts2.add(genomicDataCount2); + genomicDataCountItem2.setHugoGeneSymbol(TEST_HUGO_GENE_SYMBOL_2); + genomicDataCountItem2.setProfileType(TEST_MOLECULAR_PROFILE_TYPE); + genomicDataCountItem2.setCounts(genomicDataCounts2); + + genomicDataCountItems.add(genomicDataCountItem1); + genomicDataCountItems.add(genomicDataCountItem2); + + when(studyViewService.getCNAAlterationCountsByGeneSpecific(anyList(), anyList(), anyList())) + .thenReturn(genomicDataCountItems); + + GenomicDataCountFilter genomicDataCountFilter = new GenomicDataCountFilter(); + List genomicDataFilters = new ArrayList<>(); + + GenomicDataFilter genomicDataFilter1 = new GenomicDataFilter(); + genomicDataFilter1.setHugoGeneSymbol(TEST_HUGO_GENE_SYMBOL_1); + genomicDataFilter1.setProfileType(TEST_MOLECULAR_PROFILE_TYPE); + genomicDataFilters.add(genomicDataFilter1); + + GenomicDataFilter genomicDataFilter2 = new GenomicDataFilter(); + genomicDataFilter2.setHugoGeneSymbol(TEST_HUGO_GENE_SYMBOL_2); + genomicDataFilter2.setProfileType(TEST_MOLECULAR_PROFILE_TYPE); + genomicDataFilters.add(genomicDataFilter2); + + genomicDataCountFilter.setGenomicDataFilters(genomicDataFilters); + + StudyViewFilter studyViewFilter = new StudyViewFilter(); + studyViewFilter.setStudyIds(Arrays.asList(TEST_STUDY_ID)); + genomicDataCountFilter.setStudyViewFilter(studyViewFilter); + + mockMvc + .perform( + MockMvcRequestBuilders.post("/api/genomic-data-counts/fetch") + .with(csrf()) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(genomicDataCountFilter))) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect( + MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].hugoGeneSymbol").value(TEST_HUGO_GENE_SYMBOL_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].profileType").value(TEST_MOLECULAR_PROFILE_TYPE)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].counts[0].label") + .value(TEST_CNA_ALTERATION_NAME_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].counts[0].value") + .value(TEST_CNA_ALTERATION_VALUE_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].counts[0].count").value(1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].counts[1].label") + .value(TEST_CNA_ALTERATION_NAME_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].counts[1].value") + .value(TEST_CNA_ALTERATION_VALUE_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].counts[1].count").value(1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].hugoGeneSymbol").value(TEST_HUGO_GENE_SYMBOL_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].profileType").value(TEST_MOLECULAR_PROFILE_TYPE)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].counts[0].label") + .value(TEST_CNA_ALTERATION_NAME_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].counts[0].value") + .value(TEST_CNA_ALTERATION_VALUE_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].counts[0].count").value(1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].counts[1].label") + .value(TEST_CNA_ALTERATION_NAME_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].counts[1].value") + .value(TEST_CNA_ALTERATION_VALUE_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].counts[1].count").value(1)); + } + + @Ignore("Skip StudyViewControllerTest.fetchClinicalDataDensityPlot due to assertion errors") + @Test + @WithMockUser + public void fetchClinicalDataDensityPlot() throws Exception { + + List filteredSampleIdentifiers = new ArrayList<>(); + SampleIdentifier sampleIdentifier = new SampleIdentifier(); + sampleIdentifier.setSampleId(TEST_SAMPLE_ID_1); + sampleIdentifier.setStudyId(TEST_STUDY_ID); + filteredSampleIdentifiers.add(sampleIdentifier); + when(studyViewFilterApplier.apply(any())).thenReturn(filteredSampleIdentifiers); + + ClinicalAttribute clinicalAttribute1 = new ClinicalAttribute(); + clinicalAttribute1.setAttrId("FRACTION_GENOME_ALTERED"); + clinicalAttribute1.setPatientAttribute(false); + ClinicalAttribute clinicalAttribute2 = new ClinicalAttribute(); + clinicalAttribute2.setAttrId("MUTATION_COUNT"); + clinicalAttribute2.setPatientAttribute(false); + + when(clinicalAttributeService.getClinicalAttributesByStudyIdsAndAttributeIds( + anyList(), anyList())) + .thenReturn(Arrays.asList(clinicalAttribute1, clinicalAttribute2)); + + List clinicalData = new ArrayList<>(); + ClinicalData clinicalData1 = new ClinicalData(); + clinicalData1.setAttrId("FRACTION_GENOME_ALTERED"); + clinicalData1.setAttrValue("0.2"); + clinicalData1.setStudyId(TEST_STUDY_ID); + clinicalData1.setSampleId(TEST_SAMPLE_ID_1); + clinicalData.add(clinicalData1); + ClinicalData clinicalData2 = new ClinicalData(); + clinicalData2.setAttrId("MUTATION_COUNT"); + clinicalData2.setAttrValue("16"); + clinicalData2.setStudyId(TEST_STUDY_ID); + clinicalData2.setSampleId(TEST_SAMPLE_ID_1); + clinicalData.add(clinicalData2); + ClinicalData clinicalData3 = new ClinicalData(); + clinicalData3.setAttrId("FRACTION_GENOME_ALTERED"); + clinicalData3.setAttrValue("0.44"); + clinicalData3.setStudyId(TEST_STUDY_ID); + clinicalData3.setSampleId(TEST_SAMPLE_ID_2); + clinicalData.add(clinicalData3); + ClinicalData clinicalData4 = new ClinicalData(); + clinicalData4.setAttrId("MUTATION_COUNT"); + clinicalData4.setAttrValue("123"); + clinicalData4.setStudyId(TEST_STUDY_ID); + clinicalData4.setSampleId(TEST_SAMPLE_ID_2); + clinicalData.add(clinicalData4); + ClinicalData clinicalData5 = new ClinicalData(); + clinicalData5.setAttrId("FRACTION_GENOME_ALTERED"); + clinicalData5.setAttrValue("1.0"); + clinicalData5.setStudyId(TEST_STUDY_ID); + clinicalData5.setSampleId(TEST_SAMPLE_ID_3); + clinicalData.add(clinicalData5); + ClinicalData clinicalData6 = new ClinicalData(); + clinicalData6.setAttrId("MUTATION_COUNT"); + clinicalData6.setAttrValue("400"); + clinicalData6.setStudyId(TEST_STUDY_ID); + clinicalData6.setSampleId(TEST_SAMPLE_ID_3); + clinicalData.add(clinicalData6); + + when(clinicalDataService.fetchClinicalData( + anyList(), anyList(), anyList(), anyString(), anyString())) + .thenReturn(clinicalData); + + StudyViewFilter studyViewFilter = new StudyViewFilter(); + studyViewFilter.setStudyIds(Arrays.asList(TEST_STUDY_ID)); + + mockMvc + .perform( + MockMvcRequestBuilders.post("/api/clinical-data-density-plot/fetch") + .with(csrf()) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(studyViewFilter)) + .param("xAxisAttributeId", "FRACTION_GENOME_ALTERED") + .param("xAxisBinCount", "3") + .param("xAxisStart", "0.0") + .param("xAxisEnd", "1.0") + .param("yAxisAttributeId", "MUTATION_COUNT") + .param("yAxisBinCount", "3")) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect( + MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.jsonPath("$.bins[0].binX").value(0.0)) + .andExpect(MockMvcResultMatchers.jsonPath("$.bins[0].binY").value(16.0)) + .andExpect(MockMvcResultMatchers.jsonPath("$.bins[0].minX").value(0.2)) + .andExpect(MockMvcResultMatchers.jsonPath("$.bins[0].maxX").value(0.2)) + .andExpect(MockMvcResultMatchers.jsonPath("$.bins[0].minY").value(16.0)) + .andExpect(MockMvcResultMatchers.jsonPath("$.bins[0].maxY").value(16.0)) + .andExpect(MockMvcResultMatchers.jsonPath("$.bins[0].count").value(1)) + .andExpect(MockMvcResultMatchers.jsonPath("$.bins[1].binX").value(0.0)) + .andExpect(MockMvcResultMatchers.jsonPath("$.bins[1].binY").value(144.0)) + .andExpect(MockMvcResultMatchers.jsonPath("$.bins[1].minX").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$.bins[1].maxX").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$.bins[1].minY").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$.bins[1].maxY").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$.bins[1].count").value(0)) + .andExpect(MockMvcResultMatchers.jsonPath("$.bins[2].binX").value(0.0)) + .andExpect(MockMvcResultMatchers.jsonPath("$.bins[2].binY").value(272.0)) + .andExpect(MockMvcResultMatchers.jsonPath("$.bins[2].minX").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$.bins[2].maxX").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$.bins[2].minY").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$.bins[2].maxY").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$.bins[2].count").value(0)) + .andExpect(MockMvcResultMatchers.jsonPath("$.bins[3].binX").value(0.3333333333333333)) + .andExpect(MockMvcResultMatchers.jsonPath("$.bins[3].binY").value(16.0)) + .andExpect(MockMvcResultMatchers.jsonPath("$.bins[3].minX").value(0.44)) + .andExpect(MockMvcResultMatchers.jsonPath("$.bins[3].maxX").value(0.44)) + .andExpect(MockMvcResultMatchers.jsonPath("$.bins[3].minY").value(123.0)) + .andExpect(MockMvcResultMatchers.jsonPath("$.bins[3].maxY").value(123.0)) + .andExpect(MockMvcResultMatchers.jsonPath("$.bins[3].count").value(1)) + .andExpect(MockMvcResultMatchers.jsonPath("$.bins[4].binX").value(0.3333333333333333)) + .andExpect(MockMvcResultMatchers.jsonPath("$.bins[4].binY").value(144.0)) + .andExpect(MockMvcResultMatchers.jsonPath("$.bins[4].minX").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$.bins[4].maxX").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$.bins[4].minY").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$.bins[4].maxY").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$.bins[4].count").value(0)) + .andExpect(MockMvcResultMatchers.jsonPath("$.bins[5].binX").value(0.3333333333333333)) + .andExpect(MockMvcResultMatchers.jsonPath("$.bins[5].binY").value(272.0)) + .andExpect(MockMvcResultMatchers.jsonPath("$.bins[5].minX").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$.bins[5].maxX").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$.bins[5].minY").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$.bins[5].maxY").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$.bins[5].count").value(0)) + .andExpect(MockMvcResultMatchers.jsonPath("$.bins[6].binX").value(0.6666666666666666)) + .andExpect(MockMvcResultMatchers.jsonPath("$.bins[6].binY").value(16.0)) + .andExpect(MockMvcResultMatchers.jsonPath("$.bins[6].minX").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$.bins[6].maxX").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$.bins[6].minY").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$.bins[6].maxY").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$.bins[6].count").value(0)) + .andExpect(MockMvcResultMatchers.jsonPath("$.bins[7].binX").value(0.6666666666666666)) + .andExpect(MockMvcResultMatchers.jsonPath("$.bins[7].binY").value(144.0)) + .andExpect(MockMvcResultMatchers.jsonPath("$.bins[7].minX").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$.bins[7].maxX").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$.bins[7].minY").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$.bins[7].maxY").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$.bins[7].count").value(0)) + .andExpect(MockMvcResultMatchers.jsonPath("$.bins[8].binX").value(0.6666666666666666)) + .andExpect(MockMvcResultMatchers.jsonPath("$.bins[8].binY").value(272.0)) + .andExpect(MockMvcResultMatchers.jsonPath("$.bins[8].minX").value(1.0)) + .andExpect(MockMvcResultMatchers.jsonPath("$.bins[8].maxX").value(1.0)) + .andExpect(MockMvcResultMatchers.jsonPath("$.bins[8].minY").value(400.0)) + .andExpect(MockMvcResultMatchers.jsonPath("$.bins[8].maxY").value(400.0)) + .andExpect(MockMvcResultMatchers.jsonPath("$.bins[8].count").value(1)) + .andExpect(MockMvcResultMatchers.jsonPath("$.pearsonCorr").value(0.9997290539897087)) + .andExpect(MockMvcResultMatchers.jsonPath("$.spearmanCorr").value(1)); + + mockMvc + .perform( + MockMvcRequestBuilders.post("/clinical-data-density-plot/fetch") + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(studyViewFilter)) + .param("xAxisAttributeId", "FRACTION_GENOME_ALTERED") + .param("xAxisBinCount", "3") + .param("xAxisStart", "0.0") + .param("xAxisEnd", "1.0") + .param("yAxisAttributeId", "MUTATION_COUNT") + .param("yAxisBinCount", "3") + .param("yAxisLogScale", "true")) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect( + MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.jsonPath("$.bins[0].binX").value(0.0)) + .andExpect(MockMvcResultMatchers.jsonPath("$.bins[0].binY").value(2.833213344056216)) + .andExpect(MockMvcResultMatchers.jsonPath("$.bins[0].minX").value(0.2)) + .andExpect(MockMvcResultMatchers.jsonPath("$.bins[0].maxX").value(0.2)) + .andExpect(MockMvcResultMatchers.jsonPath("$.bins[0].minY").value(2.833213344056216)) + .andExpect(MockMvcResultMatchers.jsonPath("$.bins[0].maxY").value(2.833213344056216)) + .andExpect(MockMvcResultMatchers.jsonPath("$.bins[0].count").value(1)) + .andExpect(MockMvcResultMatchers.jsonPath("$.bins[1].binX").value(0.0)) + .andExpect(MockMvcResultMatchers.jsonPath("$.bins[1].binY").value(3.8867960384730003)) + .andExpect(MockMvcResultMatchers.jsonPath("$.bins[1].minX").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$.bins[1].maxX").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$.bins[1].minY").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$.bins[1].maxY").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$.bins[1].count").value(0)) + .andExpect(MockMvcResultMatchers.jsonPath("$.bins[2].binX").value(0.0)) + .andExpect(MockMvcResultMatchers.jsonPath("$.bins[2].binY").value(4.940378732889785)) + .andExpect(MockMvcResultMatchers.jsonPath("$.bins[2].minX").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$.bins[2].maxX").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$.bins[2].minY").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$.bins[2].maxY").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$.bins[2].count").value(0)) + .andExpect(MockMvcResultMatchers.jsonPath("$.bins[3].binX").value(0.3333333333333333)) + .andExpect(MockMvcResultMatchers.jsonPath("$.bins[3].binY").value(2.833213344056216)) + .andExpect(MockMvcResultMatchers.jsonPath("$.bins[3].minX").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$.bins[3].maxX").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$.bins[3].minY").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$.bins[3].maxY").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$.bins[3].count").value(0)) + .andExpect(MockMvcResultMatchers.jsonPath("$.bins[4].binX").value(0.3333333333333333)) + .andExpect(MockMvcResultMatchers.jsonPath("$.bins[4].binY").value(3.8867960384730003)) + .andExpect(MockMvcResultMatchers.jsonPath("$.bins[4].minX").value(0.44)) + .andExpect(MockMvcResultMatchers.jsonPath("$.bins[4].maxX").value(0.44)) + .andExpect(MockMvcResultMatchers.jsonPath("$.bins[4].minY").value(4.820281565605037)) + .andExpect(MockMvcResultMatchers.jsonPath("$.bins[4].maxY").value(4.820281565605037)) + .andExpect(MockMvcResultMatchers.jsonPath("$.bins[4].count").value(1)) + .andExpect(MockMvcResultMatchers.jsonPath("$.bins[5].binX").value(0.3333333333333333)) + .andExpect(MockMvcResultMatchers.jsonPath("$.bins[5].binY").value(4.940378732889785)) + .andExpect(MockMvcResultMatchers.jsonPath("$.bins[5].minX").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$.bins[5].maxX").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$.bins[5].minY").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$.bins[5].maxY").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$.bins[5].count").value(0)) + .andExpect(MockMvcResultMatchers.jsonPath("$.bins[6].binX").value(0.6666666666666666)) + .andExpect(MockMvcResultMatchers.jsonPath("$.bins[6].binY").value(2.833213344056216)) + .andExpect(MockMvcResultMatchers.jsonPath("$.bins[6].minX").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$.bins[6].maxX").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$.bins[6].minY").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$.bins[6].maxY").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$.bins[6].count").value(0)) + .andExpect(MockMvcResultMatchers.jsonPath("$.bins[7].binX").value(0.6666666666666666)) + .andExpect(MockMvcResultMatchers.jsonPath("$.bins[7].binY").value(3.8867960384730003)) + .andExpect(MockMvcResultMatchers.jsonPath("$.bins[7].minX").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$.bins[7].maxX").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$.bins[7].minY").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$.bins[7].maxY").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$.bins[7].count").value(0)) + .andExpect(MockMvcResultMatchers.jsonPath("$.bins[8].binX").value(0.6666666666666666)) + .andExpect(MockMvcResultMatchers.jsonPath("$.bins[8].binY").value(4.940378732889785)) + .andExpect(MockMvcResultMatchers.jsonPath("$.bins[8].minX").value(1.0)) + .andExpect(MockMvcResultMatchers.jsonPath("$.bins[8].maxX").value(1.0)) + .andExpect(MockMvcResultMatchers.jsonPath("$.bins[8].minY").value(5.993961427306569)) + .andExpect(MockMvcResultMatchers.jsonPath("$.bins[8].maxY").value(5.993961427306569)) + .andExpect(MockMvcResultMatchers.jsonPath("$.bins[8].count").value(1)) + .andExpect(MockMvcResultMatchers.jsonPath("$.pearsonCorr").value(0.9307061280832044)) + .andExpect(MockMvcResultMatchers.jsonPath("$.spearmanCorr").value(1)); + } + + @Test + @WithMockUser + public void fetchGenericAssayDataCounts() throws Exception { + + List filteredSampleIdentifiers = new ArrayList<>(); + SampleIdentifier sampleIdentifier = new SampleIdentifier(); + sampleIdentifier.setSampleId(TEST_SAMPLE_ID_1); + sampleIdentifier.setStudyId(TEST_STUDY_ID); + filteredSampleIdentifiers.add(sampleIdentifier); + when(studyViewFilterApplier.apply(any())).thenReturn(filteredSampleIdentifiers); + + List genericAssayDataCountItems = new ArrayList<>(); + GenericAssayDataCountItem genericAssayDataCountItem = new GenericAssayDataCountItem(); + genericAssayDataCountItem.setStableId(TEST_STABLE_ID); + List genericAssayDataCounts = new ArrayList<>(); + GenericAssayDataCount genericAssayDataCount1 = new GenericAssayDataCount(); + genericAssayDataCount1.setValue(TEST_GENERIC_ASSAY_DATA_VALUE_1); + genericAssayDataCount1.setCount(3); + genericAssayDataCounts.add(genericAssayDataCount1); + GenericAssayDataCount genericAssayDataCount2 = new GenericAssayDataCount(); + genericAssayDataCount2.setValue(TEST_GENERIC_ASSAY_DATA_VALUE_2); + genericAssayDataCount2.setCount(1); + genericAssayDataCounts.add(genericAssayDataCount2); + genericAssayDataCountItem.setCounts(genericAssayDataCounts); + genericAssayDataCountItems.add(genericAssayDataCountItem); + + when(studyViewService.fetchGenericAssayDataCounts(anyList(), anyList(), anyList(), anyList())) + .thenReturn(genericAssayDataCountItems); + + GenericAssayDataCountFilter genericAssayDataCountFilter = new GenericAssayDataCountFilter(); + GenericAssayDataFilter genericAssayDataFilter = new GenericAssayDataFilter(); + genericAssayDataFilter.setStableId(TEST_STABLE_ID); + genericAssayDataCountFilter.setGenericAssayDataFilters(Arrays.asList(genericAssayDataFilter)); + StudyViewFilter studyViewFilter = new StudyViewFilter(); + studyViewFilter.setStudyIds(Arrays.asList(TEST_STUDY_ID)); + genericAssayDataCountFilter.setStudyViewFilter(studyViewFilter); + + mockMvc + .perform( + MockMvcRequestBuilders.post("/api/generic-assay-data-counts/fetch") + .with(csrf()) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(genericAssayDataCountFilter))) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect( + MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].stableId").value(TEST_STABLE_ID)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].counts[0].value") + .value(TEST_GENERIC_ASSAY_DATA_VALUE_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].counts[0].count").value(3)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].counts[1].value") + .value(TEST_GENERIC_ASSAY_DATA_VALUE_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].counts[1].count").value(1)); + } + + @Test + @WithMockUser + public void fetchClinicalDataClinicalTable() throws Exception { + // For this sake of this test the sample clinical data and patient clinical data are identical. + when(clinicalDataService.fetchSampleClinicalTable( + anyList(), anyList(), anyInt(), anyInt(), anyString(), any(), anyString())) + .thenReturn(new ImmutablePair<>(tableClinicalData, 100)); + + StudyViewFilter studyViewFilter = new StudyViewFilter(); + studyViewFilter.setStudyIds(Arrays.asList(TEST_STUDY_ID)); + + when(studyViewFilterApplier.apply(any())).thenReturn(filteredSampleIdentifiers); + + String jsonPath = "$.byUniqueSampleKey." + uniqueKeySample1; + + mockMvc + .perform( + MockMvcRequestBuilders.post("/api/clinical-data-table/fetch") + .with(csrf()) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(studyViewFilter))) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect( + MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect( + MockMvcResultMatchers.jsonPath(jsonPath + "[0].clinicalAttributeId", uniqueKeySample1) + .value(TEST_ATTRIBUTE_ID)) + .andExpect( + MockMvcResultMatchers.jsonPath(jsonPath + "[0].sampleId").value(TEST_SAMPLE_ID_1)) + .andExpect( + MockMvcResultMatchers.jsonPath(jsonPath + "[1].clinicalAttributeId") + .value(TEST_ATTRIBUTE_ID)) + .andExpect( + MockMvcResultMatchers.jsonPath(jsonPath + "[1].sampleId").value(TEST_SAMPLE_ID_2)) + .andExpect( + MockMvcResultMatchers.jsonPath(jsonPath + "[2].clinicalAttributeId") + .value(TEST_ATTRIBUTE_ID)) + .andExpect( + MockMvcResultMatchers.jsonPath(jsonPath + "[2].sampleId").value(TEST_SAMPLE_ID_3)); + } + + @Test + @WithMockUser + public void fetchClinicalEventTypeCounts() throws Exception { + List testEventTypeCounts = + Arrays.asList( + new ClinicalEventTypeCount(TEST_CLINICAL_EVENT_TYPE, TEST_CLINICAL_EVENT_TYPE_COUNT)); + + when(studyViewFilterApplier.apply(any())).thenReturn(filteredSampleIdentifiers); + when(clinicalEventService.getClinicalEventTypeCounts(anyList(), anyList())) + .thenReturn(testEventTypeCounts); + + StudyViewFilter studyViewFilter = new StudyViewFilter(); + studyViewFilter.setStudyIds(Collections.singletonList(TEST_STUDY_ID)); + + mockMvc + .perform( + MockMvcRequestBuilders.post("/api/clinical-event-type-counts/fetch") + .with(csrf()) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(studyViewFilter))) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect( + MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].eventType").value(TEST_CLINICAL_EVENT_TYPE)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].count").value(TEST_CLINICAL_EVENT_TYPE_COUNT)); + } + + @Test + @WithMockUser + public void validateStructVarFilter() throws Exception { + + when(studyViewFilterApplier.apply(any())).thenReturn(filteredSampleIdentifiers); + when(studyViewFilterApplier.apply(any(), eq(false))).thenReturn(filteredSampleIdentifiers); + + List filteredSamples = new ArrayList<>(); + Sample sample1 = new Sample(); + sample1.setStableId(TEST_SAMPLE_ID_1); + sample1.setPatientStableId(TEST_PATIENT_ID_1); + sample1.setCancerStudyIdentifier(TEST_STUDY_ID); + filteredSamples.add(sample1); + Sample sample2 = new Sample(); + sample2.setStableId(TEST_SAMPLE_ID_2); + sample2.setPatientStableId(TEST_PATIENT_ID_2); + sample2.setCancerStudyIdentifier(TEST_STUDY_ID); + filteredSamples.add(sample2); + + when(sampleService.fetchSamples(anyList(), anyList(), anyString())).thenReturn(filteredSamples); + + StudyViewFilter studyViewFilter = new StudyViewFilter(); + studyViewFilter.setStudyIds(Arrays.asList(TEST_STUDY_ID)); + + final StructuralVariantFilterQuery structVarFilterQuery = + new StructuralVariantFilterQuery( + "A", null, "B", null, true, true, true, Select.all(), true, true, true, true); + final StudyViewStructuralVariantFilter structuralVariantFilter = + new StudyViewStructuralVariantFilter(); + structuralVariantFilter.setStructVarQueries(Arrays.asList(Arrays.asList(structVarFilterQuery))); + studyViewFilter.setStructuralVariantFilters(Arrays.asList(structuralVariantFilter)); + + // Test case: + structVarFilterQuery.getGene1Query().setSpecialValue(StructuralVariantSpecialValue.ANY_GENE); + structVarFilterQuery.getGene2Query().setSpecialValue(StructuralVariantSpecialValue.ANY_GENE); + + mockMvc + .perform( + MockMvcRequestBuilders.post("/api/filtered-samples/fetch") + .with(csrf()) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(studyViewFilter))) + .andExpect(MockMvcResultMatchers.status().isBadRequest()); + } + + @Test + @WithMockUser + public void validateStructVarFilterBothAnyGene() throws Exception { + + when(studyViewFilterApplier.apply(any())).thenReturn(filteredSampleIdentifiers); + when(studyViewFilterApplier.apply(any(), eq(false))).thenReturn(filteredSampleIdentifiers); + when(sampleService.fetchSamples(anyList(), anyList(), anyString())).thenReturn(filteredSamples); + + StudyViewFilter studyViewFilter = new StudyViewFilter(); + studyViewFilter.setStudyIds(Arrays.asList(TEST_STUDY_ID)); + + final StructuralVariantFilterQuery structVarFilterQuery = + new StructuralVariantFilterQuery( + "A", null, "B", null, true, true, true, Select.all(), true, true, true, true); + final StudyViewStructuralVariantFilter structuralVariantFilter = + new StudyViewStructuralVariantFilter(); + structuralVariantFilter.setStructVarQueries(Arrays.asList(Arrays.asList(structVarFilterQuery))); + studyViewFilter.setStructuralVariantFilters(Arrays.asList(structuralVariantFilter)); + + // Test case: + structVarFilterQuery.getGene1Query().setSpecialValue(StructuralVariantSpecialValue.ANY_GENE); + structVarFilterQuery.getGene2Query().setSpecialValue(StructuralVariantSpecialValue.ANY_GENE); + + mockMvc + .perform( + MockMvcRequestBuilders.post("/api/filtered-samples/fetch") + .with(csrf()) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(studyViewFilter))) + .andExpect(MockMvcResultMatchers.status().isBadRequest()); + } + + @Test + @WithMockUser + public void validateStructVarFilterBothNoGene() throws Exception { + + when(studyViewFilterApplier.apply(any())).thenReturn(filteredSampleIdentifiers); + when(studyViewFilterApplier.apply(any(), eq(false))).thenReturn(filteredSampleIdentifiers); + when(sampleService.fetchSamples(anyList(), anyList(), anyString())).thenReturn(filteredSamples); + + StudyViewFilter studyViewFilter = new StudyViewFilter(); + studyViewFilter.setStudyIds(Arrays.asList(TEST_STUDY_ID)); + + final StructuralVariantFilterQuery structVarFilterQuery = + new StructuralVariantFilterQuery( + "A", null, "B", null, true, true, true, Select.all(), true, true, true, true); + final StudyViewStructuralVariantFilter structuralVariantFilter = + new StudyViewStructuralVariantFilter(); + structuralVariantFilter.setStructVarQueries(Arrays.asList(Arrays.asList(structVarFilterQuery))); + studyViewFilter.setStructuralVariantFilters(Arrays.asList(structuralVariantFilter)); + + // Test case: + structVarFilterQuery.getGene1Query().setSpecialValue(StructuralVariantSpecialValue.NO_GENE); + structVarFilterQuery.getGene2Query().setSpecialValue(StructuralVariantSpecialValue.NO_GENE); + + mockMvc + .perform( + MockMvcRequestBuilders.post("/api/filtered-samples/fetch") + .with(csrf()) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(studyViewFilter))) + .andExpect(MockMvcResultMatchers.status().isBadRequest()); + } + + @Test + @WithMockUser + public void validateStructVarFilterBothNoGeneId() throws Exception { + + when(studyViewFilterApplier.apply(any())).thenReturn(filteredSampleIdentifiers); + when(studyViewFilterApplier.apply(any(), eq(false))).thenReturn(filteredSampleIdentifiers); + when(sampleService.fetchSamples(anyList(), anyList(), anyString())).thenReturn(filteredSamples); + + StudyViewFilter studyViewFilter = new StudyViewFilter(); + studyViewFilter.setStudyIds(Arrays.asList(TEST_STUDY_ID)); + + // Test case: + final StructuralVariantFilterQuery structVarFilterQuery = + new StructuralVariantFilterQuery( + null, null, null, null, true, true, true, Select.all(), true, true, true, true); + + final StudyViewStructuralVariantFilter structuralVariantFilter = + new StudyViewStructuralVariantFilter(); + structuralVariantFilter.setStructVarQueries(Arrays.asList(Arrays.asList(structVarFilterQuery))); + studyViewFilter.setStructuralVariantFilters(Arrays.asList(structuralVariantFilter)); + + mockMvc + .perform( + MockMvcRequestBuilders.post("/api/filtered-samples/fetch") + .with(csrf()) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(studyViewFilter))) + .andExpect(MockMvcResultMatchers.status().isBadRequest()); + } + + @Test + @WithMockUser + public void validateStructVarFilterBothGeneIdAndSpecialValueNull() throws Exception { + + when(studyViewFilterApplier.apply(any())).thenReturn(filteredSampleIdentifiers); + when(studyViewFilterApplier.apply(any(), eq(false))).thenReturn(filteredSampleIdentifiers); + when(sampleService.fetchSamples(anyList(), anyList(), anyString())).thenReturn(filteredSamples); + + StudyViewFilter studyViewFilter = new StudyViewFilter(); + studyViewFilter.setStudyIds(Arrays.asList(TEST_STUDY_ID)); + + // Test case: + final StructuralVariantFilterQuery structVarFilterQuery = + new StructuralVariantFilterQuery( + null, null, "B", null, true, true, true, Select.all(), true, true, true, true); + structVarFilterQuery.getGene1Query().setSpecialValue(null); + + final StudyViewStructuralVariantFilter structuralVariantFilter = + new StudyViewStructuralVariantFilter(); + structuralVariantFilter.setStructVarQueries(Arrays.asList(Arrays.asList(structVarFilterQuery))); + studyViewFilter.setStructuralVariantFilters(Arrays.asList(structuralVariantFilter)); + + mockMvc + .perform( + MockMvcRequestBuilders.post("/api/filtered-samples/fetch") + .with(csrf()) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(studyViewFilter))) + .andExpect(MockMvcResultMatchers.status().isBadRequest()); + } + + @Test + @WithMockUser + public void fetchMutationDataCounts() throws Exception { + + when(studyViewFilterApplier.apply(any())).thenReturn(filteredSampleIdentifiers); + + List genomicDataCountItems = new ArrayList<>(); + + GenomicDataCount genomicDataCount1 = new GenomicDataCount(); + genomicDataCount1.setLabel(TEST_MUTATION_TYPE); + genomicDataCount1.setValue(TEST_MUTATION_TYPE); + genomicDataCount1.setCount(1); + + GenomicDataCount genomicDataCount2 = new GenomicDataCount(); + genomicDataCount2.setLabel(TEST_MUTATION_TYPE); + genomicDataCount2.setValue(TEST_MUTATION_TYPE); + genomicDataCount2.setCount(1); + + GenomicDataCountItem genomicDataCountItem1 = new GenomicDataCountItem(); + List genomicDataCounts1 = new ArrayList<>(); + genomicDataCounts1.add(genomicDataCount1); + genomicDataCounts1.add(genomicDataCount2); + genomicDataCountItem1.setHugoGeneSymbol(TEST_HUGO_GENE_SYMBOL_1); + genomicDataCountItem1.setProfileType(TEST_MOLECULAR_PROFILE_TYPE); + genomicDataCountItem1.setCounts(genomicDataCounts1); + + GenomicDataCountItem genomicDataCountItem2 = new GenomicDataCountItem(); + List genomicDataCounts2 = new ArrayList<>(); + genomicDataCounts2.add(genomicDataCount1); + genomicDataCounts2.add(genomicDataCount2); + genomicDataCountItem2.setHugoGeneSymbol(TEST_HUGO_GENE_SYMBOL_2); + genomicDataCountItem2.setProfileType(TEST_MOLECULAR_PROFILE_TYPE); + genomicDataCountItem2.setCounts(genomicDataCounts2); + + genomicDataCountItems.add(genomicDataCountItem1); + genomicDataCountItems.add(genomicDataCountItem2); + + when(studyViewService.getMutationCountsByGeneSpecific( + anyList(), anyList(), anyList(), any(AlterationFilter.class))) + .thenReturn(genomicDataCountItems); + + when(studyViewService.getMutationTypeCountsByGeneSpecific(anyList(), anyList(), anyList())) + .thenReturn(genomicDataCountItems); + + GenomicDataCountFilter genomicDataCountFilter = new GenomicDataCountFilter(); + List genomicDataFilters = new ArrayList<>(); + + GenomicDataFilter genomicDataFilter1 = new GenomicDataFilter(); + genomicDataFilter1.setHugoGeneSymbol(TEST_HUGO_GENE_SYMBOL_1); + genomicDataFilter1.setProfileType(TEST_MOLECULAR_PROFILE_TYPE); + genomicDataFilters.add(genomicDataFilter1); + + genomicDataCountFilter.setGenomicDataFilters(genomicDataFilters); + + StudyViewFilter studyViewFilter = new StudyViewFilter(); + studyViewFilter.setStudyIds(Arrays.asList(TEST_STUDY_ID)); + studyViewFilter.setAlterationFilter(alterationFilter); + genomicDataCountFilter.setStudyViewFilter(studyViewFilter); + + ResultActions result1 = + mockMvc.perform( + MockMvcRequestBuilders.post("/api/mutation-data-counts/fetch") + .with(csrf()) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + .param("projection", "SUMMARY") + .content(objectMapper.writeValueAsString(genomicDataCountFilter))); + + result1 + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect( + MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].hugoGeneSymbol").value(TEST_HUGO_GENE_SYMBOL_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].profileType").value(TEST_MOLECULAR_PROFILE_TYPE)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].counts[0].label").value(TEST_MUTATION_TYPE)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].counts[0].value").value(TEST_MUTATION_TYPE)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].counts[0].count").value(1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].counts[1].label").value(TEST_MUTATION_TYPE)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].counts[1].value").value(TEST_MUTATION_TYPE)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].counts[1].count").value(1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].hugoGeneSymbol").value(TEST_HUGO_GENE_SYMBOL_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].profileType").value(TEST_MOLECULAR_PROFILE_TYPE)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].counts[0].label").value(TEST_MUTATION_TYPE)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].counts[0].value").value(TEST_MUTATION_TYPE)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].counts[0].count").value(1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].counts[1].label").value(TEST_MUTATION_TYPE)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].counts[1].value").value(TEST_MUTATION_TYPE)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].counts[1].count").value(1)); + + ResultActions result2 = + mockMvc.perform( + MockMvcRequestBuilders.post("/api/mutation-data-counts/fetch") + .with(csrf()) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + .param("projection", "DETAILED") + .content(objectMapper.writeValueAsString(genomicDataCountFilter))); + + result2 + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect( + MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].hugoGeneSymbol").value(TEST_HUGO_GENE_SYMBOL_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].profileType").value(TEST_MOLECULAR_PROFILE_TYPE)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].counts[0].label").value(TEST_MUTATION_TYPE)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].counts[0].value").value(TEST_MUTATION_TYPE)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].counts[0].count").value(1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].counts[1].label").value(TEST_MUTATION_TYPE)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].counts[1].value").value(TEST_MUTATION_TYPE)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].counts[1].count").value(1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].hugoGeneSymbol").value(TEST_HUGO_GENE_SYMBOL_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].profileType").value(TEST_MOLECULAR_PROFILE_TYPE)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].counts[0].label").value(TEST_MUTATION_TYPE)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].counts[0].value").value(TEST_MUTATION_TYPE)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].counts[0].count").value(1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].counts[1].label").value(TEST_MUTATION_TYPE)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].counts[1].value").value(TEST_MUTATION_TYPE)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].counts[1].count").value(1)); + } + + @Test + @WithMockUser + public void fetchNamespaceDataCounts() throws Exception { + + List filteredSampleIdentifiers = new ArrayList<>(); + SampleIdentifier sampleIdentifier = new SampleIdentifier(); + sampleIdentifier.setSampleId(TEST_SAMPLE_ID_1); + sampleIdentifier.setStudyId(TEST_STUDY_ID); + filteredSampleIdentifiers.add(sampleIdentifier); + when(studyViewFilterApplier.apply(any())).thenReturn(filteredSampleIdentifiers); + + List namespaceDataCountItems = new ArrayList<>(); + NamespaceDataCountItem namespaceDataCountItem = new NamespaceDataCountItem(); + namespaceDataCountItem.setOuterKey(TEST_OUTER_KEY); + namespaceDataCountItem.setInnerKey(TEST_INNER_KEY); + List namespaceDataCounts = new ArrayList<>(); + NamespaceDataCount namespaceDataCount1 = new NamespaceDataCount(); + namespaceDataCount1.setValue(TEST_NAMESPACE_DATA_VALUE_1); + namespaceDataCount1.setCount(3); + namespaceDataCounts.add(namespaceDataCount1); + NamespaceDataCount namespaceDataCount2 = new NamespaceDataCount(); + namespaceDataCount2.setValue(TEST_NAMESPACE_DATA_VALUE_2); + namespaceDataCount2.setCount(1); + namespaceDataCounts.add(namespaceDataCount2); + namespaceDataCountItem.setCounts(namespaceDataCounts); + namespaceDataCountItems.add(namespaceDataCountItem); + + when(studyViewService.fetchNamespaceDataCounts(anyList(), anyList(), anyList())) + .thenReturn(namespaceDataCountItems); + + NamespaceDataCountFilter namespaceDataCountFilter = new NamespaceDataCountFilter(); + NamespaceDataFilter namespaceDataFilter = new NamespaceDataFilter(); + namespaceDataFilter.setOuterKey(TEST_OUTER_KEY); + namespaceDataFilter.setInnerKey(TEST_INNER_KEY); + namespaceDataCountFilter.setAttributes(Arrays.asList(namespaceDataFilter)); + StudyViewFilter studyViewFilter = new StudyViewFilter(); + studyViewFilter.setStudyIds(Arrays.asList(TEST_STUDY_ID)); + namespaceDataCountFilter.setStudyViewFilter(studyViewFilter); + + mockMvc + .perform( + MockMvcRequestBuilders.post("/api/namespace-data-counts/fetch") + .with(csrf()) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(namespaceDataCountFilter))) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect( + MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].outerKey").value(TEST_OUTER_KEY)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].innerKey").value(TEST_INNER_KEY)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].counts[0].outerKey").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].counts[0].innerKey").doesNotExist()) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].counts[0].value") + .value(TEST_NAMESPACE_DATA_VALUE_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].counts[0].count").value(3)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].counts[1].outerKey").doesNotExist()) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].counts[1].innerKey").doesNotExist()) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].counts[1].value") + .value(TEST_NAMESPACE_DATA_VALUE_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].counts[1].count").value(1)); + } +} diff --git a/src/test/java/org/cbioportal/legacy/web/SurvivalControllerTest.java b/src/test/java/org/cbioportal/legacy/web/SurvivalControllerTest.java new file mode 100644 index 00000000000..edc044eb56f --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/web/SurvivalControllerTest.java @@ -0,0 +1,138 @@ +package org.cbioportal.legacy.web; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyList; +import static org.mockito.Mockito.when; +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; + +import com.fasterxml.jackson.databind.ObjectMapper; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; +import org.cbioportal.legacy.model.ClinicalData; +import org.cbioportal.legacy.service.ClinicalEventService; +import org.cbioportal.legacy.web.config.TestConfig; +import org.cbioportal.legacy.web.parameter.ClinicalEventRequest; +import org.cbioportal.legacy.web.parameter.ClinicalEventRequestIdentifier; +import org.cbioportal.legacy.web.parameter.OccurrencePosition; +import org.cbioportal.legacy.web.parameter.PatientIdentifier; +import org.cbioportal.legacy.web.parameter.SurvivalRequest; +import org.hamcrest.Matchers; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; +import org.springframework.security.test.context.support.WithMockUser; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.result.MockMvcResultMatchers; + +@RunWith(SpringJUnit4ClassRunner.class) +@WebMvcTest +@ContextConfiguration(classes = {SurvivalController.class, TestConfig.class}) +public class SurvivalControllerTest { + + private static final String TEST_CANCER_STUDY_IDENTIFIER = "test_study_id"; + private static final String TEST_PATIENT_ID_1 = "test_patient_id_1"; + private static final String TEST_PATIENT_ID_2 = "test_patient_id_2"; + private static final String TEST_ATTRIBUTE_ID_PREFIX = "test_attribute_id_prefix"; + private static final String TEST_CLINICAL_ATTRIBUTE_ID_1 = "test_clinical_attribute_id_1"; + private static final String TEST_CLINICAL_ATTRIBUTE_ID_2 = "test_clinical_attribute_id_2"; + private static final String TEST_CLINICAL_ATTRIBUTE_VALUE_1 = "test_clinical_attribute_value_1"; + private static final String TEST_CLINICAL_ATTRIBUTE_VALUE_2 = "test_clinical_attribute_value_2"; + private static final String TEST_CLINICAL_EVENT_TYPE = "test_clinical_event_type"; + + private final ObjectMapper objectMapper = new ObjectMapper(); + + @MockBean private ClinicalEventService clinicalEventService; + + @Autowired private MockMvc mockMvc; + + @Test + @WithMockUser + public void fetchSurvivalData() throws Exception { + List clinicalDataList = createClinicalDataList(); + when(clinicalEventService.getSurvivalData(anyList(), anyList(), any(), any())) + .thenReturn(clinicalDataList); + + SurvivalRequest survivalRequest = new SurvivalRequest(); + PatientIdentifier patientIdentifier = new PatientIdentifier(); + patientIdentifier.setPatientId(TEST_PATIENT_ID_1); + patientIdentifier.setStudyId(TEST_CANCER_STUDY_IDENTIFIER); + survivalRequest.setPatientIdentifiers(List.of(patientIdentifier)); + survivalRequest.setAttributeIdPrefix(TEST_ATTRIBUTE_ID_PREFIX); + + ClinicalEventRequest clinicalEventRequest = new ClinicalEventRequest(); + clinicalEventRequest.setEventType(TEST_CLINICAL_EVENT_TYPE); + clinicalEventRequest.setAttributes(new ArrayList<>()); + + ClinicalEventRequestIdentifier startEventRequestIdentifier = + new ClinicalEventRequestIdentifier(); + startEventRequestIdentifier.setClinicalEventRequests(Set.of(clinicalEventRequest)); + startEventRequestIdentifier.setPosition(OccurrencePosition.FIRST); + survivalRequest.setStartEventRequestIdentifier(startEventRequestIdentifier); + + ClinicalEventRequestIdentifier endEventRequestIdentifier = new ClinicalEventRequestIdentifier(); + endEventRequestIdentifier.setClinicalEventRequests(Set.of(clinicalEventRequest)); + endEventRequestIdentifier.setPosition(OccurrencePosition.LAST); + survivalRequest.setEndEventRequestIdentifier(endEventRequestIdentifier); + + ClinicalEventRequestIdentifier censoredEventRequestIdentifier = + new ClinicalEventRequestIdentifier(); + censoredEventRequestIdentifier.setClinicalEventRequests(Set.of(clinicalEventRequest)); + censoredEventRequestIdentifier.setPosition(OccurrencePosition.LAST); + survivalRequest.setCensoredEventRequestIdentifier(censoredEventRequestIdentifier); + + mockMvc + .perform( + MockMvcRequestBuilders.post("/api/survival-data/fetch") + .with(csrf()) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(survivalRequest))) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect( + MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.jsonPath("$", Matchers.hasSize(2))) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].studyId").value(TEST_CANCER_STUDY_IDENTIFIER)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].patientId").value(TEST_PATIENT_ID_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].clinicalAttributeId") + .value(TEST_CLINICAL_ATTRIBUTE_ID_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].value").value(TEST_CLINICAL_ATTRIBUTE_VALUE_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].studyId").value(TEST_CANCER_STUDY_IDENTIFIER)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].patientId").value(TEST_PATIENT_ID_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].clinicalAttributeId") + .value(TEST_CLINICAL_ATTRIBUTE_ID_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].value").value(TEST_CLINICAL_ATTRIBUTE_VALUE_2)); + } + + private List createClinicalDataList() { + List clinicalDataList = new ArrayList<>(); + + ClinicalData clinicalData1 = new ClinicalData(); + clinicalData1.setStudyId(TEST_CANCER_STUDY_IDENTIFIER); + clinicalData1.setPatientId(TEST_PATIENT_ID_1); + clinicalData1.setAttrId(TEST_CLINICAL_ATTRIBUTE_ID_1); + clinicalData1.setAttrValue(TEST_CLINICAL_ATTRIBUTE_VALUE_1); + clinicalDataList.add(clinicalData1); + + ClinicalData clinicalData2 = new ClinicalData(); + clinicalData2.setStudyId(TEST_CANCER_STUDY_IDENTIFIER); + clinicalData2.setPatientId(TEST_PATIENT_ID_2); + clinicalData2.setAttrId(TEST_CLINICAL_ATTRIBUTE_ID_2); + clinicalData2.setAttrValue(TEST_CLINICAL_ATTRIBUTE_VALUE_2); + clinicalDataList.add(clinicalData2); + + return clinicalDataList; + } +} diff --git a/src/test/java/org/cbioportal/legacy/web/TreatmentControllerTest.java b/src/test/java/org/cbioportal/legacy/web/TreatmentControllerTest.java new file mode 100644 index 00000000000..fbdadb9e289 --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/web/TreatmentControllerTest.java @@ -0,0 +1,152 @@ +package org.cbioportal.legacy.web; + +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; + +import com.fasterxml.jackson.databind.ObjectMapper; +import java.util.Arrays; +import java.util.List; +import org.cbioportal.legacy.model.PatientTreatmentRow; +import org.cbioportal.legacy.model.SampleTreatmentRow; +import org.cbioportal.legacy.model.TemporalRelation; +import org.cbioportal.legacy.service.TreatmentService; +import org.cbioportal.legacy.web.config.TestConfig; +import org.cbioportal.legacy.web.parameter.SampleIdentifier; +import org.cbioportal.legacy.web.parameter.StudyViewFilter; +import org.cbioportal.legacy.web.util.StudyViewFilterApplier; +import org.cbioportal.legacy.web.util.StudyViewFilterUtil; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mockito; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; +import org.springframework.security.test.context.support.WithMockUser; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.result.MockMvcResultMatchers; + +@RunWith(SpringJUnit4ClassRunner.class) +@WebMvcTest +@ContextConfiguration(classes = {TreatmentController.class, TestConfig.class}) +public class TreatmentControllerTest { + + private final List sampleIdentifiers; + private final List studies; + private final StudyViewFilter studyViewFilter; + + private ObjectMapper objectMapper = new ObjectMapper(); + + @MockBean private StudyViewFilterApplier studyViewFilterApplier; + + @MockBean private StudyViewFilterUtil studyViewFilterUtil; + + @MockBean private TreatmentService treatmentService; + + @Autowired private MockMvc mockMvc; + + public TreatmentControllerTest() { + SampleIdentifier sampleIdentifier = new SampleIdentifier(); + String STUDY_A = "study_0"; + sampleIdentifier.setStudyId(STUDY_A); + String SAMPLE_A = "sample_0"; + sampleIdentifier.setSampleId(SAMPLE_A); + + SampleIdentifier sampleIdentifierB = new SampleIdentifier(); + String STUDY_B = "study_1"; + sampleIdentifier.setStudyId(STUDY_B); + String SAMPLE_B = "sample_1"; + sampleIdentifier.setSampleId(SAMPLE_B); + sampleIdentifiers = Arrays.asList(sampleIdentifier, sampleIdentifierB); + + studies = Arrays.asList(STUDY_A, STUDY_B); + + studyViewFilter = new StudyViewFilter(); + studyViewFilter.setStudyIds(studies); + } + + @Test + @WithMockUser + public void getAllPatientTreatments() throws Exception { + Mockito.when(studyViewFilterApplier.apply(Mockito.any())).thenReturn(sampleIdentifiers); + + PatientTreatmentRow rowA = new PatientTreatmentRow("madeupanib", 2, null); + PatientTreatmentRow rowB = new PatientTreatmentRow("fakeazil", 4, null); + List treatmentRows = Arrays.asList(rowA, rowB); + + Mockito.when( + treatmentService.getAllPatientTreatmentRows( + Mockito.anyList(), Mockito.anyList(), Mockito.any())) + .thenReturn(treatmentRows); + + mockMvc + .perform( + MockMvcRequestBuilders.post("/api/treatments/patient") + .with(csrf()) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(studyViewFilter))) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].treatment").value("madeupanib")) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].count").value("2")) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].treatment").value("fakeazil")) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].count").value("4")); + } + + @Test + @WithMockUser + public void getAllSampleTreatments() throws Exception { + Mockito.when(studyViewFilterApplier.apply(Mockito.any())).thenReturn(sampleIdentifiers); + + SampleTreatmentRow rowA = new SampleTreatmentRow(TemporalRelation.Pre, "madeupanib", 2, null); + SampleTreatmentRow rowB = new SampleTreatmentRow(TemporalRelation.Post, "madeupanib", 4, null); + SampleTreatmentRow rowC = new SampleTreatmentRow(TemporalRelation.Pre, "fakeazil", 4, null); + SampleTreatmentRow rowD = new SampleTreatmentRow(TemporalRelation.Post, "fakeazil", 2, null); + List sampleTreatmentRows = Arrays.asList(rowA, rowB, rowC, rowD); + + Mockito.when( + treatmentService.getAllSampleTreatmentRows( + Mockito.anyList(), Mockito.anyList(), Mockito.any())) + .thenReturn(sampleTreatmentRows); + + mockMvc + .perform( + MockMvcRequestBuilders.post("/api/treatments/sample") + .with(csrf()) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(studyViewFilter))) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].treatment").value("madeupanib")) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].count").value("2")) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].time").value("Pre")) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].treatment").value("madeupanib")) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].count").value("4")) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].time").value("Post")) + .andExpect(MockMvcResultMatchers.jsonPath("$[2].treatment").value("fakeazil")) + .andExpect(MockMvcResultMatchers.jsonPath("$[2].count").value("4")) + .andExpect(MockMvcResultMatchers.jsonPath("$[2].time").value("Pre")) + .andExpect(MockMvcResultMatchers.jsonPath("$[3].treatment").value("fakeazil")) + .andExpect(MockMvcResultMatchers.jsonPath("$[3].count").value("2")) + .andExpect(MockMvcResultMatchers.jsonPath("$[3].time").value("Post")); + } + + @Test + @WithMockUser + public void getContainsTreatmentData() throws Exception { + List studies = Arrays.asList("study_0", "study_1"); + Mockito.when(studyViewFilterApplier.apply(Mockito.any())).thenReturn(sampleIdentifiers); + + Mockito.when(treatmentService.containsTreatmentData(Mockito.anyList(), Mockito.any())) + .thenReturn(true); + + mockMvc + .perform( + MockMvcRequestBuilders.post("/api/treatments/display-patient") + .with(csrf()) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(studies))) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect(MockMvcResultMatchers.jsonPath("$").value("true")); + } +} diff --git a/src/test/java/org/cbioportal/legacy/web/VariantCountControllerTest.java b/src/test/java/org/cbioportal/legacy/web/VariantCountControllerTest.java new file mode 100644 index 00000000000..2107edd6a63 --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/web/VariantCountControllerTest.java @@ -0,0 +1,128 @@ +package org.cbioportal.legacy.web; + +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; + +import com.fasterxml.jackson.databind.ObjectMapper; +import java.util.ArrayList; +import java.util.List; +import org.cbioportal.legacy.model.VariantCount; +import org.cbioportal.legacy.service.VariantCountService; +import org.cbioportal.legacy.web.config.TestConfig; +import org.cbioportal.legacy.web.parameter.VariantCountIdentifier; +import org.hamcrest.Matchers; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mockito; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; +import org.springframework.security.test.context.support.WithMockUser; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.result.MockMvcResultMatchers; + +@RunWith(SpringJUnit4ClassRunner.class) +@WebMvcTest +@ContextConfiguration(classes = {VariantCountController.class, TestConfig.class}) +public class VariantCountControllerTest { + + private static final String TEST_MOLECULAR_PROFILE_STABLE_ID = "test_molecular_profile_stable_id"; + private static final int TEST_ENTREZ_GENE_ID_1 = 1; + private static final String TEST_KEYWORD_1 = "test_keyword_1"; + private static final int TEST_NUMBER_OF_SAMPLES_1 = 6; + private static final int TEST_NUMBER_OF_SAMPLES_WITH_MUTATION_IN_GENE_1 = 4; + private static final int TEST_NUMBER_OF_SAMPLES_WITH_KEYWORD_1 = 1; + private static final int TEST_ENTREZ_GENE_ID_2 = 2; + private static final String TEST_KEYWORD_2 = "test_keyword_2"; + private static final int TEST_NUMBER_OF_SAMPLES_2 = 10; + private static final int TEST_NUMBER_OF_SAMPLES_WITH_MUTATION_IN_GENE_2 = 8; + private static final int TEST_NUMBER_OF_SAMPLES_WITH_KEYWORD_2 = 2; + + @MockBean private VariantCountService variantCountService; + + private ObjectMapper objectMapper = new ObjectMapper(); + + @Autowired private MockMvc mockMvc; + + @Test + @WithMockUser + public void getVariantCounts() throws Exception { + + List variantCountList = new ArrayList<>(); + VariantCount variantCount1 = new VariantCount(); + variantCount1.setMolecularProfileId(TEST_MOLECULAR_PROFILE_STABLE_ID); + variantCount1.setEntrezGeneId(TEST_ENTREZ_GENE_ID_1); + variantCount1.setKeyword(TEST_KEYWORD_1); + variantCount1.setNumberOfSamples(TEST_NUMBER_OF_SAMPLES_1); + variantCount1.setNumberOfSamplesWithMutationInGene( + TEST_NUMBER_OF_SAMPLES_WITH_MUTATION_IN_GENE_1); + variantCount1.setNumberOfSamplesWithKeyword(TEST_NUMBER_OF_SAMPLES_WITH_KEYWORD_1); + variantCountList.add(variantCount1); + VariantCount variantCount2 = new VariantCount(); + variantCount2.setMolecularProfileId(TEST_MOLECULAR_PROFILE_STABLE_ID); + variantCount2.setEntrezGeneId(TEST_ENTREZ_GENE_ID_2); + variantCount2.setKeyword(TEST_KEYWORD_2); + variantCount2.setNumberOfSamples(TEST_NUMBER_OF_SAMPLES_2); + variantCount2.setNumberOfSamplesWithMutationInGene( + TEST_NUMBER_OF_SAMPLES_WITH_MUTATION_IN_GENE_2); + variantCount2.setNumberOfSamplesWithKeyword(TEST_NUMBER_OF_SAMPLES_WITH_KEYWORD_2); + variantCountList.add(variantCount2); + + Mockito.when( + variantCountService.fetchVariantCounts( + Mockito.anyString(), Mockito.anyList(), Mockito.anyList())) + .thenReturn(variantCountList); + + List variantCountIdentifiers = new ArrayList<>(); + VariantCountIdentifier variantCountIdentifier1 = new VariantCountIdentifier(); + variantCountIdentifier1.setEntrezGeneId(TEST_ENTREZ_GENE_ID_1); + variantCountIdentifier1.setKeyword(TEST_KEYWORD_1); + variantCountIdentifiers.add(variantCountIdentifier1); + VariantCountIdentifier variantCountIdentifier2 = new VariantCountIdentifier(); + variantCountIdentifier2.setEntrezGeneId(TEST_ENTREZ_GENE_ID_2); + variantCountIdentifier2.setKeyword(TEST_KEYWORD_2); + variantCountIdentifiers.add(variantCountIdentifier2); + + mockMvc + .perform( + MockMvcRequestBuilders.post( + "/api/molecular-profiles/test_molecular_profile_id/variant-counts/fetch") + .with(csrf()) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(variantCountIdentifiers))) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect( + MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.jsonPath("$", Matchers.hasSize(2))) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].entrezGeneId").value(TEST_ENTREZ_GENE_ID_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].molecularProfileId") + .value(TEST_MOLECULAR_PROFILE_STABLE_ID)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].keyword").value(TEST_KEYWORD_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].numberOfSamples").value(TEST_NUMBER_OF_SAMPLES_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].numberOfSamplesWithMutationInGene") + .value(TEST_NUMBER_OF_SAMPLES_WITH_MUTATION_IN_GENE_1)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[0].numberOfSamplesWithKeyword") + .value(TEST_NUMBER_OF_SAMPLES_WITH_KEYWORD_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].entrezGeneId").value(TEST_ENTREZ_GENE_ID_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].molecularProfileId") + .value(TEST_MOLECULAR_PROFILE_STABLE_ID)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].keyword").value(TEST_KEYWORD_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].numberOfSamples").value(TEST_NUMBER_OF_SAMPLES_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].numberOfSamplesWithMutationInGene") + .value(TEST_NUMBER_OF_SAMPLES_WITH_MUTATION_IN_GENE_2)) + .andExpect( + MockMvcResultMatchers.jsonPath("$[1].numberOfSamplesWithKeyword") + .value(TEST_NUMBER_OF_SAMPLES_WITH_KEYWORD_2)); + } +} diff --git a/src/test/java/org/cbioportal/legacy/web/config/CacheMapUtilConfig.java b/src/test/java/org/cbioportal/legacy/web/config/CacheMapUtilConfig.java new file mode 100644 index 00000000000..2bedb4c545b --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/web/config/CacheMapUtilConfig.java @@ -0,0 +1,76 @@ +/* + * This file is part of cBioPortal. + * + * cBioPortal is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package org.cbioportal.legacy.web.config; + +import org.cbioportal.legacy.persistence.CancerTypeRepository; +import org.cbioportal.legacy.persistence.GenericAssayRepository; +import org.cbioportal.legacy.persistence.MolecularProfileRepository; +import org.cbioportal.legacy.persistence.PatientRepository; +import org.cbioportal.legacy.persistence.SampleListRepository; +import org.cbioportal.legacy.persistence.StudyRepository; +import org.cbioportal.legacy.persistence.cachemaputil.CacheMapUtil; +import org.cbioportal.legacy.service.StaticDataTimestampService; +import org.mockito.Mockito; +import org.springframework.boot.test.context.TestConfiguration; +import org.springframework.context.annotation.Bean; + +/** + * @author ochoaa + */ +@TestConfiguration +public class CacheMapUtilConfig { + @Bean + public CacheMapUtil cacheMapUtil() { + return Mockito.mock(CacheMapUtil.class); + } + + @Bean + public PatientRepository patientRepository() { + return Mockito.mock(PatientRepository.class); + } + + @Bean + public CancerTypeRepository cancerTypeRepository() { + return Mockito.mock(CancerTypeRepository.class); + } + + @Bean + public StudyRepository studyRepository() { + return Mockito.mock(StudyRepository.class); + } + + @Bean + public MolecularProfileRepository molecularProfileRepository() { + return Mockito.mock(MolecularProfileRepository.class); + } + + @Bean + public SampleListRepository sampleListRepository() { + return Mockito.mock(SampleListRepository.class); + } + + @Bean + public GenericAssayRepository genericAssayRepository() { + return Mockito.mock(GenericAssayRepository.class); + } + + @Bean + public StaticDataTimestampService staticDataTimestampService() { + return Mockito.mock(StaticDataTimestampService.class); + } +} diff --git a/src/test/java/org/cbioportal/web/config/DataAccessTokenControllerConfig.java b/src/test/java/org/cbioportal/legacy/web/config/DataAccessTokenControllerConfig.java similarity index 86% rename from src/test/java/org/cbioportal/web/config/DataAccessTokenControllerConfig.java rename to src/test/java/org/cbioportal/legacy/web/config/DataAccessTokenControllerConfig.java index cf4f53f3efb..bfd9c093bff 100644 --- a/src/test/java/org/cbioportal/web/config/DataAccessTokenControllerConfig.java +++ b/src/test/java/org/cbioportal/legacy/web/config/DataAccessTokenControllerConfig.java @@ -28,26 +28,23 @@ * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . -*/ + */ -package org.cbioportal.web.config; +package org.cbioportal.legacy.web.config; -import org.cbioportal.service.DataAccessTokenService; -import org.cbioportal.web.DataAccessTokenController; +import org.cbioportal.legacy.service.DataAccessTokenService; import org.mockito.Mockito; import org.springframework.boot.test.context.TestConfiguration; import org.springframework.context.annotation.Bean; /** - * * @author ochoaa */ @TestConfiguration public class DataAccessTokenControllerConfig { - @Bean - public DataAccessTokenService tokenService() { - return Mockito.mock(DataAccessTokenService.class); - } - + @Bean + public DataAccessTokenService tokenService() { + return Mockito.mock(DataAccessTokenService.class); + } } diff --git a/src/test/java/org/cbioportal/legacy/web/config/DataAccessTokenControllerTestConfig.java b/src/test/java/org/cbioportal/legacy/web/config/DataAccessTokenControllerTestConfig.java new file mode 100644 index 00000000000..588383ba042 --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/web/config/DataAccessTokenControllerTestConfig.java @@ -0,0 +1,68 @@ +package org.cbioportal.legacy.web.config; + +import org.springframework.boot.test.context.TestConfiguration; +import org.springframework.context.annotation.Bean; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer; +import org.springframework.security.core.userdetails.User; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.crypto.password.NoOpPasswordEncoder; +import org.springframework.security.provisioning.InMemoryUserDetailsManager; +import org.springframework.security.web.SecurityFilterChain; +import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; + +@TestConfiguration +public class DataAccessTokenControllerTestConfig { + + @Bean + protected SecurityFilterChain filterChain(HttpSecurity http) throws Exception { + http.authorizeHttpRequests((authz) -> authz.anyRequest().authenticated()) + .apply(new TestFilterDsl()) + .and() + .httpBasic() + .authenticationEntryPoint(restAuthenticationEntryPoint()); + return http.build(); + } + + @Bean + public InMemoryUserDetailsManager userDetailsService() { + UserDetails user = + User.withUsername("MOCK_USER") + .password(noopPasswordEncoder().encode("MOCK_PASSWORD")) + .roles("PLACEHOLDER_ROLE") + .build(); + return new InMemoryUserDetailsManager(user); + } + + @Bean + public static NoOpPasswordEncoder noopPasswordEncoder() { + return (NoOpPasswordEncoder) NoOpPasswordEncoder.getInstance(); + } + + private class TestFilterDsl extends AbstractHttpConfigurer { + @Override + public void configure(HttpSecurity http) { + AuthenticationManager authenticationManager = + http.getSharedObject(AuthenticationManager.class); + UsernamePasswordAuthenticationFilter filter = new UsernamePasswordAuthenticationFilter(); + filter.setPostOnly(false); + filter.setFilterProcessesUrl("/j_spring_security_check"); + filter.setUsernameParameter("j_username"); + filter.setPasswordParameter("j_password"); + filter.setAuthenticationManager(authenticationManager); + filter.setAuthenticationSuccessHandler(tokenAuthenticationSuccessHandler()); + http.addFilter(filter); + } + } + + @Bean + public RestAuthenticationEntryPoint restAuthenticationEntryPoint() { + return new RestAuthenticationEntryPoint(); + } + + @Bean + public TokenAuthenticationSuccessHandler tokenAuthenticationSuccessHandler() { + return new TokenAuthenticationSuccessHandler(); + } +} diff --git a/src/test/java/org/cbioportal/legacy/web/config/RestAuthenticationEntryPoint.java b/src/test/java/org/cbioportal/legacy/web/config/RestAuthenticationEntryPoint.java new file mode 100644 index 00000000000..a9aa218ab7d --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/web/config/RestAuthenticationEntryPoint.java @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2018 Memorial Sloan-Kettering Cancer Center. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS + * FOR A PARTICULAR PURPOSE. The software and documentation provided hereunder + * is on an "as is" basis, and Memorial Sloan-Kettering Cancer Center has no + * obligations to provide maintenance, support, updates, enhancements or + * modifications. In no event shall Memorial Sloan-Kettering Cancer Center be + * liable to any party for direct, indirect, special, incidental or + * consequential damages, including lost profits, arising out of the use of this + * software and its documentation, even if Memorial Sloan-Kettering Cancer + * Center has been advised of the possibility of such damage. + */ + +/* + * This file is part of cBioPortal. + * + * cBioPortal is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package org.cbioportal.legacy.web.config; + +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import java.io.IOException; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.web.AuthenticationEntryPoint; + +public class RestAuthenticationEntryPoint implements AuthenticationEntryPoint { + + @Override + public void commence( + HttpServletRequest request, + HttpServletResponse response, + AuthenticationException authException) + throws IOException { + response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized"); + } +} diff --git a/src/test/java/org/cbioportal/legacy/web/config/TestConfig.java b/src/test/java/org/cbioportal/legacy/web/config/TestConfig.java new file mode 100644 index 00000000000..f60639ae15f --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/web/config/TestConfig.java @@ -0,0 +1,49 @@ +package org.cbioportal.legacy.web.config; + +import org.cbioportal.legacy.persistence.cachemaputil.CacheMapUtil; +import org.cbioportal.legacy.web.error.GlobalExceptionHandler; +import org.cbioportal.legacy.web.util.InvolvedCancerStudyExtractorInterceptor; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.TestConfiguration; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.context.annotation.Bean; +import org.springframework.stereotype.Component; +import org.springframework.web.servlet.HandlerInterceptor; +import org.springframework.web.servlet.config.annotation.InterceptorRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +@TestConfiguration +public class TestConfig { + + // -- configure preauthorize security + @MockBean(name = "staticRefCacheMapUtil") + private CacheMapUtil cacheMapUtil; + + @Bean + public InvolvedCancerStudyExtractorInterceptor involvedCancerStudyExtractorInterceptor() { + return new InvolvedCancerStudyExtractorInterceptor(); + } + + @Component + public class InterceptorAppConfig implements WebMvcConfigurer { + + @Autowired private HandlerInterceptor involvedCancerStudyExtractorInterceptor; + + @Override + public void addInterceptors(InterceptorRegistry registry) { + registry.addInterceptor(involvedCancerStudyExtractorInterceptor).addPathPatterns("/api/**"); + } + } + + // -- register mixins + @Bean + public CustomObjectMapper customObjectMapper() { + return new CustomObjectMapper(); + } + + // -- handle exceptions + @Bean + public GlobalExceptionHandler globalExceptionHandler() { + return new GlobalExceptionHandler(); + } +} diff --git a/src/test/java/org/cbioportal/legacy/web/config/TokenAuthenticationSuccessHandler.java b/src/test/java/org/cbioportal/legacy/web/config/TokenAuthenticationSuccessHandler.java new file mode 100644 index 00000000000..5b6e1aa1eb8 --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/web/config/TokenAuthenticationSuccessHandler.java @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2018 Memorial Sloan-Kettering Cancer Center. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS + * FOR A PARTICULAR PURPOSE. The software and documentation provided hereunder + * is on an "as is" basis, and Memorial Sloan-Kettering Cancer Center has no + * obligations to provide maintenance, support, updates, enhancements or + * modifications. In no event shall Memorial Sloan-Kettering Cancer Center be + * liable to any party for direct, indirect, special, incidental or + * consequential damages, including lost profits, arising out of the use of this + * software and its documentation, even if Memorial Sloan-Kettering Cancer + * Center has been advised of the possibility of such damage. + */ + +/* + * This file is part of cBioPortal. + * + * cBioPortal is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package org.cbioportal.legacy.web.config; + +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import java.io.IOException; +import org.springframework.security.core.Authentication; +import org.springframework.security.web.authentication.AuthenticationSuccessHandler; + +public class TokenAuthenticationSuccessHandler implements AuthenticationSuccessHandler { + + @Override + public void onAuthenticationSuccess( + HttpServletRequest request, HttpServletResponse response, Authentication authentication) + throws IOException { + response.setStatus(HttpServletResponse.SC_OK); + response.getWriter().write("Authentication successful"); + response.getWriter().flush(); + // We do not need to do anything extra on REST authentication success, because there is no page + // to redirect to + } +} diff --git a/src/test/java/org/cbioportal/legacy/web/util/AlterationFilterMockitoArgumentMatcher.java b/src/test/java/org/cbioportal/legacy/web/util/AlterationFilterMockitoArgumentMatcher.java new file mode 100644 index 00000000000..ba678fed2e5 --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/web/util/AlterationFilterMockitoArgumentMatcher.java @@ -0,0 +1,47 @@ +package org.cbioportal.legacy.web.util; + +import org.cbioportal.legacy.model.AlterationFilter; +import org.mockito.ArgumentMatcher; + +public class AlterationFilterMockitoArgumentMatcher implements ArgumentMatcher { + private String checkWhatMutation; + private String checkWhatCna; + + public AlterationFilterMockitoArgumentMatcher(String checkWhatMutation, String checkWhatCna) { + this.checkWhatMutation = checkWhatMutation; + this.checkWhatCna = checkWhatCna; + } + + @Override + public boolean matches(AlterationFilter filter) { + boolean correctMutation; + boolean correctCna; + switch (checkWhatMutation) { + case "ALL": + correctMutation = filter.getMutationTypeSelect().hasAll(); + break; + case "EMPTY": + correctMutation = filter.getMutationTypeSelect().hasNone(); + break; + case "SOME": + correctMutation = filter.getMutationTypeSelect().hasValues(); + break; + default: + correctMutation = false; + } + switch (checkWhatCna) { + case "ALL": + correctCna = filter.getCNAEventTypeSelect().hasAll(); + break; + case "EMPTY": + correctCna = filter.getCNAEventTypeSelect().hasNone(); + break; + case "SOME": + correctCna = filter.getCNAEventTypeSelect().hasValues(); + break; + default: + correctCna = false; + } + return correctMutation && correctCna; + } +} diff --git a/src/test/java/org/cbioportal/legacy/web/util/ClinicalDataBinUtilTest.java b/src/test/java/org/cbioportal/legacy/web/util/ClinicalDataBinUtilTest.java new file mode 100644 index 00000000000..b2c97048593 --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/web/util/ClinicalDataBinUtilTest.java @@ -0,0 +1,1012 @@ +package org.cbioportal.legacy.web.util; + +import static org.junit.Assert.assertEquals; +import static org.mockito.Mockito.*; + +import com.fasterxml.jackson.core.TreeNode; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import java.io.IOException; +import java.nio.file.Files; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; +import org.cbioportal.legacy.model.ClinicalAttribute; +import org.cbioportal.legacy.model.ClinicalData; +import org.cbioportal.legacy.model.ClinicalDataBin; +import org.cbioportal.legacy.model.Patient; +import org.cbioportal.legacy.service.ClinicalAttributeService; +import org.cbioportal.legacy.service.PatientService; +import org.cbioportal.legacy.service.impl.CustomDataServiceImpl; +import org.cbioportal.legacy.service.util.ClinicalAttributeUtil; +import org.cbioportal.legacy.service.util.SessionServiceRequestHandler; +import org.cbioportal.legacy.web.parameter.ClinicalDataBinCountFilter; +import org.cbioportal.legacy.web.parameter.ClinicalDataBinFilter; +import org.cbioportal.legacy.web.parameter.ClinicalDataFilter; +import org.cbioportal.legacy.web.parameter.DataBinFilter; +import org.cbioportal.legacy.web.parameter.DataBinMethod; +import org.cbioportal.legacy.web.parameter.DataFilterValue; +import org.cbioportal.legacy.web.parameter.SampleIdentifier; +import org.cbioportal.legacy.web.parameter.StudyViewFilter; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.ArgumentMatcher; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.mockito.Spy; +import org.mockito.junit.MockitoJUnitRunner; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.core.io.Resource; +import org.springframework.util.ResourceUtils; + +@RunWith(MockitoJUnitRunner.class) +public class ClinicalDataBinUtilTest { + private static String STUDY_ID = "genie_bpc_test"; + private static Integer STUDY_ID_INT = 205; + + @Spy @InjectMocks private ClinicalDataBinUtil clinicalDataBinUtil; + @Mock private StudyViewFilterApplier studyViewFilterApplier; + @Mock private ClinicalDataFetcher clinicalDataFetcher; + @Mock private ClinicalAttributeService clinicalAttributeService; + @Mock private PatientService patientService; + @Mock private SessionServiceRequestHandler sessionServiceRequestHandler; + @Spy private ObjectMapper sessionServiceObjectMapper = new ObjectMapper(); + @Spy @InjectMocks private CustomDataServiceImpl customDataService; + @Spy private StudyViewFilterUtil studyViewFilterUtil; + @Spy private ClinicalAttributeUtil clinicalAttributeUtil; + + @Spy @InjectMocks private DataBinner dataBinner; + + @Spy @InjectMocks private DiscreteDataBinner discreteDataBinner; + @Spy @InjectMocks private LinearDataBinner linearDataBinner; + @Spy @InjectMocks private ScientificSmallDataBinner scientificSmallDataBinner; + + @Spy @InjectMocks private IdPopulator idPopulator; + + @Spy @InjectMocks private LogScaleDataBinner logScaleDataBinner; + @Spy private DataBinHelper dataBinHelper; + private final String testDataAttributeId = "test"; + private final ObjectMapper customDatasetMapper = + new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + + @Before + public void setup() { + MockitoAnnotations.initMocks(this); + } + + @Test + public void testUnfilteredFetchClinicalDataBinCounts() { + mockUnfilteredQuery(); + + List dataBins = + clinicalDataBinUtil.fetchClinicalDataBinCounts(DataBinMethod.STATIC, mockBaseFilter()); + + // assert data bin counts + + assertEquals(33, dataBins.size()); + + List mutationCountBins = + dataBins.stream() + .filter(bin -> bin.getAttributeId().equals("MUTATION_COUNT")) + .collect(Collectors.toList()); + assertEquals(6, mutationCountBins.size()); + assertEquals(2, mutationCountBins.get(0).getCount().intValue()); + assertEquals(1, mutationCountBins.get(1).getCount().intValue()); + assertEquals(1, mutationCountBins.get(2).getCount().intValue()); + assertEquals(1, mutationCountBins.get(3).getCount().intValue()); + assertEquals(1, mutationCountBins.get(4).getCount().intValue()); + assertEquals(1, mutationCountBins.get(5).getCount().intValue()); + + List fractionGenomeAlteredBins = + dataBins.stream() + .filter(bin -> bin.getAttributeId().equals("FRACTION_GENOME_ALTERED")) + .collect(Collectors.toList()); + assertEquals(7, fractionGenomeAlteredBins.size()); + assertEquals(1, fractionGenomeAlteredBins.get(0).getCount().intValue()); + assertEquals(1, fractionGenomeAlteredBins.get(1).getCount().intValue()); + assertEquals(1, fractionGenomeAlteredBins.get(2).getCount().intValue()); + assertEquals(1, fractionGenomeAlteredBins.get(3).getCount().intValue()); + assertEquals(1, fractionGenomeAlteredBins.get(4).getCount().intValue()); + assertEquals(1, fractionGenomeAlteredBins.get(5).getCount().intValue()); + assertEquals(1, fractionGenomeAlteredBins.get(6).getCount().intValue()); + + List ageAtSeqReportedYearsBins = + dataBins.stream() + .filter(bin -> bin.getAttributeId().equals("AGE_AT_SEQ_REPORTED_YEARS")) + .collect(Collectors.toList()); + assertEquals(6, ageAtSeqReportedYearsBins.size()); + assertEquals(1, ageAtSeqReportedYearsBins.get(0).getCount().intValue()); + assertEquals(1, ageAtSeqReportedYearsBins.get(1).getCount().intValue()); + assertEquals(2, ageAtSeqReportedYearsBins.get(2).getCount().intValue()); + assertEquals(1, ageAtSeqReportedYearsBins.get(3).getCount().intValue()); + assertEquals(1, ageAtSeqReportedYearsBins.get(4).getCount().intValue()); + assertEquals(1, ageAtSeqReportedYearsBins.get(5).getCount().intValue()); + + List caAgeBins = + dataBins.stream() + .filter(bin -> bin.getAttributeId().equals("CA_AGE")) + .collect(Collectors.toList()); + assertEquals(5, caAgeBins.size()); + assertEquals(1, caAgeBins.get(0).getCount().intValue()); + assertEquals(1, caAgeBins.get(1).getCount().intValue()); + assertEquals(1, caAgeBins.get(2).getCount().intValue()); + assertEquals(1, caAgeBins.get(3).getCount().intValue()); + assertEquals(1, caAgeBins.get(4).getCount().intValue()); + + List cptSeqBins = + dataBins.stream() + .filter(bin -> bin.getAttributeId().equals("CPT_SEQ_DATE")) + .collect(Collectors.toList()); + assertEquals(3, cptSeqBins.size()); + assertEquals(1, cptSeqBins.get(0).getCount().intValue()); + assertEquals(3, cptSeqBins.get(1).getCount().intValue()); + assertEquals(3, cptSeqBins.get(2).getCount().intValue()); + + List cptOrderIntBins = + dataBins.stream() + .filter(bin -> bin.getAttributeId().equals("CPT_ORDER_INT")) + .collect(Collectors.toList()); + assertEquals(1, cptOrderIntBins.size()); + assertEquals(7, cptOrderIntBins.get(0).getCount().intValue()); + + List hybridDeathIntBins = + dataBins.stream() + .filter(bin -> bin.getAttributeId().equals("HYBRID_DEATH_INT")) + .collect(Collectors.toList()); + assertEquals(5, hybridDeathIntBins.size()); + assertEquals(1, hybridDeathIntBins.get(0).getCount().intValue()); + assertEquals(1, hybridDeathIntBins.get(1).getCount().intValue()); + assertEquals(1, hybridDeathIntBins.get(2).getCount().intValue()); + assertEquals(1, hybridDeathIntBins.get(3).getCount().intValue()); + assertEquals(1, hybridDeathIntBins.get(4).getCount().intValue()); + + // assert function calls + verify(idPopulator, times(1)).populateIdLists(any(), any()); + + // we don't expect filterClinicalData to be called for an unfiltered query + verify(studyViewFilterUtil, never()) + .filterClinicalData(any(), any(), any(), any(), any(), any(), any(), any(), any(), any()); + + // study view filter should be applied only once + verify(studyViewFilterApplier, times(1)).apply(any()); + + // should call the correct bin calculate method only once for the given binning method + verify(clinicalDataBinUtil, times(1)) + .calculateStaticDataBins(any(), any(), any(), any(), any(), any(), any(), any()); + verify(clinicalDataBinUtil, never()) + .calculateDynamicDataBins(any(), any(), any(), any(), any()); + } + + @Test + public void testFilteredFetchClinicalDataBinCounts() { + mockUnfilteredQuery(); + mockFilteredQuery(); + + List dataBins = + clinicalDataBinUtil.fetchClinicalDataBinCounts(DataBinMethod.STATIC, mockQueryFilter()); + + // assert data bin counts + + assertEquals(33, dataBins.size()); + + List mutationCountBins = + dataBins.stream() + .filter(bin -> bin.getAttributeId().equals("MUTATION_COUNT")) + .collect(Collectors.toList()); + assertEquals(6, mutationCountBins.size()); + assertEquals(0, mutationCountBins.get(0).getCount().intValue()); + assertEquals(0, mutationCountBins.get(1).getCount().intValue()); + assertEquals(0, mutationCountBins.get(2).getCount().intValue()); + assertEquals(1, mutationCountBins.get(3).getCount().intValue()); + assertEquals(1, mutationCountBins.get(4).getCount().intValue()); + assertEquals(0, mutationCountBins.get(5).getCount().intValue()); + + List fractionGenomeAlteredBins = + dataBins.stream() + .filter(bin -> bin.getAttributeId().equals("FRACTION_GENOME_ALTERED")) + .collect(Collectors.toList()); + assertEquals(7, fractionGenomeAlteredBins.size()); + assertEquals(1, fractionGenomeAlteredBins.get(0).getCount().intValue()); + assertEquals(0, fractionGenomeAlteredBins.get(1).getCount().intValue()); + assertEquals(1, fractionGenomeAlteredBins.get(2).getCount().intValue()); + assertEquals(0, fractionGenomeAlteredBins.get(3).getCount().intValue()); + assertEquals(0, fractionGenomeAlteredBins.get(4).getCount().intValue()); + assertEquals(0, fractionGenomeAlteredBins.get(5).getCount().intValue()); + assertEquals(0, fractionGenomeAlteredBins.get(6).getCount().intValue()); + + List ageAtSeqReportedYearsBins = + dataBins.stream() + .filter(bin -> bin.getAttributeId().equals("AGE_AT_SEQ_REPORTED_YEARS")) + .collect(Collectors.toList()); + assertEquals(6, ageAtSeqReportedYearsBins.size()); + assertEquals(1, ageAtSeqReportedYearsBins.get(0).getCount().intValue()); + assertEquals(1, ageAtSeqReportedYearsBins.get(1).getCount().intValue()); + assertEquals(0, ageAtSeqReportedYearsBins.get(2).getCount().intValue()); + assertEquals(0, ageAtSeqReportedYearsBins.get(3).getCount().intValue()); + assertEquals(0, ageAtSeqReportedYearsBins.get(4).getCount().intValue()); + assertEquals(0, ageAtSeqReportedYearsBins.get(5).getCount().intValue()); + + List caAgeBins = + dataBins.stream() + .filter(bin -> bin.getAttributeId().equals("CA_AGE")) + .collect(Collectors.toList()); + assertEquals(5, caAgeBins.size()); + assertEquals(1, caAgeBins.get(0).getCount().intValue()); + assertEquals(1, caAgeBins.get(1).getCount().intValue()); + assertEquals(0, caAgeBins.get(2).getCount().intValue()); + assertEquals(0, caAgeBins.get(3).getCount().intValue()); + assertEquals(0, caAgeBins.get(4).getCount().intValue()); + + List cptSeqBins = + dataBins.stream() + .filter(bin -> bin.getAttributeId().equals("CPT_SEQ_DATE")) + .collect(Collectors.toList()); + assertEquals(3, cptSeqBins.size()); + assertEquals(0, cptSeqBins.get(0).getCount().intValue()); + assertEquals(2, cptSeqBins.get(1).getCount().intValue()); + assertEquals(0, cptSeqBins.get(2).getCount().intValue()); + + List cptOrderIntBins = + dataBins.stream() + .filter(bin -> bin.getAttributeId().equals("CPT_ORDER_INT")) + .collect(Collectors.toList()); + assertEquals(1, cptOrderIntBins.size()); + assertEquals(2, cptOrderIntBins.get(0).getCount().intValue()); + + List hybridDeathIntBins = + dataBins.stream() + .filter(bin -> bin.getAttributeId().equals("HYBRID_DEATH_INT")) + .collect(Collectors.toList()); + assertEquals(5, hybridDeathIntBins.size()); + assertEquals(1, hybridDeathIntBins.get(0).getCount().intValue()); + assertEquals(0, hybridDeathIntBins.get(1).getCount().intValue()); + assertEquals(0, hybridDeathIntBins.get(2).getCount().intValue()); + assertEquals(1, hybridDeathIntBins.get(3).getCount().intValue()); + assertEquals(0, hybridDeathIntBins.get(4).getCount().intValue()); + + // assert function calls + + // expect filterClinicalData to be called for a filtered query + verify(studyViewFilterUtil, times(1)) + .filterClinicalData(any(), any(), any(), any(), any(), any(), any(), any(), any(), any()); + + // study view filter should be applied twice + verify(studyViewFilterApplier, times(2)).apply(any()); + + // should call the correct bin calculate method only once for the given binning method + verify(clinicalDataBinUtil, times(1)) + .calculateStaticDataBins(any(), any(), any(), any(), any(), any(), any(), any()); + verify(clinicalDataBinUtil, never()) + .calculateDynamicDataBins(any(), any(), any(), any(), any()); + } + + @Test + public void fetchCustomDataBinCountsWithStaticBinningMethod() throws Exception { + String customDataset = getFileContents("classpath:custom-dataset.json"); + + mockCustomDataService(customDataset); + mockStudyViewFilterApplier(customDataset); + ClinicalDataBinCountFilter filter = createClinicalDataBinCountFilter(); + + List bins = + clinicalDataBinUtil.fetchCustomDataBinCounts(DataBinMethod.STATIC, filter, false); + + // Total number of bins: + assertEquals(11, bins.size()); + + // All bins should have the custom data set name as attribute: + List customDatasetAttributeBins = + bins.stream() + .filter(bin -> bin.getAttributeId().equals(testDataAttributeId)) + .collect(Collectors.toList()); + assertEquals(11, customDatasetAttributeBins.size()); + + assertEquals("<=", bins.get(0).getSpecialValue()); + assertEquals(3, bins.get(0).getCount().intValue()); + + // Bin size should be five: + assertEquals(5, bins.get(1).getEnd().intValue() - bins.get(1).getStart().intValue()); + assertEquals(5, bins.get(1).getCount().intValue()); + + assertEquals(8, bins.get(2).getCount().intValue()); + assertEquals(5, bins.get(3).getCount().intValue()); + assertEquals(8, bins.get(4).getCount().intValue()); + assertEquals(5, bins.get(5).getCount().intValue()); + assertEquals(8, bins.get(6).getCount().intValue()); + assertEquals(5, bins.get(7).getCount().intValue()); + assertEquals(6, bins.get(8).getCount().intValue()); + assertEquals(2, bins.get(9).getCount().intValue()); + + assertEquals(">", bins.get(10).getSpecialValue()); + assertEquals(1, bins.get(10).getCount().intValue()); + } + + @Test + public void fetchCustomDataBinCountsWithStaticBinningMethod_minimalExample() throws Exception { + String customDataset = getFileContents("classpath:custom-dataset-minimal.json"); + + mockCustomDataService(customDataset); + mockStudyViewFilterApplier(customDataset); + ClinicalDataBinCountFilter filter = createClinicalDataBinCountFilter(); + + List bins = + clinicalDataBinUtil.fetchCustomDataBinCounts(DataBinMethod.STATIC, filter, false); + + // Total number of bins: + assertEquals(13, bins.size()); + + // All bins should have the custom data set name as attribute: + List customDatasetAttributeBins = + bins.stream() + .filter(bin -> bin.getAttributeId().equals(testDataAttributeId)) + .collect(Collectors.toList()); + assertEquals(13, customDatasetAttributeBins.size()); + + // Start bin: + assertEquals("<=", bins.get(0).getSpecialValue()); + assertEquals(1, bins.get(0).getCount().intValue()); + assertEquals(-1.0, bins.get(0).getEnd().intValue(), 0); + + // Size of next bins should be 1: + assertEquals(1, bins.get(1).getEnd().intValue() - bins.get(1).getStart().intValue(), 0); + assertEquals(1, bins.get(1).getCount().intValue()); + + assertEquals(1, bins.get(2).getCount().intValue()); + assertEquals(2, bins.get(3).getCount().intValue()); + assertEquals(2, bins.get(4).getCount().intValue()); + assertEquals(1, bins.get(5).getCount().intValue()); + assertEquals(0, bins.get(6).getCount().intValue()); + assertEquals(1, bins.get(7).getCount().intValue()); + assertEquals(1, bins.get(8).getCount().intValue()); + assertEquals(1, bins.get(9).getCount().intValue()); + assertEquals(1, bins.get(10).getCount().intValue()); + assertEquals(1, bins.get(11).getCount().intValue()); + assertEquals(1, bins.get(12).getCount().intValue()); + } + + private void mockStudyViewFilterApplier(String customDataset) throws IOException { + TreeNode path = customDatasetMapper.readTree(customDataset).path("data").path("data"); + + TypeReference> type = new TypeReference>() {}; + List customIDs = + customDatasetMapper.readValue(customDatasetMapper.treeAsTokens(path), type); + + when(studyViewFilterApplier.apply(any())).thenReturn(customIDs); + } + + private String getFileContents(String resourceLocation) throws IOException { + return new String(Files.readAllBytes(ResourceUtils.getFile(resourceLocation).toPath())); + } + + private void mockUnfilteredQuery() { + mockMethods( + mockUnfilteredSampleIdentifiers(), + mockUnfilteredSampleIds(), + mockUnfilteredStudyIds(), + mockUnfilteredSampleAttributeIds(), + mockUnfilteredStudySampleUniqueKeys(), + mockUnfilteredClinicalDataForSamples(), + mockUnfilteredPatients(), + mockUnfilteredPatientIds(), + mockUnfilteredStudyIdsOfPatients(), + mockUnfilteredPatientAttributeIds(), + mockUnfilteredStudyPatientUniqueKeys(), + mockUnfilteredClinicalDataForPatients(), + mockUnfilteredStudyViewFilter(), + mockUnfilteredAttributeIds(), + mockUnfilteredClinicalAttributes()); + } + + private void mockFilteredQuery() { + mockMethods( + mockFilteredSampleIdentifiers(), + mockFilteredSampleIds(), + mockFilteredStudyIds(), + mockUnfilteredSampleAttributeIds(), + mockFilteredStudySampleUniqueKeys(), + null, + mockFilteredPatients(), + mockFilteredPatientIds(), + mockFilteredStudyIdsOfPatients(), + mockUnfilteredPatientAttributeIds(), + mockFilteredStudyPatientUniqueKeys(), + null, + mockFilteredStudyViewFilter(), + mockUnfilteredAttributeIds(), + mockFilteredClinicalAttributes()); + } + + private static final String sessionTestKey = "testkey"; + + @Value("classpath:state.json") + Resource stateFile; + + private void mockCustomDataService(String customDataset) throws Exception { + when(sessionServiceRequestHandler.getSessionDataJson(any(), any())).thenReturn(customDataset); + } + + private void mockMethods( + List sampleIdentifiers, + List sampleIds, + List studyIds, + List sampleAttributeIds, + List studySampleUniqueKeys, + List clinicalDataForSamples, + List patients, + List patientIds, + List studyIdsOfPatients, + List patientAttributeIds, + List studyPatientUniqueKeys, + List clinicalDataForPatients, + StudyViewFilter studyViewFilter, + List attributeIds, + List clinicalAttributes) { + when(patientService.getPatientsOfSamples(eq(studyIds), eq(sampleIds))).thenReturn(patients); + when(clinicalAttributeService.getClinicalAttributesByStudyIdsAndAttributeIds( + eq(studyIds), eq(attributeIds))) + .thenReturn(clinicalAttributes); + when(studyViewFilterApplier.apply(argThat(new StudyViewFilterMatcher(studyViewFilter)))) + .thenReturn(sampleIdentifiers); + when(studyViewFilterApplier.getUniqkeyKeys(eq(studyIds), eq(sampleIds))) + .thenReturn(studySampleUniqueKeys); + when(studyViewFilterApplier.getUniqkeyKeys(eq(studyIdsOfPatients), eq(patientIds))) + .thenReturn(studyPatientUniqueKeys); + + when(clinicalDataFetcher.fetchClinicalDataForSamples( + eq(studyIds), eq(sampleIds), eq(sampleAttributeIds))) + .thenReturn(clinicalDataForSamples); + when(clinicalDataFetcher.fetchClinicalDataForPatients( + eq(studyIdsOfPatients), eq(patientIds), eq(patientAttributeIds))) + .thenReturn(clinicalDataForPatients); + } + + private ClinicalDataBinCountFilter mockBaseFilter() { + ClinicalDataBinCountFilter filter = new ClinicalDataBinCountFilter(); + + filter.setAttributes(mockUnfilteredAttributes()); + filter.setStudyViewFilter(mockUnfilteredStudyViewFilter()); + + return filter; + } + + private ClinicalDataBinCountFilter mockQueryFilter() { + ClinicalDataBinCountFilter filter = new ClinicalDataBinCountFilter(); + + filter.setAttributes(mockUnfilteredAttributes()); + filter.setStudyViewFilter(mockFilteredStudyViewFilter()); + + return filter; + } + + private List mockUnfilteredStudySampleUniqueKeys() { + List keys = new ArrayList<>(); + + keys.add("genie_bpc_testGENIE-MSK-P-0003156-T01-IM5"); + keys.add("genie_bpc_testGENIE-MSK-P-0009680-T01-IM5"); + keys.add("genie_bpc_testGENIE-MSK-P-0012393-T01-IM5"); + keys.add("genie_bpc_testGENIE-MSK-P-0012393-T02-IM6"); + keys.add("genie_bpc_testGENIE-MSK-P-0015492-T01-IM6"); + keys.add("genie_bpc_testGENIE-MSK-P-0017284-T01-IM6"); + keys.add("genie_bpc_testGENIE-MSK-P-0017284-T02-IM5"); + + return keys; + } + + private List mockFilteredStudySampleUniqueKeys() { + List keys = new ArrayList<>(); + + keys.add("genie_bpc_testGENIE-MSK-P-0009680-T01-IM5"); + keys.add("genie_bpc_testGENIE-MSK-P-0015492-T01-IM6"); + + return keys; + } + + private List mockUnfilteredStudyPatientUniqueKeys() { + List keys = new ArrayList<>(); + + keys.add("genie_bpc_testGENIE-MSK-P-0015492"); + keys.add("genie_bpc_testGENIE-MSK-P-0003156"); + keys.add("genie_bpc_testGENIE-MSK-P-0009680"); + keys.add("genie_bpc_testGENIE-MSK-P-0012393"); + keys.add("genie_bpc_testGENIE-MSK-P-0017284"); + + return keys; + } + + private List mockFilteredStudyPatientUniqueKeys() { + List keys = new ArrayList<>(); + + keys.add("genie_bpc_testGENIE-MSK-P-0015492"); + keys.add("genie_bpc_testGENIE-MSK-P-0009680"); + + return keys; + } + + private List mockUnfilteredSampleIds() { + List sampleIds = new ArrayList<>(); + + sampleIds.add("GENIE-MSK-P-0003156-T01-IM5"); + sampleIds.add("GENIE-MSK-P-0009680-T01-IM5"); + sampleIds.add("GENIE-MSK-P-0012393-T01-IM5"); + sampleIds.add("GENIE-MSK-P-0012393-T02-IM6"); + sampleIds.add("GENIE-MSK-P-0015492-T01-IM6"); + sampleIds.add("GENIE-MSK-P-0017284-T01-IM6"); + sampleIds.add("GENIE-MSK-P-0017284-T02-IM5"); + + return sampleIds; + } + + private List mockFilteredSampleIds() { + List sampleIds = new ArrayList<>(); + + sampleIds.add("GENIE-MSK-P-0009680-T01-IM5"); + sampleIds.add("GENIE-MSK-P-0015492-T01-IM6"); + + return sampleIds; + } + + private List mockUnfilteredPatientIds() { + List patientIds = new ArrayList<>(); + + patientIds.add("GENIE-MSK-P-0015492"); + patientIds.add("GENIE-MSK-P-0003156"); + patientIds.add("GENIE-MSK-P-0009680"); + patientIds.add("GENIE-MSK-P-0012393"); + patientIds.add("GENIE-MSK-P-0017284"); + + return patientIds; + } + + private List mockFilteredPatientIds() { + List patientIds = new ArrayList<>(); + + patientIds.add("GENIE-MSK-P-0015492"); + patientIds.add("GENIE-MSK-P-0009680"); + + return patientIds; + } + + private List mockUnfilteredPatients() { + return mockPatients(mockUnfilteredPatientIds()); + } + + private List mockFilteredPatients() { + return mockPatients(mockFilteredPatientIds()); + } + + private List mockPatients(List patientIds) { + List patients = new ArrayList<>(); + + for (String patientId : patientIds) { + Patient patient = new Patient(); + patient.setCancerStudyIdentifier(STUDY_ID); + patient.setStableId(patientId); + patients.add(patient); + } + + return patients; + } + + private List mockUnfilteredStudyIds() { + return Collections.nCopies(7, STUDY_ID); + } + + private List mockFilteredStudyIds() { + return Collections.nCopies(2, STUDY_ID); + } + + private List mockUnfilteredStudyIdsOfPatients() { + return Collections.nCopies(5, STUDY_ID); + } + + private List mockFilteredStudyIdsOfPatients() { + return Collections.nCopies(2, STUDY_ID); + } + + private List mockUnfilteredSampleIdentifiers() { + return mockSampleIdentifiers(mockUnfilteredSampleIds()); + } + + private List mockFilteredSampleIdentifiers() { + return mockSampleIdentifiers(mockFilteredSampleIds()); + } + + private List mockSampleIdentifiers(List sampleIds) { + List sampleIdentifiers = new ArrayList<>(); + + for (String sampleId : sampleIds) { + SampleIdentifier identifier = new SampleIdentifier(); + identifier.setSampleId(sampleId); + identifier.setStudyId(STUDY_ID); + sampleIdentifiers.add(identifier); + } + + return sampleIdentifiers; + } + + private List mockUnfilteredAttributeIds() { + List attributeIds = new ArrayList<>(); + + attributeIds.addAll(mockUnfilteredSampleAttributeIds()); + attributeIds.addAll(mockUnfilteredPatientAttributeIds()); + + return attributeIds; + } + + private List mockUnfilteredSampleAttributeIds() { + List attributeIds = new ArrayList<>(); + + attributeIds.add("CPT_SEQ_DATE"); + attributeIds.add("CPT_ORDER_INT"); + attributeIds.add("MUTATION_COUNT"); + attributeIds.add("AGE_AT_SEQ_REPORTED_YEARS"); + attributeIds.add("FRACTION_GENOME_ALTERED"); + + return attributeIds; + } + + private List mockUnfilteredPatientAttributeIds() { + List attributeIds = new ArrayList<>(); + + attributeIds.add("CA_AGE"); + attributeIds.add("HYBRID_DEATH_INT"); + + return attributeIds; + } + + private List mockUnfilteredAttributes() { + List attributes = new ArrayList<>(); + List attributeIds = mockUnfilteredAttributeIds(); + + for (String attributeId : attributeIds) { + ClinicalDataBinFilter filter = new ClinicalDataBinFilter(); + filter.setAttributeId(attributeId); + attributes.add(filter); + } + + return attributes; + } + + private ClinicalAttribute mockClinicalAttribute( + String attrId, String displayName, boolean isPatientAttribute) { + ClinicalAttribute attr = new ClinicalAttribute(); + + attr.setAttrId(attrId); + attr.setDisplayName(displayName); + attr.setDatatype("NUMBER"); + attr.setPatientAttribute(isPatientAttribute); + attr.setCancerStudyId(STUDY_ID_INT); + attr.setCancerStudyIdentifier(STUDY_ID); + + return attr; + } + + private List mockUnfilteredClinicalAttributes() { + List clinicalAttributes = new ArrayList<>(); + + clinicalAttributes.add( + mockClinicalAttribute( + "AGE_AT_SEQ_REPORTED_YEARS", "Age at Which Sequencing was Reported (Years)", false)); + clinicalAttributes.add( + mockClinicalAttribute("CA_AGE", "Curated Patient Age at Diagnosis", true)); + clinicalAttributes.add( + mockClinicalAttribute( + "CPT_ORDER_INT", "Interval in Days from Date of Birth to Cancer Order Date", false)); + clinicalAttributes.add( + mockClinicalAttribute("CPT_SEQ_DATE", "GENIE Sequence Date (quarter year)", false)); + clinicalAttributes.add( + mockClinicalAttribute("FRACTION_GENOME_ALTERED", "Fraction Genome Altered", false)); + clinicalAttributes.add( + mockClinicalAttribute( + "HYBRID_DEATH_INT", "Interval in Months from DOB to Date of Death", true)); + clinicalAttributes.add(mockClinicalAttribute("MUTATION_COUNT", "Mutation Count", false)); + + return clinicalAttributes; + } + + private List mockFilteredClinicalAttributes() { + List clinicalAttributes = new ArrayList<>(); + + clinicalAttributes.add( + mockClinicalAttribute( + "AGE_AT_SEQ_REPORTED_YEARS", "Age at Which Sequencing was Reported (Years)", false)); + clinicalAttributes.add( + mockClinicalAttribute("CA_AGE", "Curated Patient Age at Diagnosis", true)); + clinicalAttributes.add( + mockClinicalAttribute("CPT_SEQ_DATE", "GENIE Sequence Date (quarter year)", false)); + clinicalAttributes.add( + mockClinicalAttribute("FRACTION_GENOME_ALTERED", "Fraction Genome Altered", false)); + clinicalAttributes.add( + mockClinicalAttribute( + "HYBRID_DEATH_INT", "Interval in Months from DOB to Date of Death", true)); + clinicalAttributes.add(mockClinicalAttribute("MUTATION_COUNT", "Mutation Count", false)); + + return clinicalAttributes; + } + + private ClinicalData mockClinicalData( + String id, String value, String patientId, String sampleId) { + ClinicalData data = new ClinicalData(); + + data.setAttrId(id); + data.setAttrValue(value); + data.setPatientId(patientId); + data.setSampleId(sampleId); + data.setStudyId(STUDY_ID); + + return data; + } + + private List mockUnfilteredClinicalDataForSamples() { + List data = new ArrayList<>(); + + data.add( + mockClinicalData( + "AGE_AT_SEQ_REPORTED_YEARS", + "53.03", + "GENIE-MSK-P-0015492", + "GENIE-MSK-P-0015492-T01-IM6")); + data.add( + mockClinicalData( + "CPT_SEQ_DATE", "2016", "GENIE-MSK-P-0015492", "GENIE-MSK-P-0015492-T01-IM6")); + data.add( + mockClinicalData( + "FRACTION_GENOME_ALTERED", + "0.0460", + "GENIE-MSK-P-0015492", + "GENIE-MSK-P-0015492-T01-IM6")); + data.add( + mockClinicalData( + "MUTATION_COUNT", "7", "GENIE-MSK-P-0015492", "GENIE-MSK-P-0015492-T01-IM6")); + data.add( + mockClinicalData( + "AGE_AT_SEQ_REPORTED_YEARS", + "78.05", + "GENIE-MSK-P-0003156", + "GENIE-MSK-P-0003156-T01-IM5")); + data.add( + mockClinicalData( + "CPT_SEQ_DATE", "2015", "GENIE-MSK-P-0003156", "GENIE-MSK-P-0003156-T01-IM5")); + data.add( + mockClinicalData( + "FRACTION_GENOME_ALTERED", + "0.2164", + "GENIE-MSK-P-0003156", + "GENIE-MSK-P-0003156-T01-IM5")); + data.add( + mockClinicalData( + "MUTATION_COUNT", "8", "GENIE-MSK-P-0003156", "GENIE-MSK-P-0003156-T01-IM5")); + data.add( + mockClinicalData( + "AGE_AT_SEQ_REPORTED_YEARS", + "59.04", + "GENIE-MSK-P-0009680", + "GENIE-MSK-P-0009680-T01-IM5")); + data.add( + mockClinicalData( + "CPT_SEQ_DATE", "2016", "GENIE-MSK-P-0009680", "GENIE-MSK-P-0009680-T01-IM5")); + data.add( + mockClinicalData( + "FRACTION_GENOME_ALTERED", + "0.2073", + "GENIE-MSK-P-0009680", + "GENIE-MSK-P-0009680-T01-IM5")); + data.add( + mockClinicalData( + "MUTATION_COUNT", "6", "GENIE-MSK-P-0009680", "GENIE-MSK-P-0009680-T01-IM5")); + data.add( + mockClinicalData( + "AGE_AT_SEQ_REPORTED_YEARS", + "72.04", + "GENIE-MSK-P-0012393", + "GENIE-MSK-P-0012393-T01-IM5")); + data.add( + mockClinicalData( + "CPT_SEQ_DATE", "2016", "GENIE-MSK-P-0012393", "GENIE-MSK-P-0012393-T01-IM5")); + data.add( + mockClinicalData( + "FRACTION_GENOME_ALTERED", + "0.5280", + "GENIE-MSK-P-0012393", + "GENIE-MSK-P-0012393-T01-IM5")); + data.add( + mockClinicalData( + "MUTATION_COUNT", "3", "GENIE-MSK-P-0012393", "GENIE-MSK-P-0012393-T01-IM5")); + data.add( + mockClinicalData( + "AGE_AT_SEQ_REPORTED_YEARS", + "73.04", + "GENIE-MSK-P-0012393", + "GENIE-MSK-P-0012393-T02-IM6")); + data.add( + mockClinicalData( + "CPT_SEQ_DATE", "2017", "GENIE-MSK-P-0012393", "GENIE-MSK-P-0012393-T02-IM6")); + data.add( + mockClinicalData( + "FRACTION_GENOME_ALTERED", + "0.1297", + "GENIE-MSK-P-0012393", + "GENIE-MSK-P-0012393-T02-IM6")); + data.add( + mockClinicalData( + "MUTATION_COUNT", "3", "GENIE-MSK-P-0012393", "GENIE-MSK-P-0012393-T02-IM6")); + data.add( + mockClinicalData( + "AGE_AT_SEQ_REPORTED_YEARS", + "64.04", + "GENIE-MSK-P-0017284", + "GENIE-MSK-P-0017284-T01-IM6")); + data.add( + mockClinicalData( + "CPT_SEQ_DATE", "2017", "GENIE-MSK-P-0017284", "GENIE-MSK-P-0017284-T01-IM6")); + data.add( + mockClinicalData( + "FRACTION_GENOME_ALTERED", + "0.2796", + "GENIE-MSK-P-0017284", + "GENIE-MSK-P-0017284-T01-IM6")); + data.add( + mockClinicalData( + "MUTATION_COUNT", "5", "GENIE-MSK-P-0017284", "GENIE-MSK-P-0017284-T01-IM6")); + data.add( + mockClinicalData( + "AGE_AT_SEQ_REPORTED_YEARS", + "64.04", + "GENIE-MSK-P-0017284", + "GENIE-MSK-P-0017284-T02-IM5")); + data.add( + mockClinicalData( + "CPT_SEQ_DATE", "2017", "GENIE-MSK-P-0017284", "GENIE-MSK-P-0017284-T02-IM5")); + data.add( + mockClinicalData( + "FRACTION_GENOME_ALTERED", + "0.7233", + "GENIE-MSK-P-0017284", + "GENIE-MSK-P-0017284-T02-IM5")); + data.add( + mockClinicalData( + "MUTATION_COUNT", "4", "GENIE-MSK-P-0017284", "GENIE-MSK-P-0017284-T02-IM5")); + + return data; + } + + private List mockUnfilteredClinicalDataForPatients() { + List data = new ArrayList<>(); + + data.add(mockClinicalData("CA_AGE", "52", "GENIE-MSK-P-0015492", null)); + data.add(mockClinicalData("HYBRID_DEATH_INT", "657.3", "GENIE-MSK-P-0015492", null)); + data.add(mockClinicalData("CA_AGE", "77", "GENIE-MSK-P-0003156", null)); + data.add(mockClinicalData("HYBRID_DEATH_INT", "968.1", "GENIE-MSK-P-0003156", null)); + data.add(mockClinicalData("CA_AGE", "56", "GENIE-MSK-P-0009680", null)); + data.add(mockClinicalData("HYBRID_DEATH_INT", "8765.7", "GENIE-MSK-P-0009680", null)); + data.add(mockClinicalData("CA_AGE", "71", "GENIE-MSK-P-0012393", null)); + data.add(mockClinicalData("HYBRID_DEATH_INT", "730.4", "GENIE-MSK-P-0012393", null)); + data.add(mockClinicalData("CA_AGE", "62", "GENIE-MSK-P-0017284", null)); + + return data; + } + + private StudyViewFilter mockUnfilteredStudyViewFilter() { + StudyViewFilter studyViewFilter = new StudyViewFilter(); + + List studyIds = new ArrayList<>(); + studyIds.add("genie_bpc_test"); + studyViewFilter.setStudyIds(studyIds); + + return studyViewFilter; + } + + private StudyViewFilter mockFilteredStudyViewFilter() { + StudyViewFilter studyViewFilter = mockUnfilteredStudyViewFilter(); + + ClinicalDataFilter sexFilter = new ClinicalDataFilter(); + sexFilter.setAttributeId("SEX"); + List sexValues = new ArrayList<>(); + DataFilterValue female = new DataFilterValue(); + female.setValue("Female"); + sexValues.add(female); + sexFilter.setValues(sexValues); + + ClinicalDataFilter sampleCountFilter = new ClinicalDataFilter(); + sampleCountFilter.setAttributeId("SAMPLE_COUNT"); + List sampleCountValues = new ArrayList<>(); + DataFilterValue one = new DataFilterValue(); + one.setValue("1"); + sampleCountValues.add(one); + sampleCountFilter.setValues(sampleCountValues); + + List filters = new ArrayList<>(); + filters.add(sexFilter); + filters.add(sampleCountFilter); + + studyViewFilter.setClinicalDataFilters(filters); + + return studyViewFilter; + } + + private class StudyViewFilterMatcher implements ArgumentMatcher { + + private StudyViewFilter source; + + public StudyViewFilterMatcher(StudyViewFilter source) { + this.source = source; + } + + @Override + public boolean matches(StudyViewFilter target) { + return (target != null + && Objects.equals(target.getStudyIds(), source.getStudyIds()) + && Objects.equals(target.getSampleIdentifiers(), source.getSampleIdentifiers()) + && equalClinicalDataFilters( + source.getClinicalDataFilters(), target.getClinicalDataFilters())); + } + + private boolean equalClinicalDataFilters( + List sourceFilters, List targetFilters) { + if (sourceFilters == null && targetFilters == null) { + return true; + } + + if (sourceFilters != null + && targetFilters != null + && sourceFilters.size() == targetFilters.size()) { + for (int i = 0; i < sourceFilters.size(); i++) { + if (!Objects.equals( + sourceFilters.get(i).getAttributeId(), targetFilters.get(i).getAttributeId()) + || !equalDataFilterValues( + sourceFilters.get(i).getValues(), targetFilters.get(i).getValues())) { + return false; + } + } + } else { + return false; + } + + return true; + } + + private boolean equalDataFilterValues( + List sourceValues, List targetValues) { + if (sourceValues == null && targetValues == null) { + return true; + } + + if (sourceValues != null + && targetValues != null + && sourceValues.size() == targetValues.size()) { + for (int i = 0; i < sourceValues.size(); i++) { + if (!Objects.equals(sourceValues.get(i).getStart(), targetValues.get(i).getStart()) + || !Objects.equals(sourceValues.get(i).getEnd(), targetValues.get(i).getEnd()) + || !Objects.equals(sourceValues.get(i).getValue(), targetValues.get(i).getValue())) { + return false; + } + } + } else { + return false; + } + + return true; + } + } + + private ClinicalDataBinCountFilter createClinicalDataBinCountFilter() { + ClinicalDataBinCountFilter clinicalDataBinCountFilter = new ClinicalDataBinCountFilter(); + List attributes = new ArrayList<>(); + ClinicalDataBinFilter clinicalDataBinFilter = new ClinicalDataBinFilter(); + clinicalDataBinFilter.setAttributeId(testDataAttributeId); + clinicalDataBinFilter.setBinMethod(DataBinFilter.BinMethod.CUSTOM); + StudyViewFilter studyViewFilter = new StudyViewFilter(); + ArrayList studyIds = new ArrayList<>(); + studyIds.add("study_es_0"); + studyViewFilter.setStudyIds(studyIds); + clinicalDataBinCountFilter.setStudyViewFilter(studyViewFilter); + attributes.add(clinicalDataBinFilter); + clinicalDataBinCountFilter.setAttributes(attributes); + return clinicalDataBinCountFilter; + } +} diff --git a/src/test/java/org/cbioportal/legacy/web/util/ClinicalDataEnrichmentUtilTest.java b/src/test/java/org/cbioportal/legacy/web/util/ClinicalDataEnrichmentUtilTest.java new file mode 100644 index 00000000000..55cfb14872b --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/web/util/ClinicalDataEnrichmentUtilTest.java @@ -0,0 +1,400 @@ +package org.cbioportal.legacy.web.util; + +import static org.mockito.ArgumentMatchers.*; +import static org.mockito.Mockito.when; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import org.cbioportal.legacy.model.ClinicalAttribute; +import org.cbioportal.legacy.model.ClinicalData; +import org.cbioportal.legacy.model.ClinicalDataCount; +import org.cbioportal.legacy.model.ClinicalDataCountItem; +import org.cbioportal.legacy.model.ClinicalDataEnrichment; +import org.cbioportal.legacy.model.Sample; +import org.cbioportal.legacy.service.ClinicalAttributeService; +import org.cbioportal.legacy.service.ClinicalDataService; +import org.cbioportal.legacy.service.SampleService; +import org.cbioportal.legacy.service.util.ClinicalAttributeUtil; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Spy; +import org.mockito.junit.MockitoJUnitRunner; + +@RunWith(MockitoJUnitRunner.class) +public class ClinicalDataEnrichmentUtilTest { + + public static final String STUDY_ID1 = "study_id_1"; + public static final String STUDY_ID2 = "study_id_2"; + public static final String SAMPLE_ID1 = "sample_id1"; + public static final String SAMPLE_ID2 = "sample_id2"; + public static final String SAMPLE_ID3 = "sample_id3"; + public static final String SAMPLE_ID4 = "sample_id4"; + public static final String SAMPLE_ID5 = "sample_id5"; + + public static final String PATIENT_ID1 = "patient_id1"; + public static final String PATIENT_ID2 = "patient_id2"; + public static final String PATIENT_ID3 = "patient_id3"; + public static final String PATIENT_ID4 = "patient_id4"; + public static final String PATIENT_ID5 = "patient_id5"; + public static final String CLINICAL_ATTRIBUTE_ID_1 = "attribute_id1"; + public static final String CLINICAL_ATTRIBUTE_ID_2 = "attribute_id2"; + public static final String CLINICAL_ATTRIBUTE_ID_3 = "attribute_id3"; + public static final String CLINICAL_ATTRIBUTE_ID_4 = "attribute_id4"; + + @InjectMocks private ClinicalDataEnrichmentUtil clinicalDataEnrichmentUtil; + + @Mock private ClinicalDataService clinicalDataService; + + @Mock private ClinicalAttributeService clinicalAttributeService; + + @Mock private SampleService sampleService; + + @Spy private ClinicalAttributeUtil clinicalAttributeUtil = new ClinicalAttributeUtil(); + + @Test + public void fetchClinicalDataEnrichemnts() { + + List expectedSampleClinicalDataList = new ArrayList<>(); + ClinicalData sampleClinicalData = new ClinicalData(); + expectedSampleClinicalDataList.add(sampleClinicalData); + + Sample sample1 = new Sample(); + sample1.setStableId(SAMPLE_ID1); + sample1.setPatientStableId(PATIENT_ID1); + sample1.setCancerStudyIdentifier(STUDY_ID1); + + Sample sample2 = new Sample(); + sample2.setStableId(SAMPLE_ID2); + sample2.setPatientStableId(PATIENT_ID2); + sample2.setCancerStudyIdentifier(STUDY_ID1); + + Sample sample3 = new Sample(); + sample3.setStableId(SAMPLE_ID3); + sample3.setPatientStableId(PATIENT_ID3); + sample3.setCancerStudyIdentifier(STUDY_ID2); + + Sample sample4 = new Sample(); + sample4.setStableId(SAMPLE_ID4); + sample4.setPatientStableId(PATIENT_ID4); + sample4.setCancerStudyIdentifier(STUDY_ID2); + + Sample sample5 = new Sample(); + sample5.setStableId(SAMPLE_ID5); + sample5.setPatientStableId(PATIENT_ID5); + sample5.setCancerStudyIdentifier(STUDY_ID2); + + ClinicalAttribute attribute1 = new ClinicalAttribute(); + attribute1.setAttrId(CLINICAL_ATTRIBUTE_ID_1); + attribute1.setDatatype("STRING"); + attribute1.setPatientAttribute(false); + + ClinicalAttribute attribute2 = new ClinicalAttribute(); + attribute2.setAttrId(CLINICAL_ATTRIBUTE_ID_2); + attribute2.setDatatype("STRING"); + attribute2.setPatientAttribute(true); + + ClinicalAttribute attribute3 = new ClinicalAttribute(); + attribute3.setAttrId(CLINICAL_ATTRIBUTE_ID_3); + attribute3.setDatatype("NUMBER"); + attribute3.setPatientAttribute(true); + + ClinicalAttribute attribute4 = new ClinicalAttribute(); + attribute4.setAttrId(CLINICAL_ATTRIBUTE_ID_4); + attribute4.setDatatype("NUMBER"); + attribute4.setPatientAttribute(true); + + List attributes = + Arrays.asList(attribute1, attribute2, attribute3, attribute4); + + List> groupedSamples = new ArrayList>(); + groupedSamples.add(Arrays.asList(sample1, sample2)); + groupedSamples.add(Arrays.asList(sample3, sample4, sample5)); + + ClinicalDataCount sampleClinicalDataCount1 = new ClinicalDataCount(); + sampleClinicalDataCount1.setAttributeId(CLINICAL_ATTRIBUTE_ID_1); + sampleClinicalDataCount1.setValue("TEST_CLINICAL_DATA_VALUE_1"); + sampleClinicalDataCount1.setCount(1); + + ClinicalDataCount sampleClinicalDataCount2 = new ClinicalDataCount(); + sampleClinicalDataCount2.setAttributeId(CLINICAL_ATTRIBUTE_ID_1); + sampleClinicalDataCount2.setValue("TEST_CLINICAL_DATA_VALUE_2"); + sampleClinicalDataCount2.setCount(1); + + ClinicalDataCount patientClinicalDataCount1 = new ClinicalDataCount(); + patientClinicalDataCount1.setAttributeId(CLINICAL_ATTRIBUTE_ID_2); + patientClinicalDataCount1.setValue("TEST_CLINICAL_DATA_VALUE_1"); + patientClinicalDataCount1.setCount(1); + + ClinicalDataCount patientClinicalDataCount2 = new ClinicalDataCount(); + patientClinicalDataCount2.setAttributeId(CLINICAL_ATTRIBUTE_ID_2); + patientClinicalDataCount2.setValue("TEST_CLINICAL_DATA_VALUE_2"); + patientClinicalDataCount2.setCount(1); + + ClinicalDataCountItem group1sampleClinicalDataCountItem = new ClinicalDataCountItem(); + group1sampleClinicalDataCountItem.setAttributeId(CLINICAL_ATTRIBUTE_ID_1); + group1sampleClinicalDataCountItem.setCounts( + Arrays.asList(sampleClinicalDataCount1, sampleClinicalDataCount2)); + + ClinicalDataCountItem group1patientClinicalDataCountItem = new ClinicalDataCountItem(); + group1patientClinicalDataCountItem.setAttributeId(CLINICAL_ATTRIBUTE_ID_2); + group1patientClinicalDataCountItem.setCounts( + Arrays.asList(patientClinicalDataCount1, patientClinicalDataCount2)); + + when(clinicalDataService.fetchClinicalDataCounts(anyList(), anyList(), anyList())) + .thenReturn(new ArrayList()); + + // when there is no data + Assert.assertTrue( + clinicalDataEnrichmentUtil + .createEnrichmentsForCategoricalData(attributes, groupedSamples) + .isEmpty()); + + when(clinicalDataService.fetchClinicalDataCounts( + Arrays.asList(STUDY_ID1, STUDY_ID1), + Arrays.asList(SAMPLE_ID1, SAMPLE_ID2), + Arrays.asList(CLINICAL_ATTRIBUTE_ID_1, CLINICAL_ATTRIBUTE_ID_2))) + .thenReturn( + Arrays.asList(group1sampleClinicalDataCountItem, group1patientClinicalDataCountItem)); + + // where there are no attributes with STRING datatype + Assert.assertTrue( + clinicalDataEnrichmentUtil + .createEnrichmentsForCategoricalData( + Arrays.asList(attribute3, attribute4), groupedSamples) + .isEmpty()); + + // when attributes is empty + Assert.assertTrue( + clinicalDataEnrichmentUtil + .createEnrichmentsForCategoricalData(new ArrayList(), groupedSamples) + .isEmpty()); + + List actualClinicalDataEnrichments = + clinicalDataEnrichmentUtil.createEnrichmentsForCategoricalData(attributes, groupedSamples); + + // when there is data for only one group + Assert.assertEquals(0, actualClinicalDataEnrichments.size()); + + ClinicalDataCount sampleClinicalDataCount3 = new ClinicalDataCount(); + sampleClinicalDataCount3.setAttributeId(CLINICAL_ATTRIBUTE_ID_1); + sampleClinicalDataCount3.setValue("TEST_CLINICAL_DATA_VALUE_3"); + sampleClinicalDataCount3.setCount(3); + + ClinicalDataCount patientClinicalDataCount3 = new ClinicalDataCount(); + patientClinicalDataCount3.setAttributeId(CLINICAL_ATTRIBUTE_ID_2); + patientClinicalDataCount3.setValue("TEST_CLINICAL_DATA_VALUE_3"); + patientClinicalDataCount3.setCount(3); + + ClinicalDataCountItem group2sampleClinicalDataCountItem = new ClinicalDataCountItem(); + group2sampleClinicalDataCountItem.setAttributeId(CLINICAL_ATTRIBUTE_ID_1); + group2sampleClinicalDataCountItem.setCounts(Arrays.asList(sampleClinicalDataCount3)); + + ClinicalDataCountItem group2patientClinicalDataCountItem = new ClinicalDataCountItem(); + group2patientClinicalDataCountItem.setAttributeId(CLINICAL_ATTRIBUTE_ID_2); + group2patientClinicalDataCountItem.setCounts(Arrays.asList(patientClinicalDataCount3)); + + // data only for string datatype and for all groups + when(clinicalDataService.fetchClinicalDataCounts( + Arrays.asList(STUDY_ID2, STUDY_ID2, STUDY_ID2), + Arrays.asList(SAMPLE_ID3, SAMPLE_ID4, SAMPLE_ID5), + Arrays.asList(CLINICAL_ATTRIBUTE_ID_1, CLINICAL_ATTRIBUTE_ID_2))) + .thenReturn( + Arrays.asList(group2sampleClinicalDataCountItem, group2patientClinicalDataCountItem)); + + actualClinicalDataEnrichments = + clinicalDataEnrichmentUtil.createEnrichmentsForCategoricalData(attributes, groupedSamples); + + // when there is data for more than one group + Assert.assertEquals(2, actualClinicalDataEnrichments.size()); + Assert.assertEquals( + "0.08208499862670093", actualClinicalDataEnrichments.get(0).getpValue().toString()); + Assert.assertEquals( + "4.999999999999999", actualClinicalDataEnrichments.get(0).getScore().toString()); + Assert.assertEquals("Chi-squared Test", actualClinicalDataEnrichments.get(0).getMethod()); + } + + @Test + public void createEnrichmentsForNumericData() { + + List expectedSampleClinicalDataList = new ArrayList<>(); + ClinicalData sampleClinicalData = new ClinicalData(); + expectedSampleClinicalDataList.add(sampleClinicalData); + + Sample sample1 = new Sample(); + sample1.setStableId(SAMPLE_ID1); + sample1.setPatientStableId(PATIENT_ID1); + sample1.setCancerStudyIdentifier(STUDY_ID1); + + Sample sample2 = new Sample(); + sample2.setStableId(SAMPLE_ID2); + sample2.setPatientStableId(PATIENT_ID2); + sample2.setCancerStudyIdentifier(STUDY_ID1); + + Sample sample3 = new Sample(); + sample3.setStableId(SAMPLE_ID3); + sample3.setPatientStableId(PATIENT_ID3); + sample3.setCancerStudyIdentifier(STUDY_ID2); + + Sample sample4 = new Sample(); + sample4.setStableId(SAMPLE_ID4); + sample4.setPatientStableId(PATIENT_ID4); + sample4.setCancerStudyIdentifier(STUDY_ID2); + + Sample sample5 = new Sample(); + sample5.setStableId(SAMPLE_ID5); + sample5.setPatientStableId(PATIENT_ID5); + sample5.setCancerStudyIdentifier(STUDY_ID2); + + ClinicalAttribute attribute1 = new ClinicalAttribute(); + attribute1.setAttrId(CLINICAL_ATTRIBUTE_ID_1); + attribute1.setDatatype("STRING"); + attribute1.setPatientAttribute(false); + + ClinicalAttribute attribute2 = new ClinicalAttribute(); + attribute2.setAttrId(CLINICAL_ATTRIBUTE_ID_2); + attribute2.setDatatype("STRING"); + attribute2.setPatientAttribute(true); + + ClinicalAttribute attribute3 = new ClinicalAttribute(); + attribute3.setAttrId(CLINICAL_ATTRIBUTE_ID_3); + attribute3.setDatatype("NUMBER"); + attribute3.setPatientAttribute(false); + + ClinicalAttribute attribute4 = new ClinicalAttribute(); + attribute4.setAttrId(CLINICAL_ATTRIBUTE_ID_4); + attribute4.setDatatype("NUMBER"); + attribute4.setPatientAttribute(true); + + List attributes = + Arrays.asList(attribute1, attribute2, attribute3, attribute4); + + List> groupedSamples = new ArrayList>(); + groupedSamples.add(Arrays.asList(sample1, sample2)); + groupedSamples.add(Arrays.asList(sample3, sample4, sample5)); + + ClinicalData sampleClinicalData1 = new ClinicalData(); + sampleClinicalData1.setAttrId(CLINICAL_ATTRIBUTE_ID_3); + sampleClinicalData1.setAttrValue("2"); + sampleClinicalData1.setSampleId(SAMPLE_ID1); + sampleClinicalData1.setStudyId(STUDY_ID1); + + ClinicalData sampleClinicalData2 = new ClinicalData(); + sampleClinicalData2.setAttrId(CLINICAL_ATTRIBUTE_ID_3); + sampleClinicalData2.setAttrValue("3"); + sampleClinicalData2.setSampleId(SAMPLE_ID2); + sampleClinicalData2.setStudyId(STUDY_ID1); + + ClinicalData patientClinicalData1 = new ClinicalData(); + patientClinicalData1.setAttrId(CLINICAL_ATTRIBUTE_ID_4); + patientClinicalData1.setAttrValue("2"); + patientClinicalData1.setSampleId(SAMPLE_ID1); + patientClinicalData1.setStudyId(STUDY_ID1); + + ClinicalData patientClinicalData2 = new ClinicalData(); + patientClinicalData2.setAttrId(CLINICAL_ATTRIBUTE_ID_4); + patientClinicalData2.setAttrValue("1"); + patientClinicalData2.setSampleId(SAMPLE_ID1); + patientClinicalData2.setStudyId(STUDY_ID1); + + when(clinicalDataService.fetchClinicalData( + anyList(), anyList(), anyList(), anyString(), anyString())) + .thenReturn(new ArrayList()); + + // when no data + Assert.assertTrue( + clinicalDataEnrichmentUtil + .createEnrichmentsForNumericData(attributes, groupedSamples) + .isEmpty()); + + // data only for one group + when(clinicalDataService.fetchClinicalData( + Arrays.asList(STUDY_ID1, STUDY_ID1), + Arrays.asList(SAMPLE_ID1, SAMPLE_ID2), + Arrays.asList(CLINICAL_ATTRIBUTE_ID_3), + "SAMPLE", + "SUMMARY")) + .thenReturn(Arrays.asList(sampleClinicalData1, sampleClinicalData2)); + + when(clinicalDataService.fetchClinicalData( + Arrays.asList(STUDY_ID1, STUDY_ID1), + Arrays.asList(PATIENT_ID1, PATIENT_ID2), + Arrays.asList(CLINICAL_ATTRIBUTE_ID_4), + "PATIENT", + "SUMMARY")) + .thenReturn(Arrays.asList(patientClinicalData1, patientClinicalData2)); + + // when there is data only for one group + Assert.assertTrue( + clinicalDataEnrichmentUtil + .createEnrichmentsForNumericData(attributes, groupedSamples) + .isEmpty()); + + ClinicalData sampleClinicalData3 = new ClinicalData(); + sampleClinicalData3.setAttrId(CLINICAL_ATTRIBUTE_ID_3); + sampleClinicalData3.setAttrValue("1"); + sampleClinicalData3.setSampleId(SAMPLE_ID3); + sampleClinicalData3.setStudyId(STUDY_ID2); + + ClinicalData sampleClinicalData4 = new ClinicalData(); + sampleClinicalData4.setAttrId(CLINICAL_ATTRIBUTE_ID_3); + sampleClinicalData4.setAttrValue("5"); + sampleClinicalData4.setSampleId(SAMPLE_ID4); + sampleClinicalData4.setStudyId(STUDY_ID2); + + ClinicalData sampleClinicalData5 = new ClinicalData(); + sampleClinicalData5.setAttrId(CLINICAL_ATTRIBUTE_ID_3); + sampleClinicalData5.setAttrValue("2"); + sampleClinicalData5.setSampleId(SAMPLE_ID5); + sampleClinicalData5.setStudyId(STUDY_ID2); + + ClinicalData patientClinicalData3 = new ClinicalData(); + patientClinicalData3.setAttrId(CLINICAL_ATTRIBUTE_ID_4); + patientClinicalData3.setAttrValue("5"); + patientClinicalData3.setSampleId(SAMPLE_ID3); + patientClinicalData3.setStudyId(STUDY_ID2); + + ClinicalData patientClinicalData4 = new ClinicalData(); + patientClinicalData4.setAttrId(CLINICAL_ATTRIBUTE_ID_4); + patientClinicalData4.setAttrValue("3"); + patientClinicalData4.setSampleId(SAMPLE_ID4); + patientClinicalData4.setStudyId(STUDY_ID2); + + ClinicalData patientClinicalData5 = new ClinicalData(); + patientClinicalData5.setAttrId(CLINICAL_ATTRIBUTE_ID_4); + patientClinicalData5.setAttrValue("1"); + patientClinicalData5.setSampleId(SAMPLE_ID5); + patientClinicalData5.setStudyId(STUDY_ID2); + + when(clinicalDataService.fetchClinicalData( + Arrays.asList(STUDY_ID2, STUDY_ID2, STUDY_ID2), + Arrays.asList(SAMPLE_ID3, SAMPLE_ID4, SAMPLE_ID5), + Arrays.asList(CLINICAL_ATTRIBUTE_ID_3), + "SAMPLE", + "SUMMARY")) + .thenReturn(Arrays.asList(sampleClinicalData3, sampleClinicalData4, sampleClinicalData5)); + + when(clinicalDataService.fetchClinicalData( + Arrays.asList(STUDY_ID2, STUDY_ID2, STUDY_ID2), + Arrays.asList(PATIENT_ID3, PATIENT_ID4, PATIENT_ID5), + Arrays.asList(CLINICAL_ATTRIBUTE_ID_4), + "PATIENT", + "SUMMARY")) + .thenReturn( + Arrays.asList(patientClinicalData3, patientClinicalData4, patientClinicalData5)); + + List actualClinicalDataEnrichments = + clinicalDataEnrichmentUtil.createEnrichmentsForNumericData(attributes, groupedSamples); + + // when there is data for more than one group + Assert.assertEquals(2, actualClinicalDataEnrichments.size()); + Assert.assertEquals( + "0.7670968826920188", actualClinicalDataEnrichments.get(0).getpValue().toString()); + Assert.assertEquals( + "0.08771942638231253", actualClinicalDataEnrichments.get(0).getScore().toString()); + Assert.assertEquals("Wilcoxon Test", actualClinicalDataEnrichments.get(0).getMethod()); + } +} diff --git a/src/test/java/org/cbioportal/legacy/web/util/DataBinHelperTest.java b/src/test/java/org/cbioportal/legacy/web/util/DataBinHelperTest.java new file mode 100644 index 00000000000..b69c1d81aa8 --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/web/util/DataBinHelperTest.java @@ -0,0 +1,298 @@ +package org.cbioportal.legacy.web.util; + +import static org.junit.Assert.*; + +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.junit.MockitoJUnitRunner; + +@RunWith(MockitoJUnitRunner.class) +public class DataBinHelperTest { + + private DataBinHelper dataBinHelper; + + @Before + public void setUp() throws Exception { + dataBinHelper = new DataBinHelper(); + } + + @Test + public void rangeSmallerThanAnchor() { + List sortedNumericalValues = + Arrays.asList(new BigDecimal(-62), new BigDecimal(-38)); + List boundaries = + dataBinHelper.generateBins(sortedNumericalValues, new BigDecimal(10), new BigDecimal(0)); + assertEquals(decList(-60, -50, -40), boundaries); + } + + @Test + public void rangeLargerThanAnchor() { + List sortedNumericalValues = + Arrays.asList(new BigDecimal(-62), new BigDecimal(-38)); + List boundaries = + dataBinHelper.generateBins(sortedNumericalValues, new BigDecimal(10), new BigDecimal(-70)); + assertEquals(decList(-60, -50, -40), boundaries); + } + + @Test + public void rangeSpansAnchor() { + List sortedNumericalValues = + Arrays.asList(new BigDecimal(-62), new BigDecimal(-38)); + List boundaries = + dataBinHelper.generateBins(sortedNumericalValues, new BigDecimal(10), new BigDecimal(-20)); + assertEquals(decList(-60, -50, -40), boundaries); + } + + @Test + public void rangeSmallerThanAnchorPositiveRange() { + List sortedNumericalValues = Arrays.asList(new BigDecimal(38), new BigDecimal(62)); + List boundaries = + dataBinHelper.generateBins(sortedNumericalValues, new BigDecimal(10), new BigDecimal(100)); + assertEquals(decList(40, 50, 60), boundaries); + } + + @Test + public void rangeLargerThanAnchorPositiveRange() { + List sortedNumericalValues = Arrays.asList(new BigDecimal(38), new BigDecimal(62)); + List boundaries = + dataBinHelper.generateBins(sortedNumericalValues, new BigDecimal(10), new BigDecimal(0)); + assertEquals(decList(40, 50, 60), boundaries); + } + + @Test + public void rangeSpansAnchorPositiveRange() { + List sortedNumericalValues = Arrays.asList(new BigDecimal(38), new BigDecimal(62)); + List boundaries = + dataBinHelper.generateBins(sortedNumericalValues, new BigDecimal(10), new BigDecimal(40)); + assertEquals(decList(40, 50, 60), boundaries); + } + + @Test + public void singleValueNoBoundaries() { + List sortedNumericalValues = Arrays.asList(new BigDecimal(38)); + List boundaries = + dataBinHelper.generateBins(sortedNumericalValues, new BigDecimal(10), new BigDecimal(40)); + assertEquals(decList(), boundaries); + } + + @Test + public void emptyNumericalValues() { + List sortedNumericalValues = new ArrayList<>(); + List boundaries = + dataBinHelper.generateBins(sortedNumericalValues, new BigDecimal(10), new BigDecimal(40)); + assertNull(boundaries); + } + + @Test(expected = IllegalArgumentException.class) + public void nullCustomBinsArg() { + List boundaries = + dataBinHelper.generateBins(null, new BigDecimal(10), new BigDecimal(40)); + } + + @Test(expected = IllegalArgumentException.class) + public void nullBinSizeArg() { + List boundaries = + dataBinHelper.generateBins(Collections.emptyList(), null, new BigDecimal(40)); + } + + @Test(expected = IllegalArgumentException.class) + public void nullAnchorPointArg() { + List boundaries = + dataBinHelper.generateBins(Collections.emptyList(), new BigDecimal(10), null); + } + + @Test + public void testMedianEvenSeries() { + List values = decList(1, 2, 3, 4, 5, 6); + assertEquals(new BigDecimal("3.5"), dataBinHelper.calcMedian(values)); + } + + @Test + public void testMedianUnevenSeries() { + List values = decList(1, 2, 3, 4, 5, 6, 7); + assertEquals(new BigDecimal("4"), dataBinHelper.calcMedian(values)); + } + + @Test + public void testMedianNullSeries() { + assertNull(dataBinHelper.calcMedian(null)); + } + + @Test + public void testMedianEmptySeries() { + assertNull(dataBinHelper.calcMedian(new ArrayList<>())); + } + + @Test + public void testQ1EvenSeries() { + List values = decList(1, 2, 3, 4, 5, 6); + assertEquals(new BigDecimal("2"), dataBinHelper.calcQ1(values)); + } + + @Test + public void testQ1UnevenSeries() { + List values = decList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11); + assertEquals(new BigDecimal("3"), dataBinHelper.calcQ1(values)); + } + + @Test + public void testQ1NullSeries() { + assertNull(dataBinHelper.calcQ1(null)); + } + + @Test + public void testQ1EmptySeries() { + assertNull(dataBinHelper.calcQ1(new ArrayList<>())); + } + + @Test + public void testQ3EvenSeries() { + List values = decList(1, 2, 3, 4, 5, 6); + assertEquals(new BigDecimal("5"), dataBinHelper.calcQ3(values)); + } + + @Test + public void testQ3UnevenSeries() { + List values = decList(1, 2, 3, 4, 5, 6, 7, 8, 9); + assertEquals(new BigDecimal("7.5"), dataBinHelper.calcQ3(values)); + } + + @Test + public void testQ3NullSeries() { + assertNull(dataBinHelper.calcQ3(null)); + } + + @Test + public void testQ3EmptySeries() { + assertNull(dataBinHelper.calcQ3(new ArrayList<>())); + } + + @Test + public void testValueCloseToQ1EvenSeries() { + List values = decList(1, 2, 3, 4, 5, 6); + assertEquals(new BigDecimal("2"), dataBinHelper.valueCloseToQ1(values)); + } + + @Test + public void testValueCloseToQ1UnevenSeries() { + List values = decList(1, 2, 3, 4, 5, 6, 7, 8, 9); + assertEquals(new BigDecimal("3"), dataBinHelper.valueCloseToQ1(values)); + } + + @Test + public void testValueCloseToQ1NullSeries() { + assertNull(dataBinHelper.valueCloseToQ1(null)); + } + + @Test + public void testValueCloseToQ1EmptySeries() { + assertNull(dataBinHelper.valueCloseToQ1(new ArrayList<>())); + } + + @Test + public void testValueCloseToQ3EvenSeries() { + List values = decList(1, 2, 3, 4, 5, 6); + assertEquals(new BigDecimal("5"), dataBinHelper.valueCloseToQ3(values)); + } + + @Test + public void testValueCloseToQ3UnevenSeries() { + List values = decList(1, 2, 3, 4, 5, 6, 7, 8, 9); + assertEquals(new BigDecimal("7"), dataBinHelper.valueCloseToQ3(values)); + } + + @Test + public void testValueCloseToQ3NullSeries() { + assertNull(dataBinHelper.valueCloseToQ3(null)); + } + + @Test + public void testValueCloseToQ3EmptySeries() { + assertNull(dataBinHelper.valueCloseToQ3(new ArrayList<>())); + } + + @Test + public void testCalcQuartileBoundariesUniqueSeries() { + List values = decList(1, 2, 3, 4, 5, 6, 7, 8, 9); + final List expected = + Arrays.asList(new BigDecimal("2.5"), new BigDecimal("5"), new BigDecimal("7.5")); + final List observed = dataBinHelper.calcQuartileBoundaries(values); + assertEquals(3, observed.size()); + assertEquals(0, observed.get(0).compareTo(expected.get(0))); + assertEquals(0, observed.get(1).compareTo(expected.get(1))); + assertEquals(0, observed.get(2).compareTo(expected.get(2))); + } + + @Test + public void testCalcQuartileBoundariesIdenticalSeries() { + List values = decList(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1); + final List observed = dataBinHelper.calcQuartileBoundaries(values); + assertEquals(1, observed.size()); + assertEquals(0, observed.get(0).compareTo(new BigDecimal("1"))); + } + + @Test + public void testCalcQuartileBoundariesIdenitcalUpperValues() { + List values = decList(1, 1, 1, 10, 10, 10, 10, 10, 10); + final List expected = Arrays.asList(new BigDecimal("1"), new BigDecimal("10")); + final List observed = dataBinHelper.calcQuartileBoundaries(values); + assertEquals(2, observed.size()); + assertEquals(0, observed.get(0).compareTo(expected.get(0))); + assertEquals(0, observed.get(1).compareTo(expected.get(1))); + } + + @Test + public void testCalcQuartileBoundariesIdenticalLowerValues() { + List values = decList(1, 1, 1, 1, 1, 1, 10, 10, 10); + final List expected = Arrays.asList(new BigDecimal("1"), new BigDecimal("10")); + final List observed = dataBinHelper.calcQuartileBoundaries(values); + assertEquals(2, observed.size()); + assertEquals(0, observed.get(0).compareTo(expected.get(0))); + assertEquals(0, observed.get(1).compareTo(expected.get(1))); + } + + @Test + public void testCalcQuartileBoundariesFractions() { + List values = decList(1, 2, 3, 4, 5, 6, 7, 8); + final List expected = + Arrays.asList(new BigDecimal("2.5"), new BigDecimal("4.5"), new BigDecimal("6.5")); + final List observed = dataBinHelper.calcQuartileBoundaries(values); + assertEquals(3, observed.size()); + assertEquals(0, observed.get(0).compareTo(expected.get(0))); + assertEquals(0, observed.get(1).compareTo(expected.get(1))); + assertEquals(0, observed.get(2).compareTo(expected.get(2))); + } + + @Test + public void testCalcInterquartileRangeApproximation() { + List values = decList(1, 2, 3, 4, 5, 6, 7, 8); + assertEquals( + new BigDecimal("3"), + dataBinHelper.calcInterquartileRangeApproximation(values).lowerEndpoint()); + assertEquals( + new BigDecimal("7"), + dataBinHelper.calcInterquartileRangeApproximation(values).upperEndpoint()); + } + + @Test + public void testCalsIqrUnevenSeries() { + List values = decList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11); + assertEquals( + new BigDecimal("3"), + dataBinHelper.calcInterquartileRangeApproximation(values).lowerEndpoint()); + assertEquals( + new BigDecimal("9"), + dataBinHelper.calcInterquartileRangeApproximation(values).upperEndpoint()); + } + + private List decList(int... numbers) { + return Arrays.stream(numbers).mapToObj(BigDecimal::new).collect(Collectors.toList()); + } +} diff --git a/src/test/java/org/cbioportal/legacy/web/util/DataBinnerMocker.java b/src/test/java/org/cbioportal/legacy/web/util/DataBinnerMocker.java new file mode 100644 index 00000000000..ab31639c7d7 --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/web/util/DataBinnerMocker.java @@ -0,0 +1,5027 @@ +package org.cbioportal.legacy.web.util; + +import java.util.LinkedHashMap; +import java.util.Map; + +public class DataBinnerMocker { + public static String[] mockLlgTcgaEgfrMrnaExpression() { + return new String[] { + "1595.129", + "48018.0538", + "3437.692", + "6477.4479", + "1741.5156", + "13460.7394", + "11177.2927", + "8346.922", + "11307.9572", + "2053.8323", + "2407.9032", + "3142.0384", + "20037.5515", + "1941.092", + "246.3887", + "2058.906", + "3180.5794", + "8562.7167", + "406.9185", + "3176.2458", + "1646.0859", + "1315.7853", + "573.5632", + "2172.4302", + "909.0929", + "1715.3282", + "994.1768", + "4046.4248", + "5870.9852", + "1715.4498", + "2544.5801", + "1082.2529", + "3612.3411", + "3793.2291", + "5163.891", + "2779.8315", + "4798.5528", + "8595.3408", + "3691.3868", + "2404.6954", + "1605.1942", + "1896.3648", + "1708.6601", + "2312.4903", + "912.4779", + "1341.3809", + "298.2627", + "2369.8801", + "542.1712", + "3017.4639", + "2843.3553", + "1559.3413", + "1600.5396", + "272.3066", + "1057.6701", + "2164.1674", + "3135.4217", + "3255.799", + "2549.7433", + "439.0719", + "779.2669", + "1209.6152", + "2581.0108", + "1696.1666", + "1017.4704", + "1820.2409", + "1652.5141", + "749.0988", + "3527.0578", + "1984.7141", + "2677.8279", + "3324.9434", + "2253.6943", + "67520.2984", + "4170.5709", + "26687.9453", + "4768.3418", + "4796.9907", + "1387.0656", + "3943.5318", + "2208.8515", + "383.0421", + "5036.3581", + "686.9631", + "15924.3405", + "3552.0079", + "2055.875", + "1507.8216", + "6325.1468", + "1364.5974", + "6416.6167", + "3291.3089", + "5989.5303", + "608.8495", + "24642.1375", + "5411.2579", + "1281.8875", + "16967.2917", + "39475.42", + "7771.0797", + "796.6949", + "2039.6919", + "21371.3898", + "1976.4483", + "415.3215", + "918.6554", + "1927.237", + "10879.4681", + "1219.3912", + "3198.8016", + "6040.5081", + "58123.0115", + "3197.3913", + "6053.281", + "5277.1828", + "2097.2029", + "810.2394", + "53761.6033", + "3334.8743", + "5106.7629", + "2866.913", + "1824.7472", + "2884.7918", + "3513.623", + "2972.129", + "425.1497", + "3513.9025", + "3142.0913", + "3455.6897", + "7109.4976", + "13256.1433", + "4831.5226", + "4751.8371", + "798.4197", + "7254.7288", + "1398.641", + "9229.6049", + "766.3998", + "284.9224", + "182.2973", + "1928.9693", + "278.4596", + "2151.15", + "39468.7679", + "2615.61", + "2681.6166", + "3191.8478", + "3059.6264", + "1309.6316", + "1493.7806", + "266.6225", + "970.1622", + "2684.6404", + "102.694", + "2169.9941", + "2767.6048", + "112.5551", + "1665.1758", + "120100.1081", + "825.7799", + "4248.3087", + "97394.7678", + "4129.3862", + "3470.382", + "3781.814", + "6926.0121", + "9947.1648", + "6957.2582", + "3427.8838", + "1931.2811", + "2436.8419", + "19363.0054", + "1783.8799", + "2576.6848", + "136.2785", + "57650.0135", + "457.1072", + "4192.5058", + "2511.4677", + "3003.2325", + "7116.2686", + "26504.4646", + "10766.4927", + "820.0048", + "1854.6958", + "2388.3726", + "417.2197", + "7159.7662", + "893.6034", + "1976.0762", + "1972.6717", + "6090.1321", + "4028.8229", + "2704.4703", + "3169.1905", + "91.2137", + "75.1845", + "980.3235", + "3782.7217", + "298.9544", + "19100.4381", + "2250.4807", + "6332.8925", + "6115.4945", + "14585.9036", + "4830.1418", + "1123.7056", + "16873.5013", + "1483.9419", + "5034.61", + "1841.541", + "256.0762", + "11214.4757", + "1620.0691", + "4150.8707", + "2193.2075", + "1763.4537", + "419.959", + "2500.1672", + "3302.3125", + "2535.5963", + "22441.0435", + "42612.6826", + "467.8715", + "582.8169", + "3373.6407", + "1966.7365", + "201.2209", + "479.4773", + "263.0847", + "133.209", + "1417.4623", + "12313.5206", + "1303.1226", + "994.2851", + "1184.9418", + "443.4924", + "36523.6821", + "2732.9228", + "2429.1549", + "4647.7356", + "6209.6857", + "1951.9647", + "5611.7741", + "3303.4658", + "2625.1342", + "1213.5133", + "4223.7696", + "1330.0248", + "1584.8648", + "1668.694", + "1349.731", + "3811.7828", + "4678.0751", + "1311.5177", + "3316.1825", + "3177.1293", + "1871.0737", + "552.6869", + "305.8077", + "4780.2604", + "2004.5577", + "12044.7377", + "658.9125", + "2709.9522", + "3408.1556", + "5740.3759", + "3813.2041", + "5553.7882", + "3326.607", + "1796.2905", + "6202.7418", + "1272.4993", + "1042.1114", + "990.4553", + "2612.0512", + "4520.9376", + "2659.1844", + "3140.7455", + "1318.4392", + "736.0256", + "2807.0548", + "2044.3785", + "1671.0804", + "3881.0975", + "7106.5649", + "4246.6383", + "1995.8207", + "49.9696", + "2796.1934", + "3339.3048", + "3539.3851", + "2095.8345", + "3372.8073", + "3683.6014", + "2121.6346", + "867.9918", + "720.9516", + "1440.4553", + "2802.5548", + "526.7418", + "1560.7613", + "20832.7859", + "2939.9563", + "2456.5744", + "343.7569", + "1114.6895", + "416.8189", + "114753.4672", + "2761.442", + "811.6049", + "1013.5709", + "3575.4572", + "3821.6112", + "13699.2792", + "1254.2185", + "1168.0268", + "5150.7806", + "245.856", + "995.2557", + "6015.0293", + "824.543", + "372", + "1488.9533", + "819.1502", + "4533.6119", + "24851.8993", + "3635.1582", + "58640.3236", + "475.5196", + "1892.2317", + "719.163", + "1615.3052", + "1086.7384", + "2490.5354", + "507.2134", + "259.7691", + "52.2087", + "448.3394", + "2417.9143", + "280.9917", + "11783.2103", + "324.9265", + "4471.1869", + "2453.3529", + "1372.2101", + "1467.8857", + "8146.1099", + "2882.0948", + "2080.5641", + "5946.1443", + "4325.7493", + "4246.5895", + "3809.2436", + "907.996", + "7143.4334", + "2856.7434", + "2099.8824", + "2709.4055", + "3816.9427", + "1699.5064", + "30132.0994", + "1859.664", + "4442.5386", + "2332.0974", + "3960.6705", + "1015.2504", + "647.4439", + "805.4919", + "4163.4606", + "473.0383", + "2469.8218", + "1556.1948", + "495.163", + "1149.1633", + "881.0127", + "1683.9574", + "1003.842", + "2298.4648", + "1151.2472", + "1304.8862", + "1834.8772", + "775.7309", + "5312.2811", + "660.3573", + "2085.9339", + "1376.2412", + "2498.3387", + "2018.2214", + "1071.5728", + "335.2354", + "779.0032", + "1085.2514", + "2691.9735", + "191.9866", + "30874.6345", + "4062.0536", + "13925.807", + "1014.655", + "3905.8749", + "3567.5971", + "2508.1243", + "828.8561", + "2104.1548", + "4205.7234", + "1759.3226", + "7544.4579", + "3394.6495", + "1603.9427", + "2068.5634", + "2627.9717", + "1051.8096", + "3124.0589", + "308.6282", + "1336.6126", + "1057.2254", + "214.7786", + "1760.2839", + "2701.5361", + "2271.6354", + "3149.642", + "793.6111", + "2661.6201", + "616.6699", + "1857.6189", + "3488.6071", + "4242.3761", + "8530.7567", + "32086.4878", + "3678.2463", + "4006.0388", + "717.6878", + "4510.9337", + "1968.7362", + "1475.9277", + "65.0234", + "3797.6543", + "2847.9425", + "1087.3385", + "728.8605", + "2483.855", + "574.1635", + "2749.6573", + "66389.9281", + "622.3727", + "3258.2696", + "2683.672", + "1901.3088", + "746.079", + "108.8768", + "15402.264", + "1837.1375", + "1244.2204", + "864.4824", + "2439.6576", + "5305.9453", + "2850.4222", + "1875.0232", + "2226.2051", + "2280.2934", + "3237.7925", + "6568.1474", + "948.5354", + "2179.3249", + "2442.9566", + "906.3434", + "7836.3441", + "2456.7012", + "538.2632", + "9863.1949", + "807.7762", + "2044.9539", + "3132.8012", + "3293.1948", + "1179.1579", + "4589.1975", + "596.0091", + "427.0647", + "2583.4862", + "4788.0667", + "3672.8544", + "89.6955", + "1444.2876", + "7531.4439", + "479.1792", + "2731.6058", + "1202.9413", + "2436.7675", + "3648.5118", + "2112.2789", + "1873.3046", + "3876.3096", + "5121.5519", + "3284.6448", + "839.5793", + "3335.0197", + "2033.6549", + "8783.3993", + "3631.1041", + "2062.2503", + "6136.7042", + "1917.5233", + "1931.35", + "1270.3671", + "2324.2768", + "1522.9278", + "3912.1404", + "3212.9795", + "1886.745", + "1194.3191", + "101.2416", + "424.8174", + "1913.9235", + "3353.0053", + "1080.4484", + "100.4532", + "3588.2683", + "6681.2974", + "1318.0469", + "3133.8665", + "17710.3456", + "4170.7148", + "880.9435", + "615.9762", + "610.8738", + "1238.2423", + "2535.2496", + "3311.2383", + "500.9714", + "805.6522" + }; + } + + public static String[] mockBlcaTcgaAge() { + return new String[] { + "34.0", "37.0", "41.0", "42.0", "43.0", "44.0", "45.0", "45.0", "46.0", "47.0", "47.0", + "47.0", "47.0", "48.0", "48.0", "48.0", "48.0", "48.0", "48.0", "49.0", "49.0", + "49.0", "50.0", "50.0", "50.0", "51.0", "52.0", "52.0", "52.0", "52.0", "52.0", "52.0", + "53.0", "53.0", "53.0", "53.0", "54.0", "54.0", "54.0", "54.0", "54.0", "54.0", + "54.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "56.0", "56.0", "56.0", "56.0", + "56.0", "56.0", "56.0", "56.0", "56.0", "57.0", "57.0", "57.0", "57.0", "57.0", + "57.0", "57.0", "57.0", "57.0", "57.0", "58.0", "58.0", "58.0", "58.0", "58.0", "58.0", + "59.0", "59.0", "59.0", "59.0", "59.0", "59.0", "59.0", "59.0", "59.0", "59.0", + "59.0", "59.0", "59.0", "59.0", "60.0", "60.0", "60.0", "60.0", "60.0", "60.0", "60.0", + "60.0", "60.0", "60.0", "60.0", "60.0", "60.0", "60.0", "60.0", "60.0", "60.0", + "60.0", "60.0", "60.0", "61.0", "61.0", "61.0", "61.0", "61.0", "61.0", "61.0", "61.0", + "61.0", "61.0", "61.0", "61.0", "62.0", "62.0", "62.0", "62.0", "62.0", "62.0", + "62.0", "62.0", "63.0", "63.0", "63.0", "63.0", "63.0", "63.0", "63.0", "63.0", "63.0", + "64.0", "64.0", "64.0", "64.0", "64.0", "64.0", "64.0", "64.0", "64.0", "64.0", + "64.0", "64.0", "64.0", "65.0", "65.0", "65.0", "65.0", "65.0", "65.0", "65.0", "65.0", + "65.0", "65.0", "65.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "67.0", + "67.0", "67.0", "67.0", "67.0", "67.0", "67.0", "67.0", "67.0", "67.0", "67.0", + "67.0", "67.0", "68.0", "68.0", "68.0", "68.0", "68.0", "68.0", "68.0", "68.0", "68.0", + "68.0", "68.0", "68.0", "69.0", "69.0", "69.0", "69.0", "69.0", "69.0", "69.0", + "69.0", "69.0", "69.0", "69.0", "69.0", "69.0", "70.0", "70.0", "70.0", "70.0", "70.0", + "70.0", "70.0", "70.0", "70.0", "70.0", "70.0", "70.0", "70.0", "70.0", "70.0", + "70.0", "71.0", "71.0", "71.0", "71.0", "71.0", "71.0", "71.0", "71.0", "72.0", "72.0", + "72.0", "72.0", "72.0", "72.0", "72.0", "72.0", "72.0", "72.0", "73.0", "73.0", + "73.0", "73.0", "73.0", "73.0", "73.0", "73.0", "73.0", "73.0", "73.0", "73.0", "73.0", + "73.0", "73.0", "73.0", "74.0", "74.0", "74.0", "74.0", "74.0", "74.0", "74.0", + "74.0", "74.0", "74.0", "74.0", "74.0", "75.0", "75.0", "75.0", "75.0", "75.0", "75.0", + "75.0", "75.0", "75.0", "75.0", "75.0", "75.0", "75.0", "75.0", "75.0", "75.0", + "75.0", "75.0", "75.0", "75.0", "75.0", "76.0", "76.0", "76.0", "76.0", "76.0", "76.0", + "76.0", "76.0", "76.0", "76.0", "76.0", "76.0", "76.0", "76.0", "76.0", "77.0", + "77.0", "77.0", "77.0", "77.0", "77.0", "77.0", "77.0", "77.0", "77.0", "77.0", "77.0", + "78.0", "78.0", "78.0", "78.0", "78.0", "78.0", "78.0", "78.0", "78.0", "78.0", + "78.0", "78.0", "79.0", "79.0", "79.0", "79.0", "79.0", "79.0", "79.0", "79.0", "79.0", + "79.0", "79.0", "79.0", "79.0", "80.0", "80.0", "80.0", "80.0", "80.0", "80.0", + "80.0", "80.0", "80.0", "80.0", "80.0", "80.0", "81.0", "81.0", "81.0", "81.0", "81.0", + "81.0", "81.0", "81.0", "82.0", "82.0", "82.0", "82.0", "82.0", "82.0", "82.0", + "82.0", "83.0", "83.0", "83.0", "83.0", "83.0", "83.0", "83.0", "84.0", "84.0", "84.0", + "84.0", "84.0", "84.0", "84.0", "85.0", "85.0", "85.0", "85.0", "85.0", "86.0", + "86.0", "86.0", "87.0", "87.0", "87.0", "87.0", "87.0", "88.0", "89.0", "90.0", "90.0", "90.0" + }; + } + + public static String[] mockSkcmBroadAgeAtProcurement() { + return new String[] { + "72.0", "22.0", "55.0", "57.0", "70.0", "21.0", "67.0", "42.0", "26.0", "54.0", "39.0", + "67.0", "46.0", "52.0", "47.0", "53.0", "51.0", "35.0", "53.0", "46.0", "42.0", + "31.0", "83.0", "29.0", "52.0", "47.0", "41.0", "35.0", "45.0", "40.0", "50.0", "37.0", + "54.0", "71.0", "49.0", "49.0", "56.0", "74.0", "48.0", "48.0", "76.0", "35.0", + "67.0", "74.0", "63.0", "47.0", "67.0", "39.0", "31.0", "62.0", "58.0", "65.0", "72.0", + "27.0", "59.0", "87.0", "69.0", "41.0", "39.0", "53.0", "17.0", "44.0", "76.0", + "51.0", "46.0", "63.0", "41.0", "38.0", "34.0", "69.0", "63.0", "65.0", "59.0", "58.0", + "60.0", "56.0", "65.0", "26.0", "58.0", "48.0", "65.0", "44.0", "45.0", "28.0", + "46.0", "48.0", "52.0", "52.0", "70.0", "57.0", "63.0", "68.0", "45.0", "51.0", "39.0", + "79.0", "53.0", "41.0", "47.0", "39.0", "49.0", "42.0", "37.0", "78.0", "69.0", + "33.0", "71.0", "80.0", "49.0", "65.0", "67.0", "70.0", "46.0", "49.0", "63.0", "28.0", + "62.0", "27.0", "51.0" + }; + } + + public static String[] mockBlcaTcgaLymphNodeExaminedCount() { + return new String[] { + "170.0", "141.0", "140.0", "112.0", "111.0", "108.0", "107.0", "104.0", "93.0", "87.0", + "86.0", "85.0", "83.0", "79.0", "77.0", "77.0", "76.0", "75.0", "74.0", "73.0", "73.0", + "71.0", "71.0", "70.0", "69.0", "68.0", "67.0", "66.0", "65.0", "64.0", "64.0", "62.0", + "61.0", "61.0", "60.0", "58.0", "58.0", "57.0", "54.0", "54.0", "53.0", "53.0", "52.0", + "51.0", "48.0", "48.0", "48.0", "47.0", "47.0", "47.0", "47.0", "46.0", "46.0", "45.0", + "45.0", "44.0", "43.0", "41.0", "41.0", "41.0", "41.0", "40.0", "40.0", "40.0", "38.0", + "38.0", "38.0", "37.0", "37.0", "36.0", "36.0", "36.0", "35.0", "34.0", "34.0", "34.0", + "34.0", "33.0", "31.0", "31.0", "30.0", "30.0", "30.0", "30.0", "30.0", "29.0", "29.0", + "29.0", "28.0", "28.0", "28.0", "28.0", "28.0", "28.0", "28.0", "28.0", "28.0", "28.0", + "27.0", "27.0", "27.0", "27.0", "27.0", "27.0", "27.0", "27.0", "27.0", "27.0", "26.0", + "26.0", "26.0", "26.0", "25.0", "25.0", "25.0", "25.0", "25.0", "24.0", "24.0", "24.0", + "24.0", "24.0", "24.0", "23.0", "23.0", "23.0", "23.0", "23.0", "22.0", "22.0", "22.0", + "22.0", "21.0", "21.0", "21.0", "21.0", "21.0", "21.0", "20.0", "20.0", "20.0", "20.0", + "19.0", "19.0", "19.0", "19.0", "19.0", "19.0", "19.0", "19.0", "18.0", "18.0", "18.0", + "18.0", "18.0", "18.0", "18.0", "18.0", "18.0", "17.0", "17.0", "17.0", "17.0", "17.0", + "17.0", "17.0", "16.0", "16.0", "16.0", "16.0", "16.0", "16.0", "16.0", "16.0", "16.0", + "16.0", "16.0", "15.0", "15.0", "15.0", "15.0", "15.0", "15.0", "15.0", "15.0", "14.0", + "14.0", "14.0", "14.0", "14.0", "14.0", "14.0", "14.0", "14.0", "14.0", "14.0", "14.0", + "14.0", "14.0", "14.0", "14.0", "14.0", "14.0", "14.0", "13.0", "13.0", "13.0", "13.0", + "13.0", "13.0", "13.0", "13.0", "12.0", "12.0", "12.0", "12.0", "12.0", "12.0", "12.0", + "12.0", "12.0", "11.0", "11.0", "11.0", "11.0", "11.0", "11.0", "11.0", "11.0", "11.0", + "11.0", "11.0", "10.0", "10.0", "10.0", "10.0", "10.0", "9.0", "9.0", "9.0", "9.0", "9.0", + "8.0", "8.0", "8.0", "8.0", "8.0", "8.0", "8.0", "8.0", "8.0", "8.0", "8.0", "8.0", "8.0", + "8.0", "8.0", "7.0", "7.0", "7.0", "7.0", "7.0", "7.0", "7.0", "7.0", "6.0", "6.0", "6.0", + "6.0", "6.0", "6.0", "6.0", "6.0", "5.0", "5.0", "5.0", "5.0", "5.0", "5.0", "5.0", "5.0", + "5.0", "4.0", "4.0", "4.0", "4.0", "4.0", "3.0", "3.0", "3.0", "2.0", "2.0", "2.0", "2.0", + "2.0", "2.0", "2.0", "2.0", "2.0", "2.0", "2.0", "1.0", "0.0", "NA", "NA", "NA", "NA", "NA", + "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", + "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", + "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", + "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", + "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", + "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", + "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA" + }; + } + + public static String[] mockAcycFmi2014ActionableAlterations() { + return new String[] { + "1.0", "0.0", "0.0", "2.0", "2.0", "2.0", "1.0", "0.0", "0.0", "1.0", "0.0", "0.0", "0.0", + "5.0", + "0.0", "0.0", "1.0", "0.0", "2.0", "0.0", "3.0", "0.0", "0.0", "0.0", "1.0", "0.0", "0.0", + "1.0" + }; + } + + public static String[] mockBlcaDfarberMskcc2014SilentRate() { + return new String[] { + "2.87E-06", "1.92E-06", "1.32E-06", "1.78E-06", "4.93E-06", "3.01E-06", "3.07E-06", + "3.67E-06", "1.00E-06", + "1.61E-06", "3.05E-08", "3.73E-06", "2.44E-06", "6.03E-07", "1.03E-06", "1.29E-06", + "1.00E-06", "7.35E-06", + "1.53E-06", "1.64E-06", "6.41E-07", "7.46E-07", "2.99E-06", "5.95E-07", "1.06E-05", + "6.87E-07", "5.74E-07", + "3.73E-06", "1.22E-06", "5.89E-06", "5.22E-06", "2.55E-06", "5.95E-07", "4.43E-07", + "2.87E-06", "1.68E-07", + "2.47E-06", "9.10E-06", "9.62E-07", "1.23E-06", "9.77E-07", "1.21E-06", "3.67E-06", + "1.06E-06", "4.19E-06", + "1.61E-06", "6.60E-07", "8.04E-07", "5.45E-07", "2.04E-06", "NA", "NAN", "N/A" + }; + } + + public static String[] mockAccTcgaDaysToBirth() { + return new String[] { + "-21496", "-16090", "-8624", "-8451", "-11171", "-10839", "-11279", "-24266", "-8175", + "-19436", "-19172", "-13862", + "-20989", "-6455", "-25502", "-22390", "-11994", "-8177", "-24082", "-18214", "-13155", + "-9359", "-9547", "-14667", + "-9667", "-16604", "-24017", "-23794", "-21292", "-20319", "-17513", "-18402", "-25190", + "-22218", "-25400", "-17596", + "-11970", "-19375", "-23481", "-21907", "-20657", "-14435", "-22596", "-22550", "-14606", + "-16702", "-7459", "-26404", + "-16217", "-13559", "-6250", "-20328", "-9298", "-8745", "-15594", "-13840", "-30535", + "-24763", "-17819", "-28270", + "-22057", "-13472", "-19526", "-19242", "-21565", "-26084", "-19111", "-5383", "-27179", + "-16875", "-13182", "-15536", + "-20069", "-22919", "-27607", "-8735", "-11414", "-22370", "-13574", "-11261", "-12663", + "-21032", "-19492", "-20106", + "-16659", "-21627", "-18926", "-15373", "-10173", "-23345", "-23293", "-16182" + }; + } + + public static String[] mockAmpcaBcm2016DaysToLastFollowup() { + return new String[] { + "3411.0", "2798.0", "822.0", "523.0", "1293.0", "836.0", "2695.0", "1796.0", "1734.0", + "979.0", "1813.0", "141.0", "341.0", "1021.0", "55.0", "832.0", "579.0", "726.0", "665.0", + "2746.0", "1830.0", "481.0", "2380.0", "1210.0", "1921.0", "765.0", "1870.0", "2159.0", + "1746.0", "2164.0", "537.0", "1520.0", "250.0", "1860.0", "363.0", "733.0", "251.0", "290.0", + "453.0", "230.0", "2074.0", "762.0", "192.0", "1498.0", "172.0", "1100.0", "1259.0", "5768.0", + "18.0", "842.0", "4810.0", "3239.0", "3634.0", "2703.0", "2191.0", "305.0", "253.0", "1528.0", + "742.0", "1260.0", "1331.0", "1148.0", "307.0", "1217.0", "1155.0", "994.0", "736.0", + "1056.0", "952.0", "531.0", "636.0", "901.0", "557.0", "898.0", "240.0", "377.0", "802.0", + "919.0", "821.0", "835.0", "556.0", "526.0", "261.0", "562.0", "598.0", "243.0", "383.0", + "257.0", "341.0", "886.0", "364.0", "2441.0", "1756.0", "1058.0", "215.0", "2134.0", "283.0", + "2978.0", "3154.0", "2992.0", "494.0", "2968.0", "2297.0", "398.0", "2211.0", "2208.0", + "2065.0", "2484.0", "484.0", "13.0", "471.0", "125.0", "2296.0", "477.0", "838.0", "460.0", + "457.0", "18.0", "34.0", "937.0", "2267.0", "755.0", "3270.0", "1267.0", "179.0", "1438.0", + "1899.0", "59.0", "1581.0", "1323.0", "1067.0", "178.0", "482.0", "824.0", "853.0", "876.0", + "663.0", "708.0", "711.0", "556.0", "638.0", "1330.0", "557.0", "180.0", "524.0", "158.0", + "380.0", "272.0", "64.0", "2555.0", "10.0", "374.0", "699.0", "1446.0", "578.0", "97.0", + "233.0", "879.0", "448.0", "651.0" + }; + } + + public static String[] mockGenieIntDod() { + return new String[] { + "23430.0", "20626.0", "26382.0", "22846.0", "21047.0", "28146.0", "24064.0", "26000.0", + "22121.0", "16563.0", "26681.0", "20242.0", "29721.0", + "14095.0", "15632.0", "27135.0", "18821.0", "16191.0", "18587.0", "15939.0", "17558.0", + "17165.0", "16308.0", "23305.0", "17557.0", "15944.0", + "24774.0", "18682.0", "21975.0", "24104.0", "26567.0", "18647.0", "22493.0", "16119.0", + "24928.0", "29142.0", "<6570.0", "24263.0", "25236.0", + "26013.0", "22960.0", "25002.0", "20883.0", "19673.0", "20122.0", "25160.0", "15665.0", + "21131.0", "26712.0", "15645.0", "11500.0", "20010.0", + "22355.0", "15527.0", "19600.0", "18939.0", "6978.0", "16933.0", "30367.0", "29048.0", + "30681.0", "21099.0", "21270.0", "16049.0", "24460.0", + "<6570.0", "15319.0", "24884.0", "20317.0", "21380.0", "24561.0", "23929.0", "22852.0", + "27210.0", "22676.0", "25305.0", "28152.0", "25298.0", + "13225.0", "17393.0", "18210.0", "24940.0", "21419.0", "20655.0", "25118.0", "20101.0", + "9833.0", "22682.0", "30282.0", "23775.0", "25193.0", + "26762.0", "15799.0", "19930.0", "23248.0", "13809.0", "29925.0", "27053.0", "15988.0", + "13564.0", "13852.0", "26865.0", "21416.0", "26658.0", + "24606.0", "15218.0", "26446.0", "18709.0", "18072.0", "16544.0", "19759.0", "19167.0", + "12031.0", "19599.0", "23655.0", "12525.0", "21453.0", + "16980.0", "23281.0", "19334.0", "20892.0", "26093.0", "22556.0", "22486.0", "23259.0", + "14767.0", "13641.0", "21637.0", "22616.0", "20408.0", + "14053.0", "22819.0", "24263.0", "22374.0", "27943.0", "27309.0", "16908.0", "18628.0", + "28846.0", "26717.0", "21335.0", "<6570.0", "21923.0", + "29328.0", "25110.0", "23146.0", "26304.0", "<6570.0", "25274.0", "27153.0", "30866.0", + "26967.0", "24853.0", "22795.0", "28955.0", "21310.0", + "25252.0", "16858.0", "22786.0", "29486.0", "22203.0", "19297.0", "29743.0", "25013.0", + "22353.0", "18059.0", "29596.0", "20594.0", "18610.0", + "17528.0", "21178.0", ">32485.0", "21017.0", "30818.0", "22339.0", "19296.0", "26786.0", + "25080.0", "24084.0", "27952.0", "20470.0", "17844.0", + "22822.0", "16961.0", "14125.0", "23770.0", "24414.0", "26299.0", "21986.0", "27407.0", + "23680.0", "19727.0", "24865.0", "29221.0", "13220.0", + "22555.0", "26048.0", "21493.0", "23526.0", "26777.0", "25309.0", "20682.0", "25890.0", + "23272.0", "21223.0", "17726.0", "25912.0", "27609.0", + "22550.0", "20890.0", "19001.0", "16571.0", "17405.0", "18575.0", "10678.0", "16191.0", + "20917.0", "24290.0", "25864.0", "11642.0", "28227.0", + "24645.0", "17803.0", "13517.0", "24497.0", "22063.0", "18565.0", "11785.0", "20367.0", + "21461.0", "10392.0", "22530.0", "19479.0", "23656.0", + "21495.0", "19372.0", "13877.0", "19928.0", "20102.0", "27975.0", "19541.0", "22792.0", + "19786.0", "30469.0", "25289.0", "22136.0", "11122.0", + "20219.0", "25452.0", "20915.0", "25745.0", "17041.0", "19595.0", "15223.0", "18638.0", + "23342.0", "20678.0", "20718.0", "19683.0", "26022.0", + "19910.0", "18233.0", "26086.0", "18665.0", "28321.0", "25498.0", "22040.0", "27769.0", + "23533.0", "18339.0", "17194.0", "25384.0", "30319.0", + "21446.0", "23633.0", "21796.0", "19476.0", "22742.0", "28036.0", "26086.0", "20807.0", + "18721.0", "25613.0", "26494.0", "21110.0", "22571.0", + "18262.0", "21674.0", "19526.0", "21009.0", "20047.0", "24120.0", "14753.0", "14379.0", + "26269.0", "16151.0", "23213.0", "15963.0", "17769.0", + "19871.0", "20623.0", "28343.0", "24467.0", "20843.0", "18267.0", "17283.0", "18663.0", + "27337.0", "23793.0", "24626.0", "20263.0", "24851.0", + "20607.0", "27255.0", "19622.0", "18364.0", "23325.0", "21598.0", "21830.0", "19791.0", + "22359.0", "28918.0", "24964.0", "24712.0", "25695.0", + "24982.0", "24476.0", "21297.0", "23132.0", "29450.0", ">32485.0", "24645.0", "25740.0", + "25643.0", "21793.0", "21510.0", "28954.0", "22882.0", + "29243.0", "24350.0", "23305.0", "21916.0", "12419.0", "26817.0", "27859.0", "17712.0", + "25946.0", "24971.0", "24738.0", "29361.0", "23313.0", + "22699.0", "11141.0", "19395.0", ">32485.0", "27336.0", "20452.0", "18893.0", "19431.0", + "20232.0", "25199.0", "24556.0", "23656.0", "24029.0", + "26476.0", "27039.0", "21082.0", "31789.0", "26925.0", "27604.0", "22296.0", "24333.0", + "7436.0", "13978.0", "20030.0", "29698.0", "28463.0", + "25555.0", "28039.0", "27229.0", "25463.0", "22442.0", "20347.0", "23507.0", "24525.0", + "27257.0", "24588.0", "20595.0", "21284.0", "30495.0", + "18203.0", "24034.0", "24221.0", "30494.0", "18502.0", "29325.0", "26391.0", "23484.0", + "20253.0", "16882.0", "26690.0", "18580.0", "16333.0", + "24449.0", "22478.0", "30009.0", "8687.0", "24291.0", "22268.0", "24897.0", "29726.0", + "21457.0", "19454.0", "18957.0", "19353.0", "17397.0", + "20636.0", "25080.0", "20236.0", "25866.0", "20577.0", "23954.0", "29294.0", "24174.0", + "<6570.0", "31901.0", "21034.0", "18472.0", "24370.0", + "26699.0", "18692.0", "22945.0", "26790.0", "21859.0", "24329.0", "21261.0", "22805.0", + "22207.0", "23733.0", "19847.0", "10273.0", "20359.0", + "21887.0", "23688.0", "12778.0", "26623.0", "29125.0", "18896.0", "24605.0", "28058.0", + "22613.0", "16694.0", "19314.0", "25586.0", "20084.0", + "18243.0", "25814.0", "21583.0", "28624.0", "26263.0", "26953.0", "24557.0", "25218.0", + "24934.0", "24035.0", "18815.0", "26319.0", "27207.0", + "23720.0", "24956.0", "20929.0", "27004.0", "12603.0", "24076.0", "23502.0", "19296.0", + "24310.0", "21241.0", "22137.0", "21417.0", "20812.0", + "23619.0", "19015.0", "12335.0", "26523.0", "19006.0", "20726.0", "25090.0", "25741.0", + "24294.0", "23722.0", "17631.0", "24564.0", "19322.0", + "27479.0", "12074.0", "25989.0", "13103.0", "19320.0", "25805.0", "16605.0", "23144.0", + "30034.0", "17495.0", "25825.0", "23235.0", "20526.0", + "12873.0", "21686.0", "24709.0", "25846.0", "32082.0", "19560.0", "26719.0", "18777.0", + "7996.0", ">32485.0", "29426.0", "24305.0", "21846.0", + "23945.0", "21657.0", "25406.0", "23025.0", "24511.0", "25225.0", "17914.0", "19843.0", + "24706.0", "18450.0", "22279.0", "13769.0", "22013.0", + "21477.0", "<6570.0", "26247.0", "23267.0", "25199.0", "17112.0", "31005.0", "23667.0", + "31420.0", "26845.0", "24904.0", "15040.0", "25611.0", + "25017.0", "14263.0", "22504.0", "24721.0", "25565.0", "28169.0", "26427.0", "25611.0", + "25847.0", "23696.0", "29716.0", "27579.0", "21461.0", + "22068.0", "24770.0", "28967.0", "23250.0", "16449.0", "18861.0", "20128.0", "21325.0", + "22184.0", "23149.0", "17824.0", "20979.0", "29378.0", + "18391.0", "23439.0", "21328.0", "<6570.0", "25384.0", "26367.0", "29021.0", "21594.0", + "18820.0", "27295.0", "26249.0", "26114.0", "28002.0", + "23897.0", "23328.0", "28254.0", "25724.0", "23916.0", "18359.0", "22835.0", "22542.0", + "27070.0", "19481.0", "29256.0", "28102.0", "25490.0", + "28398.0", "18956.0", "25194.0", "16696.0", "22980.0", "24545.0", "25902.0", "26109.0", + "29515.0", "14913.0", "28424.0", "28605.0", "16032.0", + "19904.0", "23743.0", "22746.0", "24784.0", "22553.0", "18258.0", "<6570.0", "28742.0", + "22768.0", "27165.0", "20843.0", "18681.0", "27266.0", + "20242.0", "22755.0", "24670.0", "21855.0", "18337.0", "16406.0", "25616.0", "21533.0", + "19252.0", "26687.0", "23866.0", "24171.0", "19421.0", + "16188.0", "24918.0", "19701.0", "26537.0", "19468.0", "25982.0", "16533.0", "30732.0", + "20378.0", "17068.0", "23774.0", "17836.0", "25671.0", + "25171.0", ">32485.0", "28743.0", "21715.0", "10262.0", "21629.0", "19514.0", "22744.0", + "21809.0", "17726.0", "13429.0", "23670.0", "17849.0", + "31656.0", "26519.0", "21302.0", "22221.0", "25532.0", "20554.0", "25526.0", "26438.0", + "17007.0", "28105.0", "23624.0", "28299.0", "25970.0", + "25049.0", "16754.0", "21539.0", "31633.0" + }; + } + + public static String[] mockCrcMsk2018MsiScore() { + return new String[] { + "0.0", "0.0", "0.0", "0.0", "0.0", "0.0", "0.0", "0.0", "0.0", "0.0", "0.0", "0.0", "0.0", + "0.0", "0.0", "0.0", "0.0", "0.0", "0.0", "0.0", "0.0", "0.0", "0.0", "0.0", "0.0", "0.0", + "0.0", "0.0", "0.0", "0.0", "0.0", "0.0", "0.0", "0.0", "0.0", "0.0", "0.0", "0.0", "0.0", + "0.0", "0.0", "0.0", "0.0", "0.0", "0.0", "0.0", "0.0", "0.0", "0.0", "0.0", "0.0", "0.0", + "0.0", "0.0", "0.0", "0.0", "0.0", "0.0", "0.0", "0.0", "0.0", "0.0", "0.0", "0.0", "0.0", + "0.0", "0.0", "0.0", "0.0", "0.0", "0.0", "0.0", "0.0", "0.0", "0.0", "0.0", "0.0", "0.0", + "0.0", "0.0", "0.0", "0.0", "0.0", "0.0", "0.0", "0.0", "0.0", "0.0", "0.0", "0.0", "0.0", + "0.0", "0.0", "0.0", "0.0", "0.0", "0.0", "0.0", "0.0", "0.0", "0.0", "0.0", "0.0", "0.0", + "0.0", "0.0", "0.0", "0.0", "0.0", "0.0", "0.0", "0.0", "0.0", "0.0", "0.0", "0.0", "0.0", + "0.0", "0.0", "0.0", "0.0", "0.0", "0.0", "0.0", "0.0", "0.0", "0.0", "0.0", "0.0", "0.0", + "0.0", "0.0", "0.0", "0.0", "0.0", "0.0", "0.0", "0.0", "0.0", "0.0", "0.0", "0.0", "0.0", + "0.0", "0.0", "0.0", "0.06", "0.07", "0.07", "0.07", "0.07", "0.07", "0.07", "0.07", "0.07", + "0.07", "0.07", "0.07", "0.07", "0.07", "0.07", "0.07", "0.07", "0.07", "0.07", "0.07", + "0.07", "0.07", "0.08", "0.08", "0.08", "0.08", "0.08", "0.08", "0.08", "0.08", "0.08", + "0.08", "0.08", "0.08", "0.08", "0.08", "0.08", "0.08", "0.08", "0.08", "0.08", "0.08", + "0.08", "0.08", "0.08", "0.08", "0.08", "0.08", "0.08", "0.08", "0.08", "0.08", "0.08", + "0.08", "0.08", "0.08", "0.08", "0.08", "0.08", "0.08", "0.08", "0.08", "0.08", "0.09", + "0.09", "0.09", "0.09", "0.09", "0.09", "0.09", "0.09", "0.09", "0.09", "0.09", "0.09", + "0.09", "0.09", "0.09", "0.09", "0.09", "0.09", "0.09", "0.09", "0.09", "0.09", "0.09", + "0.09", "0.09", "0.09", "0.09", "0.09", "0.1", "0.1", "0.1", "0.1", "0.1", "0.1", "0.1", + "0.11", "0.11", "0.11", "0.12", "0.12", "0.12", "0.13", "0.13", "0.14", "0.14", "0.14", + "0.14", "0.14", "0.14", "0.14", "0.15", "0.15", "0.15", "0.15", "0.15", "0.15", "0.15", + "0.15", "0.15", "0.15", "0.15", "0.15", "0.15", "0.15", "0.15", "0.15", "0.15", "0.15", + "0.15", "0.15", "0.15", "0.16", "0.16", "0.16", "0.16", "0.16", "0.16", "0.16", "0.16", + "0.16", "0.16", "0.16", "0.16", "0.16", "0.16", "0.16", "0.16", "0.17", "0.17", "0.17", + "0.17", "0.17", "0.17", "0.17", "0.17", "0.17", "0.17", "0.17", "0.17", "0.17", "0.17", + "0.17", "0.17", "0.18", "0.18", "0.18", "0.18", "0.18", "0.18", "0.18", "0.18", "0.18", + "0.18", "0.18", "0.19", "0.19", "0.19", "0.19", "0.19", "0.19", "0.19", "0.19", "0.2", "0.2", + "0.2", "0.2", "0.21", "0.21", "0.22", "0.22", "0.22", "0.22", "0.22", "0.22", "0.22", "0.22", + "0.23", "0.23", "0.23", "0.23", "0.24", "0.24", "0.24", "0.24", "0.24", "0.24", "0.24", + "0.24", "0.24", "0.24", "0.25", "0.25", "0.25", "0.25", "0.25", "0.25", "0.25", "0.26", + "0.26", "0.26", "0.26", "0.26", "0.26", "0.26", "0.26", "0.26", "0.26", "0.27", "0.27", + "0.27", "0.27", "0.27", "0.27", "0.27", "0.27", "0.27", "0.28", "0.28", "0.28", "0.28", + "0.28", "0.28", "0.29", "0.29", "0.29", "0.3", "0.3", "0.3", "0.3", "0.3", "0.3", "0.3", + "0.31", "0.31", "0.31", "0.31", "0.31", "0.31", "0.31", "0.32", "0.32", "0.32", "0.32", + "0.32", "0.33", "0.33", "0.33", "0.33", "0.33", "0.33", "0.33", "0.33", "0.33", "0.34", + "0.34", "0.34", "0.34", "0.34", "0.34", "0.34", "0.34", "0.34", "0.34", "0.35", "0.35", + "0.35", "0.35", "0.35", "0.35", "0.35", "0.35", "0.35", "0.36", "0.36", "0.36", "0.36", + "0.36", "0.36", "0.37", "0.37", "0.37", "0.38", "0.38", "0.38", "0.38", "0.38", "0.38", + "0.38", "0.39", "0.39", "0.39", "0.39", "0.39", "0.39", "0.39", "0.39", "0.39", "0.4", "0.4", + "0.41", "0.41", "0.41", "0.41", "0.41", "0.42", "0.42", "0.42", "0.42", "0.42", "0.42", + "0.42", "0.42", "0.42", "0.43", "0.43", "0.43", "0.43", "0.44", "0.44", "0.44", "0.44", + "0.44", "0.45", "0.45", "0.45", "0.45", "0.45", "0.45", "0.45", "0.46", "0.46", "0.47", + "0.47", "0.47", "0.47", "0.47", "0.47", "0.47", "0.48", "0.48", "0.48", "0.49", "0.49", + "0.49", "0.49", "0.49", "0.49", "0.49", "0.49", "0.5", "0.5", "0.5", "0.5", "0.5", "0.5", + "0.5", "0.51", "0.51", "0.52", "0.52", "0.52", "0.52", "0.52", "0.53", "0.53", "0.53", "0.53", + "0.53", "0.54", "0.54", "0.54", "0.54", "0.54", "0.55", "0.55", "0.55", "0.55", "0.55", + "0.55", "0.55", "0.56", "0.57", "0.57", "0.57", "0.57", "0.57", "0.57", "0.57", "0.58", + "0.58", "0.58", "0.58", "0.58", "0.59", "0.59", "0.59", "0.59", "0.59", "0.59", "0.59", + "0.59", "0.6", "0.6", "0.6", "0.6", "0.6", "0.61", "0.61", "0.61", "0.61", "0.62", "0.62", + "0.62", "0.62", "0.63", "0.63", "0.63", "0.63", "0.64", "0.64", "0.64", "0.65", "0.65", + "0.65", "0.65", "0.65", "0.65", "0.65", "0.66", "0.66", "0.66", "0.67", "0.67", "0.67", + "0.67", "0.67", "0.67", "0.67", "0.68", "0.68", "0.68", "0.68", "0.69", "0.69", "0.69", + "0.69", "0.7", "0.7", "0.7", "0.7", "0.71", "0.71", "0.72", "0.72", "0.72", "0.72", "0.72", + "0.73", "0.73", "0.73", "0.74", "0.74", "0.74", "0.75", "0.75", "0.75", "0.76", "0.76", + "0.76", "0.76", "0.76", "0.77", "0.77", "0.77", "0.77", "0.77", "0.78", "0.78", "0.78", + "0.78", "0.79", "0.79", "0.79", "0.8", "0.81", "0.81", "0.82", "0.82", "0.82", "0.83", "0.83", + "0.83", "0.83", "0.83", "0.84", "0.84", "0.84", "0.84", "0.84", "0.84", "0.85", "0.85", + "0.85", "0.85", "0.85", "0.85", "0.86", "0.86", "0.86", "0.86", "0.87", "0.87", "0.87", + "0.88", "0.88", "0.88", "0.88", "0.88", "0.89", "0.89", "0.89", "0.89", "0.89", "0.89", + "0.89", "0.89", "0.89", "0.89", "0.9", "0.9", "0.9", "0.91", "0.91", "0.92", "0.92", "0.92", + "0.93", "0.93", "0.93", "0.94", "0.94", "0.96", "0.97", "0.97", "0.97", "0.97", "0.98", + "0.98", "0.98", "0.98", "0.99", "1.0", "1.0", "1.01", "1.02", "1.02", "1.02", "1.02", "1.03", + "1.03", "1.03", "1.03", "1.03", "1.04", "1.04", "1.04", "1.04", "1.04", "1.05", "1.06", + "1.06", "1.07", "1.07", "1.08", "1.08", "1.08", "1.09", "1.09", "1.09", "1.09", "1.1", "1.1", + "1.1", "1.1", "1.1", "1.1", "1.11", "1.11", "1.11", "1.12", "1.13", "1.13", "1.13", "1.14", + "1.14", "1.15", "1.15", "1.15", "1.15", "1.16", "1.16", "1.16", "1.16", "1.17", "1.17", + "1.17", "1.17", "1.18", "1.19", "1.19", "1.19", "1.2", "1.21", "1.21", "1.22", "1.22", "1.22", + "1.23", "1.23", "1.24", "1.24", "1.24", "1.24", "1.24", "1.25", "1.25", "1.25", "1.25", + "1.26", "1.26", "1.26", "1.26", "1.27", "1.27", "1.28", "1.29", "1.3", "1.3", "1.3", "1.3", + "1.31", "1.32", "1.32", "1.32", "1.33", "1.33", "1.34", "1.34", "1.34", "1.35", "1.35", + "1.35", "1.35", "1.36", "1.36", "1.37", "1.37", "1.37", "1.38", "1.38", "1.38", "1.39", + "1.39", "1.39", "1.4", "1.41", "1.41", "1.41", "1.41", "1.42", "1.43", "1.43", "1.44", "1.44", + "1.44", "1.45", "1.45", "1.45", "1.47", "1.47", "1.48", "1.48", "1.48", "1.48", "1.49", "1.5", + "1.51", "1.51", "1.51", "1.52", "1.52", "1.53", "1.53", "1.54", "1.55", "1.55", "1.56", + "1.57", "1.57", "1.58", "1.59", "1.59", "1.6", "1.6", "1.6", "1.6", "1.61", "1.61", "1.63", + "1.63", "1.63", "1.64", "1.65", "1.66", "1.67", "1.67", "1.68", "1.69", "1.7", "1.7", "1.74", + "1.75", "1.77", "1.77", "1.78", "1.8", "1.81", "1.81", "1.82", "1.83", "1.83", "1.84", "1.84", + "1.84", "1.86", "1.86", "1.86", "1.86", "1.87", "1.87", "1.88", "1.89", "1.9", "1.91", "1.93", + "1.93", "1.93", "1.93", "1.94", "1.95", "1.95", "1.95", "1.97", "1.97", "1.98", "1.99", + "2.01", "2.02", "2.03", "2.03", "2.03", "2.04", "2.07", "2.07", "2.07", "2.07", "2.07", + "2.09", "2.13", "2.14", "2.16", "2.18", "2.2", "2.24", "2.24", "2.26", "2.27", "2.27", "2.28", + "2.31", "2.32", "2.33", "2.34", "2.37", "2.37", "2.39", "2.4", "2.41", "2.43", "2.46", "2.51", + "2.52", "2.58", "2.58", "2.59", "2.64", "2.65", "2.68", "2.72", "2.72", "2.73", "2.74", + "2.77", "2.78", "2.8", "2.82", "2.82", "2.84", "2.87", "2.88", "2.89", "2.9", "2.9", "2.99", + "3.0", "3.0", "3.01", "3.02", "3.04", "3.1", "3.13", "3.16", "3.2", "3.21", "3.28", "3.31", + "3.31", "3.35", "3.39", "3.39", "3.47", "3.48", "3.55", "3.68", "3.71", "3.75", "3.77", + "3.77", "3.83", "3.87", "3.88", "4.06", "4.08", "4.25", "4.27", "4.5", "4.5", "4.57", "4.8", + "5.04", "5.06", "5.13", "5.31", "5.59", "6.17", "6.38", "6.92", "6.96", "7.36", "8.65", + "9.41", "10.15", "12.1", "14.14", "14.48", "14.76", "16.21", "16.27", "16.51", "17.18", + "17.95", "18.87", "20.39", "21.32", "22.23", "22.62", "23.53", "23.54", "23.55", "23.97", + "24.85", "25.44", "26.19", "26.2", "27.12", "27.25", "27.79", "28.04", "28.31", "28.39", + "28.41", "28.56", "28.68", "29.17", "29.27", "29.31", "29.42", "29.5", "29.81", "29.95", + "30.36", "30.43", "30.6", "30.74", "31.2", "31.6", "32.04", "32.87", "33.2", "33.33", "33.36", + "33.56", "33.75", "33.91", "34.14", "34.3", "34.33", "34.6", "34.94", "35.09", "35.18", + "35.78", "36.15", "36.28", "36.42", "37.38", "37.46", "37.83", "37.92", "37.98", "38.06", + "38.36", "38.44", "38.64", "38.82", "39.17", "39.6", "39.84", "40.65", "41.71", "41.9", + "41.93", "41.97", "42.0", "42.22", "42.76", "42.85", "43.5", "44.05", "44.08", "45.03", + "45.45", "45.94", "46.23", "47.19", "47.7", "48.45", "NA", "NA", "NA", "NA", "NA", "NA", "NA", + "NA" + }; + } + + public static String[] mockImpactDnaInput() { + return new String[] { + "50.0", "50.0", "50.0", "51.0", "51.0", "52.0", "53.0", "54.0", "55.0", "55.0", "60.0", + "62.0", "63.0", "75.0", "75.0", "75.0", "76.0", "77.0", "78.0", "78.0", "79.0", "80.0", + "82.0", "88.0", "89.0", "90.0", "91.0", "92.0", "93.0", "96.0", "98.0", "100.0", "102.0", + "102.0", "104.0", "107.0", "108.0", "110.0", "111.0", "111.0", "111.0", "112.0", "116.0", + "118.0", "120.0", "121.0", "122.0", "123.0", "125.0", "130.0", "131.0", "132.0", "135.0", + "136.0", "136.0", "140.0", "144.0", "145.0", "150.0", "151.0", "152.0", "156.0", "157.0", + "158.0", "159.0", "161.0", "162.0", "165.0", "166.0", "166.0", "170.0", "174.0", "175.0", + "180.0", "181.0", "152.0", "156.0", "157.0", "158.0", "159.0", "191.0", "192.0", "195.0", + "196.0", "166.0", "200.0", "204.0", "205.0", "210.0", "211.0", "212.0", "216.0", "217.0", + "218.0", "219.0", "221.0", "222.0", "225.0", "226.0", "226.0", "230.0", "234.0", "235.0", + "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", + "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", + "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", + "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", + "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", + "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", + "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", + "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", + "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", + "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", + "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", + "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", + "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", + "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", + "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", + "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", + "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", + "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", + "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", + "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", + "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", + "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", + "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", + "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", + "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", + "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", + "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", + "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", + "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", + "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", + "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", + "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", + "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", + "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", + "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", + "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", + "240.0", "240.0", "240.0", "240.0", "240.0", "240.0", "240.0" + }; + } + + public static String[] mockRecursivelyAlwaysZeroIqr() { + return new String[] { + "11.0", "22.0", "22.0", "22.0", "22.0", "33.0", "33.0", "33.0", "33.0", "33.0", "33.0", + "33.0", "33.0", "33.0", "33.0", "33.0", "33.0", "33.0", "33.0", "33.0", "33.0", "33.0", + "33.0", "33.0", "44.0", "44.0", "44.0", "44.0", "44.0", "44.0", "44.0", "44.0", "44.0", + "44.0", "44.0", "44.0", "44.0", "44.0", "44.0", "44.0", "44.0", "44.0", "44.0", "44.0", + "44.0", "44.0", "44.0", "44.0", "44.0", "44.0", "44.0", "44.0", "44.0", "44.0", "44.0", + "44.0", "44.0", "44.0", "44.0", "44.0", "44.0", "44.0", "44.0", "44.0", "44.0", "44.0", + "44.0", "44.0", "44.0", "44.0", "44.0", "44.0", "44.0", "44.0", "44.0", "44.0", "44.0", + "44.0", "44.0", "44.0", "44.0", "44.0", "44.0", "44.0", "44.0", "44.0", "44.0", "44.0", + "44.0", "44.0", "44.0", "44.0", "44.0", "44.0", "44.0", "44.0", "44.0", "44.0", "44.0", + "44.0", "44.0", "44.0", "44.0", "44.0", "44.0", "44.0", "44.0", "44.0", "44.0", "44.0", + "44.0", "44.0", "44.0", "44.0", "44.0", "44.0", "44.0", "44.0", "44.0", "55.0", "55.0", + "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", + "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", + "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", + "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", + "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", + "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", + "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", + "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", + "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", + "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", + "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", + "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", + "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", + "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", + "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", + "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", + "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", + "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", + "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", + "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", + "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", + "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", + "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", + "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", + "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", + "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", + "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", + "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", + "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", + "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", + "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", + "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", + "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", + "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", + "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", + "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", + "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", + "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", + "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", + "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", + "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", + "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", + "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", "55.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", + "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0", "66.0" + }; + } + + public static String[] mockLinearIntegerContinuous() { + return new String[] { + "1.0", "2.0", "3.0", "4.0", "5.0", "6.0", "7.0", "8.0", "9.0", "10.0", "11.0", "12.0", "13.0", + "14.0", "15.0", "16.0", "17.0", "18.0", "19.0", "20.0", "21.0", "22.0", "23.0", "24.0", + "25.0", "26.0", "27.0", "28.0", "29.0", "30.0", "31.0", "32.0", "33.0", "34.0", "35.0", + "36.0", "37.0", "38.0", "39.0", "40.0", "41.0", "42.0", "43.0", "44.0", "45.0", "46.0", + "47.0", "48.0", "49.0", "50.0", "51.0", "52.0", "53.0", "54.0", "55.0", "56.0", "57.0", + "58.0", "59.0", "60.0", "61.0", "62.0", "63.0", "64.0", "65.0", "66.0", "67.0", "68.0", + "69.0", "70.0", "71.0", "72.0", "73.0", "74.0", "75.0", "76.0", "77.0", "78.0", "79.0", + "80.0", "81.0", "82.0", "83.0", "84.0", "85.0", "86.0", "87.0", "88.0", "89.0", "90.0", + "91.0", "92.0", "93.0", "94.0", "95.0", "96.0", "97.0", "98.0", "99.0", "100.0" + }; + } + + public static String[] mockGeniePublicAgeAtWhichSequencingWasReported() { + return new String[] { + "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "1", "1", "1", "1", "1", "1", "1", "1", "1", + "1", "1", "1", "2", "2", "2", "2", "2", "2", "3", "3", "3", "3", "4", "4", "4", "4", "4", "4", + "4", "4", "5", "5", "5", "5", "5", "5", "5", "5", "5", "5", "5", "6", "6", "6", "7", "7", "7", + "7", "8", "8", "8", "8", "8", "8", "9", "9", "9", "9", "9", "9", "9", "9", "10", "10", "10", + "10", "10", "10", "10", "10", "11", "11", "11", "11", "12", "12", "12", "12", "12", "13", + "13", "13", "13", "14", "14", "14", "14", "14", "14", "15", "15", "15", "15", "15", "15", + "15", "15", "16", "16", "16", "16", "16", "16", "16", "16", "16", "16", "17", "17", "17", + "17", "17", "17", "17", "17", "17", "17", "17", "<18", "<18", "<18", "<18", "<18", "<18", + "<18", "<18", "<18", "<18", "<18", "<18", "<18", "<18", "<18", "18", "18", "18", "18", "18", + "18", "18", "18", "18", "18", "18", "18", "18", "19", "19", "19", "19", "19", "19", "20", + "20", "20", "20", "20", "20", "20", "20", "21", "21", "21", "21", "21", "22", "22", "22", + "22", "22", "22", "22", "22", "23", "23", "23", "23", "23", "23", "23", "23", "23", "23", + "24", "24", "24", "24", "25", "25", "25", "25", "25", "25", "25", "25", "26", "26", "26", + "26", "26", "26", "27", "27", "27", "27", "27", "27", "27", "27", "27", "28", "28", "28", + "28", "28", "28", "28", "29", "29", "29", "29", "29", "29", "29", "30", "30", "30", "30", + "30", "30", "30", "30", "30", "31", "31", "31", "31", "31", "32", "32", "32", "32", "32", + "32", "33", "33", "33", "34", "34", "34", "34", "34", "34", "34", "34", "34", "34", "34", + "34", "35", "35", "35", "35", "35", "35", "36", "36", "36", "36", "36", "36", "36", "37", + "37", "37", "37", "38", "38", "38", "38", "38", "38", "39", "39", "39", "39", "39", "39", + "39", "40", "40", "40", "40", "40", "40", "41", "41", "41", "41", "42", "42", "42", "42", + "42", "42", "43", "43", "43", "43", "43", "43", "43", "43", "43", "44", "44", "44", "44", + "44", "45", "45", "45", "45", "45", "45", "45", "45", "46", "46", "46", "46", "47", "47", + "47", "47", "47", "47", "47", "47", "47", "48", "48", "48", "48", "48", "48", "49", "49", + "49", "49", "49", "49", "49", "49", "50", "50", "50", "50", "50", "50", "51", "51", "51", + "51", "51", "51", "51", "51", "51", "51", "52", "52", "52", "52", "52", "52", "52", "53", + "53", "53", "53", "53", "53", "53", "53", "53", "53", "53", "53", "54", "54", "54", "54", + "54", "54", "54", "54", "55", "55", "55", "55", "55", "55", "55", "55", "55", "55", "56", + "56", "56", "56", "56", "56", "56", "56", "56", "57", "57", "57", "57", "57", "57", "58", + "58", "58", "58", "58", "58", "58", "58", "58", "58", "58", "59", "59", "59", "59", "60", + "60", "60", "60", "60", "60", "60", "60", "61", "61", "61", "61", "61", "61", "61", "61", + "61", "61", "62", "62", "62", "62", "62", "62", "63", "63", "63", "63", "63", "63", "63", + "63", "64", "64", "64", "64", "64", "65", "65", "65", "65", "65", "65", "66", "66", "66", + "66", "66", "66", "66", "66", "Unknown", "Unknown", "Unknown", "Unknown", "Unknown", + "Unknown", "Unknown", "Unknown", "Unknown", "Unknown", "67", "67", "67", "68", "68", "68", + "68", "68", "68", "68", "68", "69", "69", "69", "69", "70", "70", "70", "70", "70", "70", + "71", "71", "71", "71", "71", "71", "71", "71", "71", "72", "72", "72", "72", "72", "72", + "72", "73", "73", "73", "73", "73", "73", "73", "73", "73", "73", "73", "73", "73", "74", + "74", "74", "74", "74", "74", "74", "74", "74", "74", "74", "74", "74", "74", "74", "75", + "75", "75", "75", "75", "75", "75", "75", "75", "75", "75", "75", "75", "75", "75", "75", + "75", "76", "76", "76", "76", "76", "76", "76", "76", "76", "76", "76", "76", "76", "77", + "77", "77", "77", "77", "77", "77", "77", "77", "77", "78", "78", "78", "78", "78", "78", + "78", "78", "78", "78", "78", "78", "79", "79", "79", "79", "79", "79", "79", "79", "80", + "80", "80", "80", "80", "80", "80", "80", "80", "80", "80", "80", "80", "81", "81", "81", + "81", "81", "81", "81", "81", "81", "82", "82", "82", "82", "82", "82", "82", "82", "82", + "82", "82", "82", "82", "82", "82", "82", "82", "82", "83", "83", "83", "83", "83", "83", + "83", "84", "84", "84", "84", "84", "84", "84", "84", "84", "84", "84", "85", "85", "85", + "85", "85", "85", "85", "85", "85", "86", "86", "86", "86", "86", "86", "86", "86", "86", + "86", "86", "86", "86", "87", "87", "87", "87", "87", "87", "87", "87", "87", "87", "87", + "87", "87", "87", "87", "88", "88", "88", "88", "89", "89", "89", ">89", ">89", ">89", ">89", + ">89", ">89", ">89", ">89", ">89", ">89", ">89", ">89", ">89", ">89", ">89", "90", "93" + }; + } + + public static String[] mockGenieNScansPetCtPt() { + return new String[] { + // 0: 380 + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + // 1: 680 + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + // 2: 320 + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + // 3: 180 + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + // 4: 95 + "4", + "4", + "4", + "4", + "4", + "4", + "4", + "4", + "4", + "4", + "4", + "4", + "4", + "4", + "4", + "4", + "4", + "4", + "4", + "4", + "4", + "4", + "4", + "4", + "4", + "4", + "4", + "4", + "4", + "4", + "4", + "4", + "4", + "4", + "4", + "4", + "4", + "4", + "4", + "4", + "4", + "4", + "4", + "4", + "4", + "4", + "4", + "4", + "4", + "4", + "4", + "4", + "4", + "4", + "4", + "4", + "4", + "4", + "4", + "4", + "4", + "4", + "4", + "4", + "4", + "4", + "4", + "4", + "4", + "4", + "4", + "4", + "4", + "4", + "4", + "4", + "4", + "4", + "4", + "4", + "4", + "4", + "4", + "4", + "4", + "4", + "4", + "4", + "4", + "4", + "4", + "4", + "4", + "4", + "4", + // 5: 56 + "5", + "5", + "5", + "5", + "5", + "5", + "5", + "5", + "5", + "5", + "5", + "5", + "5", + "5", + "5", + "5", + "5", + "5", + "5", + "5", + "5", + "5", + "5", + "5", + "5", + "5", + "5", + "5", + "5", + "5", + "5", + "5", + "5", + "5", + "5", + "5", + "5", + "5", + "5", + "5", + "5", + "5", + "5", + "5", + "5", + "5", + "5", + "5", + "5", + "5", + "5", + "5", + "5", + "5", + "5", + "5", + // 6: 38 + "6", + "6", + "6", + "6", + "6", + "6", + "6", + "6", + "6", + "6", + "6", + "6", + "6", + "6", + "6", + "6", + "6", + "6", + "6", + "6", + "6", + "6", + "6", + "6", + "6", + "6", + "6", + "6", + "6", + "6", + "6", + "6", + "6", + "6", + "6", + "6", + "6", + "6", + // 7: 20 + "7", + "7", + "7", + "7", + "7", + "7", + "7", + "7", + "7", + "7", + "7", + "7", + "7", + "7", + "7", + "7", + "7", + "7", + "7", + "7", + // 8: 17 + "8", + "8", + "8", + "8", + "8", + "8", + "8", + "8", + "8", + "8", + "8", + "8", + "8", + "8", + "8", + "8", + "8", + // 9: 16 + "9", + "9", + "9", + "9", + "9", + "9", + "9", + "9", + "9", + "9", + "9", + "9", + "9", + "9", + "9", + "9", + // 10: 5 + "10", + "10", + "10", + "10", + "10", + // 11: 2 + "11", + "11", + // 12: 7 + "12", + "12", + "12", + "12", + "12", + "12", + "12", + // 13: 5 + "13", + "13", + "13", + "13", + "13", + // 14: 2 + "14", + "14", + // 15: 7 + "15", + "15", + "15", + "15", + "15", + "15", + "15", + // 16: 3 + "16", + "16", + "16", + // 17: 1 + "17", + // 18: 3 + "18", + "18", + "18", + // 24: 1 + "24" + }; + } + + public static String[] mockGenieNScansBonePt() { + return new String[] { + // 0: 1600 + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + // 1: 130 + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + // 2: 30 + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + "2", + // 3: 3 + "3", + "3", + "3", + // 4: 6 + "4", + "4", + "4", + "4", + "4", + "4", + // 5: 1 + "5", + // 12: 1 + "12" + }; + } + + public static String[] mockBigNumbers() { + return new String[] { + "841848343", "3342183122", "3864712797", "1842342032", "379899823", "2460445587", + "2892643481", + "2355489888", "4088049033", "1152251985", "3046306673", "1442221907", "740892994", + "335986934", + "341426326", "4240429369", "2701394498", "1498406977", "2185930387", "3026106568", + "1316061727", + "126968438", "960679803", "2908515889", "3287820443", "2066082271", "2972157357", + "2797157960", + "3265466219", "664038053", "1417718651", "3111057409", "302561019", "1143079905", + "2207746117", + "4206054268", "1530213988", "1775115934", "1933635401", "820330890", "2005112863", + "2752104477", + "696476372", "3532676582", "3851721681" + }; + } + + public static String[] mockQ1Q2Q3Identical() { + return new String[] { + "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "250", "250", "250", "250", + "250", "250", "250", "250", "250", "250", "250", "250", "250", "250", "250", "250", "250", + "250", "250", "250", "250", "250", "250", "250", "250", "250", "250", "250", "250", "250", + "250", "250", "250", "250", "250", "250", "250", "250", "250" + }; + } + + public static String[] mockQ2Q3Identical() { + return new String[] { + "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "250", "250", "250", "250", + "250", "250", "250", "250", "250", "250", "250", "250" + }; + } + + public static Map mockData() { + Map mockData = new LinkedHashMap<>(); + + mockData.put("llg_tcga_egfr_mrna_expression", mockLlgTcgaEgfrMrnaExpression()); + mockData.put("blca_tcga_AGE", mockBlcaTcgaAge()); + mockData.put("skcm_broad_AGE_AT_PROCUREMENT", mockSkcmBroadAgeAtProcurement()); + mockData.put("blca_tcga_LYMPH_NODE_EXAMINED_COUNT", mockBlcaTcgaLymphNodeExaminedCount()); + mockData.put("acyc_fmi_2014_ACTIONABLE_ALTERATIONS", mockAcycFmi2014ActionableAlterations()); + mockData.put("blca_dfarber_mskcc_2014_SILENT_RATE", mockBlcaDfarberMskcc2014SilentRate()); + mockData.put("acc_tcga_DAYS_TO_BIRTH", mockAccTcgaDaysToBirth()); + mockData.put("ampca_bcm_2016_DAYS_TO_LAST_FOLLOWUP", mockAmpcaBcm2016DaysToLastFollowup()); + mockData.put("genie_INT_DOD", mockGenieIntDod()); + mockData.put("crc_msk_2018_MSI_SCORE", mockCrcMsk2018MsiScore()); + mockData.put("impact_DNA_INPUT", mockImpactDnaInput()); + mockData.put("recursively_always_zero_IQR", mockRecursivelyAlwaysZeroIqr()); + mockData.put("linear_integer_continuous", mockLinearIntegerContinuous()); + mockData.put( + "genie_public_AGE_AT_WHICH_SEQUENCING_WAS_REPORTED", + mockGeniePublicAgeAtWhichSequencingWasReported()); + mockData.put("genie_N_SCANS_PET_CT_PT", mockGenieNScansPetCtPt()); + mockData.put("genie_N_SCANS_BONE_PT", mockGenieNScansBonePt()); + mockData.put("random_BIG_NUMBER", mockBigNumbers()); + mockData.put("q1q2q3_identical", mockQ1Q2Q3Identical()); + mockData.put("q2q3_identical", mockQ2Q3Identical()); + + return mockData; + } +} diff --git a/src/test/java/org/cbioportal/legacy/web/util/DataBinnerTest.java b/src/test/java/org/cbioportal/legacy/web/util/DataBinnerTest.java new file mode 100644 index 00000000000..39d3104ab8c --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/web/util/DataBinnerTest.java @@ -0,0 +1,1389 @@ +package org.cbioportal.legacy.web.util; + +import static org.cbioportal.legacy.web.parameter.DataBinFilter.*; + +import java.math.BigDecimal; +import java.math.MathContext; +import java.math.RoundingMode; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; +import java.util.stream.IntStream; +import java.util.stream.Stream; +import org.cbioportal.legacy.model.Binnable; +import org.cbioportal.legacy.model.ClinicalData; +import org.cbioportal.legacy.model.DataBin; +import org.cbioportal.legacy.service.GeneService; +import org.cbioportal.legacy.service.util.MolecularProfileUtil; +import org.cbioportal.legacy.web.parameter.BinsGeneratorConfig; +import org.cbioportal.legacy.web.parameter.ClinicalDataBinFilter; +import org.cbioportal.legacy.web.parameter.ClinicalDataType; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.internal.matchers.apachecommons.ReflectionEquals; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +@RunWith(SpringJUnit4ClassRunner.class) +@SpringBootTest +@ContextConfiguration( + classes = { + DataBinner.class, + DataBinHelper.class, + DiscreteDataBinner.class, + LogScaleDataBinner.class, + LinearDataBinner.class, + ScientificSmallDataBinner.class, + StudyViewFilterUtil.class + }) +public class DataBinnerTest { + + private Map mockData; + + @Autowired private DataBinner dataBinner; + + @Autowired private StudyViewFilterUtil studyViewFilterUtil; + + @MockBean private MolecularProfileUtil molecularProfileUtil; + + @MockBean private GeneService geneService; + + private List getCaseIds(List unfilteredClinicalData, boolean getPatientIds) { + return unfilteredClinicalData.stream() + .map( + datum -> + studyViewFilterUtil.getCaseUniqueKey( + datum.getStudyId(), getPatientIds ? datum.getPatientId() : datum.getSampleId())) + .collect(Collectors.toList()); + } + + @Before + public void setup() { + mockData = DataBinnerMocker.mockData(); + } + + @Test + public void testLinearDataBinner() { + String studyId = "blca_tcga"; + String attributeId = "AGE"; + String[] values = mockData.get("blca_tcga_AGE"); + ClinicalDataBinFilter clinicalDataBinFilter = new ClinicalDataBinFilter(); + clinicalDataBinFilter.setAttributeId(attributeId); + + List clinicalData = mockClinicalData(attributeId, studyId, values); + List patientIds = getCaseIds(clinicalData, true); + + List dataBins = + dataBinner.calculateDataBins( + clinicalDataBinFilter, ClinicalDataType.PATIENT, clinicalData, patientIds); + + Assert.assertEquals(11, dataBins.size()); + + Assert.assertEquals("<=", dataBins.get(0).getSpecialValue()); + Assert.assertEquals(new BigDecimal("40.0"), dataBins.get(0).getEnd()); + Assert.assertEquals(2, dataBins.get(0).getCount().intValue()); + + Assert.assertEquals(new BigDecimal("40.0"), dataBins.get(1).getStart()); + Assert.assertEquals(new BigDecimal("45.0"), dataBins.get(1).getEnd()); + Assert.assertEquals(6, dataBins.get(1).getCount().intValue()); + + Assert.assertEquals(new BigDecimal("45.0"), dataBins.get(2).getStart()); + Assert.assertEquals(new BigDecimal("50.0"), dataBins.get(2).getEnd()); + Assert.assertEquals(17, dataBins.get(2).getCount().intValue()); + + Assert.assertEquals(new BigDecimal("50.0"), dataBins.get(3).getStart()); + Assert.assertEquals(new BigDecimal("55.0"), dataBins.get(3).getEnd()); + Assert.assertEquals(24, dataBins.get(3).getCount().intValue()); + + Assert.assertEquals(new BigDecimal("55.0"), dataBins.get(4).getStart()); + Assert.assertEquals(new BigDecimal("60.0"), dataBins.get(4).getEnd()); + Assert.assertEquals(59, dataBins.get(4).getCount().intValue()); + + Assert.assertEquals(new BigDecimal("60.0"), dataBins.get(5).getStart()); + Assert.assertEquals(new BigDecimal("65.0"), dataBins.get(5).getEnd()); + Assert.assertEquals(53, dataBins.get(5).getCount().intValue()); + + Assert.assertEquals(new BigDecimal("65.0"), dataBins.get(6).getStart()); + Assert.assertEquals(new BigDecimal("70.0"), dataBins.get(6).getEnd()); + Assert.assertEquals(71, dataBins.get(6).getCount().intValue()); + + Assert.assertEquals(new BigDecimal("70.0"), dataBins.get(7).getStart()); + Assert.assertEquals(new BigDecimal("75.0"), dataBins.get(7).getEnd()); + Assert.assertEquals(67, dataBins.get(7).getCount().intValue()); + + Assert.assertEquals(new BigDecimal("75.0"), dataBins.get(8).getStart()); + Assert.assertEquals(new BigDecimal("80.0"), dataBins.get(8).getEnd()); + Assert.assertEquals(64, dataBins.get(8).getCount().intValue()); + + Assert.assertEquals(new BigDecimal("80.0"), dataBins.get(9).getStart()); + Assert.assertEquals(new BigDecimal("85.0"), dataBins.get(9).getEnd()); + Assert.assertEquals(35, dataBins.get(9).getCount().intValue()); + + Assert.assertEquals(new BigDecimal("85.0"), dataBins.get(10).getStart()); + Assert.assertEquals(new BigDecimal("90.0"), dataBins.get(10).getEnd()); + Assert.assertEquals(13, dataBins.get(10).getCount().intValue()); + } + + @Test + public void testLinearDataBinnerWithRange() { + String studyId = "random"; + String attributeId = "random"; + String[] values = mockData.get("linear_integer_continuous"); + ClinicalDataBinFilter clinicalDataBinFilter = new ClinicalDataBinFilter(); + clinicalDataBinFilter.setAttributeId(attributeId); + clinicalDataBinFilter.setStart(new BigDecimal("39.5")); + clinicalDataBinFilter.setEnd(new BigDecimal("80.5")); + + List clinicalData = mockClinicalData(attributeId, studyId, values); + List patientIds = getCaseIds(clinicalData, true); + + List dataBins = + dataBinner.calculateDataBins( + clinicalDataBinFilter, ClinicalDataType.PATIENT, clinicalData, patientIds); + + Assert.assertEquals(8, dataBins.size()); + + Assert.assertEquals("<=", dataBins.get(0).getSpecialValue()); + Assert.assertEquals(new BigDecimal("45.0"), dataBins.get(0).getEnd()); + Assert.assertEquals(6, dataBins.get(0).getCount().intValue()); + + Assert.assertEquals(new BigDecimal("45.0"), dataBins.get(1).getStart()); + Assert.assertEquals(new BigDecimal("50.0"), dataBins.get(1).getEnd()); + Assert.assertEquals(5, dataBins.get(1).getCount().intValue()); + + Assert.assertEquals(new BigDecimal("50.0"), dataBins.get(2).getStart()); + Assert.assertEquals(new BigDecimal("55.0"), dataBins.get(2).getEnd()); + Assert.assertEquals(5, dataBins.get(2).getCount().intValue()); + + Assert.assertEquals(new BigDecimal("75.0"), dataBins.get(7).getStart()); + Assert.assertEquals(new BigDecimal("80.0"), dataBins.get(7).getEnd()); + Assert.assertEquals(5, dataBins.get(7).getCount().intValue()); + } + + @Test + public void testLinearDataBinnerWithRangeOne() { + String studyId = "random"; + String attributeId = "random"; + String[] values = mockData.get("linear_integer_continuous"); + ClinicalDataBinFilter clinicalDataBinFilter = new ClinicalDataBinFilter(); + clinicalDataBinFilter.setAttributeId(attributeId); + clinicalDataBinFilter.setStart(new BigDecimal("39.5")); + clinicalDataBinFilter.setEnd(new BigDecimal("80.5")); + + List clinicalData = mockClinicalData(attributeId, studyId, values); + List patientIds = getCaseIds(clinicalData, true); + + List dataBins = + dataBinner.calculateDataBins( + clinicalDataBinFilter, ClinicalDataType.PATIENT, clinicalData, patientIds); + + Assert.assertEquals(8, dataBins.size()); + + Assert.assertEquals("<=", dataBins.get(0).getSpecialValue()); + Assert.assertEquals(new BigDecimal("45.0"), dataBins.get(0).getEnd()); + Assert.assertEquals(6, dataBins.get(0).getCount().intValue()); + + Assert.assertEquals(new BigDecimal("45.0"), dataBins.get(1).getStart()); + Assert.assertEquals(new BigDecimal("50.0"), dataBins.get(1).getEnd()); + Assert.assertEquals(5, dataBins.get(1).getCount().intValue()); + + Assert.assertEquals(new BigDecimal("50.0"), dataBins.get(2).getStart()); + Assert.assertEquals(new BigDecimal("55.0"), dataBins.get(2).getEnd()); + Assert.assertEquals(5, dataBins.get(2).getCount().intValue()); + + Assert.assertEquals(new BigDecimal("75.0"), dataBins.get(7).getStart()); + Assert.assertEquals(new BigDecimal("80.0"), dataBins.get(7).getEnd()); + Assert.assertEquals(5, dataBins.get(7).getCount().intValue()); + } + + @Test + public void testLinearDataBinnerWithRangeTwo() { + String studyId = "random"; + String attributeId = "random"; + String[] values = mockData.get("linear_integer_continuous"); + ClinicalDataBinFilter clinicalDataBinFilter = new ClinicalDataBinFilter(); + clinicalDataBinFilter.setAttributeId(attributeId); + clinicalDataBinFilter.setStart(new BigDecimal("39.5")); + clinicalDataBinFilter.setEnd(new BigDecimal("81.5")); + + List clinicalData = mockClinicalData(attributeId, studyId, values); + List patientIds = getCaseIds(clinicalData, true); + + List dataBins = + dataBinner.calculateDataBins( + clinicalDataBinFilter, ClinicalDataType.PATIENT, clinicalData, patientIds); + + Assert.assertEquals(9, dataBins.size()); + + Assert.assertEquals("<=", dataBins.get(0).getSpecialValue()); + Assert.assertEquals(new BigDecimal("45.0"), dataBins.get(0).getEnd()); + Assert.assertEquals(6, dataBins.get(0).getCount().intValue()); + + Assert.assertEquals(new BigDecimal("45.0"), dataBins.get(1).getStart()); + Assert.assertEquals(new BigDecimal("50.0"), dataBins.get(1).getEnd()); + Assert.assertEquals(5, dataBins.get(1).getCount().intValue()); + + Assert.assertEquals(new BigDecimal("50.0"), dataBins.get(2).getStart()); + Assert.assertEquals(new BigDecimal("55.0"), dataBins.get(2).getEnd()); + Assert.assertEquals(5, dataBins.get(2).getCount().intValue()); + + Assert.assertEquals(new BigDecimal("75.0"), dataBins.get(7).getStart()); + Assert.assertEquals(new BigDecimal("80.0"), dataBins.get(7).getEnd()); + Assert.assertEquals(5, dataBins.get(7).getCount().intValue()); + + Assert.assertEquals(new BigDecimal("80.0"), dataBins.get(8).getStart()); + Assert.assertEquals(">", dataBins.get(8).getSpecialValue()); + Assert.assertEquals(1, dataBins.get(8).getCount().intValue()); + } + + @Test + public void testLinearDataBinnerWithRangeAndCustomBins() { + String studyId = "random"; + String attributeId = "random"; + String[] values = mockData.get("linear_integer_continuous"); + ClinicalDataBinFilter clinicalDataBinFilter = new ClinicalDataBinFilter(); + clinicalDataBinFilter.setAttributeId(attributeId); + clinicalDataBinFilter.setStart(new BigDecimal("39.5")); + clinicalDataBinFilter.setEnd(new BigDecimal("81.5")); + clinicalDataBinFilter.setBinMethod(BinMethod.CUSTOM); + clinicalDataBinFilter.setCustomBins( + Arrays.asList(50.0, 60.0, 70.0).stream() + .map(item -> BigDecimal.valueOf(item)) + .collect(Collectors.toList())); + + List clinicalData = mockClinicalData(attributeId, studyId, values); + List patientIds = getCaseIds(clinicalData, true); + + List dataBins = + dataBinner.calculateDataBins( + clinicalDataBinFilter, ClinicalDataType.PATIENT, clinicalData, patientIds); + + Assert.assertEquals(4, dataBins.size()); + + Assert.assertEquals("<=", dataBins.get(0).getSpecialValue()); + Assert.assertEquals(new BigDecimal("50.0"), dataBins.get(0).getEnd()); + Assert.assertEquals(11, dataBins.get(0).getCount().intValue()); + + Assert.assertEquals(new BigDecimal("50.0"), dataBins.get(1).getStart()); + Assert.assertEquals(new BigDecimal("60.0"), dataBins.get(1).getEnd()); + Assert.assertEquals(10, dataBins.get(1).getCount().intValue()); + + Assert.assertEquals(new BigDecimal("60.0"), dataBins.get(2).getStart()); + Assert.assertEquals(new BigDecimal("70.0"), dataBins.get(2).getEnd()); + Assert.assertEquals(10, dataBins.get(2).getCount().intValue()); + + Assert.assertEquals(new BigDecimal("70.0"), dataBins.get(3).getStart()); + Assert.assertEquals(">", dataBins.get(3).getSpecialValue()); + Assert.assertEquals(11, dataBins.get(3).getCount().intValue()); + } + + @Test + public void testStaticDataBinnerFilter() { + String studyId = "blca_tcga"; + String attributeId = "AGE"; + String[] values = mockData.get("blca_tcga_AGE"); + + ClinicalDataBinFilter clinicalDataBinFilter = new ClinicalDataBinFilter(); + clinicalDataBinFilter.setAttributeId(attributeId); + + List unfilteredClinicalData = mockClinicalData(attributeId, studyId, values); + List unfilteredPatientIds = getCaseIds(unfilteredClinicalData, true); + List unfilteredDataBins = + dataBinner.calculateDataBins( + clinicalDataBinFilter, + ClinicalDataType.PATIENT, + unfilteredClinicalData, + unfilteredPatientIds); + + List filteredClinicalData = + unfilteredClinicalData.subList(0, 108); // (0, 60] interval + List filteredPatientIds = getCaseIds(filteredClinicalData, true); + List filteredDataBins = + dataBinner.calculateClinicalDataBins( + clinicalDataBinFilter, + ClinicalDataType.PATIENT, + filteredClinicalData, + unfilteredClinicalData, + filteredPatientIds, + unfilteredPatientIds); + + // same number of bins for both + Assert.assertEquals(11, unfilteredDataBins.size()); + Assert.assertEquals(11, filteredDataBins.size()); + + // same start/end/special values for all bins + + Assert.assertEquals("<=", filteredDataBins.get(0).getSpecialValue()); + Assert.assertEquals("<=", unfilteredDataBins.get(0).getSpecialValue()); + Assert.assertEquals(new BigDecimal("40.0"), filteredDataBins.get(0).getEnd()); + Assert.assertEquals(new BigDecimal("40.0"), unfilteredDataBins.get(0).getEnd()); + + Assert.assertEquals(new BigDecimal("40.0"), filteredDataBins.get(1).getStart()); + Assert.assertEquals(new BigDecimal("40.0"), unfilteredDataBins.get(1).getStart()); + Assert.assertEquals(new BigDecimal("45.0"), filteredDataBins.get(1).getEnd()); + Assert.assertEquals(new BigDecimal("45.0"), unfilteredDataBins.get(1).getEnd()); + + Assert.assertEquals(new BigDecimal("45.0"), filteredDataBins.get(2).getStart()); + Assert.assertEquals(new BigDecimal("45.0"), unfilteredDataBins.get(2).getStart()); + Assert.assertEquals(new BigDecimal("50.0"), filteredDataBins.get(2).getEnd()); + Assert.assertEquals(new BigDecimal("50.0"), unfilteredDataBins.get(2).getEnd()); + + Assert.assertEquals(new BigDecimal("50.0"), filteredDataBins.get(3).getStart()); + Assert.assertEquals(new BigDecimal("50.0"), unfilteredDataBins.get(3).getStart()); + Assert.assertEquals(new BigDecimal("55.0"), filteredDataBins.get(3).getEnd()); + Assert.assertEquals(new BigDecimal("55.0"), unfilteredDataBins.get(3).getEnd()); + + Assert.assertEquals(new BigDecimal("55.0"), filteredDataBins.get(4).getStart()); + Assert.assertEquals(new BigDecimal("55.0"), unfilteredDataBins.get(4).getStart()); + Assert.assertEquals(new BigDecimal("60.0"), filteredDataBins.get(4).getEnd()); + Assert.assertEquals(new BigDecimal("60.0"), unfilteredDataBins.get(4).getEnd()); + + Assert.assertEquals(new BigDecimal("60.0"), filteredDataBins.get(5).getStart()); + Assert.assertEquals(new BigDecimal("60.0"), unfilteredDataBins.get(5).getStart()); + Assert.assertEquals(new BigDecimal("65.0"), filteredDataBins.get(5).getEnd()); + Assert.assertEquals(new BigDecimal("65.0"), unfilteredDataBins.get(5).getEnd()); + + Assert.assertEquals(new BigDecimal("85.0"), filteredDataBins.get(10).getStart()); + Assert.assertEquals(new BigDecimal("85.0"), unfilteredDataBins.get(10).getStart()); + Assert.assertEquals(new BigDecimal("90.0"), filteredDataBins.get(10).getEnd()); + Assert.assertEquals(new BigDecimal("90.0"), unfilteredDataBins.get(10).getEnd()); + + // same counts until the bin (60-65] + + Assert.assertEquals(2, filteredDataBins.get(0).getCount().intValue()); + Assert.assertEquals(2, unfilteredDataBins.get(0).getCount().intValue()); + + Assert.assertEquals(6, filteredDataBins.get(1).getCount().intValue()); + Assert.assertEquals(6, unfilteredDataBins.get(1).getCount().intValue()); + + Assert.assertEquals(17, filteredDataBins.get(2).getCount().intValue()); + Assert.assertEquals(17, unfilteredDataBins.get(2).getCount().intValue()); + + Assert.assertEquals(24, filteredDataBins.get(3).getCount().intValue()); + Assert.assertEquals(24, unfilteredDataBins.get(3).getCount().intValue()); + + Assert.assertEquals(59, filteredDataBins.get(4).getCount().intValue()); + Assert.assertEquals(59, unfilteredDataBins.get(4).getCount().intValue()); + + Assert.assertEquals(0, filteredDataBins.get(5).getCount().intValue()); + Assert.assertEquals(53, unfilteredDataBins.get(5).getCount().intValue()); + + Assert.assertEquals(0, filteredDataBins.get(6).getCount().intValue()); + Assert.assertEquals(71, unfilteredDataBins.get(6).getCount().intValue()); + + Assert.assertEquals(0, filteredDataBins.get(10).getCount().intValue()); + Assert.assertEquals(13, unfilteredDataBins.get(10).getCount().intValue()); + } + + @Test + public void testLinearDataBinnerWithNumberOfPetOrPetCtScans() { + String studyId = "genie"; + String attributeId = "N_SCANS_PET_CT_PT"; + String[] values = mockData.get("genie_N_SCANS_PET_CT_PT"); + + List clinicalData = mockClinicalData(attributeId, studyId, values); + List patientIds = getCaseIds(clinicalData, true); + + ClinicalDataBinFilter clinicalDataBinFilter = new ClinicalDataBinFilter(); + clinicalDataBinFilter.setAttributeId(attributeId); + + List dataBins = + dataBinner.calculateDataBins( + clinicalDataBinFilter, ClinicalDataType.PATIENT, clinicalData, patientIds); + + Assert.assertEquals(4, dataBins.size()); + + Assert.assertEquals("<=", dataBins.get(0).getSpecialValue()); + Assert.assertEquals(1, dataBins.get(0).getEnd().intValue()); + + Assert.assertEquals(2, dataBins.get(1).getStart().intValue()); + Assert.assertEquals(2, dataBins.get(1).getEnd().intValue()); + + Assert.assertEquals(3, dataBins.get(2).getStart().intValue()); + Assert.assertEquals(3, dataBins.get(2).getEnd().intValue()); + + Assert.assertEquals(">", dataBins.get(3).getSpecialValue()); + Assert.assertEquals(3, dataBins.get(3).getStart().intValue()); + } + + @Test + public void testLinearDataBinnerWithNumberOfBoneScans() { + String studyId = "genie"; + String attributeId = "N_SCANS_BONE_PT"; + String[] values = mockData.get("genie_N_SCANS_BONE_PT"); + + List clinicalData = mockClinicalData(attributeId, studyId, values); + List patientIds = getCaseIds(clinicalData, true); + + ClinicalDataBinFilter clinicalDataBinFilter = new ClinicalDataBinFilter(); + clinicalDataBinFilter.setAttributeId(attributeId); + + // perform data binning with the default distinct value threshold (10) + List dataBinsWithDefaultThreshold = + dataBinner.calculateDataBins( + clinicalDataBinFilter, ClinicalDataType.PATIENT, clinicalData, patientIds); + + Assert.assertEquals(7, dataBinsWithDefaultThreshold.size()); + + Assert.assertEquals(0, dataBinsWithDefaultThreshold.get(0).getStart().intValue()); + Assert.assertEquals(0, dataBinsWithDefaultThreshold.get(0).getEnd().intValue()); + + Assert.assertEquals(12, dataBinsWithDefaultThreshold.get(6).getStart().intValue()); + Assert.assertEquals(12, dataBinsWithDefaultThreshold.get(6).getEnd().intValue()); + + // perform data binning with 5 as the distinct value threshold + List dataBinsWithThreshold5 = + dataBinner.calculateDataBins( + clinicalDataBinFilter, ClinicalDataType.PATIENT, clinicalData, patientIds, 5); + + Assert.assertEquals(2, dataBinsWithThreshold5.size()); + + Assert.assertEquals(0, dataBinsWithThreshold5.get(0).getStart().intValue()); + Assert.assertEquals(0, dataBinsWithThreshold5.get(0).getEnd().intValue()); + + Assert.assertEquals(">", dataBinsWithThreshold5.get(1).getSpecialValue()); + Assert.assertEquals(0, dataBinsWithThreshold5.get(1).getStart().intValue()); + Assert.assertNull(dataBinsWithThreshold5.get(1).getEnd()); + } + + @Test + public void testLinearDataBinnerWithAgeAtWhichSequencingWasReported() { + String studyId = "genie_public"; + String attributeId = "AGE_AT_WHICH_SEQUENCING_WAS_REPORTED"; + String[] values = mockData.get("genie_public_AGE_AT_WHICH_SEQUENCING_WAS_REPORTED"); + + List clinicalData = mockClinicalData(attributeId, studyId, values); + List patientIds = getCaseIds(clinicalData, true); + + ClinicalDataBinFilter clinicalDataBinFilter = new ClinicalDataBinFilter(); + clinicalDataBinFilter.setAttributeId(attributeId); + clinicalDataBinFilter.setBinMethod(BinMethod.CUSTOM); + clinicalDataBinFilter.setCustomBins( + Stream.of(45.0, 60.0, 70.0).map(BigDecimal::valueOf).collect(Collectors.toList())); + + List dataBins1 = + dataBinner.calculateDataBins( + clinicalDataBinFilter, ClinicalDataType.PATIENT, clinicalData, patientIds); + Assert.assertEquals(5, dataBins1.size()); + + Assert.assertEquals("<=", dataBins1.get(0).getSpecialValue()); + Assert.assertEquals(new BigDecimal("45.0"), dataBins1.get(0).getEnd()); + Assert.assertEquals(337, dataBins1.get(0).getCount().intValue()); + + Assert.assertEquals(new BigDecimal("45.0"), dataBins1.get(1).getStart()); + Assert.assertEquals(new BigDecimal("60.0"), dataBins1.get(1).getEnd()); + Assert.assertEquals(118, dataBins1.get(1).getCount().intValue()); + + Assert.assertEquals(new BigDecimal("60.0"), dataBins1.get(2).getStart()); + Assert.assertEquals(new BigDecimal("70.0"), dataBins1.get(2).getEnd()); + Assert.assertEquals(64, dataBins1.get(2).getCount().intValue()); + + Assert.assertEquals(">", dataBins1.get(3).getSpecialValue()); + Assert.assertEquals(new BigDecimal("70.0"), dataBins1.get(3).getStart()); + Assert.assertEquals(223, dataBins1.get(3).getCount().intValue()); + + Assert.assertEquals("Unknown", dataBins1.get(4).getSpecialValue()); + Assert.assertEquals(10, dataBins1.get(4).getCount().intValue()); + + clinicalDataBinFilter.setCustomBins( + Stream.of(40.0, 55.0).map(BigDecimal::valueOf).collect(Collectors.toList())); + + List dataBins2 = + dataBinner.calculateDataBins( + clinicalDataBinFilter, ClinicalDataType.PATIENT, clinicalData, patientIds); + Assert.assertEquals(4, dataBins2.size()); + + Assert.assertEquals("<=", dataBins2.get(0).getSpecialValue()); + Assert.assertEquals(new BigDecimal("40.0"), dataBins2.get(0).getEnd()); + Assert.assertEquals(305, dataBins2.get(0).getCount().intValue()); + + Assert.assertEquals(new BigDecimal("40.0"), dataBins2.get(1).getStart()); + Assert.assertEquals(new BigDecimal("55.0"), dataBins2.get(1).getEnd()); + Assert.assertEquals(112, dataBins2.get(1).getCount().intValue()); + + Assert.assertEquals(">", dataBins2.get(2).getSpecialValue()); + Assert.assertEquals(new BigDecimal("55.0"), dataBins2.get(2).getStart()); + Assert.assertEquals(325, dataBins2.get(2).getCount().intValue()); + + Assert.assertEquals("Unknown", dataBins2.get(3).getSpecialValue()); + Assert.assertEquals(10, dataBins2.get(3).getCount().intValue()); + + clinicalDataBinFilter.setCustomBins( + Stream.of(5.0, 10.0, 90.0, 100.0).map(BigDecimal::valueOf).collect(Collectors.toList())); + + List dataBins3 = + dataBinner.calculateDataBins( + clinicalDataBinFilter, ClinicalDataType.PATIENT, clinicalData, patientIds); + Assert.assertEquals(4, dataBins3.size()); + + // even if we have 5 and 10 they will not be used because we have special values like "<18" + Assert.assertEquals("<=", dataBins3.get(0).getSpecialValue()); + Assert.assertEquals(new BigDecimal("18"), dataBins3.get(0).getEnd()); + Assert.assertEquals(156, dataBins3.get(0).getCount().intValue()); + + Assert.assertEquals(new BigDecimal("18"), dataBins3.get(1).getStart()); + Assert.assertEquals(new BigDecimal("89"), dataBins3.get(1).getEnd()); + Assert.assertEquals(569, dataBins3.get(1).getCount().intValue()); + + // even if we have 90 and 100 they will not be used because we have special values like ">89" in + // our data + Assert.assertEquals(">", dataBins3.get(2).getSpecialValue()); + Assert.assertEquals(new BigDecimal("89"), dataBins3.get(2).getStart()); + Assert.assertEquals(17, dataBins3.get(2).getCount().intValue()); + + Assert.assertEquals("Unknown", dataBins3.get(3).getSpecialValue()); + Assert.assertEquals(10, dataBins3.get(3).getCount().intValue()); + } + + @Test + public void testLinearDataBinnerWithPediatricAge() { + String studyId = "skcm_broad"; + String attributeId = "AGE_AT_PROCUREMENT"; + String[] values = mockData.get("skcm_broad_AGE_AT_PROCUREMENT"); + String[] patientsWithNoClinicalData = { + "NA_PATIENT_01", "NA_PATIENT_02", "NA_PATIENT_03", "NA_PATIENT_04" + }; + ClinicalDataBinFilter clinicalDataBinFilter = new ClinicalDataBinFilter(); + clinicalDataBinFilter.setAttributeId(attributeId); + clinicalDataBinFilter.setBinMethod(BinMethod.CUSTOM); + clinicalDataBinFilter.setCustomBins( + Arrays.asList(18.0, 20.0, 30.0, 40.0, 50.0, 60.0, 70.0, 80.0, 90.0).stream() + .map(item -> BigDecimal.valueOf(item)) + .collect(Collectors.toList())); + + List clinicalData = mockClinicalData(attributeId, studyId, values); + List patientIds = getCaseIds(clinicalData, true); + patientIds.addAll(Arrays.asList(patientsWithNoClinicalData)); + + List dataBins = + dataBinner.calculateDataBins( + clinicalDataBinFilter, ClinicalDataType.PATIENT, clinicalData, patientIds); + + Assert.assertEquals(10, dataBins.size()); + + Assert.assertEquals("<=", dataBins.get(0).getSpecialValue()); + Assert.assertEquals(new BigDecimal("18.0"), dataBins.get(0).getEnd()); + Assert.assertEquals(1, dataBins.get(0).getCount().intValue()); + + Assert.assertEquals(new BigDecimal("18.0"), dataBins.get(1).getStart()); + Assert.assertEquals(new BigDecimal("20.0"), dataBins.get(1).getEnd()); + Assert.assertEquals(0, dataBins.get(1).getCount().intValue()); + + Assert.assertEquals(new BigDecimal("20.0"), dataBins.get(2).getStart()); + Assert.assertEquals(new BigDecimal("30.0"), dataBins.get(2).getEnd()); + Assert.assertEquals(9, dataBins.get(2).getCount().intValue()); + + Assert.assertEquals(new BigDecimal("30.0"), dataBins.get(3).getStart()); + Assert.assertEquals(new BigDecimal("40.0"), dataBins.get(3).getEnd()); + Assert.assertEquals(16, dataBins.get(3).getCount().intValue()); + + Assert.assertEquals(new BigDecimal("40.0"), dataBins.get(4).getStart()); + Assert.assertEquals(new BigDecimal("50.0"), dataBins.get(4).getEnd()); + Assert.assertEquals(31, dataBins.get(4).getCount().intValue()); + + Assert.assertEquals(new BigDecimal("50.0"), dataBins.get(5).getStart()); + Assert.assertEquals(new BigDecimal("60.0"), dataBins.get(5).getEnd()); + Assert.assertEquals(25, dataBins.get(5).getCount().intValue()); + + Assert.assertEquals(new BigDecimal("60.0"), dataBins.get(6).getStart()); + Assert.assertEquals(new BigDecimal("70.0"), dataBins.get(6).getEnd()); + Assert.assertEquals(24, dataBins.get(6).getCount().intValue()); + + Assert.assertEquals(new BigDecimal("70.0"), dataBins.get(7).getStart()); + Assert.assertEquals(new BigDecimal("80.0"), dataBins.get(7).getEnd()); + Assert.assertEquals(11, dataBins.get(7).getCount().intValue()); + + Assert.assertEquals(new BigDecimal("80.0"), dataBins.get(8).getStart()); + Assert.assertEquals(new BigDecimal("90.0"), dataBins.get(8).getEnd()); + Assert.assertEquals(2, dataBins.get(8).getCount().intValue()); + + Assert.assertEquals("NA", dataBins.get(9).getSpecialValue()); + Assert.assertEquals(4, dataBins.get(9).getCount().intValue()); + } + + @Test + public void testLinearDataBinnerWithPediatricAgeCustomBinsTest1() { + String studyId = "skcm_broad"; + String attributeId = "AGE_AT_PROCUREMENT"; + String[] values = mockData.get("skcm_broad_AGE_AT_PROCUREMENT"); + String[] patientsWithNoClinicalData = { + "NA_PATIENT_01", "NA_PATIENT_02", "NA_PATIENT_03", "NA_PATIENT_04" + }; + ClinicalDataBinFilter clinicalDataBinFilter = new ClinicalDataBinFilter(); + clinicalDataBinFilter.setAttributeId(attributeId); + clinicalDataBinFilter.setBinMethod(BinMethod.CUSTOM); + clinicalDataBinFilter.setCustomBins( + Arrays.asList(18.0, 20.0, 30.0, 40.0, 50.0, 60.0, 70.0, 80.0, 90.0).stream() + .map(item -> BigDecimal.valueOf(item)) + .collect(Collectors.toList())); + + List clinicalData = mockClinicalData(attributeId, studyId, values); + List patientIds = getCaseIds(clinicalData, true); + patientIds.addAll(Arrays.asList(patientsWithNoClinicalData)); + + List dataBins = + dataBinner.calculateDataBins( + clinicalDataBinFilter, ClinicalDataType.PATIENT, clinicalData, patientIds); + + List expected = + Arrays.asList( + createDataBin("<=", null, "18.0", 1), + createDataBin(null, "18.0", "20.0", 0), + createDataBin(null, "20.0", "30.0", 9), + createDataBin(null, "30.0", "40.0", 16), + createDataBin(null, "40.0", "50.0", 31), + createDataBin(null, "50.0", "60.0", 25), + createDataBin(null, "60.0", "70.0", 24), + createDataBin(null, "70.0", "80.0", 11), + createDataBin(null, "80.0", "90.0", 2), + createDataBin("NA", null, null, 4)); + + testBinsIdentical(expected, dataBins); + } + + @Test + public void testLinearDataBinnerWithPediatricAgeCustomBinsTest2() { + String studyId = "skcm_broad"; + String attributeId = "AGE_AT_PROCUREMENT"; + String[] values = mockData.get("skcm_broad_AGE_AT_PROCUREMENT"); + String[] patientsWithNoClinicalData = { + "NA_PATIENT_01", "NA_PATIENT_02", "NA_PATIENT_03", "NA_PATIENT_04" + }; + ClinicalDataBinFilter clinicalDataBinFilter = new ClinicalDataBinFilter(); + clinicalDataBinFilter.setAttributeId(attributeId); + clinicalDataBinFilter.setBinMethod(BinMethod.CUSTOM); + clinicalDataBinFilter.setCustomBins( + Arrays.asList(18.0, 25.0, 30.0, 35.0).stream() + .map(item -> BigDecimal.valueOf(item)) + .collect(Collectors.toList())); + + List clinicalData = mockClinicalData(attributeId, studyId, values); + List patientIds = getCaseIds(clinicalData, true); + patientIds.addAll(Arrays.asList(patientsWithNoClinicalData)); + + List dataBins = + dataBinner.calculateDataBins( + clinicalDataBinFilter, ClinicalDataType.PATIENT, clinicalData, patientIds); + + List expected = + Arrays.asList( + createDataBin("<=", null, "18.0", 1), + createDataBin(null, "18.0", "25.0", 2), + createDataBin(null, "25.0", "30.0", 7), + createDataBin(null, "30.0", "35.0", 7), + createDataBin(">", "35.0", null, 102), + createDataBin("NA", null, null, 4)); + + testBinsIdentical(expected, dataBins); + } + + @Test + public void testLinearDataBinnerWithPediatricAgeCustomBinsSingleBoundary() { + String studyId = "skcm_broad"; + String attributeId = "AGE_AT_PROCUREMENT"; + String[] values = mockData.get("skcm_broad_AGE_AT_PROCUREMENT"); + String[] patientsWithNoClinicalData = { + "NA_PATIENT_01", "NA_PATIENT_02", "NA_PATIENT_03", "NA_PATIENT_04" + }; + ClinicalDataBinFilter clinicalDataBinFilter = new ClinicalDataBinFilter(); + clinicalDataBinFilter.setAttributeId(attributeId); + clinicalDataBinFilter.setBinMethod(BinMethod.CUSTOM); + clinicalDataBinFilter.setCustomBins( + Arrays.asList(30.0).stream() + .map(item -> BigDecimal.valueOf(item)) + .collect(Collectors.toList())); + + List clinicalData = mockClinicalData(attributeId, studyId, values); + List patientIds = getCaseIds(clinicalData, true); + patientIds.addAll(Arrays.asList(patientsWithNoClinicalData)); + + List dataBins = + dataBinner.calculateDataBins( + clinicalDataBinFilter, ClinicalDataType.PATIENT, clinicalData, patientIds); + + List expected = + Arrays.asList( + createDataBin("<=", null, "30.0", 10), + createDataBin(">", "30.0", null, 109), + createDataBin("NA", null, null, 4)); + + testBinsIdentical(expected, dataBins); + } + + @Test + public void testLinearDataBinnerWithPediatricAgeCustomBinsTwoBoundaries() { + String studyId = "skcm_broad"; + String attributeId = "AGE_AT_PROCUREMENT"; + String[] values = mockData.get("skcm_broad_AGE_AT_PROCUREMENT"); + String[] patientsWithNoClinicalData = { + "NA_PATIENT_01", "NA_PATIENT_02", "NA_PATIENT_03", "NA_PATIENT_04" + }; + ClinicalDataBinFilter clinicalDataBinFilter = new ClinicalDataBinFilter(); + clinicalDataBinFilter.setAttributeId(attributeId); + clinicalDataBinFilter.setBinMethod(BinMethod.CUSTOM); + clinicalDataBinFilter.setCustomBins( + Arrays.asList(20.0, 50.0).stream() + .map(item -> BigDecimal.valueOf(item)) + .collect(Collectors.toList())); + + List clinicalData = mockClinicalData(attributeId, studyId, values); + List patientIds = getCaseIds(clinicalData, true); + patientIds.addAll(Arrays.asList(patientsWithNoClinicalData)); + + List dataBins = + dataBinner.calculateDataBins( + clinicalDataBinFilter, ClinicalDataType.PATIENT, clinicalData, patientIds); + + List expected = + Arrays.asList( + createDataBin("<=", null, "20.0", 1), + createDataBin(null, "20.0", "50.0", 56), + createDataBin(">", "50.0", null, 62), + createDataBin("NA", null, null, 4)); + + testBinsIdentical(expected, dataBins); + } + + @Test + public void testLinearDataBinnerWithPediatricAgeGenerateBins() { + String studyId = "skcm_broad"; + String attributeId = "AGE_AT_PROCUREMENT"; + String[] values = mockData.get("skcm_broad_AGE_AT_PROCUREMENT"); + String[] patientsWithNoClinicalData = { + "NA_PATIENT_01", "NA_PATIENT_02", "NA_PATIENT_03", "NA_PATIENT_04" + }; + + ClinicalDataBinFilter clinicalDataBinFilter = new ClinicalDataBinFilter(); + clinicalDataBinFilter.setAttributeId(attributeId); + clinicalDataBinFilter.setBinMethod(BinMethod.GENERATE); + BinsGeneratorConfig generateBins = new BinsGeneratorConfig(); + generateBins.setBinSize(new BigDecimal(10)); + generateBins.setAnchorValue(new BigDecimal(50)); + clinicalDataBinFilter.setBinsGeneratorConfig(generateBins); + + List clinicalData = mockClinicalData(attributeId, studyId, values); + List patientIds = getCaseIds(clinicalData, true); + patientIds.addAll(Arrays.asList(patientsWithNoClinicalData)); + + List dataBins = + dataBinner.calculateDataBins( + clinicalDataBinFilter, ClinicalDataType.PATIENT, clinicalData, patientIds); + + List expected = + Arrays.asList( + createDataBin("<=", null, "20.0", 1), + createDataBin(null, "20.0", "30.0", 9), + createDataBin(null, "30.0", "40.0", 16), + createDataBin(null, "40.0", "50.0", 31), + createDataBin(null, "50.0", "60.0", 25), + createDataBin(null, "60.0", "70.0", 24), + createDataBin(null, "70.0", "80.0", 11), + createDataBin(">", "80.0", null, 2), + createDataBin("NA", null, null, 4)); + + testBinsIdentical(expected, dataBins); + } + + @Test + public void testLinearDataBinnerWithPediatricAgeMedianBins() { + String studyId = "skcm_broad"; + String attributeId = "AGE_AT_PROCUREMENT"; + String[] values = mockData.get("skcm_broad_AGE_AT_PROCUREMENT"); + String[] patientsWithNoClinicalData = { + "NA_PATIENT_01", "NA_PATIENT_02", "NA_PATIENT_03", "NA_PATIENT_04" + }; + + ClinicalDataBinFilter clinicalDataBinFilter = new ClinicalDataBinFilter(); + clinicalDataBinFilter.setAttributeId(attributeId); + clinicalDataBinFilter.setBinMethod(BinMethod.MEDIAN); + + List clinicalData = mockClinicalData(attributeId, studyId, values); + List patientIds = getCaseIds(clinicalData, true); + patientIds.addAll(Arrays.asList(patientsWithNoClinicalData)); + + List dataBins = + dataBinner.calculateDataBins( + clinicalDataBinFilter, ClinicalDataType.PATIENT, clinicalData, patientIds); + + List expected = + Arrays.asList( + createDataBin("<=", null, "51.0", 61), + createDataBin(">", "51.0", null, 58), + createDataBin("NA", null, null, 4)); + + testBinsIdentical(expected, dataBins); + } + + @Test + public void testLinearDataBinnerWithPediatricAgeQuartileBins() { + String studyId = "skcm_broad"; + String attributeId = "AGE_AT_PROCUREMENT"; + String[] values = mockData.get("skcm_broad_AGE_AT_PROCUREMENT"); + String[] patientsWithNoClinicalData = { + "NA_PATIENT_01", "NA_PATIENT_02", "NA_PATIENT_03", "NA_PATIENT_04" + }; + + ClinicalDataBinFilter clinicalDataBinFilter = new ClinicalDataBinFilter(); + clinicalDataBinFilter.setAttributeId(attributeId); + clinicalDataBinFilter.setBinMethod(BinMethod.QUARTILE); + + List clinicalData = mockClinicalData(attributeId, studyId, values); + List patientIds = getCaseIds(clinicalData, true); + patientIds.addAll(Arrays.asList(patientsWithNoClinicalData)); + + List dataBins = + dataBinner.calculateDataBins( + clinicalDataBinFilter, ClinicalDataType.PATIENT, clinicalData, patientIds); + + List expected = + Arrays.asList( + createDataBin("<=", null, "41.0", 30), + createDataBin(null, "41.0", "51.0", 31), + createDataBin(null, "51.0", "65.0", 33), + createDataBin(">", "65.0", null, 25), + createDataBin("NA", null, null, 4)); + + testBinsIdentical(expected, dataBins); + } + + @Test + public void testLinearDataBinnerQuartileBinsLowComplexitySeriesQ1Q2Q3Identical() { + String studyId = "skcm_broad"; + String attributeId = "AGE_AT_PROCUREMENT"; + String[] values = mockData.get("q1q2q3_identical"); + + ClinicalDataBinFilter clinicalDataBinFilter = new ClinicalDataBinFilter(); + clinicalDataBinFilter.setAttributeId(attributeId); + clinicalDataBinFilter.setBinMethod(BinMethod.QUARTILE); + + List clinicalData = mockClinicalData(attributeId, studyId, values); + List patientIds = getCaseIds(clinicalData, true); + + List dataBins = + dataBinner.calculateDataBins( + clinicalDataBinFilter, ClinicalDataType.PATIENT, clinicalData, patientIds); + + List expected = Arrays.asList(createDataBin("<=", null, "250", 50)); + + testBinsIdentical(expected, dataBins); + } + + @Test + public void testLinearDataBinnerQuartileBinsLowComplexitySeriesQ2Q3Identical() { + String studyId = "skcm_broad"; + String attributeId = "AGE_AT_PROCUREMENT"; + String[] values = mockData.get("q2q3_identical"); + + ClinicalDataBinFilter clinicalDataBinFilter = new ClinicalDataBinFilter(); + clinicalDataBinFilter.setAttributeId(attributeId); + clinicalDataBinFilter.setBinMethod(BinMethod.QUARTILE); + + List clinicalData = mockClinicalData(attributeId, studyId, values); + List patientIds = getCaseIds(clinicalData, true); + + List dataBins = + dataBinner.calculateDataBins( + clinicalDataBinFilter, ClinicalDataType.PATIENT, clinicalData, patientIds); + + List expected = + Arrays.asList(createDataBin("<=", null, "15", 6), createDataBin(null, "15", "250", 17)); + + testBinsIdentical(expected, dataBins); + } + + @Test + public void testLinearDataBinnerWithBigNumbers() { + String studyId = "random_"; + String attributeId = "BIG_NUMBER"; + String[] values = mockData.get("random_BIG_NUMBER"); + ClinicalDataBinFilter clinicalDataBinFilter = new ClinicalDataBinFilter(); + clinicalDataBinFilter.setAttributeId(attributeId); + + List clinicalData = mockClinicalData(attributeId, studyId, values); + List patientIds = getCaseIds(clinicalData, true); + + List dataBins = + dataBinner.calculateDataBins( + clinicalDataBinFilter, ClinicalDataType.PATIENT, clinicalData, patientIds); + + List expected = + Arrays.asList( + createDataBin(null, "1.0E+8", "316227766", 2), + createDataBin(null, "316227766", "1.0E+9", 9), + createDataBin(null, "1.0E+9", "3.16227766E+9", 25), + createDataBin(null, "3.16227766E+9", "1.0E+10", 9)); + + testBinsIdentical(expected, dataBins); + } + + @Test + public void testLinearDataBinnerWithPredefinedAttribute() { + String studyId = "crc_msk_2018"; + String attributeId = "MSI_SCORE"; + String[] values = mockData.get("crc_msk_2018_MSI_SCORE"); + ClinicalDataBinFilter clinicalDataBinFilter = new ClinicalDataBinFilter(); + clinicalDataBinFilter.setAttributeId(attributeId); + clinicalDataBinFilter.setBinMethod(BinMethod.CUSTOM); + clinicalDataBinFilter.setCustomBins( + Arrays.asList(1.0, 2.0, 5.0, 10.0, 30.0).stream() + .map(item -> BigDecimal.valueOf(item)) + .collect(Collectors.toList())); + + List clinicalData = mockClinicalData(attributeId, studyId, values); + List sampleIds = getCaseIds(clinicalData, false); + + List dataBins = + dataBinner.calculateDataBins( + clinicalDataBinFilter, ClinicalDataType.SAMPLE, clinicalData, sampleIds); + + List expected = + Arrays.asList( + createDataBin("<=", null, "1.0", 722), + createDataBin(null, "1.0", "2.0", 203), + createDataBin(null, "2.0", "5.0", 93), + createDataBin(null, "5.0", "10.0", 12), + createDataBin(null, "10.0", "30.0", 39), + createDataBin(">", "30.0", null, 57), + createDataBin("NA", null, null, 8)); + + testBinsIdentical(expected, dataBins); + } + + @Test + public void testLinearDataBinnerWithNA() { + String studyId = "blca_tcga"; + String attributeId = "LYMPH_NODE_EXAMINED_COUNT"; + String[] values = mockData.get("blca_tcga_LYMPH_NODE_EXAMINED_COUNT"); + ClinicalDataBinFilter clinicalDataBinFilter = new ClinicalDataBinFilter(); + clinicalDataBinFilter.setAttributeId(attributeId); + + List clinicalData = mockClinicalData(attributeId, studyId, values); + List patientIds = getCaseIds(clinicalData, true); + + List dataBins = + dataBinner.calculateDataBins( + clinicalDataBinFilter, ClinicalDataType.PATIENT, clinicalData, patientIds); + + List expected = + Arrays.asList( + createDataBin("<=", null, "5.0", 30), + createDataBin(null, "5.0", "10.0", 41), + createDataBin(null, "10.0", "15.0", 55), + createDataBin(null, "15.0", "20.0", 39), + createDataBin(null, "20.0", "25.0", 26), + createDataBin(null, "25.0", "30.0", 32), + createDataBin(null, "30.0", "35.0", 8), + createDataBin(null, "35.0", "40.0", 11), + createDataBin(null, "40.0", "45.0", 8), + createDataBin(null, "45.0", "50.0", 9), + createDataBin(null, "50.0", "55.0", 6), + createDataBin(null, "55.0", "60.0", 4), + createDataBin(null, "60.0", "65.0", 6), + createDataBin(">", "65.0", null, 28), + createDataBin("NA", null, null, 109)); + + testBinsIdentical(expected, dataBins); + } + + @Test + public void testLinearDataBinnerWithZeroIQR() { + String studyId = "impact"; + String attributeId = "DNA_INPUT"; + String[] values = mockData.get("impact_DNA_INPUT"); + ClinicalDataBinFilter clinicalDataBinFilter = new ClinicalDataBinFilter(); + clinicalDataBinFilter.setAttributeId(attributeId); + + List clinicalData = mockClinicalData(attributeId, studyId, values); + List sampleIds = getCaseIds(clinicalData, false); + + List dataBins = + dataBinner.calculateDataBins( + clinicalDataBinFilter, ClinicalDataType.SAMPLE, clinicalData, sampleIds); + + Assert.assertEquals(19, dataBins.size()); + + Assert.assertEquals("<=", dataBins.get(0).getSpecialValue()); + Assert.assertEquals(new BigDecimal("60.0"), dataBins.get(0).getEnd()); + + Assert.assertEquals(new BigDecimal("60.0"), dataBins.get(1).getStart()); + Assert.assertEquals(new BigDecimal("70.0"), dataBins.get(1).getEnd()); + + Assert.assertEquals(new BigDecimal("230.0"), dataBins.get(18).getStart()); + Assert.assertEquals(new BigDecimal("240.0"), dataBins.get(18).getEnd()); + } + + @Test + public void testLinearDataBinnerWithAlwaysZeroIQR() { + String studyId = "unknown"; + String attributeId = "DNA_INPUT"; + String[] values = mockData.get("recursively_always_zero_IQR"); + ClinicalDataBinFilter clinicalDataBinFilter = new ClinicalDataBinFilter(); + clinicalDataBinFilter.setAttributeId(attributeId); + + List clinicalData = mockClinicalData(attributeId, studyId, values); + List sampleIds = getCaseIds(clinicalData, false); + + List dataBins = + dataBinner.calculateDataBins( + clinicalDataBinFilter, ClinicalDataType.SAMPLE, clinicalData, sampleIds, 5); + + Assert.assertEquals(1, dataBins.size()); + + Assert.assertEquals("<=", dataBins.get(0).getSpecialValue()); + Assert.assertEquals(new BigDecimal("66"), dataBins.get(0).getEnd()); + Assert.assertEquals( + "all values should be included in a single bin", + values.length, + dataBins.get(0).getCount().intValue()); + } + + @Test + public void testDiscreteDataBinner() { + String studyId = "acyc_fmi_2014"; + String attributeId = "ACTIONABLE_ALTERATIONS"; + String[] values = mockData.get("acyc_fmi_2014_ACTIONABLE_ALTERATIONS"); + ClinicalDataBinFilter clinicalDataBinFilter = new ClinicalDataBinFilter(); + clinicalDataBinFilter.setAttributeId(attributeId); + + List clinicalData = mockClinicalData(attributeId, studyId, values); + List sampleIds = getCaseIds(clinicalData, false); + + List dataBins = + dataBinner.calculateDataBins( + clinicalDataBinFilter, ClinicalDataType.SAMPLE, clinicalData, sampleIds); + + Assert.assertEquals(5, dataBins.size()); + + Assert.assertEquals(new BigDecimal("0.0"), dataBins.get(0).getStart()); + Assert.assertEquals(new BigDecimal("0.0"), dataBins.get(0).getEnd()); + Assert.assertEquals(16, dataBins.get(0).getCount().intValue()); + + Assert.assertEquals(new BigDecimal("1.0"), dataBins.get(1).getStart()); + Assert.assertEquals(new BigDecimal("1.0"), dataBins.get(1).getEnd()); + Assert.assertEquals(6, dataBins.get(1).getCount().intValue()); + + Assert.assertEquals(new BigDecimal("2.0"), dataBins.get(2).getStart()); + Assert.assertEquals(new BigDecimal("2.0"), dataBins.get(2).getEnd()); + Assert.assertEquals(4, dataBins.get(2).getCount().intValue()); + + Assert.assertEquals(new BigDecimal("3.0"), dataBins.get(3).getStart()); + Assert.assertEquals(new BigDecimal("3.0"), dataBins.get(3).getEnd()); + Assert.assertEquals(1, dataBins.get(3).getCount().intValue()); + + Assert.assertEquals(new BigDecimal("5.0"), dataBins.get(4).getStart()); + Assert.assertEquals(new BigDecimal("5.0"), dataBins.get(4).getEnd()); + Assert.assertEquals(1, dataBins.get(4).getCount().intValue()); + } + + @Test + public void testScientificDataBinner() { + String studyId = "blca_dfarber_mskcc_2014"; + String attributeId = "SILENT_RATE"; + String[] values = mockData.get("blca_dfarber_mskcc_2014_SILENT_RATE"); + String[] samplesWithNoClinicalData = { + "NA_SAMPLE_01", "NA_SAMPLE_02", "NA_SAMPLE_03", "NA_SAMPLE_04", "NA_SAMPLE_05", "NA_SAMPLE_06" + }; + ClinicalDataBinFilter clinicalDataBinFilter = new ClinicalDataBinFilter(); + clinicalDataBinFilter.setAttributeId(attributeId); + + List clinicalData = mockClinicalData(attributeId, studyId, values); + List sampleIds = getCaseIds(clinicalData, false); + sampleIds.addAll(Arrays.asList(samplesWithNoClinicalData)); + + List dataBins = + dataBinner.calculateDataBins( + clinicalDataBinFilter, ClinicalDataType.SAMPLE, clinicalData, sampleIds); + + Assert.assertEquals(5, dataBins.size()); + + Assert.assertEquals(new BigDecimal("1.0e-8"), dataBins.get(0).getStart()); + Assert.assertEquals(new BigDecimal("1.0e-7"), dataBins.get(0).getEnd()); + Assert.assertEquals(1, dataBins.get(0).getCount().intValue()); + + Assert.assertEquals(new BigDecimal("1.0e-7"), dataBins.get(1).getStart()); + Assert.assertEquals(new BigDecimal("1.0e-6"), dataBins.get(1).getEnd()); + Assert.assertEquals(16, dataBins.get(1).getCount().intValue()); + + Assert.assertEquals(new BigDecimal("1.0e-6"), dataBins.get(2).getStart()); + Assert.assertEquals( + new BigDecimal("1.0e-5") + .compareTo(dataBins.get(2).getEnd().round(new MathContext(5, RoundingMode.CEILING))), + 0); + Assert.assertEquals(32, dataBins.get(2).getCount().intValue()); + + Assert.assertEquals(">", dataBins.get(3).getSpecialValue()); + Assert.assertEquals( + new BigDecimal("1.0e-5") + .compareTo(dataBins.get(3).getStart().round(new MathContext(5, RoundingMode.CEILING))), + 0); + Assert.assertEquals(1, dataBins.get(3).getCount().intValue()); + + Assert.assertEquals("NA", dataBins.get(4).getSpecialValue()); + Assert.assertEquals(3 + 6, dataBins.get(4).getCount().intValue()); + } + + @Test + public void testLogScaleNoOutlierDataBinner() { + String studyId = "llg_tcga"; + String attributeId = "egfr_mrna_expression"; + String[] values = mockData.get("llg_tcga_egfr_mrna_expression"); + ClinicalDataBinFilter clinicalDataBinFilter = new ClinicalDataBinFilter(); + clinicalDataBinFilter.setAttributeId(attributeId); + + List clinicalData = mockClinicalData(attributeId, studyId, values); + List sampleIds = getCaseIds(clinicalData, false); + + List dataBins = + dataBinner.calculateDataBins( + clinicalDataBinFilter, ClinicalDataType.SAMPLE, clinicalData, sampleIds); + + Assert.assertEquals(8, dataBins.size()); + + Assert.assertEquals(new BigDecimal("31.0"), dataBins.get(0).getStart()); + Assert.assertEquals(new BigDecimal("100.0"), dataBins.get(0).getEnd()); + Assert.assertEquals(6, dataBins.get(0).getCount().intValue()); + + Assert.assertEquals(new BigDecimal("100.0"), dataBins.get(1).getStart()); + Assert.assertEquals(new BigDecimal("316.0"), dataBins.get(1).getEnd()); + Assert.assertEquals(25, dataBins.get(1).getCount().intValue()); + + Assert.assertEquals(new BigDecimal("316.0"), dataBins.get(2).getStart()); + Assert.assertEquals(new BigDecimal("1000.0"), dataBins.get(2).getEnd()); + Assert.assertEquals(84, dataBins.get(2).getCount().intValue()); + + Assert.assertEquals(new BigDecimal("1000.0"), dataBins.get(3).getStart()); + Assert.assertEquals(new BigDecimal("3162.0"), dataBins.get(3).getEnd()); + Assert.assertEquals(222, dataBins.get(3).getCount().intValue()); + + Assert.assertEquals(new BigDecimal("3162.0"), dataBins.get(4).getStart()); + Assert.assertEquals(new BigDecimal("10000.0"), dataBins.get(4).getEnd()); + Assert.assertEquals(148, dataBins.get(4).getCount().intValue()); + + Assert.assertEquals(new BigDecimal("10000.0"), dataBins.get(5).getStart()); + Assert.assertEquals(new BigDecimal("31622.0"), dataBins.get(5).getEnd()); + Assert.assertEquals(30, dataBins.get(5).getCount().intValue()); + + Assert.assertEquals(new BigDecimal("31622.0"), dataBins.get(6).getStart()); + Assert.assertEquals(new BigDecimal("100000.0"), dataBins.get(6).getEnd()); + Assert.assertEquals(13, dataBins.get(6).getCount().intValue()); + + Assert.assertEquals(">", dataBins.get(7).getSpecialValue()); + Assert.assertEquals(new BigDecimal("100000.0"), dataBins.get(7).getStart()); + Assert.assertEquals(2, dataBins.get(7).getCount().intValue()); + } + + @Test + public void testLogScaleDataBinner() { + String studyId = "ampca_bcm_2016"; + String attributeId = "DAYS_TO_LAST_FOLLOWUP"; + String[] values = mockData.get("ampca_bcm_2016_DAYS_TO_LAST_FOLLOWUP"); + ClinicalDataBinFilter clinicalDataBinFilter = new ClinicalDataBinFilter(); + clinicalDataBinFilter.setAttributeId(attributeId); + + List clinicalData = mockClinicalData(attributeId, studyId, values); + List patientIds = getCaseIds(clinicalData, true); + + List dataBins = + dataBinner.calculateDataBins( + clinicalDataBinFilter, ClinicalDataType.PATIENT, clinicalData, patientIds); + + Assert.assertEquals(7, dataBins.size()); + + Assert.assertEquals("<=", dataBins.get(0).getSpecialValue()); + Assert.assertEquals(new BigDecimal("10.0"), dataBins.get(0).getEnd()); + Assert.assertEquals(1, dataBins.get(0).getCount().intValue()); + + Assert.assertEquals(new BigDecimal("10.0"), dataBins.get(1).getStart()); + Assert.assertEquals(new BigDecimal("31.0"), dataBins.get(1).getEnd()); + Assert.assertEquals(3, dataBins.get(1).getCount().intValue()); + + Assert.assertEquals(new BigDecimal("31.0"), dataBins.get(2).getStart()); + Assert.assertEquals(new BigDecimal("100.0"), dataBins.get(2).getEnd()); + Assert.assertEquals(5, dataBins.get(2).getCount().intValue()); + + Assert.assertEquals(new BigDecimal("100.0"), dataBins.get(3).getStart()); + Assert.assertEquals(new BigDecimal("316.0"), dataBins.get(3).getEnd()); + Assert.assertEquals(23, dataBins.get(3).getCount().intValue()); + + Assert.assertEquals(new BigDecimal("316.0"), dataBins.get(4).getStart()); + Assert.assertEquals(new BigDecimal("1000.0"), dataBins.get(4).getEnd()); + Assert.assertEquals(67, dataBins.get(4).getCount().intValue()); + + Assert.assertEquals(new BigDecimal("1000.0"), dataBins.get(5).getStart()); + Assert.assertEquals(new BigDecimal("3162.0"), dataBins.get(5).getEnd()); + Assert.assertEquals(55, dataBins.get(5).getCount().intValue()); + + Assert.assertEquals(new BigDecimal("3162.0"), dataBins.get(6).getStart()); + Assert.assertEquals(new BigDecimal("10000.0"), dataBins.get(6).getEnd()); + Assert.assertEquals(6, dataBins.get(6).getCount().intValue()); + } + + @Test + public void testLogScaleDisabledDataBinner() { + String studyId = "ampca_bcm_2016"; + String attributeId = "DAYS_TO_LAST_FOLLOWUP"; + String[] values = mockData.get("ampca_bcm_2016_DAYS_TO_LAST_FOLLOWUP"); + ClinicalDataBinFilter clinicalDataBinFilter = new ClinicalDataBinFilter(); + clinicalDataBinFilter.setAttributeId(attributeId); + clinicalDataBinFilter.setDisableLogScale(true); + + List clinicalData = mockClinicalData(attributeId, studyId, values); + List patientIds = getCaseIds(clinicalData, true); + + List dataBins = + dataBinner.calculateDataBins( + clinicalDataBinFilter, ClinicalDataType.PATIENT, clinicalData, patientIds); + + Assert.assertEquals(17, dataBins.size()); + + Assert.assertEquals("<=", dataBins.get(0).getSpecialValue()); + Assert.assertEquals(new BigDecimal("200.0"), dataBins.get(0).getEnd()); + Assert.assertEquals(17, dataBins.get(0).getCount().intValue()); + + Assert.assertEquals(new BigDecimal("200.0"), dataBins.get(1).getStart()); + Assert.assertEquals(new BigDecimal("400.0"), dataBins.get(1).getEnd()); + Assert.assertEquals(24, dataBins.get(1).getCount().intValue()); + + Assert.assertEquals(new BigDecimal("3200.0"), dataBins.get(16).getStart()); + Assert.assertEquals(">", dataBins.get(16).getSpecialValue()); + Assert.assertEquals(6, dataBins.get(16).getCount().intValue()); + } + + @Test + public void testNegativeLogScaleDataBinner() { + String studyId = "acc_tcga"; + String attributeId = "DAYS_TO_BIRTH"; + String[] values = mockData.get("acc_tcga_DAYS_TO_BIRTH"); + ClinicalDataBinFilter clinicalDataBinFilter = new ClinicalDataBinFilter(); + clinicalDataBinFilter.setAttributeId(attributeId); + + List clinicalData = mockClinicalData(attributeId, studyId, values); + List patientIds = getCaseIds(clinicalData, true); + + List dataBins = + dataBinner.calculateDataBins( + clinicalDataBinFilter, ClinicalDataType.PATIENT, clinicalData, patientIds); + + Assert.assertEquals(2, dataBins.size()); + + Assert.assertEquals(new BigDecimal("-31622.0"), dataBins.get(0).getStart()); + Assert.assertEquals(new BigDecimal("-10000.0"), dataBins.get(0).getEnd()); + Assert.assertEquals(78, dataBins.get(0).getCount().intValue()); + + Assert.assertEquals(new BigDecimal("-10000.0"), dataBins.get(1).getStart()); + Assert.assertEquals(new BigDecimal("-3162.0"), dataBins.get(1).getEnd()); + Assert.assertEquals(14, dataBins.get(1).getCount().intValue()); + } + + @Test + public void testLogScaleDataBinnerWithSpecialOutliers() { + String studyId = "genie"; + String attributeId = "INT_DOD"; + String[] values = mockData.get("genie_INT_DOD"); + ClinicalDataBinFilter clinicalDataBinFilter = new ClinicalDataBinFilter(); + clinicalDataBinFilter.setAttributeId(attributeId); + + List clinicalData = mockClinicalData(attributeId, studyId, values); + List patientIds = getCaseIds(clinicalData, true); + + List dataBins = + dataBinner.calculateDataBins( + clinicalDataBinFilter, ClinicalDataType.PATIENT, clinicalData, patientIds); + + Assert.assertEquals(5, dataBins.size()); + + Assert.assertEquals("<=", dataBins.get(0).getSpecialValue()); + Assert.assertEquals(new BigDecimal("6570.0"), dataBins.get(0).getEnd()); + Assert.assertEquals(8, dataBins.get(0).getCount().intValue()); + + Assert.assertEquals(new BigDecimal("6570.0"), dataBins.get(1).getStart()); + Assert.assertEquals(new BigDecimal("10000.0"), dataBins.get(1).getEnd()); + + Assert.assertEquals(new BigDecimal("10000.0"), dataBins.get(2).getStart()); + Assert.assertEquals(new BigDecimal("31622.0"), dataBins.get(2).getEnd()); + + Assert.assertEquals(new BigDecimal("31622.0"), dataBins.get(3).getStart()); + Assert.assertEquals(new BigDecimal("32485.0"), dataBins.get(3).getEnd()); + + Assert.assertEquals(new BigDecimal("32485.0"), dataBins.get(4).getStart()); + Assert.assertEquals(">", dataBins.get(4).getSpecialValue()); + Assert.assertEquals(5, dataBins.get(4).getCount().intValue()); + } + + @Test + public void testNegativeLogScaleDisabledDataBinner() { + String studyId = "acc_tcga"; + String attributeId = "DAYS_TO_BIRTH"; + String[] values = mockData.get("acc_tcga_DAYS_TO_BIRTH"); + ClinicalDataBinFilter clinicalDataBinFilter = new ClinicalDataBinFilter(); + clinicalDataBinFilter.setAttributeId(attributeId); + clinicalDataBinFilter.setDisableLogScale(true); + + List clinicalData = mockClinicalData(attributeId, studyId, values); + List patientIds = getCaseIds(clinicalData, true); + + List dataBins = + dataBinner.calculateDataBins( + clinicalDataBinFilter, ClinicalDataType.PATIENT, clinicalData, patientIds); + + Assert.assertEquals(14, dataBins.size()); + + Assert.assertEquals("<=", dataBins.get(0).getSpecialValue()); + Assert.assertEquals(new BigDecimal("-30000.0"), dataBins.get(0).getEnd()); + + Assert.assertEquals(new BigDecimal("-6000.0"), dataBins.get(13).getStart()); + Assert.assertEquals(">", dataBins.get(13).getSpecialValue()); + } + + private List mockClinicalData(String attributeId, String studyId, String[] values) { + List clinicalDataList = new ArrayList<>(); + + for (int index = 0; index < values.length; index++) { + ClinicalData clinicalData = new ClinicalData(); + + clinicalData.setAttrId(attributeId); + clinicalData.setStudyId(studyId); + clinicalData.setSampleId("sample_" + index); + clinicalData.setPatientId("patient_" + index); + clinicalData.setAttrValue(values[index]); + + clinicalDataList.add(clinicalData); + } + + return clinicalDataList; + } + + private DataBin createDataBin(String specialValue, String start, String end, int count) { + DataBin dataBin = new DataBin(); + dataBin.setCount(count); + if (specialValue != null) { + dataBin.setSpecialValue(specialValue); + } + if (start != null) { + dataBin.setStart(new BigDecimal(start)); + } + if (end != null) { + dataBin.setEnd(new BigDecimal(end)); + } + return dataBin; + } + + private void testBinsIdentical(List expected, List observed) { + Assert.assertEquals(expected.size(), observed.size()); + IntStream.range(0, expected.size()) + .forEach( + i -> { + DataBin e = expected.get(i); + DataBin o = observed.get(i); + Assert.assertTrue( + "Element " + i + " is not correct.", new ReflectionEquals(e).matches(o)); + }); + } +} diff --git a/src/test/java/org/cbioportal/legacy/web/util/SelectMockitoArgumentMatcher.java b/src/test/java/org/cbioportal/legacy/web/util/SelectMockitoArgumentMatcher.java new file mode 100644 index 00000000000..e26b7d576be --- /dev/null +++ b/src/test/java/org/cbioportal/legacy/web/util/SelectMockitoArgumentMatcher.java @@ -0,0 +1,26 @@ +package org.cbioportal.legacy.web.util; + +import org.cbioportal.legacy.model.util.Select; +import org.mockito.ArgumentMatcher; + +public class SelectMockitoArgumentMatcher implements ArgumentMatcher { - private String checkWhat; - - public SelectMockitoArgumentMatcher(String checkWhat) { - this.checkWhat = checkWhat; - } - - @Override - public boolean matches(Select select) { - switch (checkWhat) { - case "ALL": - return select.hasAll(); - case "EMPTY": - return select.hasNone(); - case "SOME": - return select.hasValues(); - default: - return false; - } - } -} diff --git a/src/test/java/org/cbioportal/web/util/StudyViewFilterApplierTest.java b/src/test/java/org/cbioportal/web/util/StudyViewFilterApplierTest.java deleted file mode 100644 index d71ea23157c..00000000000 --- a/src/test/java/org/cbioportal/web/util/StudyViewFilterApplierTest.java +++ /dev/null @@ -1,1109 +0,0 @@ -package org.cbioportal.web.util; - -import com.fasterxml.jackson.databind.ObjectMapper; -import org.cbioportal.model.CNA; -import org.cbioportal.model.ClinicalAttribute; -import org.cbioportal.model.ClinicalData; -import org.cbioportal.model.DiscreteCopyNumberData; -import org.cbioportal.model.Gene; -import org.cbioportal.model.GeneFilter; -import org.cbioportal.model.GeneFilterQuery; -import org.cbioportal.model.GenericAssayData; -import org.cbioportal.model.MolecularProfile; -import org.cbioportal.model.MolecularProfile.MolecularAlterationType; -import org.cbioportal.model.MolecularProfileCaseIdentifier; -import org.cbioportal.model.Mutation; -import org.cbioportal.model.Patient; -import org.cbioportal.model.Sample; -import org.cbioportal.model.util.Select; -import org.cbioportal.service.ClinicalAttributeService; -import org.cbioportal.service.ClinicalDataService; -import org.cbioportal.service.DiscreteCopyNumberService; -import org.cbioportal.service.GenePanelService; -import org.cbioportal.service.GeneService; -import org.cbioportal.service.GenericAssayService; -import org.cbioportal.service.MolecularDataService; -import org.cbioportal.service.MolecularProfileService; -import org.cbioportal.service.MutationService; -import org.cbioportal.service.PatientService; -import org.cbioportal.service.SampleListService; -import org.cbioportal.service.SampleService; -import org.cbioportal.service.StructuralVariantService; -import org.cbioportal.service.impl.CustomDataServiceImpl; -import org.cbioportal.service.util.MolecularProfileUtil; -import org.cbioportal.service.util.SessionServiceRequestHandler; -import org.cbioportal.web.config.TestConfig; -import org.cbioportal.web.parameter.ClinicalDataFilter; -import org.cbioportal.web.parameter.DataFilterValue; -import org.cbioportal.web.parameter.GeneIdType; -import org.cbioportal.web.parameter.GenericAssayDataFilter; -import org.cbioportal.web.parameter.MutationDataFilter; -import org.cbioportal.web.parameter.MutationOption; -import org.cbioportal.web.parameter.Projection; -import org.cbioportal.web.parameter.SampleIdentifier; -import org.cbioportal.web.parameter.StudyViewFilter; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; -import org.mockito.Spy; -import org.springframework.context.ApplicationContext; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; -import org.springframework.util.ResourceUtils; - -import java.io.IOException; -import java.math.BigDecimal; -import java.nio.file.Files; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashSet; -import java.util.List; - -import static com.google.common.collect.ImmutableList.of; -import static java.util.stream.Collectors.toList; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyList; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.ArgumentMatchers.isNull; -import static org.mockito.Mockito.when; - -@RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration(classes = TestConfig.class) -public class StudyViewFilterApplierTest { - - public static final String STUDY_ID = "study_id"; - public static final String SAMPLE_ID1 = "sample_id1"; - public static final String SAMPLE_ID2 = "sample_id2"; - public static final String SAMPLE_ID3 = "sample_id3"; - public static final String SAMPLE_ID4 = "sample_id4"; - public static final String SAMPLE_ID5 = "sample_id5"; - public static final String PATIENT_ID1 = "patient_id1"; - public static final String PATIENT_ID2 = "patient_id2"; - public static final String PATIENT_ID3 = "patient_id3"; - public static final String PATIENT_ID4 = "patient_id4"; - public static final String CLINICAL_ATTRIBUTE_ID_1 = "attribute_id1"; - public static final String CLINICAL_ATTRIBUTE_ID_2 = "attribute_id2"; - public static final String CLINICAL_ATTRIBUTE_ID_3 = "attribute_id3"; - public static final String CUSTOM_DATASET_ID = "custom_dataset_id"; - public static final Integer ENTREZ_GENE_ID_1 = 1; - public static final Integer ENTREZ_GENE_ID_2 = 2; - public static final String HUGO_GENE_SYMBOL_1 = "HUGO_GENE_SYMBOL_1"; - public static final String HUGO_GENE_SYMBOL_2 = "HUGO_GENE_SYMBOL_2"; - public static final String MOLECULAR_PROFILE_ID_1 = "molecular_profile_id1"; - public static final String MOLECULAR_PROFILE_ID_2 = "molecular_profile_id2"; - public static final String MUTATION_TYPE_1 = "mutation_type_1"; - public static final String MUTATION_TYPE_2 = "mutation_type_2"; - - @InjectMocks - private StudyViewFilterApplier studyViewFilterApplier; - - @Mock - private ApplicationContext applicationContext; - - @Mock - private SampleService sampleService; - @Mock - private PatientService patientService; - @Mock - private ClinicalDataService clinicalDataService; - @Mock - private MutationService mutationService; - @Mock - private DiscreteCopyNumberService discreteCopyNumberService; - @Mock - private MolecularProfileService molecularProfileService; - @Mock - private GenePanelService genePanelService; - @Mock - private GeneService geneService; - @Mock - private ClinicalAttributeService clinicalAttributeService; - @Mock - private MolecularDataService molecularDataService; - @Mock - private SampleListService sampleListService; - @Mock - private GenericAssayService genericAssayService; - @Mock - private StructuralVariantService structuralVariantService; - // Do not mock utility classes, we also want to test their functionality - @Spy - @InjectMocks - private ClinicalDataEqualityFilterApplier clinicalDataEqualityFilterApplier; - @Spy - @InjectMocks - private ClinicalDataIntervalFilterApplier clinicalDataIntervalFilterApplier; - @Spy - @InjectMocks - private StudyViewFilterUtil studyViewFilterUtil; - @Spy - @InjectMocks - private DataBinner dataBinner; - @Spy - @InjectMocks - private DataBinHelper dataBinHelper; - @Spy - @InjectMocks - private MolecularProfileUtil molecularProfileUtil; - - @Mock - private SessionServiceRequestHandler sessionServiceRequestHandler; - @Spy - private ObjectMapper sessionServiceObjectMapper = new ObjectMapper(); - - @Spy - @InjectMocks - private CustomDataServiceImpl customDataService; - - @Spy - @InjectMocks - private CustomDataFilterApplier customDataFilterApplier; - - @Before - public void setup() { - MockitoAnnotations.initMocks(this); - when(applicationContext.getBean(StudyViewFilterApplier.class)).thenReturn(studyViewFilterApplier); - } - - @Test - public void apply() throws Exception { - - List studyIds = new ArrayList<>(); - studyIds.add(STUDY_ID); - studyIds.add(STUDY_ID); - studyIds.add(STUDY_ID); - studyIds.add(STUDY_ID); - studyIds.add(STUDY_ID); - - StudyViewFilter studyViewFilter = new StudyViewFilter(); - List sampleIds = new ArrayList<>(); - sampleIds.add(SAMPLE_ID1); - sampleIds.add(SAMPLE_ID2); - sampleIds.add(SAMPLE_ID3); - sampleIds.add(SAMPLE_ID4); - sampleIds.add(SAMPLE_ID5); - - List sampleIdentifiers = new ArrayList<>(); - SampleIdentifier sampleIdentifier1 = new SampleIdentifier(); - sampleIdentifier1.setSampleId(SAMPLE_ID1); - sampleIdentifier1.setStudyId(STUDY_ID); - sampleIdentifiers.add(sampleIdentifier1); - SampleIdentifier sampleIdentifier2 = new SampleIdentifier(); - sampleIdentifier2.setSampleId(SAMPLE_ID2); - sampleIdentifier2.setStudyId(STUDY_ID); - sampleIdentifiers.add(sampleIdentifier2); - SampleIdentifier sampleIdentifier3 = new SampleIdentifier(); - sampleIdentifier3.setSampleId(SAMPLE_ID3); - sampleIdentifier3.setStudyId(STUDY_ID); - sampleIdentifiers.add(sampleIdentifier3); - SampleIdentifier sampleIdentifier4 = new SampleIdentifier(); - sampleIdentifier4.setSampleId(SAMPLE_ID4); - sampleIdentifier4.setStudyId(STUDY_ID); - sampleIdentifiers.add(sampleIdentifier4); - SampleIdentifier sampleIdentifier5 = new SampleIdentifier(); - sampleIdentifier5.setSampleId(SAMPLE_ID5); - sampleIdentifier5.setStudyId(STUDY_ID); - sampleIdentifiers.add(sampleIdentifier5); - studyViewFilter.setSampleIdentifiers(sampleIdentifiers); - List clinicalDataEqualityFilters = new ArrayList<>(); - ClinicalDataFilter clinicalDataEqualityFilter1 = new ClinicalDataFilter(); - clinicalDataEqualityFilter1.setAttributeId(CLINICAL_ATTRIBUTE_ID_1); - DataFilterValue filterValue = new DataFilterValue(); - filterValue.setValue("value1"); - clinicalDataEqualityFilter1.setValues(Arrays.asList(filterValue)); - clinicalDataEqualityFilters.add(clinicalDataEqualityFilter1); - ClinicalDataFilter clinicalDataEqualityFilter2 = new ClinicalDataFilter(); - clinicalDataEqualityFilter2.setAttributeId(CLINICAL_ATTRIBUTE_ID_2); - - DataFilterValue filterValue1 = new DataFilterValue(); - filterValue1.setValue("value1"); - DataFilterValue filterValue2 = new DataFilterValue(); - filterValue2.setValue("NA"); - clinicalDataEqualityFilter2.setValues(Arrays.asList(filterValue1, filterValue2)); - clinicalDataEqualityFilters.add(clinicalDataEqualityFilter2); - studyViewFilter.setClinicalDataFilters(clinicalDataEqualityFilters); - - boolean includeDriver = true; - boolean includeVUS = true; - boolean includeUnknownOncogenicity = true; - boolean includeGermline = true; - boolean includeSomatic = true; - boolean includeUnknownStatus = true; - Select selectedTiers = Select.none(); - boolean includeUnknownTier = true; - List geneFilters = new ArrayList<>(); - GeneFilter mutationGeneFilter = new GeneFilter(); - mutationGeneFilter.setMolecularProfileIds(new HashSet<>(Arrays.asList(MOLECULAR_PROFILE_ID_1))); - - GeneFilterQuery geneFilterQuery1 = new GeneFilterQuery("HUGO_GENE_SYMBOL_1", null, - null, includeDriver, includeVUS, includeUnknownOncogenicity, selectedTiers, includeUnknownTier, - includeGermline, includeSomatic, includeUnknownStatus); - List> q1 = new ArrayList<>(); - List q2 = new ArrayList<>(); - q2.add(geneFilterQuery1); - q1.add(q2); - mutationGeneFilter.setGeneQueries(q1); - - GeneFilter copyNumberGeneFilter = new GeneFilter(); - copyNumberGeneFilter.setMolecularProfileIds(new HashSet<>(Arrays.asList(MOLECULAR_PROFILE_ID_2))); - GeneFilterQuery geneFilterQuery2 = new GeneFilterQuery("HUGO_GENE_SYMBOL_2", null, - Arrays.asList(CNA.HOMDEL), includeDriver, includeVUS, includeUnknownOncogenicity, selectedTiers, - includeUnknownTier,includeGermline, includeSomatic, includeUnknownStatus); - List> q3 = new ArrayList<>(); - List q4 = new ArrayList<>(); - q4.add(geneFilterQuery2); - q3.add(q4); - copyNumberGeneFilter.setGeneQueries(q3); - - geneFilters.add(mutationGeneFilter); - geneFilters.add(copyNumberGeneFilter); - studyViewFilter.setGeneFilters(geneFilters); - - List samples = new ArrayList<>(); - Sample sample1 = new Sample(); - sample1.setStableId(SAMPLE_ID1); - sample1.setCancerStudyIdentifier(STUDY_ID); - samples.add(sample1); - Sample sample2 = new Sample(); - sample2.setStableId(SAMPLE_ID2); - sample2.setCancerStudyIdentifier(STUDY_ID); - samples.add(sample2); - Sample sample3 = new Sample(); - sample3.setStableId(SAMPLE_ID3); - sample3.setCancerStudyIdentifier(STUDY_ID); - samples.add(sample3); - Sample sample4 = new Sample(); - sample4.setStableId(SAMPLE_ID4); - sample4.setCancerStudyIdentifier(STUDY_ID); - samples.add(sample4); - Sample sample5 = new Sample(); - sample5.setStableId(SAMPLE_ID5); - sample5.setCancerStudyIdentifier(STUDY_ID); - samples.add(sample5); - - List patientIds = new ArrayList<>(); - patientIds.add(PATIENT_ID1); - patientIds.add(PATIENT_ID2); - patientIds.add(PATIENT_ID3); - patientIds.add(PATIENT_ID4); - - List patients = new ArrayList<>(); - Patient patient1 = new Patient(); - patient1.setStableId(PATIENT_ID1); - patient1.setCancerStudyIdentifier(STUDY_ID); - patients.add(patient1); - Patient patient2 = new Patient(); - patient2.setStableId(PATIENT_ID2); - patient2.setCancerStudyIdentifier(STUDY_ID); - patients.add(patient2); - Patient patient3 = new Patient(); - patient3.setStableId(PATIENT_ID3); - patient3.setCancerStudyIdentifier(STUDY_ID); - patients.add(patient3); - Patient patient4 = new Patient(); - patient4.setStableId(PATIENT_ID4); - patient4.setCancerStudyIdentifier(STUDY_ID); - patients.add(patient4); - - when(sampleService.fetchSamples(studyIds, sampleIds, "ID")).thenReturn(samples); - when(patientService.getPatientsOfSamples(studyIds, sampleIds)).thenReturn(patients); - - List patientClinicalDataList = new ArrayList<>(); - ClinicalData patientClinicalData1 = new ClinicalData(); - patientClinicalData1.setAttrId(CLINICAL_ATTRIBUTE_ID_2); - patientClinicalData1.setAttrValue("value2"); - patientClinicalData1.setPatientId(PATIENT_ID1); - patientClinicalData1.setSampleId(SAMPLE_ID1); - patientClinicalData1.setStudyId(STUDY_ID); - patientClinicalDataList.add(patientClinicalData1); - ClinicalData patientClinicalData2 = new ClinicalData(); - patientClinicalData2.setAttrId(CLINICAL_ATTRIBUTE_ID_2); - patientClinicalData2.setAttrValue("N/A"); - patientClinicalData2.setPatientId(PATIENT_ID2); - patientClinicalData2.setSampleId(SAMPLE_ID2); - patientClinicalData2.setStudyId(STUDY_ID); - patientClinicalDataList.add(patientClinicalData2); - ClinicalData patientClinicalData3 = new ClinicalData(); - patientClinicalData3.setAttrId(CLINICAL_ATTRIBUTE_ID_2); - patientClinicalData3.setAttrValue("value3"); - patientClinicalData3.setPatientId(PATIENT_ID3); - patientClinicalData3.setSampleId(SAMPLE_ID3); - patientClinicalData3.setStudyId(STUDY_ID); - patientClinicalDataList.add(patientClinicalData3); - - when(clinicalDataService.getPatientClinicalDataDetailedToSample( - Arrays.asList(STUDY_ID, STUDY_ID, STUDY_ID, STUDY_ID), patientIds, - Arrays.asList(CLINICAL_ATTRIBUTE_ID_1, CLINICAL_ATTRIBUTE_ID_2))).thenReturn(patientClinicalDataList); - - List updatedPatientIds = new ArrayList<>(); - updatedPatientIds.add(PATIENT_ID1); - updatedPatientIds.add(PATIENT_ID2); - updatedPatientIds.add(PATIENT_ID4); - - List updatedSamples = new ArrayList<>(); - updatedSamples.add(sample1); - updatedSamples.add(sample2); - updatedSamples.add(sample4); - updatedSamples.add(sample5); - - when(sampleService.getSamplesOfPatientsInMultipleStudies(Arrays.asList(STUDY_ID, STUDY_ID, STUDY_ID), - updatedPatientIds, "ID")).thenReturn(updatedSamples); - - List sampleClinicalDataList = new ArrayList<>(); - ClinicalData sampleClinicalData1 = new ClinicalData(); - sampleClinicalData1.setAttrId(CLINICAL_ATTRIBUTE_ID_1); - sampleClinicalData1.setAttrValue("value1"); - sampleClinicalData1.setSampleId(SAMPLE_ID1); - sampleClinicalData1.setStudyId(STUDY_ID); - sampleClinicalDataList.add(sampleClinicalData1); - ClinicalData sampleClinicalData2 = new ClinicalData(); - sampleClinicalData2.setAttrId(CLINICAL_ATTRIBUTE_ID_1); - sampleClinicalData2.setAttrValue("value1"); - sampleClinicalData2.setSampleId(SAMPLE_ID2); - sampleClinicalData2.setStudyId(STUDY_ID); - sampleClinicalDataList.add(sampleClinicalData2); - ClinicalData sampleClinicalData3 = new ClinicalData(); - sampleClinicalData3.setAttrId(CLINICAL_ATTRIBUTE_ID_1); - sampleClinicalData3.setAttrValue("NAN"); - sampleClinicalData3.setSampleId(SAMPLE_ID3); - sampleClinicalData3.setStudyId(STUDY_ID); - sampleClinicalDataList.add(sampleClinicalData3); - ClinicalData sampleClinicalData4 = new ClinicalData(); - sampleClinicalData4.setAttrId(CLINICAL_ATTRIBUTE_ID_1); - sampleClinicalData4.setAttrValue("value1"); - sampleClinicalData4.setSampleId(SAMPLE_ID4); - sampleClinicalData4.setStudyId(STUDY_ID); - sampleClinicalDataList.add(sampleClinicalData4); - ClinicalData sampleClinicalData5 = new ClinicalData(); - sampleClinicalData5.setAttrId(CLINICAL_ATTRIBUTE_ID_1); - sampleClinicalData5.setAttrValue("value1"); - sampleClinicalData5.setSampleId(SAMPLE_ID5); - sampleClinicalData5.setStudyId(STUDY_ID); - sampleClinicalDataList.add(sampleClinicalData5); - - List updatedSampleIds = new ArrayList<>(); - updatedSampleIds.add(SAMPLE_ID1); - updatedSampleIds.add(SAMPLE_ID2); - updatedSampleIds.add(SAMPLE_ID4); - updatedSampleIds.add(SAMPLE_ID5); - - when( - clinicalDataService.fetchClinicalData(Arrays.asList(STUDY_ID, STUDY_ID, STUDY_ID, STUDY_ID, STUDY_ID), - Arrays.asList(SAMPLE_ID1, SAMPLE_ID2, SAMPLE_ID3, SAMPLE_ID4, SAMPLE_ID5), - Arrays.asList(CLINICAL_ATTRIBUTE_ID_1, CLINICAL_ATTRIBUTE_ID_2), "SAMPLE", "SUMMARY")) - .thenReturn(sampleClinicalDataList); - - List updatedPatients = new ArrayList<>(); - Patient updatedPatient1 = new Patient(); - updatedPatient1.setStableId(PATIENT_ID1); - updatedPatient1.setCancerStudyIdentifier(STUDY_ID); - updatedPatients.add(updatedPatient1); - Patient updatedPatient2 = new Patient(); - updatedPatient2.setStableId(PATIENT_ID2); - updatedPatient2.setCancerStudyIdentifier(STUDY_ID); - updatedPatients.add(updatedPatient2); - Patient updatedPatient3 = new Patient(); - updatedPatient3.setStableId(PATIENT_ID4); - updatedPatient3.setCancerStudyIdentifier(STUDY_ID); - updatedPatients.add(updatedPatient3); - - when( - patientService.getPatientsOfSamples(Arrays.asList(STUDY_ID, STUDY_ID, STUDY_ID, STUDY_ID, STUDY_ID), - Arrays.asList(SAMPLE_ID1, SAMPLE_ID2, SAMPLE_ID3, SAMPLE_ID4, SAMPLE_ID5))) - .thenReturn(updatedPatients); - - MolecularProfile molecularProfile1 = new MolecularProfile(); - molecularProfile1.setStableId(MOLECULAR_PROFILE_ID_1); - molecularProfile1.setMolecularAlterationType(MolecularAlterationType.MUTATION_EXTENDED); - molecularProfile1.setCancerStudyIdentifier(STUDY_ID); - - MolecularProfile molecularProfile2 = new MolecularProfile(); - molecularProfile2.setStableId(MOLECULAR_PROFILE_ID_2); - molecularProfile2.setCancerStudyIdentifier(STUDY_ID); - molecularProfile2.setMolecularAlterationType(MolecularAlterationType.COPY_NUMBER_ALTERATION); - molecularProfile2.setDatatype("DISCRETE"); - - when(molecularProfileService.getMolecularProfilesInStudies(Arrays.asList(STUDY_ID), "SUMMARY")) - .thenReturn(Arrays.asList(molecularProfile1, molecularProfile2)); - - List mutations = new ArrayList<>(); - Mutation mutation1 = new Mutation(); - mutation1.setSampleId(SAMPLE_ID1); - mutation1.setStudyId(STUDY_ID); - mutations.add(mutation1); - Mutation mutation2 = new Mutation(); - mutation2.setSampleId(SAMPLE_ID2); - mutation2.setStudyId(STUDY_ID); - mutations.add(mutation2); - Mutation mutation3 = new Mutation(); - mutation3.setSampleId(SAMPLE_ID4); - mutation3.setStudyId(STUDY_ID); - mutations.add(mutation3); - Mutation mutation4 = new Mutation(); - mutation4.setSampleId(SAMPLE_ID4); - mutation4.setStudyId(STUDY_ID); - mutations.add(mutation4); - - Gene gene1 = new Gene(); - gene1.setEntrezGeneId(ENTREZ_GENE_ID_1); - gene1.setHugoGeneSymbol(HUGO_GENE_SYMBOL_1); - when(geneService.fetchGenes(Arrays.asList(HUGO_GENE_SYMBOL_1), GeneIdType.HUGO_GENE_SYMBOL.name(), - Projection.SUMMARY.name())).thenReturn(Arrays.asList(gene1)); - when(mutationService.getMutationsInMultipleMolecularProfilesByGeneQueries( - anyList(), anyList(), anyList(), anyString(), isNull(), isNull(), isNull(), isNull())).thenReturn(mutations); - - updatedSampleIds = new ArrayList<>(); - updatedSampleIds.add(SAMPLE_ID1); - updatedSampleIds.add(SAMPLE_ID2); - updatedSampleIds.add(SAMPLE_ID4); - - List molecularProfileCaseIdentifiers = new ArrayList<>(); - MolecularProfileCaseIdentifier profileCaseIdentifier1 = new MolecularProfileCaseIdentifier(); - profileCaseIdentifier1.setCaseId(SAMPLE_ID1); - profileCaseIdentifier1.setMolecularProfileId(MOLECULAR_PROFILE_ID_2); - molecularProfileCaseIdentifiers.add(profileCaseIdentifier1); - MolecularProfileCaseIdentifier profileCaseIdentifier2 = new MolecularProfileCaseIdentifier(); - profileCaseIdentifier2.setCaseId(SAMPLE_ID2); - profileCaseIdentifier2.setMolecularProfileId(MOLECULAR_PROFILE_ID_2); - molecularProfileCaseIdentifiers.add(profileCaseIdentifier2); - MolecularProfileCaseIdentifier profileCaseIdentifier3 = new MolecularProfileCaseIdentifier(); - profileCaseIdentifier3.setCaseId(SAMPLE_ID4); - profileCaseIdentifier3.setMolecularProfileId(MOLECULAR_PROFILE_ID_2); - molecularProfileCaseIdentifiers.add(profileCaseIdentifier3); - - when(molecularProfileService.getFirstDiscreteCNAProfileCaseIdentifiers(Arrays.asList(STUDY_ID, STUDY_ID, STUDY_ID), - updatedSampleIds)) - .thenReturn(molecularProfileCaseIdentifiers); - - List discreteCopyNumberDataList = new ArrayList<>(); - DiscreteCopyNumberData discreteCopyNumberData1 = new DiscreteCopyNumberData(); - discreteCopyNumberData1.setSampleId(SAMPLE_ID1); - discreteCopyNumberData1.setStudyId(STUDY_ID); - discreteCopyNumberDataList.add(discreteCopyNumberData1); - DiscreteCopyNumberData discreteCopyNumberData2 = new DiscreteCopyNumberData(); - discreteCopyNumberData2.setSampleId(SAMPLE_ID1); - discreteCopyNumberData2.setStudyId(STUDY_ID); - discreteCopyNumberDataList.add(discreteCopyNumberData2); - DiscreteCopyNumberData discreteCopyNumberData3 = new DiscreteCopyNumberData(); - discreteCopyNumberData3.setSampleId(SAMPLE_ID2); - discreteCopyNumberData3.setStudyId(STUDY_ID); - discreteCopyNumberDataList.add(discreteCopyNumberData3); - - Gene gene2 = new Gene(); - gene2.setEntrezGeneId(ENTREZ_GENE_ID_2); - gene2.setHugoGeneSymbol(HUGO_GENE_SYMBOL_2); - when(geneService.fetchGenes(Arrays.asList(HUGO_GENE_SYMBOL_2), GeneIdType.HUGO_GENE_SYMBOL.name(), - Projection.SUMMARY.name())).thenReturn(Arrays.asList(gene2)); - - when(discreteCopyNumberService.getDiscreteCopyNumbersInMultipleMolecularProfilesByGeneQueries( - anyList(), anyList(), anyList(), anyString())).thenReturn(discreteCopyNumberDataList); - - List clinicalAttributeList = new ArrayList<>(); - ClinicalAttribute clinicalAttribute1 = new ClinicalAttribute(); - clinicalAttribute1.setAttrId(CLINICAL_ATTRIBUTE_ID_1); - clinicalAttribute1.setDatatype("STRING"); - clinicalAttributeList.add(clinicalAttribute1); - ClinicalAttribute clinicalAttribute2 = new ClinicalAttribute(); - clinicalAttribute2.setAttrId(CLINICAL_ATTRIBUTE_ID_2); - clinicalAttribute2.setDatatype("STRING"); - clinicalAttributeList.add(clinicalAttribute2); - - when(clinicalAttributeService.getClinicalAttributesByStudyIdsAndAttributeIds(Arrays.asList(STUDY_ID), - Arrays.asList(CLINICAL_ATTRIBUTE_ID_1, CLINICAL_ATTRIBUTE_ID_2))).thenReturn(clinicalAttributeList); - - List result = studyViewFilterApplier.apply(studyViewFilter); - - Assert.assertEquals(2, result.size()); - Assert.assertEquals(SAMPLE_ID1, result.get(0).getSampleId()); - Assert.assertEquals(SAMPLE_ID2, result.get(1).getSampleId()); - } - - @Test - public void applyIntervalFilters() throws Exception { - - List studyIds = new ArrayList<>(); - studyIds.add(STUDY_ID); - studyIds.add(STUDY_ID); - studyIds.add(STUDY_ID); - studyIds.add(STUDY_ID); - studyIds.add(STUDY_ID); - - StudyViewFilter studyViewFilter = new StudyViewFilter(); - List sampleIds = new ArrayList<>(); - sampleIds.add(SAMPLE_ID1); - sampleIds.add(SAMPLE_ID2); - sampleIds.add(SAMPLE_ID3); - sampleIds.add(SAMPLE_ID4); - sampleIds.add(SAMPLE_ID5); - - List sampleIdentifiers = new ArrayList<>(); - SampleIdentifier sampleIdentifier1 = new SampleIdentifier(); - sampleIdentifier1.setSampleId(SAMPLE_ID1); - sampleIdentifier1.setStudyId(STUDY_ID); - sampleIdentifiers.add(sampleIdentifier1); - SampleIdentifier sampleIdentifier2 = new SampleIdentifier(); - sampleIdentifier2.setSampleId(SAMPLE_ID2); - sampleIdentifier2.setStudyId(STUDY_ID); - sampleIdentifiers.add(sampleIdentifier2); - SampleIdentifier sampleIdentifier3 = new SampleIdentifier(); - sampleIdentifier3.setSampleId(SAMPLE_ID3); - sampleIdentifier3.setStudyId(STUDY_ID); - sampleIdentifiers.add(sampleIdentifier3); - SampleIdentifier sampleIdentifier4 = new SampleIdentifier(); - sampleIdentifier4.setSampleId(SAMPLE_ID4); - sampleIdentifier4.setStudyId(STUDY_ID); - sampleIdentifiers.add(sampleIdentifier4); - SampleIdentifier sampleIdentifier5 = new SampleIdentifier(); - sampleIdentifier5.setSampleId(SAMPLE_ID5); - sampleIdentifier5.setStudyId(STUDY_ID); - sampleIdentifiers.add(sampleIdentifier5); - studyViewFilter.setSampleIdentifiers(sampleIdentifiers); - - List samples = new ArrayList<>(); - Sample sample1 = new Sample(); - sample1.setStableId(SAMPLE_ID1); - sample1.setCancerStudyIdentifier(STUDY_ID); - samples.add(sample1); - Sample sample2 = new Sample(); - sample2.setStableId(SAMPLE_ID2); - sample2.setCancerStudyIdentifier(STUDY_ID); - samples.add(sample2); - Sample sample3 = new Sample(); - sample3.setStableId(SAMPLE_ID3); - sample3.setCancerStudyIdentifier(STUDY_ID); - samples.add(sample3); - Sample sample4 = new Sample(); - sample4.setStableId(SAMPLE_ID4); - sample4.setCancerStudyIdentifier(STUDY_ID); - samples.add(sample4); - Sample sample5 = new Sample(); - sample5.setStableId(SAMPLE_ID5); - sample5.setCancerStudyIdentifier(STUDY_ID); - samples.add(sample5); - - List patients = new ArrayList<>(); - Patient patient1 = new Patient(); - patient1.setStableId(PATIENT_ID1); - patient1.setCancerStudyIdentifier(STUDY_ID); - patients.add(patient1); - Patient patient2 = new Patient(); - patient2.setStableId(PATIENT_ID2); - patient2.setCancerStudyIdentifier(STUDY_ID); - patients.add(patient2); - Patient patient3 = new Patient(); - patient3.setStableId(PATIENT_ID3); - patient3.setCancerStudyIdentifier(STUDY_ID); - patients.add(patient3); - Patient patient4 = new Patient(); - patient4.setStableId(PATIENT_ID4); - patient4.setCancerStudyIdentifier(STUDY_ID); - patients.add(patient4); - - when(sampleService.fetchSamples(studyIds, sampleIds, "ID")).thenReturn(samples); - when(patientService.getPatientsOfSamples(studyIds, sampleIds)).thenReturn(patients); - - List sampleClinicalDataList = new ArrayList<>(); - ClinicalData sampleClinicalData1 = new ClinicalData(); - sampleClinicalData1.setAttrId(CLINICAL_ATTRIBUTE_ID_3); - sampleClinicalData1.setAttrValue("66.6"); - sampleClinicalData1.setSampleId(SAMPLE_ID1); - sampleClinicalData1.setStudyId(STUDY_ID); - sampleClinicalDataList.add(sampleClinicalData1); - ClinicalData sampleClinicalData2 = new ClinicalData(); - sampleClinicalData2.setAttrId(CLINICAL_ATTRIBUTE_ID_3); - sampleClinicalData2.setAttrValue("666"); - sampleClinicalData2.setSampleId(SAMPLE_ID2); - sampleClinicalData2.setStudyId(STUDY_ID); - sampleClinicalDataList.add(sampleClinicalData2); - ClinicalData sampleClinicalData3 = new ClinicalData(); - sampleClinicalData3.setAttrId(CLINICAL_ATTRIBUTE_ID_3); - sampleClinicalData3.setAttrValue("NAN"); - sampleClinicalData3.setSampleId(SAMPLE_ID3); - sampleClinicalData3.setStudyId(STUDY_ID); - sampleClinicalDataList.add(sampleClinicalData3); - ClinicalData sampleClinicalData4 = new ClinicalData(); - sampleClinicalData4.setAttrId(CLINICAL_ATTRIBUTE_ID_3); - sampleClinicalData4.setAttrValue("6.66"); - sampleClinicalData4.setSampleId(SAMPLE_ID4); - sampleClinicalData4.setStudyId(STUDY_ID); - sampleClinicalDataList.add(sampleClinicalData4); - ClinicalData sampleClinicalData5 = new ClinicalData(); - sampleClinicalData5.setAttrId(CLINICAL_ATTRIBUTE_ID_3); - sampleClinicalData5.setAttrValue("SOMETHING_ELSE"); - sampleClinicalData5.setSampleId(SAMPLE_ID5); - sampleClinicalData5.setStudyId(STUDY_ID); - sampleClinicalDataList.add(sampleClinicalData5); - - when( - clinicalDataService.fetchClinicalData(Arrays.asList(STUDY_ID, STUDY_ID, STUDY_ID, STUDY_ID, STUDY_ID), - sampleIds, Arrays.asList(CLINICAL_ATTRIBUTE_ID_3), "SAMPLE", "SUMMARY")) - .thenReturn(sampleClinicalDataList); - - when(clinicalDataService.getPatientClinicalDataDetailedToSample( - Arrays.asList(STUDY_ID, STUDY_ID, STUDY_ID, STUDY_ID), sampleIds, - Arrays.asList(CLINICAL_ATTRIBUTE_ID_3))).thenReturn(new ArrayList()); - - List clinicalDataIntervalFilters = new ArrayList<>(); - ClinicalDataFilter clinicalDataIntervalFilter1 = new ClinicalDataFilter(); - clinicalDataIntervalFilter1.setAttributeId(CLINICAL_ATTRIBUTE_ID_3); - DataFilterValue filterValue1 = new DataFilterValue(); - filterValue1.setStart(new BigDecimal("66.6")); - filterValue1.setEnd(new BigDecimal("666")); - clinicalDataIntervalFilter1.setValues(Collections.singletonList(filterValue1)); - clinicalDataIntervalFilters.add(clinicalDataIntervalFilter1); - studyViewFilter.setClinicalDataFilters(clinicalDataIntervalFilters); - - List clinicalAttributeList = new ArrayList<>(); - ClinicalAttribute clinicalAttribute1 = new ClinicalAttribute(); - clinicalAttribute1.setAttrId(CLINICAL_ATTRIBUTE_ID_3); - clinicalAttribute1.setDatatype("NUMBER"); - clinicalAttributeList.add(clinicalAttribute1); - - when(clinicalAttributeService.getClinicalAttributesByStudyIdsAndAttributeIds(Arrays.asList(STUDY_ID), - Arrays.asList(CLINICAL_ATTRIBUTE_ID_3))).thenReturn(clinicalAttributeList); - - List result1 = studyViewFilterApplier.apply(studyViewFilter); - Assert.assertEquals(1, result1.size()); - - DataFilterValue filterValue2 = new DataFilterValue(); - filterValue2.setStart(new BigDecimal("6.66")); - filterValue2.setEnd(new BigDecimal("66.6")); - clinicalDataIntervalFilter1.setValues(Arrays.asList(filterValue1, filterValue2)); - - List result2 = studyViewFilterApplier.apply(studyViewFilter); - Assert.assertEquals(2, result2.size()); - - DataFilterValue filterValue3 = new DataFilterValue(); - filterValue3.setStart(new BigDecimal("6.66")); - filterValue3.setEnd(new BigDecimal("666")); - clinicalDataIntervalFilter1.setValues(Arrays.asList(filterValue1, filterValue2, filterValue3)); - - List result3 = studyViewFilterApplier.apply(studyViewFilter); - Assert.assertEquals(2, result3.size()); - - DataFilterValue filterValue4 = new DataFilterValue(); - filterValue4.setValue("na"); - clinicalDataIntervalFilter1.setValues(Arrays.asList(filterValue3, filterValue4)); - - List result4 = studyViewFilterApplier.apply(studyViewFilter); - Assert.assertEquals(3, result4.size()); - - DataFilterValue filterValue5 = new DataFilterValue(); - filterValue5.setValue("something_else"); - clinicalDataIntervalFilter1.setValues(Arrays.asList(filterValue1, filterValue5)); - - List result5 = studyViewFilterApplier.apply(studyViewFilter); - Assert.assertEquals(2, result5.size()); - } - - @Test - public void applyPatientLevelGenericAssayFilter() throws Exception { - - List studyIds = Collections.nCopies(5, STUDY_ID); - - StudyViewFilter studyViewFilter = new StudyViewFilter(); - List sampleIds = new ArrayList<>(); - sampleIds.add(SAMPLE_ID1); - sampleIds.add(SAMPLE_ID2); - sampleIds.add(SAMPLE_ID3); - sampleIds.add(SAMPLE_ID4); - sampleIds.add(SAMPLE_ID5); - - List sampleIdentifiers = new ArrayList<>(); - SampleIdentifier sampleIdentifier1 = new SampleIdentifier(); - sampleIdentifier1.setSampleId(SAMPLE_ID1); - sampleIdentifier1.setStudyId(STUDY_ID); - sampleIdentifiers.add(sampleIdentifier1); - SampleIdentifier sampleIdentifier2 = new SampleIdentifier(); - sampleIdentifier2.setSampleId(SAMPLE_ID2); - sampleIdentifier2.setStudyId(STUDY_ID); - sampleIdentifiers.add(sampleIdentifier2); - SampleIdentifier sampleIdentifier3 = new SampleIdentifier(); - sampleIdentifier3.setSampleId(SAMPLE_ID3); - sampleIdentifier3.setStudyId(STUDY_ID); - sampleIdentifiers.add(sampleIdentifier3); - SampleIdentifier sampleIdentifier4 = new SampleIdentifier(); - sampleIdentifier4.setSampleId(SAMPLE_ID4); - sampleIdentifier4.setStudyId(STUDY_ID); - sampleIdentifiers.add(sampleIdentifier4); - SampleIdentifier sampleIdentifier5 = new SampleIdentifier(); - sampleIdentifier5.setSampleId(SAMPLE_ID5); - sampleIdentifier5.setStudyId(STUDY_ID); - sampleIdentifiers.add(sampleIdentifier5); - studyViewFilter.setSampleIdentifiers(sampleIdentifiers); - - List samples = new ArrayList<>(); - Sample sample1 = new Sample(); - sample1.setStableId(SAMPLE_ID1); - sample1.setCancerStudyIdentifier(STUDY_ID); - samples.add(sample1); - Sample sample2 = new Sample(); - sample2.setStableId(SAMPLE_ID2); - sample2.setCancerStudyIdentifier(STUDY_ID); - samples.add(sample2); - Sample sample3 = new Sample(); - sample3.setStableId(SAMPLE_ID3); - sample3.setCancerStudyIdentifier(STUDY_ID); - samples.add(sample3); - Sample sample4 = new Sample(); - sample4.setStableId(SAMPLE_ID4); - sample4.setCancerStudyIdentifier(STUDY_ID); - samples.add(sample4); - Sample sample5 = new Sample(); - sample5.setStableId(SAMPLE_ID5); - sample5.setCancerStudyIdentifier(STUDY_ID); - samples.add(sample5); - - List patients = new ArrayList<>(); - Patient patient1 = new Patient(); - patient1.setStableId(PATIENT_ID1); - patient1.setCancerStudyIdentifier(STUDY_ID); - patients.add(patient1); - Patient patient2 = new Patient(); - patient2.setStableId(PATIENT_ID2); - patient2.setCancerStudyIdentifier(STUDY_ID); - patients.add(patient2); - Patient patient3 = new Patient(); - patient3.setStableId(PATIENT_ID3); - patient3.setCancerStudyIdentifier(STUDY_ID); - patients.add(patient3); - Patient patient4 = new Patient(); - patient4.setStableId(PATIENT_ID4); - patient4.setCancerStudyIdentifier(STUDY_ID); - patients.add(patient4); - - when(sampleService.fetchSamples(studyIds, sampleIds, "ID")).thenReturn(samples); - when(patientService.getPatientsOfSamples(studyIds, sampleIds)).thenReturn(patients); - - List molecularProfiles = new ArrayList<>(); - MolecularProfile molecularProfile1 = new MolecularProfile(); - molecularProfile1.setStableId(MOLECULAR_PROFILE_ID_1); - molecularProfile1.setCancerStudyIdentifier(STUDY_ID); - molecularProfile1.setPatientLevel(true); - molecularProfiles.add(molecularProfile1); - - when(molecularProfileService.getMolecularProfilesInStudies(Arrays.asList(STUDY_ID), "SUMMARY")).thenReturn(molecularProfiles); - - List genericAssayDataList = new ArrayList<>(); - - GenericAssayData genericAssayData1 = new GenericAssayData(); - genericAssayData1.setGenericAssayStableId(CLINICAL_ATTRIBUTE_ID_3); - genericAssayData1.setMolecularProfileId(MOLECULAR_PROFILE_ID_1); - genericAssayData1.setSampleId(SAMPLE_ID1); - genericAssayData1.setPatientId(PATIENT_ID1); - genericAssayData1.setStudyId(STUDY_ID); - genericAssayData1.setValue("100"); - genericAssayDataList.add(genericAssayData1); - - GenericAssayData genericAssayData2 = new GenericAssayData(); - genericAssayData2.setGenericAssayStableId(CLINICAL_ATTRIBUTE_ID_3); - genericAssayData2.setMolecularProfileId(MOLECULAR_PROFILE_ID_1); - genericAssayData2.setSampleId(SAMPLE_ID2); - genericAssayData2.setPatientId(PATIENT_ID1); - genericAssayData2.setStudyId(STUDY_ID); - genericAssayData2.setValue("100"); - genericAssayDataList.add(genericAssayData2); - - GenericAssayData genericAssayData3 = new GenericAssayData(); - genericAssayData3.setGenericAssayStableId(CLINICAL_ATTRIBUTE_ID_3); - genericAssayData3.setMolecularProfileId(MOLECULAR_PROFILE_ID_1); - genericAssayData3.setSampleId(SAMPLE_ID3); - genericAssayData3.setPatientId(PATIENT_ID2); - genericAssayData3.setStudyId(STUDY_ID); - genericAssayData3.setValue("100"); - genericAssayDataList.add(genericAssayData3); - - GenericAssayData genericAssayData4 = new GenericAssayData(); - genericAssayData4.setGenericAssayStableId(CLINICAL_ATTRIBUTE_ID_3); - genericAssayData4.setMolecularProfileId(MOLECULAR_PROFILE_ID_1); - genericAssayData4.setSampleId(SAMPLE_ID4); - genericAssayData4.setPatientId(PATIENT_ID3); - genericAssayData4.setStudyId(STUDY_ID); - genericAssayData4.setValue("100"); - genericAssayDataList.add(genericAssayData4); - - GenericAssayData genericAssayData5 = new GenericAssayData(); - genericAssayData5.setGenericAssayStableId(CLINICAL_ATTRIBUTE_ID_3); - genericAssayData5.setMolecularProfileId(MOLECULAR_PROFILE_ID_1); - genericAssayData5.setSampleId(SAMPLE_ID5); - genericAssayData5.setPatientId(PATIENT_ID4); - genericAssayData5.setStudyId(STUDY_ID); - genericAssayData5.setValue("100"); - genericAssayDataList.add(genericAssayData5); - - when(genericAssayService - .fetchGenericAssayData(Arrays.asList(MOLECULAR_PROFILE_ID_1, MOLECULAR_PROFILE_ID_1, MOLECULAR_PROFILE_ID_1, MOLECULAR_PROFILE_ID_1, MOLECULAR_PROFILE_ID_1), sampleIds, Arrays.asList(CLINICAL_ATTRIBUTE_ID_3), "SUMMARY")).thenReturn(genericAssayDataList); - - GenericAssayDataFilter genericAssayDataFilter = new GenericAssayDataFilter(); - genericAssayDataFilter.setStableId(CLINICAL_ATTRIBUTE_ID_3); - genericAssayDataFilter.setProfileType(MOLECULAR_PROFILE_ID_1); - - DataFilterValue filterValue1 = new DataFilterValue(); - filterValue1.setStart(new BigDecimal("50")); - filterValue1.setEnd(new BigDecimal("150")); - genericAssayDataFilter.setValues(Arrays.asList(filterValue1)); - studyViewFilter.setGenericAssayDataFilters(Arrays.asList(genericAssayDataFilter)); - - List result = studyViewFilterApplier.apply(studyViewFilter); - // Return 4 samples since this is a patient level profile - // And sample1 sample2 belong to patient1 - Assert.assertEquals(4, result.size()); - } - - @Test - public void applyNumericalCustomDataFilter() throws Exception { - // Create samples: - List sampleIdentifiers = new ArrayList<>(); - sampleIdentifiers.add(createSampleIdentifier(SAMPLE_ID1)); - sampleIdentifiers.add(createSampleIdentifier(SAMPLE_ID2)); - sampleIdentifiers.add(createSampleIdentifier(SAMPLE_ID3)); - StudyViewFilter studyViewFilter = new StudyViewFilter(); - studyViewFilter.setSampleIdentifiers(sampleIdentifiers); - List sampleIds = sampleIdentifiers - .stream() - .map(SampleIdentifier::getSampleId) - .collect(toList()); - List studyIds = sampleIdentifiers - .stream() - .map(SampleIdentifier::getStudyId) - .collect(toList()); - List samples = sampleIdentifiers - .stream() - .map(si -> createSample(si.getSampleId())) - .collect(toList()); - - // Create custom dataset interval filter: sample value must be between 0 and 10 - ClinicalDataFilter customDataFilter = new ClinicalDataFilter(); - customDataFilter.setAttributeId(CUSTOM_DATASET_ID); - DataFilterValue intervalFilter = new DataFilterValue(); - intervalFilter.setStart(new BigDecimal("0")); - intervalFilter.setEnd(new BigDecimal("10")); - customDataFilter.setValues(of(intervalFilter)); - List customDataFilters = new ArrayList<>(); - customDataFilters.add(customDataFilter); - studyViewFilter.setCustomDataFilters(customDataFilters); - - // Mock sample service: - when(sampleService.fetchSamples(eq(studyIds), eq(sampleIds), eq("ID"))).thenReturn(samples); - - // Load custom dataset: - String customDataset = getFileContents("classpath:numerical-custom-dataset-filter-applier.json"); - mockCustomDataService(customDataset); - - List result = studyViewFilterApplier.apply(studyViewFilter); - - Assert.assertEquals(1, result.size()); - } - - @Test - public void applyCategoricalCustomDataFilter() throws Exception { - // Create samples: - List sampleIdentifiers = new ArrayList<>(); - sampleIdentifiers.add(createSampleIdentifier(SAMPLE_ID1)); - sampleIdentifiers.add(createSampleIdentifier(SAMPLE_ID2)); - sampleIdentifiers.add(createSampleIdentifier(SAMPLE_ID3)); - StudyViewFilter studyViewFilter = new StudyViewFilter(); - studyViewFilter.setSampleIdentifiers(sampleIdentifiers); - List sampleIds = sampleIdentifiers - .stream() - .map(SampleIdentifier::getSampleId) - .collect(toList()); - List studyIds = sampleIdentifiers - .stream() - .map(SampleIdentifier::getStudyId) - .collect(toList()); - List samples = sampleIdentifiers - .stream() - .map(si -> createSample(si.getSampleId())) - .collect(toList()); - - // Create custom dataset equality filter: sample value must be value2 - ClinicalDataFilter customDataFilter = new ClinicalDataFilter(); - customDataFilter.setAttributeId(CUSTOM_DATASET_ID); - customDataFilter.setValues(of(createDataFilterValue("value2"))); - List customDataFilters = new ArrayList<>(); - customDataFilters.add(customDataFilter); - studyViewFilter.setCustomDataFilters(customDataFilters); - - // Mock sample service: - when(sampleService.fetchSamples(eq(studyIds), eq(sampleIds), eq("ID"))).thenReturn(samples); - - // Load custom dataset: - String customDataset = getFileContents("classpath:categorical-custom-dataset-filter-applier.json"); - mockCustomDataService(customDataset); - - List result = studyViewFilterApplier.apply(studyViewFilter); - - Assert.assertEquals(1, result.size()); - } - - @Test - public void applyMutationDataFilter() throws Exception { - - List studyIds = Collections.nCopies(5, STUDY_ID); - - StudyViewFilter studyViewFilter = new StudyViewFilter(); - List sampleIds = new ArrayList<>(); - sampleIds.add(SAMPLE_ID1); - sampleIds.add(SAMPLE_ID2); - sampleIds.add(SAMPLE_ID3); - sampleIds.add(SAMPLE_ID4); - sampleIds.add(SAMPLE_ID5); - - List sampleIdentifiers = new ArrayList<>(); - SampleIdentifier sampleIdentifier1 = new SampleIdentifier(); - sampleIdentifier1.setSampleId(SAMPLE_ID1); - sampleIdentifier1.setStudyId(STUDY_ID); - sampleIdentifiers.add(sampleIdentifier1); - SampleIdentifier sampleIdentifier2 = new SampleIdentifier(); - sampleIdentifier2.setSampleId(SAMPLE_ID2); - sampleIdentifier2.setStudyId(STUDY_ID); - sampleIdentifiers.add(sampleIdentifier2); - SampleIdentifier sampleIdentifier3 = new SampleIdentifier(); - sampleIdentifier3.setSampleId(SAMPLE_ID3); - sampleIdentifier3.setStudyId(STUDY_ID); - sampleIdentifiers.add(sampleIdentifier3); - SampleIdentifier sampleIdentifier4 = new SampleIdentifier(); - sampleIdentifier4.setSampleId(SAMPLE_ID4); - sampleIdentifier4.setStudyId(STUDY_ID); - sampleIdentifiers.add(sampleIdentifier4); - SampleIdentifier sampleIdentifier5 = new SampleIdentifier(); - sampleIdentifier5.setSampleId(SAMPLE_ID5); - sampleIdentifier5.setStudyId(STUDY_ID); - sampleIdentifiers.add(sampleIdentifier5); - studyViewFilter.setSampleIdentifiers(sampleIdentifiers); - - List samples = new ArrayList<>(); - Sample sample1 = new Sample(); - sample1.setStableId(SAMPLE_ID1); - sample1.setCancerStudyIdentifier(STUDY_ID); - samples.add(sample1); - Sample sample2 = new Sample(); - sample2.setStableId(SAMPLE_ID2); - sample2.setCancerStudyIdentifier(STUDY_ID); - samples.add(sample2); - Sample sample3 = new Sample(); - sample3.setStableId(SAMPLE_ID3); - sample3.setCancerStudyIdentifier(STUDY_ID); - samples.add(sample3); - Sample sample4 = new Sample(); - sample4.setStableId(SAMPLE_ID4); - sample4.setCancerStudyIdentifier(STUDY_ID); - samples.add(sample4); - Sample sample5 = new Sample(); - sample5.setStableId(SAMPLE_ID5); - sample5.setCancerStudyIdentifier(STUDY_ID); - samples.add(sample5); - - when(sampleService.fetchSamples(studyIds, sampleIds, "ID")).thenReturn(samples); - - List molecularProfiles = new ArrayList<>(); - MolecularProfile molecularProfile1 = new MolecularProfile(); - molecularProfile1.setStableId(MOLECULAR_PROFILE_ID_1); - molecularProfile1.setCancerStudyIdentifier(STUDY_ID); - molecularProfiles.add(molecularProfile1); - - when(molecularProfileService.getMolecularProfilesInStudies(List.of(STUDY_ID), "SUMMARY")).thenReturn(molecularProfiles); - - List mutationList = new ArrayList<>(); - - Mutation mutation1 = new Mutation(); - mutation1.setSampleId(SAMPLE_ID1); - mutation1.setPatientId(PATIENT_ID1); - mutation1.setStudyId(STUDY_ID); - mutation1.setMutationType(MUTATION_TYPE_1); - mutationList.add(mutation1); - - Mutation mutation2 = new Mutation(); - mutation2.setSampleId(SAMPLE_ID2); - mutation2.setPatientId(PATIENT_ID1); - mutation2.setStudyId(STUDY_ID); - mutation2.setMutationType(MUTATION_TYPE_1); - mutationList.add(mutation2); - - Mutation mutation3 = new Mutation(); - mutation3.setSampleId(SAMPLE_ID3); - mutation3.setPatientId(PATIENT_ID2); - mutation3.setStudyId(STUDY_ID); - mutation3.setMutationType(MUTATION_TYPE_2); - mutationList.add(mutation3); - - Mutation mutation4 = new Mutation(); - mutation4.setSampleId(SAMPLE_ID4); - mutation4.setPatientId(PATIENT_ID2); - mutation4.setStudyId(STUDY_ID); - mutation4.setMutationType(MUTATION_TYPE_2); - mutationList.add(mutation4); - - Gene gene1 = new Gene(); - gene1.setEntrezGeneId(ENTREZ_GENE_ID_1); - gene1.setHugoGeneSymbol(HUGO_GENE_SYMBOL_1); - - when(geneService.fetchGenes(Arrays.asList(HUGO_GENE_SYMBOL_1), GeneIdType.HUGO_GENE_SYMBOL.name(), - Projection.SUMMARY.name())).thenReturn(Arrays.asList(gene1)); - when(mutationService.getMutationsInMultipleMolecularProfiles(anyList(), anyList(), - anyList(), anyString(), - isNull(), isNull(), isNull(), isNull())).thenReturn(mutationList); - - MutationDataFilter mutationDataFilter = new MutationDataFilter(); - mutationDataFilter.setHugoGeneSymbol(HUGO_GENE_SYMBOL_1); - mutationDataFilter.setProfileType(MOLECULAR_PROFILE_ID_1); - mutationDataFilter.setCategorization(MutationOption.MUTATED); - - DataFilterValue filterValue1 = new DataFilterValue(); - filterValue1.setValue("MUTATED"); - mutationDataFilter.setValues(List.of(List.of(filterValue1))); - studyViewFilter.setMutationDataFilters(Arrays.asList(mutationDataFilter)); - - List result1 = studyViewFilterApplier.apply(studyViewFilter); - // Return 4 samples since four mutations are MUTATED - Assert.assertEquals(4, result1.size()); - - DataFilterValue filterValue2 = new DataFilterValue(); - filterValue2.setValue(MUTATION_TYPE_1); - mutationDataFilter.setCategorization(MutationOption.MUTATION_TYPE); - mutationDataFilter.setValues(List.of(List.of(filterValue2))); - studyViewFilter.setMutationDataFilters(Collections.singletonList(mutationDataFilter)); - - // Return 2 samples since two mutations are MUTATION_TYPE_1 - List result2 = studyViewFilterApplier.apply(studyViewFilter); - Assert.assertEquals(2, result2.size()); - } - - private DataFilterValue createDataFilterValue(String value) { - DataFilterValue equalityFilter = new DataFilterValue(); - equalityFilter.setValue(value); - return equalityFilter; - } - - private Sample createSample(String sampleId) { - Sample sample1 = new Sample(); - sample1.setStableId(sampleId); - sample1.setCancerStudyIdentifier(STUDY_ID); - return sample1; - } - - private SampleIdentifier createSampleIdentifier(String sampleId) { - SampleIdentifier sampleIdentifier1 = new SampleIdentifier(); - sampleIdentifier1.setSampleId(sampleId); - sampleIdentifier1.setStudyId(STUDY_ID); - return sampleIdentifier1; - } - - private void mockCustomDataService(String customDatasetFile) throws Exception { - when( - sessionServiceRequestHandler.getSessionDataJson(any(), any()) - ).thenReturn(customDatasetFile); - } - - private String getFileContents(String resourceLocation) throws IOException { - return new String(Files.readAllBytes(ResourceUtils.getFile(resourceLocation).toPath())); - } - -} diff --git a/src/test/java/org/cbioportal/web/util/appliers/PatientTreatmentFilterApplierTest.java b/src/test/java/org/cbioportal/web/util/appliers/PatientTreatmentFilterApplierTest.java deleted file mode 100644 index f722aa2f96c..00000000000 --- a/src/test/java/org/cbioportal/web/util/appliers/PatientTreatmentFilterApplierTest.java +++ /dev/null @@ -1,158 +0,0 @@ -package org.cbioportal.web.util.appliers; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import java.util.stream.Collectors; - -import org.cbioportal.model.ClinicalEventSample; -import org.cbioportal.model.PatientTreatmentRow; -import org.cbioportal.service.TreatmentService; -import org.cbioportal.web.parameter.SampleIdentifier; -import org.cbioportal.web.parameter.StudyViewFilter; -import org.cbioportal.web.parameter.filter.AndedPatientTreatmentFilters; -import org.cbioportal.web.parameter.filter.OredPatientTreatmentFilters; -import org.cbioportal.web.parameter.filter.PatientTreatmentFilter; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.*; -import org.mockito.junit.MockitoJUnitRunner; - -@RunWith(MockitoJUnitRunner.Silent.class) -public class PatientTreatmentFilterApplierTest { - @Mock - TreatmentService treatmentService; - - @Spy - TreatmentRowExtractor treatmentRowExtractor; - - @InjectMocks - PatientTreatmentFilterApplier subject; - - @Before - public void setup() { - MockitoAnnotations.initMocks(this); - } - - @Test - public void filterEmptyList() { - List samples = new ArrayList<>(); - StudyViewFilter andedFilters = createAndedFilters( - Arrays.asList("Fakeazil", "Madeupanib"), - Arrays.asList("Fabricada", "Fakeamab") - ); - Mockito - .when(treatmentService.getAllPatientTreatmentRows(Mockito.anyList(), Mockito.anyList(), Mockito.any())) - .thenReturn(new ArrayList<>()); - - List actual = subject.filter(samples, andedFilters); - List expected = new ArrayList<>(); - - Assert.assertEquals(expected, actual); - } - - @Test - public void filterAllFromList() { - List samples = Arrays.asList( - createSampleId("SA_0", "ST_0"), - createSampleId("SA_1", "ST_0"), - createSampleId("SA_2", "ST_1"), - createSampleId("SA_3", "ST_1") - ); - StudyViewFilter andedFilters = createAndedFilters( - Arrays.asList("Improvizox", "Madeupanib"), - Arrays.asList("Fabricada", "Fakeamab") - ); - Mockito - .when(treatmentService.getAllPatientTreatmentRows(Mockito.anyList(), Mockito.anyList(), Mockito.any())) - .thenReturn(new ArrayList<>()); - - List actual = subject.filter(samples, andedFilters); - List expected = new ArrayList<>(); - - Assert.assertEquals(expected, actual); - } - - @Test - public void filterNoneFromList() { - List samples = Arrays.asList( - createSampleId("SA_0", "ST_0"), - createSampleId("SA_1", "ST_0"), - createSampleId("SA_2", "ST_1"), - createSampleId("SA_3", "ST_1") - ); - StudyViewFilter andedFilters = createAndedFilters( - // so each sample needs to be from a patient that has recieved... - Arrays.asList("Improvizox", "Madeupanib"), // one of these treatments - Arrays.asList("Fabricada", "Fakeamab") // AND one of these treatments - ); - Mockito - .when(treatmentService.getAllPatientTreatmentRows(Mockito.anyList(), Mockito.anyList(), Mockito.any())) - .thenReturn(Arrays.asList( - new PatientTreatmentRow("Improvizox", 2, toSet(createEvent("SA_0", "ST_0"), createEvent("SA_1", "ST_0"))), - new PatientTreatmentRow("Fakeamab", 2, toSet(createEvent("SA_0", "ST_0"), createEvent("SA_1", "ST_0"))), - new PatientTreatmentRow("Madeupanib", 2, toSet(createEvent("SA_2", "ST_1"), createEvent("SA_3", "ST_1"))), - new PatientTreatmentRow("Fabricada", 2, toSet(createEvent("SA_2", "ST_1"), createEvent("SA_3", "ST_1"))) - )); - - List actual = subject.filter(samples, andedFilters); - List expected = Arrays.asList( - createSampleId("SA_0", "ST_0"), - createSampleId("SA_1", "ST_0"), - createSampleId("SA_2", "ST_1"), - createSampleId("SA_3", "ST_1") - ); - - Assert.assertEquals(expected, actual); - } - - private ClinicalEventSample createEvent(String sampleId, String studyId) { - ClinicalEventSample sample = new ClinicalEventSample(); - sample.setSampleId(sampleId); - sample.setStudyId(studyId); - return sample; - } - - private SampleIdentifier createSampleId(String sampleId, String studyId) { - SampleIdentifier sampleIdentifier = new SampleIdentifier(); - sampleIdentifier.setSampleId(sampleId); - sampleIdentifier.setStudyId(studyId); - return sampleIdentifier; - } - - @SafeVarargs - private final StudyViewFilter createAndedFilters(List... treatments) { - AndedPatientTreatmentFilters andedFilters = new AndedPatientTreatmentFilters(); - List oredFilters = Arrays.stream(treatments) - .map(this::createOredFilters) - .collect(Collectors.toList()); - andedFilters.setFilters(oredFilters); - - StudyViewFilter filter = new StudyViewFilter(); - filter.setPatientTreatmentFilters(andedFilters); - return filter; - } - - private OredPatientTreatmentFilters createOredFilters(List treatments) { - OredPatientTreatmentFilters oredFilters = new OredPatientTreatmentFilters(); - List filters = treatments.stream() - .map(this::createFilter) - .collect(Collectors.toList()); - oredFilters.setFilters(filters); - return oredFilters; - } - - private PatientTreatmentFilter createFilter(String treatment) { - PatientTreatmentFilter filter = new PatientTreatmentFilter(); - filter.setTreatment(treatment); - return filter; - } - - private Set toSet(ClinicalEventSample... samples) { - return new HashSet<>(Arrays.asList(samples)); - } -} \ No newline at end of file diff --git a/src/test/java/org/cbioportal/web/util/appliers/SampleTreatmentFilterApplierTest.java b/src/test/java/org/cbioportal/web/util/appliers/SampleTreatmentFilterApplierTest.java deleted file mode 100644 index 2c3f9cddada..00000000000 --- a/src/test/java/org/cbioportal/web/util/appliers/SampleTreatmentFilterApplierTest.java +++ /dev/null @@ -1,176 +0,0 @@ -package org.cbioportal.web.util.appliers; - -import org.cbioportal.model.ClinicalEventSample; -import org.cbioportal.model.SampleTreatmentRow; -import org.cbioportal.model.TemporalRelation; -import org.cbioportal.service.TreatmentService; -import org.cbioportal.web.parameter.SampleIdentifier; -import org.cbioportal.web.parameter.StudyViewFilter; -import org.cbioportal.web.parameter.filter.AndedSampleTreatmentFilters; -import org.cbioportal.web.parameter.filter.OredSampleTreatmentFilters; -import org.cbioportal.web.parameter.filter.SampleTreatmentFilter; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.*; -import org.mockito.junit.MockitoJUnitRunner; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import java.util.stream.Collectors; - -import static org.cbioportal.model.TemporalRelation.Post; -import static org.cbioportal.model.TemporalRelation.Pre; - -@RunWith(MockitoJUnitRunner.Silent.class) -public class SampleTreatmentFilterApplierTest { - @Mock - TreatmentService treatmentService; - - @Spy - TreatmentRowExtractor treatmentRowExtractor; - - @InjectMocks - SampleTreatmentFilterApplier subject; - - @Before - public void setup() { - MockitoAnnotations.initMocks(this); - } - - @Test - public void filterEmptyList() { - List samples = new ArrayList<>(); - StudyViewFilter andedFilters = createAndedFilters( - Arrays.asList(new Pair<>("Fakeazil", Pre), new Pair<>("Madeupanib", Post)), - Arrays.asList(new Pair<>("Fabricada", Pre), new Pair<>("Fakeamab", Post)) - ); - Mockito - .when(treatmentService.getAllSampleTreatmentRows(Mockito.anyList(), Mockito.anyList(), Mockito.any())) - .thenReturn(new ArrayList<>()); - - List actual = subject.filter(samples, andedFilters); - List expected = new ArrayList<>(); - - Assert.assertEquals(expected, actual); - } - - @Test - public void filterAllFromList() { - List samples = Arrays.asList( - createSampleId("SA_0", "ST_0"), - createSampleId("SA_1", "ST_0"), - createSampleId("SA_2", "ST_1"), - createSampleId("SA_3", "ST_1") - ); - StudyViewFilter andedFilters = createAndedFilters( - Arrays.asList(new Pair<>("Improvizox", Pre), new Pair<>("Madeupanib", Post)), - Arrays.asList(new Pair<>("Fabricada", Pre), new Pair<>("Fakeamab", Post)) - ); - Mockito - .when(treatmentService.getAllSampleTreatmentRows(Mockito.anyList(), Mockito.anyList(), Mockito.any())) - .thenReturn(new ArrayList<>()); - - List actual = subject.filter(samples, andedFilters); - List expected = new ArrayList<>(); - - Assert.assertEquals(expected, actual); - } - - @Test - public void filterNoneFromList() { - List samples = Arrays.asList( - createSampleId("SA_0", "ST_0"), - createSampleId("SA_1", "ST_0"), - createSampleId("SA_2", "ST_1"), - createSampleId("SA_3", "ST_1") - ); - StudyViewFilter andedFilters = createAndedFilters( - // so each sample needs to be... - // before Improvizox or after Madeupanib - Arrays.asList(new Pair<>("Improvizox", Pre), new Pair<>("Madeupanib", Post)), - // AND before Fabricada or after Fakeamab - Arrays.asList(new Pair<>("Fabricada", Pre), new Pair<>("Fakeamab", Post)) - ); - Mockito - .when(treatmentService.getAllSampleTreatmentRows(Mockito.anyList(), Mockito.anyList(), Mockito.any())) - .thenReturn(Arrays.asList( - new SampleTreatmentRow(Pre, "Improvizox", 2, toSet(createEvent("SA_0", "ST_0"), createEvent("SA_1", "ST_0"))), - new SampleTreatmentRow(Post, "Fakeamab", 2, toSet(createEvent("SA_0", "ST_0"), createEvent("SA_1", "ST_0"))), - new SampleTreatmentRow(Post, "Madeupanib", 2, toSet(createEvent("SA_2", "ST_1"), createEvent("SA_3", "ST_1"))), - new SampleTreatmentRow(Pre, "Fabricada", 2, toSet(createEvent("SA_2", "ST_1"), createEvent("SA_3", "ST_1"))) - )); - - List actual = subject.filter(samples, andedFilters); - List expected = Arrays.asList( - createSampleId("SA_0", "ST_0"), - createSampleId("SA_1", "ST_0"), - createSampleId("SA_2", "ST_1"), - createSampleId("SA_3", "ST_1") - ); - - Assert.assertEquals(expected, actual); - } - - private ClinicalEventSample createEvent(String sampleId, String studyId) { - ClinicalEventSample sample = new ClinicalEventSample(); - sample.setSampleId(sampleId); - sample.setStudyId(studyId); - return sample; - } - - private SampleIdentifier createSampleId(String sampleId, String studyId) { - SampleIdentifier sampleIdentifier = new SampleIdentifier(); - sampleIdentifier.setSampleId(sampleId); - sampleIdentifier.setStudyId(studyId); - return sampleIdentifier; - } - - @SafeVarargs - private final StudyViewFilter createAndedFilters(List>... treatments) { - AndedSampleTreatmentFilters andedFilters = new AndedSampleTreatmentFilters(); - List oredFilters = Arrays.stream(treatments) - .map(this::createOredFilters) - .collect(Collectors.toList()); - andedFilters.setFilters(oredFilters); - - StudyViewFilter filter = new StudyViewFilter(); - filter.setSampleTreatmentFilters(andedFilters); - - return filter; - } - - private OredSampleTreatmentFilters createOredFilters(List> treatments) { - OredSampleTreatmentFilters oredFilters = new OredSampleTreatmentFilters(); - List filters = treatments.stream() - .map(this::createFilter) - .collect(Collectors.toList()); - oredFilters.setFilters(filters); - return oredFilters; - } - - private SampleTreatmentFilter createFilter(Pair pair) { - SampleTreatmentFilter filter = new SampleTreatmentFilter(); - filter.setTreatment(pair.a); - filter.setTime(pair.b); - return filter; - } - - private Set toSet(ClinicalEventSample... samples) { - return new HashSet<>(Arrays.asList(samples)); - } - - private static final class Pair { - final A a; - final B b; - - Pair(A a, B b) { - this.a = a; - this.b = b; - } - } -} \ No newline at end of file diff --git a/src/test/java/org/cbioportal/web/util/appliers/StructuralVariantSubFilterApplierTest.java b/src/test/java/org/cbioportal/web/util/appliers/StructuralVariantSubFilterApplierTest.java deleted file mode 100644 index e8bd8efba6d..00000000000 --- a/src/test/java/org/cbioportal/web/util/appliers/StructuralVariantSubFilterApplierTest.java +++ /dev/null @@ -1,142 +0,0 @@ -package org.cbioportal.web.util.appliers; - -import org.cbioportal.model.MolecularProfile; -import org.cbioportal.model.StructuralVariantFilterQuery; -import org.cbioportal.model.StructuralVariant; -import org.cbioportal.model.StudyViewStructuralVariantFilter; -import org.cbioportal.model.util.Select; -import org.cbioportal.service.MolecularProfileService; -import org.cbioportal.service.impl.StructuralVariantServiceImpl; -import org.cbioportal.web.parameter.SampleIdentifier; -import org.cbioportal.web.parameter.StudyViewFilter; -import org.cbioportal.web.util.StudyViewFilterUtil; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.junit.MockitoJUnitRunner; - -import java.util.Arrays; -import java.util.HashSet; -import java.util.List; - -import static org.mockito.ArgumentMatchers.anyList; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.when; - -@RunWith(MockitoJUnitRunner.Silent.class) -public class StructuralVariantSubFilterApplierTest { - - static final String ST_1_ID = "ST_1_ID"; - static final String MP_1_ID = "MP_1_ID"; - static final String G1 = "G1"; - static final String G2 = "G2"; - - @InjectMocks - StructuralVariantSubFilterApplier subject; - - @Mock - MolecularProfileService molecularProfileService; - - @Mock - StructuralVariantServiceImpl structuralVariantService; - - @Mock - StudyViewFilterUtil studyViewFilterUtil; - - private StudyViewFilter emptyStudyViewFilter = new StudyViewFilter(); - private StudyViewFilter structVarStudyViewFilter = new StudyViewFilter(); - - @Before - public void setUp() throws Exception { - - // For the test this arrangement does not matter much. What is more important - // is the SVs returned by the structuralVariantService service mock in response to - // subsequent query filter calls. - List svA = Arrays.asList(createQuery(G1, G2)); - List svB = Arrays.asList(createQuery(G1, G2)); - List> svA_and_svB_filterQuery = Arrays.asList(svA, svB); - - final StudyViewStructuralVariantFilter structuralVariantFilter = new StudyViewStructuralVariantFilter(); - structuralVariantFilter.setStructVarQueries(svA_and_svB_filterQuery); - structuralVariantFilter.setMolecularProfileIds(new HashSet<>(Arrays.asList(MP_1_ID))); - structVarStudyViewFilter.setStructuralVariantFilters(Arrays.asList(structuralVariantFilter)); - - MolecularProfile molecularProfile1 = new MolecularProfile(); - molecularProfile1.setStableId(MP_1_ID); - molecularProfile1.setCancerStudyIdentifier(ST_1_ID); - molecularProfile1.setMolecularAlterationType(MolecularProfile.MolecularAlterationType.STRUCTURAL_VARIANT); - - when(molecularProfileService.getMolecularProfilesInStudies(anyList(), eq("SUMMARY"))) - .thenReturn(Arrays.asList(molecularProfile1)); - - final List structuralVariantsQuerySvA = Arrays.asList( - createStructVar("1", ST_1_ID), - createStructVar("2", ST_1_ID), - createStructVar("3", ST_1_ID), - createStructVar("4", ST_1_ID), - createStructVar("5", ST_1_ID) - ); - // This result determines the final result. - final List structuralVariantsQuerySvB = Arrays.asList( - createStructVar("4", ST_1_ID), - createStructVar("5", ST_1_ID) - ); - // Subsequently, return results for svA and svB queries. - when(studyViewFilterUtil.resolveEntrezGeneIds(anyList())) - .thenReturn(svA, svB); - when(structuralVariantService.fetchStructuralVariantsByStructVarQueries(anyList(), anyList(), anyList()) - ).thenReturn(structuralVariantsQuerySvA, structuralVariantsQuerySvB); - } - - // Does the function return OR relations between genes in the sv query filter? - @Test - public void filter() { - List sampleIdentifiers = Arrays.asList( - createSampleId("1", ST_1_ID), - createSampleId("2", ST_1_ID), - createSampleId("3", ST_1_ID), - createSampleId("4", ST_1_ID), - createSampleId("5", ST_1_ID), - createSampleId("6", ST_1_ID), - createSampleId("7", ST_1_ID), - createSampleId("8", ST_1_ID), - createSampleId("9", ST_1_ID), - createSampleId("10", ST_1_ID) - ); - List expected = Arrays.asList( - createSampleId("4", ST_1_ID), - createSampleId("5", ST_1_ID) - ); - Assert.assertEquals(expected, subject.filter(sampleIdentifiers, structVarStudyViewFilter)); - } - - @Test - public void shouldApplyFilter() { - Assert.assertFalse(subject.shouldApplyFilter(emptyStudyViewFilter)); - Assert.assertTrue(subject.shouldApplyFilter(structVarStudyViewFilter)); - } - - private StructuralVariantFilterQuery createQuery(String gene1, String gene2) { - return new StructuralVariantFilterQuery(gene1, null, gene2, null, - true, true, true, Select.all(), - true, true, true, true); - } - - private SampleIdentifier createSampleId(String samplId, String studyId) { - final SampleIdentifier sampleIdentifier = new SampleIdentifier(); - sampleIdentifier.setStudyId(studyId); - sampleIdentifier.setSampleId(samplId); - return sampleIdentifier; - } - - private StructuralVariant createStructVar(String samplId, String studyId) { - final StructuralVariant structuralVariant = new StructuralVariant(); - structuralVariant.setStudyId(studyId); - structuralVariant.setSampleId(samplId); - return structuralVariant; - } - -} \ No newline at end of file diff --git a/src/test/resources/cgds-h2.sql b/src/test/resources/cgds-h2.sql index 6ecf3d51560..92d250faa1a 100644 --- a/src/test/resources/cgds-h2.sql +++ b/src/test/resources/cgds-h2.sql @@ -45,8 +45,6 @@ DROP TABLE IF EXISTS `info`; DROP TABLE IF EXISTS `clinical_event_data`; DROP TABLE IF EXISTS `clinical_event`; -DROP TABLE IF EXISTS `pdb_uniprot_residue_mapping`; -DROP TABLE IF EXISTS `pdb_uniprot_alignment`; DROP TABLE IF EXISTS `cosmic_mutation`; DROP TABLE IF EXISTS `copy_number_seg_file`; DROP TABLE IF EXISTS `copy_number_seg`; @@ -650,7 +648,7 @@ CREATE TABLE `cosmic_mutation` ( -- -------------------------------------------------------- CREATE TABLE `clinical_event` ( - `CLINICAL_EVENT_ID` int NOT NULL auto_increment, + `CLINICAL_EVENT_ID` BIGINT NOT NULL auto_increment, `PATIENT_ID` int(11) NOT NULL, `START_DATE` int NOT NULL, `STOP_DATE` int, @@ -662,7 +660,7 @@ CREATE TABLE `clinical_event` ( -- -------------------------------------------------------- CREATE TABLE `clinical_event_data` ( - `CLINICAL_EVENT_ID` int(255) NOT NULL, + `CLINICAL_EVENT_ID` BIGINT NOT NULL, `KEY` varchar(255) NOT NULL, `VALUE` varchar(5000) NOT NULL, FOREIGN KEY (`CLINICAL_EVENT_ID`) REFERENCES `clinical_event` (`CLINICAL_EVENT_ID`) ON DELETE CASCADE @@ -711,7 +709,8 @@ CREATE TABLE `allele_specific_copy_number` ( -- -------------------------------------------------------- CREATE TABLE `info` ( `DB_SCHEMA_VERSION` varchar(24), - `GENESET_VERSION` varchar(24) + `GENESET_VERSION` varchar(24), + `DERIVED_TABLE_SCHEMA_VERSION` varchar(24) ); -- -------------------------------------------------------- @@ -723,6 +722,7 @@ CREATE TABLE `resource_definition` ( `OPEN_BY_DEFAULT` BOOLEAN DEFAULT 0, `PRIORITY` int(11) NOT NULL, `CANCER_STUDY_ID` int(11) NOT NULL, + `CUSTOM_METADATA` JSON, PRIMARY KEY (`RESOURCE_ID`,`CANCER_STUDY_ID`), FOREIGN KEY (`CANCER_STUDY_ID`) REFERENCES `cancer_study` (`CANCER_STUDY_ID`) ON DELETE CASCADE ); @@ -754,6 +754,6 @@ CREATE TABLE `resource_study` ( FOREIGN KEY (`INTERNAL_ID`) REFERENCES `cancer_study` (`CANCER_STUDY_ID`) ON DELETE CASCADE ); --- THIS MUST BE KEPT IN SYNC WITH db.version PROPERTY IN pom.xml -INSERT INTO info VALUES ('2.13.1', NULL); - +-- DB_SCHEMA_VERSION AND DERIVED_TABLE_SCHEMA_VERSION MUST BE KEPT IN SYNC WITH THE db.version AND derived_table.version PROPERTIES IN pom.xml +INSERT INTO `info` (`DB_SCHEMA_VERSION`, `GENESET_VERSION`, `DERIVED_TABLE_SCHEMA_VERSION`) + VALUES ('2.14.2', NULL, '1.0.0'); diff --git a/src/test/resources/cgds.sql b/src/test/resources/cgds.sql index 67edccfbd69..fa45a766b84 100644 --- a/src/test/resources/cgds.sql +++ b/src/test/resources/cgds.sql @@ -648,7 +648,7 @@ CREATE TABLE `cosmic_mutation` ( -- -------------------------------------------------------- CREATE TABLE `clinical_event` ( - `CLINICAL_EVENT_ID` int NOT NULL auto_increment, + `CLINICAL_EVENT_ID` BIGINT NOT NULL auto_increment, `PATIENT_ID` int(11) NOT NULL, `START_DATE` int NOT NULL, `STOP_DATE` int, @@ -660,7 +660,7 @@ CREATE TABLE `clinical_event` ( -- -------------------------------------------------------- CREATE TABLE `clinical_event_data` ( - `CLINICAL_EVENT_ID` int(255) NOT NULL, + `CLINICAL_EVENT_ID` BIGINT NOT NULL, `KEY` varchar(255) NOT NULL, `VALUE` varchar(5000) NOT NULL, FOREIGN KEY (`CLINICAL_EVENT_ID`) REFERENCES `clinical_event` (`CLINICAL_EVENT_ID`) ON DELETE CASCADE @@ -709,7 +709,8 @@ CREATE TABLE `allele_specific_copy_number` ( -- -------------------------------------------------------- CREATE TABLE `info` ( `DB_SCHEMA_VERSION` varchar(24), - `GENESET_VERSION` varchar(24) + `GENESET_VERSION` varchar(24), + `DERIVED_TABLE_SCHEMA_VERSION` varchar(24) ); -- -------------------------------------------------------- @@ -721,6 +722,7 @@ CREATE TABLE `resource_definition` ( `OPEN_BY_DEFAULT` BOOLEAN DEFAULT 0, `PRIORITY` int(11) NOT NULL, `CANCER_STUDY_ID` int(11) NOT NULL, + `CUSTOM_METADATA` JSON, PRIMARY KEY (`RESOURCE_ID`,`CANCER_STUDY_ID`), FOREIGN KEY (`CANCER_STUDY_ID`) REFERENCES `cancer_study` (`CANCER_STUDY_ID`) ON DELETE CASCADE ); @@ -752,6 +754,6 @@ CREATE TABLE `resource_study` ( FOREIGN KEY (`INTERNAL_ID`) REFERENCES `cancer_study` (`CANCER_STUDY_ID`) ON DELETE CASCADE ); --- THIS MUST BE KEPT IN SYNC WITH db.version PROPERTY IN pom.xml -INSERT INTO info VALUES ('2.13.1', NULL); - +-- DB_SCHEMA_VERSION AND DERIVED_TABLE_SCHEMA_VERSION MUST BE KEPT IN SYNC WITH THE db.version AND derived_table.version PROPERTIES IN pom.xml +INSERT INTO `info` (`DB_SCHEMA_VERSION`, `GENESET_VERSION`, `DERIVED_TABLE_SCHEMA_VERSION`) + VALUES ('2.14.2', NULL, '1.0.0'); diff --git a/src/test/resources/clickhouse_data.sql b/src/test/resources/clickhouse_data.sql index af1723dcf69..0bff51fadb8 100644 --- a/src/test/resources/clickhouse_data.sql +++ b/src/test/resources/clickhouse_data.sql @@ -228,10 +228,10 @@ insert into alteration_driver_annotation (alteration_event_id,genetic_profile_id insert into alteration_driver_annotation (alteration_event_id,genetic_profile_id,sample_id, driver_filter, driver_filter_annotation, driver_tiers_filter, driver_tiers_filter_annotation) values (1,2,1, 'putative_driver', 'pathogenic', 'tier 1', 'highly actionable'); insert into alteration_driver_annotation (alteration_event_id,genetic_profile_id,sample_id, driver_filter, driver_filter_annotation, driver_tiers_filter, driver_tiers_filter_annotation) values (3,2,2, 'putative_passenger', 'pathogenic', 'tier 2', 'potentially actionable'); -insert into mutation (mutation_event_id,genetic_profile_id,sample_id,entrez_gene_id,center,sequencer,mutation_status,validation_status,tumor_seq_allele1,tumor_seq_allele2,matched_norm_sample_barcode,match_norm_seq_allele1,match_norm_seq_allele2,tumor_validation_allele1,tumor_validation_allele2,match_norm_validation_allele1,match_norm_validation_allele2,verification_status,sequencing_phase,sequence_source,validation_method,score,bam_file,tumor_alt_count,tumor_ref_count,normal_alt_count,normal_ref_count,amino_acid_change,annotation_json) values (2038,6,6,672,'genome.wustl.edu','illuminagaiix','na','unknown','g','a','tcga-a1-a0sh-10a-03d-a099-09','g','a','na','na','na','na','unknown','phase_iv','capture','na','1','dbgap',1,0,-1,-1,'cyclases/protein','{"zygosity":{"status": "heterozygous"}}'); +insert into mutation (mutation_event_id,genetic_profile_id,sample_id,entrez_gene_id,center,sequencer,mutation_status,validation_status,tumor_seq_allele1,tumor_seq_allele2,matched_norm_sample_barcode,match_norm_seq_allele1,match_norm_seq_allele2,tumor_validation_allele1,tumor_validation_allele2,match_norm_validation_allele1,match_norm_validation_allele2,verification_status,sequencing_phase,sequence_source,validation_method,score,bam_file,tumor_alt_count,tumor_ref_count,normal_alt_count,normal_ref_count,amino_acid_change,annotation_json) values (2038,6,6,672,'genome.wustl.edu','illuminagaiix','GERMLINE','unknown','g','a','tcga-a1-a0sh-10a-03d-a099-09','g','a','na','na','na','na','unknown','phase_iv','capture','na','1','dbgap',1,0,-1,-1,'cyclases/protein','{"zygosity":{"status": "heterozygous"}}'); insert into mutation (mutation_event_id,genetic_profile_id,sample_id,entrez_gene_id,center,sequencer,mutation_status,validation_status,tumor_seq_allele1,tumor_seq_allele2,matched_norm_sample_barcode,match_norm_seq_allele1,match_norm_seq_allele2,tumor_validation_allele1,tumor_validation_allele2,match_norm_validation_allele1,match_norm_validation_allele2,verification_status,sequencing_phase,sequence_source,validation_method,score,bam_file,tumor_alt_count,tumor_ref_count,normal_alt_count,normal_ref_count,amino_acid_change,annotation_json) values (22604,6,6,672,'genome.wustl.edu','illuminagaiix','GERMLINE','unknown','a','c','tcga-a1-a0sh-10a-03d-a099-09','a','c','na','na','na','na','unknown','phase_iv','capture','na','1','dbgap',-1,-1,-1,-1,'cyclases/protein','{"zygosity":{"status": "heterozygous"}}'); insert into mutation (mutation_event_id,genetic_profile_id,sample_id,entrez_gene_id,center,sequencer,mutation_status,validation_status,tumor_seq_allele1,tumor_seq_allele2,matched_norm_sample_barcode,match_norm_seq_allele1,match_norm_seq_allele2,tumor_validation_allele1,tumor_validation_allele2,match_norm_validation_allele1,match_norm_validation_allele2,verification_status,sequencing_phase,sequence_source,validation_method,score,bam_file,tumor_alt_count,tumor_ref_count,normal_alt_count,normal_ref_count,amino_acid_change,annotation_json) values (2039,6,12,672,'genome.wustl.edu','illuminagaiix','GERMLINE','unknown','t','t','tcga-a1-a0so-10a-03d-a099-09','t','t','na','na','na','na','unknown','phase_iv','capture','na','1','dbgap',-1,-1,-1,-1,'cyclases/protein','{"zygosity":{"status": "heterozygous"}}'); -insert into mutation (mutation_event_id,genetic_profile_id,sample_id,entrez_gene_id,center,sequencer,mutation_status,validation_status,tumor_seq_allele1,tumor_seq_allele2,matched_norm_sample_barcode,match_norm_seq_allele1,match_norm_seq_allele2,tumor_validation_allele1,tumor_validation_allele2,match_norm_validation_allele1,match_norm_validation_allele2,verification_status,sequencing_phase,sequence_source,validation_method,score,bam_file,tumor_alt_count,tumor_ref_count,normal_alt_count,normal_ref_count,amino_acid_change,annotation_json) values (2038,6,7,672,'genome.wustl.edu','illuminagaiix','GERMLINE','unknown','g','a','tcga-a1-a0sh-10a-03d-a099-09','g','a','na','na','na','na','unknown','phase_iv','capture','na','1','dbgap',-1,-1,-1,-1,'cyclases/protein','{"zygosity":{"status": "heterozygous"}}'); +insert into mutation (mutation_event_id,genetic_profile_id,sample_id,entrez_gene_id,center,sequencer,mutation_status,validation_status,tumor_seq_allele1,tumor_seq_allele2,matched_norm_sample_barcode,match_norm_seq_allele1,match_norm_seq_allele2,tumor_validation_allele1,tumor_validation_allele2,match_norm_validation_allele1,match_norm_validation_allele2,verification_status,sequencing_phase,sequence_source,validation_method,score,bam_file,tumor_alt_count,tumor_ref_count,normal_alt_count,normal_ref_count,amino_acid_change,annotation_json) values (2038,6,7,672,'genome.wustl.edu','illuminagaiix','na','unknown','g','a','tcga-a1-a0sh-10a-03d-a099-09','g','a','na','na','na','na','unknown','phase_iv','capture','na','1','dbgap',-1,-1,-1,-1,'cyclases/protein','{"zygosity":{"status": "heterozygous"}}'); insert into mutation (mutation_event_id,genetic_profile_id,sample_id,entrez_gene_id,center,sequencer,mutation_status,validation_status,tumor_seq_allele1,tumor_seq_allele2,matched_norm_sample_barcode,match_norm_seq_allele1,match_norm_seq_allele2,tumor_validation_allele1,tumor_validation_allele2,match_norm_validation_allele1,match_norm_validation_allele2,verification_status,sequencing_phase,sequence_source,validation_method,score,bam_file,tumor_alt_count,tumor_ref_count,normal_alt_count,normal_ref_count,amino_acid_change,annotation_json) values (2039,6,13,672,'genome.wustl.edu','illuminagaiix','GERMLINE','unknown','t','t','tcga-a1-a0so-10a-03d-a099-09','t','t','na','na','na','na','unknown','phase_iv','capture','na','1','dbgap',-1,-1,-1,-1,'cyclases/protein','{"zygosity":{"status": "heterozygous"}}'); insert into mutation (mutation_event_id,genetic_profile_id,sample_id,entrez_gene_id,center,sequencer,mutation_status,validation_status,tumor_seq_allele1,tumor_seq_allele2,matched_norm_sample_barcode,match_norm_seq_allele1,match_norm_seq_allele2,tumor_validation_allele1,tumor_validation_allele2,match_norm_validation_allele1,match_norm_validation_allele2,verification_status,sequencing_phase,sequence_source,validation_method,score,bam_file,tumor_alt_count,tumor_ref_count,normal_alt_count,normal_ref_count,amino_acid_change,annotation_json) values (2040,6,1,207,'genome.wustl.edu','illuminagaiix','GERMLINE','unknown','g','a','tcga-a1-a0sh-10a-03d-a099-09','g','a','na','na','na','na','unknown','phase_iv','capture','na','1','dbgap',-1,-1,-1,-1,'cyclases/protein','{"zygosity":{"status": "heterozygous"}}'); insert into mutation (mutation_event_id,genetic_profile_id,sample_id,entrez_gene_id,center,sequencer,mutation_status,validation_status,tumor_seq_allele1,tumor_seq_allele2,matched_norm_sample_barcode,match_norm_seq_allele1,match_norm_seq_allele2,tumor_validation_allele1,tumor_validation_allele2,match_norm_validation_allele1,match_norm_validation_allele2,verification_status,sequencing_phase,sequence_source,validation_method,score,bam_file,tumor_alt_count,tumor_ref_count,normal_alt_count,normal_ref_count,amino_acid_change,annotation_json) values (2041,6,2,207,'genome.wustl.edu','illuminagaiix','GERMLINE','unknown','a','c','tcga-a1-a0sh-10a-03d-a099-09','a','c','na','na','na','na','unknown','phase_iv','capture','na','1','dbgap',0,-1,-1,-1,'cyclases/protein','{"zygosity":{"status": "heterozygous"}}'); diff --git a/src/test/resources/maven.properties b/src/test/resources/maven.properties index 9ef36016da2..5da84d2c45a 100644 --- a/src/test/resources/maven.properties +++ b/src/test/resources/maven.properties @@ -1,3 +1,4 @@ portal.version=test_portal_version db.version=test_db_version +derived_table.version=test_derived_table_version app.version=test_app_version diff --git a/test/api-e2e/specs/clinical-data-filters.json b/test/api-e2e/specs/clinical-data-filters.json index b11a6ae46b8..0ee29babb61 100644 --- a/test/api-e2e/specs/clinical-data-filters.json +++ b/test/api-e2e/specs/clinical-data-filters.json @@ -271,7 +271,8 @@ "filterUrl": "/study/summary?id=genie_public#filterJson={\"clinicalDataFilters\":[{\"attributeId\":\"AGE_AT_SEQ_REPORT\",\"values\":[{\"end\":25}]}],\"studyIds\":[\"genie_public\"],\"alterationFilter\":{\"copyNumberAlterationEventTypes\":{\"AMP\":true,\"HOMDEL\":true},\"mutationEventTypes\":{\"any\":true},\"structuralVariants\":null,\"includeDriver\":true,\"includeVUS\":true,\"includeUnknownOncogenicity\":true,\"includeUnknownTier\":true,\"includeGermline\":true,\"includeSomatic\":true,\"includeUnknownStatus\":true,\"tiersBooleanMap\":{}}}" }, { - "hash": 2119685176, + "hash": 2119685176, + "skip": "off panel discrep", "filterString": "Age at Which Sequencing was Reported:≤ 25", "data": { "clinicalDataFilters": [ @@ -467,7 +468,8 @@ "filterUrl": "/study/summary?id=genie_public#filterJson={\"clinicalDataFilters\":[{\"attributeId\":\"AGE_AT_SEQ_REPORT\",\"values\":[{\"end\":25}]}],\"studyIds\":[\"genie_public\"],\"alterationFilter\":{\"copyNumberAlterationEventTypes\":{\"AMP\":true,\"HOMDEL\":true},\"mutationEventTypes\":{\"any\":true},\"structuralVariants\":null,\"includeDriver\":true,\"includeVUS\":true,\"includeUnknownOncogenicity\":true,\"includeUnknownTier\":true,\"includeGermline\":true,\"includeSomatic\":true,\"includeUnknownStatus\":true,\"tiersBooleanMap\":{}}}" }, { - "hash": -527271474, + "hash": -527271474, + "skip": "off panel discrep", "filterString": "Age at Which Sequencing was Reported:≤ 25", "data": { "clinicalDataFilters": [ @@ -740,6 +742,7 @@ }, { "hash": 430471933, + "skip": "off panel discrep", "filterString": "Age at Which Sequencing was Reported:≤ 25Interval in days from DOB to DOD:≤ 6570", "data": { "clinicalDataFilters": [ @@ -1036,6 +1039,7 @@ }, { "hash": 2009673299, + "skip": "off panel discrep", "filterString": "Age at Which Sequencing was Reported:≤ 25Interval in days from DOB to DOD:≤ 6570", "data": { "clinicalDataFilters": [ @@ -1451,6 +1455,7 @@ }, { "hash": 119943124, + "skip": "off panel discrep", "filterString": "Age at Which Sequencing was Reported:> 85Interval in days from DOB to date of last contact:> 32485", "data": { "clinicalDataFilters": [ @@ -1562,6 +1567,7 @@ }, { "hash": 1187512938, + "skip": "off panel discrep", "filterString": "Age at Which Sequencing was Reported:> 85Interval in days from DOB to date of last contact:> 32485", "data": { "clinicalDataFilters": [ diff --git a/test/api-e2e/specs/generic-assay-data-counts.json b/test/api-e2e/specs/generic-assay-data-counts.json index bf5325da945..06167cebf85 100644 --- a/test/api-e2e/specs/generic-assay-data-counts.json +++ b/test/api-e2e/specs/generic-assay-data-counts.json @@ -20,7 +20,9 @@ {"hash":1857690789,"filterString":"2q_status: Putative arm-level copy-number from GISTIC:NA","data":{"genericAssayDataFilters":[{"stableId":"2q_status","profileType":"armlevel_cna","values":[{"value":"NA"}]}],"studyIds":["crc_public_genie_bpc","acc_tcga_pan_can_atlas_2018"],"alterationFilter":{"copyNumberAlterationEventTypes":{"AMP":true,"HOMDEL":true},"mutationEventTypes":{"any":true},"structuralVariants":null,"includeDriver":true,"includeVUS":true,"includeUnknownOncogenicity":true,"includeUnknownTier":true,"includeGermline":true,"includeSomatic":true,"includeUnknownStatus":true,"tiersBooleanMap":{}}},"url":"/api/column-store/treatments/sample-counts/fetch?","label":"SampleTreatmentCounts","studies":["crc_public_genie_bpc","acc_tcga_pan_can_atlas_2018"],"filterUrl":"/study/summary?id=crc_public_genie_bpc%2Cacc_tcga_pan_can_atlas_2018#filterJson={\"genericAssayDataFilters\":[{\"stableId\":\"2q_status\",\"profileType\":\"armlevel_cna\",\"values\":[{\"value\":\"NA\"}]}],\"studyIds\":[\"crc_public_genie_bpc\",\"acc_tcga_pan_can_atlas_2018\"],\"alterationFilter\":{\"copyNumberAlterationEventTypes\":{\"AMP\":true,\"HOMDEL\":true},\"mutationEventTypes\":{\"any\":true},\"structuralVariants\":null,\"includeDriver\":true,\"includeVUS\":true,\"includeUnknownOncogenicity\":true,\"includeUnknownTier\":true,\"includeGermline\":true,\"includeSomatic\":true,\"includeUnknownStatus\":true,\"tiersBooleanMap\":{}}}"}, - {"hash":1945949655,"filterString":"2q_status: Putative arm-level copy-number from GISTIC:NA","data":{"genericAssayDataFilters":[{"stableId":"2q_status","profileType":"armlevel_cna","values":[{"value":"NA"}]}],"studyIds":["crc_public_genie_bpc","acc_tcga_pan_can_atlas_2018"],"alterationFilter":{"copyNumberAlterationEventTypes":{"AMP":true,"HOMDEL":true},"mutationEventTypes":{"any":true},"structuralVariants":null,"includeDriver":true,"includeVUS":true,"includeUnknownOncogenicity":true,"includeUnknownTier":true,"includeGermline":true,"includeSomatic":true,"includeUnknownStatus":true,"tiersBooleanMap":{}}},"url":"/api/column-store/mutated-genes/fetch?","label":"MutatedGenes","studies":["crc_public_genie_bpc","acc_tcga_pan_can_atlas_2018"],"filterUrl":"/study/summary?id=crc_public_genie_bpc%2Cacc_tcga_pan_can_atlas_2018#filterJson={\"genericAssayDataFilters\":[{\"stableId\":\"2q_status\",\"profileType\":\"armlevel_cna\",\"values\":[{\"value\":\"NA\"}]}],\"studyIds\":[\"crc_public_genie_bpc\",\"acc_tcga_pan_can_atlas_2018\"],\"alterationFilter\":{\"copyNumberAlterationEventTypes\":{\"AMP\":true,\"HOMDEL\":true},\"mutationEventTypes\":{\"any\":true},\"structuralVariants\":null,\"includeDriver\":true,\"includeVUS\":true,\"includeUnknownOncogenicity\":true,\"includeUnknownTier\":true,\"includeGermline\":true,\"includeSomatic\":true,\"includeUnknownStatus\":true,\"tiersBooleanMap\":{}}}"}, + {"hash":1945949655, + "skip": "off panel discrep", + "filterString":"2q_status: Putative arm-level copy-number from GISTIC:NA","data":{"genericAssayDataFilters":[{"stableId":"2q_status","profileType":"armlevel_cna","values":[{"value":"NA"}]}],"studyIds":["crc_public_genie_bpc","acc_tcga_pan_can_atlas_2018"],"alterationFilter":{"copyNumberAlterationEventTypes":{"AMP":true,"HOMDEL":true},"mutationEventTypes":{"any":true},"structuralVariants":null,"includeDriver":true,"includeVUS":true,"includeUnknownOncogenicity":true,"includeUnknownTier":true,"includeGermline":true,"includeSomatic":true,"includeUnknownStatus":true,"tiersBooleanMap":{}}},"url":"/api/column-store/mutated-genes/fetch?","label":"MutatedGenes","studies":["crc_public_genie_bpc","acc_tcga_pan_can_atlas_2018"],"filterUrl":"/study/summary?id=crc_public_genie_bpc%2Cacc_tcga_pan_can_atlas_2018#filterJson={\"genericAssayDataFilters\":[{\"stableId\":\"2q_status\",\"profileType\":\"armlevel_cna\",\"values\":[{\"value\":\"NA\"}]}],\"studyIds\":[\"crc_public_genie_bpc\",\"acc_tcga_pan_can_atlas_2018\"],\"alterationFilter\":{\"copyNumberAlterationEventTypes\":{\"AMP\":true,\"HOMDEL\":true},\"mutationEventTypes\":{\"any\":true},\"structuralVariants\":null,\"includeDriver\":true,\"includeVUS\":true,\"includeUnknownOncogenicity\":true,\"includeUnknownTier\":true,\"includeGermline\":true,\"includeSomatic\":true,\"includeUnknownStatus\":true,\"tiersBooleanMap\":{}}}"}, {"hash":-72431407,"filterString":"2q_status: Putative arm-level copy-number from GISTIC:NA","data":{"genericAssayDataFilters":[{"stableId":"2q_status","profileType":"armlevel_cna","values":[{"value":"NA"}]}],"studyIds":["crc_public_genie_bpc","acc_tcga_pan_can_atlas_2018"],"alterationFilter":{"copyNumberAlterationEventTypes":{"AMP":true,"HOMDEL":true},"mutationEventTypes":{"any":true},"structuralVariants":null,"includeDriver":true,"includeVUS":true,"includeUnknownOncogenicity":true,"includeUnknownTier":true,"includeGermline":true,"includeSomatic":true,"includeUnknownStatus":true,"tiersBooleanMap":{}}},"url":"/api/column-store/clinical-data-density-plot/fetch?xAxisAttributeId=FRACTION_GENOME_ALTERED&xAxisBinCount=44&xAxisStart=0&xAxisEnd=1&yAxisAttributeId=MUTATION_COUNT&yAxisBinCount=38&yAxisStart=0&xAxisLogScale=false&yAxisLogScale=false&","label":"ClinicalDataDensity","studies":["crc_public_genie_bpc","acc_tcga_pan_can_atlas_2018"],"filterUrl":"/study/summary?id=crc_public_genie_bpc%2Cacc_tcga_pan_can_atlas_2018#filterJson={\"genericAssayDataFilters\":[{\"stableId\":\"2q_status\",\"profileType\":\"armlevel_cna\",\"values\":[{\"value\":\"NA\"}]}],\"studyIds\":[\"crc_public_genie_bpc\",\"acc_tcga_pan_can_atlas_2018\"],\"alterationFilter\":{\"copyNumberAlterationEventTypes\":{\"AMP\":true,\"HOMDEL\":true},\"mutationEventTypes\":{\"any\":true},\"structuralVariants\":null,\"includeDriver\":true,\"includeVUS\":true,\"includeUnknownOncogenicity\":true,\"includeUnknownTier\":true,\"includeGermline\":true,\"includeSomatic\":true,\"includeUnknownStatus\":true,\"tiersBooleanMap\":{}}}"}, diff --git a/test/api-e2e/specs/mutated-genes-filter.json b/test/api-e2e/specs/mutated-genes-filter.json index 6c11f4099ad..d3fe96edc74 100644 --- a/test/api-e2e/specs/mutated-genes-filter.json +++ b/test/api-e2e/specs/mutated-genes-filter.json @@ -69,7 +69,9 @@ {"hash":1804856631,"filterString":"TP53","data":{"geneFilters":[{"molecularProfileIds":["nsclc_public_genie_bpc_mutations","acc_tcga_pan_can_atlas_2018_mutations","blca_tcga_pan_can_atlas_2018_mutations","brca_tcga_pan_can_atlas_2018_mutations","cesc_tcga_pan_can_atlas_2018_mutations","coadread_tcga_pan_can_atlas_2018_mutations","chol_tcga_pan_can_atlas_2018_mutations","dlbc_tcga_pan_can_atlas_2018_mutations","esca_tcga_pan_can_atlas_2018_mutations","gbm_tcga_pan_can_atlas_2018_mutations","hnsc_tcga_pan_can_atlas_2018_mutations","kich_tcga_pan_can_atlas_2018_mutations","kirc_tcga_pan_can_atlas_2018_mutations","kirp_tcga_pan_can_atlas_2018_mutations","laml_tcga_pan_can_atlas_2018_mutations","lgg_tcga_pan_can_atlas_2018_mutations","lihc_tcga_pan_can_atlas_2018_mutations","luad_tcga_pan_can_atlas_2018_mutations","lusc_tcga_pan_can_atlas_2018_mutations","meso_tcga_pan_can_atlas_2018_mutations","ov_tcga_pan_can_atlas_2018_mutations","paad_tcga_pan_can_atlas_2018_mutations","pcpg_tcga_pan_can_atlas_2018_mutations","prad_tcga_pan_can_atlas_2018_mutations","sarc_tcga_pan_can_atlas_2018_mutations","skcm_tcga_pan_can_atlas_2018_mutations","stad_tcga_pan_can_atlas_2018_mutations","tgct_tcga_pan_can_atlas_2018_mutations","thca_tcga_pan_can_atlas_2018_mutations","thym_tcga_pan_can_atlas_2018_mutations","ucec_tcga_pan_can_atlas_2018_mutations","ucs_tcga_pan_can_atlas_2018_mutations","uvm_tcga_pan_can_atlas_2018_mutations"],"geneQueries":[[{"hugoGeneSymbol":"TP53","entrezGeneId":0,"alterations":[],"includeDriver":true,"includeVUS":true,"includeUnknownOncogenicity":true,"tiersBooleanMap":{},"includeUnknownTier":true,"includeGermline":true,"includeSomatic":true,"includeUnknownStatus":true}]]}],"studyIds":["ov_tcga_pan_can_atlas_2018","nsclc_public_genie_bpc","kirc_tcga_pan_can_atlas_2018","kirp_tcga_pan_can_atlas_2018","kich_tcga_pan_can_atlas_2018","acc_tcga_pan_can_atlas_2018","chol_tcga_pan_can_atlas_2018","blca_tcga_pan_can_atlas_2018","coadread_tcga_pan_can_atlas_2018","brca_tcga_pan_can_atlas_2018","lgg_tcga_pan_can_atlas_2018","gbm_tcga_pan_can_atlas_2018","cesc_tcga_pan_can_atlas_2018","esca_tcga_pan_can_atlas_2018","stad_tcga_pan_can_atlas_2018","uvm_tcga_pan_can_atlas_2018","hnsc_tcga_pan_can_atlas_2018","lihc_tcga_pan_can_atlas_2018","luad_tcga_pan_can_atlas_2018","lusc_tcga_pan_can_atlas_2018","dlbc_tcga_pan_can_atlas_2018","laml_tcga_pan_can_atlas_2018","paad_tcga_pan_can_atlas_2018","meso_tcga_pan_can_atlas_2018","skcm_tcga_pan_can_atlas_2018","prad_tcga_pan_can_atlas_2018","pcpg_tcga_pan_can_atlas_2018","sarc_tcga_pan_can_atlas_2018","tgct_tcga_pan_can_atlas_2018","thym_tcga_pan_can_atlas_2018","thca_tcga_pan_can_atlas_2018","ucec_tcga_pan_can_atlas_2018","ucs_tcga_pan_can_atlas_2018"],"alterationFilter":{"copyNumberAlterationEventTypes":{"AMP":true,"HOMDEL":true},"mutationEventTypes":{"any":true},"structuralVariants":null,"includeDriver":true,"includeVUS":true,"includeUnknownOncogenicity":true,"includeUnknownTier":true,"includeGermline":true,"includeSomatic":true,"includeUnknownStatus":true,"tiersBooleanMap":{}}},"url":"/api/column-store/sample-lists-counts/fetch?","label":"CaseList","studies":["ov_tcga_pan_can_atlas_2018","nsclc_public_genie_bpc","kirc_tcga_pan_can_atlas_2018","kirp_tcga_pan_can_atlas_2018","kich_tcga_pan_can_atlas_2018","acc_tcga_pan_can_atlas_2018","chol_tcga_pan_can_atlas_2018","blca_tcga_pan_can_atlas_2018","coadread_tcga_pan_can_atlas_2018","brca_tcga_pan_can_atlas_2018","lgg_tcga_pan_can_atlas_2018","gbm_tcga_pan_can_atlas_2018","cesc_tcga_pan_can_atlas_2018","esca_tcga_pan_can_atlas_2018","stad_tcga_pan_can_atlas_2018","uvm_tcga_pan_can_atlas_2018","hnsc_tcga_pan_can_atlas_2018","lihc_tcga_pan_can_atlas_2018","luad_tcga_pan_can_atlas_2018","lusc_tcga_pan_can_atlas_2018","dlbc_tcga_pan_can_atlas_2018","laml_tcga_pan_can_atlas_2018","paad_tcga_pan_can_atlas_2018","meso_tcga_pan_can_atlas_2018","skcm_tcga_pan_can_atlas_2018","prad_tcga_pan_can_atlas_2018","pcpg_tcga_pan_can_atlas_2018","sarc_tcga_pan_can_atlas_2018","tgct_tcga_pan_can_atlas_2018","thym_tcga_pan_can_atlas_2018","thca_tcga_pan_can_atlas_2018","ucec_tcga_pan_can_atlas_2018","ucs_tcga_pan_can_atlas_2018"],"filterUrl":"/study/summary?id=ov_tcga_pan_can_atlas_2018%2Cnsclc_public_genie_bpc%2Ckirc_tcga_pan_can_atlas_2018%2Ckirp_tcga_pan_can_atlas_2018%2Ckich_tcga_pan_can_atlas_2018%2Cacc_tcga_pan_can_atlas_2018%2Cchol_tcga_pan_can_atlas_2018%2Cblca_tcga_pan_can_atlas_2018%2Ccoadread_tcga_pan_can_atlas_2018%2Cbrca_tcga_pan_can_atlas_2018%2Clgg_tcga_pan_can_atlas_2018%2Cgbm_tcga_pan_can_atlas_2018%2Ccesc_tcga_pan_can_atlas_2018%2Cesca_tcga_pan_can_atlas_2018%2Cstad_tcga_pan_can_atlas_2018%2Cuvm_tcga_pan_can_atlas_2018%2Chnsc_tcga_pan_can_atlas_2018%2Clihc_tcga_pan_can_atlas_2018%2Cluad_tcga_pan_can_atlas_2018%2Clusc_tcga_pan_can_atlas_2018%2Cdlbc_tcga_pan_can_atlas_2018%2Claml_tcga_pan_can_atlas_2018%2Cpaad_tcga_pan_can_atlas_2018%2Cmeso_tcga_pan_can_atlas_2018%2Cskcm_tcga_pan_can_atlas_2018%2Cprad_tcga_pan_can_atlas_2018%2Cpcpg_tcga_pan_can_atlas_2018%2Csarc_tcga_pan_can_atlas_2018%2Ctgct_tcga_pan_can_atlas_2018%2Cthym_tcga_pan_can_atlas_2018%2Cthca_tcga_pan_can_atlas_2018%2Cucec_tcga_pan_can_atlas_2018%2Cucs_tcga_pan_can_atlas_2018#filterJson={\"geneFilters\":[{\"molecularProfileIds\":[\"nsclc_public_genie_bpc_mutations\",\"acc_tcga_pan_can_atlas_2018_mutations\",\"blca_tcga_pan_can_atlas_2018_mutations\",\"brca_tcga_pan_can_atlas_2018_mutations\",\"cesc_tcga_pan_can_atlas_2018_mutations\",\"coadread_tcga_pan_can_atlas_2018_mutations\",\"chol_tcga_pan_can_atlas_2018_mutations\",\"dlbc_tcga_pan_can_atlas_2018_mutations\",\"esca_tcga_pan_can_atlas_2018_mutations\",\"gbm_tcga_pan_can_atlas_2018_mutations\",\"hnsc_tcga_pan_can_atlas_2018_mutations\",\"kich_tcga_pan_can_atlas_2018_mutations\",\"kirc_tcga_pan_can_atlas_2018_mutations\",\"kirp_tcga_pan_can_atlas_2018_mutations\",\"laml_tcga_pan_can_atlas_2018_mutations\",\"lgg_tcga_pan_can_atlas_2018_mutations\",\"lihc_tcga_pan_can_atlas_2018_mutations\",\"luad_tcga_pan_can_atlas_2018_mutations\",\"lusc_tcga_pan_can_atlas_2018_mutations\",\"meso_tcga_pan_can_atlas_2018_mutations\",\"ov_tcga_pan_can_atlas_2018_mutations\",\"paad_tcga_pan_can_atlas_2018_mutations\",\"pcpg_tcga_pan_can_atlas_2018_mutations\",\"prad_tcga_pan_can_atlas_2018_mutations\",\"sarc_tcga_pan_can_atlas_2018_mutations\",\"skcm_tcga_pan_can_atlas_2018_mutations\",\"stad_tcga_pan_can_atlas_2018_mutations\",\"tgct_tcga_pan_can_atlas_2018_mutations\",\"thca_tcga_pan_can_atlas_2018_mutations\",\"thym_tcga_pan_can_atlas_2018_mutations\",\"ucec_tcga_pan_can_atlas_2018_mutations\",\"ucs_tcga_pan_can_atlas_2018_mutations\",\"uvm_tcga_pan_can_atlas_2018_mutations\"],\"geneQueries\":[[{\"hugoGeneSymbol\":\"TP53\",\"entrezGeneId\":0,\"alterations\":[],\"includeDriver\":true,\"includeVUS\":true,\"includeUnknownOncogenicity\":true,\"tiersBooleanMap\":{},\"includeUnknownTier\":true,\"includeGermline\":true,\"includeSomatic\":true,\"includeUnknownStatus\":true}]]}],\"studyIds\":[\"ov_tcga_pan_can_atlas_2018\",\"nsclc_public_genie_bpc\",\"kirc_tcga_pan_can_atlas_2018\",\"kirp_tcga_pan_can_atlas_2018\",\"kich_tcga_pan_can_atlas_2018\",\"acc_tcga_pan_can_atlas_2018\",\"chol_tcga_pan_can_atlas_2018\",\"blca_tcga_pan_can_atlas_2018\",\"coadread_tcga_pan_can_atlas_2018\",\"brca_tcga_pan_can_atlas_2018\",\"lgg_tcga_pan_can_atlas_2018\",\"gbm_tcga_pan_can_atlas_2018\",\"cesc_tcga_pan_can_atlas_2018\",\"esca_tcga_pan_can_atlas_2018\",\"stad_tcga_pan_can_atlas_2018\",\"uvm_tcga_pan_can_atlas_2018\",\"hnsc_tcga_pan_can_atlas_2018\",\"lihc_tcga_pan_can_atlas_2018\",\"luad_tcga_pan_can_atlas_2018\",\"lusc_tcga_pan_can_atlas_2018\",\"dlbc_tcga_pan_can_atlas_2018\",\"laml_tcga_pan_can_atlas_2018\",\"paad_tcga_pan_can_atlas_2018\",\"meso_tcga_pan_can_atlas_2018\",\"skcm_tcga_pan_can_atlas_2018\",\"prad_tcga_pan_can_atlas_2018\",\"pcpg_tcga_pan_can_atlas_2018\",\"sarc_tcga_pan_can_atlas_2018\",\"tgct_tcga_pan_can_atlas_2018\",\"thym_tcga_pan_can_atlas_2018\",\"thca_tcga_pan_can_atlas_2018\",\"ucec_tcga_pan_can_atlas_2018\",\"ucs_tcga_pan_can_atlas_2018\"],\"alterationFilter\":{\"copyNumberAlterationEventTypes\":{\"AMP\":true,\"HOMDEL\":true},\"mutationEventTypes\":{\"any\":true},\"structuralVariants\":null,\"includeDriver\":true,\"includeVUS\":true,\"includeUnknownOncogenicity\":true,\"includeUnknownTier\":true,\"includeGermline\":true,\"includeSomatic\":true,\"includeUnknownStatus\":true,\"tiersBooleanMap\":{}}}"}, - {"hash":2133353191,"filterString":"TP53","data":{"geneFilters":[{"molecularProfileIds":["nsclc_public_genie_bpc_mutations","acc_tcga_pan_can_atlas_2018_mutations","blca_tcga_pan_can_atlas_2018_mutations","brca_tcga_pan_can_atlas_2018_mutations","cesc_tcga_pan_can_atlas_2018_mutations","coadread_tcga_pan_can_atlas_2018_mutations","chol_tcga_pan_can_atlas_2018_mutations","dlbc_tcga_pan_can_atlas_2018_mutations","esca_tcga_pan_can_atlas_2018_mutations","gbm_tcga_pan_can_atlas_2018_mutations","hnsc_tcga_pan_can_atlas_2018_mutations","kich_tcga_pan_can_atlas_2018_mutations","kirc_tcga_pan_can_atlas_2018_mutations","kirp_tcga_pan_can_atlas_2018_mutations","laml_tcga_pan_can_atlas_2018_mutations","lgg_tcga_pan_can_atlas_2018_mutations","lihc_tcga_pan_can_atlas_2018_mutations","luad_tcga_pan_can_atlas_2018_mutations","lusc_tcga_pan_can_atlas_2018_mutations","meso_tcga_pan_can_atlas_2018_mutations","ov_tcga_pan_can_atlas_2018_mutations","paad_tcga_pan_can_atlas_2018_mutations","pcpg_tcga_pan_can_atlas_2018_mutations","prad_tcga_pan_can_atlas_2018_mutations","sarc_tcga_pan_can_atlas_2018_mutations","skcm_tcga_pan_can_atlas_2018_mutations","stad_tcga_pan_can_atlas_2018_mutations","tgct_tcga_pan_can_atlas_2018_mutations","thca_tcga_pan_can_atlas_2018_mutations","thym_tcga_pan_can_atlas_2018_mutations","ucec_tcga_pan_can_atlas_2018_mutations","ucs_tcga_pan_can_atlas_2018_mutations","uvm_tcga_pan_can_atlas_2018_mutations"],"geneQueries":[[{"hugoGeneSymbol":"TP53","entrezGeneId":0,"alterations":[],"includeDriver":true,"includeVUS":true,"includeUnknownOncogenicity":true,"tiersBooleanMap":{},"includeUnknownTier":true,"includeGermline":true,"includeSomatic":true,"includeUnknownStatus":true}]]}],"studyIds":["ov_tcga_pan_can_atlas_2018","nsclc_public_genie_bpc","kirc_tcga_pan_can_atlas_2018","kirp_tcga_pan_can_atlas_2018","kich_tcga_pan_can_atlas_2018","acc_tcga_pan_can_atlas_2018","chol_tcga_pan_can_atlas_2018","blca_tcga_pan_can_atlas_2018","coadread_tcga_pan_can_atlas_2018","brca_tcga_pan_can_atlas_2018","lgg_tcga_pan_can_atlas_2018","gbm_tcga_pan_can_atlas_2018","cesc_tcga_pan_can_atlas_2018","esca_tcga_pan_can_atlas_2018","stad_tcga_pan_can_atlas_2018","uvm_tcga_pan_can_atlas_2018","hnsc_tcga_pan_can_atlas_2018","lihc_tcga_pan_can_atlas_2018","luad_tcga_pan_can_atlas_2018","lusc_tcga_pan_can_atlas_2018","dlbc_tcga_pan_can_atlas_2018","laml_tcga_pan_can_atlas_2018","paad_tcga_pan_can_atlas_2018","meso_tcga_pan_can_atlas_2018","skcm_tcga_pan_can_atlas_2018","prad_tcga_pan_can_atlas_2018","pcpg_tcga_pan_can_atlas_2018","sarc_tcga_pan_can_atlas_2018","tgct_tcga_pan_can_atlas_2018","thym_tcga_pan_can_atlas_2018","thca_tcga_pan_can_atlas_2018","ucec_tcga_pan_can_atlas_2018","ucs_tcga_pan_can_atlas_2018"],"alterationFilter":{"copyNumberAlterationEventTypes":{"AMP":true,"HOMDEL":true},"mutationEventTypes":{"any":true},"structuralVariants":null,"includeDriver":true,"includeVUS":true,"includeUnknownOncogenicity":true,"includeUnknownTier":true,"includeGermline":true,"includeSomatic":true,"includeUnknownStatus":true,"tiersBooleanMap":{}}},"url":"/api/column-store/mutated-genes/fetch?","label":"MutatedGenes","studies":["ov_tcga_pan_can_atlas_2018","nsclc_public_genie_bpc","kirc_tcga_pan_can_atlas_2018","kirp_tcga_pan_can_atlas_2018","kich_tcga_pan_can_atlas_2018","acc_tcga_pan_can_atlas_2018","chol_tcga_pan_can_atlas_2018","blca_tcga_pan_can_atlas_2018","coadread_tcga_pan_can_atlas_2018","brca_tcga_pan_can_atlas_2018","lgg_tcga_pan_can_atlas_2018","gbm_tcga_pan_can_atlas_2018","cesc_tcga_pan_can_atlas_2018","esca_tcga_pan_can_atlas_2018","stad_tcga_pan_can_atlas_2018","uvm_tcga_pan_can_atlas_2018","hnsc_tcga_pan_can_atlas_2018","lihc_tcga_pan_can_atlas_2018","luad_tcga_pan_can_atlas_2018","lusc_tcga_pan_can_atlas_2018","dlbc_tcga_pan_can_atlas_2018","laml_tcga_pan_can_atlas_2018","paad_tcga_pan_can_atlas_2018","meso_tcga_pan_can_atlas_2018","skcm_tcga_pan_can_atlas_2018","prad_tcga_pan_can_atlas_2018","pcpg_tcga_pan_can_atlas_2018","sarc_tcga_pan_can_atlas_2018","tgct_tcga_pan_can_atlas_2018","thym_tcga_pan_can_atlas_2018","thca_tcga_pan_can_atlas_2018","ucec_tcga_pan_can_atlas_2018","ucs_tcga_pan_can_atlas_2018"],"filterUrl":"/study/summary?id=ov_tcga_pan_can_atlas_2018%2Cnsclc_public_genie_bpc%2Ckirc_tcga_pan_can_atlas_2018%2Ckirp_tcga_pan_can_atlas_2018%2Ckich_tcga_pan_can_atlas_2018%2Cacc_tcga_pan_can_atlas_2018%2Cchol_tcga_pan_can_atlas_2018%2Cblca_tcga_pan_can_atlas_2018%2Ccoadread_tcga_pan_can_atlas_2018%2Cbrca_tcga_pan_can_atlas_2018%2Clgg_tcga_pan_can_atlas_2018%2Cgbm_tcga_pan_can_atlas_2018%2Ccesc_tcga_pan_can_atlas_2018%2Cesca_tcga_pan_can_atlas_2018%2Cstad_tcga_pan_can_atlas_2018%2Cuvm_tcga_pan_can_atlas_2018%2Chnsc_tcga_pan_can_atlas_2018%2Clihc_tcga_pan_can_atlas_2018%2Cluad_tcga_pan_can_atlas_2018%2Clusc_tcga_pan_can_atlas_2018%2Cdlbc_tcga_pan_can_atlas_2018%2Claml_tcga_pan_can_atlas_2018%2Cpaad_tcga_pan_can_atlas_2018%2Cmeso_tcga_pan_can_atlas_2018%2Cskcm_tcga_pan_can_atlas_2018%2Cprad_tcga_pan_can_atlas_2018%2Cpcpg_tcga_pan_can_atlas_2018%2Csarc_tcga_pan_can_atlas_2018%2Ctgct_tcga_pan_can_atlas_2018%2Cthym_tcga_pan_can_atlas_2018%2Cthca_tcga_pan_can_atlas_2018%2Cucec_tcga_pan_can_atlas_2018%2Cucs_tcga_pan_can_atlas_2018#filterJson={\"geneFilters\":[{\"molecularProfileIds\":[\"nsclc_public_genie_bpc_mutations\",\"acc_tcga_pan_can_atlas_2018_mutations\",\"blca_tcga_pan_can_atlas_2018_mutations\",\"brca_tcga_pan_can_atlas_2018_mutations\",\"cesc_tcga_pan_can_atlas_2018_mutations\",\"coadread_tcga_pan_can_atlas_2018_mutations\",\"chol_tcga_pan_can_atlas_2018_mutations\",\"dlbc_tcga_pan_can_atlas_2018_mutations\",\"esca_tcga_pan_can_atlas_2018_mutations\",\"gbm_tcga_pan_can_atlas_2018_mutations\",\"hnsc_tcga_pan_can_atlas_2018_mutations\",\"kich_tcga_pan_can_atlas_2018_mutations\",\"kirc_tcga_pan_can_atlas_2018_mutations\",\"kirp_tcga_pan_can_atlas_2018_mutations\",\"laml_tcga_pan_can_atlas_2018_mutations\",\"lgg_tcga_pan_can_atlas_2018_mutations\",\"lihc_tcga_pan_can_atlas_2018_mutations\",\"luad_tcga_pan_can_atlas_2018_mutations\",\"lusc_tcga_pan_can_atlas_2018_mutations\",\"meso_tcga_pan_can_atlas_2018_mutations\",\"ov_tcga_pan_can_atlas_2018_mutations\",\"paad_tcga_pan_can_atlas_2018_mutations\",\"pcpg_tcga_pan_can_atlas_2018_mutations\",\"prad_tcga_pan_can_atlas_2018_mutations\",\"sarc_tcga_pan_can_atlas_2018_mutations\",\"skcm_tcga_pan_can_atlas_2018_mutations\",\"stad_tcga_pan_can_atlas_2018_mutations\",\"tgct_tcga_pan_can_atlas_2018_mutations\",\"thca_tcga_pan_can_atlas_2018_mutations\",\"thym_tcga_pan_can_atlas_2018_mutations\",\"ucec_tcga_pan_can_atlas_2018_mutations\",\"ucs_tcga_pan_can_atlas_2018_mutations\",\"uvm_tcga_pan_can_atlas_2018_mutations\"],\"geneQueries\":[[{\"hugoGeneSymbol\":\"TP53\",\"entrezGeneId\":0,\"alterations\":[],\"includeDriver\":true,\"includeVUS\":true,\"includeUnknownOncogenicity\":true,\"tiersBooleanMap\":{},\"includeUnknownTier\":true,\"includeGermline\":true,\"includeSomatic\":true,\"includeUnknownStatus\":true}]]}],\"studyIds\":[\"ov_tcga_pan_can_atlas_2018\",\"nsclc_public_genie_bpc\",\"kirc_tcga_pan_can_atlas_2018\",\"kirp_tcga_pan_can_atlas_2018\",\"kich_tcga_pan_can_atlas_2018\",\"acc_tcga_pan_can_atlas_2018\",\"chol_tcga_pan_can_atlas_2018\",\"blca_tcga_pan_can_atlas_2018\",\"coadread_tcga_pan_can_atlas_2018\",\"brca_tcga_pan_can_atlas_2018\",\"lgg_tcga_pan_can_atlas_2018\",\"gbm_tcga_pan_can_atlas_2018\",\"cesc_tcga_pan_can_atlas_2018\",\"esca_tcga_pan_can_atlas_2018\",\"stad_tcga_pan_can_atlas_2018\",\"uvm_tcga_pan_can_atlas_2018\",\"hnsc_tcga_pan_can_atlas_2018\",\"lihc_tcga_pan_can_atlas_2018\",\"luad_tcga_pan_can_atlas_2018\",\"lusc_tcga_pan_can_atlas_2018\",\"dlbc_tcga_pan_can_atlas_2018\",\"laml_tcga_pan_can_atlas_2018\",\"paad_tcga_pan_can_atlas_2018\",\"meso_tcga_pan_can_atlas_2018\",\"skcm_tcga_pan_can_atlas_2018\",\"prad_tcga_pan_can_atlas_2018\",\"pcpg_tcga_pan_can_atlas_2018\",\"sarc_tcga_pan_can_atlas_2018\",\"tgct_tcga_pan_can_atlas_2018\",\"thym_tcga_pan_can_atlas_2018\",\"thca_tcga_pan_can_atlas_2018\",\"ucec_tcga_pan_can_atlas_2018\",\"ucs_tcga_pan_can_atlas_2018\"],\"alterationFilter\":{\"copyNumberAlterationEventTypes\":{\"AMP\":true,\"HOMDEL\":true},\"mutationEventTypes\":{\"any\":true},\"structuralVariants\":null,\"includeDriver\":true,\"includeVUS\":true,\"includeUnknownOncogenicity\":true,\"includeUnknownTier\":true,\"includeGermline\":true,\"includeSomatic\":true,\"includeUnknownStatus\":true,\"tiersBooleanMap\":{}}}"}, + {"hash":2133353191, + "skip": "off panel discrep", + "filterString":"TP53","data":{"geneFilters":[{"molecularProfileIds":["nsclc_public_genie_bpc_mutations","acc_tcga_pan_can_atlas_2018_mutations","blca_tcga_pan_can_atlas_2018_mutations","brca_tcga_pan_can_atlas_2018_mutations","cesc_tcga_pan_can_atlas_2018_mutations","coadread_tcga_pan_can_atlas_2018_mutations","chol_tcga_pan_can_atlas_2018_mutations","dlbc_tcga_pan_can_atlas_2018_mutations","esca_tcga_pan_can_atlas_2018_mutations","gbm_tcga_pan_can_atlas_2018_mutations","hnsc_tcga_pan_can_atlas_2018_mutations","kich_tcga_pan_can_atlas_2018_mutations","kirc_tcga_pan_can_atlas_2018_mutations","kirp_tcga_pan_can_atlas_2018_mutations","laml_tcga_pan_can_atlas_2018_mutations","lgg_tcga_pan_can_atlas_2018_mutations","lihc_tcga_pan_can_atlas_2018_mutations","luad_tcga_pan_can_atlas_2018_mutations","lusc_tcga_pan_can_atlas_2018_mutations","meso_tcga_pan_can_atlas_2018_mutations","ov_tcga_pan_can_atlas_2018_mutations","paad_tcga_pan_can_atlas_2018_mutations","pcpg_tcga_pan_can_atlas_2018_mutations","prad_tcga_pan_can_atlas_2018_mutations","sarc_tcga_pan_can_atlas_2018_mutations","skcm_tcga_pan_can_atlas_2018_mutations","stad_tcga_pan_can_atlas_2018_mutations","tgct_tcga_pan_can_atlas_2018_mutations","thca_tcga_pan_can_atlas_2018_mutations","thym_tcga_pan_can_atlas_2018_mutations","ucec_tcga_pan_can_atlas_2018_mutations","ucs_tcga_pan_can_atlas_2018_mutations","uvm_tcga_pan_can_atlas_2018_mutations"],"geneQueries":[[{"hugoGeneSymbol":"TP53","entrezGeneId":0,"alterations":[],"includeDriver":true,"includeVUS":true,"includeUnknownOncogenicity":true,"tiersBooleanMap":{},"includeUnknownTier":true,"includeGermline":true,"includeSomatic":true,"includeUnknownStatus":true}]]}],"studyIds":["ov_tcga_pan_can_atlas_2018","nsclc_public_genie_bpc","kirc_tcga_pan_can_atlas_2018","kirp_tcga_pan_can_atlas_2018","kich_tcga_pan_can_atlas_2018","acc_tcga_pan_can_atlas_2018","chol_tcga_pan_can_atlas_2018","blca_tcga_pan_can_atlas_2018","coadread_tcga_pan_can_atlas_2018","brca_tcga_pan_can_atlas_2018","lgg_tcga_pan_can_atlas_2018","gbm_tcga_pan_can_atlas_2018","cesc_tcga_pan_can_atlas_2018","esca_tcga_pan_can_atlas_2018","stad_tcga_pan_can_atlas_2018","uvm_tcga_pan_can_atlas_2018","hnsc_tcga_pan_can_atlas_2018","lihc_tcga_pan_can_atlas_2018","luad_tcga_pan_can_atlas_2018","lusc_tcga_pan_can_atlas_2018","dlbc_tcga_pan_can_atlas_2018","laml_tcga_pan_can_atlas_2018","paad_tcga_pan_can_atlas_2018","meso_tcga_pan_can_atlas_2018","skcm_tcga_pan_can_atlas_2018","prad_tcga_pan_can_atlas_2018","pcpg_tcga_pan_can_atlas_2018","sarc_tcga_pan_can_atlas_2018","tgct_tcga_pan_can_atlas_2018","thym_tcga_pan_can_atlas_2018","thca_tcga_pan_can_atlas_2018","ucec_tcga_pan_can_atlas_2018","ucs_tcga_pan_can_atlas_2018"],"alterationFilter":{"copyNumberAlterationEventTypes":{"AMP":true,"HOMDEL":true},"mutationEventTypes":{"any":true},"structuralVariants":null,"includeDriver":true,"includeVUS":true,"includeUnknownOncogenicity":true,"includeUnknownTier":true,"includeGermline":true,"includeSomatic":true,"includeUnknownStatus":true,"tiersBooleanMap":{}}},"url":"/api/column-store/mutated-genes/fetch?","label":"MutatedGenes","studies":["ov_tcga_pan_can_atlas_2018","nsclc_public_genie_bpc","kirc_tcga_pan_can_atlas_2018","kirp_tcga_pan_can_atlas_2018","kich_tcga_pan_can_atlas_2018","acc_tcga_pan_can_atlas_2018","chol_tcga_pan_can_atlas_2018","blca_tcga_pan_can_atlas_2018","coadread_tcga_pan_can_atlas_2018","brca_tcga_pan_can_atlas_2018","lgg_tcga_pan_can_atlas_2018","gbm_tcga_pan_can_atlas_2018","cesc_tcga_pan_can_atlas_2018","esca_tcga_pan_can_atlas_2018","stad_tcga_pan_can_atlas_2018","uvm_tcga_pan_can_atlas_2018","hnsc_tcga_pan_can_atlas_2018","lihc_tcga_pan_can_atlas_2018","luad_tcga_pan_can_atlas_2018","lusc_tcga_pan_can_atlas_2018","dlbc_tcga_pan_can_atlas_2018","laml_tcga_pan_can_atlas_2018","paad_tcga_pan_can_atlas_2018","meso_tcga_pan_can_atlas_2018","skcm_tcga_pan_can_atlas_2018","prad_tcga_pan_can_atlas_2018","pcpg_tcga_pan_can_atlas_2018","sarc_tcga_pan_can_atlas_2018","tgct_tcga_pan_can_atlas_2018","thym_tcga_pan_can_atlas_2018","thca_tcga_pan_can_atlas_2018","ucec_tcga_pan_can_atlas_2018","ucs_tcga_pan_can_atlas_2018"],"filterUrl":"/study/summary?id=ov_tcga_pan_can_atlas_2018%2Cnsclc_public_genie_bpc%2Ckirc_tcga_pan_can_atlas_2018%2Ckirp_tcga_pan_can_atlas_2018%2Ckich_tcga_pan_can_atlas_2018%2Cacc_tcga_pan_can_atlas_2018%2Cchol_tcga_pan_can_atlas_2018%2Cblca_tcga_pan_can_atlas_2018%2Ccoadread_tcga_pan_can_atlas_2018%2Cbrca_tcga_pan_can_atlas_2018%2Clgg_tcga_pan_can_atlas_2018%2Cgbm_tcga_pan_can_atlas_2018%2Ccesc_tcga_pan_can_atlas_2018%2Cesca_tcga_pan_can_atlas_2018%2Cstad_tcga_pan_can_atlas_2018%2Cuvm_tcga_pan_can_atlas_2018%2Chnsc_tcga_pan_can_atlas_2018%2Clihc_tcga_pan_can_atlas_2018%2Cluad_tcga_pan_can_atlas_2018%2Clusc_tcga_pan_can_atlas_2018%2Cdlbc_tcga_pan_can_atlas_2018%2Claml_tcga_pan_can_atlas_2018%2Cpaad_tcga_pan_can_atlas_2018%2Cmeso_tcga_pan_can_atlas_2018%2Cskcm_tcga_pan_can_atlas_2018%2Cprad_tcga_pan_can_atlas_2018%2Cpcpg_tcga_pan_can_atlas_2018%2Csarc_tcga_pan_can_atlas_2018%2Ctgct_tcga_pan_can_atlas_2018%2Cthym_tcga_pan_can_atlas_2018%2Cthca_tcga_pan_can_atlas_2018%2Cucec_tcga_pan_can_atlas_2018%2Cucs_tcga_pan_can_atlas_2018#filterJson={\"geneFilters\":[{\"molecularProfileIds\":[\"nsclc_public_genie_bpc_mutations\",\"acc_tcga_pan_can_atlas_2018_mutations\",\"blca_tcga_pan_can_atlas_2018_mutations\",\"brca_tcga_pan_can_atlas_2018_mutations\",\"cesc_tcga_pan_can_atlas_2018_mutations\",\"coadread_tcga_pan_can_atlas_2018_mutations\",\"chol_tcga_pan_can_atlas_2018_mutations\",\"dlbc_tcga_pan_can_atlas_2018_mutations\",\"esca_tcga_pan_can_atlas_2018_mutations\",\"gbm_tcga_pan_can_atlas_2018_mutations\",\"hnsc_tcga_pan_can_atlas_2018_mutations\",\"kich_tcga_pan_can_atlas_2018_mutations\",\"kirc_tcga_pan_can_atlas_2018_mutations\",\"kirp_tcga_pan_can_atlas_2018_mutations\",\"laml_tcga_pan_can_atlas_2018_mutations\",\"lgg_tcga_pan_can_atlas_2018_mutations\",\"lihc_tcga_pan_can_atlas_2018_mutations\",\"luad_tcga_pan_can_atlas_2018_mutations\",\"lusc_tcga_pan_can_atlas_2018_mutations\",\"meso_tcga_pan_can_atlas_2018_mutations\",\"ov_tcga_pan_can_atlas_2018_mutations\",\"paad_tcga_pan_can_atlas_2018_mutations\",\"pcpg_tcga_pan_can_atlas_2018_mutations\",\"prad_tcga_pan_can_atlas_2018_mutations\",\"sarc_tcga_pan_can_atlas_2018_mutations\",\"skcm_tcga_pan_can_atlas_2018_mutations\",\"stad_tcga_pan_can_atlas_2018_mutations\",\"tgct_tcga_pan_can_atlas_2018_mutations\",\"thca_tcga_pan_can_atlas_2018_mutations\",\"thym_tcga_pan_can_atlas_2018_mutations\",\"ucec_tcga_pan_can_atlas_2018_mutations\",\"ucs_tcga_pan_can_atlas_2018_mutations\",\"uvm_tcga_pan_can_atlas_2018_mutations\"],\"geneQueries\":[[{\"hugoGeneSymbol\":\"TP53\",\"entrezGeneId\":0,\"alterations\":[],\"includeDriver\":true,\"includeVUS\":true,\"includeUnknownOncogenicity\":true,\"tiersBooleanMap\":{},\"includeUnknownTier\":true,\"includeGermline\":true,\"includeSomatic\":true,\"includeUnknownStatus\":true}]]}],\"studyIds\":[\"ov_tcga_pan_can_atlas_2018\",\"nsclc_public_genie_bpc\",\"kirc_tcga_pan_can_atlas_2018\",\"kirp_tcga_pan_can_atlas_2018\",\"kich_tcga_pan_can_atlas_2018\",\"acc_tcga_pan_can_atlas_2018\",\"chol_tcga_pan_can_atlas_2018\",\"blca_tcga_pan_can_atlas_2018\",\"coadread_tcga_pan_can_atlas_2018\",\"brca_tcga_pan_can_atlas_2018\",\"lgg_tcga_pan_can_atlas_2018\",\"gbm_tcga_pan_can_atlas_2018\",\"cesc_tcga_pan_can_atlas_2018\",\"esca_tcga_pan_can_atlas_2018\",\"stad_tcga_pan_can_atlas_2018\",\"uvm_tcga_pan_can_atlas_2018\",\"hnsc_tcga_pan_can_atlas_2018\",\"lihc_tcga_pan_can_atlas_2018\",\"luad_tcga_pan_can_atlas_2018\",\"lusc_tcga_pan_can_atlas_2018\",\"dlbc_tcga_pan_can_atlas_2018\",\"laml_tcga_pan_can_atlas_2018\",\"paad_tcga_pan_can_atlas_2018\",\"meso_tcga_pan_can_atlas_2018\",\"skcm_tcga_pan_can_atlas_2018\",\"prad_tcga_pan_can_atlas_2018\",\"pcpg_tcga_pan_can_atlas_2018\",\"sarc_tcga_pan_can_atlas_2018\",\"tgct_tcga_pan_can_atlas_2018\",\"thym_tcga_pan_can_atlas_2018\",\"thca_tcga_pan_can_atlas_2018\",\"ucec_tcga_pan_can_atlas_2018\",\"ucs_tcga_pan_can_atlas_2018\"],\"alterationFilter\":{\"copyNumberAlterationEventTypes\":{\"AMP\":true,\"HOMDEL\":true},\"mutationEventTypes\":{\"any\":true},\"structuralVariants\":null,\"includeDriver\":true,\"includeVUS\":true,\"includeUnknownOncogenicity\":true,\"includeUnknownTier\":true,\"includeGermline\":true,\"includeSomatic\":true,\"includeUnknownStatus\":true,\"tiersBooleanMap\":{}}}"}, {"hash":-201846160,"filterString":"TP53","data":{"attributes":[{"attributeId":"MUTATION_COUNT","disableLogScale":false,"showNA":false},{"attributeId":"FRACTION_GENOME_ALTERED","disableLogScale":false,"showNA":false},{"attributeId":"AGE","disableLogScale":false,"showNA":false},{"attributeId":"MSI_SCORE_MANTIS","disableLogScale":false,"showNA":false,"customBins":[0.4,0.6]},{"attributeId":"MSI_SENSOR_SCORE","disableLogScale":false,"showNA":false,"customBins":[4,10]},{"attributeId":"AGE_AT_SEQUENCING","disableLogScale":false,"showNA":false},{"attributeId":"ANEUPLOIDY_SCORE","disableLogScale":false,"showNA":false}],"studyViewFilter":{"geneFilters":[{"molecularProfileIds":["nsclc_public_genie_bpc_mutations","acc_tcga_pan_can_atlas_2018_mutations","blca_tcga_pan_can_atlas_2018_mutations","brca_tcga_pan_can_atlas_2018_mutations","cesc_tcga_pan_can_atlas_2018_mutations","coadread_tcga_pan_can_atlas_2018_mutations","chol_tcga_pan_can_atlas_2018_mutations","dlbc_tcga_pan_can_atlas_2018_mutations","esca_tcga_pan_can_atlas_2018_mutations","gbm_tcga_pan_can_atlas_2018_mutations","hnsc_tcga_pan_can_atlas_2018_mutations","kich_tcga_pan_can_atlas_2018_mutations","kirc_tcga_pan_can_atlas_2018_mutations","kirp_tcga_pan_can_atlas_2018_mutations","laml_tcga_pan_can_atlas_2018_mutations","lgg_tcga_pan_can_atlas_2018_mutations","lihc_tcga_pan_can_atlas_2018_mutations","luad_tcga_pan_can_atlas_2018_mutations","lusc_tcga_pan_can_atlas_2018_mutations","meso_tcga_pan_can_atlas_2018_mutations","ov_tcga_pan_can_atlas_2018_mutations","paad_tcga_pan_can_atlas_2018_mutations","pcpg_tcga_pan_can_atlas_2018_mutations","prad_tcga_pan_can_atlas_2018_mutations","sarc_tcga_pan_can_atlas_2018_mutations","skcm_tcga_pan_can_atlas_2018_mutations","stad_tcga_pan_can_atlas_2018_mutations","tgct_tcga_pan_can_atlas_2018_mutations","thca_tcga_pan_can_atlas_2018_mutations","thym_tcga_pan_can_atlas_2018_mutations","ucec_tcga_pan_can_atlas_2018_mutations","ucs_tcga_pan_can_atlas_2018_mutations","uvm_tcga_pan_can_atlas_2018_mutations"],"geneQueries":[[{"hugoGeneSymbol":"TP53","entrezGeneId":0,"alterations":[],"includeDriver":true,"includeVUS":true,"includeUnknownOncogenicity":true,"tiersBooleanMap":{},"includeUnknownTier":true,"includeGermline":true,"includeSomatic":true,"includeUnknownStatus":true}]]}],"studyIds":["ov_tcga_pan_can_atlas_2018","nsclc_public_genie_bpc","kirc_tcga_pan_can_atlas_2018","kirp_tcga_pan_can_atlas_2018","kich_tcga_pan_can_atlas_2018","acc_tcga_pan_can_atlas_2018","chol_tcga_pan_can_atlas_2018","blca_tcga_pan_can_atlas_2018","coadread_tcga_pan_can_atlas_2018","brca_tcga_pan_can_atlas_2018","lgg_tcga_pan_can_atlas_2018","gbm_tcga_pan_can_atlas_2018","cesc_tcga_pan_can_atlas_2018","esca_tcga_pan_can_atlas_2018","stad_tcga_pan_can_atlas_2018","uvm_tcga_pan_can_atlas_2018","hnsc_tcga_pan_can_atlas_2018","lihc_tcga_pan_can_atlas_2018","luad_tcga_pan_can_atlas_2018","lusc_tcga_pan_can_atlas_2018","dlbc_tcga_pan_can_atlas_2018","laml_tcga_pan_can_atlas_2018","paad_tcga_pan_can_atlas_2018","meso_tcga_pan_can_atlas_2018","skcm_tcga_pan_can_atlas_2018","prad_tcga_pan_can_atlas_2018","pcpg_tcga_pan_can_atlas_2018","sarc_tcga_pan_can_atlas_2018","tgct_tcga_pan_can_atlas_2018","thym_tcga_pan_can_atlas_2018","thca_tcga_pan_can_atlas_2018","ucec_tcga_pan_can_atlas_2018","ucs_tcga_pan_can_atlas_2018"],"alterationFilter":{"copyNumberAlterationEventTypes":{"AMP":true,"HOMDEL":true},"mutationEventTypes":{"any":true},"structuralVariants":null,"includeDriver":true,"includeVUS":true,"includeUnknownOncogenicity":true,"includeUnknownTier":true,"includeGermline":true,"includeSomatic":true,"includeUnknownStatus":true,"tiersBooleanMap":{}}}},"url":"/api/column-store/clinical-data-bin-counts/fetch?dataBinMethod=STATIC&","label":"ClinicalDataBin","studies":["ov_tcga_pan_can_atlas_2018","nsclc_public_genie_bpc","kirc_tcga_pan_can_atlas_2018","kirp_tcga_pan_can_atlas_2018","kich_tcga_pan_can_atlas_2018","acc_tcga_pan_can_atlas_2018","chol_tcga_pan_can_atlas_2018","blca_tcga_pan_can_atlas_2018","coadread_tcga_pan_can_atlas_2018","brca_tcga_pan_can_atlas_2018","lgg_tcga_pan_can_atlas_2018","gbm_tcga_pan_can_atlas_2018","cesc_tcga_pan_can_atlas_2018","esca_tcga_pan_can_atlas_2018","stad_tcga_pan_can_atlas_2018","uvm_tcga_pan_can_atlas_2018","hnsc_tcga_pan_can_atlas_2018","lihc_tcga_pan_can_atlas_2018","luad_tcga_pan_can_atlas_2018","lusc_tcga_pan_can_atlas_2018","dlbc_tcga_pan_can_atlas_2018","laml_tcga_pan_can_atlas_2018","paad_tcga_pan_can_atlas_2018","meso_tcga_pan_can_atlas_2018","skcm_tcga_pan_can_atlas_2018","prad_tcga_pan_can_atlas_2018","pcpg_tcga_pan_can_atlas_2018","sarc_tcga_pan_can_atlas_2018","tgct_tcga_pan_can_atlas_2018","thym_tcga_pan_can_atlas_2018","thca_tcga_pan_can_atlas_2018","ucec_tcga_pan_can_atlas_2018","ucs_tcga_pan_can_atlas_2018"],"filterUrl":"/study/summary?id=ov_tcga_pan_can_atlas_2018%2Cnsclc_public_genie_bpc%2Ckirc_tcga_pan_can_atlas_2018%2Ckirp_tcga_pan_can_atlas_2018%2Ckich_tcga_pan_can_atlas_2018%2Cacc_tcga_pan_can_atlas_2018%2Cchol_tcga_pan_can_atlas_2018%2Cblca_tcga_pan_can_atlas_2018%2Ccoadread_tcga_pan_can_atlas_2018%2Cbrca_tcga_pan_can_atlas_2018%2Clgg_tcga_pan_can_atlas_2018%2Cgbm_tcga_pan_can_atlas_2018%2Ccesc_tcga_pan_can_atlas_2018%2Cesca_tcga_pan_can_atlas_2018%2Cstad_tcga_pan_can_atlas_2018%2Cuvm_tcga_pan_can_atlas_2018%2Chnsc_tcga_pan_can_atlas_2018%2Clihc_tcga_pan_can_atlas_2018%2Cluad_tcga_pan_can_atlas_2018%2Clusc_tcga_pan_can_atlas_2018%2Cdlbc_tcga_pan_can_atlas_2018%2Claml_tcga_pan_can_atlas_2018%2Cpaad_tcga_pan_can_atlas_2018%2Cmeso_tcga_pan_can_atlas_2018%2Cskcm_tcga_pan_can_atlas_2018%2Cprad_tcga_pan_can_atlas_2018%2Cpcpg_tcga_pan_can_atlas_2018%2Csarc_tcga_pan_can_atlas_2018%2Ctgct_tcga_pan_can_atlas_2018%2Cthym_tcga_pan_can_atlas_2018%2Cthca_tcga_pan_can_atlas_2018%2Cucec_tcga_pan_can_atlas_2018%2Cucs_tcga_pan_can_atlas_2018#filterJson={\"geneFilters\":[{\"molecularProfileIds\":[\"nsclc_public_genie_bpc_mutations\",\"acc_tcga_pan_can_atlas_2018_mutations\",\"blca_tcga_pan_can_atlas_2018_mutations\",\"brca_tcga_pan_can_atlas_2018_mutations\",\"cesc_tcga_pan_can_atlas_2018_mutations\",\"coadread_tcga_pan_can_atlas_2018_mutations\",\"chol_tcga_pan_can_atlas_2018_mutations\",\"dlbc_tcga_pan_can_atlas_2018_mutations\",\"esca_tcga_pan_can_atlas_2018_mutations\",\"gbm_tcga_pan_can_atlas_2018_mutations\",\"hnsc_tcga_pan_can_atlas_2018_mutations\",\"kich_tcga_pan_can_atlas_2018_mutations\",\"kirc_tcga_pan_can_atlas_2018_mutations\",\"kirp_tcga_pan_can_atlas_2018_mutations\",\"laml_tcga_pan_can_atlas_2018_mutations\",\"lgg_tcga_pan_can_atlas_2018_mutations\",\"lihc_tcga_pan_can_atlas_2018_mutations\",\"luad_tcga_pan_can_atlas_2018_mutations\",\"lusc_tcga_pan_can_atlas_2018_mutations\",\"meso_tcga_pan_can_atlas_2018_mutations\",\"ov_tcga_pan_can_atlas_2018_mutations\",\"paad_tcga_pan_can_atlas_2018_mutations\",\"pcpg_tcga_pan_can_atlas_2018_mutations\",\"prad_tcga_pan_can_atlas_2018_mutations\",\"sarc_tcga_pan_can_atlas_2018_mutations\",\"skcm_tcga_pan_can_atlas_2018_mutations\",\"stad_tcga_pan_can_atlas_2018_mutations\",\"tgct_tcga_pan_can_atlas_2018_mutations\",\"thca_tcga_pan_can_atlas_2018_mutations\",\"thym_tcga_pan_can_atlas_2018_mutations\",\"ucec_tcga_pan_can_atlas_2018_mutations\",\"ucs_tcga_pan_can_atlas_2018_mutations\",\"uvm_tcga_pan_can_atlas_2018_mutations\"],\"geneQueries\":[[{\"hugoGeneSymbol\":\"TP53\",\"entrezGeneId\":0,\"alterations\":[],\"includeDriver\":true,\"includeVUS\":true,\"includeUnknownOncogenicity\":true,\"tiersBooleanMap\":{},\"includeUnknownTier\":true,\"includeGermline\":true,\"includeSomatic\":true,\"includeUnknownStatus\":true}]]}],\"studyIds\":[\"ov_tcga_pan_can_atlas_2018\",\"nsclc_public_genie_bpc\",\"kirc_tcga_pan_can_atlas_2018\",\"kirp_tcga_pan_can_atlas_2018\",\"kich_tcga_pan_can_atlas_2018\",\"acc_tcga_pan_can_atlas_2018\",\"chol_tcga_pan_can_atlas_2018\",\"blca_tcga_pan_can_atlas_2018\",\"coadread_tcga_pan_can_atlas_2018\",\"brca_tcga_pan_can_atlas_2018\",\"lgg_tcga_pan_can_atlas_2018\",\"gbm_tcga_pan_can_atlas_2018\",\"cesc_tcga_pan_can_atlas_2018\",\"esca_tcga_pan_can_atlas_2018\",\"stad_tcga_pan_can_atlas_2018\",\"uvm_tcga_pan_can_atlas_2018\",\"hnsc_tcga_pan_can_atlas_2018\",\"lihc_tcga_pan_can_atlas_2018\",\"luad_tcga_pan_can_atlas_2018\",\"lusc_tcga_pan_can_atlas_2018\",\"dlbc_tcga_pan_can_atlas_2018\",\"laml_tcga_pan_can_atlas_2018\",\"paad_tcga_pan_can_atlas_2018\",\"meso_tcga_pan_can_atlas_2018\",\"skcm_tcga_pan_can_atlas_2018\",\"prad_tcga_pan_can_atlas_2018\",\"pcpg_tcga_pan_can_atlas_2018\",\"sarc_tcga_pan_can_atlas_2018\",\"tgct_tcga_pan_can_atlas_2018\",\"thym_tcga_pan_can_atlas_2018\",\"thca_tcga_pan_can_atlas_2018\",\"ucec_tcga_pan_can_atlas_2018\",\"ucs_tcga_pan_can_atlas_2018\"],\"alterationFilter\":{\"copyNumberAlterationEventTypes\":{\"AMP\":true,\"HOMDEL\":true},\"mutationEventTypes\":{\"any\":true},\"structuralVariants\":null,\"includeDriver\":true,\"includeVUS\":true,\"includeUnknownOncogenicity\":true,\"includeUnknownTier\":true,\"includeGermline\":true,\"includeSomatic\":true,\"includeUnknownStatus\":true,\"tiersBooleanMap\":{}}}"}, @@ -77,9 +79,11 @@ {"hash":-337484351,"filterString":"TP53","data":{"geneFilters":[{"molecularProfileIds":["nsclc_public_genie_bpc_mutations","acc_tcga_pan_can_atlas_2018_mutations","blca_tcga_pan_can_atlas_2018_mutations","brca_tcga_pan_can_atlas_2018_mutations","cesc_tcga_pan_can_atlas_2018_mutations","coadread_tcga_pan_can_atlas_2018_mutations","chol_tcga_pan_can_atlas_2018_mutations","dlbc_tcga_pan_can_atlas_2018_mutations","esca_tcga_pan_can_atlas_2018_mutations","gbm_tcga_pan_can_atlas_2018_mutations","hnsc_tcga_pan_can_atlas_2018_mutations","kich_tcga_pan_can_atlas_2018_mutations","kirc_tcga_pan_can_atlas_2018_mutations","kirp_tcga_pan_can_atlas_2018_mutations","laml_tcga_pan_can_atlas_2018_mutations","lgg_tcga_pan_can_atlas_2018_mutations","lihc_tcga_pan_can_atlas_2018_mutations","luad_tcga_pan_can_atlas_2018_mutations","lusc_tcga_pan_can_atlas_2018_mutations","meso_tcga_pan_can_atlas_2018_mutations","ov_tcga_pan_can_atlas_2018_mutations","paad_tcga_pan_can_atlas_2018_mutations","pcpg_tcga_pan_can_atlas_2018_mutations","prad_tcga_pan_can_atlas_2018_mutations","sarc_tcga_pan_can_atlas_2018_mutations","skcm_tcga_pan_can_atlas_2018_mutations","stad_tcga_pan_can_atlas_2018_mutations","tgct_tcga_pan_can_atlas_2018_mutations","thca_tcga_pan_can_atlas_2018_mutations","thym_tcga_pan_can_atlas_2018_mutations","ucec_tcga_pan_can_atlas_2018_mutations","ucs_tcga_pan_can_atlas_2018_mutations","uvm_tcga_pan_can_atlas_2018_mutations"],"geneQueries":[[{"hugoGeneSymbol":"TP53","entrezGeneId":0,"alterations":[],"includeDriver":true,"includeVUS":true,"includeUnknownOncogenicity":true,"tiersBooleanMap":{},"includeUnknownTier":true,"includeGermline":true,"includeSomatic":true,"includeUnknownStatus":true}]]}],"studyIds":["ov_tcga_pan_can_atlas_2018","nsclc_public_genie_bpc","kirc_tcga_pan_can_atlas_2018","kirp_tcga_pan_can_atlas_2018","kich_tcga_pan_can_atlas_2018","acc_tcga_pan_can_atlas_2018","chol_tcga_pan_can_atlas_2018","blca_tcga_pan_can_atlas_2018","coadread_tcga_pan_can_atlas_2018","brca_tcga_pan_can_atlas_2018","lgg_tcga_pan_can_atlas_2018","gbm_tcga_pan_can_atlas_2018","cesc_tcga_pan_can_atlas_2018","esca_tcga_pan_can_atlas_2018","stad_tcga_pan_can_atlas_2018","uvm_tcga_pan_can_atlas_2018","hnsc_tcga_pan_can_atlas_2018","lihc_tcga_pan_can_atlas_2018","luad_tcga_pan_can_atlas_2018","lusc_tcga_pan_can_atlas_2018","dlbc_tcga_pan_can_atlas_2018","laml_tcga_pan_can_atlas_2018","paad_tcga_pan_can_atlas_2018","meso_tcga_pan_can_atlas_2018","skcm_tcga_pan_can_atlas_2018","prad_tcga_pan_can_atlas_2018","pcpg_tcga_pan_can_atlas_2018","sarc_tcga_pan_can_atlas_2018","tgct_tcga_pan_can_atlas_2018","thym_tcga_pan_can_atlas_2018","thca_tcga_pan_can_atlas_2018","ucec_tcga_pan_can_atlas_2018","ucs_tcga_pan_can_atlas_2018"],"alterationFilter":{"copyNumberAlterationEventTypes":{"AMP":true,"HOMDEL":true},"mutationEventTypes":{"any":true},"structuralVariants":null,"includeDriver":true,"includeVUS":true,"includeUnknownOncogenicity":true,"includeUnknownTier":true,"includeGermline":true,"includeSomatic":true,"includeUnknownStatus":true,"tiersBooleanMap":{}}},"url":"/api/column-store/clinical-data-density-plot/fetch?xAxisAttributeId=FRACTION_GENOME_ALTERED&xAxisBinCount=44&xAxisStart=0&xAxisEnd=1&yAxisAttributeId=MUTATION_COUNT&yAxisBinCount=38&yAxisStart=0&xAxisLogScale=false&yAxisLogScale=false&","label":"ClinicalDataDensity","studies":["ov_tcga_pan_can_atlas_2018","nsclc_public_genie_bpc","kirc_tcga_pan_can_atlas_2018","kirp_tcga_pan_can_atlas_2018","kich_tcga_pan_can_atlas_2018","acc_tcga_pan_can_atlas_2018","chol_tcga_pan_can_atlas_2018","blca_tcga_pan_can_atlas_2018","coadread_tcga_pan_can_atlas_2018","brca_tcga_pan_can_atlas_2018","lgg_tcga_pan_can_atlas_2018","gbm_tcga_pan_can_atlas_2018","cesc_tcga_pan_can_atlas_2018","esca_tcga_pan_can_atlas_2018","stad_tcga_pan_can_atlas_2018","uvm_tcga_pan_can_atlas_2018","hnsc_tcga_pan_can_atlas_2018","lihc_tcga_pan_can_atlas_2018","luad_tcga_pan_can_atlas_2018","lusc_tcga_pan_can_atlas_2018","dlbc_tcga_pan_can_atlas_2018","laml_tcga_pan_can_atlas_2018","paad_tcga_pan_can_atlas_2018","meso_tcga_pan_can_atlas_2018","skcm_tcga_pan_can_atlas_2018","prad_tcga_pan_can_atlas_2018","pcpg_tcga_pan_can_atlas_2018","sarc_tcga_pan_can_atlas_2018","tgct_tcga_pan_can_atlas_2018","thym_tcga_pan_can_atlas_2018","thca_tcga_pan_can_atlas_2018","ucec_tcga_pan_can_atlas_2018","ucs_tcga_pan_can_atlas_2018"],"filterUrl":"/study/summary?id=ov_tcga_pan_can_atlas_2018%2Cnsclc_public_genie_bpc%2Ckirc_tcga_pan_can_atlas_2018%2Ckirp_tcga_pan_can_atlas_2018%2Ckich_tcga_pan_can_atlas_2018%2Cacc_tcga_pan_can_atlas_2018%2Cchol_tcga_pan_can_atlas_2018%2Cblca_tcga_pan_can_atlas_2018%2Ccoadread_tcga_pan_can_atlas_2018%2Cbrca_tcga_pan_can_atlas_2018%2Clgg_tcga_pan_can_atlas_2018%2Cgbm_tcga_pan_can_atlas_2018%2Ccesc_tcga_pan_can_atlas_2018%2Cesca_tcga_pan_can_atlas_2018%2Cstad_tcga_pan_can_atlas_2018%2Cuvm_tcga_pan_can_atlas_2018%2Chnsc_tcga_pan_can_atlas_2018%2Clihc_tcga_pan_can_atlas_2018%2Cluad_tcga_pan_can_atlas_2018%2Clusc_tcga_pan_can_atlas_2018%2Cdlbc_tcga_pan_can_atlas_2018%2Claml_tcga_pan_can_atlas_2018%2Cpaad_tcga_pan_can_atlas_2018%2Cmeso_tcga_pan_can_atlas_2018%2Cskcm_tcga_pan_can_atlas_2018%2Cprad_tcga_pan_can_atlas_2018%2Cpcpg_tcga_pan_can_atlas_2018%2Csarc_tcga_pan_can_atlas_2018%2Ctgct_tcga_pan_can_atlas_2018%2Cthym_tcga_pan_can_atlas_2018%2Cthca_tcga_pan_can_atlas_2018%2Cucec_tcga_pan_can_atlas_2018%2Cucs_tcga_pan_can_atlas_2018#filterJson={\"geneFilters\":[{\"molecularProfileIds\":[\"nsclc_public_genie_bpc_mutations\",\"acc_tcga_pan_can_atlas_2018_mutations\",\"blca_tcga_pan_can_atlas_2018_mutations\",\"brca_tcga_pan_can_atlas_2018_mutations\",\"cesc_tcga_pan_can_atlas_2018_mutations\",\"coadread_tcga_pan_can_atlas_2018_mutations\",\"chol_tcga_pan_can_atlas_2018_mutations\",\"dlbc_tcga_pan_can_atlas_2018_mutations\",\"esca_tcga_pan_can_atlas_2018_mutations\",\"gbm_tcga_pan_can_atlas_2018_mutations\",\"hnsc_tcga_pan_can_atlas_2018_mutations\",\"kich_tcga_pan_can_atlas_2018_mutations\",\"kirc_tcga_pan_can_atlas_2018_mutations\",\"kirp_tcga_pan_can_atlas_2018_mutations\",\"laml_tcga_pan_can_atlas_2018_mutations\",\"lgg_tcga_pan_can_atlas_2018_mutations\",\"lihc_tcga_pan_can_atlas_2018_mutations\",\"luad_tcga_pan_can_atlas_2018_mutations\",\"lusc_tcga_pan_can_atlas_2018_mutations\",\"meso_tcga_pan_can_atlas_2018_mutations\",\"ov_tcga_pan_can_atlas_2018_mutations\",\"paad_tcga_pan_can_atlas_2018_mutations\",\"pcpg_tcga_pan_can_atlas_2018_mutations\",\"prad_tcga_pan_can_atlas_2018_mutations\",\"sarc_tcga_pan_can_atlas_2018_mutations\",\"skcm_tcga_pan_can_atlas_2018_mutations\",\"stad_tcga_pan_can_atlas_2018_mutations\",\"tgct_tcga_pan_can_atlas_2018_mutations\",\"thca_tcga_pan_can_atlas_2018_mutations\",\"thym_tcga_pan_can_atlas_2018_mutations\",\"ucec_tcga_pan_can_atlas_2018_mutations\",\"ucs_tcga_pan_can_atlas_2018_mutations\",\"uvm_tcga_pan_can_atlas_2018_mutations\"],\"geneQueries\":[[{\"hugoGeneSymbol\":\"TP53\",\"entrezGeneId\":0,\"alterations\":[],\"includeDriver\":true,\"includeVUS\":true,\"includeUnknownOncogenicity\":true,\"tiersBooleanMap\":{},\"includeUnknownTier\":true,\"includeGermline\":true,\"includeSomatic\":true,\"includeUnknownStatus\":true}]]}],\"studyIds\":[\"ov_tcga_pan_can_atlas_2018\",\"nsclc_public_genie_bpc\",\"kirc_tcga_pan_can_atlas_2018\",\"kirp_tcga_pan_can_atlas_2018\",\"kich_tcga_pan_can_atlas_2018\",\"acc_tcga_pan_can_atlas_2018\",\"chol_tcga_pan_can_atlas_2018\",\"blca_tcga_pan_can_atlas_2018\",\"coadread_tcga_pan_can_atlas_2018\",\"brca_tcga_pan_can_atlas_2018\",\"lgg_tcga_pan_can_atlas_2018\",\"gbm_tcga_pan_can_atlas_2018\",\"cesc_tcga_pan_can_atlas_2018\",\"esca_tcga_pan_can_atlas_2018\",\"stad_tcga_pan_can_atlas_2018\",\"uvm_tcga_pan_can_atlas_2018\",\"hnsc_tcga_pan_can_atlas_2018\",\"lihc_tcga_pan_can_atlas_2018\",\"luad_tcga_pan_can_atlas_2018\",\"lusc_tcga_pan_can_atlas_2018\",\"dlbc_tcga_pan_can_atlas_2018\",\"laml_tcga_pan_can_atlas_2018\",\"paad_tcga_pan_can_atlas_2018\",\"meso_tcga_pan_can_atlas_2018\",\"skcm_tcga_pan_can_atlas_2018\",\"prad_tcga_pan_can_atlas_2018\",\"pcpg_tcga_pan_can_atlas_2018\",\"sarc_tcga_pan_can_atlas_2018\",\"tgct_tcga_pan_can_atlas_2018\",\"thym_tcga_pan_can_atlas_2018\",\"thca_tcga_pan_can_atlas_2018\",\"ucec_tcga_pan_can_atlas_2018\",\"ucs_tcga_pan_can_atlas_2018\"],\"alterationFilter\":{\"copyNumberAlterationEventTypes\":{\"AMP\":true,\"HOMDEL\":true},\"mutationEventTypes\":{\"any\":true},\"structuralVariants\":null,\"includeDriver\":true,\"includeVUS\":true,\"includeUnknownOncogenicity\":true,\"includeUnknownTier\":true,\"includeGermline\":true,\"includeSomatic\":true,\"includeUnknownStatus\":true,\"tiersBooleanMap\":{}}}"}, - {"hash":-1059079747,"skipMessage": "Legacy Imp merges counts with different entrez_ids","filterString":"TP53","data":{"geneFilters":[{"molecularProfileIds":["nsclc_public_genie_bpc_mutations","acc_tcga_pan_can_atlas_2018_mutations","blca_tcga_pan_can_atlas_2018_mutations","brca_tcga_pan_can_atlas_2018_mutations","cesc_tcga_pan_can_atlas_2018_mutations","coadread_tcga_pan_can_atlas_2018_mutations","chol_tcga_pan_can_atlas_2018_mutations","dlbc_tcga_pan_can_atlas_2018_mutations","esca_tcga_pan_can_atlas_2018_mutations","gbm_tcga_pan_can_atlas_2018_mutations","hnsc_tcga_pan_can_atlas_2018_mutations","kich_tcga_pan_can_atlas_2018_mutations","kirc_tcga_pan_can_atlas_2018_mutations","kirp_tcga_pan_can_atlas_2018_mutations","laml_tcga_pan_can_atlas_2018_mutations","lgg_tcga_pan_can_atlas_2018_mutations","lihc_tcga_pan_can_atlas_2018_mutations","luad_tcga_pan_can_atlas_2018_mutations","lusc_tcga_pan_can_atlas_2018_mutations","meso_tcga_pan_can_atlas_2018_mutations","ov_tcga_pan_can_atlas_2018_mutations","paad_tcga_pan_can_atlas_2018_mutations","pcpg_tcga_pan_can_atlas_2018_mutations","prad_tcga_pan_can_atlas_2018_mutations","sarc_tcga_pan_can_atlas_2018_mutations","skcm_tcga_pan_can_atlas_2018_mutations","stad_tcga_pan_can_atlas_2018_mutations","tgct_tcga_pan_can_atlas_2018_mutations","thca_tcga_pan_can_atlas_2018_mutations","thym_tcga_pan_can_atlas_2018_mutations","ucec_tcga_pan_can_atlas_2018_mutations","ucs_tcga_pan_can_atlas_2018_mutations","uvm_tcga_pan_can_atlas_2018_mutations"],"geneQueries":[[{"hugoGeneSymbol":"TP53","entrezGeneId":0,"alterations":[],"includeDriver":true,"includeVUS":true,"includeUnknownOncogenicity":true,"tiersBooleanMap":{},"includeUnknownTier":true,"includeGermline":true,"includeSomatic":true,"includeUnknownStatus":true}]]}],"studyIds":["ov_tcga_pan_can_atlas_2018","nsclc_public_genie_bpc","kirc_tcga_pan_can_atlas_2018","kirp_tcga_pan_can_atlas_2018","kich_tcga_pan_can_atlas_2018","acc_tcga_pan_can_atlas_2018","chol_tcga_pan_can_atlas_2018","blca_tcga_pan_can_atlas_2018","coadread_tcga_pan_can_atlas_2018","brca_tcga_pan_can_atlas_2018","lgg_tcga_pan_can_atlas_2018","gbm_tcga_pan_can_atlas_2018","cesc_tcga_pan_can_atlas_2018","esca_tcga_pan_can_atlas_2018","stad_tcga_pan_can_atlas_2018","uvm_tcga_pan_can_atlas_2018","hnsc_tcga_pan_can_atlas_2018","lihc_tcga_pan_can_atlas_2018","luad_tcga_pan_can_atlas_2018","lusc_tcga_pan_can_atlas_2018","dlbc_tcga_pan_can_atlas_2018","laml_tcga_pan_can_atlas_2018","paad_tcga_pan_can_atlas_2018","meso_tcga_pan_can_atlas_2018","skcm_tcga_pan_can_atlas_2018","prad_tcga_pan_can_atlas_2018","pcpg_tcga_pan_can_atlas_2018","sarc_tcga_pan_can_atlas_2018","tgct_tcga_pan_can_atlas_2018","thym_tcga_pan_can_atlas_2018","thca_tcga_pan_can_atlas_2018","ucec_tcga_pan_can_atlas_2018","ucs_tcga_pan_can_atlas_2018"],"alterationFilter":{"copyNumberAlterationEventTypes":{"AMP":true,"HOMDEL":true},"mutationEventTypes":{"any":true},"structuralVariants":null,"includeDriver":true,"includeVUS":true,"includeUnknownOncogenicity":true,"includeUnknownTier":true,"includeGermline":true,"includeSomatic":true,"includeUnknownStatus":true,"tiersBooleanMap":{}}},"url":"/api/column-store/structuralvariant-genes/fetch?","label":"StructuralVariantGenes","studies":["ov_tcga_pan_can_atlas_2018","nsclc_public_genie_bpc","kirc_tcga_pan_can_atlas_2018","kirp_tcga_pan_can_atlas_2018","kich_tcga_pan_can_atlas_2018","acc_tcga_pan_can_atlas_2018","chol_tcga_pan_can_atlas_2018","blca_tcga_pan_can_atlas_2018","coadread_tcga_pan_can_atlas_2018","brca_tcga_pan_can_atlas_2018","lgg_tcga_pan_can_atlas_2018","gbm_tcga_pan_can_atlas_2018","cesc_tcga_pan_can_atlas_2018","esca_tcga_pan_can_atlas_2018","stad_tcga_pan_can_atlas_2018","uvm_tcga_pan_can_atlas_2018","hnsc_tcga_pan_can_atlas_2018","lihc_tcga_pan_can_atlas_2018","luad_tcga_pan_can_atlas_2018","lusc_tcga_pan_can_atlas_2018","dlbc_tcga_pan_can_atlas_2018","laml_tcga_pan_can_atlas_2018","paad_tcga_pan_can_atlas_2018","meso_tcga_pan_can_atlas_2018","skcm_tcga_pan_can_atlas_2018","prad_tcga_pan_can_atlas_2018","pcpg_tcga_pan_can_atlas_2018","sarc_tcga_pan_can_atlas_2018","tgct_tcga_pan_can_atlas_2018","thym_tcga_pan_can_atlas_2018","thca_tcga_pan_can_atlas_2018","ucec_tcga_pan_can_atlas_2018","ucs_tcga_pan_can_atlas_2018"],"filterUrl":"/study/summary?id=ov_tcga_pan_can_atlas_2018%2Cnsclc_public_genie_bpc%2Ckirc_tcga_pan_can_atlas_2018%2Ckirp_tcga_pan_can_atlas_2018%2Ckich_tcga_pan_can_atlas_2018%2Cacc_tcga_pan_can_atlas_2018%2Cchol_tcga_pan_can_atlas_2018%2Cblca_tcga_pan_can_atlas_2018%2Ccoadread_tcga_pan_can_atlas_2018%2Cbrca_tcga_pan_can_atlas_2018%2Clgg_tcga_pan_can_atlas_2018%2Cgbm_tcga_pan_can_atlas_2018%2Ccesc_tcga_pan_can_atlas_2018%2Cesca_tcga_pan_can_atlas_2018%2Cstad_tcga_pan_can_atlas_2018%2Cuvm_tcga_pan_can_atlas_2018%2Chnsc_tcga_pan_can_atlas_2018%2Clihc_tcga_pan_can_atlas_2018%2Cluad_tcga_pan_can_atlas_2018%2Clusc_tcga_pan_can_atlas_2018%2Cdlbc_tcga_pan_can_atlas_2018%2Claml_tcga_pan_can_atlas_2018%2Cpaad_tcga_pan_can_atlas_2018%2Cmeso_tcga_pan_can_atlas_2018%2Cskcm_tcga_pan_can_atlas_2018%2Cprad_tcga_pan_can_atlas_2018%2Cpcpg_tcga_pan_can_atlas_2018%2Csarc_tcga_pan_can_atlas_2018%2Ctgct_tcga_pan_can_atlas_2018%2Cthym_tcga_pan_can_atlas_2018%2Cthca_tcga_pan_can_atlas_2018%2Cucec_tcga_pan_can_atlas_2018%2Cucs_tcga_pan_can_atlas_2018#filterJson={\"geneFilters\":[{\"molecularProfileIds\":[\"nsclc_public_genie_bpc_mutations\",\"acc_tcga_pan_can_atlas_2018_mutations\",\"blca_tcga_pan_can_atlas_2018_mutations\",\"brca_tcga_pan_can_atlas_2018_mutations\",\"cesc_tcga_pan_can_atlas_2018_mutations\",\"coadread_tcga_pan_can_atlas_2018_mutations\",\"chol_tcga_pan_can_atlas_2018_mutations\",\"dlbc_tcga_pan_can_atlas_2018_mutations\",\"esca_tcga_pan_can_atlas_2018_mutations\",\"gbm_tcga_pan_can_atlas_2018_mutations\",\"hnsc_tcga_pan_can_atlas_2018_mutations\",\"kich_tcga_pan_can_atlas_2018_mutations\",\"kirc_tcga_pan_can_atlas_2018_mutations\",\"kirp_tcga_pan_can_atlas_2018_mutations\",\"laml_tcga_pan_can_atlas_2018_mutations\",\"lgg_tcga_pan_can_atlas_2018_mutations\",\"lihc_tcga_pan_can_atlas_2018_mutations\",\"luad_tcga_pan_can_atlas_2018_mutations\",\"lusc_tcga_pan_can_atlas_2018_mutations\",\"meso_tcga_pan_can_atlas_2018_mutations\",\"ov_tcga_pan_can_atlas_2018_mutations\",\"paad_tcga_pan_can_atlas_2018_mutations\",\"pcpg_tcga_pan_can_atlas_2018_mutations\",\"prad_tcga_pan_can_atlas_2018_mutations\",\"sarc_tcga_pan_can_atlas_2018_mutations\",\"skcm_tcga_pan_can_atlas_2018_mutations\",\"stad_tcga_pan_can_atlas_2018_mutations\",\"tgct_tcga_pan_can_atlas_2018_mutations\",\"thca_tcga_pan_can_atlas_2018_mutations\",\"thym_tcga_pan_can_atlas_2018_mutations\",\"ucec_tcga_pan_can_atlas_2018_mutations\",\"ucs_tcga_pan_can_atlas_2018_mutations\",\"uvm_tcga_pan_can_atlas_2018_mutations\"],\"geneQueries\":[[{\"hugoGeneSymbol\":\"TP53\",\"entrezGeneId\":0,\"alterations\":[],\"includeDriver\":true,\"includeVUS\":true,\"includeUnknownOncogenicity\":true,\"tiersBooleanMap\":{},\"includeUnknownTier\":true,\"includeGermline\":true,\"includeSomatic\":true,\"includeUnknownStatus\":true}]]}],\"studyIds\":[\"ov_tcga_pan_can_atlas_2018\",\"nsclc_public_genie_bpc\",\"kirc_tcga_pan_can_atlas_2018\",\"kirp_tcga_pan_can_atlas_2018\",\"kich_tcga_pan_can_atlas_2018\",\"acc_tcga_pan_can_atlas_2018\",\"chol_tcga_pan_can_atlas_2018\",\"blca_tcga_pan_can_atlas_2018\",\"coadread_tcga_pan_can_atlas_2018\",\"brca_tcga_pan_can_atlas_2018\",\"lgg_tcga_pan_can_atlas_2018\",\"gbm_tcga_pan_can_atlas_2018\",\"cesc_tcga_pan_can_atlas_2018\",\"esca_tcga_pan_can_atlas_2018\",\"stad_tcga_pan_can_atlas_2018\",\"uvm_tcga_pan_can_atlas_2018\",\"hnsc_tcga_pan_can_atlas_2018\",\"lihc_tcga_pan_can_atlas_2018\",\"luad_tcga_pan_can_atlas_2018\",\"lusc_tcga_pan_can_atlas_2018\",\"dlbc_tcga_pan_can_atlas_2018\",\"laml_tcga_pan_can_atlas_2018\",\"paad_tcga_pan_can_atlas_2018\",\"meso_tcga_pan_can_atlas_2018\",\"skcm_tcga_pan_can_atlas_2018\",\"prad_tcga_pan_can_atlas_2018\",\"pcpg_tcga_pan_can_atlas_2018\",\"sarc_tcga_pan_can_atlas_2018\",\"tgct_tcga_pan_can_atlas_2018\",\"thym_tcga_pan_can_atlas_2018\",\"thca_tcga_pan_can_atlas_2018\",\"ucec_tcga_pan_can_atlas_2018\",\"ucs_tcga_pan_can_atlas_2018\"],\"alterationFilter\":{\"copyNumberAlterationEventTypes\":{\"AMP\":true,\"HOMDEL\":true},\"mutationEventTypes\":{\"any\":true},\"structuralVariants\":null,\"includeDriver\":true,\"includeVUS\":true,\"includeUnknownOncogenicity\":true,\"includeUnknownTier\":true,\"includeGermline\":true,\"includeSomatic\":true,\"includeUnknownStatus\":true,\"tiersBooleanMap\":{}}}"}, + {"hash":-1059079747,"skip": "Legacy Imp merges counts with different entrez_ids","filterString":"TP53","data":{"geneFilters":[{"molecularProfileIds":["nsclc_public_genie_bpc_mutations","acc_tcga_pan_can_atlas_2018_mutations","blca_tcga_pan_can_atlas_2018_mutations","brca_tcga_pan_can_atlas_2018_mutations","cesc_tcga_pan_can_atlas_2018_mutations","coadread_tcga_pan_can_atlas_2018_mutations","chol_tcga_pan_can_atlas_2018_mutations","dlbc_tcga_pan_can_atlas_2018_mutations","esca_tcga_pan_can_atlas_2018_mutations","gbm_tcga_pan_can_atlas_2018_mutations","hnsc_tcga_pan_can_atlas_2018_mutations","kich_tcga_pan_can_atlas_2018_mutations","kirc_tcga_pan_can_atlas_2018_mutations","kirp_tcga_pan_can_atlas_2018_mutations","laml_tcga_pan_can_atlas_2018_mutations","lgg_tcga_pan_can_atlas_2018_mutations","lihc_tcga_pan_can_atlas_2018_mutations","luad_tcga_pan_can_atlas_2018_mutations","lusc_tcga_pan_can_atlas_2018_mutations","meso_tcga_pan_can_atlas_2018_mutations","ov_tcga_pan_can_atlas_2018_mutations","paad_tcga_pan_can_atlas_2018_mutations","pcpg_tcga_pan_can_atlas_2018_mutations","prad_tcga_pan_can_atlas_2018_mutations","sarc_tcga_pan_can_atlas_2018_mutations","skcm_tcga_pan_can_atlas_2018_mutations","stad_tcga_pan_can_atlas_2018_mutations","tgct_tcga_pan_can_atlas_2018_mutations","thca_tcga_pan_can_atlas_2018_mutations","thym_tcga_pan_can_atlas_2018_mutations","ucec_tcga_pan_can_atlas_2018_mutations","ucs_tcga_pan_can_atlas_2018_mutations","uvm_tcga_pan_can_atlas_2018_mutations"],"geneQueries":[[{"hugoGeneSymbol":"TP53","entrezGeneId":0,"alterations":[],"includeDriver":true,"includeVUS":true,"includeUnknownOncogenicity":true,"tiersBooleanMap":{},"includeUnknownTier":true,"includeGermline":true,"includeSomatic":true,"includeUnknownStatus":true}]]}],"studyIds":["ov_tcga_pan_can_atlas_2018","nsclc_public_genie_bpc","kirc_tcga_pan_can_atlas_2018","kirp_tcga_pan_can_atlas_2018","kich_tcga_pan_can_atlas_2018","acc_tcga_pan_can_atlas_2018","chol_tcga_pan_can_atlas_2018","blca_tcga_pan_can_atlas_2018","coadread_tcga_pan_can_atlas_2018","brca_tcga_pan_can_atlas_2018","lgg_tcga_pan_can_atlas_2018","gbm_tcga_pan_can_atlas_2018","cesc_tcga_pan_can_atlas_2018","esca_tcga_pan_can_atlas_2018","stad_tcga_pan_can_atlas_2018","uvm_tcga_pan_can_atlas_2018","hnsc_tcga_pan_can_atlas_2018","lihc_tcga_pan_can_atlas_2018","luad_tcga_pan_can_atlas_2018","lusc_tcga_pan_can_atlas_2018","dlbc_tcga_pan_can_atlas_2018","laml_tcga_pan_can_atlas_2018","paad_tcga_pan_can_atlas_2018","meso_tcga_pan_can_atlas_2018","skcm_tcga_pan_can_atlas_2018","prad_tcga_pan_can_atlas_2018","pcpg_tcga_pan_can_atlas_2018","sarc_tcga_pan_can_atlas_2018","tgct_tcga_pan_can_atlas_2018","thym_tcga_pan_can_atlas_2018","thca_tcga_pan_can_atlas_2018","ucec_tcga_pan_can_atlas_2018","ucs_tcga_pan_can_atlas_2018"],"alterationFilter":{"copyNumberAlterationEventTypes":{"AMP":true,"HOMDEL":true},"mutationEventTypes":{"any":true},"structuralVariants":null,"includeDriver":true,"includeVUS":true,"includeUnknownOncogenicity":true,"includeUnknownTier":true,"includeGermline":true,"includeSomatic":true,"includeUnknownStatus":true,"tiersBooleanMap":{}}},"url":"/api/column-store/structuralvariant-genes/fetch?","label":"StructuralVariantGenes","studies":["ov_tcga_pan_can_atlas_2018","nsclc_public_genie_bpc","kirc_tcga_pan_can_atlas_2018","kirp_tcga_pan_can_atlas_2018","kich_tcga_pan_can_atlas_2018","acc_tcga_pan_can_atlas_2018","chol_tcga_pan_can_atlas_2018","blca_tcga_pan_can_atlas_2018","coadread_tcga_pan_can_atlas_2018","brca_tcga_pan_can_atlas_2018","lgg_tcga_pan_can_atlas_2018","gbm_tcga_pan_can_atlas_2018","cesc_tcga_pan_can_atlas_2018","esca_tcga_pan_can_atlas_2018","stad_tcga_pan_can_atlas_2018","uvm_tcga_pan_can_atlas_2018","hnsc_tcga_pan_can_atlas_2018","lihc_tcga_pan_can_atlas_2018","luad_tcga_pan_can_atlas_2018","lusc_tcga_pan_can_atlas_2018","dlbc_tcga_pan_can_atlas_2018","laml_tcga_pan_can_atlas_2018","paad_tcga_pan_can_atlas_2018","meso_tcga_pan_can_atlas_2018","skcm_tcga_pan_can_atlas_2018","prad_tcga_pan_can_atlas_2018","pcpg_tcga_pan_can_atlas_2018","sarc_tcga_pan_can_atlas_2018","tgct_tcga_pan_can_atlas_2018","thym_tcga_pan_can_atlas_2018","thca_tcga_pan_can_atlas_2018","ucec_tcga_pan_can_atlas_2018","ucs_tcga_pan_can_atlas_2018"],"filterUrl":"/study/summary?id=ov_tcga_pan_can_atlas_2018%2Cnsclc_public_genie_bpc%2Ckirc_tcga_pan_can_atlas_2018%2Ckirp_tcga_pan_can_atlas_2018%2Ckich_tcga_pan_can_atlas_2018%2Cacc_tcga_pan_can_atlas_2018%2Cchol_tcga_pan_can_atlas_2018%2Cblca_tcga_pan_can_atlas_2018%2Ccoadread_tcga_pan_can_atlas_2018%2Cbrca_tcga_pan_can_atlas_2018%2Clgg_tcga_pan_can_atlas_2018%2Cgbm_tcga_pan_can_atlas_2018%2Ccesc_tcga_pan_can_atlas_2018%2Cesca_tcga_pan_can_atlas_2018%2Cstad_tcga_pan_can_atlas_2018%2Cuvm_tcga_pan_can_atlas_2018%2Chnsc_tcga_pan_can_atlas_2018%2Clihc_tcga_pan_can_atlas_2018%2Cluad_tcga_pan_can_atlas_2018%2Clusc_tcga_pan_can_atlas_2018%2Cdlbc_tcga_pan_can_atlas_2018%2Claml_tcga_pan_can_atlas_2018%2Cpaad_tcga_pan_can_atlas_2018%2Cmeso_tcga_pan_can_atlas_2018%2Cskcm_tcga_pan_can_atlas_2018%2Cprad_tcga_pan_can_atlas_2018%2Cpcpg_tcga_pan_can_atlas_2018%2Csarc_tcga_pan_can_atlas_2018%2Ctgct_tcga_pan_can_atlas_2018%2Cthym_tcga_pan_can_atlas_2018%2Cthca_tcga_pan_can_atlas_2018%2Cucec_tcga_pan_can_atlas_2018%2Cucs_tcga_pan_can_atlas_2018#filterJson={\"geneFilters\":[{\"molecularProfileIds\":[\"nsclc_public_genie_bpc_mutations\",\"acc_tcga_pan_can_atlas_2018_mutations\",\"blca_tcga_pan_can_atlas_2018_mutations\",\"brca_tcga_pan_can_atlas_2018_mutations\",\"cesc_tcga_pan_can_atlas_2018_mutations\",\"coadread_tcga_pan_can_atlas_2018_mutations\",\"chol_tcga_pan_can_atlas_2018_mutations\",\"dlbc_tcga_pan_can_atlas_2018_mutations\",\"esca_tcga_pan_can_atlas_2018_mutations\",\"gbm_tcga_pan_can_atlas_2018_mutations\",\"hnsc_tcga_pan_can_atlas_2018_mutations\",\"kich_tcga_pan_can_atlas_2018_mutations\",\"kirc_tcga_pan_can_atlas_2018_mutations\",\"kirp_tcga_pan_can_atlas_2018_mutations\",\"laml_tcga_pan_can_atlas_2018_mutations\",\"lgg_tcga_pan_can_atlas_2018_mutations\",\"lihc_tcga_pan_can_atlas_2018_mutations\",\"luad_tcga_pan_can_atlas_2018_mutations\",\"lusc_tcga_pan_can_atlas_2018_mutations\",\"meso_tcga_pan_can_atlas_2018_mutations\",\"ov_tcga_pan_can_atlas_2018_mutations\",\"paad_tcga_pan_can_atlas_2018_mutations\",\"pcpg_tcga_pan_can_atlas_2018_mutations\",\"prad_tcga_pan_can_atlas_2018_mutations\",\"sarc_tcga_pan_can_atlas_2018_mutations\",\"skcm_tcga_pan_can_atlas_2018_mutations\",\"stad_tcga_pan_can_atlas_2018_mutations\",\"tgct_tcga_pan_can_atlas_2018_mutations\",\"thca_tcga_pan_can_atlas_2018_mutations\",\"thym_tcga_pan_can_atlas_2018_mutations\",\"ucec_tcga_pan_can_atlas_2018_mutations\",\"ucs_tcga_pan_can_atlas_2018_mutations\",\"uvm_tcga_pan_can_atlas_2018_mutations\"],\"geneQueries\":[[{\"hugoGeneSymbol\":\"TP53\",\"entrezGeneId\":0,\"alterations\":[],\"includeDriver\":true,\"includeVUS\":true,\"includeUnknownOncogenicity\":true,\"tiersBooleanMap\":{},\"includeUnknownTier\":true,\"includeGermline\":true,\"includeSomatic\":true,\"includeUnknownStatus\":true}]]}],\"studyIds\":[\"ov_tcga_pan_can_atlas_2018\",\"nsclc_public_genie_bpc\",\"kirc_tcga_pan_can_atlas_2018\",\"kirp_tcga_pan_can_atlas_2018\",\"kich_tcga_pan_can_atlas_2018\",\"acc_tcga_pan_can_atlas_2018\",\"chol_tcga_pan_can_atlas_2018\",\"blca_tcga_pan_can_atlas_2018\",\"coadread_tcga_pan_can_atlas_2018\",\"brca_tcga_pan_can_atlas_2018\",\"lgg_tcga_pan_can_atlas_2018\",\"gbm_tcga_pan_can_atlas_2018\",\"cesc_tcga_pan_can_atlas_2018\",\"esca_tcga_pan_can_atlas_2018\",\"stad_tcga_pan_can_atlas_2018\",\"uvm_tcga_pan_can_atlas_2018\",\"hnsc_tcga_pan_can_atlas_2018\",\"lihc_tcga_pan_can_atlas_2018\",\"luad_tcga_pan_can_atlas_2018\",\"lusc_tcga_pan_can_atlas_2018\",\"dlbc_tcga_pan_can_atlas_2018\",\"laml_tcga_pan_can_atlas_2018\",\"paad_tcga_pan_can_atlas_2018\",\"meso_tcga_pan_can_atlas_2018\",\"skcm_tcga_pan_can_atlas_2018\",\"prad_tcga_pan_can_atlas_2018\",\"pcpg_tcga_pan_can_atlas_2018\",\"sarc_tcga_pan_can_atlas_2018\",\"tgct_tcga_pan_can_atlas_2018\",\"thym_tcga_pan_can_atlas_2018\",\"thca_tcga_pan_can_atlas_2018\",\"ucec_tcga_pan_can_atlas_2018\",\"ucs_tcga_pan_can_atlas_2018\"],\"alterationFilter\":{\"copyNumberAlterationEventTypes\":{\"AMP\":true,\"HOMDEL\":true},\"mutationEventTypes\":{\"any\":true},\"structuralVariants\":null,\"includeDriver\":true,\"includeVUS\":true,\"includeUnknownOncogenicity\":true,\"includeUnknownTier\":true,\"includeGermline\":true,\"includeSomatic\":true,\"includeUnknownStatus\":true,\"tiersBooleanMap\":{}}}"}, - {"hash":-1638803473,"filterString":"TP53","data":{"geneFilters":[{"molecularProfileIds":["nsclc_public_genie_bpc_mutations","acc_tcga_pan_can_atlas_2018_mutations","blca_tcga_pan_can_atlas_2018_mutations","brca_tcga_pan_can_atlas_2018_mutations","cesc_tcga_pan_can_atlas_2018_mutations","coadread_tcga_pan_can_atlas_2018_mutations","chol_tcga_pan_can_atlas_2018_mutations","dlbc_tcga_pan_can_atlas_2018_mutations","esca_tcga_pan_can_atlas_2018_mutations","gbm_tcga_pan_can_atlas_2018_mutations","hnsc_tcga_pan_can_atlas_2018_mutations","kich_tcga_pan_can_atlas_2018_mutations","kirc_tcga_pan_can_atlas_2018_mutations","kirp_tcga_pan_can_atlas_2018_mutations","laml_tcga_pan_can_atlas_2018_mutations","lgg_tcga_pan_can_atlas_2018_mutations","lihc_tcga_pan_can_atlas_2018_mutations","luad_tcga_pan_can_atlas_2018_mutations","lusc_tcga_pan_can_atlas_2018_mutations","meso_tcga_pan_can_atlas_2018_mutations","ov_tcga_pan_can_atlas_2018_mutations","paad_tcga_pan_can_atlas_2018_mutations","pcpg_tcga_pan_can_atlas_2018_mutations","prad_tcga_pan_can_atlas_2018_mutations","sarc_tcga_pan_can_atlas_2018_mutations","skcm_tcga_pan_can_atlas_2018_mutations","stad_tcga_pan_can_atlas_2018_mutations","tgct_tcga_pan_can_atlas_2018_mutations","thca_tcga_pan_can_atlas_2018_mutations","thym_tcga_pan_can_atlas_2018_mutations","ucec_tcga_pan_can_atlas_2018_mutations","ucs_tcga_pan_can_atlas_2018_mutations","uvm_tcga_pan_can_atlas_2018_mutations"],"geneQueries":[[{"hugoGeneSymbol":"TP53","entrezGeneId":0,"alterations":[],"includeDriver":true,"includeVUS":true,"includeUnknownOncogenicity":true,"tiersBooleanMap":{},"includeUnknownTier":true,"includeGermline":true,"includeSomatic":true,"includeUnknownStatus":true}]]}],"studyIds":["ov_tcga_pan_can_atlas_2018","nsclc_public_genie_bpc","kirc_tcga_pan_can_atlas_2018","kirp_tcga_pan_can_atlas_2018","kich_tcga_pan_can_atlas_2018","acc_tcga_pan_can_atlas_2018","chol_tcga_pan_can_atlas_2018","blca_tcga_pan_can_atlas_2018","coadread_tcga_pan_can_atlas_2018","brca_tcga_pan_can_atlas_2018","lgg_tcga_pan_can_atlas_2018","gbm_tcga_pan_can_atlas_2018","cesc_tcga_pan_can_atlas_2018","esca_tcga_pan_can_atlas_2018","stad_tcga_pan_can_atlas_2018","uvm_tcga_pan_can_atlas_2018","hnsc_tcga_pan_can_atlas_2018","lihc_tcga_pan_can_atlas_2018","luad_tcga_pan_can_atlas_2018","lusc_tcga_pan_can_atlas_2018","dlbc_tcga_pan_can_atlas_2018","laml_tcga_pan_can_atlas_2018","paad_tcga_pan_can_atlas_2018","meso_tcga_pan_can_atlas_2018","skcm_tcga_pan_can_atlas_2018","prad_tcga_pan_can_atlas_2018","pcpg_tcga_pan_can_atlas_2018","sarc_tcga_pan_can_atlas_2018","tgct_tcga_pan_can_atlas_2018","thym_tcga_pan_can_atlas_2018","thca_tcga_pan_can_atlas_2018","ucec_tcga_pan_can_atlas_2018","ucs_tcga_pan_can_atlas_2018"],"alterationFilter":{"copyNumberAlterationEventTypes":{"AMP":true,"HOMDEL":true},"mutationEventTypes":{"any":true},"structuralVariants":null,"includeDriver":true,"includeVUS":true,"includeUnknownOncogenicity":true,"includeUnknownTier":true,"includeGermline":true,"includeSomatic":true,"includeUnknownStatus":true,"tiersBooleanMap":{}}},"url":"/api/column-store/cna-genes/fetch?","label":"CNAGenes","studies":["ov_tcga_pan_can_atlas_2018","nsclc_public_genie_bpc","kirc_tcga_pan_can_atlas_2018","kirp_tcga_pan_can_atlas_2018","kich_tcga_pan_can_atlas_2018","acc_tcga_pan_can_atlas_2018","chol_tcga_pan_can_atlas_2018","blca_tcga_pan_can_atlas_2018","coadread_tcga_pan_can_atlas_2018","brca_tcga_pan_can_atlas_2018","lgg_tcga_pan_can_atlas_2018","gbm_tcga_pan_can_atlas_2018","cesc_tcga_pan_can_atlas_2018","esca_tcga_pan_can_atlas_2018","stad_tcga_pan_can_atlas_2018","uvm_tcga_pan_can_atlas_2018","hnsc_tcga_pan_can_atlas_2018","lihc_tcga_pan_can_atlas_2018","luad_tcga_pan_can_atlas_2018","lusc_tcga_pan_can_atlas_2018","dlbc_tcga_pan_can_atlas_2018","laml_tcga_pan_can_atlas_2018","paad_tcga_pan_can_atlas_2018","meso_tcga_pan_can_atlas_2018","skcm_tcga_pan_can_atlas_2018","prad_tcga_pan_can_atlas_2018","pcpg_tcga_pan_can_atlas_2018","sarc_tcga_pan_can_atlas_2018","tgct_tcga_pan_can_atlas_2018","thym_tcga_pan_can_atlas_2018","thca_tcga_pan_can_atlas_2018","ucec_tcga_pan_can_atlas_2018","ucs_tcga_pan_can_atlas_2018"],"filterUrl":"/study/summary?id=ov_tcga_pan_can_atlas_2018%2Cnsclc_public_genie_bpc%2Ckirc_tcga_pan_can_atlas_2018%2Ckirp_tcga_pan_can_atlas_2018%2Ckich_tcga_pan_can_atlas_2018%2Cacc_tcga_pan_can_atlas_2018%2Cchol_tcga_pan_can_atlas_2018%2Cblca_tcga_pan_can_atlas_2018%2Ccoadread_tcga_pan_can_atlas_2018%2Cbrca_tcga_pan_can_atlas_2018%2Clgg_tcga_pan_can_atlas_2018%2Cgbm_tcga_pan_can_atlas_2018%2Ccesc_tcga_pan_can_atlas_2018%2Cesca_tcga_pan_can_atlas_2018%2Cstad_tcga_pan_can_atlas_2018%2Cuvm_tcga_pan_can_atlas_2018%2Chnsc_tcga_pan_can_atlas_2018%2Clihc_tcga_pan_can_atlas_2018%2Cluad_tcga_pan_can_atlas_2018%2Clusc_tcga_pan_can_atlas_2018%2Cdlbc_tcga_pan_can_atlas_2018%2Claml_tcga_pan_can_atlas_2018%2Cpaad_tcga_pan_can_atlas_2018%2Cmeso_tcga_pan_can_atlas_2018%2Cskcm_tcga_pan_can_atlas_2018%2Cprad_tcga_pan_can_atlas_2018%2Cpcpg_tcga_pan_can_atlas_2018%2Csarc_tcga_pan_can_atlas_2018%2Ctgct_tcga_pan_can_atlas_2018%2Cthym_tcga_pan_can_atlas_2018%2Cthca_tcga_pan_can_atlas_2018%2Cucec_tcga_pan_can_atlas_2018%2Cucs_tcga_pan_can_atlas_2018#filterJson={\"geneFilters\":[{\"molecularProfileIds\":[\"nsclc_public_genie_bpc_mutations\",\"acc_tcga_pan_can_atlas_2018_mutations\",\"blca_tcga_pan_can_atlas_2018_mutations\",\"brca_tcga_pan_can_atlas_2018_mutations\",\"cesc_tcga_pan_can_atlas_2018_mutations\",\"coadread_tcga_pan_can_atlas_2018_mutations\",\"chol_tcga_pan_can_atlas_2018_mutations\",\"dlbc_tcga_pan_can_atlas_2018_mutations\",\"esca_tcga_pan_can_atlas_2018_mutations\",\"gbm_tcga_pan_can_atlas_2018_mutations\",\"hnsc_tcga_pan_can_atlas_2018_mutations\",\"kich_tcga_pan_can_atlas_2018_mutations\",\"kirc_tcga_pan_can_atlas_2018_mutations\",\"kirp_tcga_pan_can_atlas_2018_mutations\",\"laml_tcga_pan_can_atlas_2018_mutations\",\"lgg_tcga_pan_can_atlas_2018_mutations\",\"lihc_tcga_pan_can_atlas_2018_mutations\",\"luad_tcga_pan_can_atlas_2018_mutations\",\"lusc_tcga_pan_can_atlas_2018_mutations\",\"meso_tcga_pan_can_atlas_2018_mutations\",\"ov_tcga_pan_can_atlas_2018_mutations\",\"paad_tcga_pan_can_atlas_2018_mutations\",\"pcpg_tcga_pan_can_atlas_2018_mutations\",\"prad_tcga_pan_can_atlas_2018_mutations\",\"sarc_tcga_pan_can_atlas_2018_mutations\",\"skcm_tcga_pan_can_atlas_2018_mutations\",\"stad_tcga_pan_can_atlas_2018_mutations\",\"tgct_tcga_pan_can_atlas_2018_mutations\",\"thca_tcga_pan_can_atlas_2018_mutations\",\"thym_tcga_pan_can_atlas_2018_mutations\",\"ucec_tcga_pan_can_atlas_2018_mutations\",\"ucs_tcga_pan_can_atlas_2018_mutations\",\"uvm_tcga_pan_can_atlas_2018_mutations\"],\"geneQueries\":[[{\"hugoGeneSymbol\":\"TP53\",\"entrezGeneId\":0,\"alterations\":[],\"includeDriver\":true,\"includeVUS\":true,\"includeUnknownOncogenicity\":true,\"tiersBooleanMap\":{},\"includeUnknownTier\":true,\"includeGermline\":true,\"includeSomatic\":true,\"includeUnknownStatus\":true}]]}],\"studyIds\":[\"ov_tcga_pan_can_atlas_2018\",\"nsclc_public_genie_bpc\",\"kirc_tcga_pan_can_atlas_2018\",\"kirp_tcga_pan_can_atlas_2018\",\"kich_tcga_pan_can_atlas_2018\",\"acc_tcga_pan_can_atlas_2018\",\"chol_tcga_pan_can_atlas_2018\",\"blca_tcga_pan_can_atlas_2018\",\"coadread_tcga_pan_can_atlas_2018\",\"brca_tcga_pan_can_atlas_2018\",\"lgg_tcga_pan_can_atlas_2018\",\"gbm_tcga_pan_can_atlas_2018\",\"cesc_tcga_pan_can_atlas_2018\",\"esca_tcga_pan_can_atlas_2018\",\"stad_tcga_pan_can_atlas_2018\",\"uvm_tcga_pan_can_atlas_2018\",\"hnsc_tcga_pan_can_atlas_2018\",\"lihc_tcga_pan_can_atlas_2018\",\"luad_tcga_pan_can_atlas_2018\",\"lusc_tcga_pan_can_atlas_2018\",\"dlbc_tcga_pan_can_atlas_2018\",\"laml_tcga_pan_can_atlas_2018\",\"paad_tcga_pan_can_atlas_2018\",\"meso_tcga_pan_can_atlas_2018\",\"skcm_tcga_pan_can_atlas_2018\",\"prad_tcga_pan_can_atlas_2018\",\"pcpg_tcga_pan_can_atlas_2018\",\"sarc_tcga_pan_can_atlas_2018\",\"tgct_tcga_pan_can_atlas_2018\",\"thym_tcga_pan_can_atlas_2018\",\"thca_tcga_pan_can_atlas_2018\",\"ucec_tcga_pan_can_atlas_2018\",\"ucs_tcga_pan_can_atlas_2018\"],\"alterationFilter\":{\"copyNumberAlterationEventTypes\":{\"AMP\":true,\"HOMDEL\":true},\"mutationEventTypes\":{\"any\":true},\"structuralVariants\":null,\"includeDriver\":true,\"includeVUS\":true,\"includeUnknownOncogenicity\":true,\"includeUnknownTier\":true,\"includeGermline\":true,\"includeSomatic\":true,\"includeUnknownStatus\":true,\"tiersBooleanMap\":{}}}"} + {"hash":-1638803473, + "skip": "off panel discrep", + "filterString":"TP53","data":{"geneFilters":[{"molecularProfileIds":["nsclc_public_genie_bpc_mutations","acc_tcga_pan_can_atlas_2018_mutations","blca_tcga_pan_can_atlas_2018_mutations","brca_tcga_pan_can_atlas_2018_mutations","cesc_tcga_pan_can_atlas_2018_mutations","coadread_tcga_pan_can_atlas_2018_mutations","chol_tcga_pan_can_atlas_2018_mutations","dlbc_tcga_pan_can_atlas_2018_mutations","esca_tcga_pan_can_atlas_2018_mutations","gbm_tcga_pan_can_atlas_2018_mutations","hnsc_tcga_pan_can_atlas_2018_mutations","kich_tcga_pan_can_atlas_2018_mutations","kirc_tcga_pan_can_atlas_2018_mutations","kirp_tcga_pan_can_atlas_2018_mutations","laml_tcga_pan_can_atlas_2018_mutations","lgg_tcga_pan_can_atlas_2018_mutations","lihc_tcga_pan_can_atlas_2018_mutations","luad_tcga_pan_can_atlas_2018_mutations","lusc_tcga_pan_can_atlas_2018_mutations","meso_tcga_pan_can_atlas_2018_mutations","ov_tcga_pan_can_atlas_2018_mutations","paad_tcga_pan_can_atlas_2018_mutations","pcpg_tcga_pan_can_atlas_2018_mutations","prad_tcga_pan_can_atlas_2018_mutations","sarc_tcga_pan_can_atlas_2018_mutations","skcm_tcga_pan_can_atlas_2018_mutations","stad_tcga_pan_can_atlas_2018_mutations","tgct_tcga_pan_can_atlas_2018_mutations","thca_tcga_pan_can_atlas_2018_mutations","thym_tcga_pan_can_atlas_2018_mutations","ucec_tcga_pan_can_atlas_2018_mutations","ucs_tcga_pan_can_atlas_2018_mutations","uvm_tcga_pan_can_atlas_2018_mutations"],"geneQueries":[[{"hugoGeneSymbol":"TP53","entrezGeneId":0,"alterations":[],"includeDriver":true,"includeVUS":true,"includeUnknownOncogenicity":true,"tiersBooleanMap":{},"includeUnknownTier":true,"includeGermline":true,"includeSomatic":true,"includeUnknownStatus":true}]]}],"studyIds":["ov_tcga_pan_can_atlas_2018","nsclc_public_genie_bpc","kirc_tcga_pan_can_atlas_2018","kirp_tcga_pan_can_atlas_2018","kich_tcga_pan_can_atlas_2018","acc_tcga_pan_can_atlas_2018","chol_tcga_pan_can_atlas_2018","blca_tcga_pan_can_atlas_2018","coadread_tcga_pan_can_atlas_2018","brca_tcga_pan_can_atlas_2018","lgg_tcga_pan_can_atlas_2018","gbm_tcga_pan_can_atlas_2018","cesc_tcga_pan_can_atlas_2018","esca_tcga_pan_can_atlas_2018","stad_tcga_pan_can_atlas_2018","uvm_tcga_pan_can_atlas_2018","hnsc_tcga_pan_can_atlas_2018","lihc_tcga_pan_can_atlas_2018","luad_tcga_pan_can_atlas_2018","lusc_tcga_pan_can_atlas_2018","dlbc_tcga_pan_can_atlas_2018","laml_tcga_pan_can_atlas_2018","paad_tcga_pan_can_atlas_2018","meso_tcga_pan_can_atlas_2018","skcm_tcga_pan_can_atlas_2018","prad_tcga_pan_can_atlas_2018","pcpg_tcga_pan_can_atlas_2018","sarc_tcga_pan_can_atlas_2018","tgct_tcga_pan_can_atlas_2018","thym_tcga_pan_can_atlas_2018","thca_tcga_pan_can_atlas_2018","ucec_tcga_pan_can_atlas_2018","ucs_tcga_pan_can_atlas_2018"],"alterationFilter":{"copyNumberAlterationEventTypes":{"AMP":true,"HOMDEL":true},"mutationEventTypes":{"any":true},"structuralVariants":null,"includeDriver":true,"includeVUS":true,"includeUnknownOncogenicity":true,"includeUnknownTier":true,"includeGermline":true,"includeSomatic":true,"includeUnknownStatus":true,"tiersBooleanMap":{}}},"url":"/api/column-store/cna-genes/fetch?","label":"CNAGenes","studies":["ov_tcga_pan_can_atlas_2018","nsclc_public_genie_bpc","kirc_tcga_pan_can_atlas_2018","kirp_tcga_pan_can_atlas_2018","kich_tcga_pan_can_atlas_2018","acc_tcga_pan_can_atlas_2018","chol_tcga_pan_can_atlas_2018","blca_tcga_pan_can_atlas_2018","coadread_tcga_pan_can_atlas_2018","brca_tcga_pan_can_atlas_2018","lgg_tcga_pan_can_atlas_2018","gbm_tcga_pan_can_atlas_2018","cesc_tcga_pan_can_atlas_2018","esca_tcga_pan_can_atlas_2018","stad_tcga_pan_can_atlas_2018","uvm_tcga_pan_can_atlas_2018","hnsc_tcga_pan_can_atlas_2018","lihc_tcga_pan_can_atlas_2018","luad_tcga_pan_can_atlas_2018","lusc_tcga_pan_can_atlas_2018","dlbc_tcga_pan_can_atlas_2018","laml_tcga_pan_can_atlas_2018","paad_tcga_pan_can_atlas_2018","meso_tcga_pan_can_atlas_2018","skcm_tcga_pan_can_atlas_2018","prad_tcga_pan_can_atlas_2018","pcpg_tcga_pan_can_atlas_2018","sarc_tcga_pan_can_atlas_2018","tgct_tcga_pan_can_atlas_2018","thym_tcga_pan_can_atlas_2018","thca_tcga_pan_can_atlas_2018","ucec_tcga_pan_can_atlas_2018","ucs_tcga_pan_can_atlas_2018"],"filterUrl":"/study/summary?id=ov_tcga_pan_can_atlas_2018%2Cnsclc_public_genie_bpc%2Ckirc_tcga_pan_can_atlas_2018%2Ckirp_tcga_pan_can_atlas_2018%2Ckich_tcga_pan_can_atlas_2018%2Cacc_tcga_pan_can_atlas_2018%2Cchol_tcga_pan_can_atlas_2018%2Cblca_tcga_pan_can_atlas_2018%2Ccoadread_tcga_pan_can_atlas_2018%2Cbrca_tcga_pan_can_atlas_2018%2Clgg_tcga_pan_can_atlas_2018%2Cgbm_tcga_pan_can_atlas_2018%2Ccesc_tcga_pan_can_atlas_2018%2Cesca_tcga_pan_can_atlas_2018%2Cstad_tcga_pan_can_atlas_2018%2Cuvm_tcga_pan_can_atlas_2018%2Chnsc_tcga_pan_can_atlas_2018%2Clihc_tcga_pan_can_atlas_2018%2Cluad_tcga_pan_can_atlas_2018%2Clusc_tcga_pan_can_atlas_2018%2Cdlbc_tcga_pan_can_atlas_2018%2Claml_tcga_pan_can_atlas_2018%2Cpaad_tcga_pan_can_atlas_2018%2Cmeso_tcga_pan_can_atlas_2018%2Cskcm_tcga_pan_can_atlas_2018%2Cprad_tcga_pan_can_atlas_2018%2Cpcpg_tcga_pan_can_atlas_2018%2Csarc_tcga_pan_can_atlas_2018%2Ctgct_tcga_pan_can_atlas_2018%2Cthym_tcga_pan_can_atlas_2018%2Cthca_tcga_pan_can_atlas_2018%2Cucec_tcga_pan_can_atlas_2018%2Cucs_tcga_pan_can_atlas_2018#filterJson={\"geneFilters\":[{\"molecularProfileIds\":[\"nsclc_public_genie_bpc_mutations\",\"acc_tcga_pan_can_atlas_2018_mutations\",\"blca_tcga_pan_can_atlas_2018_mutations\",\"brca_tcga_pan_can_atlas_2018_mutations\",\"cesc_tcga_pan_can_atlas_2018_mutations\",\"coadread_tcga_pan_can_atlas_2018_mutations\",\"chol_tcga_pan_can_atlas_2018_mutations\",\"dlbc_tcga_pan_can_atlas_2018_mutations\",\"esca_tcga_pan_can_atlas_2018_mutations\",\"gbm_tcga_pan_can_atlas_2018_mutations\",\"hnsc_tcga_pan_can_atlas_2018_mutations\",\"kich_tcga_pan_can_atlas_2018_mutations\",\"kirc_tcga_pan_can_atlas_2018_mutations\",\"kirp_tcga_pan_can_atlas_2018_mutations\",\"laml_tcga_pan_can_atlas_2018_mutations\",\"lgg_tcga_pan_can_atlas_2018_mutations\",\"lihc_tcga_pan_can_atlas_2018_mutations\",\"luad_tcga_pan_can_atlas_2018_mutations\",\"lusc_tcga_pan_can_atlas_2018_mutations\",\"meso_tcga_pan_can_atlas_2018_mutations\",\"ov_tcga_pan_can_atlas_2018_mutations\",\"paad_tcga_pan_can_atlas_2018_mutations\",\"pcpg_tcga_pan_can_atlas_2018_mutations\",\"prad_tcga_pan_can_atlas_2018_mutations\",\"sarc_tcga_pan_can_atlas_2018_mutations\",\"skcm_tcga_pan_can_atlas_2018_mutations\",\"stad_tcga_pan_can_atlas_2018_mutations\",\"tgct_tcga_pan_can_atlas_2018_mutations\",\"thca_tcga_pan_can_atlas_2018_mutations\",\"thym_tcga_pan_can_atlas_2018_mutations\",\"ucec_tcga_pan_can_atlas_2018_mutations\",\"ucs_tcga_pan_can_atlas_2018_mutations\",\"uvm_tcga_pan_can_atlas_2018_mutations\"],\"geneQueries\":[[{\"hugoGeneSymbol\":\"TP53\",\"entrezGeneId\":0,\"alterations\":[],\"includeDriver\":true,\"includeVUS\":true,\"includeUnknownOncogenicity\":true,\"tiersBooleanMap\":{},\"includeUnknownTier\":true,\"includeGermline\":true,\"includeSomatic\":true,\"includeUnknownStatus\":true}]]}],\"studyIds\":[\"ov_tcga_pan_can_atlas_2018\",\"nsclc_public_genie_bpc\",\"kirc_tcga_pan_can_atlas_2018\",\"kirp_tcga_pan_can_atlas_2018\",\"kich_tcga_pan_can_atlas_2018\",\"acc_tcga_pan_can_atlas_2018\",\"chol_tcga_pan_can_atlas_2018\",\"blca_tcga_pan_can_atlas_2018\",\"coadread_tcga_pan_can_atlas_2018\",\"brca_tcga_pan_can_atlas_2018\",\"lgg_tcga_pan_can_atlas_2018\",\"gbm_tcga_pan_can_atlas_2018\",\"cesc_tcga_pan_can_atlas_2018\",\"esca_tcga_pan_can_atlas_2018\",\"stad_tcga_pan_can_atlas_2018\",\"uvm_tcga_pan_can_atlas_2018\",\"hnsc_tcga_pan_can_atlas_2018\",\"lihc_tcga_pan_can_atlas_2018\",\"luad_tcga_pan_can_atlas_2018\",\"lusc_tcga_pan_can_atlas_2018\",\"dlbc_tcga_pan_can_atlas_2018\",\"laml_tcga_pan_can_atlas_2018\",\"paad_tcga_pan_can_atlas_2018\",\"meso_tcga_pan_can_atlas_2018\",\"skcm_tcga_pan_can_atlas_2018\",\"prad_tcga_pan_can_atlas_2018\",\"pcpg_tcga_pan_can_atlas_2018\",\"sarc_tcga_pan_can_atlas_2018\",\"tgct_tcga_pan_can_atlas_2018\",\"thym_tcga_pan_can_atlas_2018\",\"thca_tcga_pan_can_atlas_2018\",\"ucec_tcga_pan_can_atlas_2018\",\"ucs_tcga_pan_can_atlas_2018\"],\"alterationFilter\":{\"copyNumberAlterationEventTypes\":{\"AMP\":true,\"HOMDEL\":true},\"mutationEventTypes\":{\"any\":true},\"structuralVariants\":null,\"includeDriver\":true,\"includeVUS\":true,\"includeUnknownOncogenicity\":true,\"includeUnknownTier\":true,\"includeGermline\":true,\"includeSomatic\":true,\"includeUnknownStatus\":true,\"tiersBooleanMap\":{}}}"} ] }, @@ -88,11 +92,15 @@ "note":"", "studies":["crc_public_genie_bpc","coadread_tcga_pan_can_atlas_2018"], "tests":[ - {"hash":1237514557,"filterString":" (APC OR TP53) ","data":{"geneFilters":[{"molecularProfileIds":["coadread_tcga_pan_can_atlas_2018_mutations","crc_public_genie_bpc_mutations"],"geneQueries":[[{"hugoGeneSymbol":"APC","entrezGeneId":0,"alterations":[],"includeDriver":true,"includeVUS":true,"includeUnknownOncogenicity":true,"tiersBooleanMap":{},"includeUnknownTier":true,"includeGermline":true,"includeSomatic":true,"includeUnknownStatus":true},{"hugoGeneSymbol":"TP53","entrezGeneId":0,"alterations":[],"includeDriver":true,"includeVUS":true,"includeUnknownOncogenicity":true,"tiersBooleanMap":{},"includeUnknownTier":true,"includeGermline":true,"includeSomatic":true,"includeUnknownStatus":true}]]}],"studyIds":["crc_public_genie_bpc","coadread_tcga_pan_can_atlas_2018"],"alterationFilter":{"copyNumberAlterationEventTypes":{"AMP":true,"HOMDEL":true},"mutationEventTypes":{"any":true},"structuralVariants":null,"includeDriver":true,"includeVUS":true,"includeUnknownOncogenicity":true,"includeUnknownTier":true,"includeGermline":true,"includeSomatic":true,"includeUnknownStatus":true,"tiersBooleanMap":{}}},"url":"/api/column-store/structuralvariant-genes/fetch?","label":"StructuralVariantGenes","studies":["crc_public_genie_bpc","coadread_tcga_pan_can_atlas_2018"],"filterUrl":"/study/summary?id=crc_public_genie_bpc%2Ccoadread_tcga_pan_can_atlas_2018#filterJson={\"geneFilters\":[{\"molecularProfileIds\":[\"coadread_tcga_pan_can_atlas_2018_mutations\",\"crc_public_genie_bpc_mutations\"],\"geneQueries\":[[{\"hugoGeneSymbol\":\"APC\",\"entrezGeneId\":0,\"alterations\":[],\"includeDriver\":true,\"includeVUS\":true,\"includeUnknownOncogenicity\":true,\"tiersBooleanMap\":{},\"includeUnknownTier\":true,\"includeGermline\":true,\"includeSomatic\":true,\"includeUnknownStatus\":true},{\"hugoGeneSymbol\":\"TP53\",\"entrezGeneId\":0,\"alterations\":[],\"includeDriver\":true,\"includeVUS\":true,\"includeUnknownOncogenicity\":true,\"tiersBooleanMap\":{},\"includeUnknownTier\":true,\"includeGermline\":true,\"includeSomatic\":true,\"includeUnknownStatus\":true}]]}],\"studyIds\":[\"crc_public_genie_bpc\",\"coadread_tcga_pan_can_atlas_2018\"],\"alterationFilter\":{\"copyNumberAlterationEventTypes\":{\"AMP\":true,\"HOMDEL\":true},\"mutationEventTypes\":{\"any\":true},\"structuralVariants\":null,\"includeDriver\":true,\"includeVUS\":true,\"includeUnknownOncogenicity\":true,\"includeUnknownTier\":true,\"includeGermline\":true,\"includeSomatic\":true,\"includeUnknownStatus\":true,\"tiersBooleanMap\":{}}}"}, + {"hash":1237514557, + "skip":"off panel discrep", + "filterString":" (APC OR TP53) ","data":{"geneFilters":[{"molecularProfileIds":["coadread_tcga_pan_can_atlas_2018_mutations","crc_public_genie_bpc_mutations"],"geneQueries":[[{"hugoGeneSymbol":"APC","entrezGeneId":0,"alterations":[],"includeDriver":true,"includeVUS":true,"includeUnknownOncogenicity":true,"tiersBooleanMap":{},"includeUnknownTier":true,"includeGermline":true,"includeSomatic":true,"includeUnknownStatus":true},{"hugoGeneSymbol":"TP53","entrezGeneId":0,"alterations":[],"includeDriver":true,"includeVUS":true,"includeUnknownOncogenicity":true,"tiersBooleanMap":{},"includeUnknownTier":true,"includeGermline":true,"includeSomatic":true,"includeUnknownStatus":true}]]}],"studyIds":["crc_public_genie_bpc","coadread_tcga_pan_can_atlas_2018"],"alterationFilter":{"copyNumberAlterationEventTypes":{"AMP":true,"HOMDEL":true},"mutationEventTypes":{"any":true},"structuralVariants":null,"includeDriver":true,"includeVUS":true,"includeUnknownOncogenicity":true,"includeUnknownTier":true,"includeGermline":true,"includeSomatic":true,"includeUnknownStatus":true,"tiersBooleanMap":{}}},"url":"/api/column-store/structuralvariant-genes/fetch?","label":"StructuralVariantGenes","studies":["crc_public_genie_bpc","coadread_tcga_pan_can_atlas_2018"],"filterUrl":"/study/summary?id=crc_public_genie_bpc%2Ccoadread_tcga_pan_can_atlas_2018#filterJson={\"geneFilters\":[{\"molecularProfileIds\":[\"coadread_tcga_pan_can_atlas_2018_mutations\",\"crc_public_genie_bpc_mutations\"],\"geneQueries\":[[{\"hugoGeneSymbol\":\"APC\",\"entrezGeneId\":0,\"alterations\":[],\"includeDriver\":true,\"includeVUS\":true,\"includeUnknownOncogenicity\":true,\"tiersBooleanMap\":{},\"includeUnknownTier\":true,\"includeGermline\":true,\"includeSomatic\":true,\"includeUnknownStatus\":true},{\"hugoGeneSymbol\":\"TP53\",\"entrezGeneId\":0,\"alterations\":[],\"includeDriver\":true,\"includeVUS\":true,\"includeUnknownOncogenicity\":true,\"tiersBooleanMap\":{},\"includeUnknownTier\":true,\"includeGermline\":true,\"includeSomatic\":true,\"includeUnknownStatus\":true}]]}],\"studyIds\":[\"crc_public_genie_bpc\",\"coadread_tcga_pan_can_atlas_2018\"],\"alterationFilter\":{\"copyNumberAlterationEventTypes\":{\"AMP\":true,\"HOMDEL\":true},\"mutationEventTypes\":{\"any\":true},\"structuralVariants\":null,\"includeDriver\":true,\"includeVUS\":true,\"includeUnknownOncogenicity\":true,\"includeUnknownTier\":true,\"includeGermline\":true,\"includeSomatic\":true,\"includeUnknownStatus\":true,\"tiersBooleanMap\":{}}}"}, {"hash":1258482871,"filterString":" (APC OR TP53) ","data":{"geneFilters":[{"molecularProfileIds":["coadread_tcga_pan_can_atlas_2018_mutations","crc_public_genie_bpc_mutations"],"geneQueries":[[{"hugoGeneSymbol":"APC","entrezGeneId":0,"alterations":[],"includeDriver":true,"includeVUS":true,"includeUnknownOncogenicity":true,"tiersBooleanMap":{},"includeUnknownTier":true,"includeGermline":true,"includeSomatic":true,"includeUnknownStatus":true},{"hugoGeneSymbol":"TP53","entrezGeneId":0,"alterations":[],"includeDriver":true,"includeVUS":true,"includeUnknownOncogenicity":true,"tiersBooleanMap":{},"includeUnknownTier":true,"includeGermline":true,"includeSomatic":true,"includeUnknownStatus":true}]]}],"studyIds":["crc_public_genie_bpc","coadread_tcga_pan_can_atlas_2018"],"alterationFilter":{"copyNumberAlterationEventTypes":{"AMP":true,"HOMDEL":true},"mutationEventTypes":{"any":true},"structuralVariants":null,"includeDriver":true,"includeVUS":true,"includeUnknownOncogenicity":true,"includeUnknownTier":true,"includeGermline":true,"includeSomatic":true,"includeUnknownStatus":true,"tiersBooleanMap":{}}},"url":"/api/column-store/sample-lists-counts/fetch?","label":"CaseList","studies":["crc_public_genie_bpc","coadread_tcga_pan_can_atlas_2018"],"filterUrl":"/study/summary?id=crc_public_genie_bpc%2Ccoadread_tcga_pan_can_atlas_2018#filterJson={\"geneFilters\":[{\"molecularProfileIds\":[\"coadread_tcga_pan_can_atlas_2018_mutations\",\"crc_public_genie_bpc_mutations\"],\"geneQueries\":[[{\"hugoGeneSymbol\":\"APC\",\"entrezGeneId\":0,\"alterations\":[],\"includeDriver\":true,\"includeVUS\":true,\"includeUnknownOncogenicity\":true,\"tiersBooleanMap\":{},\"includeUnknownTier\":true,\"includeGermline\":true,\"includeSomatic\":true,\"includeUnknownStatus\":true},{\"hugoGeneSymbol\":\"TP53\",\"entrezGeneId\":0,\"alterations\":[],\"includeDriver\":true,\"includeVUS\":true,\"includeUnknownOncogenicity\":true,\"tiersBooleanMap\":{},\"includeUnknownTier\":true,\"includeGermline\":true,\"includeSomatic\":true,\"includeUnknownStatus\":true}]]}],\"studyIds\":[\"crc_public_genie_bpc\",\"coadread_tcga_pan_can_atlas_2018\"],\"alterationFilter\":{\"copyNumberAlterationEventTypes\":{\"AMP\":true,\"HOMDEL\":true},\"mutationEventTypes\":{\"any\":true},\"structuralVariants\":null,\"includeDriver\":true,\"includeVUS\":true,\"includeUnknownOncogenicity\":true,\"includeUnknownTier\":true,\"includeGermline\":true,\"includeSomatic\":true,\"includeUnknownStatus\":true,\"tiersBooleanMap\":{}}}"}, - {"hash":1605173863,"filterString":" (APC OR TP53) ","data":{"geneFilters":[{"molecularProfileIds":["coadread_tcga_pan_can_atlas_2018_mutations","crc_public_genie_bpc_mutations"],"geneQueries":[[{"hugoGeneSymbol":"APC","entrezGeneId":0,"alterations":[],"includeDriver":true,"includeVUS":true,"includeUnknownOncogenicity":true,"tiersBooleanMap":{},"includeUnknownTier":true,"includeGermline":true,"includeSomatic":true,"includeUnknownStatus":true},{"hugoGeneSymbol":"TP53","entrezGeneId":0,"alterations":[],"includeDriver":true,"includeVUS":true,"includeUnknownOncogenicity":true,"tiersBooleanMap":{},"includeUnknownTier":true,"includeGermline":true,"includeSomatic":true,"includeUnknownStatus":true}]]}],"studyIds":["crc_public_genie_bpc","coadread_tcga_pan_can_atlas_2018"],"alterationFilter":{"copyNumberAlterationEventTypes":{"AMP":true,"HOMDEL":true},"mutationEventTypes":{"any":true},"structuralVariants":null,"includeDriver":true,"includeVUS":true,"includeUnknownOncogenicity":true,"includeUnknownTier":true,"includeGermline":true,"includeSomatic":true,"includeUnknownStatus":true,"tiersBooleanMap":{}}},"url":"/api/column-store/mutated-genes/fetch?","label":"MutatedGenes","studies":["crc_public_genie_bpc","coadread_tcga_pan_can_atlas_2018"],"filterUrl":"/study/summary?id=crc_public_genie_bpc%2Ccoadread_tcga_pan_can_atlas_2018#filterJson={\"geneFilters\":[{\"molecularProfileIds\":[\"coadread_tcga_pan_can_atlas_2018_mutations\",\"crc_public_genie_bpc_mutations\"],\"geneQueries\":[[{\"hugoGeneSymbol\":\"APC\",\"entrezGeneId\":0,\"alterations\":[],\"includeDriver\":true,\"includeVUS\":true,\"includeUnknownOncogenicity\":true,\"tiersBooleanMap\":{},\"includeUnknownTier\":true,\"includeGermline\":true,\"includeSomatic\":true,\"includeUnknownStatus\":true},{\"hugoGeneSymbol\":\"TP53\",\"entrezGeneId\":0,\"alterations\":[],\"includeDriver\":true,\"includeVUS\":true,\"includeUnknownOncogenicity\":true,\"tiersBooleanMap\":{},\"includeUnknownTier\":true,\"includeGermline\":true,\"includeSomatic\":true,\"includeUnknownStatus\":true}]]}],\"studyIds\":[\"crc_public_genie_bpc\",\"coadread_tcga_pan_can_atlas_2018\"],\"alterationFilter\":{\"copyNumberAlterationEventTypes\":{\"AMP\":true,\"HOMDEL\":true},\"mutationEventTypes\":{\"any\":true},\"structuralVariants\":null,\"includeDriver\":true,\"includeVUS\":true,\"includeUnknownOncogenicity\":true,\"includeUnknownTier\":true,\"includeGermline\":true,\"includeSomatic\":true,\"includeUnknownStatus\":true,\"tiersBooleanMap\":{}}}"}, + {"hash":1605173863, + "skip":"off panel discrep", + "filterString":" (APC OR TP53) ","data":{"geneFilters":[{"molecularProfileIds":["coadread_tcga_pan_can_atlas_2018_mutations","crc_public_genie_bpc_mutations"],"geneQueries":[[{"hugoGeneSymbol":"APC","entrezGeneId":0,"alterations":[],"includeDriver":true,"includeVUS":true,"includeUnknownOncogenicity":true,"tiersBooleanMap":{},"includeUnknownTier":true,"includeGermline":true,"includeSomatic":true,"includeUnknownStatus":true},{"hugoGeneSymbol":"TP53","entrezGeneId":0,"alterations":[],"includeDriver":true,"includeVUS":true,"includeUnknownOncogenicity":true,"tiersBooleanMap":{},"includeUnknownTier":true,"includeGermline":true,"includeSomatic":true,"includeUnknownStatus":true}]]}],"studyIds":["crc_public_genie_bpc","coadread_tcga_pan_can_atlas_2018"],"alterationFilter":{"copyNumberAlterationEventTypes":{"AMP":true,"HOMDEL":true},"mutationEventTypes":{"any":true},"structuralVariants":null,"includeDriver":true,"includeVUS":true,"includeUnknownOncogenicity":true,"includeUnknownTier":true,"includeGermline":true,"includeSomatic":true,"includeUnknownStatus":true,"tiersBooleanMap":{}}},"url":"/api/column-store/mutated-genes/fetch?","label":"MutatedGenes","studies":["crc_public_genie_bpc","coadread_tcga_pan_can_atlas_2018"],"filterUrl":"/study/summary?id=crc_public_genie_bpc%2Ccoadread_tcga_pan_can_atlas_2018#filterJson={\"geneFilters\":[{\"molecularProfileIds\":[\"coadread_tcga_pan_can_atlas_2018_mutations\",\"crc_public_genie_bpc_mutations\"],\"geneQueries\":[[{\"hugoGeneSymbol\":\"APC\",\"entrezGeneId\":0,\"alterations\":[],\"includeDriver\":true,\"includeVUS\":true,\"includeUnknownOncogenicity\":true,\"tiersBooleanMap\":{},\"includeUnknownTier\":true,\"includeGermline\":true,\"includeSomatic\":true,\"includeUnknownStatus\":true},{\"hugoGeneSymbol\":\"TP53\",\"entrezGeneId\":0,\"alterations\":[],\"includeDriver\":true,\"includeVUS\":true,\"includeUnknownOncogenicity\":true,\"tiersBooleanMap\":{},\"includeUnknownTier\":true,\"includeGermline\":true,\"includeSomatic\":true,\"includeUnknownStatus\":true}]]}],\"studyIds\":[\"crc_public_genie_bpc\",\"coadread_tcga_pan_can_atlas_2018\"],\"alterationFilter\":{\"copyNumberAlterationEventTypes\":{\"AMP\":true,\"HOMDEL\":true},\"mutationEventTypes\":{\"any\":true},\"structuralVariants\":null,\"includeDriver\":true,\"includeVUS\":true,\"includeUnknownOncogenicity\":true,\"includeUnknownTier\":true,\"includeGermline\":true,\"includeSomatic\":true,\"includeUnknownStatus\":true,\"tiersBooleanMap\":{}}}"}, {"hash":1720035856,"filterString":" (APC OR TP53) ","data":{"geneFilters":[{"molecularProfileIds":["coadread_tcga_pan_can_atlas_2018_mutations","crc_public_genie_bpc_mutations"],"geneQueries":[[{"hugoGeneSymbol":"APC","entrezGeneId":0,"alterations":[],"includeDriver":true,"includeVUS":true,"includeUnknownOncogenicity":true,"tiersBooleanMap":{},"includeUnknownTier":true,"includeGermline":true,"includeSomatic":true,"includeUnknownStatus":true},{"hugoGeneSymbol":"TP53","entrezGeneId":0,"alterations":[],"includeDriver":true,"includeVUS":true,"includeUnknownOncogenicity":true,"tiersBooleanMap":{},"includeUnknownTier":true,"includeGermline":true,"includeSomatic":true,"includeUnknownStatus":true}]]}],"studyIds":["crc_public_genie_bpc","coadread_tcga_pan_can_atlas_2018"],"alterationFilter":{"copyNumberAlterationEventTypes":{"AMP":true,"HOMDEL":true},"mutationEventTypes":{"any":true},"structuralVariants":null,"includeDriver":true,"includeVUS":true,"includeUnknownOncogenicity":true,"includeUnknownTier":true,"includeGermline":true,"includeSomatic":true,"includeUnknownStatus":true,"tiersBooleanMap":{}}},"url":"/api/column-store/molecular-profile-sample-counts/fetch?","label":"MolecularProfileSample","studies":["crc_public_genie_bpc","coadread_tcga_pan_can_atlas_2018"],"filterUrl":"/study/summary?id=crc_public_genie_bpc%2Ccoadread_tcga_pan_can_atlas_2018#filterJson={\"geneFilters\":[{\"molecularProfileIds\":[\"coadread_tcga_pan_can_atlas_2018_mutations\",\"crc_public_genie_bpc_mutations\"],\"geneQueries\":[[{\"hugoGeneSymbol\":\"APC\",\"entrezGeneId\":0,\"alterations\":[],\"includeDriver\":true,\"includeVUS\":true,\"includeUnknownOncogenicity\":true,\"tiersBooleanMap\":{},\"includeUnknownTier\":true,\"includeGermline\":true,\"includeSomatic\":true,\"includeUnknownStatus\":true},{\"hugoGeneSymbol\":\"TP53\",\"entrezGeneId\":0,\"alterations\":[],\"includeDriver\":true,\"includeVUS\":true,\"includeUnknownOncogenicity\":true,\"tiersBooleanMap\":{},\"includeUnknownTier\":true,\"includeGermline\":true,\"includeSomatic\":true,\"includeUnknownStatus\":true}]]}],\"studyIds\":[\"crc_public_genie_bpc\",\"coadread_tcga_pan_can_atlas_2018\"],\"alterationFilter\":{\"copyNumberAlterationEventTypes\":{\"AMP\":true,\"HOMDEL\":true},\"mutationEventTypes\":{\"any\":true},\"structuralVariants\":null,\"includeDriver\":true,\"includeVUS\":true,\"includeUnknownOncogenicity\":true,\"includeUnknownTier\":true,\"includeGermline\":true,\"includeSomatic\":true,\"includeUnknownStatus\":true,\"tiersBooleanMap\":{}}}"}, diff --git a/test/integration/docker-compose-localbuild.yml b/test/integration/docker-compose-localbuild.yml index b9c88de96fc..8cac16b9446 100644 --- a/test/integration/docker-compose-localbuild.yml +++ b/test/integration/docker-compose-localbuild.yml @@ -5,6 +5,7 @@ version: '3' services: cbioportal: + image: cbioportal/cbioportal:master command: /bin/sh -c "java -Xms2g -Xmx4g -jar cbioportal/target/cbioportal-exec.jar --spring.config.location=cbioportal-webapp/application.properties --authenticate=false" volumes: #- $PORTAL_INFO_DIR:/portalinfo/ diff --git a/test/test_data/study_es_0/data_mutations_extended.maf b/test/test_data/study_es_0/data_mutations_extended.maf index 32fc3e84e9d..fd510f5f122 100644 --- a/test/test_data/study_es_0/data_mutations_extended.maf +++ b/test/test_data/study_es_0/data_mutations_extended.maf @@ -1,4 +1,4 @@ -#version 2.4 +#version 2.4 Hugo_Symbol Entrez_Gene_Id Center NCBI_Build Chromosome Start_Position End_Position Strand Variant_Classification Variant_Type Reference_Allele Tumor_Seq_Allele1 Tumor_Seq_Allele2 dbSNP_RS dbSNP_Val_Status Tumor_Sample_Barcode Matched_Norm_Sample_Barcode Match_Norm_Seq_Allele1 Match_Norm_Seq_Allele2 Tumor_Validation_Allele1 Tumor_Validation_Allele2 Match_Norm_Validation_Allele1 Match_Norm_Validation_Allele2 Verification_Status Validation_Status Mutation_Status Sequencing_Phase Sequence_Source Validation_Method Score BAM_File Sequencer MA:FImpact MA:FIS Amino_Acid_Change MA:link.MSA MA:link.PDB MA:link.var Tumor_Sample_UUID Matched_Norm_Sample_UUID HGVSc HGVSp HGVSp_Short Transcript_ID Exon_Number t_depth t_ref_count t_alt_count n_depth n_ref_count n_alt_count all_effects Allele Gene Feature Feature_type Consequence cDNA_position CDS_position Protein_position Amino_acids Codons Existing_variation ALLELE_NUM DISTANCE SYMBOL SYMBOL_SOURCE HGNC_ID BIOTYPE CANONICAL CCDS ENSP SWISSPROT TREMBL UNIPARC RefSeq SIFT PolyPhen EXON INTRON DOMAINS GMAF AFR_MAF AMR_MAF ASN_MAF EAS_MAF EUR_MAF SAS_MAF AA_MAF EA_MAF CLIN_SIG SOMATIC PUBMED MOTIF_NAME MOTIF_POS HIGH_INF_POS MOTIF_SCORE_CHANGE IMPACT PICK VARIANT_CLASS TSL HGVS_OFFSET PHENO chromosome_name_wu start_wu stop_wu reference_wu variant_wu type_wu gene_name_wu transcript_name_wu transcript_species_wu transcript_source_wu transcript_version_wu strand_wu transcript_status_wu trv_type_wu c_position_wu amino_acid_change_wu ucsc_cons_wu domain_wu all_domains_wu deletion_substructures_wu transcript_error_wu default_gene_name_wu gene_name_source_wu ensembl_gene_id normal_ref_reads normal_var_reads normal_vaf tumor_ref_reads tumors_var_reads tumor_vaf evs_ea evs_aa evs_all chromosome_name_WU start_WU stop_WU reference_WU variant_WU type_WU gene_name_WU transcript_name_WU transcript_species_WU transcript_source_WU transcript_version_WU strand_WU transcript_status_WU trv_type_WU c_position_WU amino_acid_change_WU ucsc_cons_WU domain_WU all_domains_WU deletion_substructures_WU transcript_error_WU default_gene_name_WU gene_name_source_WU EVS_EA EVS_AA EVS_All cbp_driver cbp_driver_annotation cbp_driver_tiers cbp_driver_tiers_annotation Zygosity.name Zygosity.code OR11H1 genome.wustl.edu GRCh37 22 16449539 16449539 -1 Missense_Mutation SNP A A G TCGA-A1-A0SB-01 TCGA-A1-A0SB-10 A A Unknown Untested Somatic Phase_IV WXS none 1 dbGAP Illumina GAIIx low 1.49 V89A getma.org/?cm=msa&ty=f&p=O11H1_HUMAN&rb=1&re=154&var=V89A getma.org/?cm=var&var=hg19,22,16449539,A,G&fts=all db9d40fb-bfce-4c3b-a6c2-41c5c88982f1 a3254f8e-3bbd-42fc-abea-a5f25b7648b3 c.266T>C p.Val89Ala p.V89A ENST00000252835 1/1 0 0 OR11H1,missense_variant,p.Val89Ala,ENST00000252835,NM_001005239.1; G ENSG00000130538 ENST00000252835 Transcript missense_variant 267/982 266/981 89/326 V/A gTc/gCc rs199856986,COSM1484040 1 OR11H1 HGNC 15404 protein_coding YES CCDS33594.1 ENSP00000252835 O11H1_HUMAN UPI000004B1CF NM_001005239.1 deleterious(0.02) possibly_damaging(0.589) 1/1 Transmembrane_helices:TMhelix,PROSITE_profiles:PS50262,hmmpanther:PTHR24242:SF201,hmmpanther:PTHR24242,Gene3D:1.20.1070.10,Superfamily_domains:SSF81321 0,1 MODERATE 1 SNV 0,1 22 16449539 16449539 A G SNP OR11H1 ENST00000252835 human ensembl 69_37n -1 known missense c.266 p.V89A 234 pfam_7TM_GPCR_Rhodpsn,pfscan_GPCR_Rhodpsn_supfam pfam_7TM_GPCR_Rhodpsn,pfscan_GPCR_Rhodpsn_supfam,prints_Olfact_rcpt,prints_7TM_GPCR_Rhodpsn - no_errors OR11H1 HGNC ENSG00000130538 65 0 0 38 6 13.64 - - - 22 16449539 16449539 A G SNP OR11H1 ENST00000252835 human ensembl 69_37n -1 known missense c.266 p.V89A 234 pfam_7TM_GPCR_Rhodpsn,pfscan_GPCR_Rhodpsn_supfam pfam_7TM_GPCR_Rhodpsn,pfscan_GPCR_Rhodpsn_supfam,prints_Olfact_rcpt,prints_7TM_GPCR_Rhodpsn - no_errors OR11H1 HGNC - - - Putative_Driver Test driver TMEM247 genome.wustl.edu GRCh37 2 46707888 46707888 1 Frame_Shift_Del DEL G G - TCGA-A1-A0SB-01 TCGA-A1-A0SB-10 G G Unknown Untested Somatic Phase_IV WXS none 1 dbGAP Illumina GAIIx db9d40fb-bfce-4c3b-a6c2-41c5c88982f1 a3254f8e-3bbd-42fc-abea-a5f25b7648b3 c.463delG p.Ala155ArgfsTer59 p.A155Rfs*59 ENST00000434431 2/3 0 0 TMEM247,frameshift_variant,p.Ala155ArgfsTer59,ENST00000434431,NM_001145051.2;TMEM247,intron_variant,,ENST00000432241,; - ENSG00000187600 ENST00000434431 Transcript frameshift_variant 462/659 462/659 154/219 E/X gaG/ga COSM1408208,~rs70940616 1 TMEM247 HGNC 42967 protein_coding YES CCDS56117.1 ENSP00000388684 TM247_HUMAN UPI0000366EF8 NM_001145051.2 2/3 Coiled-coils_(Ncoils):Coil,Pfam_domain:PF15444 -:0.0202 -:0.0439 1 HIGH 1 deletion 1 1 2 46707888 46707888 G - DEL TMEM247 ENST00000434431 human ensembl 69_37n 1 known frame_shift_del c.462 p.A155fs 83 - no_stop_codon:bad_bp_length_for_coding_region TMEM247 HGNC ENSG00000187600 20 0 0 7 3 30 - - - 2 46707888 46707888 G - DEL TMEM247 ENST00000434431 human ensembl 69_37n 1 known frame_shift_del c.462 p.A155fs 83 - no_stop_codon:bad_bp_length_for_coding_region TMEM247 HGNC - - - Putative_Passenger Test passenger Class 2 Class annotation @@ -10,26 +10,26 @@ KAT2A genome.wustl.edu GRCh37 17 40272381 40272381 -1 Silent SNP G G A TCGA-A MSH3 genome.wustl.edu GRCh37 5 80024722 80024722 1 Frame_Shift_Del DEL T T - TCGA-A1-A0SB-02 TCGA-A1-A0SB-10 T T Unknown Untested Somatic Phase_IV WXS none 1 dbGAP Illumina GAIIx db9d40fb-bfce-4c3b-a6c2-41c5c88982f1 a3254f8e-3bbd-42fc-abea-a5f25b7648b3 c.1508delT p.Leu503TrpfsTer5 p.L503Wfs*5 ENST00000265081 10/24 0 0 MSH3,frameshift_variant,p.Leu503TrpfsTer5,ENST00000265081,NM_002439.4;MSH3,non_coding_transcript_exon_variant,,ENST00000512258,; - ENSG00000113318 ENST00000265081 Transcript frameshift_variant 1586/4092 1506/3414 502/1137 S/X tcT/tc 1 MSH3 HGNC 7326 protein_coding YES CCDS34195.1 ENSP00000265081 MSH3_HUMAN UPI0000DBEE85 NM_002439.4 10/24 Superfamily_domains:SSF53150,Gene3D:3.30.420.110,Pfam_domain:PF05188,hmmpanther:PTHR11361,hmmpanther:PTHR11361:SF34 HIGH 1 deletion 2 5 80024722 80024722 T - DEL MSH3 ENST00000265081 human ensembl 69_37n 1 known frame_shift_del c.1506 p.L503fs 998 pfam_DNA_mismatch_repair_MutS_connt,superfamily_DNA_mismatch_repair_MutS_connt pfam_DNA_mismatch_repair_MutS_C,pfam_DNA_mismatch_repair_MutS_core,pfam_DNA_mismatch_repair_MutS_connt,pfam_DNA_mismatch_repair_MutS-lik_N,pfam_DNA_mismatch_repair_MutS_clamp,superfamily_DNA_mismatch_repair_MutS_core,superfamily_DNA_mismatch_repair_MutS_N,superfamily_DNA_mismatch_repair_MutS_connt,smart_DNA_mismatch_repair_MutS_core,smart_DNA_mismatch_repair_MutS_C - no_errors MSH3 HGNC ENSG00000113318 83 0 0 12 2 14.29 - - - 5 80024722 80024722 T - DEL MSH3 ENST00000265081 human ensembl 69_37n 1 known frame_shift_del c.1506 p.L503fs 998 pfam_DNA_mismatch_repair_MutS_connt,superfamily_DNA_mismatch_repair_MutS_connt pfam_DNA_mismatch_repair_MutS_C,pfam_DNA_mismatch_repair_MutS_core,pfam_DNA_mismatch_repair_MutS_connt,pfam_DNA_mismatch_repair_MutS-lik_N,pfam_DNA_mismatch_repair_MutS_clamp,superfamily_DNA_mismatch_repair_MutS_core,superfamily_DNA_mismatch_repair_MutS_N,superfamily_DNA_mismatch_repair_MutS_connt,smart_DNA_mismatch_repair_MutS_core,smart_DNA_mismatch_repair_MutS_C - no_errors MSH3 HGNC - - - Putative_Passenger Test passenger Class 3 Class annotation MYB genome.wustl.edu GRCh37 6 135507043 135507044 1 Frame_Shift_Ins INS - - A TCGA-A1-A0SB-02 TCGA-A1-A0SB-10 - - Unknown Untested Somatic Phase_IV WXS none 1 dbGAP Illumina GAIIx db9d40fb-bfce-4c3b-a6c2-41c5c88982f1 a3254f8e-3bbd-42fc-abea-a5f25b7648b3 c.27dupA p.Tyr10IlefsTer2 p.Y10Ifs*2 ENST00000367814 2/15 0 0 MYB,frameshift_variant,p.Tyr10IlefsTer2,ENST00000341911,NM_001130173.1,NM_001161658.1,NM_001161656.1;MYB,frameshift_variant,p.Tyr10IlefsTer2,ENST00000316528,;MYB,frameshift_variant,p.Tyr10IlefsTer2,ENST00000442647,NM_001161660.1,NM_001130172.1;MYB,frameshift_variant,p.Tyr10IlefsTer2,ENST00000367814,NM_001161659.1,NM_005375.2;MYB,frameshift_variant,p.Tyr10IlefsTer2,ENST00000525369,NM_001161657.1;MYB,frameshift_variant,p.Tyr10IlefsTer2,ENST00000527615,;MYB,frameshift_variant,p.Tyr10IlefsTer2,ENST00000528774,;MYB,frameshift_variant,p.Tyr10IlefsTer2,ENST00000534121,;MYB,frameshift_variant,p.Tyr10IlefsTer2,ENST00000533624,;MYB,frameshift_variant,p.Tyr10IlefsTer2,ENST00000534044,;MYB,frameshift_variant,p.Tyr10IlefsTer2,ENST00000420123,;MYB,upstream_gene_variant,,ENST00000430686,;MYB,non_coding_transcript_exon_variant,,ENST00000531845,;MYB,frameshift_variant,p.Tyr10IlefsTer2,ENST00000367812,;MYB,frameshift_variant,p.Tyr10IlefsTer2,ENST00000533837,;MYB,frameshift_variant,p.Tyr10IlefsTer2,ENST00000438901,;MYB,frameshift_variant,p.Tyr10IlefsTer2,ENST00000525477,;MYB,frameshift_variant,p.Tyr10IlefsTer2,ENST00000463282,;MYB,frameshift_variant,p.Tyr10IlefsTer2,ENST00000339290,;MYB,frameshift_variant,p.Tyr10IlefsTer2,ENST00000533808,;MYB,frameshift_variant,p.Tyr10IlefsTer2,ENST00000525514,;MYB,frameshift_variant,p.Tyr10IlefsTer2,ENST00000529586,;MYB,frameshift_variant,p.Tyr10IlefsTer2,ENST00000526889,;MYB,frameshift_variant,p.Tyr10IlefsTer2,ENST00000526320,;MYB,frameshift_variant,p.Tyr10IlefsTer2,ENST00000531519,;MYB,frameshift_variant,p.Tyr10IlefsTer2,ENST00000533384,;MYB,frameshift_variant,p.Tyr10IlefsTer2,ENST00000531737,;MYB,frameshift_variant,p.Tyr10IlefsTer2,ENST00000529262,;MYB,frameshift_variant,p.Tyr10IlefsTer2,ENST00000526565,;MYB,frameshift_variant,p.Tyr10IlefsTer2,ENST00000528015,;MYB,frameshift_variant,p.Tyr10IlefsTer2,ENST00000526187,;MYB,frameshift_variant,p.Tyr10IlefsTer2,ENST00000525002,;MYB,frameshift_variant,p.Tyr10IlefsTer2,ENST00000528343,;MYB,frameshift_variant,p.Tyr10IlefsTer2,ENST00000528140,;MYB,frameshift_variant,p.Tyr10IlefsTer2,ENST00000528345,;MYB,frameshift_variant,p.Tyr10IlefsTer2,ENST00000525940,;MYB,frameshift_variant,p.Tyr10Ter,ENST00000531634,;MYB,frameshift_variant,p.Tyr10IlefsTer2,ENST00000524588,; A ENSG00000118513 ENST00000367814 Transcript frameshift_variant 212-213/3302 26-27/1923 9/640 I/IX ata/atAa COSM1487247,COSM1487248 1 MYB HGNC 7545 protein_coding CCDS5174.1 ENSP00000356788 MYB_HUMAN Q9UMI7_HUMAN,Q708J0_HUMAN,Q708E9_HUMAN,Q708E3_HUMAN UPI000012FAEA NM_001161659.1,NM_005375.2 2/15 hmmpanther:PTHR10641,hmmpanther:PTHR10641:SF454 1,1 HIGH insertion 1 1,1 6 135507043 135507044 - A INS MYB ENST00000341911 human ensembl 69_37n 1 known frame_shift_ins c.26_27 p.Y10fs 1.000:0.997 pfam_C-myb_C,pfam_SANT/Myb,pfam_Tscrpt_reg_Wos2-domain,superfamily_Homeodomain-like,smart_SANT/Myb,pfscan_Myb-like_dom - no_errors MYB HGNC ENSG00000118513 50 0 0 36 4 10 - - - 6 135507043 135507044 - A INS MYB ENST00000341911 human ensembl 69_37n 1 known frame_shift_ins c.26_27 p.Y10fs 1.000:0.997 pfam_C-myb_C,pfam_SANT/Myb,pfam_Tscrpt_reg_Wos2-domain,superfamily_Homeodomain-like,smart_SANT/Myb,pfscan_Myb-like_dom - no_errors MYB HGNC - - - Putative_Passenger Test passenger PIEZO1 genome.wustl.edu GRCh37 16 88790292 88790292 -1 Missense_Mutation SNP T T C TCGA-A1-A0SB-02 TCGA-A1-A0SB-10 T T Unknown Untested Somatic Phase_IV WXS none 1 dbGAP Illumina GAIIx low 1.18 Q1441R getma.org/?cm=msa&ty=f&p=PIEZ1_HUMAN&rb=58&re=1627&var=Q1441R getma.org/?cm=var&var=hg19,16,88790292,T,C&fts=all db9d40fb-bfce-4c3b-a6c2-41c5c88982f1 a3254f8e-3bbd-42fc-abea-a5f25b7648b3 c.4322A>G p.Gln1441Arg p.Q1441R ENST00000301015 31/51 0 0 PIEZO1,missense_variant,p.Gln1441Arg,ENST00000301015,NM_001142864.2;PIEZO1,missense_variant,p.Gln115Arg,ENST00000474606,;PIEZO1,upstream_gene_variant,,ENST00000327397,;PIEZO1,upstream_gene_variant,,ENST00000466823,;RP5-1142A6.9,downstream_gene_variant,,ENST00000564984,;PIEZO1,non_coding_transcript_exon_variant,,ENST00000566414,;PIEZO1,upstream_gene_variant,,ENST00000419505,;PIEZO1,upstream_gene_variant,,ENST00000497793,;PIEZO1,upstream_gene_variant,,ENST00000495568,;PIEZO1,downstream_gene_variant,,ENST00000475586,;PIEZO1,downstream_gene_variant,,ENST00000491917,; C ENSG00000103335 ENST00000301015 Transcript missense_variant 4569/8072 4322/7566 1441/2521 Q/R cAg/cGg COSM1479166 1 PIEZO1 HGNC 28993 protein_coding YES CCDS54058.1 ENSP00000301015 PIEZ1_HUMAN UPI0001B300F3 NM_001142864.2 tolerated(0.25) possibly_damaging(0.78) 31/51 hmmpanther:PTHR13167,hmmpanther:PTHR13167:SF40 1 MODERATE 1 SNV 1 16 88790292 88790292 T C SNP PIEZO1 ENST00000301015 human ensembl 69_37n -1 novel missense c.4322 p.Q1441R 1000 pfam_DUF3595 - no_errors PIEZO1 HGNC ENSG00000103335 37 0 0 20 8 28.57 - - - 16 88790292 88790292 T C SNP PIEZO1 ENST00000301015 human ensembl 69_37n -1 novel missense c.4322 p.Q1441R 1000 pfam_DUF3595 - no_errors PIEZO1 HGNC - - - Putative_Passenger Test passenger Class 3 Class annotation -TP53 genome.wustl.edu GRCh37 17 7578253 7578253 0 Missense_Mutation SNP C C A TCGA-A1-A0SB-01 TCGA-A1-A0SB-10 A C Unknown Germline Phase_IV Capture 1 dbGAP IlluminaGAIIx medium 3.005 getma.org/?cm=msa&ty=f&p=P53_HUMAN&rb=95&re=289&var=G199V getma.org/pdb.php?prot=P53_HUMAN&from=95&to=289&var=G199V getma.org/?cm=var&var=hg19,17,7578253,C,A&fts=all ENST00000269305.4:c.596G>T p.Gly199Val p.G199V ENST00000269305 11-Jun 0 0 TP53,missense_variant,p.Gly199Val,ENST00000420246,NM_001126114.2,NM_001276696.1;TP53,missense_variant,p.Gly199Val,ENST00000455263,NM_001276695.1,NM_001126113.2;TP53,missense_variant,p.Gly199Val,ENST00000269305,NM_001126112.2,NM_001276761.1,NM_001276760.1,NM_000546.5,NM_001126118.1;TP53,missense_variant,p.Gly199Val,ENST00000445888,;TP53,missense_variant,p.Gly199Val,ENST00000359597,;TP53,missense_variant,p.Gly199Val,ENST00000413465,;TP53,missense_variant,p.Gly67Val,ENST00000509690,;TP53,missense_variant,p.Gly106Val,ENST00000514944,;TP53,downstream_gene_variant,,ENST00000508793,;TP53,downstream_gene_variant,,ENST00000604348,;TP53,downstream_gene_variant,,ENST00000503591,;TP53,upstream_gene_variant,,ENST00000576024,;TP53,intron_variant,,ENST00000574684,;TP53,non_coding_transcript_exon_variant,,ENST00000510385,;TP53,non_coding_transcript_exon_variant,,ENST00000504290,;TP53,non_coding_transcript_exon_variant,,ENST00000504937,;TP53,non_coding_transcript_exon_variant,,ENST00000505014,; A ENSG00000141510 ENST00000269305 Transcript missense_variant 786/2579 596/1182 199 G/V gGa/gTa TP53_g.12665G>T,COSM44140,COSM255788,COSM255787,COSM255789,COSM3675525,COSM3675524,COSM255790 1 TP53 HGNC 11998 protein_coding YES CCDS11118.1 ENSP00000269305 P53_HUMAN S5LQU8_HUMAN,Q761V2_HUMAN,Q6IT77_HUMAN,Q1HGV1_HUMAN,Q0PKT5_HUMAN,L0ES54_HUMAN,L0EQ05_HUMAN,K7PPA8_HUMAN,H2EHT1_HUMAN,G4Y083_HUMAN,E9PCY9_HUMAN,E7ESS1_HUMAN,E7EMR6_HUMAN,B5AKF6_HUMAN,B4DNI2_HUMAN,A4GWD0_HUMAN,A4GWB8_HUMAN,A4GWB5_HUMAN,A4GW97_HUMAN,A4GW76_HUMAN,A4GW75_HUMAN,A4GW74_HUMAN,A4GW67_HUMAN,A2I9Z1_HUMAN,A2I9Z0_HUMAN UPI000002ED67 NM_001126112.2 deleterious(0) probably_damaging(1) 11-Jun Gene3D:2.60.40.720,Pfam_domain:PF00870,hmmpanther:PTHR11447,hmmpanther:PTHR11447:SF6,Superfamily_domains:SSF49417 0,1,1,1,1,1,1,1 MODERATE 1 SNV 0,1,1,1,1,1,1,1 17 7578253 7578253 C A SNP TP53 NM_000546.4 human genbank 58_37c -1 reviewed missense c.596 p.G199V 1 HMMPfam_P53|7Csuperfamily_p53-like transcription factors HMMPfam_P53_TAD|7CHMMPfam_P53|7Csuperfamily_p53-like transcription factors|7CPatternScan_P53|7CHMMPfam_P53_tetramer|7Csuperfamily_p53 tetramerization domain - 17 7578253 7578253 C A SNP TP53 NM_000546.4 human genbank 58_37c -1 reviewed missense c.596 p.G199V 1 HMMPfam_P53|7Csuperfamily_p53-like transcription factors HMMPfam_P53_TAD|7CHMMPfam_P53|7Csuperfamily_p53-like transcription factors|7CPatternScan_P53|7CHMMPfam_P53_tetramer|7Csuperfamily_p53 tetramerization domain - +TP53 genome.wustl.edu GRCh37 17 7578253 7578253 0 Missense_Mutation SNP C C A TCGA-A1-A0SB-01 TCGA-A1-A0SB-10 A C Unknown Somatic Phase_IV Capture 1 dbGAP IlluminaGAIIx medium 3.005 getma.org/?cm=msa&ty=f&p=P53_HUMAN&rb=95&re=289&var=G199V getma.org/pdb.php?prot=P53_HUMAN&from=95&to=289&var=G199V getma.org/?cm=var&var=hg19,17,7578253,C,A&fts=all ENST00000269305.4:c.596G>T p.Gly199Val p.G199V ENST00000269305 11-Jun 0 0 TP53,missense_variant,p.Gly199Val,ENST00000420246,NM_001126114.2,NM_001276696.1;TP53,missense_variant,p.Gly199Val,ENST00000455263,NM_001276695.1,NM_001126113.2;TP53,missense_variant,p.Gly199Val,ENST00000269305,NM_001126112.2,NM_001276761.1,NM_001276760.1,NM_000546.5,NM_001126118.1;TP53,missense_variant,p.Gly199Val,ENST00000445888,;TP53,missense_variant,p.Gly199Val,ENST00000359597,;TP53,missense_variant,p.Gly199Val,ENST00000413465,;TP53,missense_variant,p.Gly67Val,ENST00000509690,;TP53,missense_variant,p.Gly106Val,ENST00000514944,;TP53,downstream_gene_variant,,ENST00000508793,;TP53,downstream_gene_variant,,ENST00000604348,;TP53,downstream_gene_variant,,ENST00000503591,;TP53,upstream_gene_variant,,ENST00000576024,;TP53,intron_variant,,ENST00000574684,;TP53,non_coding_transcript_exon_variant,,ENST00000510385,;TP53,non_coding_transcript_exon_variant,,ENST00000504290,;TP53,non_coding_transcript_exon_variant,,ENST00000504937,;TP53,non_coding_transcript_exon_variant,,ENST00000505014,; A ENSG00000141510 ENST00000269305 Transcript missense_variant 786/2579 596/1182 199 G/V gGa/gTa TP53_g.12665G>T,COSM44140,COSM255788,COSM255787,COSM255789,COSM3675525,COSM3675524,COSM255790 1 TP53 HGNC 11998 protein_coding YES CCDS11118.1 ENSP00000269305 P53_HUMAN S5LQU8_HUMAN,Q761V2_HUMAN,Q6IT77_HUMAN,Q1HGV1_HUMAN,Q0PKT5_HUMAN,L0ES54_HUMAN,L0EQ05_HUMAN,K7PPA8_HUMAN,H2EHT1_HUMAN,G4Y083_HUMAN,E9PCY9_HUMAN,E7ESS1_HUMAN,E7EMR6_HUMAN,B5AKF6_HUMAN,B4DNI2_HUMAN,A4GWD0_HUMAN,A4GWB8_HUMAN,A4GWB5_HUMAN,A4GW97_HUMAN,A4GW76_HUMAN,A4GW75_HUMAN,A4GW74_HUMAN,A4GW67_HUMAN,A2I9Z1_HUMAN,A2I9Z0_HUMAN UPI000002ED67 NM_001126112.2 deleterious(0) probably_damaging(1) 11-Jun Gene3D:2.60.40.720,Pfam_domain:PF00870,hmmpanther:PTHR11447,hmmpanther:PTHR11447:SF6,Superfamily_domains:SSF49417 0,1,1,1,1,1,1,1 MODERATE 1 SNV 0,1,1,1,1,1,1,1 17 7578253 7578253 C A SNP TP53 NM_000546.4 human genbank 58_37c -1 reviewed missense c.596 p.G199V 1 HMMPfam_P53|7Csuperfamily_p53-like transcription factors HMMPfam_P53_TAD|7CHMMPfam_P53|7Csuperfamily_p53-like transcription factors|7CPatternScan_P53|7CHMMPfam_P53_tetramer|7Csuperfamily_p53 tetramerization domain - 17 7578253 7578253 C A SNP TP53 NM_000546.4 human genbank 58_37c -1 reviewed missense c.596 p.G199V 1 HMMPfam_P53|7Csuperfamily_p53-like transcription factors HMMPfam_P53_TAD|7CHMMPfam_P53|7Csuperfamily_p53-like transcription factors|7CPatternScan_P53|7CHMMPfam_P53_tetramer|7Csuperfamily_p53 tetramerization domain - TP53 genome.wustl.edu GRCh37 17 7576851 7576851 0 Splice_Site SNP A A C novel unknown TCGA-A1-A0SB-01 TCGA-A1-A0SB-10 A A Unknown Somatic Phase_IV Capture 1 dbGAP Illumina GAIIx ENST00000269305.4:c.993+2T>G p.X331_splice ENST00000269305 0 0 TP53,splice_donor_variant,,ENST00000420246,NM_001126114.2,NM_001276696.1;TP53,splice_donor_variant,,ENST00000455263,NM_001276695.1,NM_001126113.2;TP53,splice_donor_variant,,ENST00000269305,NM_001126112.2,NM_001276761.1,NM_001276760.1,NM_000546.5,NM_001126118.1;TP53,splice_donor_variant,,ENST00000445888,;TP53,splice_donor_variant,,ENST00000359597,;TP53,splice_donor_variant,,ENST00000576024,;TP53,intron_variant,,ENST00000413465,;TP53,downstream_gene_variant,,ENST00000509690,;TP53,downstream_gene_variant,,ENST00000508793,;TP53,downstream_gene_variant,,ENST00000604348,;TP53,downstream_gene_variant,,ENST00000503591,;TP53,downstream_gene_variant,,ENST00000514944,;TP53,downstream_gene_variant,,ENST00000574684,;TP53,splice_donor_variant,,ENST00000510385,;TP53,splice_donor_variant,,ENST00000504290,;TP53,splice_donor_variant,,ENST00000504937,;TP53,downstream_gene_variant,,ENST00000505014,; C ENSG00000141510 ENST00000269305 Transcript splice_donor_variant -/2579 993/1182 TP53_g.14067T>G,COSM29774,COSM146229 1 TP53 HGNC 11998 protein_coding YES CCDS11118.1 ENSP00000269305 P53_HUMAN S5LQU8_HUMAN,Q761V2_HUMAN,Q6IT77_HUMAN,Q1HGV1_HUMAN,Q0PKT5_HUMAN,L0ES54_HUMAN,L0EQ05_HUMAN,K7PPA8_HUMAN,H2EHT1_HUMAN,G4Y083_HUMAN,E9PCY9_HUMAN,E7ESS1_HUMAN,E7EMR6_HUMAN,B5AKF6_HUMAN,B4DNI2_HUMAN,A4GWD0_HUMAN,A4GWB8_HUMAN,A4GWB5_HUMAN,A4GW97_HUMAN,A4GW76_HUMAN,A4GW75_HUMAN,A4GW74_HUMAN,A4GW67_HUMAN,A2I9Z1_HUMAN,A2I9Z0_HUMAN UPI000002ED67 NM_001126112.2 10-Sep 0,1,1 HIGH 1 SNV 0,1,1 17 7576851 7576851 A C SNP TP53 NM_000546 human genbank 57_37b -1 reviewed splice_site c.993+2 e8+2 1 - - - 17 7576851 7576851 A C SNP TP53 NM_000546 human genbank 57_37b -1 reviewed splice_site c.993+2 e8+2 1 - - - -BRCA1 genome.wustl.edu GRCh37 17 41243581 41243581 0 Nonsense_Mutation SNP G G A rs80357262 TCGA-A1-A0SB-01 TCGA-A1-A0SB-10 A G Unknown Germline Phase_IV Capture 1 dbGAP IlluminaGAIIx 0 getma.org/?cm=var&var=hg19,17,41243581,G,A&fts=all ENST00000357654.3:c.3967C>T p.Gln1323Ter p.Q1323* ENST00000357654 23-Oct 0 0 BRCA1,stop_gained,p.Gln1027Ter,ENST00000309486,NM_007297.3;BRCA1,stop_gained,p.Gln1323Ter,ENST00000357654,NM_007294.3;BRCA1,stop_gained,p.Gln1323Ter,ENST00000346315,;BRCA1,stop_gained,p.Gln1323Ter,ENST00000354071,;BRCA1,stop_gained,p.Gln1323Ter,ENST00000471181,NM_007300.3;BRCA1,stop_gained,p.Gln1276Ter,ENST00000493795,;BRCA1,stop_gained,p.Gln88Ter,ENST00000461574,;BRCA1,intron_variant,,ENST00000352993,;BRCA1,intron_variant,,ENST00000351666,;BRCA1,intron_variant,,ENST00000468300,NM_007299.3;BRCA1,intron_variant,,ENST00000491747,NM_007298.3;BRCA1,intron_variant,,ENST00000478531,;BRCA1,intron_variant,,ENST00000493919,;BRCA1,intron_variant,,ENST00000484087,;BRCA1,intron_variant,,ENST00000591534,;BRCA1,intron_variant,,ENST00000487825,;BRCA1,intron_variant,,ENST00000586385,;BRCA1,intron_variant,,ENST00000591849,;BRCA1,downstream_gene_variant,,ENST00000470026,;BRCA1,downstream_gene_variant,,ENST00000477152,;BRCA1,downstream_gene_variant,,ENST00000494123,;BRCA1,downstream_gene_variant,,ENST00000473961,;BRCA1,downstream_gene_variant,,ENST00000497488,;BRCA1,downstream_gene_variant,,ENST00000476777,;BRCA1,3_prime_UTR_variant,,ENST00000461221,;BRCA1,non_coding_transcript_exon_variant,,ENST00000467274,;BRCA1,downstream_gene_variant,,ENST00000492859,;BRCA1,downstream_gene_variant,,ENST00000412061,; A ENSG00000012048 ENST00000357654 Transcript stop_gained 4086/7094 3967/5592 1323 Q/* Caa/Taa rs80357262 1 BRCA1 HGNC 1100 protein_coding CCDS11453.1 ENSP00000350283 BRCA1_HUMAN Q9UE29_HUMAN,Q9NQR3_HUMAN,Q92897_HUMAN,Q7KYU6_HUMAN,Q4EW25_HUMAN,Q3YB53_HUMAN,Q3YB50_HUMAN,Q3YB49_HUMAN,Q3LRH8_HUMAN,Q3B891_HUMAN,K7EPC7_HUMAN,K4K7V3_HUMAN,K4JXS7_HUMAN,K4JUB1_HUMAN,G4V503_HUMAN,G4V502_HUMAN,G4V500_HUMAN,G4V4Z8_HUMAN,G4V4Z7_HUMAN,G1UI37_HUMAN,E9PFZ0_HUMAN,E7EWN5_HUMAN,E7EP70_HUMAN,C9IZW4_HUMAN,C4PFY7_HUMAN UPI0000126AC8 NM_007294.3 23-Oct PIRSF_domain:PIRSF001734,hmmpanther:PTHR13763,hmmpanther:PTHR13763:SF0 not_provided,pathogenic HIGH SNV 1 17 41243581 41243581 G A SNP BRCA1 NM_007294.3 human genbank 58_37c -1 reviewed nonsense c.3967 p.Q1323* 0.949 HMMPfam_BRCT|7CHMMSmart_SM00292|7Csuperfamily_BRCT domain|7CHMMSmart_SM00184|7CPatternScan_ZF_RING_1|7CHMMPfam_zf-C3HC4|7Csuperfamily_RING/U-box - 17 41243581 41243581 G A SNP BRCA1 NM_007294.3 human genbank 58_37c -1 reviewed nonsense c.3967 p.Q1323* 0.949 HMMPfam_BRCT|7CHMMSmart_SM00292|7Csuperfamily_BRCT domain|7CHMMSmart_SM00184|7CPatternScan_ZF_RING_1|7CHMMPfam_zf-C3HC4|7Csuperfamily_RING/U-box - +BRCA1 genome.wustl.edu GRCh37 17 41243581 41243581 0 Nonsense_Mutation SNP G G A rs80357262 TCGA-A1-A0SB-01 TCGA-A1-A0SB-10 A G Unknown Somatic Phase_IV Capture 1 dbGAP IlluminaGAIIx 0 getma.org/?cm=var&var=hg19,17,41243581,G,A&fts=all ENST00000357654.3:c.3967C>T p.Gln1323Ter p.Q1323* ENST00000357654 23-Oct 0 0 BRCA1,stop_gained,p.Gln1027Ter,ENST00000309486,NM_007297.3;BRCA1,stop_gained,p.Gln1323Ter,ENST00000357654,NM_007294.3;BRCA1,stop_gained,p.Gln1323Ter,ENST00000346315,;BRCA1,stop_gained,p.Gln1323Ter,ENST00000354071,;BRCA1,stop_gained,p.Gln1323Ter,ENST00000471181,NM_007300.3;BRCA1,stop_gained,p.Gln1276Ter,ENST00000493795,;BRCA1,stop_gained,p.Gln88Ter,ENST00000461574,;BRCA1,intron_variant,,ENST00000352993,;BRCA1,intron_variant,,ENST00000351666,;BRCA1,intron_variant,,ENST00000468300,NM_007299.3;BRCA1,intron_variant,,ENST00000491747,NM_007298.3;BRCA1,intron_variant,,ENST00000478531,;BRCA1,intron_variant,,ENST00000493919,;BRCA1,intron_variant,,ENST00000484087,;BRCA1,intron_variant,,ENST00000591534,;BRCA1,intron_variant,,ENST00000487825,;BRCA1,intron_variant,,ENST00000586385,;BRCA1,intron_variant,,ENST00000591849,;BRCA1,downstream_gene_variant,,ENST00000470026,;BRCA1,downstream_gene_variant,,ENST00000477152,;BRCA1,downstream_gene_variant,,ENST00000494123,;BRCA1,downstream_gene_variant,,ENST00000473961,;BRCA1,downstream_gene_variant,,ENST00000497488,;BRCA1,downstream_gene_variant,,ENST00000476777,;BRCA1,3_prime_UTR_variant,,ENST00000461221,;BRCA1,non_coding_transcript_exon_variant,,ENST00000467274,;BRCA1,downstream_gene_variant,,ENST00000492859,;BRCA1,downstream_gene_variant,,ENST00000412061,; A ENSG00000012048 ENST00000357654 Transcript stop_gained 4086/7094 3967/5592 1323 Q/* Caa/Taa rs80357262 1 BRCA1 HGNC 1100 protein_coding CCDS11453.1 ENSP00000350283 BRCA1_HUMAN Q9UE29_HUMAN,Q9NQR3_HUMAN,Q92897_HUMAN,Q7KYU6_HUMAN,Q4EW25_HUMAN,Q3YB53_HUMAN,Q3YB50_HUMAN,Q3YB49_HUMAN,Q3LRH8_HUMAN,Q3B891_HUMAN,K7EPC7_HUMAN,K4K7V3_HUMAN,K4JXS7_HUMAN,K4JUB1_HUMAN,G4V503_HUMAN,G4V502_HUMAN,G4V500_HUMAN,G4V4Z8_HUMAN,G4V4Z7_HUMAN,G1UI37_HUMAN,E9PFZ0_HUMAN,E7EWN5_HUMAN,E7EP70_HUMAN,C9IZW4_HUMAN,C4PFY7_HUMAN UPI0000126AC8 NM_007294.3 23-Oct PIRSF_domain:PIRSF001734,hmmpanther:PTHR13763,hmmpanther:PTHR13763:SF0 not_provided,pathogenic HIGH SNV 1 17 41243581 41243581 G A SNP BRCA1 NM_007294.3 human genbank 58_37c -1 reviewed nonsense c.3967 p.Q1323* 0.949 HMMPfam_BRCT|7CHMMSmart_SM00292|7Csuperfamily_BRCT domain|7CHMMSmart_SM00184|7CPatternScan_ZF_RING_1|7CHMMPfam_zf-C3HC4|7Csuperfamily_RING/U-box - 17 41243581 41243581 G A SNP BRCA1 NM_007294.3 human genbank 58_37c -1 reviewed nonsense c.3967 p.Q1323* 0.949 HMMPfam_BRCT|7CHMMSmart_SM00292|7Csuperfamily_BRCT domain|7CHMMSmart_SM00184|7CPatternScan_ZF_RING_1|7CHMMPfam_zf-C3HC4|7Csuperfamily_RING/U-box - BRCA1 genome.wustl.edu GRCh37 17 41243581 41243581 0 Missense_Mutation SNP G G A rs80357262 TEST_SAMPLE_SOMATIC_HOMOZYGOUS TCGA-A1-A0SB-10 A G Unknown Somatic Phase_IV Capture 1 dbGAP IlluminaGAIIx 0 getma.org/?cm=var&var=hg19,17,41243581,G,A&fts=all ENST00000357654.3:c.3967C>T p.Ser1436Ser p.S1436S ENST00000357654 23-Oct 0 0 BRCA1,stop_gained,p.Gln1027Ter,ENST00000309486,NM_007297.3;BRCA1,stop_gained,p.Gln1323Ter,ENST00000357654,NM_007294.3;BRCA1,stop_gained,p.Gln1323Ter,ENST00000346315,;BRCA1,stop_gained,p.Gln1323Ter,ENST00000354071,;BRCA1,stop_gained,p.Gln1323Ter,ENST00000471181,NM_007300.3;BRCA1,stop_gained,p.Gln1276Ter,ENST00000493795,;BRCA1,stop_gained,p.Gln88Ter,ENST00000461574,;BRCA1,intron_variant,,ENST00000352993,;BRCA1,intron_variant,,ENST00000351666,;BRCA1,intron_variant,,ENST00000468300,NM_007299.3;BRCA1,intron_variant,,ENST00000491747,NM_007298.3;BRCA1,intron_variant,,ENST00000478531,;BRCA1,intron_variant,,ENST00000493919,;BRCA1,intron_variant,,ENST00000484087,;BRCA1,intron_variant,,ENST00000591534,;BRCA1,intron_variant,,ENST00000487825,;BRCA1,intron_variant,,ENST00000586385,;BRCA1,intron_variant,,ENST00000591849,;BRCA1,downstream_gene_variant,,ENST00000470026,;BRCA1,downstream_gene_variant,,ENST00000477152,;BRCA1,downstream_gene_variant,,ENST00000494123,;BRCA1,downstream_gene_variant,,ENST00000473961,;BRCA1,downstream_gene_variant,,ENST00000497488,;BRCA1,downstream_gene_variant,,ENST00000476777,;BRCA1,3_prime_UTR_variant,,ENST00000461221,;BRCA1,non_coding_transcript_exon_variant,,ENST00000467274,;BRCA1,downstream_gene_variant,,ENST00000492859,;BRCA1,downstream_gene_variant,,ENST00000412061,; A ENSG00000012048 ENST00000357654 Transcript stop_gained 4086/7094 3967/5592 1323 Q/* Caa/Taa rs80357262 1 BRCA1 HGNC 1100 protein_coding CCDS11453.1 ENSP00000350283 BRCA1_HUMAN Q9UE29_HUMAN,Q9NQR3_HUMAN,Q92897_HUMAN,Q7KYU6_HUMAN,Q4EW25_HUMAN,Q3YB53_HUMAN,Q3YB50_HUMAN,Q3YB49_HUMAN,Q3LRH8_HUMAN,Q3B891_HUMAN,K7EPC7_HUMAN,K4K7V3_HUMAN,K4JXS7_HUMAN,K4JUB1_HUMAN,G4V503_HUMAN,G4V502_HUMAN,G4V500_HUMAN,G4V4Z8_HUMAN,G4V4Z7_HUMAN,G1UI37_HUMAN,E9PFZ0_HUMAN,E7EWN5_HUMAN,E7EP70_HUMAN,C9IZW4_HUMAN,C4PFY7_HUMAN UPI0000126AC8 NM_007294.3 23-Oct PIRSF_domain:PIRSF001734,hmmpanther:PTHR13763,hmmpanther:PTHR13763:SF0 not_provided,pathogenic HIGH SNV 1 17 41243581 41243581 G A SNP BRCA1 NM_007294.3 human genbank 58_37c -1 reviewed nonsense c.3967 p.Q1323* 0.949 HMMPfam_BRCT|7CHMMSmart_SM00292|7Csuperfamily_BRCT domain|7CHMMSmart_SM00184|7CPatternScan_ZF_RING_1|7CHMMPfam_zf-C3HC4|7Csuperfamily_RING/U-box - 17 41243581 41243581 G A SNP BRCA1 NM_007294.3 human genbank 58_37c -1 reviewed nonsense c.3967 p.Q1323* 0.949 HMMPfam_BRCT|7CHMMSmart_SM00292|7Csuperfamily_BRCT domain|7CHMMSmart_SM00184|7CPatternScan_ZF_RING_1|7CHMMPfam_zf-C3HC4|7Csuperfamily_RING/U-box - Putative_Driver Test driver Class 1 Class annotation Homozygous 2 BRCA1 genome.wustl.edu GRCh37 17 41243581 41243581 0 Missense_Mutation SNP G G A rs80357262 TEST_SAMPLE_SOMATIC_HETEROZYGOUS TCGA-A1-A0SB-10 A G Unknown Somatic Phase_IV Capture 1 dbGAP IlluminaGAIIx 0 getma.org/?cm=var&var=hg19,17,41243581,G,A&fts=all ENST00000357654.3:c.3967C>T p.Ser694Ser p.S694S ENST00000357654 23-Oct 0 0 BRCA1,stop_gained,p.Gln1027Ter,ENST00000309486,NM_007297.3;BRCA1,stop_gained,p.Gln1323Ter,ENST00000357654,NM_007294.3;BRCA1,stop_gained,p.Gln1323Ter,ENST00000346315,;BRCA1,stop_gained,p.Gln1323Ter,ENST00000354071,;BRCA1,stop_gained,p.Gln1323Ter,ENST00000471181,NM_007300.3;BRCA1,stop_gained,p.Gln1276Ter,ENST00000493795,;BRCA1,stop_gained,p.Gln88Ter,ENST00000461574,;BRCA1,intron_variant,,ENST00000352993,;BRCA1,intron_variant,,ENST00000351666,;BRCA1,intron_variant,,ENST00000468300,NM_007299.3;BRCA1,intron_variant,,ENST00000491747,NM_007298.3;BRCA1,intron_variant,,ENST00000478531,;BRCA1,intron_variant,,ENST00000493919,;BRCA1,intron_variant,,ENST00000484087,;BRCA1,intron_variant,,ENST00000591534,;BRCA1,intron_variant,,ENST00000487825,;BRCA1,intron_variant,,ENST00000586385,;BRCA1,intron_variant,,ENST00000591849,;BRCA1,downstream_gene_variant,,ENST00000470026,;BRCA1,downstream_gene_variant,,ENST00000477152,;BRCA1,downstream_gene_variant,,ENST00000494123,;BRCA1,downstream_gene_variant,,ENST00000473961,;BRCA1,downstream_gene_variant,,ENST00000497488,;BRCA1,downstream_gene_variant,,ENST00000476777,;BRCA1,3_prime_UTR_variant,,ENST00000461221,;BRCA1,non_coding_transcript_exon_variant,,ENST00000467274,;BRCA1,downstream_gene_variant,,ENST00000492859,;BRCA1,downstream_gene_variant,,ENST00000412061,; A ENSG00000012048 ENST00000357654 Transcript stop_gained 4086/7094 3967/5592 1323 Q/* Caa/Taa rs80357262 1 BRCA1 HGNC 1100 protein_coding CCDS11453.1 ENSP00000350283 BRCA1_HUMAN Q9UE29_HUMAN,Q9NQR3_HUMAN,Q92897_HUMAN,Q7KYU6_HUMAN,Q4EW25_HUMAN,Q3YB53_HUMAN,Q3YB50_HUMAN,Q3YB49_HUMAN,Q3LRH8_HUMAN,Q3B891_HUMAN,K7EPC7_HUMAN,K4K7V3_HUMAN,K4JXS7_HUMAN,K4JUB1_HUMAN,G4V503_HUMAN,G4V502_HUMAN,G4V500_HUMAN,G4V4Z8_HUMAN,G4V4Z7_HUMAN,G1UI37_HUMAN,E9PFZ0_HUMAN,E7EWN5_HUMAN,E7EP70_HUMAN,C9IZW4_HUMAN,C4PFY7_HUMAN UPI0000126AC8 NM_007294.3 23-Oct PIRSF_domain:PIRSF001734,hmmpanther:PTHR13763,hmmpanther:PTHR13763:SF0 not_provided,pathogenic HIGH SNV 1 17 41243581 41243581 G A SNP BRCA1 NM_007294.3 human genbank 58_37c -1 reviewed nonsense c.3967 p.Q1323* 0.949 HMMPfam_BRCT|7CHMMSmart_SM00292|7Csuperfamily_BRCT domain|7CHMMSmart_SM00184|7CPatternScan_ZF_RING_1|7CHMMPfam_zf-C3HC4|7Csuperfamily_RING/U-box - 17 41243581 41243581 G A SNP BRCA1 NM_007294.3 human genbank 58_37c -1 reviewed nonsense c.3967 p.Q1323* 0.949 HMMPfam_BRCT|7CHMMSmart_SM00292|7Csuperfamily_BRCT domain|7CHMMSmart_SM00184|7CPatternScan_ZF_RING_1|7CHMMPfam_zf-C3HC4|7Csuperfamily_RING/U-box - Putative_Passenger Test passenger Class 1 Class annotation Heterozygous 1 BRCA1 genome.wustl.edu GRCh37 17 41243581 41243581 0 Missense_Mutation SNP G G A rs80357262 TEST_SAMPLE_SOMATIC_UNDEFINED TCGA-A1-A0SB-10 A G Unknown Somatic Phase_IV Capture 1 dbGAP IlluminaGAIIx 0 getma.org/?cm=var&var=hg19,17,41243581,G,A&fts=all ENST00000357654.3:c.3967C>T p.Pro871Gln p.P871Q ENST00000357654 23-Oct 0 0 BRCA1,stop_gained,p.Gln1027Ter,ENST00000309486,NM_007297.3;BRCA1,stop_gained,p.Gln1323Ter,ENST00000357654,NM_007294.3;BRCA1,stop_gained,p.Gln1323Ter,ENST00000346315,;BRCA1,stop_gained,p.Gln1323Ter,ENST00000354071,;BRCA1,stop_gained,p.Gln1323Ter,ENST00000471181,NM_007300.3;BRCA1,stop_gained,p.Gln1276Ter,ENST00000493795,;BRCA1,stop_gained,p.Gln88Ter,ENST00000461574,;BRCA1,intron_variant,,ENST00000352993,;BRCA1,intron_variant,,ENST00000351666,;BRCA1,intron_variant,,ENST00000468300,NM_007299.3;BRCA1,intron_variant,,ENST00000491747,NM_007298.3;BRCA1,intron_variant,,ENST00000478531,;BRCA1,intron_variant,,ENST00000493919,;BRCA1,intron_variant,,ENST00000484087,;BRCA1,intron_variant,,ENST00000591534,;BRCA1,intron_variant,,ENST00000487825,;BRCA1,intron_variant,,ENST00000586385,;BRCA1,intron_variant,,ENST00000591849,;BRCA1,downstream_gene_variant,,ENST00000470026,;BRCA1,downstream_gene_variant,,ENST00000477152,;BRCA1,downstream_gene_variant,,ENST00000494123,;BRCA1,downstream_gene_variant,,ENST00000473961,;BRCA1,downstream_gene_variant,,ENST00000497488,;BRCA1,downstream_gene_variant,,ENST00000476777,;BRCA1,3_prime_UTR_variant,,ENST00000461221,;BRCA1,non_coding_transcript_exon_variant,,ENST00000467274,;BRCA1,downstream_gene_variant,,ENST00000492859,;BRCA1,downstream_gene_variant,,ENST00000412061,; A ENSG00000012048 ENST00000357654 Transcript stop_gained 4086/7094 3967/5592 1323 Q/* Caa/Taa rs80357262 1 BRCA1 HGNC 1100 protein_coding CCDS11453.1 ENSP00000350283 BRCA1_HUMAN Q9UE29_HUMAN,Q9NQR3_HUMAN,Q92897_HUMAN,Q7KYU6_HUMAN,Q4EW25_HUMAN,Q3YB53_HUMAN,Q3YB50_HUMAN,Q3YB49_HUMAN,Q3LRH8_HUMAN,Q3B891_HUMAN,K7EPC7_HUMAN,K4K7V3_HUMAN,K4JXS7_HUMAN,K4JUB1_HUMAN,G4V503_HUMAN,G4V502_HUMAN,G4V500_HUMAN,G4V4Z8_HUMAN,G4V4Z7_HUMAN,G1UI37_HUMAN,E9PFZ0_HUMAN,E7EWN5_HUMAN,E7EP70_HUMAN,C9IZW4_HUMAN,C4PFY7_HUMAN UPI0000126AC8 NM_007294.3 23-Oct PIRSF_domain:PIRSF001734,hmmpanther:PTHR13763,hmmpanther:PTHR13763:SF0 not_provided,pathogenic HIGH SNV 1 17 41243581 41243581 G A SNP BRCA1 NM_007294.3 human genbank 58_37c -1 reviewed nonsense c.3967 p.Q1323* 0.949 HMMPfam_BRCT|7CHMMSmart_SM00292|7Csuperfamily_BRCT domain|7CHMMSmart_SM00184|7CPatternScan_ZF_RING_1|7CHMMPfam_zf-C3HC4|7Csuperfamily_RING/U-box - 17 41243581 41243581 G A SNP BRCA1 NM_007294.3 human genbank 58_37c -1 reviewed nonsense c.3967 p.Q1323* 0.949 HMMPfam_BRCT|7CHMMSmart_SM00292|7Csuperfamily_BRCT domain|7CHMMSmart_SM00184|7CPatternScan_ZF_RING_1|7CHMMPfam_zf-C3HC4|7Csuperfamily_RING/U-box - Putative_Driver Test driver Class 1 Class annotation BRCA1 genome.wustl.edu GRCh37 17 41201181 41201181 0 Missense_Mutation SNP C C A rs80357069 byCluster TCGA-A1-A0SB-01 TCGA-A1-A0SB-10 C C Unknown Somatic Phase_IV Capture 1 dbGAP Illumina GAIIx medium 2.25 getma.org/?cm=msa&ty=f&p=BRCA1_HUMAN&rb=1756&re=1842&var=G1788V getma.org/pdb.php?prot=BRCA1_HUMAN&from=1756&to=1842&var=G1788V getma.org/?cm=var&var=hg19,17,41201181,C,A&fts=all ENST00000357654.3:c.5363G>T p.Gly1788Val p.G1788V ENST00000357654 21/23 0 0 BRCA1,missense_variant,p.Gly1492Val,ENST00000309486,NM_007297.3;BRCA1,missense_variant,p.Gly1788Val,ENST00000357654,NM_007294.3;BRCA1,missense_variant,p.Gly1549Val,ENST00000346315,;BRCA1,missense_variant,p.Gly1523Val,ENST00000354071,;BRCA1,missense_variant,p.Gly1809Val,ENST00000471181,NM_007300.3;BRCA1,missense_variant,p.Gly1741Val,ENST00000493795,;BRCA1,missense_variant,p.Gly646Val,ENST00000352993,;BRCA1,missense_variant,p.Gly605Val,ENST00000351666,;BRCA1,missense_variant,p.Gly684Val,ENST00000491747,NM_007298.3;BRCA1,missense_variant,p.Gly279Val,ENST00000591534,;BRCA1,missense_variant,p.Gly98Val,ENST00000586385,;BRCA1,missense_variant,p.Gly21Val,ENST00000591849,;BRCA1,intron_variant,,ENST00000468300,NM_007299.3;BRCA1,3_prime_UTR_variant,,ENST00000461221,; A ENSG00000012048 ENST00000357654 Transcript missense_variant 5482/7094 5363/5592 1788 G/V gGt/gTt rs80357069,COSM436662 1 BRCA1 HGNC 1100 protein_coding CCDS11453.1 ENSP00000350283 BRCA1_HUMAN Q9UE29_HUMAN,Q9NQR3_HUMAN,Q92897_HUMAN,Q7KYU6_HUMAN,Q4EW25_HUMAN,Q3YB53_HUMAN,Q3YB50_HUMAN,Q3YB49_HUMAN,Q3LRH8_HUMAN,Q3B891_HUMAN,K7EPC7_HUMAN,K4K7V3_HUMAN,K4JXS7_HUMAN,K4JUB1_HUMAN,G4V503_HUMAN,G4V502_HUMAN,G4V500_HUMAN,G4V4Z8_HUMAN,G4V4Z7_HUMAN,G1UI37_HUMAN,E9PFZ0_HUMAN,E7EWN5_HUMAN,E7EP70_HUMAN,C9IZW4_HUMAN,C4PFY7_HUMAN UPI0000126AC8 NM_007294.3 deleterious(0) benign(0.031) 21/23 Gene3D:3.40.50.10190,Pfam_domain:PF00533,PIRSF_domain:PIRSF001734,Prints_domain:PR00493,PROSITE_profiles:PS50172,hmmpanther:PTHR13763,hmmpanther:PTHR13763:SF0,SMART_domains:SM00292,Superfamily_domains:SSF52113 not_provided,pathogenic 0,1 MODERATE SNV 1,1 17 41201181 41201181 C A SNP BRCA1 NM_007294 human genbank 57_37b -1 reviewed missense c.5363 p.G1788V 1 HMMPfam_BRCT,HMMSmart_SM00292,superfamily_BRCT domain superfamily_RING/U-box,HMMSmart_SM00184,HMMPfam_zf-C3HC4,PatternScan_ZF_RING_1,HMMPfam_BRCT,HMMSmart_SM00292,superfamily_BRCT domain - 17 41201181 41201181 C A SNP BRCA1 NM_007294 human genbank 57_37b -1 reviewed missense c.5363 p.G1788V 1 HMMPfam_BRCT,HMMSmart_SM00292,superfamily_BRCT domain superfamily_RING/U-box,HMMSmart_SM00184,HMMPfam_zf-C3HC4,PatternScan_ZF_RING_1,HMMPfam_BRCT,HMMSmart_SM00292,superfamily_BRCT domain - -ATM genome.wustl.edu GRCh37 11 108173702 108173702 0 Frame_Shift_Del DEL G G - TCGA-A1-A0SB-01 TCGA-A1-A0SB-10 - G Unknown Germline Phase_IV Capture 1 dbGAP IlluminaGAIIx ENST00000278616.4:c.5443delG p.Asp1815ThrfsTer13 p.D1815Tfs*13 ENST00000278616 36/63 0 0 ATM,frameshift_variant,p.Asp1815ThrfsTer13,ENST00000278616,NM_000051.3;ATM,frameshift_variant,p.Asp1815ThrfsTer13,ENST00000452508,;ATM,non_coding_transcript_exon_variant,,ENST00000524792,;ATM,non_coding_transcript_exon_variant,,ENST00000533690,;ATM,non_coding_transcript_exon_variant,,ENST00000534625,;ATM,upstream_gene_variant,,ENST00000529588,; - ENSG00000149311 ENST00000278616 Transcript frameshift_variant 5827/13147 5442/9171 1814 L/X ttG/tt rs772138812 1 ATM HGNC 795 protein_coding YES CCDS31669.1 ENSP00000278616 ATM_HUMAN M0QXY8_HUMAN,E9PRG7_HUMAN,E9PIN0_HUMAN UPI0000DBEF44 NM_000051.3 36/63 hmmpanther:PTHR11139,hmmpanther:PTHR11139:SF66 HIGH 1 deletion 1 11 108173702 108173702 G - DEL ATM NM_000051.3 human genbank 58_37c 1 reviewed frame_shift_del c.5442 p.D1815fs 1 superfamily_ARM repeat superfamily_ARM repeat|7CHMMPfam_FAT|7Csuperfamily_Protein kinase-like (PK-like)|7CHMMPfam_PI3_PI4_kinase|7CHMMSmart_SM00146|7CPatternScan_PI3_4_KINASE_1|7CPatternScan_PI3_4_KINASE_2|7CHMMPfam_FATC - 11 108173702 108173702 G - DEL ATM NM_000051.3 human genbank 58_37c 1 reviewed frame_shift_del c.5442 p.D1815fs 1 superfamily_ARM repeat superfamily_ARM repeat|7CHMMPfam_FAT|7Csuperfamily_Protein kinase-like (PK-like)|7CHMMPfam_PI3_PI4_kinase|7CHMMSmart_SM00146|7CPatternScan_PI3_4_KINASE_1|7CPatternScan_PI3_4_KINASE_2|7CHMMPfam_FATC - +ATM genome.wustl.edu GRCh37 11 108173702 108173702 0 Frame_Shift_Del DEL G G - TCGA-A1-A0SB-01 TCGA-A1-A0SB-10 - G Unknown Somatic Phase_IV Capture 1 dbGAP IlluminaGAIIx ENST00000278616.4:c.5443delG p.Asp1815ThrfsTer13 p.D1815Tfs*13 ENST00000278616 36/63 0 0 ATM,frameshift_variant,p.Asp1815ThrfsTer13,ENST00000278616,NM_000051.3;ATM,frameshift_variant,p.Asp1815ThrfsTer13,ENST00000452508,;ATM,non_coding_transcript_exon_variant,,ENST00000524792,;ATM,non_coding_transcript_exon_variant,,ENST00000533690,;ATM,non_coding_transcript_exon_variant,,ENST00000534625,;ATM,upstream_gene_variant,,ENST00000529588,; - ENSG00000149311 ENST00000278616 Transcript frameshift_variant 5827/13147 5442/9171 1814 L/X ttG/tt rs772138812 1 ATM HGNC 795 protein_coding YES CCDS31669.1 ENSP00000278616 ATM_HUMAN M0QXY8_HUMAN,E9PRG7_HUMAN,E9PIN0_HUMAN UPI0000DBEF44 NM_000051.3 36/63 hmmpanther:PTHR11139,hmmpanther:PTHR11139:SF66 HIGH 1 deletion 1 11 108173702 108173702 G - DEL ATM NM_000051.3 human genbank 58_37c 1 reviewed frame_shift_del c.5442 p.D1815fs 1 superfamily_ARM repeat superfamily_ARM repeat|7CHMMPfam_FAT|7Csuperfamily_Protein kinase-like (PK-like)|7CHMMPfam_PI3_PI4_kinase|7CHMMSmart_SM00146|7CPatternScan_PI3_4_KINASE_1|7CPatternScan_PI3_4_KINASE_2|7CHMMPfam_FATC - 11 108173702 108173702 G - DEL ATM NM_000051.3 human genbank 58_37c 1 reviewed frame_shift_del c.5442 p.D1815fs 1 superfamily_ARM repeat superfamily_ARM repeat|7CHMMPfam_FAT|7Csuperfamily_Protein kinase-like (PK-like)|7CHMMPfam_PI3_PI4_kinase|7CHMMSmart_SM00146|7CPatternScan_PI3_4_KINASE_1|7CPatternScan_PI3_4_KINASE_2|7CHMMPfam_FATC - ATM genome.wustl.edu GRCh37 11 108106472 108106472 0 Frame_Shift_Del DEL T T - novel unknown TCGA-A1-A0SB-01 TCGA-A1-A0SB-10 T T Unknown Somatic Phase_IV Capture 1 dbGAP Illumina GAIIx ENST00000278616.4:c.409delT p.Tyr137ThrfsTer16 p.Y137Tfs*16 ENST00000278616 May-63 0 0 ATM,frameshift_variant,p.Tyr137ThrfsTer16,ENST00000278616,NM_000051.3;ATM,frameshift_variant,p.Tyr137ThrfsTer16,ENST00000452508,;ATM,frameshift_variant,p.Tyr137ThrfsTer16,ENST00000527805,;ATM,intron_variant,,ENST00000527891,;ATM,downstream_gene_variant,,ENST00000601453,;ATM,non_coding_transcript_exon_variant,,ENST00000530958,; - ENSG00000149311 ENST00000278616 Transcript frameshift_variant 792/13147 407/9171 136 I/X aTt/at COSM428356,COSM1474979 1 ATM HGNC 795 protein_coding YES CCDS31669.1 ENSP00000278616 ATM_HUMAN M0QXY8_HUMAN,E9PRG7_HUMAN,E9PIN0_HUMAN UPI0000DBEF44 NM_000051.3 May-63 Pfam_domain:PF11640,hmmpanther:PTHR11139,hmmpanther:PTHR11139:SF66 1,1 HIGH 1 deletion 2 1,1 11 108106472 108106472 T - DEL ATM NM_000051 human genbank 57_37b 1 reviewed frame_shift_del c.407 p.Y137fs 0.013 superfamily_ARM repeat,HMMPfam_FAT,superfamily_Protein kinase-like (PK-like),HMMPfam_PI3_PI4_kinase,HMMSmart_SM00146,PatternScan_PI3_4_KINASE_1,PatternScan_PI3_4_KINASE_2,HMMPfam_FATC (deletion:cds_exon[108106397,108106561]) 11 108106472 108106472 T - DEL ATM NM_000051 human genbank 57_37b 1 reviewed frame_shift_del c.407 p.Y137fs 0.013 superfamily_ARM repeat,HMMPfam_FAT,superfamily_Protein kinase-like (PK-like),HMMPfam_PI3_PI4_kinase,HMMSmart_SM00146,PatternScan_PI3_4_KINASE_1,PatternScan_PI3_4_KINASE_2,HMMPfam_FATC (deletion:cds_exon[108106397,108106561]) -BRCA2 genome.wustl.edu GRCh37 13 108106473 108106473 0 Nonsense_Mutation SNP T T C TCGA-A1-A0SB-01 TCGA-A1-A0SB-10 Germline p.D191G BRCA2_HUMAN +BRCA2 genome.wustl.edu GRCh37 13 108106473 108106473 0 Nonsense_Mutation SNP T T C TCGA-A1-A0SB-01 TCGA-A1-A0SB-10 Somatic p.D191G BRCA2_HUMAN BRCA2 genome.wustl.edu GRCh37 13 108106474 108106474 0 Nonsense_Mutation SNP T T C TCGA-A2-A04P-01 TCGA-A2-A04P-10 Somatic p.D191G BRCA2_HUMAN -BRCA2 genome.wustl.edu GRCh37 13 108106475 108106475 0 In_Frame_Del DEL T T - TCGA-A1-A0SK-01 TCGA-A1-A0SK-10 Germline p.R2659T BRCA2_HUMAN +BRCA2 genome.wustl.edu GRCh37 13 108106475 108106475 0 In_Frame_Del DEL T T - TCGA-A1-A0SK-01 TCGA-A1-A0SK-10 Somatic p.R2659T BRCA2_HUMAN BRCA2 genome.wustl.edu GRCh37 13 108106476 108106476 0 In_Frame_Del DEL T T - TCGA-A2-A0CM-01 TCGA-A2-A0CM-10 Somatic p.R2659T BRCA2_HUMAN -BRCA2 genome.wustl.edu GRCh37 13 108106477 108106477 0 Missense_Mutation SNP T T C TCGA-AR-A1AR-01 TCGA-AR-A1AR-10 Germline p.R2336C BRCA2_HUMAN +BRCA2 genome.wustl.edu GRCh37 13 108106477 108106477 0 Missense_Mutation SNP T T C TCGA-AR-A1AR-01 TCGA-AR-A1AR-10 Somatic p.R2336C BRCA2_HUMAN BRCA2 genome.wustl.edu GRCh37 13 108106478 108106478 0 Missense_Mutation SNP T T C TCGA-B6-A0WX-01 TCGA-B6-A0WX-10 Somatic p.R2336C BRCA2_HUMAN -BRCA2 genome.wustl.edu GRCh37 13 108106479 108106479 0 Nonsense_Mutation SNP T T C TCGA-BH-A1F0-01 TCGA-BH-A1F0-10 Germline p.R2000T BRCA2_HUMAN +BRCA2 genome.wustl.edu GRCh37 13 108106479 108106479 0 Nonsense_Mutation SNP T T C TCGA-BH-A1F0-01 TCGA-BH-A1F0-10 Somatic p.R2000T BRCA2_HUMAN BRCA2 genome.wustl.edu GRCh37 13 108106480 108106480 0 Nonsense_Mutation SNP T T C TCGA-B6-A0I6-01 TCGA-B6-A0I6-10 Somatic p.R2000T BRCA2_HUMAN -BRCA2 genome.wustl.edu GRCh37 13 108106481 108106481 0 In_Frame_Del DEL T T - TCGA-BH-A18V-01 TCGA-BH-A18V-10 Germline p.V1270del BRCA2_HUMAN +BRCA2 genome.wustl.edu GRCh37 13 108106481 108106481 0 In_Frame_Del DEL T T - TCGA-BH-A18V-01 TCGA-BH-A18V-10 Somatic p.V1270del BRCA2_HUMAN BRCA2 genome.wustl.edu GRCh37 13 108106482 108106482 0 In_Frame_Del DEL T T - TCGA-BH-A18K-01 TCGA-BH-A18K-10 Somatic p.V1270del BRCA2_HUMAN -BRCA2 genome.wustl.edu GRCh37 13 108106483 108106483 0 Missense_Mutation SNP T T C TCGA-BH-A0HL-01 TCGA-BH-A0HL-10 Germline p.D3073G BRCA2_HUMAN +BRCA2 genome.wustl.edu GRCh37 13 108106483 108106483 0 Missense_Mutation SNP T T C TCGA-BH-A0HL-01 TCGA-BH-A0HL-10 Somatic p.D3073G BRCA2_HUMAN BRCA2 genome.wustl.edu GRCh37 13 108106484 108106484 0 Missense_Mutation SNP T T C TCGA-BH-A0E0-01 TCGA-BH-A0E0-10 Somatic p.D3073G BRCA2_HUMAN ACP3 genome.wustl.edu GRCh37 3 132047117 132047117 0 Missense_Mutation SNP C C T TEST_SAMPLE_1 Somatic NA NA NA NA NA NA NA NA NA NA NA NA NA NA ENST00000336375.5:c.127C>T p.Arg43Trp p.R43W ENST00000336375 NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA PPAP_HUMAN NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA ACP3 genome.wustl.edu GRCh37 3 132047117 132047117 0 Missense_Mutation SNP C C T TEST_SAMPLE_2 Somatic NA NA NA NA NA NA NA NA NA NA NA NA NA NA ENST00000336375.5:c.127C>T p.Arg43Trp p.R43W ENST00000336375 NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA PPAP_HUMAN NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA diff --git a/test/test_data/study_oncokb_import/data_mutations_extended.maf b/test/test_data/study_oncokb_import/data_mutations_extended.maf index 45202410217..29eec08371d 100644 --- a/test/test_data/study_oncokb_import/data_mutations_extended.maf +++ b/test/test_data/study_oncokb_import/data_mutations_extended.maf @@ -13,23 +13,23 @@ NPIPB15 genome.wustl.edu GRCh37 16 74425902 74425902 1 Missense_Mutation SNP T OTOR genome.wustl.edu GRCh37 20 16730581 16730581 1 Missense_Mutation SNP G G A TCGA-A1-A0SB-01 TCGA-A1-A0SB-10 G G Unknown Untested Somatic Phase_IV WXS none 1 dbGAP Illumina GAIIx medium 2.69 V97M getma.org/?cm=msa&ty=f&p=OTOR_HUMAN&rb=43&re=108&var=V97M getma.org/pdb.php?prot=OTOR_HUMAN&from=43&to=108&var=V97M getma.org/?cm=var&var=hg19,20,16730581,G,A&fts=all db9d40fb-bfce-4c3b-a6c2-41c5c88982f1 a3254f8e-3bbd-42fc-abea-a5f25b7648b3 c.289G>A p.Val97Met p.V97M ENST00000246081 3/4 0 0 OTOR,missense_variant,p.Val97Met,ENST00000246081,NM_020157.3;OTOR,non_coding_transcript_exon_variant,,ENST00000486129,;OTOR,intron_variant,,ENST00000490148,; A ENSG00000125879 ENST00000246081 Transcript missense_variant 333/1477 289/387 97/128 V/M Gtg/Atg COSM1410526 1 OTOR HGNC 8517 protein_coding YES CCDS13124.1 ENSP00000246081 OTOR_HUMAN UPI0000047809 NM_020157.3 deleterious(0) benign(0.344) 3/4 hmmpanther:PTHR23158,Gene3D:2.30.30.40,Pfam_domain:PF07653,SMART_domains:SM00326,Superfamily_domains:SSF50044 1 MODERATE 1 SNV 1 20 16730581 16730581 G A SNP OTOR ENST00000246081 human ensembl 69_37n 1 known missense c.289 p.V97M 963 pfam_SH3_2,superfamily_SH3_domain,smart_SH3_domain pfam_SH3_2,superfamily_SH3_domain,smart_SH3_domain - no_errors OTOR HGNC ENSG00000125879 57 0 0 36 9 20 - - - 20 16730581 16730581 G A SNP OTOR ENST00000246081 human ensembl 69_37n 1 known missense c.289 p.V97M 963 pfam_SH3_2,superfamily_SH3_domain,smart_SH3_domain pfam_SH3_2,superfamily_SH3_domain,smart_SH3_domain - no_errors OTOR HGNC - - - P2RY10 genome.wustl.edu GRCh37 X 78216689 78216689 1 Silent SNP C C T TCGA-A1-A0SB-01 TCGA-A1-A0SB-10 C C Unknown Untested Somatic Phase_IV WXS none 1 dbGAP Illumina GAIIx db9d40fb-bfce-4c3b-a6c2-41c5c88982f1 a3254f8e-3bbd-42fc-abea-a5f25b7648b3 c.672C>T p.= p.S224S ENST00000171757 4/4 0 0 P2RY10,synonymous_variant,p.=,ENST00000171757,NM_014499.2;P2RY10,synonymous_variant,p.=,ENST00000544091,NM_198333.1;P2RY10,downstream_gene_variant,,ENST00000475374,;P2RY10,downstream_gene_variant,,ENST00000461541,; T ENSG00000078589 ENST00000171757 Transcript synonymous_variant 952/1714 672/1020 224/339 S tcC/tcT COSM1491292 1 P2RY10 HGNC 19906 protein_coding YES CCDS14442.1 ENSP00000171757 P2Y10_HUMAN UPI0000050471 NM_014499.2 4/4 PROSITE_profiles:PS50262,hmmpanther:PTHR24232:SF6,hmmpanther:PTHR24232,Gene3D:1.20.1070.10,Pfam_domain:PF00001,Superfamily_domains:SSF81321 1 LOW 1 SNV 1 X 78216689 78216689 C T SNP P2RY10 ENST00000171757 human ensembl 69_37n 1 known silent c.672 p.S224 92 pfam_7TM_GPCR_Rhodpsn,pfscan_GPCR_Rhodpsn_supfam pfam_7TM_GPCR_Rhodpsn,pfscan_GPCR_Rhodpsn_supfam,prints_7TM_GPCR_Rhodpsn,prints_P2_purnocptor - no_errors P2RY10 HGNC ENSG00000078589 65 0 0 46 10 17.86 - - - X 78216689 78216689 C T SNP P2RY10 ENST00000171757 human ensembl 69_37n 1 known silent c.672 p.S224 92 pfam_7TM_GPCR_Rhodpsn,pfscan_GPCR_Rhodpsn_supfam pfam_7TM_GPCR_Rhodpsn,pfscan_GPCR_Rhodpsn_supfam,prints_7TM_GPCR_Rhodpsn,prints_P2_purnocptor - no_errors P2RY10 HGNC - - - PIEZO1 genome.wustl.edu GRCh37 16 88790292 88790292 -1 Missense_Mutation SNP T T C TCGA-A1-A0SB-01 TCGA-A1-A0SB-10 T T Unknown Untested Somatic Phase_IV WXS none 1 dbGAP Illumina GAIIx low 1.18 Q1441R getma.org/?cm=msa&ty=f&p=PIEZ1_HUMAN&rb=58&re=1627&var=Q1441R getma.org/?cm=var&var=hg19,16,88790292,T,C&fts=all db9d40fb-bfce-4c3b-a6c2-41c5c88982f1 a3254f8e-3bbd-42fc-abea-a5f25b7648b3 c.4322A>G p.Gln1441Arg p.Q1441R ENST00000301015 31/51 0 0 PIEZO1,missense_variant,p.Gln1441Arg,ENST00000301015,NM_001142864.2;PIEZO1,missense_variant,p.Gln115Arg,ENST00000474606,;PIEZO1,upstream_gene_variant,,ENST00000327397,;PIEZO1,upstream_gene_variant,,ENST00000466823,;RP5-1142A6.9,downstream_gene_variant,,ENST00000564984,;PIEZO1,non_coding_transcript_exon_variant,,ENST00000566414,;PIEZO1,upstream_gene_variant,,ENST00000419505,;PIEZO1,upstream_gene_variant,,ENST00000497793,;PIEZO1,upstream_gene_variant,,ENST00000495568,;PIEZO1,downstream_gene_variant,,ENST00000475586,;PIEZO1,downstream_gene_variant,,ENST00000491917,; C ENSG00000103335 ENST00000301015 Transcript missense_variant 4569/8072 4322/7566 1441/2521 Q/R cAg/cGg COSM1479166 1 PIEZO1 HGNC 28993 protein_coding YES CCDS54058.1 ENSP00000301015 PIEZ1_HUMAN UPI0001B300F3 NM_001142864.2 tolerated(0.25) possibly_damaging(0.78) 31/51 hmmpanther:PTHR13167,hmmpanther:PTHR13167:SF40 1 MODERATE 1 SNV 1 16 88790292 88790292 T C SNP PIEZO1 ENST00000301015 human ensembl 69_37n -1 novel missense c.4322 p.Q1441R 1000 pfam_DUF3595 - no_errors PIEZO1 HGNC ENSG00000103335 37 0 0 20 8 28.57 - - - 16 88790292 88790292 T C SNP PIEZO1 ENST00000301015 human ensembl 69_37n -1 novel missense c.4322 p.Q1441R 1000 pfam_DUF3595 - no_errors PIEZO1 HGNC - - - -TP53 genome.wustl.edu GRCh37 17 7578253 7578253 0 Missense_Mutation SNP C C A TCGA-A1-A0SB-01 TCGA-A1-A0SB-10 A C Unknown Germline Phase_IV Capture 1 dbGAP IlluminaGAIIx medium 3.005 getma.org/?cm=msa&ty=f&p=P53_HUMAN&rb=95&re=289&var=G199V getma.org/pdb.php?prot=P53_HUMAN&from=95&to=289&var=G199V getma.org/?cm=var&var=hg19,17,7578253,C,A&fts=all ENST00000269305.4:c.596G>T p.Gly199Val p.G199V ENST00000269305 11-Jun 0 0 TP53,missense_variant,p.Gly199Val,ENST00000420246,NM_001126114.2,NM_001276696.1;TP53,missense_variant,p.Gly199Val,ENST00000455263,NM_001276695.1,NM_001126113.2;TP53,missense_variant,p.Gly199Val,ENST00000269305,NM_001126112.2,NM_001276761.1,NM_001276760.1,NM_000546.5,NM_001126118.1;TP53,missense_variant,p.Gly199Val,ENST00000445888,;TP53,missense_variant,p.Gly199Val,ENST00000359597,;TP53,missense_variant,p.Gly199Val,ENST00000413465,;TP53,missense_variant,p.Gly67Val,ENST00000509690,;TP53,missense_variant,p.Gly106Val,ENST00000514944,;TP53,downstream_gene_variant,,ENST00000508793,;TP53,downstream_gene_variant,,ENST00000604348,;TP53,downstream_gene_variant,,ENST00000503591,;TP53,upstream_gene_variant,,ENST00000576024,;TP53,intron_variant,,ENST00000574684,;TP53,non_coding_transcript_exon_variant,,ENST00000510385,;TP53,non_coding_transcript_exon_variant,,ENST00000504290,;TP53,non_coding_transcript_exon_variant,,ENST00000504937,;TP53,non_coding_transcript_exon_variant,,ENST00000505014,; A ENSG00000141510 ENST00000269305 Transcript missense_variant 786/2579 596/1182 199 G/V gGa/gTa TP53_g.12665G>T,COSM44140,COSM255788,COSM255787,COSM255789,COSM3675525,COSM3675524,COSM255790 1 TP53 HGNC 11998 protein_coding YES CCDS11118.1 ENSP00000269305 P53_HUMAN S5LQU8_HUMAN,Q761V2_HUMAN,Q6IT77_HUMAN,Q1HGV1_HUMAN,Q0PKT5_HUMAN,L0ES54_HUMAN,L0EQ05_HUMAN,K7PPA8_HUMAN,H2EHT1_HUMAN,G4Y083_HUMAN,E9PCY9_HUMAN,E7ESS1_HUMAN,E7EMR6_HUMAN,B5AKF6_HUMAN,B4DNI2_HUMAN,A4GWD0_HUMAN,A4GWB8_HUMAN,A4GWB5_HUMAN,A4GW97_HUMAN,A4GW76_HUMAN,A4GW75_HUMAN,A4GW74_HUMAN,A4GW67_HUMAN,A2I9Z1_HUMAN,A2I9Z0_HUMAN UPI000002ED67 NM_001126112.2 deleterious(0) probably_damaging(1) 11-Jun Gene3D:2.60.40.720,Pfam_domain:PF00870,hmmpanther:PTHR11447,hmmpanther:PTHR11447:SF6,Superfamily_domains:SSF49417 0,1,1,1,1,1,1,1 MODERATE 1 SNV 0,1,1,1,1,1,1,1 17 7578253 7578253 C A SNP TP53 NM_000546.4 human genbank 58_37c -1 reviewed missense c.596 p.G199V 1 HMMPfam_P53|7Csuperfamily_p53-like transcription factors HMMPfam_P53_TAD|7CHMMPfam_P53|7Csuperfamily_p53-like transcription factors|7CPatternScan_P53|7CHMMPfam_P53_tetramer|7Csuperfamily_p53 tetramerization domain - 17 7578253 7578253 C A SNP TP53 NM_000546.4 human genbank 58_37c -1 reviewed missense c.596 p.G199V 1 HMMPfam_P53|7Csuperfamily_p53-like transcription factors HMMPfam_P53_TAD|7CHMMPfam_P53|7Csuperfamily_p53-like transcription factors|7CPatternScan_P53|7CHMMPfam_P53_tetramer|7Csuperfamily_p53 tetramerization domain - +TP53 genome.wustl.edu GRCh37 17 7578253 7578253 0 Missense_Mutation SNP C C A TCGA-A1-A0SB-01 TCGA-A1-A0SB-10 A C Unknown Somatic Phase_IV Capture 1 dbGAP IlluminaGAIIx medium 3.005 getma.org/?cm=msa&ty=f&p=P53_HUMAN&rb=95&re=289&var=G199V getma.org/pdb.php?prot=P53_HUMAN&from=95&to=289&var=G199V getma.org/?cm=var&var=hg19,17,7578253,C,A&fts=all ENST00000269305.4:c.596G>T p.Gly199Val p.G199V ENST00000269305 11-Jun 0 0 TP53,missense_variant,p.Gly199Val,ENST00000420246,NM_001126114.2,NM_001276696.1;TP53,missense_variant,p.Gly199Val,ENST00000455263,NM_001276695.1,NM_001126113.2;TP53,missense_variant,p.Gly199Val,ENST00000269305,NM_001126112.2,NM_001276761.1,NM_001276760.1,NM_000546.5,NM_001126118.1;TP53,missense_variant,p.Gly199Val,ENST00000445888,;TP53,missense_variant,p.Gly199Val,ENST00000359597,;TP53,missense_variant,p.Gly199Val,ENST00000413465,;TP53,missense_variant,p.Gly67Val,ENST00000509690,;TP53,missense_variant,p.Gly106Val,ENST00000514944,;TP53,downstream_gene_variant,,ENST00000508793,;TP53,downstream_gene_variant,,ENST00000604348,;TP53,downstream_gene_variant,,ENST00000503591,;TP53,upstream_gene_variant,,ENST00000576024,;TP53,intron_variant,,ENST00000574684,;TP53,non_coding_transcript_exon_variant,,ENST00000510385,;TP53,non_coding_transcript_exon_variant,,ENST00000504290,;TP53,non_coding_transcript_exon_variant,,ENST00000504937,;TP53,non_coding_transcript_exon_variant,,ENST00000505014,; A ENSG00000141510 ENST00000269305 Transcript missense_variant 786/2579 596/1182 199 G/V gGa/gTa TP53_g.12665G>T,COSM44140,COSM255788,COSM255787,COSM255789,COSM3675525,COSM3675524,COSM255790 1 TP53 HGNC 11998 protein_coding YES CCDS11118.1 ENSP00000269305 P53_HUMAN S5LQU8_HUMAN,Q761V2_HUMAN,Q6IT77_HUMAN,Q1HGV1_HUMAN,Q0PKT5_HUMAN,L0ES54_HUMAN,L0EQ05_HUMAN,K7PPA8_HUMAN,H2EHT1_HUMAN,G4Y083_HUMAN,E9PCY9_HUMAN,E7ESS1_HUMAN,E7EMR6_HUMAN,B5AKF6_HUMAN,B4DNI2_HUMAN,A4GWD0_HUMAN,A4GWB8_HUMAN,A4GWB5_HUMAN,A4GW97_HUMAN,A4GW76_HUMAN,A4GW75_HUMAN,A4GW74_HUMAN,A4GW67_HUMAN,A2I9Z1_HUMAN,A2I9Z0_HUMAN UPI000002ED67 NM_001126112.2 deleterious(0) probably_damaging(1) 11-Jun Gene3D:2.60.40.720,Pfam_domain:PF00870,hmmpanther:PTHR11447,hmmpanther:PTHR11447:SF6,Superfamily_domains:SSF49417 0,1,1,1,1,1,1,1 MODERATE 1 SNV 0,1,1,1,1,1,1,1 17 7578253 7578253 C A SNP TP53 NM_000546.4 human genbank 58_37c -1 reviewed missense c.596 p.G199V 1 HMMPfam_P53|7Csuperfamily_p53-like transcription factors HMMPfam_P53_TAD|7CHMMPfam_P53|7Csuperfamily_p53-like transcription factors|7CPatternScan_P53|7CHMMPfam_P53_tetramer|7Csuperfamily_p53 tetramerization domain - 17 7578253 7578253 C A SNP TP53 NM_000546.4 human genbank 58_37c -1 reviewed missense c.596 p.G199V 1 HMMPfam_P53|7Csuperfamily_p53-like transcription factors HMMPfam_P53_TAD|7CHMMPfam_P53|7Csuperfamily_p53-like transcription factors|7CPatternScan_P53|7CHMMPfam_P53_tetramer|7Csuperfamily_p53 tetramerization domain - TP53 genome.wustl.edu GRCh37 17 7576851 7576851 0 Splice_Site SNP A A C novel unknown TCGA-A1-A0SB-01 TCGA-A1-A0SB-10 A A Unknown Somatic Phase_IV Capture 1 dbGAP Illumina GAIIx ENST00000269305.4:c.993+2T>G p.X331_splice ENST00000269305 0 0 TP53,splice_donor_variant,,ENST00000420246,NM_001126114.2,NM_001276696.1;TP53,splice_donor_variant,,ENST00000455263,NM_001276695.1,NM_001126113.2;TP53,splice_donor_variant,,ENST00000269305,NM_001126112.2,NM_001276761.1,NM_001276760.1,NM_000546.5,NM_001126118.1;TP53,splice_donor_variant,,ENST00000445888,;TP53,splice_donor_variant,,ENST00000359597,;TP53,splice_donor_variant,,ENST00000576024,;TP53,intron_variant,,ENST00000413465,;TP53,downstream_gene_variant,,ENST00000509690,;TP53,downstream_gene_variant,,ENST00000508793,;TP53,downstream_gene_variant,,ENST00000604348,;TP53,downstream_gene_variant,,ENST00000503591,;TP53,downstream_gene_variant,,ENST00000514944,;TP53,downstream_gene_variant,,ENST00000574684,;TP53,splice_donor_variant,,ENST00000510385,;TP53,splice_donor_variant,,ENST00000504290,;TP53,splice_donor_variant,,ENST00000504937,;TP53,downstream_gene_variant,,ENST00000505014,; C ENSG00000141510 ENST00000269305 Transcript splice_donor_variant -/2579 993/1182 TP53_g.14067T>G,COSM29774,COSM146229 1 TP53 HGNC 11998 protein_coding YES CCDS11118.1 ENSP00000269305 P53_HUMAN S5LQU8_HUMAN,Q761V2_HUMAN,Q6IT77_HUMAN,Q1HGV1_HUMAN,Q0PKT5_HUMAN,L0ES54_HUMAN,L0EQ05_HUMAN,K7PPA8_HUMAN,H2EHT1_HUMAN,G4Y083_HUMAN,E9PCY9_HUMAN,E7ESS1_HUMAN,E7EMR6_HUMAN,B5AKF6_HUMAN,B4DNI2_HUMAN,A4GWD0_HUMAN,A4GWB8_HUMAN,A4GWB5_HUMAN,A4GW97_HUMAN,A4GW76_HUMAN,A4GW75_HUMAN,A4GW74_HUMAN,A4GW67_HUMAN,A2I9Z1_HUMAN,A2I9Z0_HUMAN UPI000002ED67 NM_001126112.2 10-Sep 0,1,1 HIGH 1 SNV 0,1,1 17 7576851 7576851 A C SNP TP53 NM_000546 human genbank 57_37b -1 reviewed splice_site c.993+2 e8+2 1 - - - 17 7576851 7576851 A C SNP TP53 NM_000546 human genbank 57_37b -1 reviewed splice_site c.993+2 e8+2 1 - - - -BRCA1 genome.wustl.edu GRCh37 17 41243581 41243581 0 Nonsense_Mutation SNP G G A rs80357262 TCGA-A1-A0SB-01 TCGA-A1-A0SB-10 A G Unknown Germline Phase_IV Capture 1 dbGAP IlluminaGAIIx 0 getma.org/?cm=var&var=hg19,17,41243581,G,A&fts=all ENST00000357654.3:c.3967C>T p.Gln1323Ter p.Q1323* ENST00000357654 23-Oct 0 0 BRCA1,stop_gained,p.Gln1027Ter,ENST00000309486,NM_007297.3;BRCA1,stop_gained,p.Gln1323Ter,ENST00000357654,NM_007294.3;BRCA1,stop_gained,p.Gln1323Ter,ENST00000346315,;BRCA1,stop_gained,p.Gln1323Ter,ENST00000354071,;BRCA1,stop_gained,p.Gln1323Ter,ENST00000471181,NM_007300.3;BRCA1,stop_gained,p.Gln1276Ter,ENST00000493795,;BRCA1,stop_gained,p.Gln88Ter,ENST00000461574,;BRCA1,intron_variant,,ENST00000352993,;BRCA1,intron_variant,,ENST00000351666,;BRCA1,intron_variant,,ENST00000468300,NM_007299.3;BRCA1,intron_variant,,ENST00000491747,NM_007298.3;BRCA1,intron_variant,,ENST00000478531,;BRCA1,intron_variant,,ENST00000493919,;BRCA1,intron_variant,,ENST00000484087,;BRCA1,intron_variant,,ENST00000591534,;BRCA1,intron_variant,,ENST00000487825,;BRCA1,intron_variant,,ENST00000586385,;BRCA1,intron_variant,,ENST00000591849,;BRCA1,downstream_gene_variant,,ENST00000470026,;BRCA1,downstream_gene_variant,,ENST00000477152,;BRCA1,downstream_gene_variant,,ENST00000494123,;BRCA1,downstream_gene_variant,,ENST00000473961,;BRCA1,downstream_gene_variant,,ENST00000497488,;BRCA1,downstream_gene_variant,,ENST00000476777,;BRCA1,3_prime_UTR_variant,,ENST00000461221,;BRCA1,non_coding_transcript_exon_variant,,ENST00000467274,;BRCA1,downstream_gene_variant,,ENST00000492859,;BRCA1,downstream_gene_variant,,ENST00000412061,; A ENSG00000012048 ENST00000357654 Transcript stop_gained 4086/7094 3967/5592 1323 Q/* Caa/Taa rs80357262 1 BRCA1 HGNC 1100 protein_coding CCDS11453.1 ENSP00000350283 BRCA1_HUMAN Q9UE29_HUMAN,Q9NQR3_HUMAN,Q92897_HUMAN,Q7KYU6_HUMAN,Q4EW25_HUMAN,Q3YB53_HUMAN,Q3YB50_HUMAN,Q3YB49_HUMAN,Q3LRH8_HUMAN,Q3B891_HUMAN,K7EPC7_HUMAN,K4K7V3_HUMAN,K4JXS7_HUMAN,K4JUB1_HUMAN,G4V503_HUMAN,G4V502_HUMAN,G4V500_HUMAN,G4V4Z8_HUMAN,G4V4Z7_HUMAN,G1UI37_HUMAN,E9PFZ0_HUMAN,E7EWN5_HUMAN,E7EP70_HUMAN,C9IZW4_HUMAN,C4PFY7_HUMAN UPI0000126AC8 NM_007294.3 23-Oct PIRSF_domain:PIRSF001734,hmmpanther:PTHR13763,hmmpanther:PTHR13763:SF0 not_provided,pathogenic HIGH SNV 1 17 41243581 41243581 G A SNP BRCA1 NM_007294.3 human genbank 58_37c -1 reviewed nonsense c.3967 p.Q1323* 0.949 HMMPfam_BRCT|7CHMMSmart_SM00292|7Csuperfamily_BRCT domain|7CHMMSmart_SM00184|7CPatternScan_ZF_RING_1|7CHMMPfam_zf-C3HC4|7Csuperfamily_RING/U-box - 17 41243581 41243581 G A SNP BRCA1 NM_007294.3 human genbank 58_37c -1 reviewed nonsense c.3967 p.Q1323* 0.949 HMMPfam_BRCT|7CHMMSmart_SM00292|7Csuperfamily_BRCT domain|7CHMMSmart_SM00184|7CPatternScan_ZF_RING_1|7CHMMPfam_zf-C3HC4|7Csuperfamily_RING/U-box - +BRCA1 genome.wustl.edu GRCh37 17 41243581 41243581 0 Nonsense_Mutation SNP G G A rs80357262 TCGA-A1-A0SB-01 TCGA-A1-A0SB-10 A G Unknown Somatic Phase_IV Capture 1 dbGAP IlluminaGAIIx 0 getma.org/?cm=var&var=hg19,17,41243581,G,A&fts=all ENST00000357654.3:c.3967C>T p.Gln1323Ter p.Q1323* ENST00000357654 23-Oct 0 0 BRCA1,stop_gained,p.Gln1027Ter,ENST00000309486,NM_007297.3;BRCA1,stop_gained,p.Gln1323Ter,ENST00000357654,NM_007294.3;BRCA1,stop_gained,p.Gln1323Ter,ENST00000346315,;BRCA1,stop_gained,p.Gln1323Ter,ENST00000354071,;BRCA1,stop_gained,p.Gln1323Ter,ENST00000471181,NM_007300.3;BRCA1,stop_gained,p.Gln1276Ter,ENST00000493795,;BRCA1,stop_gained,p.Gln88Ter,ENST00000461574,;BRCA1,intron_variant,,ENST00000352993,;BRCA1,intron_variant,,ENST00000351666,;BRCA1,intron_variant,,ENST00000468300,NM_007299.3;BRCA1,intron_variant,,ENST00000491747,NM_007298.3;BRCA1,intron_variant,,ENST00000478531,;BRCA1,intron_variant,,ENST00000493919,;BRCA1,intron_variant,,ENST00000484087,;BRCA1,intron_variant,,ENST00000591534,;BRCA1,intron_variant,,ENST00000487825,;BRCA1,intron_variant,,ENST00000586385,;BRCA1,intron_variant,,ENST00000591849,;BRCA1,downstream_gene_variant,,ENST00000470026,;BRCA1,downstream_gene_variant,,ENST00000477152,;BRCA1,downstream_gene_variant,,ENST00000494123,;BRCA1,downstream_gene_variant,,ENST00000473961,;BRCA1,downstream_gene_variant,,ENST00000497488,;BRCA1,downstream_gene_variant,,ENST00000476777,;BRCA1,3_prime_UTR_variant,,ENST00000461221,;BRCA1,non_coding_transcript_exon_variant,,ENST00000467274,;BRCA1,downstream_gene_variant,,ENST00000492859,;BRCA1,downstream_gene_variant,,ENST00000412061,; A ENSG00000012048 ENST00000357654 Transcript stop_gained 4086/7094 3967/5592 1323 Q/* Caa/Taa rs80357262 1 BRCA1 HGNC 1100 protein_coding CCDS11453.1 ENSP00000350283 BRCA1_HUMAN Q9UE29_HUMAN,Q9NQR3_HUMAN,Q92897_HUMAN,Q7KYU6_HUMAN,Q4EW25_HUMAN,Q3YB53_HUMAN,Q3YB50_HUMAN,Q3YB49_HUMAN,Q3LRH8_HUMAN,Q3B891_HUMAN,K7EPC7_HUMAN,K4K7V3_HUMAN,K4JXS7_HUMAN,K4JUB1_HUMAN,G4V503_HUMAN,G4V502_HUMAN,G4V500_HUMAN,G4V4Z8_HUMAN,G4V4Z7_HUMAN,G1UI37_HUMAN,E9PFZ0_HUMAN,E7EWN5_HUMAN,E7EP70_HUMAN,C9IZW4_HUMAN,C4PFY7_HUMAN UPI0000126AC8 NM_007294.3 23-Oct PIRSF_domain:PIRSF001734,hmmpanther:PTHR13763,hmmpanther:PTHR13763:SF0 not_provided,pathogenic HIGH SNV 1 17 41243581 41243581 G A SNP BRCA1 NM_007294.3 human genbank 58_37c -1 reviewed nonsense c.3967 p.Q1323* 0.949 HMMPfam_BRCT|7CHMMSmart_SM00292|7Csuperfamily_BRCT domain|7CHMMSmart_SM00184|7CPatternScan_ZF_RING_1|7CHMMPfam_zf-C3HC4|7Csuperfamily_RING/U-box - 17 41243581 41243581 G A SNP BRCA1 NM_007294.3 human genbank 58_37c -1 reviewed nonsense c.3967 p.Q1323* 0.949 HMMPfam_BRCT|7CHMMSmart_SM00292|7Csuperfamily_BRCT domain|7CHMMSmart_SM00184|7CPatternScan_ZF_RING_1|7CHMMPfam_zf-C3HC4|7Csuperfamily_RING/U-box - BRCA1 genome.wustl.edu GRCh37 17 41201181 41201181 0 Missense_Mutation SNP C C A rs80357069 byCluster TCGA-A1-A0SB-01 TCGA-A1-A0SB-10 C C Unknown Somatic Phase_IV Capture 1 dbGAP Illumina GAIIx medium 2.25 getma.org/?cm=msa&ty=f&p=BRCA1_HUMAN&rb=1756&re=1842&var=G1788V getma.org/pdb.php?prot=BRCA1_HUMAN&from=1756&to=1842&var=G1788V getma.org/?cm=var&var=hg19,17,41201181,C,A&fts=all ENST00000357654.3:c.5363G>T p.Gly1788Val p.G1788V ENST00000357654 21/23 0 0 BRCA1,missense_variant,p.Gly1492Val,ENST00000309486,NM_007297.3;BRCA1,missense_variant,p.Gly1788Val,ENST00000357654,NM_007294.3;BRCA1,missense_variant,p.Gly1549Val,ENST00000346315,;BRCA1,missense_variant,p.Gly1523Val,ENST00000354071,;BRCA1,missense_variant,p.Gly1809Val,ENST00000471181,NM_007300.3;BRCA1,missense_variant,p.Gly1741Val,ENST00000493795,;BRCA1,missense_variant,p.Gly646Val,ENST00000352993,;BRCA1,missense_variant,p.Gly605Val,ENST00000351666,;BRCA1,missense_variant,p.Gly684Val,ENST00000491747,NM_007298.3;BRCA1,missense_variant,p.Gly279Val,ENST00000591534,;BRCA1,missense_variant,p.Gly98Val,ENST00000586385,;BRCA1,missense_variant,p.Gly21Val,ENST00000591849,;BRCA1,intron_variant,,ENST00000468300,NM_007299.3;BRCA1,3_prime_UTR_variant,,ENST00000461221,; A ENSG00000012048 ENST00000357654 Transcript missense_variant 5482/7094 5363/5592 1788 G/V gGt/gTt rs80357069,COSM436662 1 BRCA1 HGNC 1100 protein_coding CCDS11453.1 ENSP00000350283 BRCA1_HUMAN Q9UE29_HUMAN,Q9NQR3_HUMAN,Q92897_HUMAN,Q7KYU6_HUMAN,Q4EW25_HUMAN,Q3YB53_HUMAN,Q3YB50_HUMAN,Q3YB49_HUMAN,Q3LRH8_HUMAN,Q3B891_HUMAN,K7EPC7_HUMAN,K4K7V3_HUMAN,K4JXS7_HUMAN,K4JUB1_HUMAN,G4V503_HUMAN,G4V502_HUMAN,G4V500_HUMAN,G4V4Z8_HUMAN,G4V4Z7_HUMAN,G1UI37_HUMAN,E9PFZ0_HUMAN,E7EWN5_HUMAN,E7EP70_HUMAN,C9IZW4_HUMAN,C4PFY7_HUMAN UPI0000126AC8 NM_007294.3 deleterious(0) benign(0.031) 21/23 Gene3D:3.40.50.10190,Pfam_domain:PF00533,PIRSF_domain:PIRSF001734,Prints_domain:PR00493,PROSITE_profiles:PS50172,hmmpanther:PTHR13763,hmmpanther:PTHR13763:SF0,SMART_domains:SM00292,Superfamily_domains:SSF52113 not_provided,pathogenic 0,1 MODERATE SNV 1,1 17 41201181 41201181 C A SNP BRCA1 NM_007294 human genbank 57_37b -1 reviewed missense c.5363 p.G1788V 1 HMMPfam_BRCT,HMMSmart_SM00292,superfamily_BRCT domain superfamily_RING/U-box,HMMSmart_SM00184,HMMPfam_zf-C3HC4,PatternScan_ZF_RING_1,HMMPfam_BRCT,HMMSmart_SM00292,superfamily_BRCT domain - 17 41201181 41201181 C A SNP BRCA1 NM_007294 human genbank 57_37b -1 reviewed missense c.5363 p.G1788V 1 HMMPfam_BRCT,HMMSmart_SM00292,superfamily_BRCT domain superfamily_RING/U-box,HMMSmart_SM00184,HMMPfam_zf-C3HC4,PatternScan_ZF_RING_1,HMMPfam_BRCT,HMMSmart_SM00292,superfamily_BRCT domain - -ATM genome.wustl.edu GRCh37 11 108173702 108173702 0 Frame_Shift_Del DEL G G - TCGA-A1-A0SB-01 TCGA-A1-A0SB-10 - G Unknown Germline Phase_IV Capture 1 dbGAP IlluminaGAIIx ENST00000278616.4:c.5443delG p.Asp1815ThrfsTer13 p.D1815Tfs*13 ENST00000278616 36/63 0 0 ATM,frameshift_variant,p.Asp1815ThrfsTer13,ENST00000278616,NM_000051.3;ATM,frameshift_variant,p.Asp1815ThrfsTer13,ENST00000452508,;ATM,non_coding_transcript_exon_variant,,ENST00000524792,;ATM,non_coding_transcript_exon_variant,,ENST00000533690,;ATM,non_coding_transcript_exon_variant,,ENST00000534625,;ATM,upstream_gene_variant,,ENST00000529588,; - ENSG00000149311 ENST00000278616 Transcript frameshift_variant 5827/13147 5442/9171 1814 L/X ttG/tt rs772138812 1 ATM HGNC 795 protein_coding YES CCDS31669.1 ENSP00000278616 ATM_HUMAN M0QXY8_HUMAN,E9PRG7_HUMAN,E9PIN0_HUMAN UPI0000DBEF44 NM_000051.3 36/63 hmmpanther:PTHR11139,hmmpanther:PTHR11139:SF66 HIGH 1 deletion 1 11 108173702 108173702 G - DEL ATM NM_000051.3 human genbank 58_37c 1 reviewed frame_shift_del c.5442 p.D1815fs 1 superfamily_ARM repeat superfamily_ARM repeat|7CHMMPfam_FAT|7Csuperfamily_Protein kinase-like (PK-like)|7CHMMPfam_PI3_PI4_kinase|7CHMMSmart_SM00146|7CPatternScan_PI3_4_KINASE_1|7CPatternScan_PI3_4_KINASE_2|7CHMMPfam_FATC - 11 108173702 108173702 G - DEL ATM NM_000051.3 human genbank 58_37c 1 reviewed frame_shift_del c.5442 p.D1815fs 1 superfamily_ARM repeat superfamily_ARM repeat|7CHMMPfam_FAT|7Csuperfamily_Protein kinase-like (PK-like)|7CHMMPfam_PI3_PI4_kinase|7CHMMSmart_SM00146|7CPatternScan_PI3_4_KINASE_1|7CPatternScan_PI3_4_KINASE_2|7CHMMPfam_FATC - +ATM genome.wustl.edu GRCh37 11 108173702 108173702 0 Frame_Shift_Del DEL G G - TCGA-A1-A0SB-01 TCGA-A1-A0SB-10 - G Unknown Somatic Phase_IV Capture 1 dbGAP IlluminaGAIIx ENST00000278616.4:c.5443delG p.Asp1815ThrfsTer13 p.D1815Tfs*13 ENST00000278616 36/63 0 0 ATM,frameshift_variant,p.Asp1815ThrfsTer13,ENST00000278616,NM_000051.3;ATM,frameshift_variant,p.Asp1815ThrfsTer13,ENST00000452508,;ATM,non_coding_transcript_exon_variant,,ENST00000524792,;ATM,non_coding_transcript_exon_variant,,ENST00000533690,;ATM,non_coding_transcript_exon_variant,,ENST00000534625,;ATM,upstream_gene_variant,,ENST00000529588,; - ENSG00000149311 ENST00000278616 Transcript frameshift_variant 5827/13147 5442/9171 1814 L/X ttG/tt rs772138812 1 ATM HGNC 795 protein_coding YES CCDS31669.1 ENSP00000278616 ATM_HUMAN M0QXY8_HUMAN,E9PRG7_HUMAN,E9PIN0_HUMAN UPI0000DBEF44 NM_000051.3 36/63 hmmpanther:PTHR11139,hmmpanther:PTHR11139:SF66 HIGH 1 deletion 1 11 108173702 108173702 G - DEL ATM NM_000051.3 human genbank 58_37c 1 reviewed frame_shift_del c.5442 p.D1815fs 1 superfamily_ARM repeat superfamily_ARM repeat|7CHMMPfam_FAT|7Csuperfamily_Protein kinase-like (PK-like)|7CHMMPfam_PI3_PI4_kinase|7CHMMSmart_SM00146|7CPatternScan_PI3_4_KINASE_1|7CPatternScan_PI3_4_KINASE_2|7CHMMPfam_FATC - 11 108173702 108173702 G - DEL ATM NM_000051.3 human genbank 58_37c 1 reviewed frame_shift_del c.5442 p.D1815fs 1 superfamily_ARM repeat superfamily_ARM repeat|7CHMMPfam_FAT|7Csuperfamily_Protein kinase-like (PK-like)|7CHMMPfam_PI3_PI4_kinase|7CHMMSmart_SM00146|7CPatternScan_PI3_4_KINASE_1|7CPatternScan_PI3_4_KINASE_2|7CHMMPfam_FATC - ATM genome.wustl.edu GRCh37 11 108106472 108106472 0 Frame_Shift_Del DEL T T - novel unknown TCGA-A1-A0SB-01 TCGA-A1-A0SB-10 T T Unknown Somatic Phase_IV Capture 1 dbGAP Illumina GAIIx ENST00000278616.4:c.409delT p.Tyr137ThrfsTer16 p.Y137Tfs*16 ENST00000278616 May-63 0 0 ATM,frameshift_variant,p.Tyr137ThrfsTer16,ENST00000278616,NM_000051.3;ATM,frameshift_variant,p.Tyr137ThrfsTer16,ENST00000452508,;ATM,frameshift_variant,p.Tyr137ThrfsTer16,ENST00000527805,;ATM,intron_variant,,ENST00000527891,;ATM,downstream_gene_variant,,ENST00000601453,;ATM,non_coding_transcript_exon_variant,,ENST00000530958,; - ENSG00000149311 ENST00000278616 Transcript frameshift_variant 792/13147 407/9171 136 I/X aTt/at COSM428356,COSM1474979 1 ATM HGNC 795 protein_coding YES CCDS31669.1 ENSP00000278616 ATM_HUMAN M0QXY8_HUMAN,E9PRG7_HUMAN,E9PIN0_HUMAN UPI0000DBEF44 NM_000051.3 May-63 Pfam_domain:PF11640,hmmpanther:PTHR11139,hmmpanther:PTHR11139:SF66 1,1 HIGH 1 deletion 2 1,1 11 108106472 108106472 T - DEL ATM NM_000051 human genbank 57_37b 1 reviewed frame_shift_del c.407 p.Y137fs 0.013 superfamily_ARM repeat,HMMPfam_FAT,superfamily_Protein kinase-like (PK-like),HMMPfam_PI3_PI4_kinase,HMMSmart_SM00146,PatternScan_PI3_4_KINASE_1,PatternScan_PI3_4_KINASE_2,HMMPfam_FATC (deletion:cds_exon[108106397,108106561]) 11 108106472 108106472 T - DEL ATM NM_000051 human genbank 57_37b 1 reviewed frame_shift_del c.407 p.Y137fs 0.013 superfamily_ARM repeat,HMMPfam_FAT,superfamily_Protein kinase-like (PK-like),HMMPfam_PI3_PI4_kinase,HMMSmart_SM00146,PatternScan_PI3_4_KINASE_1,PatternScan_PI3_4_KINASE_2,HMMPfam_FATC (deletion:cds_exon[108106397,108106561]) -BRCA2 genome.wustl.edu GRCh37 13 108106473 108106473 0 Nonsense_Mutation SNP T T C TCGA-A1-A0SB-01 TCGA-A1-A0SB-10 Germline p.D191G BRCA2_HUMAN +BRCA2 genome.wustl.edu GRCh37 13 108106473 108106473 0 Nonsense_Mutation SNP T T C TCGA-A1-A0SB-01 TCGA-A1-A0SB-10 Somatic p.D191G BRCA2_HUMAN BRCA2 genome.wustl.edu GRCh37 13 108106474 108106474 0 Nonsense_Mutation SNP T T C TCGA-A2-A04P-01 TCGA-A2-A04P-10 Somatic p.D191G BRCA2_HUMAN -BRCA2 genome.wustl.edu GRCh37 13 108106475 108106475 0 In_Frame_Del DEL T T - TCGA-A1-A0SK-01 TCGA-A1-A0SK-10 Germline p.R2659T BRCA2_HUMAN +BRCA2 genome.wustl.edu GRCh37 13 108106475 108106475 0 In_Frame_Del DEL T T - TCGA-A1-A0SK-01 TCGA-A1-A0SK-10 Somatic p.R2659T BRCA2_HUMAN BRCA2 genome.wustl.edu GRCh37 13 108106476 108106476 0 In_Frame_Del DEL T T - TCGA-A2-A0CM-01 TCGA-A2-A0CM-10 Somatic p.R2659T BRCA2_HUMAN -BRCA2 genome.wustl.edu GRCh37 13 108106477 108106477 0 Missense_Mutation SNP T T C TCGA-AR-A1AR-01 TCGA-AR-A1AR-10 Germline p.R2336C BRCA2_HUMAN +BRCA2 genome.wustl.edu GRCh37 13 108106477 108106477 0 Missense_Mutation SNP T T C TCGA-AR-A1AR-01 TCGA-AR-A1AR-10 Somatic p.R2336C BRCA2_HUMAN BRCA2 genome.wustl.edu GRCh37 13 108106478 108106478 0 Missense_Mutation SNP T T C TCGA-B6-A0WX-01 TCGA-B6-A0WX-10 Somatic p.R2336C BRCA2_HUMAN -BRCA2 genome.wustl.edu GRCh37 13 108106479 108106479 0 Nonsense_Mutation SNP T T C TCGA-BH-A1F0-01 TCGA-BH-A1F0-10 Germline p.R2000T BRCA2_HUMAN +BRCA2 genome.wustl.edu GRCh37 13 108106479 108106479 0 Nonsense_Mutation SNP T T C TCGA-BH-A1F0-01 TCGA-BH-A1F0-10 Somatic p.R2000T BRCA2_HUMAN BRCA2 genome.wustl.edu GRCh37 13 108106480 108106480 0 Nonsense_Mutation SNP T T C TCGA-B6-A0I6-01 TCGA-B6-A0I6-10 Somatic p.R2000T BRCA2_HUMAN -BRCA2 genome.wustl.edu GRCh37 13 108106481 108106481 0 In_Frame_Del DEL T T - TCGA-BH-A18V-01 TCGA-BH-A18V-10 Germline p.V1270del BRCA2_HUMAN +BRCA2 genome.wustl.edu GRCh37 13 108106481 108106481 0 In_Frame_Del DEL T T - TCGA-BH-A18V-01 TCGA-BH-A18V-10 Somatic p.V1270del BRCA2_HUMAN BRCA2 genome.wustl.edu GRCh37 13 108106482 108106482 0 In_Frame_Del DEL T T - TCGA-BH-A18K-01 TCGA-BH-A18K-10 Somatic p.V1270del BRCA2_HUMAN -BRCA2 genome.wustl.edu GRCh37 13 108106483 108106483 0 Missense_Mutation SNP T T C TCGA-BH-A0HL-01 TCGA-BH-A0HL-10 Germline p.D3073G BRCA2_HUMAN +BRCA2 genome.wustl.edu GRCh37 13 108106483 108106483 0 Missense_Mutation SNP T T C TCGA-BH-A0HL-01 TCGA-BH-A0HL-10 Somatic p.D3073G BRCA2_HUMAN BRCA2 genome.wustl.edu GRCh37 13 108106484 108106484 0 Missense_Mutation SNP T T C TCGA-BH-A0E0-01 TCGA-BH-A0E0-10 Somatic p.D3073G BRCA2_HUMAN ACP3 genome.wustl.edu GRCh37 3 132047117 132047117 0 Missense_Mutation SNP C C T TEST_SAMPLE_1 Somatic NA NA NA NA NA NA NA NA NA NA NA NA NA NA ENST00000336375.5:c.127C>T p.Arg43Trp p.R43W ENST00000336375 NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA PPAP_HUMAN NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA ACP3 genome.wustl.edu GRCh37 3 132047117 132047117 0 Missense_Mutation SNP C C T TEST_SAMPLE_2 Somatic NA NA NA NA NA NA NA NA NA NA NA NA NA NA ENST00000336375.5:c.127C>T p.Arg43Trp p.R43W ENST00000336375 NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA PPAP_HUMAN NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA diff --git a/test/test_data/study_oncokb_update/data_mutations_extended.maf b/test/test_data/study_oncokb_update/data_mutations_extended.maf index e8bab052040..399bd4a0f82 100644 --- a/test/test_data/study_oncokb_update/data_mutations_extended.maf +++ b/test/test_data/study_oncokb_update/data_mutations_extended.maf @@ -1,3 +1,3 @@ #version 2.4 Hugo_Symbol Entrez_Gene_Id Center NCBI_Build Chromosome Start_Position End_Position Strand Variant_Classification Variant_Type Reference_Allele Tumor_Seq_Allele1 Tumor_Seq_Allele2 dbSNP_RS dbSNP_Val_Status Tumor_Sample_Barcode Matched_Norm_Sample_Barcode Match_Norm_Seq_Allele1 Match_Norm_Seq_Allele2 Tumor_Validation_Allele1 Tumor_Validation_Allele2 Match_Norm_Validation_Allele1 Match_Norm_Validation_Allele2 Verification_Status Validation_Status Mutation_Status Sequencing_Phase Sequence_Source Validation_Method Score BAM_File Sequencer MA:FImpact MA:FIS Amino_Acid_Change MA:link.MSA MA:link.PDB MA:link.var Tumor_Sample_UUID Matched_Norm_Sample_UUID HGVSc HGVSp HGVSp_Short Transcript_ID Exon_Number t_depth t_ref_count t_alt_count n_depth n_ref_count n_alt_count all_effects Allele Gene Feature Feature_type Consequence cDNA_position CDS_position Protein_position Amino_acids Codons Existing_variation ALLELE_NUM DISTANCE SYMBOL SYMBOL_SOURCE HGNC_ID BIOTYPE CANONICAL CCDS ENSP SWISSPROT TREMBL UNIPARC RefSeq SIFT PolyPhen EXON INTRON DOMAINS GMAF AFR_MAF AMR_MAF ASN_MAF EAS_MAF EUR_MAF SAS_MAF AA_MAF EA_MAF CLIN_SIG SOMATIC PUBMED MOTIF_NAME MOTIF_POS HIGH_INF_POS MOTIF_SCORE_CHANGE IMPACT PICK VARIANT_CLASS TSL HGVS_OFFSET PHENO chromosome_name_wu start_wu stop_wu reference_wu variant_wu type_wu gene_name_wu transcript_name_wu transcript_species_wu transcript_source_wu transcript_version_wu strand_wu transcript_status_wu trv_type_wu c_position_wu amino_acid_change_wu ucsc_cons_wu domain_wu all_domains_wu deletion_substructures_wu transcript_error_wu default_gene_name_wu gene_name_source_wu ensembl_gene_id normal_ref_reads normal_var_reads normal_vaf tumor_ref_reads tumors_var_reads tumor_vaf evs_ea evs_aa evs_all chromosome_name_WU start_WU stop_WU reference_WU variant_WU type_WU gene_name_WU transcript_name_WU transcript_species_WU transcript_source_WU transcript_version_WU strand_WU transcript_status_WU trv_type_WU c_position_WU amino_acid_change_WU ucsc_cons_WU domain_WU all_domains_WU deletion_substructures_WU transcript_error_WU default_gene_name_WU gene_name_source_WU EVS_EA EVS_AA EVS_All cbp_driver cbp_driver_annotation -TP53 genome.wustl.edu GRCh37 17 7578253 7578253 0 Missense_Mutation SNP C C A TCGA-A1-A0SB-01 TCGA-A1-A0SB-10 A C Unknown Germline Phase_IV Capture 1 dbGAP IlluminaGAIIx medium 3.005 getma.org/?cm=msa&ty=f&p=P53_HUMAN&rb=95&re=289&var=G199V getma.org/pdb.php?prot=P53_HUMAN&from=95&to=289&var=G199V getma.org/?cm=var&var=hg19,17,7578253,C,A&fts=all ENST00000269305.4:c.596G>T p.Gly199Val p.G199V ENST00000269305 11-Jun 0 0 TP53,missense_variant,p.Gly199Val,ENST00000420246,NM_001126114.2,NM_001276696.1;TP53,missense_variant,p.Gly199Val,ENST00000455263,NM_001276695.1,NM_001126113.2;TP53,missense_variant,p.Gly199Val,ENST00000269305,NM_001126112.2,NM_001276761.1,NM_001276760.1,NM_000546.5,NM_001126118.1;TP53,missense_variant,p.Gly199Val,ENST00000445888,;TP53,missense_variant,p.Gly199Val,ENST00000359597,;TP53,missense_variant,p.Gly199Val,ENST00000413465,;TP53,missense_variant,p.Gly67Val,ENST00000509690,;TP53,missense_variant,p.Gly106Val,ENST00000514944,;TP53,downstream_gene_variant,,ENST00000508793,;TP53,downstream_gene_variant,,ENST00000604348,;TP53,downstream_gene_variant,,ENST00000503591,;TP53,upstream_gene_variant,,ENST00000576024,;TP53,intron_variant,,ENST00000574684,;TP53,non_coding_transcript_exon_variant,,ENST00000510385,;TP53,non_coding_transcript_exon_variant,,ENST00000504290,;TP53,non_coding_transcript_exon_variant,,ENST00000504937,;TP53,non_coding_transcript_exon_variant,,ENST00000505014,; A ENSG00000141510 ENST00000269305 Transcript missense_variant 786/2579 596/1182 199 G/V gGa/gTa TP53_g.12665G>T,COSM44140,COSM255788,COSM255787,COSM255789,COSM3675525,COSM3675524,COSM255790 1 TP53 HGNC 11998 protein_coding YES CCDS11118.1 ENSP00000269305 P53_HUMAN S5LQU8_HUMAN,Q761V2_HUMAN,Q6IT77_HUMAN,Q1HGV1_HUMAN,Q0PKT5_HUMAN,L0ES54_HUMAN,L0EQ05_HUMAN,K7PPA8_HUMAN,H2EHT1_HUMAN,G4Y083_HUMAN,E9PCY9_HUMAN,E7ESS1_HUMAN,E7EMR6_HUMAN,B5AKF6_HUMAN,B4DNI2_HUMAN,A4GWD0_HUMAN,A4GWB8_HUMAN,A4GWB5_HUMAN,A4GW97_HUMAN,A4GW76_HUMAN,A4GW75_HUMAN,A4GW74_HUMAN,A4GW67_HUMAN,A2I9Z1_HUMAN,A2I9Z0_HUMAN UPI000002ED67 NM_001126112.2 deleterious(0) probably_damaging(1) 11-Jun Gene3D:2.60.40.720,Pfam_domain:PF00870,hmmpanther:PTHR11447,hmmpanther:PTHR11447:SF6,Superfamily_domains:SSF49417 0,1,1,1,1,1,1,1 MODERATE 1 SNV 0,1,1,1,1,1,1,1 17 7578253 7578253 C A SNP TP53 NM_000546.4 human genbank 58_37c -1 reviewed missense c.596 p.G199V 1 HMMPfam_P53|7Csuperfamily_p53-like transcription factors HMMPfam_P53_TAD|7CHMMPfam_P53|7Csuperfamily_p53-like transcription factors|7CPatternScan_P53|7CHMMPfam_P53_tetramer|7Csuperfamily_p53 tetramerization domain - 17 7578253 7578253 C A SNP TP53 NM_000546.4 human genbank 58_37c -1 reviewed missense c.596 p.G199V 1 HMMPfam_P53|7Csuperfamily_p53-like transcription factors HMMPfam_P53_TAD|7CHMMPfam_P53|7Csuperfamily_p53-like transcription factors|7CPatternScan_P53|7CHMMPfam_P53_tetramer|7Csuperfamily_p53 tetramerization domain - NA TEST +TP53 genome.wustl.edu GRCh37 17 7578253 7578253 0 Missense_Mutation SNP C C A TCGA-A1-A0SB-01 TCGA-A1-A0SB-10 A C Unknown Somatic Phase_IV Capture 1 dbGAP IlluminaGAIIx medium 3.005 getma.org/?cm=msa&ty=f&p=P53_HUMAN&rb=95&re=289&var=G199V getma.org/pdb.php?prot=P53_HUMAN&from=95&to=289&var=G199V getma.org/?cm=var&var=hg19,17,7578253,C,A&fts=all ENST00000269305.4:c.596G>T p.Gly199Val p.G199V ENST00000269305 11-Jun 0 0 TP53,missense_variant,p.Gly199Val,ENST00000420246,NM_001126114.2,NM_001276696.1;TP53,missense_variant,p.Gly199Val,ENST00000455263,NM_001276695.1,NM_001126113.2;TP53,missense_variant,p.Gly199Val,ENST00000269305,NM_001126112.2,NM_001276761.1,NM_001276760.1,NM_000546.5,NM_001126118.1;TP53,missense_variant,p.Gly199Val,ENST00000445888,;TP53,missense_variant,p.Gly199Val,ENST00000359597,;TP53,missense_variant,p.Gly199Val,ENST00000413465,;TP53,missense_variant,p.Gly67Val,ENST00000509690,;TP53,missense_variant,p.Gly106Val,ENST00000514944,;TP53,downstream_gene_variant,,ENST00000508793,;TP53,downstream_gene_variant,,ENST00000604348,;TP53,downstream_gene_variant,,ENST00000503591,;TP53,upstream_gene_variant,,ENST00000576024,;TP53,intron_variant,,ENST00000574684,;TP53,non_coding_transcript_exon_variant,,ENST00000510385,;TP53,non_coding_transcript_exon_variant,,ENST00000504290,;TP53,non_coding_transcript_exon_variant,,ENST00000504937,;TP53,non_coding_transcript_exon_variant,,ENST00000505014,; A ENSG00000141510 ENST00000269305 Transcript missense_variant 786/2579 596/1182 199 G/V gGa/gTa TP53_g.12665G>T,COSM44140,COSM255788,COSM255787,COSM255789,COSM3675525,COSM3675524,COSM255790 1 TP53 HGNC 11998 protein_coding YES CCDS11118.1 ENSP00000269305 P53_HUMAN S5LQU8_HUMAN,Q761V2_HUMAN,Q6IT77_HUMAN,Q1HGV1_HUMAN,Q0PKT5_HUMAN,L0ES54_HUMAN,L0EQ05_HUMAN,K7PPA8_HUMAN,H2EHT1_HUMAN,G4Y083_HUMAN,E9PCY9_HUMAN,E7ESS1_HUMAN,E7EMR6_HUMAN,B5AKF6_HUMAN,B4DNI2_HUMAN,A4GWD0_HUMAN,A4GWB8_HUMAN,A4GWB5_HUMAN,A4GW97_HUMAN,A4GW76_HUMAN,A4GW75_HUMAN,A4GW74_HUMAN,A4GW67_HUMAN,A2I9Z1_HUMAN,A2I9Z0_HUMAN UPI000002ED67 NM_001126112.2 deleterious(0) probably_damaging(1) 11-Jun Gene3D:2.60.40.720,Pfam_domain:PF00870,hmmpanther:PTHR11447,hmmpanther:PTHR11447:SF6,Superfamily_domains:SSF49417 0,1,1,1,1,1,1,1 MODERATE 1 SNV 0,1,1,1,1,1,1,1 17 7578253 7578253 C A SNP TP53 NM_000546.4 human genbank 58_37c -1 reviewed missense c.596 p.G199V 1 HMMPfam_P53|7Csuperfamily_p53-like transcription factors HMMPfam_P53_TAD|7CHMMPfam_P53|7Csuperfamily_p53-like transcription factors|7CPatternScan_P53|7CHMMPfam_P53_tetramer|7Csuperfamily_p53 tetramerization domain - 17 7578253 7578253 C A SNP TP53 NM_000546.4 human genbank 58_37c -1 reviewed missense c.596 p.G199V 1 HMMPfam_P53|7Csuperfamily_p53-like transcription factors HMMPfam_P53_TAD|7CHMMPfam_P53|7Csuperfamily_p53-like transcription factors|7CPatternScan_P53|7CHMMPfam_P53_tetramer|7Csuperfamily_p53 tetramerization domain - NA TEST diff --git a/test/test_db_version.sh b/test/test_db_version.sh index e370ed930ca..022acc6f680 100755 --- a/test/test_db_version.sh +++ b/test/test_db_version.sh @@ -11,17 +11,109 @@ NC='\033[0m' echo "Making sure all db versions are the same in cgds.sql, pom.xml and migration.sql" -POM_DB_VERSION=$(grep db.version ${DIR}/../pom.xml | cut -d'>' -f2 | cut -d'<' -f1) -echo pom.xml db version is $POM_DB_VERSION +declare -a found_delimited_substrings -CGDS_DB_SQL_VERSION=$(grep 'INSERT INTO info' ${DIR}/../src/main/resources/db-scripts/cgds.sql | cut -d"'" -f2 | cut -d"'" -f1) -echo src/main/resources/db-scripts/cgds.sql db version is $CGDS_DB_SQL_VERSION +# find delimited substrings in a containing string +# positional arguments: +# - string_with_delimited_substrings +# - starting_delimiting_character +# - ending_delimiting_chracter +# example use : find_delimited_substrings 'roses are "red", "white", "pink"' '"' '"' +# will set array found_delimited_substrings to ('red', 'white', 'pink') +# example use : find_delimited_substrings 'roses are "red", "white", "pink"' '"' '' +# will set array found_delimited_substrings to: +# ('roses are ', 'red', ', ', 'white', ', ', 'pink') +# when ending_delimiting_character argument is the empty string ('') then substrings are +# found by breaking the string between each occurrence of the staring delimiting character. +# Otherwise, substrings are found iteratively by locating the first not-previously used +# occurrence of the starting delimiting character and using all characters from that point +# to the next occurrence of the ending_delimiting_character (which is consumed but not +# returned). +# +function find_delimited_substrings() { + string_with_delimited_substrings=$1 + starting_delimiting_character=$2 + ending_delimiting_character=$3 + if [ ${#ending_delimiting_character} == 0 ] ; then + IFS=$starting_delimiting_character ; read -ra found_delimited_substrings <<< "$string_with_delimited_substrings" + return 0 + fi + found_delimited_substrings=() + working_string="$string_with_delimited_substrings" + done=false + while true; do + working_string_length=${#working_string} + startpos=0 + while [ $startpos -lt $working_string_length ] ; do + if [ "${working_string:$startpos:1}" == "$starting_delimiting_character" ] ; then + break + fi + startpos=$(($startpos+1)) + done + if [ $startpos -eq $working_string_length ] ; then + break # no more found + fi + endpos=$(($startpos+1)) + while [ $endpos -lt $working_string_length ] ; do + if [ "${working_string:$endpos:1}" == "$ending_delimiting_character" ] ; then + break + fi + endpos=$(($endpos+1)) + done + if [ $endpos -eq $working_string_length ] ; then + break # no more found + fi + substring_start=$((startpos+1)) + substring_len=$(($endpos-$startpos-1)) + found_delimited_substrings+=(${working_string:$substring_start:$substring_len}) + next_working_startpos=$((endpos+1)) + working_string=${working_string:$next_working_startpos} + done + return 0 +} -MIGRATION_DB_VERSION=$(grep 'UPDATE `info`' ${DIR}/../src/main/resources/db-scripts/migration.sql | tail -1 | cut -d '"' -f2 | cut -d'"' -f1) -echo src/main/resources/db-scripts/migration.sql db version is $MIGRATION_DB_VERSION +pom_db_version_line=$(grep db.version ${DIR}/../pom.xml | tail -n 1) +find_delimited_substrings "$pom_db_version_line" ">" "<" +pom_db_version=${found_delimited_substrings[0]} -if [ "$POM_DB_VERSION" == "$CGDS_DB_SQL_VERSION" ] && [ "$CGDS_DB_SQL_VERSION" == "$MIGRATION_DB_VERSION" ] -then +pom_derived_table_version_line=$(grep derived_table.version ${DIR}/../pom.xml | tail -n 1) +find_delimited_substrings "$pom_derived_table_version_line" ">" "<" +pom_derived_table_version=${found_delimited_substrings[0]} + +cgds_db_sql_version_line=$(grep -A1 'INSERT INTO `info`' ${DIR}/../src/main/resources/db-scripts/cgds.sql | tail -n 1) +find_delimited_substrings "$cgds_db_sql_version_line" "'" "'" +cgds_db_sql_version=${found_delimited_substrings[0]} +cgds_db_derived_table_version=${found_delimited_substrings[1]} + +migration_db_version_line=$(grep 'UPDATE `info` SET `DB_SCHEMA_VERSION`' ${DIR}/../src/main/resources/db-scripts/migration.sql | tail -n 1 ) +find_delimited_substrings "$migration_db_version_line" '"' '"' +migration_db_version=${found_delimited_substrings[0]} + +migration_derived_table_version_line=$(grep 'UPDATE `info` SET `DERIVED_TABLE_SCHEMA_VERSION`' ${DIR}/../src/main/resources/db-scripts/migration.sql | tail -n 1 ) +find_delimited_substrings "$migration_derived_table_version_line" '"' '"' +migration_derived_table_version=${found_delimited_substrings[0]} + +echo "pom.xml db version is $pom_db_version" +echo "src/main/resources/db-scripts/cgds.sql db version is $cgds_db_sql_version" +echo src/main/resources/db-scripts/migration.sql db version is $migration_db_version +echo "pom.xml derived_table version is $pom_derived_table_version" +echo "src/main/resources/db-scripts/cgds.sql derived_table_version is $cgds_db_derived_table_version" +echo src/main/resources/db-scripts/migration.sql derived_table version is $migration_derived_table_version + +if [ "$pom_db_version" == "$cgds_db_sql_version" ] && + [ "$cgds_db_sql_version" == "$migration_db_version" ] ; then + db_versions_all_match="yes" +else + db_versions_all_match="no" +fi +if [ "$pom_derived_table_version" == "$cgds_db_derived_table_version" ] && + [ "$cgds_db_derived_table_version" == "$migration_derived_table_version" ] ; then + derived_table_versions_all_match="yes" +else + derived_table_versions_all_match="no" +fi + +if [ $db_versions_all_match == "yes" ] && [ $derived_table_versions_all_match == "yes" ] ; then echo -e "${GREEN}db versions match${NC}"; exit 0; else