diff --git a/.github/workflows/ruby-unit-tests.yml b/.github/workflows/ruby-unit-tests.yml deleted file mode 100644 index 2aac14680..000000000 --- a/.github/workflows/ruby-unit-tests.yml +++ /dev/null @@ -1,30 +0,0 @@ -name: Ruby Unit Tests - -on: - push: - pull_request: - -jobs: - test: - strategy: - fail-fast: false - matrix: - backend: ['api', 'api-agraph'] # api runs tests with 4store backend and api-agraph runs with AllegroGraph backend - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - name: Build docker-compose - run: docker compose --profile 4store build #profile flag is set in order to build all containers in this step - - name: Run unit tests - # unit tests are run inside a container - # http://docs.codecov.io/docs/testing-with-docker - run: | - ci_env=`bash <(curl -s https://codecov.io/env)` - docker compose run $ci_env -e CI --rm ${{ matrix.backend }} bundle exec rake test TESTOPTS='-v' - - name: Upload coverage reports to Codecov - uses: codecov/codecov-action@v4 - with: - token: ${{ secrets.CODECOV_TOKEN }} - flags: unittests - verbose: true - fail_ci_if_error: false # optional (default = false) diff --git a/.github/workflows/testkit-unit-tests.yml b/.github/workflows/testkit-unit-tests.yml new file mode 100644 index 000000000..358194a41 --- /dev/null +++ b/.github/workflows/testkit-unit-tests.yml @@ -0,0 +1,87 @@ +name: Docker Unit Tests + +on: + push: + branches: + - '**' + tags-ignore: + - '**' + pull_request: + +env: + # CI execution mode for backend tests: + # - container: run `test:docker::container` (default) + # - native: run `test:docker:` on host Ruby + OPTK_CI_RUN_MODE: ${{ vars.OPTK_CI_RUN_MODE || 'container' }} + # Example override to force native mode in this workflow file: + # OPTK_CI_RUN_MODE: native + +jobs: + prepare: + runs-on: ubuntu-latest + outputs: + backends: ${{ steps.cfg.outputs.backends }} + steps: + - uses: actions/checkout@v4 + + - id: cfg + name: Read backend matrix from .ontoportal-testkit.yml + run: | + BACKENDS=$(ruby -ryaml -rjson -e 'c=YAML.safe_load_file(".ontoportal-testkit.yml") || {}; b=c["backends"] || %w[fs ag vo gd]; puts JSON.generate(b)') + echo "backends=$BACKENDS" >> "$GITHUB_OUTPUT" + + test: + needs: prepare + runs-on: ubuntu-latest + timeout-minutes: 45 + strategy: + fail-fast: false + matrix: + backend: ${{ fromJson(needs.prepare.outputs.backends) }} + + steps: + - uses: actions/checkout@v4 + + - name: Set up Ruby from .ruby-version + uses: ruby/setup-ruby@v1 + with: + ruby-version: .ruby-version + bundler-cache: true + + - name: Set up Java 11 (native mode) + if: env.OPTK_CI_RUN_MODE == 'native' + uses: actions/setup-java@v4 + with: + distribution: temurin + java-version: '11' + + - name: Install native system dependencies + if: env.OPTK_CI_RUN_MODE == 'native' + run: | + sudo apt-get update + sudo apt-get install -y raptor2-utils + + - name: Run unit tests + env: + CI: "true" + TESTOPTS: "--verbose" + BACKEND: ${{ matrix.backend }} + run: | + MODE="${OPTK_CI_RUN_MODE:-container}" + TASK="test:docker:${BACKEND}" + if [ "$MODE" = "container" ]; then + TASK="${TASK}:container" + elif [ "$MODE" != "native" ]; then + echo "Invalid OPTK_CI_RUN_MODE=$MODE (expected container or native)" + exit 1 + fi + + bundle exec rake "$TASK" + + - name: Upload coverage reports to Codecov + uses: codecov/codecov-action@v5 + with: + token: ${{ secrets.CODECOV_TOKEN }} + flags: unittests,${{ matrix.backend }} + verbose: true + fail_ci_if_error: false diff --git a/.ontoportal-testkit.yml b/.ontoportal-testkit.yml new file mode 100644 index 000000000..c63def5c1 --- /dev/null +++ b/.ontoportal-testkit.yml @@ -0,0 +1,9 @@ +component_name: ontologies_api +app_service: test-container +backends: + - fs + - ag + - vo + - gd +dependency_services: + - mgrep diff --git a/.ruby-version b/.ruby-version index 9cec7165a..f15386a5d 100644 --- a/.ruby-version +++ b/.ruby-version @@ -1 +1 @@ -3.1.6 +3.2.10 diff --git a/Capfile b/Capfile index 3bf9ae11e..c01b1e450 100644 --- a/Capfile +++ b/Capfile @@ -22,6 +22,5 @@ require 'capistrano/bundler' # require 'capistrano/rails/assets' # require 'capistrano/rails/migrations' require 'capistrano/locally' -require 'new_relic/recipes' # announce deployments in NewRelic # Loads custom tasks from `lib/capistrano/tasks' if you have any defined. Dir.glob('lib/capistrano/tasks/*.cap').each { |r| import r } diff --git a/Dockerfile b/Dockerfile index 896b90cb4..3ca8019ce 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,24 +1,20 @@ -ARG RUBY_VERSION=3.1 -ARG DISTRO_NAME=bullseye +ARG RUBY_VERSION=3.2 +ARG DISTRO=bullseye +ARG TESTKIT_BASE_IMAGE=ontoportal/testkit-base:ruby${RUBY_VERSION}-${DISTRO} +FROM ${TESTKIT_BASE_IMAGE} -FROM ruby:$RUBY_VERSION-$DISTRO_NAME +WORKDIR /app -RUN apt-get update -yqq && apt-get install -yqq --no-install-recommends \ - openjdk-11-jre-headless \ - raptor2-utils \ - && rm -rf /var/lib/apt/lists/* +COPY Gemfile* *.gemspec ./ -RUN mkdir -p /srv/ontoportal/ontologies_api -RUN mkdir -p /srv/ontoportal/bundle -COPY Gemfile* /srv/ontoportal/ontologies_api/ +# Respect the project's Bundler lock when present. +RUN if [ -f Gemfile.lock ]; then \ + BUNDLER_VERSION=$(grep -A 1 "BUNDLED WITH" Gemfile.lock | tail -n 1 | tr -d ' '); \ + gem install bundler -v "$BUNDLER_VERSION"; \ + fi -WORKDIR /srv/ontoportal/ontologies_api +RUN bundle install --jobs 4 --retry 3 -ENV BUNDLE_PATH=/srv/ontoportal/bundle -RUN bundle install +COPY . ./ -COPY . /srv/ontoportal/ontologies_api -RUN cp /srv/ontoportal/ontologies_api/config/environments/config.rb.sample /srv/ontoportal/ontologies_api/config/environments/development.rb - -EXPOSE 9393 CMD ["bundle", "exec", "rackup", "-p", "9393", "--host", "0.0.0.0"] diff --git a/Gemfile b/Gemfile index c0f5193f4..4a5279004 100644 --- a/Gemfile +++ b/Gemfile @@ -1,38 +1,41 @@ source 'https://rubygems.org' -gem 'activesupport', '~> 5' +gem 'activesupport' # see https://github.com/ncbo/ontologies_api/issues/69 gem 'bigdecimal' -# gem 'faraday', '~> 1.9' -gem 'json-schema', '~> 2.0' +gem 'json-schema' gem 'multi_json' gem 'oj' gem 'parseconfig' gem 'rack' -gem 'rake', '~> 10.0' +gem 'rake' gem 'rexml' # Investigate why unicorn fails to start under ruby 3 without adding rexml gem to the Gemfile -gem 'sinatra', '~> 1.0' -gem 'sinatra-advanced-routes' -gem 'sinatra-contrib', '~> 1.0' +gem 'rackup' +gem 'sinatra' +gem 'sinatra-contrib' + +gem 'request_store' +gem 'parallel' +gem 'google-protobuf', '3.25.3' +gem 'grpc', '1.70.1' +gem 'net-ftp' +gem 'json-ld', '~> 3.2.0' +gem 'rdf-raptor', github:'ruby-rdf/rdf-raptor', ref: '6392ceabf71c3233b0f7f0172f662bd4a22cd534' # use version 3.3.0 when available # Rack middleware gem 'ffi' -gem 'rack-accept', '~> 0.4' -gem 'rack-attack', '~> 6.6.1', require: 'rack/attack' -gem 'rack-cache', '~> 1.13.0' # see https://github.com/ncbo/ontologies_api/issues/118 +gem 'rack-accept' +gem 'rack-attack', require: 'rack/attack' +gem 'rack-cache' # see https://github.com/ncbo/ontologies_api/issues/118 gem 'rack-cors', require: 'rack/cors' # GitHub dependency can be removed when https://github.com/niko/rack-post-body-to-params/pull/6 is merged and released gem 'rack-post-body-to-params', github: 'palexander/rack-post-body-to-params', branch: 'multipart_support' gem 'rack-timeout' -gem 'redis-rack-cache', '~> 2.0' +gem 'redis-rack-cache' # Data access (caching) gem 'redis' -gem 'redis-store', '~>1.10' - -# Monitoring -gem 'cube-ruby', require: 'cube' -gem 'newrelic_rpm', group: [:default, :deployment] +gem 'redis-store' # HTTP server gem 'unicorn' @@ -40,19 +43,19 @@ gem 'unicorn-worker-killer' # Templating gem 'haml', '~> 5.2.2' # pin see https://github.com/ncbo/ontologies_api/pull/107 -gem 'redcarpet' +gem 'rack-contrib' +gem 'pandoc-ruby' # NCBO gems (can be from a local dev path or from rubygems/git) -gem 'goo', github: 'ncbo/goo', branch: 'develop' -gem 'ncbo_annotator', github: 'ncbo/ncbo_annotator', branch: 'develop' -gem 'ncbo_cron', github: 'ncbo/ncbo_cron', branch: 'develop' -gem 'ncbo_ontology_recommender', github: 'ncbo/ncbo_ontology_recommender', branch: 'develop' -gem 'ontologies_linked_data', github: 'ncbo/ontologies_linked_data', branch: 'develop' -gem 'sparql-client', github: 'ncbo/sparql-client', tag: 'v6.3.0' +gem 'goo', github: 'ncbo/goo', branch: 'main' +gem 'sparql-client', github: 'ncbo/sparql-client', branch: 'main' +gem 'ncbo_annotator', github: 'ncbo/ncbo_annotator', branch: 'chore/ruby3.2-minitest6-compat' +gem 'ncbo_cron', github: 'ncbo/ncbo_cron', branch: 'chore/ontoportal-lirmm-goo-compat' +gem 'ncbo_ontology_recommender', github: 'ncbo/ncbo_ontology_recommender', branch: 'chore/ruby3.2-minitest6-compat' +gem 'ontologies_linked_data', github: 'ncbo/ontologies_linked_data', branch: 'chore/ontoportal-lirmm-goo-compat' group :development do - # bcrypt_pbkdf and ed35519 is required for capistrano deployments when using ed25519 keys; see https://github.com/miloserdow/capistrano-deploy/issues/42 - gem 'shotgun', github: 'palexander/shotgun', branch: 'ncbo' + gem 'shotgun', github: 'syphax-bouazzouni/shotgun', branch: 'master' gem 'rubocop' end @@ -73,13 +76,14 @@ end group :test do gem 'byebug', '~> 12.0' gem 'crack', '0.4.5' - gem 'minitest', '~> 5.0' - gem 'minitest-hooks', "~> 1.5" + gem 'minitest' + gem 'minitest-hooks' + gem 'minitest-reporters' gem 'minitest-stub_any_instance' + gem 'ontoportal_testkit', github: 'alexskr/ontoportal_testkit', branch: 'main' gem 'rack-test' gem 'simplecov', require: false gem 'simplecov-cobertura' # for codecov.io - gem 'webmock', '~> 3.19.1' + gem 'webmock' gem 'webrick' - gem 'minitest-bisect' -end \ No newline at end of file +end diff --git a/Gemfile.lock b/Gemfile.lock index 7ee73a860..c826e74ea 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,14 +1,24 @@ +GIT + remote: https://github.com/alexskr/ontoportal_testkit.git + revision: b930b550bc8c98ca566c5f71b4f91f6703721240 + branch: main + specs: + ontoportal_testkit (0.1.0) + rake (>= 13.0) + GIT remote: https://github.com/ncbo/goo.git - revision: b92ae7ab3d2fad40a8b4a7563047c7157765472c - branch: develop + revision: 2411deb0143c773b9e6d89b3232c9cca0d50e2bd + branch: main specs: goo (0.0.2) addressable (~> 2.8) pry - rdf (= 1.0.8) + rdf + rdf-raptor + rdf-rdfxml + rdf-vocab redis - request_store rest-client rsolr sparql-client @@ -16,8 +26,8 @@ GIT GIT remote: https://github.com/ncbo/ncbo_annotator.git - revision: 55e8cbfac358b2c40deb0bd963bfe6dee91e8347 - branch: develop + revision: 2b4efe17a95b5be42ead4d4507c50c244ef24e0f + branch: chore/ruby3.2-minitest6-compat specs: ncbo_annotator (0.0.1) goo @@ -27,8 +37,8 @@ GIT GIT remote: https://github.com/ncbo/ncbo_cron.git - revision: 111c7263d8a98b1e8f7c033cb0b7d9c6cc10cd01 - branch: develop + revision: f668a62b60ca6002a45779ac2afd39600ec35f00 + branch: chore/ontoportal-lirmm-goo-compat specs: ncbo_cron (0.0.1) dante @@ -41,12 +51,12 @@ GIT ncbo_annotator ontologies_linked_data redis - rufus-scheduler (~> 2.0.24) + rufus-scheduler (~> 3.9) GIT remote: https://github.com/ncbo/ncbo_ontology_recommender.git - revision: 76d9516adc3c5c6d5c95f21f307bdd60eb3e0acd - branch: develop + revision: 70e49a2d3951b7d326e9ada01a4f6b9bd4df395e + branch: chore/ruby3.2-minitest6-compat specs: ncbo_ontology_recommender (0.0.1) goo @@ -56,12 +66,13 @@ GIT GIT remote: https://github.com/ncbo/ontologies_linked_data.git - revision: 9cae83def8a2a4a9bd1a3a1e8388c595c339ce72 - branch: develop + revision: e7310135a510369384204d873ba8b1c5039fcdbc + branch: chore/ontoportal-lirmm-goo-compat specs: ontologies_linked_data (0.0.1) activesupport bcrypt + down (~> 5.0) goo json libxml-ruby @@ -77,13 +88,12 @@ GIT GIT remote: https://github.com/ncbo/sparql-client.git - revision: 512edc320b43e83971835dc046b4923485e8f70e - tag: v6.3.0 + revision: fa69937120104bafb3d3b8350e4f2df2efb7c247 + branch: main specs: - sparql-client (1.0.1) - json_pure (>= 1.4) - net-http-persistent (= 2.9.4) - rdf (>= 1.0) + sparql-client (3.2.2) + net-http-persistent (~> 4.0, >= 4.0.2) + rdf (~> 3.2, >= 3.2.11) GIT remote: https://github.com/palexander/rack-post-body-to-params.git @@ -94,41 +104,60 @@ GIT activesupport (>= 2.3) GIT - remote: https://github.com/palexander/shotgun.git - revision: db198224aaab2e4cb9b049adccb30e387d88bc3b - branch: ncbo + remote: https://github.com/ruby-rdf/rdf-raptor.git + revision: 6392ceabf71c3233b0f7f0172f662bd4a22cd534 + ref: 6392ceabf71c3233b0f7f0172f662bd4a22cd534 specs: - shotgun (0.9) - rack (>= 1.0) + rdf-raptor (3.3.0) + ffi (~> 1.15) + rdf (~> 3.3) + +GIT + remote: https://github.com/syphax-bouazzouni/shotgun.git + revision: 421f4d0bc2f3193f7cd4b634f5f8ccab09f6b0f7 + branch: master + specs: + shotgun (0.9.2) + rack + rackup GEM remote: https://rubygems.org/ specs: - activesupport (5.2.8.1) - concurrent-ruby (~> 1.0, >= 1.0.2) - i18n (>= 0.7, < 2) - minitest (~> 5.1) - tzinfo (~> 1.1) - addressable (2.8.7) - public_suffix (>= 2.0.2, < 7.0) - airbrussh (1.5.3) + activesupport (8.1.2) + base64 + bigdecimal + concurrent-ruby (~> 1.0, >= 1.3.1) + connection_pool (>= 2.2.5) + drb + i18n (>= 1.6, < 2) + json + logger (>= 1.4.2) + minitest (>= 5.1) + securerandom (>= 0.3) + tzinfo (~> 2.0, >= 2.0.5) + uri (>= 0.13.1) + addressable (2.8.9) + public_suffix (>= 2.0.2, < 8.0) + airbrussh (1.6.1) sshkit (>= 1.6.1, != 1.7.0) + ansi (1.5.0) ast (2.4.3) - backports (3.25.1) base64 (0.3.0) - bcrypt (3.1.20) - bcrypt_pbkdf (1.1.1) - bcrypt_pbkdf (1.1.1-arm64-darwin) - bcrypt_pbkdf (1.1.1-x86_64-darwin) - bigdecimal (3.3.1) + bcp47_spec (0.2.1) + bcrypt (3.1.21) + bcrypt_pbkdf (1.1.2) + bcrypt_pbkdf (1.1.2-arm64-darwin) + bcrypt_pbkdf (1.1.2-x86_64-darwin) + bigdecimal (4.0.1) builder (3.3.0) byebug (12.0.0) - capistrano (3.19.2) + capistrano (3.20.0) airbrussh (>= 1.0.0) i18n rake (>= 10.0.0) sshkit (>= 1.9.0) - capistrano-bundler (2.1.1) + capistrano-bundler (2.2.0) capistrano (~> 3.1) capistrano-locally (0.3.0) capistrano (~> 3.0) @@ -136,38 +165,38 @@ GEM capistrano (~> 3.1) sshkit (~> 1.3) coderay (1.1.3) - concurrent-ruby (1.3.5) - connection_pool (2.5.4) + concurrent-ruby (1.3.6) + connection_pool (3.0.2) crack (0.4.5) rexml - cube-ruby (0.0.3) dante (0.2.0) - date (3.5.0) + date (3.5.1) docile (1.4.1) domain_name (0.6.20240107) + down (5.4.2) + addressable (~> 2.8) drb (2.2.3) ed25519 (1.4.0) - faraday (2.14.0) + et-orbi (1.4.0) + tzinfo + faraday (2.14.1) faraday-net_http (>= 2.0, < 3.5) json logger - faraday-follow_redirects (0.4.0) + faraday-follow_redirects (0.5.0) faraday (>= 1, < 3) - faraday-net_http (3.4.1) - net-http (>= 0.5.0) - faraday-retry (2.3.2) + faraday-net_http (3.4.2) + net-http (~> 0.5) + faraday-retry (2.4.0) faraday (~> 2.0) - ffi (1.17.2) - ffi (1.17.2-aarch64-linux-gnu) - ffi (1.17.2-aarch64-linux-musl) - ffi (1.17.2-arm-linux-gnu) - ffi (1.17.2-arm-linux-musl) - ffi (1.17.2-arm64-darwin) - ffi (1.17.2-x86-linux-gnu) - ffi (1.17.2-x86-linux-musl) - ffi (1.17.2-x86_64-darwin) - ffi (1.17.2-x86_64-linux-gnu) - ffi (1.17.2-x86_64-linux-musl) + ffi (1.17.3) + ffi (1.17.3-aarch64-linux-gnu) + ffi (1.17.3-arm64-darwin) + ffi (1.17.3-x86_64-darwin) + ffi (1.17.3-x86_64-linux-gnu) + fugit (1.12.1) + et-orbi (~> 1.4) + raabro (~> 1.4) gapic-common (1.1.0) faraday (>= 1.9, < 3.a) faraday-retry (>= 1.0, < 3.a) @@ -194,19 +223,18 @@ GEM faraday (>= 1.0, < 3.a) google-cloud-errors (1.5.0) google-logging-utils (0.2.0) - google-protobuf (3.25.8) - google-protobuf (3.25.8-aarch64-linux) - google-protobuf (3.25.8-arm64-darwin) - google-protobuf (3.25.8-x86-linux) - google-protobuf (3.25.8-x86_64-darwin) - google-protobuf (3.25.8-x86_64-linux) + google-protobuf (3.25.3) + google-protobuf (3.25.3-aarch64-linux) + google-protobuf (3.25.3-arm64-darwin) + google-protobuf (3.25.3-x86_64-darwin) + google-protobuf (3.25.3-x86_64-linux) googleapis-common-protos (1.8.0) google-protobuf (>= 3.18, < 5.a) googleapis-common-protos-types (~> 1.20) grpc (~> 1.41) googleapis-common-protos-types (1.20.0) google-protobuf (>= 3.18, < 5.a) - googleauth (1.15.1) + googleauth (1.16.2) faraday (>= 1.0, < 3.a) google-cloud-env (~> 2.2) google-logging-utils (~> 0.1) @@ -214,51 +242,50 @@ GEM multi_json (~> 1.11) os (>= 0.9, < 2.0) signet (>= 0.16, < 2.a) - grpc (1.76.0) - google-protobuf (>= 3.25, < 5.0) - googleapis-common-protos-types (~> 1.0) - grpc (1.76.0-aarch64-linux-gnu) - google-protobuf (>= 3.25, < 5.0) - googleapis-common-protos-types (~> 1.0) - grpc (1.76.0-aarch64-linux-musl) + grpc (1.70.1) google-protobuf (>= 3.25, < 5.0) googleapis-common-protos-types (~> 1.0) - grpc (1.76.0-arm64-darwin) + grpc (1.70.1-aarch64-linux) google-protobuf (>= 3.25, < 5.0) googleapis-common-protos-types (~> 1.0) - grpc (1.76.0-x86-linux-gnu) + grpc (1.70.1-arm64-darwin) google-protobuf (>= 3.25, < 5.0) googleapis-common-protos-types (~> 1.0) - grpc (1.76.0-x86-linux-musl) + grpc (1.70.1-x86_64-darwin) google-protobuf (>= 3.25, < 5.0) googleapis-common-protos-types (~> 1.0) - grpc (1.76.0-x86_64-darwin) - google-protobuf (>= 3.25, < 5.0) - googleapis-common-protos-types (~> 1.0) - grpc (1.76.0-x86_64-linux-gnu) - google-protobuf (>= 3.25, < 5.0) - googleapis-common-protos-types (~> 1.0) - grpc (1.76.0-x86_64-linux-musl) + grpc (1.70.1-x86_64-linux) google-protobuf (>= 3.25, < 5.0) googleapis-common-protos-types (~> 1.0) haml (5.2.2) temple (>= 0.8.0) tilt - hashdiff (1.2.0) + hashdiff (1.2.1) + htmlentities (4.4.2) http-accept (1.7.0) http-cookie (1.1.0) domain_name (~> 0.5) - i18n (1.14.7) + i18n (1.14.8) concurrent-ruby (~> 1.0) - json (2.15.2) - json-schema (2.8.1) - addressable (>= 2.4) - json_pure (2.8.1) + io-console (0.8.2) + json (2.19.2) + json-canonicalization (0.4.0) + json-ld (3.2.5) + htmlentities (~> 4.3) + json-canonicalization (~> 0.3, >= 0.3.2) + link_header (~> 0.0, >= 0.0.8) + multi_json (~> 1.15) + rack (>= 2.2, < 4) + rdf (~> 3.2, >= 3.2.10) + json-schema (6.2.0) + addressable (~> 2.8) + bigdecimal (>= 3.1, < 5) jwt (3.1.2) base64 kgio (2.11.4) language_server-protocol (3.17.0.5) libxml-ruby (5.0.5) + link_header (0.0.8) lint_roller (1.1.0) logger (1.7.0) macaddr (1.7.2) @@ -269,32 +296,38 @@ GEM net-imap net-pop net-smtp + mcp (0.8.0) + json-schema (>= 4.1) method_source (1.1.0) mime-types (3.7.0) logger mime-types-data (~> 3.2025, >= 3.2025.0507) - mime-types-data (3.2025.0924) + mime-types-data (3.2026.0317) mini_mime (1.1.5) - minitest (5.26.0) - minitest-bisect (1.7.0) - minitest-server (~> 1.0) - path_expander (~> 1.1) - minitest-hooks (1.5.2) - minitest (> 5.3) - minitest-server (1.0.8) + minitest (6.0.2) drb (~> 2.0) - minitest (~> 5.16) + prism (~> 1.5) + minitest-hooks (1.5.3) + minitest (> 5.3) + minitest-reporters (1.7.1) + ansi + builder + minitest (>= 5.0) + ruby-progressbar minitest-stub_any_instance (1.0.3) mlanett-redis-lock (0.2.7) redis - multi_json (1.17.0) + multi_json (1.19.1) + mustermann (3.0.4) + ruby2_keywords (~> 0.0.1) net-ftp (0.3.9) net-protocol time - net-http (0.7.0) - uri - net-http-persistent (2.9.4) - net-imap (0.5.12) + net-http (0.9.1) + uri (>= 0.11.1) + net-http-persistent (4.0.8) + connection_pool (>= 2.2.4, < 4) + net-imap (0.6.3) date net-protocol net-pop (0.1.2) @@ -309,60 +342,83 @@ GEM net-protocol net-ssh (7.3.0) netrc (0.11.0) - newrelic_rpm (9.19.0) - oj (3.16.12) + oj (3.16.15) bigdecimal (>= 3.0) ostruct (>= 0.2) omni_logger (0.1.4) logger os (1.1.4) ostruct (0.6.3) + pandoc-ruby (2.1.10) parallel (1.27.0) parseconfig (1.1.2) - parser (3.3.8.0) + parser (3.3.10.2) ast (~> 2.4.1) racc - path_expander (1.1.3) pony (1.13.1) mail (>= 2.0) - prism (1.4.0) - pry (0.15.2) + prism (1.9.0) + pry (0.16.0) coderay (~> 1.1) method_source (~> 1.0) - public_suffix (6.0.2) + reline (>= 0.6.0) + public_suffix (7.0.5) + raabro (1.4.0) racc (1.8.1) - rack (1.6.13) + rack (3.2.5) rack-accept (0.4.5) rack (>= 0.4) - rack-attack (6.6.1) - rack (>= 1.0, < 3) - rack-cache (1.13.0) + rack-attack (6.8.0) + rack (>= 1.0, < 4) + rack-cache (1.17.0) rack (>= 0.4) - rack-cors (1.0.6) - rack (>= 1.6.0) - rack-mini-profiler (4.0.0) + rack-contrib (2.5.0) + rack (< 4) + rack-cors (3.0.0) + logger + rack (>= 3.0.14) + rack-mini-profiler (4.0.1) rack (>= 1.2.0) - rack-protection (1.5.5) - rack + rack-protection (4.2.1) + base64 (>= 0.1.0) + logger (>= 1.6.0) + rack (>= 3.0.0, < 4) + rack-session (2.1.1) + base64 (>= 0.1.0) + rack (>= 3.0.0) rack-test (2.2.0) rack (>= 1.3) rack-timeout (0.7.0) + rackup (2.3.1) + rack (>= 3) rainbow (3.1.1) raindrops (0.20.1) - rake (10.5.0) - rdf (1.0.8) - addressable (>= 2.2) - redcarpet (3.6.1) + rake (13.3.1) + rdf (3.3.1) + bcp47_spec (~> 0.2) + link_header (~> 0.0, >= 0.0.8) + rdf-rdfxml (3.3.0) + builder (~> 3.2, >= 3.2.4) + htmlentities (~> 4.3) + rdf (~> 3.3) + rdf-xsd (~> 3.3) + rdf-vocab (3.3.3) + rdf (~> 3.3) + rdf-xsd (3.3.0) + rdf (~> 3.3) + rexml (~> 3.2) redis (5.4.1) redis-client (>= 0.22.0) - redis-client (0.26.1) + redis-client (0.28.0) connection_pool redis-rack-cache (2.2.1) rack-cache (>= 1.10, < 2) redis-store (>= 1.6, < 2) redis-store (1.11.0) redis (>= 4, < 6) - regexp_parser (2.10.0) + regexp_parser (2.11.3) + reline (0.6.3) + io-console (~> 0.5) request_store (1.7.0) rack (>= 1.4) rest-client (2.1.0) @@ -370,29 +426,32 @@ GEM http-cookie (>= 1.0.2, < 2.0) mime-types (>= 1.16, < 4.0) netrc (~> 0.8) - rexml (3.4.1) + rexml (3.4.4) rsolr (2.6.0) builder (>= 2.1.2) faraday (>= 0.9, < 3, != 2.0.0) - rubocop (1.78.0) + rubocop (1.85.1) json (~> 2.3) language_server-protocol (~> 3.17.0.2) lint_roller (~> 1.1.0) + mcp (~> 0.6) parallel (~> 1.10) parser (>= 3.3.0.2) rainbow (>= 2.2.2, < 4.0) regexp_parser (>= 2.9.3, < 3.0) - rubocop-ast (>= 1.45.1, < 2.0) + rubocop-ast (>= 1.49.0, < 2.0) ruby-progressbar (~> 1.7) unicode-display_width (>= 2.4.0, < 4.0) - rubocop-ast (1.46.0) + rubocop-ast (1.49.0) parser (>= 3.3.7.2) - prism (~> 1.4) + prism (~> 1.7) ruby-progressbar (1.13.0) ruby-xxHash (0.4.0.2) + ruby2_keywords (0.0.5) rubyzip (3.2.2) - rufus-scheduler (2.0.24) - tzinfo (>= 0.3.22) + rufus-scheduler (3.9.2) + fugit (~> 1.1, >= 1.11.1) + securerandom (0.4.1) signet (0.21.0) addressable (~> 2.8) faraday (>= 0.17.5, < 3.a) @@ -402,25 +461,25 @@ GEM docile (~> 1.1) simplecov-html (~> 0.11) simplecov_json_formatter (~> 0.1) - simplecov-cobertura (3.0.0) + simplecov-cobertura (3.1.0) rexml simplecov (~> 0.19) simplecov-html (0.13.2) simplecov_json_formatter (0.1.4) - sinatra (1.4.8) - rack (~> 1.5) - rack-protection (~> 1.4) - tilt (>= 1.3, < 3) - sinatra-advanced-routes (0.5.3) - sinatra (~> 1.0) - sinatra-contrib (1.4.7) - backports (>= 2.0) - multi_json - rack-protection - rack-test - sinatra (~> 1.4.0) - tilt (>= 1.3, < 3) - sshkit (1.24.0) + sinatra (4.2.1) + logger (>= 1.6.0) + mustermann (~> 3.0) + rack (>= 3.0.0, < 4) + rack-protection (= 4.2.1) + rack-session (>= 2.0.0, < 3) + tilt (~> 2.0) + sinatra-contrib (4.2.1) + multi_json (>= 0.0.2) + mustermann (~> 3.0) + rack-protection (= 4.2.1) + sinatra (= 4.2.1) + tilt (~> 2.0) + sshkit (1.25.0) base64 logger net-scp (>= 1.1.2) @@ -428,17 +487,16 @@ GEM net-ssh (>= 2.8.0) ostruct systemu (2.6.5) - temple (0.10.3) - thread_safe (0.3.6) - tilt (2.6.1) - time (0.4.1) + temple (0.10.4) + tilt (2.7.0) + time (0.4.2) date - timeout (0.4.4) - tzinfo (1.2.11) - thread_safe (~> 0.1) - unicode-display_width (3.1.4) - unicode-emoji (~> 4.0, >= 4.0.4) - unicode-emoji (4.0.4) + timeout (0.6.1) + tzinfo (2.0.6) + concurrent-ruby (~> 1.0) + unicode-display_width (3.2.0) + unicode-emoji (~> 4.1) + unicode-emoji (4.2.0) unicorn (6.1.0) kgio (~> 2.6) raindrops (~> 0.7) @@ -448,30 +506,21 @@ GEM uri (1.1.1) uuid (2.3.9) macaddr (~> 1.0) - webmock (3.19.1) + webmock (3.26.1) addressable (>= 2.8.0) crack (>= 0.3.2) hashdiff (>= 0.4.0, < 2.0.0) - webrick (1.9.1) + webrick (1.9.2) PLATFORMS - aarch64-linux aarch64-linux-gnu - aarch64-linux-musl - arm-linux-gnu - arm-linux-musl arm64-darwin ruby - x86-linux - x86-linux-gnu - x86-linux-musl x86_64-darwin - x86_64-linux x86_64-linux-gnu - x86_64-linux-musl DEPENDENCIES - activesupport (~> 5) + activesupport bcrypt_pbkdf (>= 1.0, < 2.0) bigdecimal byebug (~> 12.0) @@ -480,51 +529,247 @@ DEPENDENCIES capistrano-locally capistrano-rbenv crack (= 0.4.5) - cube-ruby ed25519 (>= 1.2, < 2.0) ffi goo! + google-protobuf (= 3.25.3) + grpc (= 1.70.1) haml (~> 5.2.2) - json-schema (~> 2.0) - minitest (~> 5.0) - minitest-bisect - minitest-hooks (~> 1.5) + json-ld (~> 3.2.0) + json-schema + minitest + minitest-hooks + minitest-reporters minitest-stub_any_instance multi_json ncbo_annotator! ncbo_cron! ncbo_ontology_recommender! - newrelic_rpm + net-ftp oj ontologies_linked_data! + ontoportal_testkit! + pandoc-ruby + parallel parseconfig rack - rack-accept (~> 0.4) - rack-attack (~> 6.6.1) - rack-cache (~> 1.13.0) + rack-accept + rack-attack + rack-cache + rack-contrib rack-cors rack-mini-profiler rack-post-body-to-params! rack-test rack-timeout - rake (~> 10.0) - redcarpet + rackup + rake + rdf-raptor! redis - redis-rack-cache (~> 2.0) - redis-store (~> 1.10) + redis-rack-cache + redis-store + request_store rexml rubocop shotgun! simplecov simplecov-cobertura - sinatra (~> 1.0) - sinatra-advanced-routes - sinatra-contrib (~> 1.0) + sinatra + sinatra-contrib sparql-client! unicorn unicorn-worker-killer - webmock (~> 3.19.1) + webmock webrick +CHECKSUMS + activesupport (8.1.2) sha256=88842578ccd0d40f658289b0e8c842acfe9af751afee2e0744a7873f50b6fdae + addressable (2.8.9) sha256=cc154fcbe689711808a43601dee7b980238ce54368d23e127421753e46895485 + airbrussh (1.6.1) sha256=9a5fc95583cefe722054a016d26ff0338cf00072b031b829086dde2039d5836a + ansi (1.5.0) sha256=5408253274e33d9d27d4a98c46d2998266fd51cba58a7eb9d08f50e57ed23592 + ast (2.4.3) sha256=954615157c1d6a382bc27d690d973195e79db7f55e9765ac7c481c60bdb4d383 + base64 (0.3.0) sha256=27337aeabad6ffae05c265c450490628ef3ebd4b67be58257393227588f5a97b + bcp47_spec (0.2.1) sha256=3fd62edf96c126bd9624e4319ac74082a966081859d1ee0ef3c3041640a37810 + bcrypt (3.1.21) sha256=5964613d750a42c7ee5dc61f7b9336fb6caca429ba4ac9f2011609946e4a2dcf + bcrypt_pbkdf (1.1.2) sha256=c2414c23ce66869b3eb9f643d6a3374d8322dfb5078125c82792304c10b94cf6 + bcrypt_pbkdf (1.1.2-arm64-darwin) sha256=afdd6feb6ed5a97b8e44caacb3f2d641b98af78e6a516d4a3520b69af5cf9fea + bcrypt_pbkdf (1.1.2-x86_64-darwin) sha256=35f5639d0058e6c2cc2f856f9c0b14080543268d3047abe6bc81c513093caa0e + bigdecimal (4.0.1) sha256=8b07d3d065a9f921c80ceaea7c9d4ae596697295b584c296fe599dd0ad01c4a7 + builder (3.3.0) sha256=497918d2f9dca528fdca4b88d84e4ef4387256d984b8154e9d5d3fe5a9c8835f + byebug (12.0.0) sha256=d4a150d291cca40b66ec9ca31f754e93fed8aa266a17335f71bb0afa7fca1a1e + capistrano (3.20.0) sha256=0113e58dda99add0342e56a244f664734c59f442c5ed734f5303b0b559b479c9 + capistrano-bundler (2.2.0) sha256=47b4cf2ea17ea132bb0a5cabc5663443f5190a54f4da5b322d04e1558ff1468c + capistrano-locally (0.3.0) sha256=ad44252f19641e8dd980f7cb0241e9ac11919b1f4cbdb642d272a6d0edcb84eb + capistrano-rbenv (2.2.0) sha256=3c8f39b7c624f3806630dcb475484bb3579aef07a40efe85089d83f64b0c35f5 + coderay (1.1.3) sha256=dc530018a4684512f8f38143cd2a096c9f02a1fc2459edcfe534787a7fc77d4b + concurrent-ruby (1.3.6) sha256=6b56837e1e7e5292f9864f34b69c5a2cbc75c0cf5338f1ce9903d10fa762d5ab + connection_pool (3.0.2) sha256=33fff5ba71a12d2aa26cb72b1db8bba2a1a01823559fb01d29eb74c286e62e0a + crack (0.4.5) sha256=798416fb29b8c9f655d139d5559169b39c4a0a3b8f8f39b7f670eec1af9b21b3 + dante (0.2.0) sha256=939776f04b4d253ffbbcf53341631aa2ee6e6cf314dedade2e60ac43b40a6fe6 + date (3.5.1) sha256=750d06384d7b9c15d562c76291407d89e368dda4d4fff957eb94962d325a0dc0 + docile (1.4.1) sha256=96159be799bfa73cdb721b840e9802126e4e03dfc26863db73647204c727f21e + domain_name (0.6.20240107) sha256=5f693b2215708476517479bf2b3802e49068ad82167bcd2286f899536a17d933 + down (5.4.2) sha256=516e5e01e7a96214a7e2cd155aac6f700593038ae6c857c0f4a05413b1c58acf + drb (2.2.3) sha256=0b00d6fdb50995fe4a45dea13663493c841112e4068656854646f418fda13373 + ed25519 (1.4.0) sha256=16e97f5198689a154247169f3453ef4cfd3f7a47481fde0ae33206cdfdcac506 + et-orbi (1.4.0) sha256=6c7e3c90779821f9e3b324c5e96fda9767f72995d6ae435b96678a4f3e2de8bc + faraday (2.14.1) sha256=a43cceedc1e39d188f4d2cdd360a8aaa6a11da0c407052e426ba8d3fb42ef61c + faraday-follow_redirects (0.5.0) sha256=5cde93c894b30943a5d2b93c2fe9284216a6b756f7af406a1e55f211d97d10ad + faraday-net_http (3.4.2) sha256=f147758260d3526939bf57ecf911682f94926a3666502e24c69992765875906c + faraday-retry (2.4.0) sha256=7b79c48fb7e56526faf247b12d94a680071ff40c9fda7cf1ec1549439ad11ebe + ffi (1.17.3) sha256=0e9f39f7bb3934f77ad6feab49662be77e87eedcdeb2a3f5c0234c2938563d4c + ffi (1.17.3-aarch64-linux-gnu) sha256=28ad573df26560f0aedd8a90c3371279a0b2bd0b4e834b16a2baa10bd7a97068 + ffi (1.17.3-arm64-darwin) sha256=0c690555d4cee17a7f07c04d59df39b2fba74ec440b19da1f685c6579bb0717f + ffi (1.17.3-x86_64-darwin) sha256=1f211811eb5cfaa25998322cdd92ab104bfbd26d1c4c08471599c511f2c00bb5 + ffi (1.17.3-x86_64-linux-gnu) sha256=3746b01f677aae7b16dc1acb7cb3cc17b3e35bdae7676a3f568153fb0e2c887f + fugit (1.12.1) sha256=5898f478ede9b415f0804e42b8f3fd53f814bd85eebffceebdbc34e1107aaf68 + gapic-common (1.1.0) sha256=3270ab3c5135012a4ab4d8848f945cf35014192f24504cdb40c66fc67f1beaa3 + get_process_mem (0.2.7) sha256=4afd3c3641dd6a817c09806c7d6d509d8a9984512ac38dea8b917426bbf77eba + goo (0.0.2) + google-analytics-data (0.7.2) sha256=5e4bf6dc575c7725c2b32541725749890a88e0a64ff0ad7e8a73f75ad5a1bbc9 + google-analytics-data-v1beta (0.17.0) sha256=1145d30d794bcf6bf8b723140a0ee2c445e740b82cf4051a31d992e7393168a6 + google-cloud-core (1.8.0) sha256=e572edcbf189cfcab16590628a516cec3f4f63454b730e59f0b36575120281cf + google-cloud-env (2.3.1) sha256=0faac01eb27be78c2591d64433663b1a114f8f7af55a4f819755426cac9178e7 + google-cloud-errors (1.5.0) sha256=b56be28b8c10628125214dde571b925cfcebdbc58619e598250c37a2114f7b4b + google-logging-utils (0.2.0) sha256=675462b4ea5affa825a3442694ca2d75d0069455a1d0956127207498fca3df7b + google-protobuf (3.25.3) sha256=39bd97cbc7631905e76cdf8f1bf3dda1c3d05200d7e23f575aced78930fbddd6 + google-protobuf (3.25.3-aarch64-linux) sha256=5ea9d20d60e5d3bef8d881b426946345e5ac6cf4779ac81cd900e45f40567243 + google-protobuf (3.25.3-arm64-darwin) sha256=c42cddd21c4f09fd756fe0efd70ab6c8006dd67ffbb04e99fe7310f49923d18c + google-protobuf (3.25.3-x86_64-darwin) sha256=13d27e96e89835f642c444e32414fd50fabc29a125d78760ad067d6536214f02 + google-protobuf (3.25.3-x86_64-linux) sha256=ceeba879d9313a2bd0600a97d6fe3cf529a9b37d12ca026f891996c118b7ffb2 + googleapis-common-protos (1.8.0) sha256=bfe89cb75d1a8f13e4591d262a20333e145481d803adb74dd13ac0517decdffe + googleapis-common-protos-types (1.20.0) sha256=5e374b06bcfc7e13556e7c0d87b99f1fa3d42de6396a1de3d8fc13aefb4dd07f + googleauth (1.16.2) sha256=15009502e2e38af71948cda918f230e27d327f6882a1e47967a5a4664930a638 + grpc (1.70.1) sha256=174594605c96df3caed44a83221665aa6e11f554e56028f89bef82c07ffb83cb + grpc (1.70.1-aarch64-linux) sha256=48e0b22b8b96e61ca7054a7fea894a4845498e6bf366b50eff03e588f714ed96 + grpc (1.70.1-arm64-darwin) sha256=eeb6758dd58135e4e5fcd78726b9a18d34d7313e41bc81528ff4b3dce65cf525 + grpc (1.70.1-x86_64-darwin) sha256=628cb929542c277b6e5f638b6b8575b3bdcde250a2a70bddf8c0be1bf77e6781 + grpc (1.70.1-x86_64-linux) sha256=ed12eea749127119c9761a58ba17ce92aadbc35b0b4fa27e4bd8ec84047d63be + haml (5.2.2) sha256=6e759246556145642ef832d670fc06f9bd8539159a0e600847a00291dd7aae0c + hashdiff (1.2.1) sha256=9c079dbc513dfc8833ab59c0c2d8f230fa28499cc5efb4b8dd276cf931457cd1 + htmlentities (4.4.2) sha256=bbafbdf69f2eca9262be4efef7e43e6a1de54c95eb600f26984f71d2fe96c5c3 + http-accept (1.7.0) sha256=c626860682bfbb3b46462f8c39cd470fd7b0584f61b3cc9df5b2e9eb9972a126 + http-cookie (1.1.0) sha256=38a5e60d1527eebc396831b8c4b9455440509881219273a6c99943d29eadbb19 + i18n (1.14.8) sha256=285778639134865c5e0f6269e0b818256017e8cde89993fdfcbfb64d088824a5 + io-console (0.8.2) sha256=d6e3ae7a7cc7574f4b8893b4fca2162e57a825b223a177b7afa236c5ef9814cc + json (2.19.2) sha256=e7e1bd318b2c37c4ceee2444841c86539bc462e81f40d134cf97826cb14e83cf + json-canonicalization (0.4.0) sha256=73ea88b68f210d1a09c2116d4cd1ff5a39684c6a409f7ccac70d5b1a426a8bef + json-ld (3.2.5) sha256=98b96f1831b0fe9c7d2568a7d43b64f6b8c3f5892d55ccf91640e32a99c273fc + json-schema (6.2.0) sha256=e8bff46ed845a22c1ab2bd0d7eccf831c01fe23bb3920caa4c74db4306813666 + jwt (3.1.2) sha256=af6991f19a6bb4060d618d9add7a66f0eeb005ac0bc017cd01f63b42e122d535 + kgio (2.11.4) sha256=bda7a2146115998a5b07154e708e0ac02c38dcee7e793c33e2e14f600fdfffc6 + language_server-protocol (3.17.0.5) sha256=fd1e39a51a28bf3eec959379985a72e296e9f9acfce46f6a79d31ca8760803cc + libxml-ruby (5.0.5) sha256=f1bc07152982df555d70159a694ee2a53539de2cdad4b3c8a447fbb15e7e4e9a + link_header (0.0.8) sha256=15c65ce43b29f739b30d05e5f25c22c23797e89cf6f905dbb595fb4c70cb55f9 + lint_roller (1.1.0) sha256=2c0c845b632a7d172cb849cc90c1bce937a28c5c8ccccb50dfd46a485003cc87 + logger (1.7.0) sha256=196edec7cc44b66cfb40f9755ce11b392f21f7967696af15d274dde7edff0203 + macaddr (1.7.2) sha256=da377809968bbc1160bf02a999e916bb3255000007291d9d1a49a93ceedadf82 + mail (2.9.0) sha256=6fa6673ecd71c60c2d996260f9ee3dd387d4673b8169b502134659ece6d34941 + mcp (0.8.0) sha256=ae8bd146bb8e168852866fd26f805f52744f6326afb3211e073f78a95e0c34fb + method_source (1.1.0) sha256=181301c9c45b731b4769bc81e8860e72f9161ad7d66dd99103c9ab84f560f5c5 + mime-types (3.7.0) sha256=dcebf61c246f08e15a4de34e386ebe8233791e868564a470c3fe77c00eed5e56 + mime-types-data (3.2026.0317) sha256=77f078a4d8631d52b842ba77099734b06eddb7ad339d792e746d2272b67e511b + mini_mime (1.1.5) sha256=8681b7e2e4215f2a159f9400b5816d85e9d8c6c6b491e96a12797e798f8bccef + minitest (6.0.2) sha256=db6e57956f6ecc6134683b4c87467d6dd792323c7f0eea7b93f66bd284adbc3d + minitest-hooks (1.5.3) sha256=ef50dd3bf47e6d1646befc358c640c71ca41f5650f0036b4c69929a44d6f32c4 + minitest-reporters (1.7.1) sha256=5060413a0c95b8c32fe73e0606f3631c173a884d7900e50013e15094eb50562c + minitest-stub_any_instance (1.0.3) sha256=d53ca295d173817f828789ac44ad3c2a4a0752166eea7a63c9ae026d9e7660e8 + mlanett-redis-lock (0.2.7) sha256=55fea6e6fb9d9241d921187dd93f0d4ccc116138f873e5d5ee729f4c5aa9aad3 + multi_json (1.19.1) sha256=7aefeff8f2c854bf739931a238e4aea64592845e0c0395c8a7d2eea7fdd631b7 + mustermann (3.0.4) sha256=85fadcb6b3c6493a8b511b42426f904b7f27b282835502233dd154daab13aa22 + ncbo_annotator (0.0.1) + ncbo_cron (0.0.1) + ncbo_ontology_recommender (0.0.1) + net-ftp (0.3.9) sha256=307817ccf7f428f79d083f7e36dbb46a9d1d375e0d23027824de1866f0b13b65 + net-http (0.9.1) sha256=25ba0b67c63e89df626ed8fac771d0ad24ad151a858af2cc8e6a716ca4336996 + net-http-persistent (4.0.8) sha256=ef3de8319d691537b329053fae3a33195f8b070bbbfae8bf1a58c796081960e6 + net-imap (0.6.3) sha256=9bab75f876596d09ee7bf911a291da478e0cd6badc54dfb82874855ccc82f2ad + net-pop (0.1.2) sha256=848b4e982013c15b2f0382792268763b748cce91c9e91e36b0f27ed26420dff3 + net-protocol (0.2.2) sha256=aa73e0cba6a125369de9837b8d8ef82a61849360eba0521900e2c3713aa162a8 + net-scp (4.1.0) sha256=a99b0b92a1e5d360b0de4ffbf2dc0c91531502d3d4f56c28b0139a7c093d1a5d + net-sftp (4.0.0) sha256=65bb91c859c2f93b09826757af11b69af931a3a9155050f50d1b06d384526364 + net-smtp (0.5.1) sha256=ed96a0af63c524fceb4b29b0d352195c30d82dd916a42f03c62a3a70e5b70736 + net-ssh (7.3.0) sha256=172076c4b30ce56fb25a03961b0c4da14e1246426401b0f89cba1a3b54bf3ef0 + netrc (0.11.0) sha256=de1ce33da8c99ab1d97871726cba75151113f117146becbe45aa85cb3dabee3f + oj (3.16.15) sha256=4d3324cac3e8fef54c0fa250b2af26a16dadd9f9788a1d6b1b2098b793a1b2cd + omni_logger (0.1.4) sha256=b61596f7d96aa8426929e46c3500558d33e838e1afd7f4735244feb4d082bb3e + ontologies_linked_data (0.0.1) + ontoportal_testkit (0.1.0) + os (1.1.4) sha256=57816d6a334e7bd6aed048f4b0308226c5fb027433b67d90a9ab435f35108d3f + ostruct (0.6.3) sha256=95a2ed4a4bd1d190784e666b47b2d3f078e4a9efda2fccf18f84ddc6538ed912 + pandoc-ruby (2.1.10) sha256=37653d6b5e71657fb25b3cb230e6eebbfb8c925c7f1fcf69dfb6b929d12b74b2 + parallel (1.27.0) sha256=4ac151e1806b755fb4e2dc2332cbf0e54f2e24ba821ff2d3dcf86bf6dc4ae130 + parseconfig (1.1.2) sha256=e52247d15070fb47f9e58f44f7888d1e7f65775274cd60f9ab4b7acd7943b291 + parser (3.3.10.2) sha256=6f60c84aa4bdcedb6d1a2434b738fe8a8136807b6adc8f7f53b97da9bc4e9357 + pony (1.13.1) sha256=ab507c8ade8b35de96f1e75c0ae4566a3c40ac8a0d5101433969b6fd29c718a7 + prism (1.9.0) sha256=7b530c6a9f92c24300014919c9dcbc055bf4cdf51ec30aed099b06cd6674ef85 + pry (0.16.0) sha256=d76c69065698ed1f85e717bd33d7942c38a50868f6b0673c636192b3d1b6054e + public_suffix (7.0.5) sha256=1a8bb08f1bbea19228d3bed6e5ed908d1cb4f7c2726d18bd9cadf60bc676f623 + raabro (1.4.0) sha256=d4fa9ff5172391edb92b242eed8be802d1934b1464061ae5e70d80962c5da882 + racc (1.8.1) sha256=4a7f6929691dbec8b5209a0b373bc2614882b55fc5d2e447a21aaa691303d62f + rack (3.2.5) sha256=4cbd0974c0b79f7a139b4812004a62e4c60b145cba76422e288ee670601ed6d3 + rack-accept (0.4.5) sha256=66247b5449db64ebb93ae2ec4af4764b87d1ae8a7463c7c68893ac13fa8d4da2 + rack-attack (6.8.0) sha256=f2499fdebf85bcc05573a22dff57d24305ac14ec2e4156cd3c28d47cafeeecf2 + rack-cache (1.17.0) sha256=49592f3ef2173b0f5524df98bb801fb411e839869e7ce84ac428dc492bf0eb90 + rack-contrib (2.5.0) sha256=51bd2ce82b8a3270f9173130c4cdaea72aab8b03dce8cd6af1c4344d84a32d02 + rack-cors (3.0.0) sha256=7b95be61db39606906b61b83bd7203fa802b0ceaaad8fcb2fef39e097bf53f68 + rack-mini-profiler (4.0.1) sha256=485810c23211f908196c896ea10cad72ed68780ee2998bec1f1dfd7558263d78 + rack-post-body-to-params (0.1.8) + rack-protection (4.2.1) sha256=cf6e2842df8c55f5e4d1a4be015e603e19e9bc3a7178bae58949ccbb58558bac + rack-session (2.1.1) sha256=0b6dc07dea7e4b583f58a48e8b806d4c9f1c6c9214ebc202ec94562cbea2e4e9 + rack-test (2.2.0) sha256=005a36692c306ac0b4a9350355ee080fd09ddef1148a5f8b2ac636c720f5c463 + rack-timeout (0.7.0) sha256=757337e9793cca999bb73a61fe2a7d4280aa9eefbaf787ce3b98d860749c87d9 + rackup (2.3.1) sha256=6c79c26753778e90983761d677a48937ee3192b3ffef6bc963c0950f94688868 + rainbow (3.1.1) sha256=039491aa3a89f42efa1d6dec2fc4e62ede96eb6acd95e52f1ad581182b79bc6a + raindrops (0.20.1) sha256=aa0eb9ff6834f2d9e232ba688bd49cb30be893bc5a3452e74722c94c1fab4730 + rake (13.3.1) sha256=8c9e89d09f66a26a01264e7e3480ec0607f0c497a861ef16063604b1b08eb19c + rdf (3.3.1) sha256=dda6a2c95198915fc63d66ee270e35d4a76d431720747a2cf97ecd92062fa150 + rdf-raptor (3.3.0) + rdf-rdfxml (3.3.0) sha256=11647f6111b97b6a9b82413bd9810d4bb5524aa7dd06b3c1330bf58ec3aa6a9a + rdf-vocab (3.3.3) sha256=d3b642edb37be7b37b73cafa9e01d55762f99292838e7b0868a3575bd297bf8b + rdf-xsd (3.3.0) sha256=fab51d27b20344237d9b622ef32e83e4c44940840bfc76a245ce6b6abba44772 + redis (5.4.1) sha256=b5e675b57ad22b15c9bcc765d5ac26f60b675408af916d31527af9bd5a81faae + redis-client (0.28.0) sha256=888892f9cd8787a41c0ece00bdf5f556dfff7770326ce40bb2bc11f1bfec824b + redis-rack-cache (2.2.1) sha256=9c72978a6354e02efeb2f933dd32c94a4a13f1137dac492442126bf25cc19970 + redis-store (1.11.0) sha256=edc4f3e239dcd1fdd9905584e6b1e623a84618e14436e6e8a07c70891008eda4 + regexp_parser (2.11.3) sha256=ca13f381a173b7a93450e53459075c9b76a10433caadcb2f1180f2c741fc55a4 + reline (0.6.3) sha256=1198b04973565b36ec0f11542ab3f5cfeeec34823f4e54cebde90968092b1835 + request_store (1.7.0) sha256=e1b75d5346a315f452242a68c937ef8e48b215b9453a77a6c0acdca2934c88cb + rest-client (2.1.0) sha256=35a6400bdb14fae28596618e312776c158f7ebbb0ccad752ff4fa142bf2747e3 + rexml (3.4.4) sha256=19e0a2c3425dfbf2d4fc1189747bdb2f849b6c5e74180401b15734bc97b5d142 + rsolr (2.6.0) sha256=4b3bcea772cac300562775c20eeddedf63a6b7516a070cb6fbde000b09cfe12b + rubocop (1.85.1) sha256=3dbcf9e961baa4c376eeeb2a03913dca5e3987033b04d38fa538aa1e7406cc77 + rubocop-ast (1.49.0) sha256=49c3676d3123a0923d333e20c6c2dbaaae2d2287b475273fddee0c61da9f71fd + ruby-progressbar (1.13.0) sha256=80fc9c47a9b640d6834e0dc7b3c94c9df37f08cb072b7761e4a71e22cff29b33 + ruby-xxHash (0.4.0.2) sha256=201d8305ec1bd0bc32abeaecf7b423755dd1f45f4f4d02ef793b6bb71bf20684 + ruby2_keywords (0.0.5) sha256=ffd13740c573b7301cf7a2e61fc857b2a8e3d3aff32545d6f8300d8bae10e3ef + rubyzip (3.2.2) sha256=c0ed99385f0625415c8f05bcae33fe649ed2952894a95ff8b08f26ca57ea5b3c + rufus-scheduler (3.9.2) sha256=55fa9e4db0ff69d7f38c804f17baba0c9bce5cba39984ae3c5cf6c039d1323b9 + securerandom (0.4.1) sha256=cc5193d414a4341b6e225f0cb4446aceca8e50d5e1888743fac16987638ea0b1 + shotgun (0.9.2) + signet (0.21.0) sha256=d617e9fbf24928280d39dcfefba9a0372d1c38187ffffd0a9283957a10a8cd5b + simplecov (0.22.0) sha256=fe2622c7834ff23b98066bb0a854284b2729a569ac659f82621fc22ef36213a5 + simplecov-cobertura (3.1.0) sha256=6d7f38aa32c965ca2174b2e5bd88cb17138eaf629518854976ac50e628925dc5 + simplecov-html (0.13.2) sha256=bd0b8e54e7c2d7685927e8d6286466359b6f16b18cb0df47b508e8d73c777246 + simplecov_json_formatter (0.1.4) sha256=529418fbe8de1713ac2b2d612aa3daa56d316975d307244399fa4838c601b428 + sinatra (4.2.1) sha256=b7aeb9b11d046b552972ade834f1f9be98b185fa8444480688e3627625377080 + sinatra-contrib (4.2.1) sha256=10d091c944d268aa910c618ea40a3c3ebe0533e6e32990d84af92235a3d26b4a + sparql-client (3.2.2) + sshkit (1.25.0) sha256=c8c6543cdb60f91f1d277306d585dd11b6a064cb44eab0972827e4311ff96744 + systemu (2.6.5) sha256=01f7d014b1453b28e5781e15c4d7d63fc9221c29b174b7aae5253207a75ab33e + temple (0.10.4) sha256=b7a1e94b6f09038ab0b6e4fe0126996055da2c38bec53a8a336f075748fff72c + tilt (2.7.0) sha256=0d5b9ba69f6a36490c64b0eee9f6e9aad517e20dcc848800a06eb116f08c6ab3 + time (0.4.2) sha256=f324e498c3bde9471d45a7d18f874c27980e9867aa5cfca61bebf52262bc3dab + timeout (0.6.1) sha256=78f57368a7e7bbadec56971f78a3f5ecbcfb59b7fcbb0a3ed6ddc08a5094accb + tzinfo (2.0.6) sha256=8daf828cc77bcf7d63b0e3bdb6caa47e2272dcfaf4fbfe46f8c3a9df087a829b + unicode-display_width (3.2.0) sha256=0cdd96b5681a5949cdbc2c55e7b420facae74c4aaf9a9815eee1087cb1853c42 + unicode-emoji (4.2.0) sha256=519e69150f75652e40bf736106cfbc8f0f73aa3fb6a65afe62fefa7f80b0f80f + unicorn (6.1.0) sha256=45dd987add4c2b084c1880a68373af42797a704ad7441faff9b14b4982aa0fc0 + unicorn-worker-killer (0.4.5) sha256=fc3c5dae71566c9e2a165dfbf75664f7bc16fec20251a1d09c3375ffe58b3991 + uri (1.1.1) sha256=379fa58d27ffb1387eaada68c749d1426738bd0f654d812fcc07e7568f5c57c6 + uuid (2.3.9) sha256=aec0cf592053cd6e07c13c1ef94c440aba705f22eb1ee767b39631f2760124d7 + webmock (3.26.1) sha256=4f696fb57c90a827c20aadb2d4f9058bbff10f7f043bd0d4c3f58791143b1cd7 + webrick (1.9.2) sha256=beb4a15fc474defed24a3bda4ffd88a490d517c9e4e6118c3edce59e45864131 + BUNDLED WITH - 2.6.3 + 4.0.7 diff --git a/Rakefile b/Rakefile index 87565be14..749a5baa2 100644 --- a/Rakefile +++ b/Rakefile @@ -4,29 +4,34 @@ task default: %w[test] Rake::TestTask.new do |t| t.libs = [] + t.warning = false t.test_files = FileList['test/**/test*.rb'] end Rake::TestTask.new do |t| t.libs = [] + t.warning = false t.name = "test:controllers" t.test_files = FileList['test/controllers/test*.rb'] end Rake::TestTask.new do |t| t.libs = [] + t.warning = false t.name = "test:models" t.test_files = FileList['test/models/test*.rb'] end Rake::TestTask.new do |t| t.libs = [] + t.warning = false t.name = "test:helpers" t.test_files = FileList['test/helpers/test*.rb'] end Rake::TestTask.new do |t| t.libs = [] + t.warning = false t.name = "test:lib" t.test_files = FileList['test/lib/test*.rb'] end diff --git a/app.rb b/app.rb index e09178bd0..08ed31a42 100644 --- a/app.rb +++ b/app.rb @@ -1,10 +1,11 @@ +$VERBOSE = false + # sinatra-base require 'sinatra' # sinatra-contrib require 'sinatra/respond_with' require 'sinatra/namespace' -require 'sinatra/advanced_routes' require 'sinatra/multi_route' # Other gem dependencies @@ -24,7 +25,6 @@ require 'rack-timeout' require 'rack/cors' require_relative 'lib/rack/slow_requests' -require_relative 'lib/rack/cube_reporter' require_relative 'lib/rack/param_translator' require_relative 'lib/rack/slice_detection' require_relative 'lib/rack/request_lang' @@ -48,6 +48,8 @@ use Rack::Static, :urls => ["/static"], :root => "public" +set :public_folder, File.expand_path('public', __dir__) +set :static, true # Setup the environment environment = settings.environment.nil? ? :development : settings.environment @@ -84,6 +86,9 @@ set :raise_errors, true set :dump_errors, false set :show_exceptions, false + # use Rack::DowncaseHeaders to ensure headers are downcased for rack > 3.0 compatibility + require_relative 'lib/rack/downcase_headers' + use Rack::DowncaseHeaders end # mini-profiler sets the etag header to nil, so don't use when caching is enabled @@ -127,11 +132,6 @@ # Monitoring middleware if LinkedData::OntologiesAPI.settings.enable_monitoring - cube_settings = { - cube_host: LinkedData::OntologiesAPI.settings.cube_host, - cube_port: LinkedData::OntologiesAPI.settings.cube_port - } - use Rack::CubeReporter, cube_settings use Rack::SlowRequests, log_path: LinkedData::OntologiesAPI.settings.slow_request_log end @@ -172,9 +172,6 @@ require_relative 'config/unicorn_workerkiller' end -# Add New Relic last to allow Rack middleware instrumentation -require 'newrelic_rpm' - # Initialize the app require_relative 'init' diff --git a/config/config.rb b/config/config.rb index a67829071..d50035d6d 100644 --- a/config/config.rb +++ b/config/config.rb @@ -13,8 +13,6 @@ def config(&block) # Set defaults @settings.enable_monitoring ||= false - @settings.cube_host ||= "localhost" - @settings.cube_port ||= 1180 @settings.slow_request_log ||= File.expand_path("../../logs/slow_requests.log", __FILE__) @settings.http_redis_host ||= "localhost" @settings.http_redis_port ||= 6379 @@ -30,7 +28,6 @@ def config(&block) if @settings.enable_monitoring puts "(API) >> Slow queries log enabled: #{@settings.slow_request_log}" - puts "(API) >> Using cube server #{@settings.cube_host}:#{@settings.cube_port}" end end diff --git a/config/deploy.rb b/config/deploy.rb index 2d7497be6..a764cd9fb 100644 --- a/config/deploy.rb +++ b/config/deploy.rb @@ -106,10 +106,8 @@ end end - after :publishing, :get_config - after :get_config, :restart - # after :deploy, :smoke_test - after :restart, "newrelic:notice_deployment" + after :updating, :get_config + after :publishing, :restart after :restart, :clear_cache do on roles(:web), in: :groups, limit: 3, wait: 10 do diff --git a/config/environments/config.rb.sample b/config/environments/config.rb.sample index e8667dc44..f153cfe16 100644 --- a/config/environments/config.rb.sample +++ b/config/environments/config.rb.sample @@ -19,8 +19,8 @@ REDIS_PORT = ENV.include?("REDIS_PORT") ? ENV["REDIS_PORT" REPORT_PATH = ENV.include?("REPORT_PATH") ? ENV["REPORT_PATH"] : "./test/ontologies_report.json" REPOSITORY_FOLDER = ENV.include?("REPOSITORY_FOLDER") ? ENV["REPOSITORY_FOLDER"] : "./test/data/ontology_files/repo" REST_URL_PREFIX = ENV.include?("REST_URL_PREFIX") ? ENV["REST_URL_PREFIX"] : "http://localhost:9393" -SOLR_PROP_SEARCH_URL = ENV.include?("SOLR_PROP_SEARCH_URL") ? ENV["SOLR_PROP_SEARCH_URL"] : "http://localhost:8983/solr/prop_search_core1" -SOLR_TERM_SEARCH_URL = ENV.include?("SOLR_TERM_SEARCH_URL") ? ENV["SOLR_TERM_SEARCH_URL"] : "http://localhost:8983/solr/term_search_core1" +SOLR_PROP_SEARCH_URL = ENV.include?("SOLR_PROP_SEARCH_URL") ? ENV["SOLR_PROP_SEARCH_URL"] : "http://localhost:8983/solr" +SOLR_TERM_SEARCH_URL = ENV.include?("SOLR_TERM_SEARCH_URL") ? ENV["SOLR_TERM_SEARCH_URL"] : "http://localhost:8983/solr" LinkedData.config do |config| config.goo_backend_name = GOO_BACKEND_NAME.to_s diff --git a/config/environments/test.rb b/config/environments/test.rb index 9eccf1d9b..a24789165 100644 --- a/config/environments/test.rb +++ b/config/environments/test.rb @@ -1,35 +1,16 @@ # conig file for unit tests -# GOO_BACKEND_NAME = ENV.include?("GOO_BACKEND_NAME") ? ENV["GOO_BACKEND_NAME"] : "AG" -# GOO_HOST = ENV.include?("GOO_HOST") ? ENV["GOO_HOST"] : "localhost" -# GOO_PATH_QUERY = ENV.include?("GOO_PATH_QUERY") ? ENV["GOO_PATH_QUERY"] : "/repositories/bioportal" -# GOO_PATH_DATA = ENV.include?("GOO_PATH_DATA") ? ENV["GOO_PATH_DATA"] : "/repositories/bioportal/statements" -# GOO_PATH_UPDATE = ENV.include?("GOO_PATH_UPDATE") ? ENV["GOO_PATH_UPDATE"] : "/repositories/bioportal/statements" -# GOO_PORT = ENV.include?("GOO_PORT") ? ENV["GOO_PORT"] : 10035 - -GOO_BACKEND_NAME = ENV.include?("GOO_BACKEND_NAME") ? ENV["GOO_BACKEND_NAME"] : "4store" -GOO_HOST = ENV.include?("GOO_HOST") ? ENV["GOO_HOST"] : "localhost" -GOO_PATH_DATA = ENV.include?("GOO_PATH_DATA") ? ENV["GOO_PATH_DATA"] : "/data/" -GOO_PATH_QUERY = ENV.include?("GOO_PATH_QUERY") ? ENV["GOO_PATH_QUERY"] : "/sparql/" -GOO_PATH_UPDATE = ENV.include?("GOO_PATH_UPDATE") ? ENV["GOO_PATH_UPDATE"] : "/update/" -GOO_PORT = ENV.include?("GOO_PORT") ? ENV["GOO_PORT"] : 8080 - -MGREP_DICTIONARY_FILE = ENV.include?("MGREP_DICTIONARY_FILE") ? ENV["MGREP_DICTIONARY_FILE"] : "./test/data/dictionary.txt" -MGREP_HOST = ENV.include?("MGREP_HOST") ? ENV["MGREP_HOST"] : "localhost" - - -# MGREP_PORT = ENV.include?("MGREP_PORT") ? ENV["MGREP_PORT"] : 55556 -MGREP_PORT = ENV.include?("MGREP_PORT") ? ENV["MGREP_PORT"] : 55555 - - -REDIS_GOO_CACHE_HOST = ENV.include?("REDIS_GOO_CACHE_HOST") ? ENV["REDIS_GOO_CACHE_HOST"] : "localhost" -REDIS_HTTP_CACHE_HOST = ENV.include?("REDIS_HTTP_CACHE_HOST") ? ENV["REDIS_HTTP_CACHE_HOST"] : "localhost" -REDIS_PERSISTENT_HOST = ENV.include?("REDIS_PERSISTENT_HOST") ? ENV["REDIS_PERSISTENT_HOST"] : "localhost" -REDIS_PORT = ENV.include?("REDIS_PORT") ? ENV["REDIS_PORT"] : 6379 -REPORT_PATH = ENV.include?("REPORT_PATH") ? ENV["REPORT_PATH"] : "./test/ontologies_report.json" -REPOSITORY_FOLDER = ENV.include?("REPOSITORY_FOLDER") ? ENV["REPOSITORY_FOLDER"] : "./test/data/ontology_files/repo" -SOLR_PROP_SEARCH_URL = ENV.include?("SOLR_PROP_SEARCH_URL") ? ENV["SOLR_PROP_SEARCH_URL"] : "http://localhost:8983/solr/prop_search_core1" -SOLR_TERM_SEARCH_URL = ENV.include?("SOLR_TERM_SEARCH_URL") ? ENV["SOLR_TERM_SEARCH_URL"] : "http://localhost:8983/solr/term_search_core1" +GOO_BACKEND_NAME = ENV.include?("GOO_BACKEND_NAME") ? ENV["GOO_BACKEND_NAME"] : "4store" +GOO_HOST = ENV.include?("GOO_HOST") ? ENV["GOO_HOST"] : "localhost" +GOO_PATH_DATA = ENV.include?("GOO_PATH_DATA") ? ENV["GOO_PATH_DATA"] : "/data/" +GOO_PATH_QUERY = ENV.include?("GOO_PATH_QUERY") ? ENV["GOO_PATH_QUERY"] : "/sparql/" +GOO_PATH_UPDATE = ENV.include?("GOO_PATH_UPDATE") ? ENV["GOO_PATH_UPDATE"] : "/update/" +GOO_PORT = ENV.include?("GOO_PORT") ? ENV["GOO_PORT"] : 9000 +MGREP_HOST = ENV.include?("MGREP_HOST") ? ENV["MGREP_HOST"] : "localhost" +MGREP_PORT = ENV.include?("MGREP_PORT") ? ENV["MGREP_PORT"] : 55556 +REDIS_HOST = ENV.include?("REDIS_HOST") ? ENV["REDIS_HOST"] : "localhost" +REDIS_PORT = ENV.include?("REDIS_PORT") ? ENV["REDIS_PORT"] : 6379 +SEARCH_SERVER_URL = ENV.include?('SEARCH_SERVER_URL') ? ENV['SEARCH_SERVER_URL'] : 'http://localhost:8983/solr' LinkedData.config do |config| config.goo_backend_name = GOO_BACKEND_NAME.to_s @@ -38,35 +19,50 @@ config.goo_path_query = GOO_PATH_QUERY.to_s config.goo_path_data = GOO_PATH_DATA.to_s config.goo_path_update = GOO_PATH_UPDATE.to_s - config.goo_redis_host = REDIS_GOO_CACHE_HOST.to_s + config.goo_redis_host = REDIS_HOST.to_s config.goo_redis_port = REDIS_PORT.to_i - config.http_redis_host = REDIS_HTTP_CACHE_HOST.to_s + config.http_redis_host = REDIS_HOST.to_s config.http_redis_port = REDIS_PORT.to_i - config.search_server_url = SOLR_TERM_SEARCH_URL.to_s - config.property_search_server_url = SOLR_PROP_SEARCH_URL.to_s - #config.enable_notifications = false + config.search_server_url = SEARCH_SERVER_URL.to_s + config.property_search_server_url = SEARCH_SERVER_URL.to_s # Ontology analytics - config.ontology_analytics_redis_host = REDIS_PERSISTENT_HOST.to_s + config.ontology_analytics_redis_host = REDIS_HOST.to_s config.ontology_analytics_redis_port = REDIS_PORT.to_i config.ontology_analytics_redis_field = 'test_analytics' + config.oauth_providers = { + github: { + check: :access_token, + link: 'https://api.github.com/user' + }, + keycloak: { + check: :jwt_token, + cert: 'KEYCLOAK_SECRET_KEY' + }, + orcid: { + check: :access_token, + link: 'https://pub.orcid.org/v3.0/me' + }, + google: { + check: :access_token, + link: 'https://www.googleapis.com/oauth2/v3/userinfo' + } + } end Annotator.config do |config| - config.annotator_redis_host = REDIS_PERSISTENT_HOST.to_s + config.annotator_redis_host = REDIS_HOST.to_s config.annotator_redis_port = REDIS_PORT.to_i config.mgrep_host = MGREP_HOST.to_s config.mgrep_port = MGREP_PORT.to_i - config.mgrep_dictionary_file = MGREP_DICTIONARY_FILE.to_s end LinkedData::OntologiesAPI.config do |config| - config.http_redis_host = REDIS_HTTP_CACHE_HOST.to_s + config.http_redis_host = REDIS_HOST.to_s config.http_redis_port = REDIS_PORT.to_i end NcboCron.config do |config| - config.redis_host = REDIS_PERSISTENT_HOST.to_s + config.redis_host = REDIS_HOST.to_s config.redis_port = REDIS_PORT.to_i -# config.ontology_report_path = REPORT_PATH end diff --git a/config/logging.rb b/config/logging.rb index e37ba4aa3..66c323a57 100644 --- a/config/logging.rb +++ b/config/logging.rb @@ -1,23 +1,9 @@ require 'logger' -class CustomLogger < Logger - alias write << - def flush - ((self.instance_variable_get :@logdev).instance_variable_get :@dev).flush - end -end - -# Setup global logging -require 'rack/logger' -# if [:development, :console, :test].include?(settings.environment) -if [:development, :console].include?(settings.environment) - LOGGER = CustomLogger.new(STDOUT) - LOGGER.level = Logger::DEBUG -else - Dir.mkdir('log') unless File.exist?('log') - log = File.new("log/#{settings.environment}.log", "a+") - log.sync = true - LOGGER = CustomLogger.new(log) - LOGGER.level = Logger::INFO - use Rack::CommonLogger, log +configure do + log_file = File.new("log/#{settings.environment}.log", 'a+') + log_file.sync = true + LOGGER = Logger.new(log_file) + LOGGER.level = settings.development? ? Logger::DEBUG : Logger::INFO + set :logger, LOGGER end diff --git a/config/rack_attack.rb b/config/rack_attack.rb index 4612b4935..e24e05fbb 100644 --- a/config/rack_attack.rb +++ b/config/rack_attack.rb @@ -29,11 +29,11 @@ request.env['REMOTE_USER']&.admin? end -Rack::Attack.throttle('req/ip/heavy', limit: limit_req_ip_heavy, period: 1.second) do |req| +Rack::Attack.throttle('req/ip/heavy', limit: limit_req_ip_heavy, period: 1) do |req| req.ip if req.path.include?('/recommender') || req.path.include?('/annotator') end -Rack::Attack.throttle('req/ip', limit: limit_req_ip, period: 1.second) do |req| +Rack::Attack.throttle('req/ip', limit: limit_req_ip, period: 1) do |req| req.ip end diff --git a/config/solr/property_search/enumsconfig.xml b/config/solr/property_search/enumsconfig.xml deleted file mode 100644 index 72e7b7d31..000000000 --- a/config/solr/property_search/enumsconfig.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - ONTOLOGY - VALUE_SET_COLLECTION - - - ANNOTATION - DATATYPE - OBJECT - - \ No newline at end of file diff --git a/config/solr/property_search/mapping-ISOLatin1Accent.txt b/config/solr/property_search/mapping-ISOLatin1Accent.txt deleted file mode 100644 index ede774258..000000000 --- a/config/solr/property_search/mapping-ISOLatin1Accent.txt +++ /dev/null @@ -1,246 +0,0 @@ -# The ASF licenses this file to You 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. - -# Syntax: -# "source" => "target" -# "source".length() > 0 (source cannot be empty.) -# "target".length() >= 0 (target can be empty.) - -# example: -# "À" => "A" -# "\u00C0" => "A" -# "\u00C0" => "\u0041" -# "ß" => "ss" -# "\t" => " " -# "\n" => "" - -# À => A -"\u00C0" => "A" - -# Á => A -"\u00C1" => "A" - -#  => A -"\u00C2" => "A" - -# à => A -"\u00C3" => "A" - -# Ä => A -"\u00C4" => "A" - -# Å => A -"\u00C5" => "A" - -# Æ => AE -"\u00C6" => "AE" - -# Ç => C -"\u00C7" => "C" - -# È => E -"\u00C8" => "E" - -# É => E -"\u00C9" => "E" - -# Ê => E -"\u00CA" => "E" - -# Ë => E -"\u00CB" => "E" - -# Ì => I -"\u00CC" => "I" - -# Í => I -"\u00CD" => "I" - -# Î => I -"\u00CE" => "I" - -# Ï => I -"\u00CF" => "I" - -# IJ => IJ -"\u0132" => "IJ" - -# Ð => D -"\u00D0" => "D" - -# Ñ => N -"\u00D1" => "N" - -# Ò => O -"\u00D2" => "O" - -# Ó => O -"\u00D3" => "O" - -# Ô => O -"\u00D4" => "O" - -# Õ => O -"\u00D5" => "O" - -# Ö => O -"\u00D6" => "O" - -# Ø => O -"\u00D8" => "O" - -# Œ => OE -"\u0152" => "OE" - -# Þ -"\u00DE" => "TH" - -# Ù => U -"\u00D9" => "U" - -# Ú => U -"\u00DA" => "U" - -# Û => U -"\u00DB" => "U" - -# Ü => U -"\u00DC" => "U" - -# Ý => Y -"\u00DD" => "Y" - -# Ÿ => Y -"\u0178" => "Y" - -# à => a -"\u00E0" => "a" - -# á => a -"\u00E1" => "a" - -# â => a -"\u00E2" => "a" - -# ã => a -"\u00E3" => "a" - -# ä => a -"\u00E4" => "a" - -# å => a -"\u00E5" => "a" - -# æ => ae -"\u00E6" => "ae" - -# ç => c -"\u00E7" => "c" - -# è => e -"\u00E8" => "e" - -# é => e -"\u00E9" => "e" - -# ê => e -"\u00EA" => "e" - -# ë => e -"\u00EB" => "e" - -# ì => i -"\u00EC" => "i" - -# í => i -"\u00ED" => "i" - -# î => i -"\u00EE" => "i" - -# ï => i -"\u00EF" => "i" - -# ij => ij -"\u0133" => "ij" - -# ð => d -"\u00F0" => "d" - -# ñ => n -"\u00F1" => "n" - -# ò => o -"\u00F2" => "o" - -# ó => o -"\u00F3" => "o" - -# ô => o -"\u00F4" => "o" - -# õ => o -"\u00F5" => "o" - -# ö => o -"\u00F6" => "o" - -# ø => o -"\u00F8" => "o" - -# œ => oe -"\u0153" => "oe" - -# ß => ss -"\u00DF" => "ss" - -# þ => th -"\u00FE" => "th" - -# ù => u -"\u00F9" => "u" - -# ú => u -"\u00FA" => "u" - -# û => u -"\u00FB" => "u" - -# ü => u -"\u00FC" => "u" - -# ý => y -"\u00FD" => "y" - -# ÿ => y -"\u00FF" => "y" - -# ff => ff -"\uFB00" => "ff" - -# fi => fi -"\uFB01" => "fi" - -# fl => fl -"\uFB02" => "fl" - -# ffi => ffi -"\uFB03" => "ffi" - -# ffl => ffl -"\uFB04" => "ffl" - -# ſt => ft -"\uFB05" => "ft" - -# st => st -"\uFB06" => "st" diff --git a/config/solr/property_search/schema.xml b/config/solr/property_search/schema.xml deleted file mode 100644 index 20824ea65..000000000 --- a/config/solr/property_search/schema.xml +++ /dev/null @@ -1,1179 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - id - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/config/solr/property_search/solrconfig.xml b/config/solr/property_search/solrconfig.xml deleted file mode 100644 index 771a0f322..000000000 --- a/config/solr/property_search/solrconfig.xml +++ /dev/null @@ -1,1299 +0,0 @@ - - - - - - - - - 8.8.2 - - - - - - - - - - - ${solr.data.dir:} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ${solr.lock.type:native} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ${solr.ulog.dir:} - ${solr.ulog.numVersionBuckets:65536} - - - - - ${solr.autoCommit.maxTime:15000} - false - - - - - - ${solr.autoSoftCommit.maxTime:-1} - - - - - - - - - - - - - - ${solr.max.booleanClauses:500000} - - - - - - - - - - - - - - - - - - - - - - - - true - - - - - - 20 - - - 200 - - - - - - - - - - - - - - - - - - - false - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - explicit - 10 - - - - - - - - - - - - - - - - explicit - json - true - - - - - - _text_ - - - - - - - - - text_general - - - - - - default - _text_ - solr.DirectSolrSpellChecker - - internal - - 0.5 - - 2 - - 1 - - 5 - - 4 - - 0.01 - - - - - - - - - - - - default - on - true - 10 - 5 - 5 - true - true - 10 - 5 - - - spellcheck - - - - - - - - - - true - false - - - terms - - - - - - - - - - - 100 - - - - - - - - 70 - - 0.5 - - [-\w ,/\n\"']{20,200} - - - - - - - ]]> - ]]> - - - - - - - - - - - - - - - - - - - - - - - - ,, - ,, - ,, - ,, - ,]]> - ]]> - - - - - - 10 - .,!? - - - - - - - WORD - - - en - US - - - - - - - - - - - - [^\w-\.] - _ - - - - - - - yyyy-MM-dd['T'[HH:mm[:ss[.SSS]][z - yyyy-MM-dd['T'[HH:mm[:ss[,SSS]][z - yyyy-MM-dd HH:mm[:ss[.SSS]][z - yyyy-MM-dd HH:mm[:ss[,SSS]][z - [EEE, ]dd MMM yyyy HH:mm[:ss] z - EEEE, dd-MMM-yy HH:mm:ss z - EEE MMM ppd HH:mm:ss [z ]yyyy - - - - - java.lang.String - text_general - - *_str - 256 - - - true - - - java.lang.Boolean - booleans - - - java.util.Date - pdates - - - java.lang.Long - java.lang.Integer - plongs - - - java.lang.Number - pdoubles - - - - - - - - - - - - - - - - - - - - text/plain; charset=UTF-8 - - - - - - - - - - - - - - diff --git a/config/solr/solr.xml b/config/solr/solr.xml deleted file mode 100644 index d9d089e4d..000000000 --- a/config/solr/solr.xml +++ /dev/null @@ -1,60 +0,0 @@ - - - - - - - - ${solr.max.booleanClauses:500000} - ${solr.sharedLib:} - ${solr.allowPaths:} - - - - ${host:} - ${solr.port.advertise:0} - ${hostContext:solr} - - ${genericCoreNodeNames:true} - - ${zkClientTimeout:30000} - ${distribUpdateSoTimeout:600000} - ${distribUpdateConnTimeout:60000} - ${zkCredentialsProvider:org.apache.solr.common.cloud.DefaultZkCredentialsProvider} - ${zkACLProvider:org.apache.solr.common.cloud.DefaultZkACLProvider} - - - - - ${socketTimeout:600000} - ${connTimeout:60000} - ${solr.shardsWhitelist:} - - - - - diff --git a/config/solr/term_search/enumsconfig.xml b/config/solr/term_search/enumsconfig.xml deleted file mode 100644 index 72e7b7d31..000000000 --- a/config/solr/term_search/enumsconfig.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - ONTOLOGY - VALUE_SET_COLLECTION - - - ANNOTATION - DATATYPE - OBJECT - - \ No newline at end of file diff --git a/config/solr/term_search/mapping-ISOLatin1Accent.txt b/config/solr/term_search/mapping-ISOLatin1Accent.txt deleted file mode 100644 index ede774258..000000000 --- a/config/solr/term_search/mapping-ISOLatin1Accent.txt +++ /dev/null @@ -1,246 +0,0 @@ -# The ASF licenses this file to You 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. - -# Syntax: -# "source" => "target" -# "source".length() > 0 (source cannot be empty.) -# "target".length() >= 0 (target can be empty.) - -# example: -# "À" => "A" -# "\u00C0" => "A" -# "\u00C0" => "\u0041" -# "ß" => "ss" -# "\t" => " " -# "\n" => "" - -# À => A -"\u00C0" => "A" - -# Á => A -"\u00C1" => "A" - -#  => A -"\u00C2" => "A" - -# à => A -"\u00C3" => "A" - -# Ä => A -"\u00C4" => "A" - -# Å => A -"\u00C5" => "A" - -# Æ => AE -"\u00C6" => "AE" - -# Ç => C -"\u00C7" => "C" - -# È => E -"\u00C8" => "E" - -# É => E -"\u00C9" => "E" - -# Ê => E -"\u00CA" => "E" - -# Ë => E -"\u00CB" => "E" - -# Ì => I -"\u00CC" => "I" - -# Í => I -"\u00CD" => "I" - -# Î => I -"\u00CE" => "I" - -# Ï => I -"\u00CF" => "I" - -# IJ => IJ -"\u0132" => "IJ" - -# Ð => D -"\u00D0" => "D" - -# Ñ => N -"\u00D1" => "N" - -# Ò => O -"\u00D2" => "O" - -# Ó => O -"\u00D3" => "O" - -# Ô => O -"\u00D4" => "O" - -# Õ => O -"\u00D5" => "O" - -# Ö => O -"\u00D6" => "O" - -# Ø => O -"\u00D8" => "O" - -# Œ => OE -"\u0152" => "OE" - -# Þ -"\u00DE" => "TH" - -# Ù => U -"\u00D9" => "U" - -# Ú => U -"\u00DA" => "U" - -# Û => U -"\u00DB" => "U" - -# Ü => U -"\u00DC" => "U" - -# Ý => Y -"\u00DD" => "Y" - -# Ÿ => Y -"\u0178" => "Y" - -# à => a -"\u00E0" => "a" - -# á => a -"\u00E1" => "a" - -# â => a -"\u00E2" => "a" - -# ã => a -"\u00E3" => "a" - -# ä => a -"\u00E4" => "a" - -# å => a -"\u00E5" => "a" - -# æ => ae -"\u00E6" => "ae" - -# ç => c -"\u00E7" => "c" - -# è => e -"\u00E8" => "e" - -# é => e -"\u00E9" => "e" - -# ê => e -"\u00EA" => "e" - -# ë => e -"\u00EB" => "e" - -# ì => i -"\u00EC" => "i" - -# í => i -"\u00ED" => "i" - -# î => i -"\u00EE" => "i" - -# ï => i -"\u00EF" => "i" - -# ij => ij -"\u0133" => "ij" - -# ð => d -"\u00F0" => "d" - -# ñ => n -"\u00F1" => "n" - -# ò => o -"\u00F2" => "o" - -# ó => o -"\u00F3" => "o" - -# ô => o -"\u00F4" => "o" - -# õ => o -"\u00F5" => "o" - -# ö => o -"\u00F6" => "o" - -# ø => o -"\u00F8" => "o" - -# œ => oe -"\u0153" => "oe" - -# ß => ss -"\u00DF" => "ss" - -# þ => th -"\u00FE" => "th" - -# ù => u -"\u00F9" => "u" - -# ú => u -"\u00FA" => "u" - -# û => u -"\u00FB" => "u" - -# ü => u -"\u00FC" => "u" - -# ý => y -"\u00FD" => "y" - -# ÿ => y -"\u00FF" => "y" - -# ff => ff -"\uFB00" => "ff" - -# fi => fi -"\uFB01" => "fi" - -# fl => fl -"\uFB02" => "fl" - -# ffi => ffi -"\uFB03" => "ffi" - -# ffl => ffl -"\uFB04" => "ffl" - -# ſt => ft -"\uFB05" => "ft" - -# st => st -"\uFB06" => "st" diff --git a/config/solr/term_search/schema.xml b/config/solr/term_search/schema.xml deleted file mode 100644 index 73c75b31f..000000000 --- a/config/solr/term_search/schema.xml +++ /dev/null @@ -1,1224 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - id - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/config/solr/term_search/solrconfig.xml b/config/solr/term_search/solrconfig.xml deleted file mode 100644 index 771a0f322..000000000 --- a/config/solr/term_search/solrconfig.xml +++ /dev/null @@ -1,1299 +0,0 @@ - - - - - - - - - 8.8.2 - - - - - - - - - - - ${solr.data.dir:} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ${solr.lock.type:native} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ${solr.ulog.dir:} - ${solr.ulog.numVersionBuckets:65536} - - - - - ${solr.autoCommit.maxTime:15000} - false - - - - - - ${solr.autoSoftCommit.maxTime:-1} - - - - - - - - - - - - - - ${solr.max.booleanClauses:500000} - - - - - - - - - - - - - - - - - - - - - - - - true - - - - - - 20 - - - 200 - - - - - - - - - - - - - - - - - - - false - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - explicit - 10 - - - - - - - - - - - - - - - - explicit - json - true - - - - - - _text_ - - - - - - - - - text_general - - - - - - default - _text_ - solr.DirectSolrSpellChecker - - internal - - 0.5 - - 2 - - 1 - - 5 - - 4 - - 0.01 - - - - - - - - - - - - default - on - true - 10 - 5 - 5 - true - true - 10 - 5 - - - spellcheck - - - - - - - - - - true - false - - - terms - - - - - - - - - - - 100 - - - - - - - - 70 - - 0.5 - - [-\w ,/\n\"']{20,200} - - - - - - - ]]> - ]]> - - - - - - - - - - - - - - - - - - - - - - - - ,, - ,, - ,, - ,, - ,]]> - ]]> - - - - - - 10 - .,!? - - - - - - - WORD - - - en - US - - - - - - - - - - - - [^\w-\.] - _ - - - - - - - yyyy-MM-dd['T'[HH:mm[:ss[.SSS]][z - yyyy-MM-dd['T'[HH:mm[:ss[,SSS]][z - yyyy-MM-dd HH:mm[:ss[.SSS]][z - yyyy-MM-dd HH:mm[:ss[,SSS]][z - [EEE, ]dd MMM yyyy HH:mm[:ss] z - EEEE, dd-MMM-yy HH:mm:ss z - EEE MMM ppd HH:mm:ss [z ]yyyy - - - - - java.lang.String - text_general - - *_str - 256 - - - true - - - java.lang.Boolean - booleans - - - java.util.Date - pdates - - - java.lang.Long - java.lang.Integer - plongs - - - java.lang.Number - pdoubles - - - - - - - - - - - - - - - - - - - - text/plain; charset=UTF-8 - - - - - - - - - - - - - - diff --git a/controllers/admin_controller.rb b/controllers/admin_controller.rb index d6a23b90a..a355329cc 100644 --- a/controllers/admin_controller.rb +++ b/controllers/admin_controller.rb @@ -127,14 +127,77 @@ class AdminController < ApplicationController halt 204 end - private + namespace "/search" do + get '/collections' do + conn = SOLR::SolrConnector.new(Goo.search_conf, '') + collections = { collections: conn.fetch_all_collections} + reply(200, collections) + end - def redis_goo - Redis.new(host: LinkedData.settings.goo_redis_host, port: LinkedData.settings.goo_redis_port, timeout: 30) - end + get '/collections/:collection/schema' do + collection = params[:collection].to_sym + conn = SOLR::SolrConnector.new(Goo.search_conf, collection) + collection_schema = conn.fetch_schema + + reply(200, collection_schema) + end + + post '/collections/:collection/schema/init' do + collection = params[:collection].to_sym + conn = SOLR::SolrConnector.new(Goo.search_conf, collection) + collection_schema = conn.init_schema + reply(200, collection_schema) + end + + post '/collections/:collection/search' do + collection = params[:collection].to_sym + + search_keys = %w[defType fq qf sort start rows fl stopwords lowercaseOperators] - def redis_http - Redis.new(host: LinkedData.settings.http_redis_host, port: LinkedData.settings.http_redis_port, timeout: 30) + search_params = params.select { |key, _| search_keys.include?(key) } + search_query = params[:query] || params[:q] + search_query = search_query.blank? ? '*' : search_query + conn = SOLR::SolrConnector.new(Goo.search_conf, collection) + reply(200, conn.search(search_query, search_params).to_h) + end + + post '/index_batch/:model_name' do + error 500, "model_name parameter not set" if params["model_name"].blank? + + model = Goo.model_by_name(params["model_name"].to_sym) + error 500, "#{params["model_name"]} is not indexable" if model.nil? || !model.index_enabled? + + all_attrs = get_attributes_to_include([:all], model) + + collections = model.where.include(all_attrs).all + indexed = [] + not_indexed = [] + collections.each do |m| + begin + response = m.index.dig("responseHeader", "status") + if response.eql?(0) + indexed << m.id + else + not_indexed << m.id + end + rescue StandardError + not_indexed << m.id + end + end + + if !indexed.empty? + msg = "Batch indexing for #{model.model_name} completed for" + + if not_indexed.empty? + msg += " all models" + else + msg += " #{indexed.join(', ')} and not for the following #{not_indexed.join(', ')}, see logs for more details" + end + reply(200, msg) + else + reply(500, "Batch indexing for #{model.model_name} failed") + end + end end end diff --git a/controllers/batch_controller.rb b/controllers/batch_controller.rb index 2ee9b88ca..33276cc8d 100644 --- a/controllers/batch_controller.rb +++ b/controllers/batch_controller.rb @@ -15,7 +15,7 @@ class BatchController < ApplicationController goo_include = LinkedData::Models::Class.goo_attrs_to_load(incl) class_id_by_ontology = {} collection.each do |class_input| - unless class_input.instance_of?(Hash) + unless class_input.is_a?(Hash) error 422, "The collection param needs to be { 'class' : CLS_ID, 'ontology' : ont_id }" end unless class_input.include?("ontology") and class_input.include?("class") diff --git a/controllers/dereference_resource_controller.rb b/controllers/dereference_resource_controller.rb new file mode 100644 index 000000000..8b69efdb5 --- /dev/null +++ b/controllers/dereference_resource_controller.rb @@ -0,0 +1,53 @@ +use Rack::ContentNegotiation + +class DereferenceResourceController < ApplicationController + namespace "/ontologies" do + get "/:acronym/resolve/:uri" do + acronym = params[:acronym] + uri = params[:uri] + + if acronym.blank? || uri.blank? + error 500, "Usage: ontologies/:acronym/resolve/:uri?output_format= OR POST: acronym, uri, output_format parameters" + end + + output_format = env["format"].presence || params[:output_format].presence || 'application/n-triples' + + process_request(acronym, uri, output_format) + end + + private + + def process_request(acronym_param, uri_param, output_format) + acronym = acronym_param + uri = URI.decode_www_form_component(uri_param) + + error 500, "INVALID URI" unless valid_url?(uri) + sub = LinkedData::Models::Ontology.find(acronym).first&.latest_submission + + error 500, "Ontology not found" unless sub + + r = Resource.new(sub.id, uri) + case output_format + when 'application/ld+json', 'application/json' + r.to_json + when 'application/rdf+xml', 'application/xml' + r.to_xml + when 'text/turtle' + r.to_turtle + when 'application/n-triples' + r.to_ntriples + else + error 500, "Invalid output format, valid format are: application/json, application/ld+json, application/xml, application/rdf+xml, text/turtle and application/n-triples" + end + + + end + + def valid_url?(url) + uri = URI.parse(url) + uri.is_a?(URI::HTTP) || uri.is_a?(URI::HTTPS) + rescue URI::InvalidURIError + false + end + end +end \ No newline at end of file diff --git a/controllers/home_controller.rb b/controllers/home_controller.rb index fc6d03947..2d2490f53 100644 --- a/controllers/home_controller.rb +++ b/controllers/home_controller.rb @@ -1,5 +1,4 @@ require 'haml' -require 'redcarpet' class HomeController < ApplicationController @@ -18,7 +17,9 @@ class HomeController < ApplicationController routes.each do |route| next if route.length < 3 || route.split("/").length > 2 route_no_slash = route.gsub("/", "") - context[route_no_slash] = route_to_class_map[route].type_uri.to_s if route_to_class_map[route] && route_to_class_map[route].respond_to?(:type_uri) + mapped_class = route_to_class_map[route] + mapped_type_uri = safe_type_uri(mapped_class) + context[route_no_slash] = mapped_type_uri.to_s unless mapped_type_uri.nil? routes_hash[route_no_slash] = LinkedData.settings.rest_url_prefix+route_no_slash end routes_hash["@context"] = context @@ -132,7 +133,7 @@ def metadata_all cls_info = { attributes: attributes_info, - uri: cls.type_uri, + uri: safe_type_uri(cls), cls: cls } @@ -161,8 +162,10 @@ def routes_by_class routes_by_file = {} all_routes.each do |method, routes| routes.each do |route| - routes_by_file[route.file] ||= [] - routes_by_file[route.file] << route + route_info = parse_route(method, route) + next if route_info[:file].nil? + routes_by_file[route_info[:file]] ||= [] + routes_by_file[route_info[:file]] << route_info end end routes_by_class = {} @@ -188,9 +191,9 @@ def routes_by_class next if cls.nil? routes.each do |route| - next if route.verb == "HEAD" + next if route[:verb] == "HEAD" routes_by_class[cls] ||= [] - routes_by_class[cls] << [route.verb, route.path] + routes_by_class[cls] << [route[:verb], route[:path]] end end @routes_by_class = routes_by_class @@ -211,17 +214,52 @@ def route_to_class_map def routes_list return @navigable_routes if @navigable_routes - routes = Sinatra::Application.routes["GET"] - navigable_routes = [] - Sinatra::Application.each_route do |route| - if route.verb.eql?("GET") - navigable_routes << route.path.split("?").first - end - end + all_routes = Sinatra::Application.routes + get_routes = all_routes["GET"] || all_routes[:GET] || [] + navigable_routes = get_routes.map { |route| parse_route("GET", route)[:path] }.uniq @navigable_routes = navigable_routes navigable_routes end + # Sinatra < 4 routes are route objects; Sinatra 4 routes are arrays. + # Normalize both to a common shape. + def parse_route(method, route) + if route.respond_to?(:path) && route.respond_to?(:file) + return { verb: route.verb.to_s, path: route.path.to_s.split("?").first, file: route.file } + end + + if route.is_a?(Array) + pattern = route[0] + wrapper_proc = route[-1] + original_block = nil + file = nil + + if wrapper_proc.respond_to?(:binding) + begin + route_binding = wrapper_proc.binding + if route_binding.local_variables.include?(:block) + original_block = route_binding.local_variable_get(:block) + end + rescue StandardError + # ignore and leave file nil + end + end + + if original_block.respond_to?(:source_location) + file = original_block.source_location&.first + end + return { verb: method.to_s, path: pattern.to_s.split("?").first, file: file } + end + + { verb: method.to_s, path: "", file: nil } + end + + def safe_type_uri(cls) + return nil if cls.nil? || !cls.respond_to?(:type_uri) + cls.type_uri + rescue NoMethodError + nil + end + end end - diff --git a/controllers/mappings_controller.rb b/controllers/mappings_controller.rb index 29e26483a..64ffc799d 100644 --- a/controllers/mappings_controller.rb +++ b/controllers/mappings_controller.rb @@ -166,11 +166,13 @@ class MappingsController < ApplicationController persistent_counts = {} f = Goo::Filter.new(:pair_count) == false LinkedData::Models::MappingCount.where.filter(f) - .include(:ontologies,:count) - .all - .each do |m| + .include(:ontologies, :count) + .all + .each do |m| persistent_counts[m.ontologies.first] = m.count end + ont_acronyms = restricted_ontologies_to_acronyms(params) + persistent_counts = persistent_counts.select { |key, _| ont_acronyms.include?(key) || key.start_with?("http://") } reply persistent_counts end @@ -189,9 +191,9 @@ class MappingsController < ApplicationController persistent_counts = {} LinkedData::Models::MappingCount.where(pair_count: true) .and(ontologies: ontology.acronym) - .include(:ontologies,:count) - .all - .each do |m| + .include(:ontologies, :count) + .all + .each do |m| other = m.ontologies.first if other == ontology.acronym other = m.ontologies[1] @@ -200,5 +202,7 @@ class MappingsController < ApplicationController end reply persistent_counts end + end end + diff --git a/controllers/notes_controller.rb b/controllers/notes_controller.rb index 804f4cf6a..e8dd7bdec 100644 --- a/controllers/notes_controller.rb +++ b/controllers/notes_controller.rb @@ -1,7 +1,7 @@ class NotesController < ApplicationController ## # Ontology notes - get "/ontologies/:ontology/notes?:include_threads?" do + get '/ontologies/:ontology/notes' do ont = Ontology.find(params["ontology"]).include(:acronym).first error 404, "You must provide a valid id to retrieve notes for an ontology" if ont.nil? check_last_modified_segment(LinkedData::Models::Note, [ont.acronym]) @@ -13,7 +13,7 @@ class NotesController < ApplicationController ## # Class notes - get "/ontologies/:ontology/classes/:cls/notes?:include_threads?" do + get "/ontologies/:ontology/classes/:cls/notes" do ont = Ontology.find(params["ontology"]).include(:submissions, :acronym).first error 404, "You must provide a valid id to retrieve notes for an ontology" if ont.nil? check_last_modified_segment(LinkedData::Models::Note, [ont.acronym]) @@ -27,7 +27,7 @@ class NotesController < ApplicationController namespace "/notes" do # Display all notes - get "?:include_threads?" do + get '' do check_last_modified_collection(LinkedData::Models::Note) notes = LinkedData::Models::Note.where.include(LinkedData::Models::Note.goo_attrs_to_load(includes_param)).to_a recurse_replies(notes) if params["include_threads"] @@ -35,7 +35,7 @@ class NotesController < ApplicationController end # Display a single note - get '/:noteid?:include_threads?' do + get '/:noteid' do noteid = params["noteid"] note = LinkedData::Models::Note.find(noteid).include(relatedOntology: [:acronym]).first error 404, "Note #{noteid} not found" if note.nil? @@ -124,3 +124,4 @@ def clean_notes_hash(hash) end end end + diff --git a/controllers/ontology_analytics_controller.rb b/controllers/ontology_analytics_controller.rb index 829708c13..b4435e8f7 100644 --- a/controllers/ontology_analytics_controller.rb +++ b/controllers/ontology_analytics_controller.rb @@ -4,14 +4,14 @@ class OntologyAnalyticsController < ApplicationController ## # get all ontology analytics for a given year/month combination - namespace "/analytics" do + namespace '/analytics' do get do expires 86400, :public year = year_param(params) - error 400, "The year you supplied is invalid. Valid years start with 2 and contain 4 digits." if params["year"] && !year + error 400, 'The year you supplied is invalid. Valid years start with 2 and contain 4 digits.' if params['year'] && !year month = month_param(params) - error 400, "The month you supplied is invalid. Valid months are 1-12." if params["month"] && !month + error 400, 'The month you supplied is invalid. Valid months are 1-12.' if params['month'] && !month acronyms = restricted_ontologies_to_acronyms(params) analytics = Ontology.analytics(year, month, acronyms) @@ -22,7 +22,7 @@ class OntologyAnalyticsController < ApplicationController ## # get all analytics for a given ontology - namespace "/ontologies/:acronym/analytics" do + namespace '/ontologies/:acronym/analytics' do get do expires 86400, :public @@ -34,7 +34,7 @@ class OntologyAnalyticsController < ApplicationController error 400, "The month you supplied is invalid. Valid months are 1-12." if params["month"] && !month analytics = ont.analytics(year, month) - if params["format"].to_s.downcase.eql?("csv") + if params['format'].to_s.downcase.eql?("csv") tf = Tempfile.new("analytics-#{params['acronym']}") csv = CSV.new(tf, headers: true, return_headers: true, write_headers: true) csv << [:month, :visits] @@ -50,8 +50,7 @@ class OntologyAnalyticsController < ApplicationController end end csv.close - content_type "text/csv" - send_file tf.path, filename: "analytics-#{params['acronym']}.csv" + send_file tf.path, filename: "analytics-#{params['acronym']}.csv", type: 'text/csv', status: 200 else reply analytics end diff --git a/controllers/ontology_submissions_controller.rb b/controllers/ontology_submissions_controller.rb index 1b9463103..bdda6f65f 100644 --- a/controllers/ontology_submissions_controller.rb +++ b/controllers/ontology_submissions_controller.rb @@ -3,8 +3,15 @@ class OntologySubmissionsController < ApplicationController get "/submissions" do check_last_modified_collection(LinkedData::Models::OntologySubmission) - options = { also_include_views: params["also_include_views"], status: (params["include_status"] || "ANY") } - reply retrieve_latest_submissions(options).values + options = { + also_include_views: params["also_include_views"], + status: (params["include_status"] || "ANY") + } + subs = retrieve_latest_submissions(options) + subs = subs.values unless page? + # Force to show ontology reviews, notes and projects by default only for this request + LinkedData::Models::Ontology.serialize_default(*(LinkedData::Models::Ontology.hypermedia_settings[:serialize_default] + [:reviews, :notes, :projects])) + reply subs end ## diff --git a/controllers/properties_controller.rb b/controllers/properties_controller.rb index f98e90168..82313355b 100644 --- a/controllers/properties_controller.rb +++ b/controllers/properties_controller.rb @@ -24,7 +24,8 @@ class PropertiesController < ApplicationController get '/:property' do prop = params[:property] ont, submission = get_ontology_and_submission - p = ont.property(prop, submission) + bring_unmapped = bring_unmapped?(includes_param) + p = ont.property(prop, submission, display_all_attributes: bring_unmapped) error 404, "Property #{prop} not found in ontology #{ont.id.to_s}" if p.nil? reply 200, p end @@ -51,7 +52,7 @@ class PropertiesController < ApplicationController get '/:property/tree' do prop = params[:property] ont, submission = get_ontology_and_submission - p = ont.property(prop, submission) + p = ont.property(prop, submission, display_all_attributes: false) error 404, "Property #{prop} not found in ontology #{ont.id.to_s}" if p.nil? root_tree = p.tree @@ -79,7 +80,7 @@ class PropertiesController < ApplicationController get '/:property/ancestors' do prop = params[:property] ont, submission = get_ontology_and_submission - p = ont.property(prop, submission) + p = ont.property(prop, submission, display_all_attributes: false) error 404, "Property #{prop} not found in ontology #{ont.id.to_s}" if p.nil? ancestors = p.ancestors p.class.in(submission).models(ancestors).include(:label, :definition).all @@ -91,7 +92,7 @@ class PropertiesController < ApplicationController get '/:property/descendants' do prop = params[:property] ont, submission = get_ontology_and_submission - p = ont.property(prop, submission) + p = ont.property(prop, submission, display_all_attributes: false) error 404, "Property #{prop} not found in ontology #{ont.id.to_s}" if p.nil? descendants = p.descendants p.class.in(submission).models(descendants).include(:label, :definition).all @@ -103,7 +104,7 @@ class PropertiesController < ApplicationController get '/:property/parents' do prop = params[:property] ont, submission = get_ontology_and_submission - p = ont.property(prop, submission) + p = ont.property(prop, submission, display_all_attributes: false) error 404, "Property #{prop} not found in ontology #{ont.id.to_s}" if p.nil? p.bring(:parents) @@ -120,7 +121,7 @@ class PropertiesController < ApplicationController get '/:property/children' do prop = params[:property] ont, submission = get_ontology_and_submission - p = ont.property(prop, submission) + p = ont.property(prop, submission, display_all_attributes: false) error 404, "Property #{prop} not found in ontology #{ont.id.to_s}" if p.nil? p.bring(:children) diff --git a/controllers/properties_search_controller.rb b/controllers/properties_search_controller.rb index 29d6b7726..6c5b6cdfb 100644 --- a/controllers/properties_search_controller.rb +++ b/controllers/properties_search_controller.rb @@ -22,7 +22,7 @@ def process_search(params=nil) # puts "Properties query: #{query}, params: #{params}" set_page_params(params) docs = Array.new - resp = LinkedData::Models::Class.search(query, params, :property) + resp = LinkedData::Models::OntologyProperty.search(query, params) total_found = resp["response"]["numFound"] add_matched_fields(resp, Sinatra::Helpers::SearchHelper::MATCH_TYPE_LABEL) ontology_rank = LinkedData::Models::Ontology.rank diff --git a/controllers/replies_controller.rb b/controllers/replies_controller.rb index 081238a17..88ffcd48d 100644 --- a/controllers/replies_controller.rb +++ b/controllers/replies_controller.rb @@ -12,7 +12,7 @@ class RepliesController < ApplicationController namespace "/replies" do # Display all replies - get "?:include_threads?" do + get '' do check_last_modified_collection(LinkedData::Models::Notes::Reply) replies = LinkedData::Models::Notes::Reply.where.include(LinkedData::Models::Notes::Reply.goo_attrs_to_load(includes_param)).to_a reply replies @@ -82,4 +82,4 @@ class RepliesController < ApplicationController halt 204 end end -end \ No newline at end of file +end diff --git a/controllers/search_controller.rb b/controllers/search_controller.rb index 280944a6b..88e18c3a3 100644 --- a/controllers/search_controller.rb +++ b/controllers/search_controller.rb @@ -4,64 +4,101 @@ class SearchController < ApplicationController namespace "/search" do # execute a search query + get do - process_search() + page = process_search + reply 200, page end post do - process_search() + page = process_search + reply 200, page end - private - - def process_search(params=nil) - params ||= @params - text = params["q"] - - query = get_term_search_query(text, params) - # puts "Edismax query: #{query}, params: #{params}" - set_page_params(params) - - docs = Array.new - resp = LinkedData::Models::Class.search(query, params) - total_found = resp["response"]["numFound"] - add_matched_fields(resp, Sinatra::Helpers::SearchHelper::MATCH_TYPE_PREFLABEL) - ontology_rank = LinkedData::Models::Ontology.rank - - resp["response"]["docs"].each do |doc| - doc = doc.symbolize_keys - # NCBO-974 - doc[:matchType] = resp["match_types"][doc[:id]] - resource_id = doc[:resource_id] - doc.delete :resource_id - doc[:id] = resource_id - # TODO: The `rescue next` on the following line shouldn't be here - # However, at some point we didn't store the ontologyId in the index - # and these records haven't been cleared out so this is getting skipped - ontology_uri = doc[:ontologyId].sub(/\/submissions\/.*/, "") rescue next - ontology = LinkedData::Models::Ontology.read_only(id: ontology_uri, acronym: doc[:submissionAcronym]) - submission = LinkedData::Models::OntologySubmission.read_only(id: doc[:ontologyId], ontology: ontology) - doc[:submission] = submission - doc[:ontology_rank] = (ontology_rank[doc[:submissionAcronym]] && !ontology_rank[doc[:submissionAcronym]].empty?) ? ontology_rank[doc[:submissionAcronym]][:normalizedScore] : 0.0 - doc[:properties] = MultiJson.load(doc.delete(:propertyRaw)) if include_param_contains?(:properties) - instance = doc[:provisional] ? LinkedData::Models::ProvisionalClass.read_only(doc) : LinkedData::Models::Class.read_only(doc) - filter_language_attributes(params, instance) - docs.push(instance) - end + namespace "/ontologies" do + get do + query = params[:query] || params[:q] + options = get_ontology_metadata_search_options(params) + page_data = search(Ontology, query, options) + total_found = page_data.aggregate + ontology_rank = LinkedData::Models::Ontology.rank + docs = {} + acronyms_ids = {} + + page_data.each do |doc| + resource_id = doc["resource_id"] + id = doc["submissionId_i"] + acronym = doc["ontology_acronym_text"] + old_resource_id = acronyms_ids[acronym] + old_id = old_resource_id.split('/').last.to_i rescue 0 + + already_found = (old_id && id && (id <= old_id)) + not_restricted = (doc["ontology_viewingRestriction_t"]&.eql?('public') || current_user&.admin?) + user_not_restricted = not_restricted || + Array(doc["ontology_viewingRestriction_txt"]).any? {|u| u.split('/').last == current_user&.username} || + Array(doc["ontology_acl_txt"]).any? {|u| u.split('/').last == current_user&.username} + + user_restricted = !user_not_restricted - unless params['sort'] - if !text.nil? && text[-1] == '*' - docs.sort! {|a, b| [b[:score], a[:prefLabelExact].downcase, b[:ontology_rank]] <=> [a[:score], b[:prefLabelExact].downcase, a[:ontology_rank]]} - else - docs.sort! {|a, b| [b[:score], b[:ontology_rank]] <=> [a[:score], a[:ontology_rank]]} + if acronym.blank? || already_found || user_restricted + total_found -= 1 + next + end + + docs.delete(old_resource_id) + acronyms_ids[acronym] = resource_id + + doc["ontology_rank"] = ontology_rank.dig(doc["ontology_acronym_text"], :normalizedScore) || 0.0 + docs[resource_id] = doc end + + docs = docs.values + + docs.sort! { |a, b| [b["score"], b["ontology_rank"]] <=> [a["score"], a["ontology_rank"]] } unless params[:sort].present? + + page = page_object(docs, total_found) + + reply 200, page end - #need to return a Page object - page = page_object(docs, total_found) + get '/content' do + query = params[:query] || params[:q] + page, page_size = page_params - reply 200, page + ontologies = params.fetch("ontologies", "").split(',') + + unless current_user&.admin? + restricted_acronyms = restricted_ontologies_to_acronyms(params) + ontologies = ontologies.empty? ? restricted_acronyms : ontologies & restricted_acronyms + end + + types = params.fetch("types", "").split(',') + qf = params.fetch("qf", "") + + qf = [ + "ontology_t^100 resource_id^10", + "http___www.w3.org_2004_02_skos_core_prefLabel_txt^30", + "http___www.w3.org_2004_02_skos_core_prefLabel_t^30", + "http___www.w3.org_2000_01_rdf-schema_label_txt^30", + "http___www.w3.org_2000_01_rdf-schema_label_t^30", + ].join(' ') if qf.blank? + + fq = [] + + fq << ontologies.map { |x| "ontology_t:\"#{x}\"" }.join(' OR ') unless ontologies.blank? + fq << types.map { |x| "type_t:\"#{x}\" OR type_txt:\"#{x}\"" }.join(' OR ') unless types.blank? + + + conn = SOLR::SolrConnector.new(Goo.search_conf, :ontology_data) + resp = conn.search(query, fq: fq, qf: qf, defType: "edismax", + start: (page - 1) * page_size, rows: page_size) + + total_found = resp["response"]["numFound"] + docs = resp["response"]["docs"] + + reply 200, page_object(docs, total_found) + end end end -end +end \ No newline at end of file diff --git a/controllers/users_controller.rb b/controllers/users_controller.rb index 41fc155ca..4e4f4db25 100644 --- a/controllers/users_controller.rb +++ b/controllers/users_controller.rb @@ -1,15 +1,22 @@ + class UsersController < ApplicationController namespace "/users" do - post "/authenticate" do - user_id = params["user"] - user_password = params["password"] + # Modify params to show all user attributes params["display"] = User.attributes.join(",") - user = User.find(user_id).include(User.goo_attrs_to_load(includes_param) + [:passwordHash]).first - authenticated = user.authenticate(user_password) unless user.nil? - error 401, "Username/password combination invalid" unless authenticated - user.show_apikey = true + + if params["access_token"] + user = oauth_authenticate(params) + user.bring(*User.goo_attrs_to_load(includes_param)) + else + user = login_password_authenticate(params) + end + unless user.nil? + user.update_last_login + user.show_apikey = true + update_current_user(user) + end reply user end @@ -19,20 +26,15 @@ class UsersController < ApplicationController # to click and login to the UI. The token can then be provided to # the /reset_password endpoint to actually reset the password. post "/create_reset_password_token" do - email = params["email"] + email = params["email"] username = params["username"] - user = LinkedData::Models::User.where(email: email, username: username).include(LinkedData::Models::User.attributes).first - error 404, "User not found" unless user - reset_token = token(36) - user.resetToken = reset_token - user.resetTokenExpireTime = Time.now.to_i + 1.hours.to_i + user = send_reset_token(email, username) + if user.valid? - user.save(override_security: true) - LinkedData::Utils::Notifications.reset_password(user, reset_token) + halt 204 else error 422, user.errors end - halt 204 end ## @@ -41,31 +43,15 @@ class UsersController < ApplicationController # can be used to log a user in. This will allow them to change their # password and update the user object. post "/reset_password" do - email = params["email"] || "" - username = params["username"] || "" - token = params["token"] || "" + email = params["email"] || "" + username = params["username"] || "" + token = params["token"] || "" params["display"] = User.attributes.join(",") # used to serialize everything via the serializer - user = LinkedData::Models::User.where(email: email, username: username).include(User.goo_attrs_to_load(includes_param)).first - error 404, "User not found" unless user - - user.bring(:resetToken) - user.bring(:resetTokenExpireTime) - user.bring(:passwordHash) - - if token.eql?(user.resetToken) - error 401, "Invalid password reset token" if user.resetTokenExpireTime.nil? - error 401, "The password reset token expired" if user.resetTokenExpireTime < Time.now.to_i - user.resetToken = nil - user.resetTokenExpireTime = nil - - if user.valid? - user.save(override_security: true) - user.show_apikey = true - reply user - else - error 422, "Error resetting password" - end + + user, token_accepted = reset_password(email, username, token) + if token_accepted + reply user else error 401, "Password reset not authorized with this token" end @@ -86,6 +72,14 @@ class UsersController < ApplicationController reply user end + # Display a single user + get '/:username/ontologies' do + user = User.find(params[:username]).first + error 404, "Cannot find user with username `#{params['username']}`" if user.nil? + check_last_modified(user) + reply user.createdOntologies + end + # Create user post do create_user @@ -118,21 +112,15 @@ class UsersController < ApplicationController private - def token(len) - chars = ("a".."z").to_a + ("A".."Z").to_a + ("1".."9").to_a - token = "" - 1.upto(len) { |i| token << chars[rand(chars.size-1)] } - token - end - def create_user + def create_user(send_notifications: true) params ||= @params user = User.find(params["username"]).first error 409, "User with username `#{params["username"]}` already exists" unless user.nil? params.delete("role") unless current_user.admin? user = instance_from_params(User, params) if user.valid? - user.save + user.save(send_notifications: send_notifications) else error 422, user.errors end diff --git a/docker-compose.yml b/docker-compose.yml deleted file mode 100644 index 8f70e7196..000000000 --- a/docker-compose.yml +++ /dev/null @@ -1,150 +0,0 @@ -x-app: &app - build: - context: . - args: - RUBY_VERSION: '3.1' - # Increase the version number in the image tag every time Dockerfile or its arguments is changed - image: ontologies_api:0.0.6 - environment: &env - BUNDLE_PATH: /srv/ontoportal/bundle - # default bundle config resolves to /usr/local/bundle/config inside of the container - # we are setting it to local app directory if we need to use 'bundle config local' - BUNDLE_APP_CONFIG: /srv/ontoportal/ontologies_api/.bundle - COVERAGE: 'true' - GOO_REDIS_HOST: redis-ut - REDIS_GOO_CACHE_HOST: redis-ut - REDIS_HTTP_CACHE_HOST: redis-ut - REDIS_PERSISTENT_HOST: redis-ut - REDIS_PORT: 6379 - SOLR_TERM_SEARCH_URL: http://solr-ut:8983/solr/term_search_core1 - SOLR_PROP_SEARCH_URL: http://solr-ut:8983/solr/prop_search_core1 - MGREP_HOST: mgrep-ut - MGREP_PORT: 55556 - stdin_open: true - tty: true - command: "bundle exec rackup -o 0.0.0.0 --port 9393" - ports: - - 9393:9393 - volumes: - # bundle volume for hosting gems installed by bundle; it helps in local development with gem udpates - - bundle:/srv/ontoportal/bundle - # api code - - .:/srv/ontoportal/ontologies_api - # mount directory containing development version of the gems if you need to use 'bundle config local' - #- /Users/alexskr/ontoportal:/Users/alexskr/ontoportal - depends_on: &depends_on - solr-ut: - condition: service_healthy - redis-ut: - condition: service_healthy - mgrep-ut: - condition: service_healthy - -services: - api: - <<: *app - environment: - <<: *env - GOO_BACKEND_NAME: 4store - GOO_PORT: 9000 - GOO_HOST: 4store-ut - GOO_PATH_QUERY: /sparql/ - GOO_PATH_DATA: /data/ - GOO_PATH_UPDATE: /update/ - profiles: - - 4store - depends_on: - <<: *depends_on - 4store-ut: - condition: service_started - - api-agraph: - <<: *app - environment: - <<: *env - GOO_BACKEND_NAME: ag - GOO_PORT: 10035 - GOO_HOST: agraph-ut - GOO_PATH_QUERY: /repositories/ontoportal_test - GOO_PATH_DATA: /repositories/ontoportal_test/statements - GOO_PATH_UPDATE: /repositories/ontoportal_test/statements - profiles: - - agraph - depends_on: - <<: *depends_on - agraph-ut: - condition: service_healthy - - redis-ut: - image: redis - healthcheck: - test: redis-cli ping - interval: 10s - timeout: 3s - retries: 10 - - 4store-ut: - image: bde2020/4store - platform: linux/amd64 - #volume: fourstore:/var/lib/4store - command: > - bash -c "4s-backend-setup --segments 4 ontoportal_kb - && 4s-backend ontoportal_kb - && 4s-httpd -D -s-1 -p 9000 ontoportal_kb" - profiles: - - 4store - - solr-ut: - image: solr:8 - volumes: - - ./test/solr/configsets:/configsets:ro - ports: - - "8983:8983" - command: > - bash -c "precreate-core term_search_core1 /configsets/term_search - && precreate-core prop_search_core1 /configsets/property_search - && solr-foreground" - healthcheck: - test: [ "CMD-SHELL", "curl -sf http://localhost:8983/solr/term_search_core1/admin/ping?wt=json | grep -iq '\"status\":\"OK\"}' || exit 1" ] - start_period: 5s - interval: 10s - timeout: 5s - retries: 5 - - mgrep-ut: - image: ontoportal/mgrep:0.0.2 - platform: linux/amd64 - healthcheck: - test: ["CMD", "nc", "-z", "-v", "127.0.0.1", "55556"] - start_period: 3s - interval: 10s - timeout: 5s - retries: 5 - - agraph-ut: - image: franzinc/agraph:v8.1.0 - platform: linux/amd64 - environment: - - AGRAPH_SUPER_USER=test - - AGRAPH_SUPER_PASSWORD=xyzzy - shm_size: 1g - # ports: - # - 10035:10035 - command: > - bash -c "/agraph/bin/agraph-control --config /agraph/etc/agraph.cfg start - ; agtool repos create ontoportal_test - ; agtool users add anonymous - ; agtool users grant anonymous root:ontoportal_test:rw - ; tail -f /agraph/data/agraph.log" - healthcheck: - test: ["CMD-SHELL", "agtool storage-report ontoportal_test || exit 1"] - start_period: 30s - interval: 20s - timeout: 10s - retries: 10 - profiles: - - agraph - -volumes: - bundle: - diff --git a/helpers/application_helper.rb b/helpers/application_helper.rb index e97366916..9bcc61cc0 100644 --- a/helpers/application_helper.rb +++ b/helpers/application_helper.rb @@ -13,7 +13,7 @@ module ApplicationHelper ## # Escape text for use in html def h(text) - Rack::Utils.escape_html(text) + Rack::Utils.escape_html(text).gsub('/', '/') end ## @@ -188,9 +188,19 @@ def halt(*response) status = obj obj = nil end - status, obj = response.first, response.last if response.length == 2 - status, headers, obj = response.first, response[1], response.last if response.length == 3 - if obj.is_a?(Rack::File) # Avoid the serializer when returning files + + if response.length == 2 + status = response.first + obj = response.last + end + + if response.length == 3 + status = response.first + headers = response[1] + obj = response.last + end + + if obj.is_a?(Rack::Files) || obj.is_a?(Rack::Files::Iterator) # Avoid the serializer when returning files super(response) else super(LinkedData::Serializer.build_response(@env, status: status, headers: headers, ld_object: obj)) @@ -215,7 +225,7 @@ def error(*message) # Look for the includes parameter and provide a formatted list of attributes def includes_param if @params["display"] - return @params["display"].split(",").map {|e| e.to_sym} + return @params["display"].split(",").map { |e| e.to_sym } end Array.new end @@ -223,14 +233,14 @@ def includes_param ## # Look for the ontologies acronym and give back a formatted list of ontolody id uris # This can be called without passing an argument and it will use the values from the current request - def ontologies_param(params=nil) + def ontologies_param(params = nil) params ||= @params if params["ontologies"] # Get list - ontologies = params["ontologies"].split(",").map {|o| o.strip} + ontologies = params["ontologies"].split(",").map { |o| o.strip } # When they aren't URIs, make them URIs - ontologies.map! {|o| o.start_with?("http://") ? replace_url_prefix(o) : ontology_uri_from_acronym(o)} + ontologies.map! { |o| o.start_with?("http://") ? replace_url_prefix(o) : ontology_uri_from_acronym(o) } if ontologies.include? nil error 404, "The ontologies parameter `[#{params["ontologies"]}]` includes non-existent acronyms. Notice that acronyms are case sensitive." end @@ -239,7 +249,7 @@ def ontologies_param(params=nil) Array.new end - def restricted_ontologies(params=nil) + def restricted_ontologies(params = nil) params ||= @params found_onts = false @@ -268,23 +278,23 @@ def restricted_ontologies(params=nil) return onts end - def restricted_ontologies_to_acronyms(params=nil, onts=nil) + def restricted_ontologies_to_acronyms(params = nil, onts = nil) onts ||= restricted_ontologies(params) - return onts.map {|o| o.acronym } + return onts.map { |o| o.acronym } end - def ontologies_param_to_acronyms(params=nil) + def ontologies_param_to_acronyms(params = nil) ontResourceIds = ontologies_param(params) - return ontResourceIds.map { |ontResourceId| ontResourceId.to_s.split('/')[-1]} + return ontResourceIds.map { |ontResourceId| ontResourceId.to_s.split('/')[-1] } end ## # Get semantic types parameter in the form [semantic_types=T099,T085,T345] - def semantic_types_param(params=nil) + def semantic_types_param(params = nil) params ||= @params if params["semantic_types"] - semanticTypes = params["semantic_types"].split(",").map {|o| o.strip} + semanticTypes = params["semantic_types"].split(",").map { |o| o.strip } return semanticTypes end Array.new @@ -292,10 +302,10 @@ def semantic_types_param(params=nil) ## # Get cui parameter in the form [cui=C0302369,C0522224,C0176617] - def cui_param(params=nil) + def cui_param(params = nil) params ||= @params if params["cui"] - cui = params["cui"].split(",").map {|o| o.strip} + cui = params["cui"].split(",").map { |o| o.strip } return cui end Array.new @@ -306,7 +316,7 @@ def month_param(params=nil) params ||= @params if params["month"] month = params["month"].strip - if %r{(?^(0[1-9]|[1-9]|1[0-2])$)}x === month + if /(?^(0[1-9]|[1-9]|1[0-2])$)/x === month return month.to_i.to_s end end @@ -314,11 +324,11 @@ def month_param(params=nil) end # validates year for starting with 1 or 2 and containing 4 digits - def year_param(params=nil) + def year_param(params = nil) params ||= @params if params["year"] year = params["year"].strip - if %r{(?^([1-2]\d{3})$)}x === year + if /(?^([1-2]\d{3})$)/x === year return year.to_i.to_s end end @@ -358,14 +368,14 @@ def ontology_from_acronym(acronym) def ontology_objects_from_params(params = nil) ontologies = Set.new(ontologies_param(params)) all_onts = LinkedData::Models::Ontology.where.include(LinkedData::Models::Ontology.goo_attrs_to_load).to_a - all_onts.select {|o| ontologies.include?(o.id.to_s)} + all_onts.select { |o| ontologies.include?(o.id.to_s) } end def ontology_uri_acronym_map cached_map = naive_expiring_cache_read(__method__) return cached_map if cached_map map = {} - LinkedData::Models::Ontology.where.include(:acronym).all.each {|o| map[o.acronym] = o.id.to_s} + LinkedData::Models::Ontology.where.include(:acronym).all.each { |o| map[o.acronym] = o.id.to_s } naive_expiring_cache_write(__method__, map) map end @@ -374,7 +384,7 @@ def acronym_ontology_uri_map cached_map = naive_expiring_cache_read(__method__) return cached_map if cached_map map = {} - LinkedData::Models::Ontology.where.include(:acronym).all.each {|o| map[o.id.to_s] = o.acronym} + LinkedData::Models::Ontology.where.include(:acronym).all.each { |o| map[o.id.to_s] = o.acronym } naive_expiring_cache_write(__method__, map) map end @@ -414,6 +424,21 @@ def replace_url_prefix(id) LinkedData::Models::Base.replace_url_prefix_to_id(id) end + def retrieve_latest_submissions(options = {}) + submissions = retrieve_submissions(options) + + latest_submissions = page? ? submissions : {} # latest_submission doest not work with pagination + submissions.each do |sub| + unless page? + next if include_ready?(options) && !sub.ready? + next if sub.ontology.nil? + latest_submissions[sub.ontology.acronym] ||= sub + latest_submissions[sub.ontology.acronym] = sub if sub.submissionId.to_i > latest_submissions[sub.ontology.acronym].submissionId.to_i + end + end + latest_submissions + end + def get_ontology_and_submission ont = Ontology.find(@params["ontology"]) .include(:acronym, :administeredBy, :acl, :viewingRestriction) @@ -453,6 +478,24 @@ def include_param_contains?(str) return class_params_include || params_include end + ## + # Checks to see if the request has a file attached + def request_has_file? + @params.any? { |p, v| v.instance_of?(Hash) && v.key?(:tempfile) && v[:tempfile].instance_of?(Tempfile) } + end + + ## + # Looks for a file that was included as a multipart in a request + def file_from_request + @params.each_value do |value| + if value.is_a?(Hash) && value.key?(:tempfile) && value[:tempfile].instance_of?(Tempfile) + return value[:filename], value[:tempfile] + end + end + + [nil, nil] + end + # Long-operation helper modeled after the original from AdminController#process_long_operation # Start: "processing" # Success (empty/nil): "done" @@ -507,6 +550,14 @@ def redis Redis.new(host: Annotator.settings.annotator_redis_host, port: Annotator.settings.annotator_redis_port, timeout: 30) end + def redis_goo + Redis.new(host: LinkedData.settings.goo_redis_host, port: LinkedData.settings.goo_redis_port, timeout: 30) + end + + def redis_http + Redis.new(host: LinkedData.settings.http_redis_host, port: LinkedData.settings.http_redis_port, timeout: 30) + end + private def naive_expiring_cache_write(key, object, timeout = 60) @@ -551,6 +602,11 @@ def assign_creator_if_applicable(obj) obj.creator = current_user end + + def update_current_user(user) + Thread.current[:remote_user] = user + env.update("REMOTE_USER" => user) + end end end end diff --git a/helpers/ontology_helper.rb b/helpers/ontology_helper.rb index e5798ff7d..b34724f74 100644 --- a/helpers/ontology_helper.rb +++ b/helpers/ontology_helper.rb @@ -16,7 +16,12 @@ def create_submission(ont) ont_submission.submissionId = submission_id # Get file info - add_file_to_submission(ont, ont_submission) + filename, tmpfile = add_file_to_submission(ont, ont_submission) + # if no actual file was uploaded, we remove the file parameters + if filename.nil? && tmpfile.nil? + params.delete("uploadFilePath") + params.delete("diffFilePath") + end # Add new format if it doesn't exist if ont_submission.hasOntologyLanguage.nil? @@ -35,23 +40,6 @@ def create_submission(ont) ont_submission end - ## - # Checks to see if the request has a file attached - def request_has_file? - @params.any? {|p,v| v.instance_of?(Hash) && v.key?(:tempfile) && v[:tempfile].instance_of?(Tempfile)} - end - - ## - # Looks for a file that was included as a multipart in a request - def file_from_request - @params.each do |param, value| - if value.instance_of?(Hash) && value.has_key?(:tempfile) && value[:tempfile].instance_of?(Tempfile) - return value[:filename], value[:tempfile] - end - end - return nil, nil - end - ## # Add a file to the submission if a file exists in the params def add_file_to_submission(ont, submission) @@ -69,7 +57,7 @@ def add_file_to_submission(ont, submission) file_location = OntologySubmission.copy_file_repository(ont.acronym, submission.submissionId, tmpfile, filename) submission.uploadFilePath = file_location end - return filename, tmpfile + [filename, tmpfile] end end end diff --git a/helpers/properties_search_helper.rb b/helpers/properties_search_helper.rb index c3567eddd..b4597b0a9 100644 --- a/helpers/properties_search_helper.rb +++ b/helpers/properties_search_helper.rb @@ -45,7 +45,7 @@ def get_properties_search_query(text, params) onts.select! { |o| ont_type = o.ontologyType.nil? ? "ONTOLOGY" : o.ontologyType.get_code_from_id; ontology_types.include?(ont_type) } unless ontology_types.empty? acronyms = restricted_ontologies_to_acronyms(params, onts) - filter_query = get_quoted_field_query_param(acronyms, "OR", "submissionAcronym") + filter_query = get_terms_field_query_param(acronyms, "submissionAcronym") ontology_types_clause = ontology_types.empty? ? "" : get_quoted_field_query_param(ontology_types, "OR", "ontologyType") filter_query = "#{filter_query} AND #{ontology_types_clause}" unless (ontology_types_clause.empty?) diff --git a/helpers/search_helper.rb b/helpers/search_helper.rb index 80eec4cc2..87c1e723e 100644 --- a/helpers/search_helper.rb +++ b/helpers/search_helper.rb @@ -19,7 +19,6 @@ module SearchHelper VALUESET_ROOTS_ONLY_PARAM = "valueset_roots_only" VALUESET_EXCLUDE_ROOTS_PARAM = "valueset_exclude_roots" ONTOLOGY_TYPES_PARAM = "ontology_types" - LANGUAGES_PARAM = "lang" ALSO_SEARCH_VIEWS = "also_search_views" # NCBO-961 MATCH_HTML_PRE = "" @@ -27,10 +26,8 @@ module SearchHelper MATCH_TYPE_PREFLABEL = "prefLabel" MATCH_TYPE_SYNONYM = "synonym" MATCH_TYPE_PROPERTY = "property" - MATCH_TYPE_DEFINITION = "definition" MATCH_TYPE_LABEL = "label" MATCH_TYPE_LABELGENERATED = "labelGenerated" - NO_LANGUAGE_SUFFIX = "none" MATCH_TYPE_MAP = { "resource_id" => "id", @@ -87,10 +84,6 @@ def get_term_search_query(text, params={}) end end - lang = params["lang"] || params["language"] - lang_suffix = lang && !lang.eql?("all") ? "_#{lang}" : "" - - query = "" params["defType"] = "edismax" params["stopwords"] = "true" params["lowercaseOperators"] = "true" @@ -102,29 +95,54 @@ def get_term_search_query(text, params={}) params["hl.simple.pre"] = MATCH_HTML_PRE params["hl.simple.post"] = MATCH_HTML_POST - # text.gsub!(/\*+$/, '') - if params[EXACT_MATCH_PARAM] == "true" query = "\"#{solr_escape(text)}\"" - params["qf"] = "resource_id^20 notation^20 oboId^20 prefLabelExact#{lang_suffix}^10 synonymExact#{lang_suffix} #{QUERYLESS_FIELDS_STR_NO_IDS}" - params["hl.fl"] = "resource_id prefLabelExact#{lang_suffix} synonymExact#{lang_suffix} #{QUERYLESS_FIELDS_STR}" + params["qf"] = "resource_id^20 notation^20 oboId^20 #{add_lang_suffix('prefLabelExact', '^10')} #{add_lang_suffix('synonymExact')} #{QUERYLESS_FIELDS_STR_NO_IDS}" + params["hl.fl"] = "resource_id #{add_lang_suffix('prefLabelExact')} #{add_lang_suffix('synonymExact')} #{QUERYLESS_FIELDS_STR}" elsif params[SUGGEST_PARAM] == "true" || text[-1] == '*' text.gsub!(/\*+$/, '') query = "\"#{solr_escape(text)}\"" params["qt"] = "/suggest_ncbo" - params["qf"] = " prefLabelExact#{lang_suffix}^100 prefLabelSuggestEdge#{lang_suffix}^50 synonymSuggestEdge#{lang_suffix}^10 prefLabelSuggestNgram#{lang_suffix} synonymSuggestNgram#{lang_suffix} resource_id #{QUERYLESS_FIELDS_STR}" - params["pf"] = "prefLabelSuggest#{lang_suffix}^50" - params["hl.fl"] = "prefLabelExact#{lang_suffix} prefLabelSuggestEdge#{lang_suffix} synonymSuggestEdge#{lang_suffix} prefLabelSuggestNgram#{lang_suffix} synonymSuggestNgram#{lang_suffix} resource_id #{QUERYLESS_FIELDS_STR}" + params["qf"] = [ + add_lang_suffix('prefLabelExact', '^100'), + add_lang_suffix('prefLabelSuggestEdge', '^50'), + add_lang_suffix('synonymSuggestEdge', '^10'), + add_lang_suffix('prefLabelSuggestNgram'), + add_lang_suffix('synonymSuggestNgram'), + "resource_id #{QUERYLESS_FIELDS_STR}" + ].join(' ') + + params["pf"] = add_lang_suffix('prefLabelSuggest', '^50') + + params["hl.fl"] = [ + add_lang_suffix('prefLabelExact'), + add_lang_suffix('prefLabelSuggestEdge'), + add_lang_suffix('synonymSuggestEdge'), + add_lang_suffix('prefLabelSuggestNgram'), + add_lang_suffix('synonymSuggestNgram'), + "resource_id #{QUERYLESS_FIELDS_STR}" + ].join(' ') else if text.strip.empty? query = '*' else query = solr_escape(text) end - params["qf"] = "resource_id^100 notation^100 oboId^100 prefLabelExact#{lang_suffix}^90 prefLabel#{lang_suffix}^70 synonymExact#{lang_suffix}^50 synonym#{lang_suffix}^10 #{QUERYLESS_FIELDS_STR_NO_IDS}" + + params["qf"] = [ + "resource_id^100", + "notation^100", + "oboId^100", + add_lang_suffix('prefLabelExact', '^90'), + add_lang_suffix('prefLabel', '^70'), + add_lang_suffix('synonymExact', '^50'), + add_lang_suffix('synonym', '^10'), + QUERYLESS_FIELDS_STR_NO_IDS + ].join(' ') + params["qf"] << " property" if params[INCLUDE_PROPERTIES_PARAM] == "true" params["bq"] = "idAcronymMatch:true^80" - params["hl.fl"] = "resource_id prefLabelExact#{lang_suffix} prefLabel#{lang_suffix} synonymExact#{lang_suffix} synonym#{lang_suffix} #{QUERYLESS_FIELDS_STR}" + params["hl.fl"] = "resource_id #{add_lang_suffix('prefLabelExact')} #{ add_lang_suffix('prefLabel')} #{add_lang_suffix('synonymExact')} #{add_lang_suffix('synonym')} #{QUERYLESS_FIELDS_STR}" params["hl.fl"] = "#{params["hl.fl"]} property" if params[INCLUDE_PROPERTIES_PARAM] == "true" end @@ -139,7 +157,7 @@ def get_term_search_query(text, params={}) onts = restricted_ontologies(params) onts.select! { |o| ont_type = o.ontologyType.nil? ? "ONTOLOGY" : o.ontologyType.get_code_from_id; ontology_types.include?(ont_type) } unless ontology_types.empty? acronyms = restricted_ontologies_to_acronyms(params, onts) - filter_query = get_quoted_field_query_param(acronyms, "OR", "submissionAcronym") + filter_query = get_terms_field_query_param(acronyms, "submissionAcronym") # add subtree filter query if not empty filter_query << subtree_filter_query @@ -156,7 +174,7 @@ def get_term_search_query(text, params={}) valueset_root_ids = get_valueset_root_ids(onts, params) unless valueset_root_ids.empty? - valueset_root_ids_clause = get_quoted_field_query_param(valueset_root_ids, "OR", "resource_id") + valueset_root_ids_clause = get_terms_field_query_param(valueset_root_ids, "resource_id") valueset_root_ids_clause = valueset_exclude_roots == "true" ? "AND -#{valueset_root_ids_clause}" : "AND #{valueset_root_ids_clause}" filter_query = "#{filter_query} #{valueset_root_ids_clause}" end @@ -185,10 +203,6 @@ def get_term_search_query(text, params={}) params["fq"] = filter_query params["q"] = query - - # binding.pry - - query end @@ -230,6 +244,72 @@ def add_matched_fields(solr_response, default_match) solr_response["match_types"] = all_matches end + def portal_language + Goo.main_languages.first + end + + def request_languages + lang = params['lang'] || params['languages'] + + return [portal_language] if lang.blank? + + lang.split(',') + end + + def request_multiple_languages? + request_languages.size > 1 || request_all_languages? + end + + def request_languages? + !(params['lang'] || params['language']).blank? + end + + def request_all_languages? + request_languages.first.eql?('all') + end + + def add_lang_suffix(attr, rank = "") + if request_languages? && !request_all_languages? + languages = request_languages + languages.map { |lang| "#{attr}_#{lang}#{rank} " }.join + else + "#{attr}#{rank}" + end + end + + def pref_label_by_language(doc) + Array(doc["prefLabel_#{request_languages.first}".to_sym]).first || Array(doc["prefLabel_none".to_sym]).first || Array(doc[:prefLabel]).first + end + + def filter_attrs_by_language(doc) + lang_values = {} + doc.each do |k, v| + attr, lang = k.to_s.split('_') + + next if [:ontology_rank, :resource_id, :resource_model].include?(k) + next if lang.blank? || attr.blank? + next if !(request_languages + %w[none]).include?(lang) && !request_all_languages? + + lang_values[attr.to_sym] ||= {} + lang_values[attr.to_sym][lang] ||= [] + lang_values[attr.to_sym][lang] += v + end + + if request_multiple_languages? + lang_values.each do |k, lang_vals| + doc[k] = lang_vals + end + else + lang_values.each do |k, lang_vals| + doc[k] = lang_vals.map { |l, v| l.eql?('none') ? nil : v }.compact.flatten + Array(lang_vals['none']) + end + + doc[:prefLabel] = pref_label_by_language(doc) + end + + doc + end + # see https://github.com/rsolr/rsolr/issues/101 # and https://github.com/projecthydra/active_fedora/commit/75b4afb248ee61d9edb56911b2ef51f30f1ce17f # @@ -305,6 +385,16 @@ def get_non_quoted_field_query_param(words, fieldName="") query end + def get_terms_field_query_param(values, field_name) + return "" if values.nil? || values.empty? + + escaped_values = values.map do |value| + value.to_s.gsub('\\', '\\\\\\').gsub(',', '\\,').gsub('"', '\\"') + end + + "_query_:\"{!terms f=#{field_name}}#{escaped_values.join(',')}\"" + end + def set_page_params(params={}) pagenum, pagesize = page_params(params) params["page"] = pagenum @@ -342,7 +432,7 @@ def populate_classes_from_search(classes, ontology_acronyms=nil) params["fq"] << " AND #{get_quoted_field_query_param(class_ids, "OR", "resource_id")}" params["rows"] = 99999 # Replace fake query with wildcard - resp = LinkedData::Models::Class.search("*:*", params) + resp = LinkedData::Models::Class.submit_search_query("*:*", params) classes_hash = {} resp["response"]["docs"].each do |doc| @@ -357,46 +447,153 @@ def populate_classes_from_search(classes, ontology_acronyms=nil) doc[:submission] = old_class.submission doc[:properties] = MultiJson.load(doc.delete(:propertyRaw)) if include_param_contains?(:properties) instance = LinkedData::Models::Class.read_only(doc) - filter_language_attributes(@params, instance) + instance.prefLabel = pref_label_by_language(doc) classes_hash[ont_uri_class_uri] = instance end classes_hash end - def filter_language_attribute(params, class_instance, attr, is_single) - if class_instance.respond_to?(attr) - lang_param = (params["lang"] || params["language"])&.downcase - lang_suffix = lang_param && !lang_param.eql?("all") ? "_#{lang_param}" : "" - - if !lang_suffix.empty? && class_instance.respond_to?("#{attr}#{lang_suffix}") - class_instance[attr] = is_single ? class_instance["#{attr}#{lang_suffix}"][0] : class_instance["#{attr}#{lang_suffix}"] - elsif !lang_param.eql?("all") - site_label = Goo.main_languages[0] - - if class_instance.respond_to?("#{attr}_#{site_label}") && class_instance["#{attr}_#{site_label}"] - class_instance[attr] = is_single ? class_instance["#{attr}_#{site_label}"][0] : class_instance["#{attr}_#{site_label}"] - elsif class_instance.respond_to?("#{attr}_#{NO_LANGUAGE_SUFFIX}") && class_instance["#{attr}_#{NO_LANGUAGE_SUFFIX}"] - class_instance[attr] = is_single ? class_instance["#{attr}_#{NO_LANGUAGE_SUFFIX}"][0] : class_instance["#{attr}_#{NO_LANGUAGE_SUFFIX}"] - elsif is_single - class_instance[attr] = class_instance[attr][0] - end - end - end - end - - def filter_language_attributes(params, class_instance) - filter_language_attribute(params, class_instance, MATCH_TYPE_PREFLABEL, true) - filter_language_attribute(params, class_instance, MATCH_TYPE_SYNONYM, false) - filter_language_attribute(params, class_instance, MATCH_TYPE_DEFINITION, false) - end - def validate_params_solr_population(allowed_includes_params) leftover = includes_param - allowed_includes_params invalid = leftover.length > 0 message = "The `include` query string parameter cannot accept #{leftover.join(", ")}, please use only #{allowed_includes_params.join(", ")}" error 400, message if invalid end + + def get_ontology_metadata_search_options(params) + groups = params.fetch("groups", "").split(',') + categories = params.fetch("hasDomain", "").split(',') + languages = params.fetch("languages", "").split(',') + status = params.fetch("status", "").split(',') + format = params.fetch("hasOntologyLanguage", "").split(',') + is_of_type = params.fetch("isOfType", "").split(',') + has_format = params.fetch("hasFormat", "").split(',') + visibility = params["visibility"] + show_views = params["show_views"] == 'true' + sort = params.fetch("sort", "score desc, ontology_name_sort asc, ontology_acronym_sort asc") + page, page_size = page_params + + fq = [ + 'resource_model:"ontology_submission"', + 'submissionStatus_txt:ERROR_* OR submissionStatus_txt:"RDF" OR submissionStatus_txt:"UPLOADED"', + groups.map { |x| "ontology_group_txt:\"http://data.bioontology.org/groups/#{x.upcase}\"" }.join(' OR '), + categories.map { |x| "ontology_hasDomain_txt:\"http://data.bioontology.org/categories/#{x.upcase}\"" }.join(' OR '), + languages.map { |x| "naturalLanguage_txt:\"#{x.downcase}\"" }.join(' OR '), + ] + + fq << "ontology_viewingRestriction_t:#{visibility}" unless visibility.blank? + fq << "!ontology_viewOf_t:*" unless show_views + + fq << format.map { |x| "hasOntologyLanguage_t:\"http://data.bioontology.org/ontology_formats/#{x}\"" }.join(' OR ') unless format.blank? + + fq << status.map { |x| "status_t:#{x}" }.join(' OR ') unless status.blank? + fq << is_of_type.map { |x| "isOfType_t:#{x}" }.join(' OR ') unless is_of_type.blank? + fq << has_format.map { |x| "hasFormalityLevel_t:#{x}" }.join(' OR ') unless has_format.blank? + + fq.reject!(&:blank?) + + if params[:qf] + qf = params[:qf] + else + qf = [ + "ontologySuggestEdge^25 ontology_acronymSuggestEdge^25 ontology_nameSuggestEdge^15 descriptionSuggestEdge^10 ", # start of the word first + "ontology_t^15 ontology_acronym_text^15 ontology_name_text^10 description_text^5 ", # full word match + "ontologySuggestNgram^2 ontology_acronymSuggestNgram^2 ontology_nameSuggestNgram^1.5 descriptionSuggestNgram" # substring match last + ].join(' ') + end + + options = { + fq: fq, + qf: qf, + page: page, + page_size: page_size, + sort: sort + } + options + end + + def get_query(params) + if params[:query].nil? && params[:q].nil? + raise error 400, "The search query must be provided via /search?q=[&page=&pagesize=] /search?query=[&page=&pagesize=]" + end + query = params[:query] || params[:q] + query + end + + def search(model, query, params = {}) + query = query.blank? ? "*" : query + resp = model.search(query, search_params(**params)) + total_found = resp["response"]["numFound"] + docs = resp["response"]["docs"] + + page_object(docs, total_found) + end + + def search_params(defType: "edismax", fq:, qf:, stopwords: "true", lowercaseOperators: "true", page:, page_size:, fl: '*,score', sort:) + { + defType: defType, + fq: fq, + qf: qf, + sort: sort, + start: (page - 1) * page_size, + rows: page_size, + fl: fl, + stopwords: stopwords, + lowercaseOperators: lowercaseOperators, + } + end + + def process_search(params = nil) + params ||= @params + params['q'] ||= params['query'] + params.delete('query') + text = params["q"] + + query = get_term_search_query(text, params) + # puts "Edismax query: #{query}, params: #{params}" + set_page_params(params) + + docs = Array.new + resp = LinkedData::Models::Class.search(query, params) + total_found = resp["response"]["numFound"] + add_matched_fields(resp, Sinatra::Helpers::SearchHelper::MATCH_TYPE_PREFLABEL) + ontology_rank = LinkedData::Models::Ontology.rank + + resp["response"]["docs"].each do |doc| + doc = doc.symbolize_keys + # NCBO-974 + doc[:matchType] = resp["match_types"][doc[:id]] + resource_id = doc[:resource_id] + doc.delete :resource_id + doc[:id] = resource_id + # TODO: The `rescue next` on the following line shouldn't be here + # However, at some point we didn't store the ontologyId in the index + # and these records haven't been cleared out so this is getting skipped + ontology_uri = doc[:ontologyId].sub(/\/submissions\/.*/, "") rescue next + ontology = LinkedData::Models::Ontology.read_only(id: ontology_uri, acronym: doc[:submissionAcronym]) + submission = LinkedData::Models::OntologySubmission.read_only(id: doc[:ontologyId], ontology: ontology) + doc[:submission] = submission + doc[:ontology_rank] = (ontology_rank[doc[:submissionAcronym]] && !ontology_rank[doc[:submissionAcronym]].empty?) ? ontology_rank[doc[:submissionAcronym]][:normalizedScore] : 0.0 + doc[:properties] = MultiJson.load(doc.delete(:propertyRaw)) if include_param_contains?(:properties) + + doc = filter_attrs_by_language(doc) + + instance = doc[:provisional] ? LinkedData::Models::ProvisionalClass.read_only(doc) : LinkedData::Models::Class.read_only(doc) + docs.push(instance) + end + + unless params['sort'] + if !text.nil? && text[-1] == '*' + docs.sort! { |a, b| [b[:score], a[:prefLabelExact].downcase, b[:ontology_rank]] <=> [a[:score], b[:prefLabelExact].downcase, a[:ontology_rank]] } + else + docs.sort! { |a, b| [b[:score], b[:ontology_rank]] <=> [a[:score], a[:ontology_rank]] } + end + end + + page_object(docs, total_found) + end + end end end diff --git a/helpers/submission_helper.rb b/helpers/submission_helper.rb index 0e095bb18..d5a6a400a 100644 --- a/helpers/submission_helper.rb +++ b/helpers/submission_helper.rb @@ -6,24 +6,33 @@ module SubmissionHelper def submission_include_params # When asking to display all metadata, we are using bring_remaining on each submission. Slower but best way to retrieve all attrs includes = OntologySubmission.goo_attrs_to_load(includes_param) - if includes.find { |v| v.is_a?(Hash) && v.keys.include?(:ontology) } - includes << { :ontology => [:administeredBy, :acronym, :name, :viewingRestriction, :group, :hasDomain, :notes, :reviews, :projects, :acl, :viewOf] } + if includes.find{|v| v.is_a?(Hash) && v.keys.include?(:ontology)} + includes << {:ontology=>[:administeredBy, :acronym, :name, :viewingRestriction, :group, :hasDomain,:notes, :reviews, :projects,:acl, :viewOf]} end - if includes.find { |v| v.is_a?(Hash) && v.keys.include?(:contact) } - includes << { :contact => [:name, :email] } + if includes.find{|v| v.is_a?(Hash) && v.keys.include?(:contact)} + includes << {:contact=>[:name, :email]} end - if includes.find { |v| v.is_a?(Hash) && v.keys.include?(:metrics) } + if includes.find{|v| v.is_a?(Hash) && v.keys.include?(:metrics)} includes << { metrics: [:maxChildCount, :properties, :classesWithMoreThan25Children, :classesWithOneChild, :individuals, :maxDepth, :classes, :classesWithNoDefinition, :averageChildCount, :numberOfAxioms, - :entities] } + :entities]} end includes end + def submission_attributes_all + out = [LinkedData::Models::OntologySubmission.embed_values_hash] + out << {:contact=>[:name, :email]} + out << {:ontology=>[:acronym, :name, :administeredBy, :group, :viewingRestriction, :doNotUpdate, :flat, + :hasDomain, :summaryOnly, :acl, :viewOf, :ontologyType]} + + out + end + def retrieve_submissions(options) status = (options[:status] || "RDF").to_s.upcase status = "RDF" if status.eql?("READY") @@ -44,7 +53,9 @@ def retrieve_submissions(options) submissions_query = submissions_query.order_by(order_by) unless order_by.nil? + submissions_query = apply_submission_filters(submissions_query) submissions_query = submissions_query.filter(Goo::Filter.new(ontology: [:viewOf]).unbound) unless include_views + submissions_query = submissions_query.filter(filter) if filter? submissions = submissions_query.include(submission_include_params) if page? @@ -54,21 +65,6 @@ def retrieve_submissions(options) end end - def retrieve_latest_submissions(options = {}) - submissions = retrieve_submissions(options) - - latest_submissions = page? ? submissions : {} # latest_submission doest not work with pagination - submissions.each do |sub| - unless page? - next if include_ready?(options) && !sub.ready? - next if sub.ontology.nil? - latest_submissions[sub.ontology.acronym] ||= sub - latest_submissions[sub.ontology.acronym] = sub if sub.submissionId.to_i > latest_submissions[sub.ontology.acronym].submissionId.to_i - end - end - latest_submissions - end - def include_ready?(options) options[:status] && options[:status].to_s.upcase.eql?("READY") end diff --git a/helpers/users_helper.rb b/helpers/users_helper.rb index 22cce9e28..0669b8f87 100644 --- a/helpers/users_helper.rb +++ b/helpers/users_helper.rb @@ -19,18 +19,75 @@ def get_users def filter_for_user_onts(obj) return obj unless obj.is_a?(Enumerable) - return obj unless env['REMOTE_USER'] - return obj if env['REMOTE_USER'].customOntology.empty? - return obj if params['ignore_custom_ontologies'] + return obj unless env["REMOTE_USER"] + return obj if env["REMOTE_USER"].customOntology.empty? + return obj if params["ignore_custom_ontologies"] - user = env['REMOTE_USER'] + user = env["REMOTE_USER"] if obj.first.is_a?(LinkedData::Models::Ontology) - obj = obj.select { |o| user.custom_ontology_id_set.include?(o.id.to_s) } + obj = obj.select {|o| user.custom_ontology_id_set.include?(o.id.to_s)} end obj end + + def send_reset_token(email, username) + user = LinkedData::Models::User.where(email: email, username: username).include(LinkedData::Models::User.attributes).first + error 404, "User not found" unless user + reset_token = token(36) + user.resetToken = reset_token + user.resetTokenExpireTime = Time.now.to_i + 1.hours.to_i + + user.save(override_security: true) + LinkedData::Utils::Notifications.reset_password(user, reset_token) + user + end + + def token(len) + chars = ("a".."z").to_a + ("A".."Z").to_a + ("1".."9").to_a + token = "" + 1.upto(len) { |i| token << chars[rand(chars.size-1)] } + token + end + + def reset_password(email, username, token) + user = LinkedData::Models::User.where(email: email, username: username).include(User.goo_attrs_to_load(includes_param) + [:resetToken, :passwordHash, :resetTokenExpireTime]).first + + error 404, "User not found" unless user + + user.show_apikey = true + token_accepted = token.eql?(user.resetToken) + if token_accepted + error 401, "Invalid password reset token" if user.resetTokenExpireTime.nil? + error 401, "The password reset token expired" if user.resetTokenExpireTime < Time.now.to_i + user.resetToken = nil + user.resetTokenExpireTime = nil + user.save(override_security: true) if user.valid? + user.show_apikey = true + end + + [user, token_accepted] + end + + def oauth_authenticate(params) + access_token = params["access_token"] + provider = params["token_provider"] + user = LinkedData::Models::User.oauth_authenticate(access_token, provider) + error 401, "Access token invalid"if user.nil? + user + end + + def login_password_authenticate(params) + user_id = params["user"] + user_password = params["password"] + user = User.find(user_id).include(User.goo_attrs_to_load(includes_param) + [:passwordHash]).first + authenticated = false + authenticated = user.authenticate(user_password) unless user.nil? + error 401, "Username/password combination invalid" unless authenticated + + user + end end end end diff --git a/init.rb b/init.rb index 44a1eef52..0fd644a9c 100644 --- a/init.rb +++ b/init.rb @@ -1,34 +1,30 @@ -# Recursively require files from directories and their sub-directories +# Recursively require files from directories def require_dir(dir) - Dir.glob("#{dir}/*.rb").each {|f| require_relative f } - Dir.glob("#{dir}/*/").each {|d| require_dir(d.gsub(/\/+$/, '')) } + Dir.glob("#{dir}/**/*.rb").sort.each { |f| require_relative f } end -# Require controller base files -require_relative "controllers/application_controller" +# Require core files +require_relative 'controllers/application_controller' +require_dir('lib') +require_dir('helpers') +require_dir('models') +require_dir('controllers') -# Require known directories -require_dir("lib") -require_dir("helpers") -require_dir("models") -require_dir("controllers") +# Add optional trailing slash to routes +Sinatra.register do + def self.registered(app) + app.routes.each do |verb, routes| + routes.each do |route| + pattern = route[0] + next if pattern.to_s.end_with?('/') -## -# Look for routes without an optional trailing slash or existing trailing slash -# and add the optional trailing slash so both /ontologies/ and /ontologies works -def rewrite_routes_trailing_slash - trailing_slash = Regexp.new(/.*\/\?\\z/) - no_trailing_slash = Regexp.new(/(.*)\\z\//) - Sinatra::Application.routes.each do |method, routes| - routes.each do |r| - route_regexp_str = r[0].inspect - if trailing_slash.match(route_regexp_str) - next - else - new_route = route_regexp_str.gsub(no_trailing_slash, "\\1\\/?\\z/") - r[0] = eval(new_route) + http_verb = verb.to_s.downcase + app.public_send(http_verb, "#{pattern}/") do + pass unless request.path_info.end_with?('/') + redirect_path = request.path_info.chomp('/') + redirect redirect_path, 301 + end end end end end -rewrite_routes_trailing_slash() \ No newline at end of file diff --git a/lib/rack/content_negotiation.rb b/lib/rack/content_negotiation.rb new file mode 100644 index 000000000..4c91da6af --- /dev/null +++ b/lib/rack/content_negotiation.rb @@ -0,0 +1,131 @@ +module Rack + class ContentNegotiation + DEFAULT_CONTENT_TYPE = "application/n-triples" # N-Triples + VARY = { 'Vary' => 'Accept' }.freeze + ENDPOINTS_FILTER = %r{^/ontologies/[^/]+/resolve/[^/]+$} # Accepted API endpoints to apply content negotiation + + # @return [#call] + attr_reader :app + + # @return [Hash{Symbol => String}] + attr_reader :options + + ## + # @param [#call] app + # @param [Hash{Symbol => Object}] options + # Other options passed to writer. + # @option options [String] :default (DEFAULT_CONTENT_TYPE) Specific content type + # @option options [RDF::Format, #to_sym] :format Specific RDF writer format to use + def initialize(app, options = {}) + @app, @options = app, options + @options[:default] = (@options[:default] || DEFAULT_CONTENT_TYPE).to_s + end + + ## + # Handles a Rack protocol request. + # Parses Accept header to find appropriate mime-type and sets content_type accordingly. + # + # Inserts ordered content types into the environment as `ORDERED_CONTENT_TYPES` if an Accept header is present + # + # @param [Hash{String => String}] env + # @return [Array(Integer, Hash, #each)] Status, Headers and Body + # @see https://rubydoc.info/github/rack/rack/file/SPEC + def call(env) + if env['PATH_INFO'].match?(ENDPOINTS_FILTER) + if env.has_key?('HTTP_ACCEPT') + accepted_types = parse_accept_header(env['HTTP_ACCEPT']) + if !accepted_types.empty? + env["format"] = accepted_types.first + add_content_type_header(app.call(env), env["format"]) + else + not_acceptable + end + else + env["format"] = options[:default] + add_content_type_header(app.call(env), env["format"]) + end + else + app.call(env) + end + end + + protected + + # Parses an HTTP `Accept` header, returning an array of MIME content types ordered by precedence rules. + # + # @param [String, #to_s] header + # @return [Array] Array of content types sorted by precedence + # @see https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.1 + def parse_accept_header(header) + entries = header.to_s.split(',') + parsed_entries = entries.map { |entry| parse_accept_entry(entry) } + sorted_entries = parsed_entries.sort_by { |entry| entry.quality }.reverse + content_types = sorted_entries.map { |entry| entry.content_type } + content_types.flatten.compact + end + + + + # Parses an individual entry from the Accept header. + # + # @param [String] entry An entry from the Accept header + # @return [Entry] An object representing the parsed entry + def parse_accept_entry(entry) + # Represents an entry parsed from the Accept header + entry_struct = Struct.new(:content_type, :quality, :wildcard_count, :param_count) + content_type, *params = entry.split(';').map(&:strip) + quality = 1.0 # Default quality + params.reject! do |param| + if param.start_with?('q=') + quality = param[2..-1].to_f + true + end + end + wildcard_count = content_type.count('*') + entry_struct.new(content_type, quality, wildcard_count, params.size) + end + + + ## + # Returns a content type appropriate for the given `media_range`, + # returns `nil` if `media_range` contains a wildcard subtype + # that is not mapped. + # + # @param [String, #to_s] media_range + # @return [String, nil] + def find_content_type_for_media_range(media_range) + case media_range.to_s + when '*/*', 'text/*' + options[:default] + when 'application/n-triples' + 'application/n-triples' + when 'text/turtle' + 'text/turtle' + when 'application/json', 'application/ld+json', 'application/*' + 'application/ld+json' + when 'text/xml', 'text/rdf+xml', 'application/rdf+xml', 'application/xml' + 'application/rdf+xml' + else + nil + end + end + + ## + # Outputs an HTTP `406 Not Acceptable` response. + # + # @param [String, #to_s] message + # @return [Array(Integer, Hash, #each)] + def not_acceptable(message = nil) + code = 406 + http_status = [code, Rack::Utils::HTTP_STATUS_CODES[code]].join(' ') + message = http_status + (message.nil? ? "\n" : " (#{message})\n") + [code, { 'Content-Type' => "text/plain" }.merge(VARY), [message]] + end + + def add_content_type_header(response, type) + response[1] = response[1].merge(VARY).merge('Content-Type' => type) + response + end + + end +end diff --git a/lib/rack/cube_reporter.rb b/lib/rack/cube_reporter.rb deleted file mode 100644 index d6694b874..000000000 --- a/lib/rack/cube_reporter.rb +++ /dev/null @@ -1,41 +0,0 @@ -require 'cube' - -## -# This enables collection of request statistics for anaylsis via cube. -# A cube server is required. See http://square.github.io/cube/ for more info. -module Rack - class CubeReporter - - def initialize(app = nil, options = {}) - host = options[:cube_host] || "localhost" - port = options[:cube_port] || 1180 - @app = app - @cube = ::Cube::Client.new(host, port) - end - - def call(env) - start = Time.now - data = @app.call(env) - finish = Time.now - cache_hit = !data[1]["X-Rack-Cache"].nil? && data[1]["X-Rack-Cache"].eql?("fresh") - user = env["REMOTE_USER"] - apikey = user.apikey if user - username = user.username if user - req_data = { - duration_ms: ((finish - start)*1000).ceil, - path: env["REQUEST_PATH"], - cache_hit: cache_hit, - status: data[0], - user: { - apikey: apikey, - username: username, - ip: env["REMOTE_ADDR"], - user_agent: env["HTTP_USER_AGENT"] - } - } - @cube.send "ontologies_api_request", DateTime.now, req_data - data - end - - end -end \ No newline at end of file diff --git a/lib/rack/downcase_headers.rb b/lib/rack/downcase_headers.rb new file mode 100644 index 000000000..5aa3ae28d --- /dev/null +++ b/lib/rack/downcase_headers.rb @@ -0,0 +1,15 @@ +module Rack + class DowncaseHeaders + def initialize(app) + @app = app + end + + def call(env) + status, headers, body = @app.call(env) + downcased_headers = headers.each_with_object({}) do |(key, value), new_headers| + new_headers[key.downcase] = value + end + [status, downcased_headers, body] + end + end +end \ No newline at end of file diff --git a/lib/rack/param_translator.rb b/lib/rack/param_translator.rb index 20738b2a5..93798f591 100644 --- a/lib/rack/param_translator.rb +++ b/lib/rack/param_translator.rb @@ -1,6 +1,3 @@ -## -# This enables collection of request statistics for anaylsis via cube. -# A cube server is required. See http://square.github.io/cube/ for more info. module Rack class ParamTranslator diff --git a/models/simple_wrappers.rb b/models/simple_wrappers.rb index e4097affd..0d59a5187 100644 --- a/models/simple_wrappers.rb +++ b/models/simple_wrappers.rb @@ -29,3 +29,5 @@ ProvisionalRelation = LinkedData::Models::ProvisionalRelation SearchHelper = Sinatra::Helpers::SearchHelper + +Resource = LinkedData::Models::Resource diff --git a/rakelib/ontoportal_testkit.rake b/rakelib/ontoportal_testkit.rake new file mode 100644 index 000000000..39a3ec73d --- /dev/null +++ b/rakelib/ontoportal_testkit.rake @@ -0,0 +1 @@ +require "ontoportal/testkit/tasks" diff --git a/test/controllers/test_batch_controller.rb b/test/controllers/test_batch_controller.rb index 492a608ff..faea8be5b 100644 --- a/test/controllers/test_batch_controller.rb +++ b/test/controllers/test_batch_controller.rb @@ -22,7 +22,7 @@ def test_class_batch_one_ontology "display" => "prefLabel,synonym" } } - post "/batch/", call_params + post "/batch", call_params assert last_response.ok? data = MultiJson.load(last_response.body) classes = data["http://www.w3.org/2002/07/owl#Class"] @@ -48,7 +48,7 @@ def test_class_wrong_params "display" => "prefLabel,synonym" } } - post "/batch/", call_params + post "/batch", call_params assert_equal 422, last_response.status end @@ -72,7 +72,7 @@ def test_class_batch_multiple "display" => "prefLabel" } } - post "/batch/", call_params + post "/batch", call_params assert last_response.ok? data = MultiJson.load(last_response.body) classes = data["http://www.w3.org/2002/07/owl#Class"] @@ -101,7 +101,7 @@ def test_class_all_bro "display" => "prefLabel" } } - post "/batch/", call_params + post "/batch", call_params assert last_response.ok? # refute last_response.ok? data = MultiJson.load(last_response.body) diff --git a/test/controllers/test_classes_controller.rb b/test/controllers/test_classes_controller.rb index 838385d7e..bee4d4bed 100644 --- a/test/controllers/test_classes_controller.rb +++ b/test/controllers/test_classes_controller.rb @@ -422,7 +422,7 @@ def test_calls_not_found escaped_cls= CGI.escape("http://my.bogus.inexistent.class/that/this/is") #404 on ontology - get "/ontologies/NO-ONT-ZZZZZZ/classes/" + get "/ontologies/NO-ONT-ZZZZZZ/classes" assert last_response.status == 404 get "/ontologies/NO-ONT-ZZZZZZ/classes/#{escaped_cls}/children" assert last_response.status == 404 @@ -525,7 +525,7 @@ def test_class_page_with_metric_count assert page_response["collection"].length == 0 end - def test_multilingual + def test_default_multilingual ont = Ontology.find("TEST-ONT-0").include(:acronym).first sub = ont.latest_submission sub.bring_remaining @@ -551,7 +551,7 @@ def test_multilingual assert last_response.ok? page_response = MultiJson.load(last_response.body) # does not contain a value in english show the generated one - assert_equal 'Gene_Therapy', page_response["prefLabel"] + assert_equal 'Gene Therapy', page_response["prefLabel"] # prefLabel is present in the ontology language sub.naturalLanguage = ['fr'] @@ -560,8 +560,7 @@ def test_multilingual assert last_response.ok? page_response = MultiJson.load(last_response.body) # show french value as specified in submission naturalLanguage - assert_equal 'Gestion des échantillons biologiques', page_response["prefLabel"] - + assert_equal 'Gestion des Bioéchantillons', page_response["prefLabel"] sub.naturalLanguage = [] sub.save @@ -584,7 +583,6 @@ def test_multilingual page_response = MultiJson.load(last_response.body) # show Japanese value as specified in submission naturalLanguage assert_equal 'カタログ', page_response["prefLabel"] - sub.naturalLanguage = [] sub.save @@ -605,7 +603,7 @@ def test_multilingual assert last_response.ok? page_response = MultiJson.load(last_response.body) - assert_equal 'Research Lab Management', page_response["prefLabel"]["none"] + assert_equal 'Research Lab Management', page_response.dig("prefLabel", "none") || page_response.dig("prefLabel", "@none") assert_equal 'Gestion du laboratoire de recherche', page_response["prefLabel"]["fr"] assert_equal 'Gestione del laboratorio di ricerca', page_response["prefLabel"]["it"] end diff --git a/test/controllers/test_dereference_resource_controller.rb b/test/controllers/test_dereference_resource_controller.rb new file mode 100644 index 000000000..03427c41f --- /dev/null +++ b/test/controllers/test_dereference_resource_controller.rb @@ -0,0 +1,195 @@ +require_relative '../test_case' +require 'rexml/document' + +class TestDereferenceResourceController < TestCase + + def before_suite + LinkedData::SampleData::Ontology.create_ontologies_and_submissions({ + process_submission: true, + process_options: { process_rdf: true, extract_metadata: false, generate_missing_labels: false}, + acronym: 'INRAETHESDEREF', + name: 'INRAETHES', + file_path: './test/data/ontology_files/thesaurusINRAE_nouv_structure.rdf', + ont_count: 1, + ontology_format: 'SKOS', + submission_count: 1 + }) + + @@graph = "INRAETHESDEREF-0" + @@uri = CGI.escape("http://opendata.inrae.fr/thesaurusINRAE/c_6496") + end + + def test_dereference_resource_controller_json + header 'Accept', 'application/json' + get "/ontologies/#{@@graph}/resolve/#{@@uri}" + assert last_response.ok? + + result = last_response.body + expected_result = <<-JSON + { + "@context": { + "ns0": "http://opendata.inrae.fr/thesaurusINRAE/", + "rdf": "http://www.w3.org/1999/02/22-rdf-syntax-ns#", + "owl": "http://www.w3.org/2002/07/owl#", + "skos": "http://www.w3.org/2004/02/skos/core#" + }, + "@graph": [ + { + "@id": "ns0:c_6496", + "@type": [ + "owl:NamedIndividual", + "skos:Concept" + ], + "skos:broader": { + "@id": "ns0:c_a9d99f3a" + }, + "skos:topConceptOf": { + "@id": "ns0:mt_65" + }, + "skos:inScheme": [ + { + "@id": "ns0:thesaurusINRAE" + }, + { + "@id": "ns0:mt_65" + } + ], + "skos:prefLabel": { + "@value": "altération de l'ADN", + "@language": "fr" + } + }, + { + "@id": "ns0:mt_65", + "skos:hasTopConcept": { + "@id": "ns0:c_6496" + } + } + ] + } + JSON + a = sort_nested_hash(JSON.parse(result)) + b = sort_nested_hash(JSON.parse(expected_result)) + assert_equal b, a + end + + def test_dereference_resource_controller_xml + header 'Accept', 'application/xml' + get "/ontologies/#{@@graph}/resolve/#{@@uri}" + assert last_response.ok? + + result = last_response.body + + expected_result_1 = <<-XML + + + + + + + + + altération de l'ADN + + + + + + XML + + expected_result_2 = <<-XML + + + + + + + altération de l'ADN + + + + + + + + XML + + + clean_xml = -> (x) { x.strip.gsub('/>', '').gsub('', '').split(' ').reject(&:empty?)} + + + a = result.gsub('\\"', '"')[1..-2].split("\\n").map{|x| clean_xml.call(x)}.flatten + b_1 = expected_result_1.split("\n").map{|x| clean_xml.call(x)}.flatten + b_2 = expected_result_2.split("\n").map{|x| clean_xml.call(x)}.flatten + + assert_includes [b_1.sort, b_2.sort], a.sort + end + + def test_dereference_resource_controller_ntriples + header 'Accept', 'application/n-triples' + get "/ontologies/#{@@graph}/resolve/#{@@uri}" + assert last_response.ok? + + result = last_response.body + expected_result = <<-NTRIPLES + . + . + . + . + . + . + "alt\\u00E9rationdel'ADN"@fr . + . + NTRIPLES + a = result.gsub(' ', '').split("\n").reject(&:empty?) + b = expected_result.gsub(' ', '').split("\n").reject(&:empty?) + assert_equal b.sort, a.sort + end + + def test_dereference_resource_controller_turtle + header 'Accept', 'text/turtle' + get "/ontologies/#{@@graph}/resolve/#{@@uri}" + assert last_response.ok? + + result = last_response.body + expected_result = <<-TURTLE + @prefix rdf: . + @prefix ns0: . + @prefix owl: . + @prefix skos: . + + ns0:c_6496 + a owl:NamedIndividual, skos:Concept ; + skos:broader ns0:c_a9d99f3a ; + skos:inScheme ns0:mt_65, ns0:thesaurusINRAE ; + skos:prefLabel "altération de l'ADN"@fr ; + skos:topConceptOf ns0:mt_65 . + + ns0:mt_65 + skos:hasTopConcept ns0:c_6496 . + TURTLE + a = result.gsub(' ', '').split("\n").reject(&:empty?) + b = expected_result.gsub(' ', '').split("\n").reject(&:empty?) + + assert_equal b.sort, a.sort + end + + private + + def sort_nested_hash(hash) + sorted_hash = {} + + hash.each do |key, value| + if value.is_a?(Hash) + sorted_hash[key] = sort_nested_hash(value) + elsif value.is_a?(Array) + sorted_hash[key] = value.map { |item| item.is_a?(Hash) ? sort_nested_hash(item) : item }.sort_by { |item| item.to_s } + else + sorted_hash[key] = value + end + end + + sorted_hash.sort.to_h + end + +end diff --git a/test/controllers/test_home_controller.rb b/test/controllers/test_home_controller.rb new file mode 100644 index 000000000..bc4e64b9d --- /dev/null +++ b/test/controllers/test_home_controller.rb @@ -0,0 +1,49 @@ +require_relative '../test_case' + +class TestHomeController < TestCase + def test_home_index_returns_links_hash + get '/' + assert last_response.ok?, get_errors(last_response) + + body = MultiJson.load(last_response.body) + assert body.key?('links') + assert_kind_of Hash, body['links'] + assert body['links'].key?('@context') + assert_kind_of Hash, body['links']['@context'] + assert_operator body['links']['@context'].length, :>, 0 + end + + def test_home_index_handles_type_uri_failures + bad_class = Class.new do + def self.type_uri + raise NoMethodError, 'model settings missing' + end + end + + klass = Sinatra::Application + original_routes_list = klass.instance_method(:routes_list) rescue nil + original_route_to_class_map = klass.instance_method(:route_to_class_map) rescue nil + + klass.class_eval do + define_method(:routes_list) { ['/broken'] } + define_method(:route_to_class_map) { { '/broken' => bad_class } } + end + + get '/' + assert last_response.ok?, get_errors(last_response) + ensure + klass.class_eval do + if original_routes_list + define_method(:routes_list, original_routes_list) + else + remove_method(:routes_list) rescue nil + end + + if original_route_to_class_map + define_method(:route_to_class_map, original_route_to_class_map) + else + remove_method(:route_to_class_map) rescue nil + end + end + end +end diff --git a/test/controllers/test_mappings_controller.rb b/test/controllers/test_mappings_controller.rb index d8c6f6192..8d687fd70 100644 --- a/test/controllers/test_mappings_controller.rb +++ b/test/controllers/test_mappings_controller.rb @@ -103,7 +103,7 @@ def mappings_between_ontologies ] ontologies_params.each do |ontologies| ont1, ont2 = ontologies.split(",") - get "/mappings/?ontologies=#{ontologies}" + get "/mappings?ontologies=#{ontologies}" assert last_response.ok? mappings = MultiJson.load(last_response.body) #pages @@ -219,7 +219,7 @@ def create_mapping creator: "http://data.bioontology.org/users/tim" } - post "/mappings/", + post "/mappings", MultiJson.dump(mapping), "CONTENT_TYPE" => "application/json" @@ -259,7 +259,7 @@ def create_mapping end assert rest_count == 3 - get "/mappings/recent/" + get "/mappings/recent" assert last_response.status == 200 response = MultiJson.load(last_response.body) assert (response.length == 5) @@ -314,7 +314,7 @@ def delete_mapping creator: "http://data.bioontology.org/users/tim" } - post "/mappings/", + post "/mappings", MultiJson.dump(mapping), "CONTENT_TYPE" => "application/json" @@ -363,7 +363,7 @@ def mappings_statistics end NcboCron::Models::QueryWarmer.new(Logger.new(TestLogFile.new)).run assert LinkedData::Models::MappingCount.where.all.length > 2 - get "/mappings/statistics/ontologies/" + get "/mappings/statistics/ontologies" assert last_response.ok? stats = MultiJson.load(last_response.body) data = {"BRO-TEST-MAP-0"=>18, diff --git a/test/controllers/test_ontologies_controller.rb b/test/controllers/test_ontologies_controller.rb index 874efe394..37f7adcb0 100644 --- a/test/controllers/test_ontologies_controller.rb +++ b/test/controllers/test_ontologies_controller.rb @@ -97,7 +97,7 @@ def test_create_ontology assert last_response.status == 201 delete "/ontologies/#{@@acronym}" - post "/ontologies/", @@file_params.merge(acronym: @@acronym) + post "/ontologies", @@file_params.merge(acronym: @@acronym) assert last_response.status == 201 end diff --git a/test/controllers/test_ontology_submissions_controller.rb b/test/controllers/test_ontology_submissions_controller.rb index 3a5712f15..a4df6becf 100644 --- a/test/controllers/test_ontology_submissions_controller.rb +++ b/test/controllers/test_ontology_submissions_controller.rb @@ -29,7 +29,7 @@ def setup end def test_submissions_for_given_ontology - num_onts_created, created_ont_acronyms = create_ontologies_and_submissions(ont_count: 1) + _, created_ont_acronyms = create_ontologies_and_submissions(ont_count: 1) ontology = created_ont_acronyms.first get "/ontologies/#{ontology}/submissions" assert last_response.ok? @@ -68,7 +68,7 @@ def test_create_new_ontology_submission end def test_patch_ontology_submission - num_onts_created, created_ont_acronyms = create_ontologies_and_submissions(ont_count: 1) + _, created_ont_acronyms = create_ontologies_and_submissions(ont_count: 1) ont = Ontology.find(created_ont_acronyms.first).include(submissions: [:submissionId, {ontology: :acronym}]).first assert_operator ont.submissions.length, :>, 0 submission = ont.submissions[0] @@ -112,7 +112,7 @@ def test_patch_submission_ignores_system_controlled_attributes end def test_delete_ontology_submission - num_onts_created, created_ont_acronyms = create_ontologies_and_submissions(ont_count: 1, + _, created_ont_acronyms = create_ontologies_and_submissions(ont_count: 1, random_submission_count: false, submission_count: 5) acronym = created_ont_acronyms.first submission_to_delete = (1..5).to_a.sample @@ -218,13 +218,13 @@ def test_download_submission # see also test_ontologies_controller::test_download_ontology # Test downloads of nonexistent ontology - get "/ontologies/BOGUS66/submissions/55/download" + get '/ontologies/BOGUS66/submissions/55/download' assert_equal(422, last_response.status, "failed to handle downloads of nonexistent ontology" + get_errors(last_response)) end def test_download_ontology_submission_rdf - count, created_ont_acronyms, onts = create_ontologies_and_submissions(ont_count: 1, submission_count: 1, + _, created_ont_acronyms, onts = create_ontologies_and_submissions(ont_count: 1, submission_count: 1, process_submission: true) acronym = created_ont_acronyms.first ont = onts.first @@ -239,7 +239,7 @@ def test_download_ontology_submission_rdf end def test_download_acl_only - count, created_ont_acronyms, onts = create_ontologies_and_submissions(ont_count: 1, submission_count: 1, + _, created_ont_acronyms, onts = create_ontologies_and_submissions(ont_count: 1, submission_count: 1, process_submission: false) acronym = created_ont_acronyms.first ont = onts.first.bring_remaining @@ -288,7 +288,7 @@ def test_download_acl_only def test_submissions_default_includes ontology_count = 5 - num_onts_created, created_ont_acronyms, ontologies = create_ontologies_and_submissions(ont_count: ontology_count, + _, created_ont_acronyms, ontologies = create_ontologies_and_submissions(ont_count: ontology_count, submission_count: 1, submissions_to_process: []) submission_default_attributes = LinkedData::Models::OntologySubmission.hypermedia_settings[:serialize_default].map(&:to_s) @@ -314,88 +314,282 @@ def test_submissions_default_includes def test_submissions_all_includes ontology_count = 5 - num_onts_created, created_ont_acronyms, ontologies = create_ontologies_and_submissions(ont_count: ontology_count, - submission_count: 1, submissions_to_process: []) - def submission_all_attributes - attrs = OntologySubmission.goo_attrs_to_load([:all]) - embed_attrs = attrs.find { |x| x.is_a?(Hash) } + _, created_ont_acronyms, = create_ontologies_and_submissions(ont_count: ontology_count, submission_count: 1, submissions_to_process: []) + + submission_all_attributes = begin + attrs = OntologySubmission.goo_attrs_to_load([:all]) + embed_attrs = attrs.select { |x| x.is_a?(Hash) }.first || {} + attrs.reject { |x| x.is_a?(Hash) }.map(&:to_s) + embed_attrs.keys.map(&:to_s) + end.sort + + params = '?include=all&display_links=false&display_context=false' + + [ + "/submissions#{params}", + "/ontologies/#{created_ont_acronyms.first}/submissions#{params}", + "/ontologies/#{created_ont_acronyms.first}/latest_submission#{params}", + "/ontologies/#{created_ont_acronyms.first}/submissions/1#{params}" + ].each do |url| + get(url) + assert last_response.ok? + + response_body = MultiJson.load(last_response.body) + submissions = response_body.is_a?(Array) ? response_body : [response_body] + + assert_equal(ontology_count, submissions.size) if url == "/submissions#{params}" + assert(submissions.all? { |sub| submission_all_attributes.eql?(submission_keys(sub).sort) }) + assert(submissions.all? { |sub| sub['contact']&.first&.keys.to_a.sort.eql?(%w[name email id].sort) }) + end + end - attrs.delete_if { |x| x.is_a?(Hash) }.map(&:to_s) + embed_attrs.keys.map(&:to_s) + def test_submissions_custom_includes + ontology_count = 5 + _, created_ont_acronyms, _ = create_ontologies_and_submissions(ont_count: ontology_count, submission_count: 1, submissions_to_process: []) + include_keys = %w[ontology contact submissionId] + params = "?include=#{include_keys.join(',')}&display_links=false&display_context=false" + + [ + "/submissions#{params}", + "/ontologies/#{created_ont_acronyms.first}/submissions#{params}", + "/ontologies/#{created_ont_acronyms.first}/latest_submission#{params}", + "/ontologies/#{created_ont_acronyms.first}/submissions/1#{params}" + ].each do |url| + get(url) + assert last_response.ok? + + response_body = MultiJson.load(last_response.body) + submissions = response_body.is_a?(Array) ? response_body : [response_body] + + assert_equal(ontology_count, submissions.size) if url == "/submissions#{params}" + assert(submissions.all? { |sub| include_keys.eql?(submission_keys(sub)) }) + assert(submissions.all? { |sub| sub['contact']&.first&.keys&.sort.eql?(%w[name email id].sort) }) end - get("/submissions?include=all&display_links=false&display_context=false") + end - assert(last_response.ok?) - submissions = MultiJson.load(last_response.body) - assert_equal(ontology_count, submissions.size) + def test_ontology_submissions_access_controller + _, created_ont_acronyms, onts = create_ontologies_and_submissions(ont_count: 2, submission_count: 1, process_submission: false) + # case first submission is private + created_ont_acronyms.first + ont = onts.first.bring_remaining - submissions.each do |sub| - assert_equal(submission_all_attributes.sort, submission_keys(sub).sort) - assert_submission_contact_structure(sub) + begin + allowed_user = User.new({ + username: 'allowed', + email: 'test@example.org', + password: '12345' + }) + allowed_user.save + blocked_user = User.new({ + username: 'blocked', + email: 'test1254@example.org', + password: '12345' + }) + blocked_user.save + + ont.acl = [allowed_user] + ont.viewingRestriction = 'private' + ont.save + + LinkedData.settings.enable_security = true + + get "/submissions?apikey=#{allowed_user.apikey}" + assert_equal 200, last_response.status + submissions = MultiJson.load(last_response.body) + assert_equal 2, submissions.size + + get "/submissions?apikey=#{blocked_user.apikey}" + assert_equal 200, last_response.status + submissions = MultiJson.load(last_response.body) + assert_equal 1, submissions.size + ensure + LinkedData.settings.enable_security = false + del = User.find('allowed').first + del.delete if del + del = User.find('blocked').first + del.delete if del end + end - get("/ontologies/#{created_ont_acronyms.first}/submissions?include=all&display_links=false&display_context=false") + def test_submissions_pagination + create_ontologies_and_submissions(ont_count: 2, submission_count: 2) - assert(last_response.ok?) + get '/submissions' + assert last_response.ok? submissions = MultiJson.load(last_response.body) - assert_equal(1, submissions.size) - submissions.each do |sub| - assert_equal(submission_all_attributes.sort, submission_keys(sub).sort) - assert_submission_contact_structure(sub) + assert_equal 2, submissions.length + + get '/submissions?page=1&pagesize=1' + assert last_response.ok? + submissions = MultiJson.load(last_response.body) + assert_equal 1, submissions['collection'].length + end + + def test_submissions_pagination_filter + num_onts_created, created_ont_acronyms, ontologies = create_ontologies_and_submissions(ont_count: 10, submission_count: 1) + group1 = LinkedData::Models::Group.new(acronym: 'group-1', name: 'Test Group 1').save + group2 = LinkedData::Models::Group.new(acronym: 'group-2', name: 'Test Group 2').save + category1 = LinkedData::Models::Category.new(acronym: 'category-1', name: 'Test Category 1').save + category2 = LinkedData::Models::Category.new(acronym: 'category-2', name: 'Test Category 2').save + + ontologies1 = ontologies[0..5].each do |o| + o.bring_remaining + o.group = [group1] + o.hasDomain = [category1] + o.save end - get("/ontologies/#{created_ont_acronyms.first}/latest_submission?include=all&display_links=false&display_context=false") - assert(last_response.ok?) - sub = MultiJson.load(last_response.body) + ontologies2 = ontologies[6..8].each do |o| + o.bring_remaining + o.group = [group2] + o.hasDomain = [category2] + o.save + end - assert_equal(submission_all_attributes.sort, submission_keys(sub).sort) - assert_submission_contact_structure(sub) + # test filter by group and category + get "/submissions?page=1&pagesize=100&group=#{group1.acronym}" + assert last_response.ok? + assert_equal ontologies1.size, MultiJson.load(last_response.body)['collection'].length + get "/submissions?page=1&pagesize=100&group=#{group2.acronym}" + assert last_response.ok? + assert_equal ontologies2.size, MultiJson.load(last_response.body)['collection'].length + get "/submissions?page=1&pagesize=100&hasDomain=#{category1.acronym}" + assert last_response.ok? + assert_equal ontologies1.size, MultiJson.load(last_response.body)['collection'].length + get "/submissions?page=1&pagesize=100&hasDomain=#{category2.acronym}" + assert last_response.ok? + assert_equal ontologies2.size, MultiJson.load(last_response.body)['collection'].length + get "/submissions?page=1&pagesize=100&hasDomain=#{category2.acronym}&group=#{group1.acronym}" + assert last_response.ok? + assert_equal 0, MultiJson.load(last_response.body)['collection'].length + get "/submissions?page=1&pagesize=100&hasDomain=#{category2.acronym}&group=#{group2.acronym}" + assert last_response.ok? + assert_equal ontologies2.size, MultiJson.load(last_response.body)['collection'].length + + ontologies3 = ontologies[9] + ontologies3.bring_remaining + ontologies3.group = [group1, group2] + ontologies3.hasDomain = [category1, category2] + ontologies3.name = 'name search test' + ontologies3.save + + # test search with acronym + [ + [ 1, ontologies.first.acronym], + [ 1, ontologies.last.acronym], + [ontologies.size, 'TEST-ONT'] + ].each do |count, acronym_search| + get "/submissions?page=1&pagesize=100&acronym=#{acronym_search}" + assert last_response.ok? + submissions = MultiJson.load(last_response.body) + assert_equal count, submissions['collection'].length + end - get("/ontologies/#{created_ont_acronyms.first}/submissions/1?include=all&display_links=false&display_context=false") - assert(last_response.ok?) - sub = MultiJson.load(last_response.body) + # test search with name + [ + [ 1, ontologies.first.name], + [ 1, ontologies.last.name], + [ontologies.size - 1, 'TEST-ONT'] + ].each do |count, name_search| + get "/submissions?page=1&pagesize=100&name=#{name_search}" + assert last_response.ok? + submissions = MultiJson.load(last_response.body) + assert_equal count, submissions['collection'].length + end - assert_equal(submission_all_attributes.sort, submission_keys(sub).sort) - assert_submission_contact_structure(sub) - end + # test search with name and acronym + # search by name + get '/submissions?page=1&pagesize=100&name=search&acronym=search' + assert last_response.ok? + submissions = MultiJson.load(last_response.body) + assert_equal 1, submissions['collection'].length + # search by acronym + get '/submissions?page=1&pagesize=100&name=9&acronym=9' + assert last_response.ok? + submissions = MultiJson.load(last_response.body) + assert_equal 1, submissions['collection'].length + # search by acronym or name + get '/submissions?page=1&pagesize=100&name=search&acronym=8' + assert last_response.ok? + submissions = MultiJson.load(last_response.body) + assert_equal 2, submissions['collection'].length + + ontologies.first.name = 'sort by test' + ontologies.first.save + sub = ontologies.first.latest_submission(status: :any).bring_remaining + sub.status = 'retired' + sub.description = '234' + sub.creationDate = DateTime.yesterday.to_datetime + sub.hasOntologyLanguage = LinkedData::Models::OntologyFormat.find('SKOS').first + sub.save + + #test search with sort + get '/submissions?page=1&pagesize=100&acronym=tes&name=tes&order_by=ontology_name' + assert last_response.ok? + submissions = MultiJson.load(last_response.body) + refute_empty submissions['collection'] + assert_equal ontologies.map{|x| x.name}.sort, submissions['collection'].map{|x| x['ontology']['name']} - def test_submissions_custom_includes - ontology_count = 5 - num_onts_created, created_ont_acronyms, ontologies = create_ontologies_and_submissions(ont_count: ontology_count, - submission_count: 1, submissions_to_process: []) - include = "ontology,contact,submissionId" + get '/submissions?page=1&pagesize=100&acronym=tes&name=tes&order_by=creationDate' + assert last_response.ok? + submissions = MultiJson.load(last_response.body) + refute_empty submissions['collection'] + assert_equal ontologies.map{|x| x.latest_submission(status: :any).bring(:creationDate).creationDate}.sort, submissions['collection'].map{|x| DateTime.parse(x['creationDate'])}.reverse - get("/submissions?include=#{include}&display_links=false&display_context=false") + # test search with format + get '/submissions?page=1&pagesize=100&acronym=tes&name=tes&hasOntologyLanguage=SKOS' + assert last_response.ok? + submissions = MultiJson.load(last_response.body) + refute_empty submissions['collection'] + assert_equal 1, submissions['collection'].size - assert(last_response.ok?) + get '/submissions?page=1&pagesize=100&acronym=tes&name=tes&hasOntologyLanguage=OWL' + assert last_response.ok? submissions = MultiJson.load(last_response.body) - assert_equal ontology_count, submissions.size - submissions.each do |sub| - assert_equal(include.split(","), submission_keys(sub)) - assert_submission_contact_structure(sub) - end + refute_empty submissions['collection'] + assert_equal ontologies.size-1 , submissions['collection'].size - get("/ontologies/#{created_ont_acronyms.first}/submissions?include=#{include}&display_links=false&display_context=false") + # test ontology filter with submission filter attributes + get '/submissions?page=1&pagesize=100&acronym=tes&name=tes&group=group-2&category=category-2&hasOntologyLanguage=OWL' + assert last_response.ok? + submissions = MultiJson.load(last_response.body) + refute_empty submissions['collection'] + assert_equal ontologies2.size + 1 , submissions['collection'].size - assert(last_response.ok?) + # test ontology filter with status + get '/submissions?page=1&pagesize=100&status=retired' + assert last_response.ok? submissions = MultiJson.load(last_response.body) - assert_equal(1, submissions.size) - submissions.each do |sub| - assert_equal(include.split(","), submission_keys(sub)) - assert_submission_contact_structure(sub) - end + refute_empty submissions['collection'] + assert_equal 1 , submissions['collection'].size - get("/ontologies/#{created_ont_acronyms.first}/latest_submission?include=#{include}&display_links=false&display_context=false") - assert(last_response.ok?) - sub = MultiJson.load(last_response.body) - assert_equal(include.split(","), submission_keys(sub)) - assert_submission_contact_structure(sub) + get '/submissions?page=1&pagesize=100&status=alpha,beta,production' + assert last_response.ok? + submissions = MultiJson.load(last_response.body) + refute_empty submissions['collection'] + assert_equal ontologies.size - 1 , submissions['collection'].size + get '/submissions?page=1&pagesize=100&description=234&acronym=234&name=234' + assert last_response.ok? + submissions = MultiJson.load(last_response.body) + assert_equal 1 , submissions['collection'].size + end - get("/ontologies/#{created_ont_acronyms.first}/submissions/1?include=#{include}&display_links=false&display_context=false") - assert(last_response.ok?) - sub = MultiJson.load(last_response.body) - assert_equal(include.split(","), submission_keys(sub)) - assert_submission_contact_structure(sub) + def test_submissions_param_include + skip('only for local development regrouping a set of tests') + test_submissions_default_includes + test_submissions_all_includes + test_submissions_custom_includes + end + + def test_submission_diff + _, _, onts = create_ontologies_and_submissions(ont_count: 1, submission_count: 2, + process_submission: true, + process_options: { process_rdf: true, extract_metadata: false, diff: true} ) + + ont = onts.first + sub = ont.latest_submission(status: :any) + + get "/ontologies/#{ont.acronym}/submissions/#{sub.submissionId}/diff" end private diff --git a/test/controllers/test_projects_controller.rb b/test/controllers/test_projects_controller.rb index 8083a75c3..cd479f6f9 100644 --- a/test/controllers/test_projects_controller.rb +++ b/test/controllers/test_projects_controller.rb @@ -107,7 +107,7 @@ def test_project_create_failure _project_delete(@p.acronym) # Fail PUT for any project with required missing data. username = 'user_does_not_exist' - @projectParams['creator'] = username + @projectParams[:creator] = username put "/projects/#{@p.acronym}", MultiJson.dump(@projectParams), "CONTENT_TYPE" => "application/json" _response_status(422, last_response) _project_get_failure(@p.acronym) diff --git a/test/controllers/test_properties_controller.rb b/test/controllers/test_properties_controller.rb index 6aac347df..33e9b26a2 100644 --- a/test/controllers/test_properties_controller.rb +++ b/test/controllers/test_properties_controller.rb @@ -3,26 +3,26 @@ class TestPropertiesController < TestCase def before_suite - count, acronyms, bro = LinkedData::SampleData::Ontology.create_ontologies_and_submissions({ - process_submission: true, - process_options:{process_rdf: true, extract_metadata: false}, - acronym: "BROSEARCHTEST", - name: "BRO Search Test", - file_path: "./test/data/ontology_files/BRO_v3.2.owl", - ont_count: 1, - submission_count: 1, - ontology_type: "VALUE_SET_COLLECTION" - }) - - count, acronyms, mccl = LinkedData::SampleData::Ontology.create_ontologies_and_submissions({ - process_submission: true, - process_options:{process_rdf: true, extract_metadata: true}, - acronym: "MCCLSEARCHTEST", - name: "MCCL Search Test", - file_path: "./test/data/ontology_files/CellLine_OWL_BioPortal_v1.0.owl", - ont_count: 1, - submission_count: 1 - }) + _, _, bro = LinkedData::SampleData::Ontology.create_ontologies_and_submissions({ + process_submission: true, + process_options:{process_rdf: true, extract_metadata: false}, + acronym: "BROSEARCHTEST", + name: "BRO Search Test", + file_path: "./test/data/ontology_files/BRO_v3.2.owl", + ont_count: 1, + submission_count: 1, + ontology_type: "VALUE_SET_COLLECTION" + }) + + _, _, mccl = LinkedData::SampleData::Ontology.create_ontologies_and_submissions({ + process_submission: true, + process_options:{process_rdf: true, extract_metadata: true}, + acronym: "MCCLSEARCHTEST", + name: "MCCL Search Test", + file_path: "./test/data/ontology_files/CellLine_OWL_BioPortal_v1.0.owl", + ont_count: 1, + submission_count: 1 + }) @@ontologies = bro.concat(mccl) @@acronyms = @@ontologies.map { |ont| ont.bring_remaining; ont.acronym } end @@ -47,14 +47,33 @@ def test_single_property get "/ontologies/#{@@acronyms.first}/properties/http%3A%2F%2Fbioontology.org%2Fontologies%2FBiomedicalResourceOntology.owl%23Originator" assert last_response.ok? results = MultiJson.load(last_response.body) + assert results.is_a?(Hash) assert_equal ["Originator"], results["label"] assert_equal "http://bioontology.org/ontologies/BiomedicalResourceOntology.owl#Originator", results["@id"] + assert results.key?('range') + assert results.key?('domain') get "/ontologies/#{@@acronyms.first}/properties/http%3A%2F%2Fbioontology.org%2Fontologies%2FBiomedicalResourceOntology.owl%23DummyProp" assert_equal 404, last_response.status end + def test_single_property_all_attributes + get "/ontologies/#{@@acronyms.first}/properties/http%3A%2F%2Fbioontology.org%2Fontologies%2FBiomedicalResourceOntology.owl%23Originator?display=all" + assert last_response.ok? + results = MultiJson.load(last_response.body) + + assert_equal ["Originator"], results["label"] + assert results.key?('range') + assert results.key?('domain') + + assert_equal results["properties"]["http://www.w3.org/2000/01/rdf-schema#comment"], ["Originator of a class"] + assert_equal results["properties"]["http://www.w3.org/2004/02/skos/core#prefLabel"], ["Originator"] + assert_equal results["properties"]["http://www.w3.org/1999/02/22-rdf-syntax-ns#type"], ["http://www.w3.org/2002/07/owl#DatatypeProperty"] + assert_equal results["properties"]["http://www.w3.org/2000/01/rdf-schema#domain"], ["http://bioontology.org/ontologies/BiomedicalResourceOntology.owl#Algorithm"] + assert_equal results["properties"]["http://www.w3.org/2000/01/rdf-schema#label"], ["Originator"] + end + def test_property_roots get "/ontologies/#{@@acronyms.first}/properties/roots" assert last_response.ok? @@ -63,14 +82,15 @@ def test_property_roots # count object properties opr = pr.select { |p| p["@type"] == "http://www.w3.org/2002/07/owl#ObjectProperty" } - assert_equal 18, opr.length + assert_includes [18, 13], opr.length # count datatype properties dpr = pr.select { |p| p["@type"] == "http://www.w3.org/2002/07/owl#DatatypeProperty" } - assert_equal 32, dpr.length + assert_includes [32, 31], dpr.length # count annotation properties apr = pr.select { |p| p["@type"] == "http://www.w3.org/2002/07/owl#AnnotationProperty" } - assert_equal 12, apr.length + assert_includes [12, 8], apr.length # check for non-root properties + assert_empty pr.select { |p| ["http://www.w3.org/2004/02/skos/core#broaderTransitive", "http://www.w3.org/2004/02/skos/core#topConceptOf", "http://www.w3.org/2004/02/skos/core#relatedMatch", @@ -100,6 +120,9 @@ def test_property_roots end def test_property_tree + get "/ontologies/#{@@acronyms.first}/properties/http%3A%2F%2Fwww.w3.org%2F2004%2F02%2Fskos%2Fcore%23topConceptOf" + return unless last_response.ok? # depending if owlapi import SKOS + get "/ontologies/#{@@acronyms.first}/properties/http%3A%2F%2Fwww.w3.org%2F2004%2F02%2Fskos%2Fcore%23topConceptOf/tree" assert last_response.ok? pr = MultiJson.load(last_response.body) @@ -131,6 +154,9 @@ def test_property_tree end def test_property_ancestors + get "/ontologies/#{@@acronyms.first}/properties/http%3A%2F%2Fwww.w3.org%2F2004%2F02%2Fskos%2Fcore%23exactMatch" + return unless last_response.ok? + get "/ontologies/#{@@acronyms.first}/properties/http%3A%2F%2Fwww.w3.org%2F2004%2F02%2Fskos%2Fcore%23exactMatch/ancestors" assert last_response.ok? an = MultiJson.load(last_response.body) @@ -145,6 +171,9 @@ def test_property_ancestors end def test_property_descendants + get "/ontologies/#{@@acronyms.first}/properties/http%3A%2F%2Fwww.w3.org%2F2004%2F02%2Fskos%2Fcore%23note" + return unless last_response.ok? # depending if owlapi import SKOS + get "/ontologies/#{@@acronyms.first}/properties/http%3A%2F%2Fwww.w3.org%2F2004%2F02%2Fskos%2Fcore%23note/descendants" assert last_response.ok? dn = MultiJson.load(last_response.body) @@ -162,10 +191,13 @@ def test_property_descendants dn = MultiJson.load(last_response.body) assert_equal 2, dn.length assert_equal ["http://www.semanticweb.org/ontologies/2009/9/12/Ontology1255323704656.owl#overExpress", - "http://www.semanticweb.org/ontologies/2009/9/12/Ontology1255323704656.owl#underExpress"].sort, dn.map { |d| d["@id"] }.sort + "http://www.semanticweb.org/ontologies/2009/9/12/Ontology1255323704656.owl#underExpress"].sort, dn.map { |d| d["@id"] }.sort end def test_property_parents + get "/ontologies/#{@@acronyms.first}/properties/http%3A%2F%2Fwww.w3.org%2F2004%2F02%2Fskos%2Fcore%23changeNote" + return unless last_response.ok? # depending if owlapi import SKOS + get "/ontologies/#{@@acronyms.first}/properties/http%3A%2F%2Fwww.w3.org%2F2004%2F02%2Fskos%2Fcore%23changeNote/parents" assert last_response.ok? pr = MultiJson.load(last_response.body) @@ -191,6 +223,9 @@ def test_property_children ch = MultiJson.load(last_response.body) assert_empty ch + get "/ontologies/#{@@acronyms.first}/properties/http%3A%2F%2Fwww.w3.org%2F2004%2F02%2Fskos%2Fcore%23semanticRelation" + return unless last_response.ok? # depending if owlapi import SKOS + get "/ontologies/#{@@acronyms.first}/properties/http%3A%2F%2Fwww.w3.org%2F2004%2F02%2Fskos%2Fcore%23semanticRelation/children" assert last_response.ok? ch = MultiJson.load(last_response.body) diff --git a/test/controllers/test_properties_search_controller.rb b/test/controllers/test_properties_search_controller.rb index 2a8cadd0a..7d2d961e5 100644 --- a/test/controllers/test_properties_search_controller.rb +++ b/test/controllers/test_properties_search_controller.rb @@ -30,8 +30,8 @@ def before_suite def after_suite LinkedData::SampleData::Ontology.delete_ontologies_and_submissions - LinkedData::Models::Ontology.indexClear(:property) - LinkedData::Models::Ontology.indexCommit(nil, :property) + LinkedData::Models::OntologyProperty.indexClear + LinkedData::Models::OntologyProperty.indexCommit end def test_property_search diff --git a/test/controllers/test_search_controller.rb b/test/controllers/test_search_controller.rb index 1e98a84a5..8ae369501 100644 --- a/test/controllers/test_search_controller.rb +++ b/test/controllers/test_search_controller.rb @@ -4,6 +4,10 @@ class TestSearchController < TestCase def before_suite self.backend_4s_delete + LinkedData::Models::Ontology.indexClear + LinkedData::Models::Class.indexClear + LinkedData::Models::OntologyProperty.indexClear + count, acronyms, bro = LinkedData::SampleData::Ontology.create_ontologies_and_submissions({ process_submission: true, acronym: "BROSEARCHTEST", @@ -265,7 +269,7 @@ def test_search_obo_id # mdorf, 3/2/2024, when the : is followed by a LETTER, as in NCIT:C20480, # then Solr does not split the query on the tokens, # but when the : is followed by a number, as in OGMS:0000071, - # then Solr does split this on tokens and shows the other resuluts + # then Solr does split this on tokens and shows the other results get "/search?q=OGMS:0000071" assert last_response.ok? results = MultiJson.load(last_response.body) @@ -436,11 +440,11 @@ def test_language_attribute_filter assert last_response.ok? assert_equal 1, results["collection"].size doc = results["collection"][0] - assert doc["prefLabel"].kind_of?(Array) + assert doc["prefLabel"].kind_of?(Hash) assert_equal 3, doc["prefLabel"].size - assert doc["synonym"].kind_of?(Array) + assert doc["synonym"].kind_of?(Hash) assert_equal 1, doc["synonym"].size - assert doc["definition"].kind_of?(Array) + assert doc["definition"].kind_of?(Hash) assert_equal 2, doc["definition"].size end diff --git a/test/controllers/test_search_models_controller.rb b/test/controllers/test_search_models_controller.rb new file mode 100644 index 000000000..9b7ab3a60 --- /dev/null +++ b/test/controllers/test_search_models_controller.rb @@ -0,0 +1,417 @@ +require_relative '../test_case' + +class TestSearchModelsController < TestCase + + def after_suite + LinkedData::SampleData::Ontology.delete_ontologies_and_submissions + LinkedData::Models::Ontology.indexClear + LinkedData::Models::Class.indexClear + LinkedData::Models::OntologyProperty.indexClear + Goo.init_search_connection(:ontology_data) + end + + def setup + after_suite + end + + def test_show_all_collection + get '/admin/search/collections' + assert last_response.ok? + res = MultiJson.load(last_response.body) + required = %w[ontology_data ontology_metadata prop_search_core1 term_search_core1] + allowed_extra = %w[term_search test_solr] + collections = res["collections"] + assert_empty required - collections + assert_empty collections - (required + allowed_extra) + end + + def test_collection_schema + get '/admin/search/collections' + assert last_response.ok? + res = MultiJson.load(last_response.body) + collection = res["collections"].first + refute_nil collection + get "/admin/search/collections/#{collection}/schema" + assert last_response.ok? + res = MultiJson.load(last_response.body) + fields = res["fields"].map { |x| x["name"] } + assert_includes fields, 'id' + assert_includes fields, 'resource_id' + assert_includes fields, 'resource_model' + end + + def test_collection_search + LinkedData::SampleData::Ontology.create_ontologies_and_submissions({ + process_submission: false, + acronym: "BROSEARCHTEST", + name: "BRO Search Test", + file_path: "./test/data/ontology_files/BRO_v3.2.owl", + ont_count: 1, + submission_count: 1, + ontology_type: "VALUE_SET_COLLECTION" + }) + collection = 'ontology_metadata' + post "/admin/search/collections/#{collection}/search", {q: ""} + + assert last_response.ok? + res = MultiJson.load(last_response.body) + assert_equal 2, res['response']['numFound'] + end + + def test_search_security + _, _, bro = LinkedData::SampleData::Ontology.create_ontologies_and_submissions({ + process_submission: true, + process_options: { process_rdf: true, extract_metadata: false, generate_missing_labels: false}, + acronym: "BROSEARCHTEST", + name: "BRO Search Test", + file_path: "./test/data/ontology_files/BRO_v3.2.owl", + ont_count: 1, + submission_count: 1, + ontology_type: "VALUE_SET_COLLECTION" + }) + + LinkedData::SampleData::Ontology.create_ontologies_and_submissions({ + process_submission: true, + process_options: { process_rdf: true, extract_metadata: false, generate_missing_labels: false}, + acronym: "MCCLSEARCHTEST", + name: "MCCL Search Test", + file_path: "./test/data/ontology_files/CellLine_OWL_BioPortal_v1.0.owl", + ont_count: 1, + submission_count: 1 + }) + subs = LinkedData::Models::OntologySubmission.all + + subs.each do |s| + s.bring_remaining + s.index_all(Logger.new($stdout)) + end + + allowed_user1 = User.new({ + username: "allowed1", + email: "test1@example.org", + password: "12345" + }) + allowed_user1.save + + allowed_user2 = User.new({ + username: "allowed2", + email: "test2@example.org", + password: "12345" + }) + allowed_user2.save + + blocked_user = User.new({ + username: "blocked", + email: "test3@example.org", + password: "12345" + }) + blocked_user.save + + bro = bro.first + bro.bring_remaining + bro.acl = [allowed_user1, allowed_user2] + bro.viewingRestriction = "private" + bro.save + + begin + self.class.enable_security + + get "/search/ontologies?query=#{bro.acronym}&apikey=#{blocked_user.apikey}" + response = MultiJson.load(last_response.body)["collection"] + assert_empty response.select{|x| x["ontology_acronym_text"].eql?(bro.acronym)} + + get "/search/ontologies/content?q=*Research_Lab_Management*&apikey=#{blocked_user.apikey}" + assert last_response.ok? + res = MultiJson.load(last_response.body) + assert_equal 0, res['totalCount'] + + get "/search/ontologies?query=#{bro.acronym}&apikey=#{allowed_user1.apikey}" + response = MultiJson.load(last_response.body)["collection"] + refute_empty response.select{|x| x["ontology_acronym_text"].eql?(bro.acronym)} + + get "/search/ontologies/content?q=*Research_Lab_Management*&apikey=#{allowed_user1.apikey}" + assert last_response.ok? + res = MultiJson.load(last_response.body) + assert_equal 1, res['totalCount'] + + self.class.reset_security(false) + ensure + self.class.disable_security + end + end + + def test_ontology_metadata_search + LinkedData::SampleData::Ontology.create_ontologies_and_submissions({ + process_submission: false, + acronym: "BROSEARCHTEST", + name: "BRO Search Test", + file_path: "./test/data/ontology_files/BRO_v3.2.owl", + ont_count: 1, + submission_count: 1, + ontology_type: "VALUE_SET_COLLECTION" + }) + + LinkedData::SampleData::Ontology.create_ontologies_and_submissions({ + process_submission: false, + acronym: "MCCLSEARCHTEST", + name: "MCCL Search Test", + file_path: "./test/data/ontology_files/CellLine_OWL_BioPortal_v1.0.owl", + ont_count: 1, + submission_count: 1 + }) + # Search ACRONYM + ## full word + get '/search/ontologies?query=BROSEARCHTEST-0' + response = MultiJson.load(last_response.body)["collection"] + assert_equal 'BROSEARCHTEST-0', response.first['ontology_acronym_text'] + + ### start + get '/search/ontologies?query=BROSEARCHTEST' + response = MultiJson.load(last_response.body)["collection"] + assert_equal 'BROSEARCHTEST-0', response.first['ontology_acronym_text'] + + ## part of the word + get '/search/ontologies?query=BRO' + response = MultiJson.load(last_response.body)["collection"] + assert_equal 'BROSEARCHTEST-0', response.first['ontology_acronym_text'] + + + # Search name + ## full word + ### start + get '/search/ontologies?query=MCCL Search' + response = MultiJson.load(last_response.body)["collection"] + assert_equal 'MCCLSEARCHTEST-0', response.first['ontology_acronym_text'] + ###in the middle + get '/search/ontologies?query=Search Test' + response = MultiJson.load(last_response.body)["collection"] + assert_equal 2, response.size + assert_equal 'BROSEARCHTEST-0', response.first['ontology_acronym_text'] + assert_equal 'MCCLSEARCHTEST-0', response.last['ontology_acronym_text'] + ## part of the word + ### start + get '/search/ontologies?query=MCCL Sea' + response = MultiJson.load(last_response.body)["collection"] + assert_equal 'MCCLSEARCHTEST-0', response.first['ontology_acronym_text'] + ### in the middle + get '/search/ontologies?query=Sea' + response = MultiJson.load(last_response.body)["collection"] + assert_equal 2, response.size + assert_equal 'BROSEARCHTEST-0', response.first['ontology_acronym_text'] + assert_equal 'MCCLSEARCHTEST-0', response.last['ontology_acronym_text'] + + + ## full text + get '/search/ontologies?query=MCCL Search Test' + response = MultiJson.load(last_response.body)["collection"] + assert_equal 'MCCLSEARCHTEST-0', response.first['ontology_acronym_text'] + + + # Search description + ## full word + ### start + get '/search/ontologies?query=Description' + response = MultiJson.load(last_response.body)["collection"] + assert_equal 2, response.size + assert_equal 'BROSEARCHTEST-0', response.first['ontology_acronym_text'] + assert_equal 'MCCLSEARCHTEST-0', response.last['ontology_acronym_text'] + + ### in the middle + get '/search/ontologies?query=1' + response = MultiJson.load(last_response.body)["collection"] + assert_equal 2, response.size + assert_equal 'BROSEARCHTEST-0', response.first['ontology_acronym_text'] + assert_equal 'MCCLSEARCHTEST-0', response.last['ontology_acronym_text'] + + ## part of the word + ### start + get '/search/ontologies?query=Desc' + response = MultiJson.load(last_response.body)["collection"] + assert_equal 2, response.size + assert_equal 'BROSEARCHTEST-0', response.first['ontology_acronym_text'] + assert_equal 'MCCLSEARCHTEST-0', response.last['ontology_acronym_text'] + + ### full text + get '/search/ontologies?query=Description 1' + response = MultiJson.load(last_response.body)["collection"] + assert_equal 2, response.size + assert_equal 'BROSEARCHTEST-0', response.first['ontology_acronym_text'] + assert_equal 'MCCLSEARCHTEST-0', response.last['ontology_acronym_text'] + end + + def test_ontology_metadata_filters + num_onts_created, created_ont_acronyms, ontologies = create_ontologies_and_submissions(ont_count: 10, submission_count: 1) + + group1 = LinkedData::Models::Group.find('group-1').first || LinkedData::Models::Group.new(acronym: 'group-1', name: "Test Group 1").save + group2 = LinkedData::Models::Group.find('group-2').first || LinkedData::Models::Group.new(acronym: 'group-2', name: "Test Group 2").save + category1 = LinkedData::Models::Category.find('category-1').first || LinkedData::Models::Category.new(acronym: 'category-1', name: "Test Category 1").save + category2 = LinkedData::Models::Category.find('category-2').first || LinkedData::Models::Category.new(acronym: 'category-2', name: "Test Category 2").save + + ontologies1 = ontologies[0..5].each do |o| + o.bring_remaining + o.group = [group1] + o.hasDomain = [category1] + o.save + end + + ontologies2 = ontologies[6..8].each do |o| + o.bring_remaining + o.group = [group2] + o.hasDomain = [category2] + o.save + end + + # test filter by group and category + get "/search/ontologies?page=1&pagesize=100&groups=#{group1.acronym}" + assert last_response.ok? + assert_equal ontologies1.size, MultiJson.load(last_response.body)["collection"].length + get "/search/ontologies?page=1&pagesize=100&groups=#{group2.acronym}" + assert last_response.ok? + assert_equal ontologies2.size, MultiJson.load(last_response.body)["collection"].length + + get "/search/ontologies?page=1&pagesize=100&groups=#{group1.acronym},#{group2.acronym}" + assert last_response.ok? + assert_equal ontologies1.size + ontologies2.size, MultiJson.load(last_response.body)["collection"].length + + get "/search/ontologies?page=1&pagesize=100&hasDomain=#{category1.acronym}" + assert last_response.ok? + assert_equal ontologies1.size, MultiJson.load(last_response.body)["collection"].length + + get "/search/ontologies?page=1&pagesize=100&hasDomain=#{category2.acronym}" + assert last_response.ok? + assert_equal ontologies2.size, MultiJson.load(last_response.body)["collection"].length + + get "/search/ontologies?page=1&pagesize=100&hasDomain=#{category2.acronym},#{category1.acronym}" + assert last_response.ok? + assert_equal ontologies1.size + ontologies2.size, MultiJson.load(last_response.body)["collection"].length + + get "/search/ontologies?page=1&pagesize=100&hasDomain=#{category2.acronym}&groups=#{group1.acronym}" + assert last_response.ok? + assert_equal 0, MultiJson.load(last_response.body)["collection"].length + get "/search/ontologies?page=1&pagesize=100&hasDomain=#{category2.acronym}&groups=#{group2.acronym}" + assert last_response.ok? + assert_equal ontologies2.size, MultiJson.load(last_response.body)["collection"].length + + ontologies3 = ontologies[9] + ontologies3.bring_remaining + ontologies3.group = [group1, group2] + ontologies3.hasDomain = [category1, category2] + ontologies3.name = "name search test" + ontologies3.save + + ontologies.first.name = "sort by test" + ontologies.first.save + sub = ontologies.first.latest_submission(status: :any).bring_remaining + sub.status = 'retired' + sub.description = "234" + sub.creationDate = DateTime.yesterday.to_datetime + sub.hasOntologyLanguage = LinkedData::Models::OntologyFormat.find('SKOS').first + sub.save + + #test search with sort + get "/search/ontologies?page=1&pagesize=100&q=tes&sort=ontology_name_sort asc" + assert last_response.ok? + submissions = MultiJson.load(last_response.body) + + refute_empty submissions["collection"] + assert_equal ontologies.map{|x| x.bring(:name).name}.sort, submissions["collection"].map{|x| x["ontology_name_text"]} + + get "/search/ontologies?page=1&pagesize=100&q=tes&sort=creationDate_dt desc" + + assert last_response.ok? + submissions = MultiJson.load(last_response.body) + refute_empty submissions["collection"] + assert_equal ontologies.map{|x| x.latest_submission(status: :any).bring(:creationDate).creationDate.to_s.split('T').first}.sort.reverse, + submissions["collection"].map{|x| x["creationDate_dt"].split('T').first} + + # test search with format + get "/search/ontologies?page=1&pagesize=100&q=tes&hasOntologyLanguage=SKOS" + assert last_response.ok? + submissions = MultiJson.load(last_response.body) + + refute_empty submissions["collection"] + assert_equal 1, submissions["collection"].size + + get "/search/ontologies?page=1&pagesize=100&q=tes&hasOntologyLanguage=OWL" + assert last_response.ok? + submissions = MultiJson.load(last_response.body) + refute_empty submissions["collection"] + assert_equal ontologies.size-1 , submissions["collection"].size + + # test ontology filter with submission filter attributes + get "/search/ontologies?page=1&pagesize=100&q=tes&groups=group-2&hasDomain=category-2&hasOntologyLanguage=OWL" + assert last_response.ok? + submissions = MultiJson.load(last_response.body) + refute_empty submissions["collection"] + assert_equal ontologies2.size + 1 , submissions["collection"].size + + # test ontology filter with status + get "/search/ontologies?page=1&pagesize=100&status=retired" + assert last_response.ok? + submissions = MultiJson.load(last_response.body) + refute_empty submissions["collection"] + assert_equal 1 , submissions["collection"].size + + get "/search/ontologies?page=1&pagesize=100&status=alpha,beta,production" + assert last_response.ok? + submissions = MultiJson.load(last_response.body) + refute_empty submissions["collection"] + assert_equal ontologies.size - 1 , submissions["collection"].size + + get "/search/ontologies?page=1&pagesize=100&q=234" + assert last_response.ok? + submissions = MultiJson.load(last_response.body) + assert_equal "http://data.bioontology.org/ontologies/TEST-ONT-0/submissions/1" , submissions["collection"].first["id"] + end + + def test_search_data + LinkedData::SampleData::Ontology.create_ontologies_and_submissions({ + process_submission: true, + process_options: { process_rdf: true, extract_metadata: false, index_all_data: true, generate_missing_labels: false}, + acronym: "BROSEARCHTEST", + name: "BRO Search Test", + file_path: "./test/data/ontology_files/BRO_v3.2.owl", + ont_count: 1, + submission_count: 1, + ontology_type: "VALUE_SET_COLLECTION" + }) + + LinkedData::SampleData::Ontology.create_ontologies_and_submissions({ + process_submission: true, + process_options: { process_rdf: true, extract_metadata: false, index_all_data: true, generate_missing_labels: false}, + acronym: "MCCLSEARCHTEST", + name: "MCCL Search Test", + file_path: "./test/data/ontology_files/CellLine_OWL_BioPortal_v1.0.owl", + ont_count: 1, + submission_count: 1 + }) + subs = LinkedData::Models::OntologySubmission.all + count = [] + subs.each do |s| + count << Goo.sparql_query_client.query("SELECT (COUNT( DISTINCT ?id) as ?c) FROM <#{s.id}> WHERE {?id ?p ?v}") + .first[:c] + .to_i + end + + get "/search/ontologies/content?q=*" + assert last_response.ok? + res = MultiJson.load(last_response.body) + assert_equal count.sum, res['totalCount'] + + get "/search/ontologies/content?q=*&ontologies=MCCLSEARCHTEST-0,BROSEARCHTEST-0" + assert last_response.ok? + res = MultiJson.load(last_response.body) + assert_equal count.sum, res['totalCount'] + + get "/search/ontologies/content?q=*&ontologies=BROSEARCHTEST-0" + assert last_response.ok? + res = MultiJson.load(last_response.body) + assert_includes count, res['totalCount'] + + get "/search/ontologies/content?q=*&ontologies=MCCLSEARCHTEST-0" + assert last_response.ok? + res = MultiJson.load(last_response.body) + assert_includes count, res['totalCount'] + end + +end diff --git a/test/controllers/test_users_controller.rb b/test/controllers/test_users_controller.rb index 223cd641b..47c929c33 100644 --- a/test/controllers/test_users_controller.rb +++ b/test/controllers/test_users_controller.rb @@ -21,48 +21,6 @@ def self._delete_users end end - def test_rejects_restricted_user_attributes_on_post_and_patch - username = "restricted_test_user" - email = "restricted@example.org" - password = "testpass" - - # Create baseline user - post "/users", { - username: username, - email: email, - password: password - } - assert_equal 201, last_response.status - - # POST attempt with restricted attributes - post "/users", { - username: "new-user", - email: "new@example.org", - password: "newpass", - created: DateTime.now + 1.year, - resetToken: "invalid", - resetTokenExpireTime: DateTime.now - } - assert_equal 201, last_response.status - user = User.find('new-user').include(User.attributes).first - assert_nil user.resetToken - assert_nil user.resetTokenExpireTime - assert_operator Time.now.to_time.to_i, :>=, user.created.to_time.to_i - - # PATCH attempt with restricted attributes - patch "/users/#{username}", { - created: DateTime.now + 1.year, - resetToken: "still-invalid", - resetTokenExpireTime: DateTime.now - } - assert_equal 204, last_response.status - user = User.find('new-user').include(User.attributes).first - assert_nil user.resetToken - assert_nil user.resetTokenExpireTime - assert_operator Time.at(Time.now.to_i), :>=, user.created.to_time - - end - def test_admin_creation existent_user = @@users.first #no admin @@ -80,18 +38,6 @@ def test_all_users users = MultiJson.load(last_response.body) assert users.any? {|u| u["username"].eql?("fred")} assert users.length >= @@usernames.length - - get '/users?search=fred' - assert last_response.ok? - users = MultiJson.load(last_response.body) - assert users.all? {|u| u["username"].include?("fred")} - assert users.length == 1 - - get '/users?page=1&pagesize=5' - assert last_response.ok? - users = MultiJson.load(last_response.body) - assert_equal 5, users["collection"].length - assert users["totalCount"] >= @@usernames.length end def test_single_user @@ -102,21 +48,6 @@ def test_single_user assert_equal "fred", MultiJson.load(last_response.body)["username"] end - def test_hide_sensitive_data - user = @@users[0] - reset_token = token(36) - user.resetToken = reset_token - user.resetTokenExpireTime = Time.now.to_i - 2.hours.to_i - user.save - - username = user.username - get "/users/#{username}?display=resetToken,resetTokenExpireTime" - assert last_response.ok? - - refute_includes MultiJson.load(last_response.body), 'resetToken', "resetToken should NOT be included in the response" - refute_includes MultiJson.load(last_response.body), 'resetTokenExpireTime', "resetTokenExpireTime should NOT be included in the response" - end - def test_create_new_user user = {email: "#{@@username}@example.org", password: "pass_the_word"} put "/users/#{@@username}", MultiJson.dump(user), "CONTENT_TYPE" => "application/json" @@ -136,7 +67,7 @@ def test_create_new_user get "/users/#{@@username}" assert last_response.ok? - assert MultiJson.load(last_response.body)["username"].eql?(@@username) + assert MultiJson.load(last_response.body)["username"].eql?(@@username) assert_equal "test_user@example.org", MultiJson.load(last_response.body)["email"] end @@ -187,7 +118,6 @@ def test_reset_password_expired_token assert_equal 401, last_response.status end - def test_create_new_invalid_user put "/users/totally_new_user" assert last_response.status == 422 @@ -238,18 +168,61 @@ def test_authentication assert user["username"].eql?(@@usernames.first) end - private + def test_oauth_authentication + fake_responses = { + github: { + id: 123456789, + login: 'github_user', + email: 'github_user@example.com', + name: 'GitHub User', + avatar_url: 'https://avatars.githubusercontent.com/u/123456789' + }, + google: { + sub: 'google_user_id', + email: 'google_user@example.com', + name: 'Google User', + given_name: 'Google', + family_name: 'User', + picture: 'https://lh3.googleusercontent.com/a-/user-profile-image-url' + }, + orcid: { + orcid: '0000-0002-1825-0097', + email: 'orcid_user@example.com', + name: { + "family-name": 'ORCID', + "given-names": 'User' + } + } + } + + fake_responses.each do |provider, data| + WebMock.stub_request(:get, LinkedData::Models::User.oauth_providers[provider][:link]) + .to_return(status: 200, body: data.to_json, headers: { 'Content-Type' => 'application/json' }) + post "/users/authenticate", {access_token:'jkooko', token_provider: provider.to_s} + assert last_response.ok? + user = MultiJson.load(last_response.body) + assert data[:email], user["email"] + end + end - def token(len) - chars = ("a".."z").to_a + ("A".."Z").to_a + ("1".."9").to_a - token = "" - 1.upto(len) { |i| token << chars[rand(chars.size-1)] } - token + def test_hide_sensitive_data + user = @@users[0] + reset_token = "reset_password_token" + user.resetToken = reset_token + user.save + username = user.username + get "/users/#{username}?display=resetToken,passwordHash" + assert last_response.ok? + refute_includes MultiJson.load(last_response.body), 'resetToken', "resetToken should NOT be included in the response" + refute_includes MultiJson.load(last_response.body), 'passwordHash', "passwordHash should NOT be included in the response" end + private + def _delete_user(username) LinkedData::Models::User.find(@@username).first&.delete end + def _create_admin_user(apikey: nil) user = {email: "#{@@username}@example.org", password: "pass_the_word", role: ['ADMINISTRATOR']} _delete_user(@@username) @@ -276,4 +249,4 @@ def _create_admin_user(apikey: nil) true if user["role"].eql?(['ADMINISTRATOR']) end -end +end \ No newline at end of file diff --git a/test/data/ontology_files/BRO_v3.2.owl b/test/data/ontology_files/BRO_v3.2.owl index 33e91d797..c083fb3d3 100644 --- a/test/data/ontology_files/BRO_v3.2.owl +++ b/test/data/ontology_files/BRO_v3.2.owl @@ -44,10 +44,10 @@ - - - + @@ -64,7 +64,7 @@ Definition definition - + @@ -73,28 +73,28 @@ replacedBy - + - + - + - - - + @@ -113,7 +113,7 @@ Scientific purpose of algorithm - + @@ -124,7 +124,7 @@ What are the goals of the document - + @@ -134,7 +134,7 @@ InteractionType What type of interaction is this? - + @@ -145,7 +145,7 @@ what kind of information is being capture in this measurement? - + @@ -156,7 +156,7 @@ What form of output is produced by this thing - + @@ -168,7 +168,7 @@ - + @@ -180,7 +180,7 @@ - + @@ -198,7 +198,7 @@ - + @@ -209,7 +209,7 @@ - + @@ -219,7 +219,7 @@ - + @@ -227,7 +227,7 @@ replacedBy - + @@ -239,7 +239,7 @@ - + @@ -250,10 +250,10 @@ - - - + @@ -271,7 +271,7 @@ Any kind of identifier Identifier - + @@ -280,7 +280,7 @@ Implementation_Language Implementation Language - + @@ -291,7 +291,7 @@ Originator of a class - + @@ -301,7 +301,7 @@ Other Information - + @@ -312,7 +312,7 @@ is this a peer-reviewed scientific publication? - + @@ -322,7 +322,7 @@ ProteinType broad classification of protein type based on structure or function - + @@ -331,7 +331,7 @@ Target_User_Type Target User Type - + @@ -341,7 +341,7 @@ TranscriptType Type of biological transcript - + @@ -352,7 +352,7 @@ - + @@ -363,7 +363,7 @@ - + @@ -373,7 +373,7 @@ true - + @@ -385,7 +385,7 @@ - + @@ -397,7 +397,7 @@ - + @@ -407,7 +407,7 @@ contact person email - + @@ -418,7 +418,7 @@ - + @@ -428,7 +428,7 @@ definition - + @@ -440,7 +440,7 @@ - + @@ -452,7 +452,7 @@ - + @@ -462,7 +462,7 @@ true - + @@ -474,7 +474,7 @@ - + @@ -486,7 +486,7 @@ - + @@ -498,7 +498,7 @@ - + @@ -510,7 +510,7 @@ - + @@ -520,7 +520,7 @@ true - + @@ -532,7 +532,7 @@ - + @@ -544,7 +544,7 @@ - + @@ -554,7 +554,7 @@ release date - + @@ -566,7 +566,7 @@ - + @@ -578,7 +578,7 @@ - + @@ -590,7 +590,7 @@ - + @@ -601,7 +601,7 @@ - + @@ -613,10 +613,10 @@ - - - + @@ -638,19 +638,19 @@ Activité d’intérêt pouvant être liée à un BRO:Resource. activities - + + Activity related to the creation, use, or maintenance of a biorepository (http://en.wikipedia.org/wiki/Biorepository) + Biospecimen Management Activity related to the creation, use, or maintenance of a biorepository (http://en.wikipedia.org/wiki/Biorepository) Activité liée à la création, à l'utilisation ou à la maintenance d'un bioréférentiel (http://en.wikipedia.org/wiki/Biorepository) - Biospecimen Management - Gestion des échantillons biologiques - + @@ -658,9 +658,8 @@ As defined in http://en.wikipedia.org/wiki/Community_engagement - Community Engagement - + @@ -670,7 +669,7 @@ Former subclasses of activity:Activity that have been deprecated and their usage is not recommended. true - + @@ -678,9 +677,9 @@ As defined in http://en.wikipedia.org/wiki/Gene_therapy - Gene Therapy + Gene Therapy - + @@ -690,7 +689,7 @@ As defined in http://en.wikipedia.org/wiki/Health_services_research Health Services - + @@ -703,7 +702,7 @@ true - + @@ -714,7 +713,7 @@ Tag as a resource for a specific Institutional Review Board (http://en.wikipedia.org/wiki/Institutional_Review_Board) 0123456789 - + @@ -724,7 +723,7 @@ As defined in http://en.wikipedia.org/wiki/Medical_device Medical Device Development - + @@ -737,7 +736,7 @@ true - + @@ -747,7 +746,7 @@ As defined in http://en.wikipedia.org/wiki/Regulatory_compliance Regulatory Compliance - + @@ -757,7 +756,7 @@ Activity related to learning about, securing, and managing money to support research Research Funding - + @@ -767,7 +766,7 @@ Management and communications within the laboratory setting (http://www.umuc.edu/programs/undergrad/certificates/lab_mgmt.shtml) Research Lab Management - + @@ -777,7 +776,7 @@ Activity related to gathering and inventory of resources, e.g., biositemaps Resource Inventory - + @@ -787,7 +786,7 @@ As defined in http://en.wikipedia.org/wiki/Small_molecule Small Molecule - + @@ -797,7 +796,7 @@ As defined in http://en.wikipedia.org/wiki/Social_network Social Networking - + @@ -806,7 +805,7 @@ Software Development - + @@ -816,7 +815,7 @@ Methods used in the medical specialty of surgery, as defined in http://en.wikipedia.org/wiki/Surgical_procedure Surgical Procedure - + @@ -826,7 +825,7 @@ Innovative therapeutics (http://en.wiktionary.org/wiki/therapeutics) Therapeutics - + @@ -836,7 +835,7 @@ As defined in http://en.wikipedia.org/wiki/Training Training - + @@ -846,7 +845,7 @@ A resource that provides data from clinical care that comprises combined data from multiple individual human subjects. Aggregate Human Data - + @@ -856,7 +855,7 @@ Algorithm Resource that provides access to software or application that perform numerical analysis or other canonical computational methods that act either on experimental or synthetic data. - + @@ -867,7 +866,7 @@ An instrument that increases the output of another instrument. pending final vetting: work with eagle-i to define terms since out of scope of BRO - + @@ -877,7 +876,7 @@ Analysis of Gel-Electrophoresis Resource that provides access to software, applications, or toolkits that can be used to provide quantitative data on the molecules being analyzed such as molecular weight, abundance or purity. - + @@ -890,7 +889,7 @@ true - + @@ -901,7 +900,7 @@ Animal Care Facility pending final vetting: Refine definition - + @@ -911,7 +910,7 @@ A resource which can include a committee or a board that reviews research protocols and conducts evaluations of the animal care facilities. The resource can be used to ensure the use of animals in research follows the required legal and ethical guidelines. Animal Compliance Resource - + @@ -922,7 +921,7 @@ Animal Models Facility pending final vetting: Refine definition - + @@ -932,7 +931,7 @@ A resource that provides access to the ability to generate antibodies that bind to a specific antigen. Antibody Production - + @@ -942,7 +941,7 @@ Application Programming Interface Resource that provides access to software, application, or toolkit that enables or can be used to develop application programming interfaces. - + @@ -953,7 +952,7 @@ Approximate Graph Alignment Resource that provides access to software, applications, or toolkits that allows insertions, deletions, or mismatches in nodes/edges. - + @@ -963,7 +962,7 @@ A resource that provides access to scientific data assessment instruments, for example behavioral assessment tests. Assessment Material Resource - + @@ -973,7 +972,7 @@ A resource that provides anatomical data represented by spatially indexed anatomical maps. Atlas - + @@ -983,7 +982,7 @@ Atlas Generation Resource that provides access to software, applications, or toolkits that generate computational atlases of biological objects using imaging techniques. - + @@ -993,7 +992,7 @@ Authentication The process of confirming the correctness of the claimed identity. - + @@ -1003,7 +1002,7 @@ Authorization The process of specifying access rights to a resource. - + @@ -1016,7 +1015,7 @@ true - + @@ -1026,7 +1025,7 @@ Averaging and Agglomeration Resource that provides access to software, applications, or toolkits that performs signal processing by repeated measures of the signal and then calculates the expected value of the data set. - + @@ -1039,7 +1038,7 @@ true - + @@ -1049,7 +1048,7 @@ A resource that provides long-term storage for back-up copies of files. Backup Archive Service - + @@ -1063,7 +1062,7 @@ - + @@ -1074,7 +1073,7 @@ Behavioral Analysis Service pending final vetting: review hierarchy location - + @@ -1085,7 +1084,7 @@ Bibliographic Resource - + @@ -1098,7 +1097,7 @@ true - + @@ -1108,7 +1107,7 @@ A facility or core that provides storage for any type of biospecimen. Biobank Facility - + @@ -1121,7 +1120,7 @@ true - + @@ -1131,7 +1130,7 @@ A resource that provides data from any biomaterial sample that was given to the service provider. This can also be a service that performs an experiment such as electrophysiological examination of LTP in a transgenic mouse. Viewing this as an input/output relationship the input would be a tissue or an animal and the output would be data. Biomaterial Analysis Service - + @@ -1141,7 +1140,7 @@ A resource that produces a product that is of organismal origin. An example of a biomaterial service is the production of a knockout mouse or cell culture. Note, for simplicity of definitions all molecules including antibodies and toxins are considered reagents even though some may have an organismal origin. Biomaterial Manufacture - + @@ -1151,7 +1150,7 @@ A resource that provides access to physical materials like tissue samples or organisms. For example, the IMSR enables acquisition of a transgenic mouse or cell line. Note, for the sake of simplicity we have excluded molecules of organismal origin from this category as these can be manufactured chemically and have included them under the reagent category (eg. antibodies, toxins). Biomaterial Supply Resource - + @@ -1162,7 +1161,7 @@ Biomedical Supply Resource pending final vetting: suggest to deprecate - + @@ -1173,7 +1172,7 @@ Biomolecular Interaction Facility pending final vetting: Refine definition - + @@ -1183,7 +1182,7 @@ A resource that provides access to an enclosed facility that takes specified precautions for containment of dangerous biological agents, as defined by http://en.wikipedia.org/wiki/Biosafety_level Biosafety Level Facility - + @@ -1193,7 +1192,7 @@ A resource that provides access to a written or printed work of fiction or nonfiction, usually on sheets of paper fastened or bound together within covers. Book - + @@ -1203,7 +1202,7 @@ Bug Reporting Resource that provides access to software, application, or toolkit that enable web-based tools that provide structure to indicate a problem or issue. Typically, bug reporting software provides a mechanism to indicate the severity of the problem and a contact person to review the issue. - + @@ -1215,7 +1214,7 @@ CT Scanner pending final vetting: location in hierarchy and harmonize with OBI/eagle-i - + @@ -1225,7 +1224,7 @@ Calculation of Solvent Accessible Area Resource that provides access to software, applications, or toolkits that can be used to determine the surface area of a molecule such as DNA or protein. - + @@ -1235,7 +1234,7 @@ A resource that provides functionality to allocate resources based on a method of timekeeping. Calendar Schedule and Resource Management - + @@ -1246,7 +1245,7 @@ Calorimeter pending final vetting: work with eagle-i to define terms since out of scope of BRO - + @@ -1257,7 +1256,7 @@ Cardiovascular Facility pending final vetting: Refine definition - + @@ -1267,7 +1266,7 @@ Cardiovascular Model Resource that provides access to software, applications, or toolkits that can be used to model physiological processes of the cardiovascular system. - + @@ -1277,7 +1276,7 @@ A resource that provides access to instruments, technologies, facilities, and/or expert support devoted to cell biology (http://en.wikipedia.org/wiki/Cell_biology) research Cell Biology Facility - + @@ -1287,7 +1286,7 @@ A facility or core that provides resources for the growth of cells. Cell Culture Facility - + @@ -1297,7 +1296,7 @@ Cell Model Resource that provides access to software, applications, or toolkits that model the processes of a cell. - + @@ -1307,7 +1306,7 @@ A resource that provides access to an enclosed environment that has a low and controlled level of environmental pollutants such as dust, airborne microbes, aerosol particles and chemical vapors. Cell Processing Clean Room Facility - + @@ -1320,7 +1319,7 @@ true - + @@ -1330,7 +1329,7 @@ A Resource that provides access to a graph algorithm that uses ranking of network elements to identify the importance of elements in a network. Centrality Analysis - + @@ -1340,7 +1339,7 @@ A resource that provides a document that certifies completion of the program. Certificate Program - + @@ -1351,7 +1350,7 @@ Chamber pending final vetting: work with eagle-i to define terms since out of scope of BRO - + @@ -1361,7 +1360,7 @@ A resource that provides any type of data obtained in the course of caring for humans outside of measurements obtained in clinical trials. Clinical Care Data - + @@ -1375,7 +1374,7 @@ we think this should be deleted true - + @@ -1389,7 +1388,7 @@ we think this should be deleted true - + @@ -1402,7 +1401,7 @@ we think this should be deleted true - + @@ -1412,7 +1411,7 @@ we think this should be deleted A resource that provides data on clinical trials and outcomes studies. Clinical Research Data - + @@ -1425,7 +1424,7 @@ we think this should be deleted true - + @@ -1435,7 +1434,7 @@ we think this should be deleted A resource that provides a performance analysis tool that measures the behavior of a program as it executes, particularly the frequency and duration of function calls. The profiling process helps to determine which subroutines (or just snippets of code) take longest to execute and which subroutines are called most often. Code profilers are used when you suspect that some part of your code is called very often and maybe there is a need to optimize it, which could significantly improve the overall performance. Profilers use a wide variety of techniques to collect data, including hardware interrupts, code instrumentation, instruction set simulation, operating system hooks, and performance counters. Code Profiler - + @@ -1445,7 +1444,7 @@ we think this should be deleted A resource that provides a software environment created to investigate the quality of the product or service under test, with respect to the context in which it is intended to operate. This includes, but is not limited to, the process of executing a program or application with the intent of finding software bugs. Code Testing Framework - + @@ -1455,7 +1454,7 @@ we think this should be deleted Communication Interface Resource that provides access to software, applications, or toolkits that enable electronic communication. - + @@ -1465,7 +1464,7 @@ we think this should be deleted Communication and Collaborative Work Resource that provides access to software, application, or toolkit that has mechanisms for sharing information between members of a group working on a shared project. - + @@ -1475,7 +1474,7 @@ we think this should be deleted Community Structure Analysis Resource that provides access to a graph algorithm that identifies densely interlinked nodes in the graph. - + @@ -1485,7 +1484,7 @@ we think this should be deleted A resource that provides a computer program (or set of programs) that transforms source code written in a computer language (the source language) into another computer language (the target language, often having a binary form known as object code). The most common reason for wanting to transform source code is to create an executable program. A \\u201ccompiler\\u201d is primarily used for programs that translate source code from a high-level programming language to a lower level language (e.g., assembly language or machine language), and is likely to perform many or all of the following operations: lexical analysis, pre-processing, parsing, semantic analysis, code generation, and code optimization. Compiler - + @@ -1496,7 +1495,7 @@ we think this should be deleted Computational Geometry Resource that provides access to tools for computational geometric representation and analysis. - + @@ -1507,7 +1506,7 @@ we think this should be deleted Computational Hosting pending final vetting: propose definition - + @@ -1517,7 +1516,7 @@ we think this should be deleted A resource that provides a simplified or symbolic representation of a system or phenomenon. Computational Model - + @@ -1527,7 +1526,7 @@ we think this should be deleted A resource that provides support for computer-related services such as database hosting and backup and disaster recovery. Computational Service - + @@ -1538,7 +1537,7 @@ we think this should be deleted Computer-Instrumentation Interface pending final vetting: work with eagle-i to define terms since out of scope of BRO - + @@ -1548,7 +1547,7 @@ we think this should be deleted A resource the provides access to papers and/or talk and poster abstracts that are presented at a conference. Conference Proceeding - + @@ -1558,7 +1557,7 @@ we think this should be deleted A resource that develops policies and procedures related to associations between academia and industry to ensure that the advantages of these connections are not being achieved at the expense of the fundamental values of objectivity in research. Conflict of Interest Resource - + @@ -1571,7 +1570,7 @@ we think this should be deleted true - + @@ -1581,7 +1580,7 @@ we think this should be deleted Contact Modeling Resource that provides access to software, applications, or toolkits that simulate the effect of contact between objects. For example an articular contact model to study articular surface stresses. - + @@ -1591,7 +1590,7 @@ we think this should be deleted A resource that provides post-grad education for physicians. Continuing Medical Education - + @@ -1604,7 +1603,7 @@ we think this should be deleted true - + @@ -1614,7 +1613,7 @@ we think this should be deleted Continuum Method Simulation Resource that provides access to software, applications, or toolkits that uses all data points in a simulation. - + @@ -1624,7 +1623,7 @@ we think this should be deleted Controllers Resource that provides access to software, applications, or toolkits that use controllers in the performance of a simulation. - + @@ -1635,7 +1634,7 @@ we think this should be deleted Convolution Resource the provides access to tools or functions that implements the canonical convolution or operation that describes the action of a linear system on a signal. - + @@ -1645,7 +1644,7 @@ we think this should be deleted Cortical Modeling Resource that provides access to software, applications, or toolkits that perform detection, extraction, representation and analysis of cortical brain structure. - + @@ -1655,7 +1654,7 @@ we think this should be deleted Course Material Resource that provides access to educational material that can be used to disseminate information about a course of study. - + @@ -1665,7 +1664,7 @@ we think this should be deleted Cross-Language Wrapping Resource that provides access to software, application, or toolkit that enables an interactive software development tool that creates language bindings. - + @@ -1675,7 +1674,7 @@ we think this should be deleted Cross-Platform Tool Resource that provides access to software, application, or toolkit that enables an interactive software development tool that runs on different computer operating systems. - + @@ -1685,7 +1684,7 @@ we think this should be deleted Cross-Sectional Viewer Resource that provides access to data visualization tools relying on displays of lower-dimensional cross-sectional (hyper)planes. - + @@ -1696,7 +1695,7 @@ we think this should be deleted Resource that provides access to software or application that support collection of real-world conditions and converts these to a numerical representation that can be processed by a computer, http://en.wikipedia.org/wiki/Data_acquisition. pending final vetting: review term in comparison to siblings data analysis software and data processing software - + @@ -1706,7 +1705,7 @@ we think this should be deleted A resource that provides access to software or application that is used to analyze, model, and transform data with the goal of testing a research hypothesis, highlighting useful information, suggesting conclusions, or supporting decision making. Data Analysis Software - + @@ -1716,7 +1715,7 @@ we think this should be deleted Data Annotation Resource that provides access an interactive software tool that enables tagging data with ontology terms. - + @@ -1726,7 +1725,7 @@ we think this should be deleted Data Compression Resource that provides access to software, applications, or toolkits that reduces the bits (information units) needed to encode the data. - + @@ -1736,7 +1735,7 @@ we think this should be deleted A resource that provides calculating or processing over a data input, such as interpreting EEG data. Note, this may include human and/or computer expertise, so that a software tool may be included as a data computation service. Data Computation Service - + @@ -1749,7 +1748,7 @@ we think this should be deleted true - + @@ -1759,7 +1758,7 @@ we think this should be deleted Data Editor Resource that provides access to software, application, or toolkit that is able to alter information. - + @@ -1769,7 +1768,7 @@ we think this should be deleted Data Exploration Resource that provides access to a visualization tool that is able to display data as an image or graphical representation. - + @@ -1781,7 +1780,7 @@ we think this should be deleted Data Mining and Inference pending final vetting: review location in hierarchy and child terms - + @@ -1791,7 +1790,7 @@ we think this should be deleted Data Normalization Resource that provides access to software, applications, or toolkits that reduces systematic sources of variation from data. - + @@ -1804,7 +1803,7 @@ we think this should be deleted true - + @@ -1814,7 +1813,7 @@ we think this should be deleted A resource that provides access to software or application that is used to convert or manipulate data into information or knowledge. Data Processing Software - + @@ -1827,7 +1826,7 @@ we think this should be deleted true - + @@ -1837,7 +1836,7 @@ we think this should be deleted A resource that provides individual facts, statistics or items of information. Data Resource - + @@ -1848,7 +1847,7 @@ we think this should be deleted Data Service pending final vetting: review location in hierarchy - + @@ -1862,7 +1861,7 @@ we think this should be deleted - + @@ -1875,7 +1874,7 @@ we think this should be deleted true - + @@ -1885,7 +1884,7 @@ we think this should be deleted A resource that provides data storage and maintenance, such as a database that accepts submissions of similar data for storage and use. For example, the cell centered database (CCDB) encourages submissions of anatomical images that will increase its' holdings. Data Storage Service - + @@ -1895,7 +1894,7 @@ we think this should be deleted A resource that provides access to software or application that is used to transmit formatted textual or binary data. Data Transfer and Communication - + @@ -1905,7 +1904,7 @@ we think this should be deleted Data Transform Resource that provides access to software, applications, or toolkits that general data transformations. - + @@ -1918,7 +1917,7 @@ we think this should be deleted true - + @@ -1928,7 +1927,7 @@ we think this should be deleted Data Visualization Resource that provides access to software, applications, or toolkits that present information as an image. - + @@ -1939,7 +1938,7 @@ we think this should be deleted Data Repository Database - + @@ -1949,7 +1948,7 @@ we think this should be deleted A resource that provides space for and access to a database. Database Hosting - + @@ -1959,7 +1958,7 @@ we think this should be deleted A resource that provides access to software, applications, or toolkits that are used in the development of database management systems. Database Software - + @@ -1969,7 +1968,7 @@ we think this should be deleted Deep Parsing Resource that provides access to applications, libraries, or software that detect relationships between language constructs. - + @@ -1979,7 +1978,7 @@ we think this should be deleted A resource that provides access to structured data that is separated by a sequence of one or more characters to mark the boundary between plain text or data streams. Delimited Table - + @@ -1991,7 +1990,7 @@ we think this should be deleted Former subclasses of BRO:Data_Resource that have been deprecated and their usage is not recommended. true - + @@ -2001,7 +2000,7 @@ we think this should be deleted Former subclasses of BRO:Resource that have been deprecated and their usage is not recommended. true - + @@ -2011,7 +2010,7 @@ we think this should be deleted A resource that provides the ability to retrieve archived content in the event of a disaster that impacts the system in question. Disaster Recovery Service - + @@ -2024,7 +2023,7 @@ we think this should be deleted true - + @@ -2034,7 +2033,7 @@ we think this should be deleted Dissemination Vehicle Resource that provides access to Community and User Interaction Systems, educational resources and web-services. - + @@ -2047,7 +2046,7 @@ we think this should be deleted true - + @@ -2057,7 +2056,7 @@ we think this should be deleted Document Generation Resource that provides access to software, application, or toolkit that enables a software development tool that is able to generate textual information when included in computer source code as specially formatted comments. - + @@ -2068,7 +2067,7 @@ we think this should be deleted Resource that provides access to software, applications, or toolkits that provides an electronic document or file in response to a query. pending final vetting: review location in hierarchy - + @@ -2078,7 +2077,7 @@ we think this should be deleted Document Structure Parsing Resource that provides access to applications, libraries, or software that analyze and report on document structure. - + @@ -2088,7 +2087,7 @@ we think this should be deleted Documentation Generation Resource that provides access to software, application, or toolkit that enables a software development tool create documentation of software source code. - + @@ -2099,7 +2098,7 @@ we think this should be deleted Drug Delivery Device pending final vetting: work with eagle-i to define terms since out of scope of BRO - + @@ -2109,7 +2108,7 @@ we think this should be deleted A resource that provides a simplified or symbolic representation representing the states of a system or network over time. Dynamic Model - + @@ -2122,7 +2121,7 @@ we think this should be deleted true - + @@ -2132,7 +2131,7 @@ we think this should be deleted Education Resource that provides access to educational resources (incl. book, magazines, audio, video, digital streams, etc.), - + @@ -2143,7 +2142,7 @@ we think this should be deleted Electrode Holder pending final vetting: work with eagle-i to define terms since out of scope of BRO - + @@ -2154,7 +2153,7 @@ we think this should be deleted Electrode Puller pending final vetting: work with eagle-i to define terms since out of scope of BRO - + @@ -2166,7 +2165,7 @@ we think this should be deleted Electron Microscope In version 3.2 pending final vetting: work with eagle-i to define terms since out of scope of BRO - + @@ -2176,7 +2175,7 @@ we think this should be deleted A resource that provides services to ensure research is conducted in accordance with environmental and safety standards (e.g. laboratory safety procedures, radiation safety procedures, disposal protocols, etc). Environmental Health and Safety Resource - + @@ -2189,7 +2188,7 @@ we think this should be deleted true - + @@ -2199,7 +2198,7 @@ we think this should be deleted A resource that provides detailed plans for a scientific experiments, medical trials, or other pieces of research. Experimental Protocol - + @@ -2212,7 +2211,7 @@ we think this should be deleted true - + @@ -2222,7 +2221,7 @@ we think this should be deleted Exploratory Data Analysis Resource that provides access to software, applications, or toolkits that performs exploratory data analysis methods. - + @@ -2232,7 +2231,7 @@ we think this should be deleted A facility core devoted to creating, manufacturing, building or assembling resources used in scientific research. Fabrication Facility - + @@ -2245,7 +2244,7 @@ we think this should be deleted Facility Core pending final vetting: suggest to re-name to Core Facility, discuss how to manage change. - + @@ -2256,7 +2255,7 @@ we think this should be deleted Faraday Cage pending final vetting: work with eagle-i to define terms since out of scope of BRO - + @@ -2267,7 +2266,7 @@ we think this should be deleted Fast Fourier Transform Resource that provides access to tools or functions that compute the discrete Fourier transform (DFT) and its inverse. - + @@ -2277,7 +2276,7 @@ we think this should be deleted Feature Analysis Resource that provides access to methods for automated analysis of object features and quantitative characterization of data. - + @@ -2287,7 +2286,7 @@ we think this should be deleted Feature Request Resource that provides access to software, application, or toolkit that enable interactive web-based tool that has functionality to collect a request for new features for a specified tool. - + @@ -2297,7 +2296,7 @@ we think this should be deleted A funding resource where money is obtained from the central government. Federal Funding Resource - + @@ -2307,7 +2306,7 @@ we think this should be deleted Filtering Resource that provides access to software, applications, or toolkits that perform alter the spatial-temporal spectral content of data. - + @@ -2317,7 +2316,7 @@ we think this should be deleted Finite Element Model Resource that provides access to software, applications, or toolkits that can be used to generate approximate solutions of partial differential equations. - + @@ -2327,7 +2326,7 @@ we think this should be deleted A resource that provides access to structured data that is found in separate, unlinked files that is accessible via the internet. Flatfile Distribution - + @@ -2338,7 +2337,7 @@ we think this should be deleted Flow Cytometry Cell Sorting Facility pending final vetting: consider changing name to Flow Cytometry Facility - + @@ -2351,7 +2350,7 @@ we think this should be deleted true - + @@ -2361,7 +2360,7 @@ we think this should be deleted Fourier Transform Resource that provides access to software, applications, or toolkits that performs Multi-dimensional Fourier transform - + @@ -2374,7 +2373,7 @@ we think this should be deleted true - + @@ -2388,7 +2387,7 @@ we think this should be deleted http://bioportal.bioontology.org/ontologies/umls/sty/T028 pending final vetting: are more subclasses needed, e.g. Foreign_Funding_Resource and Local_Funding_Resource - + @@ -2398,7 +2397,7 @@ we think this should be deleted A resource that provides data on the abundance of RNA that is coded from genes. Gene Expression - + @@ -2408,7 +2407,7 @@ we think this should be deleted A facility or core for generating recombinant vectors containing a functioning copy of a human gene. Gene Therapy Facility - + @@ -2420,7 +2419,7 @@ we think this should be deleted Genomic Phenotypic Analysis - + @@ -2431,7 +2430,7 @@ we think this should be deleted Genomics Facility pending final vetting: Refine definition - + @@ -2441,7 +2440,7 @@ we think this should be deleted A resource the provides access to a publicly available document that is generated by a governing entity. Government Publication - + @@ -2452,7 +2451,7 @@ we think this should be deleted Grant Preparation Expertise pending final vetting: refine definition - + @@ -2462,7 +2461,7 @@ we think this should be deleted Graph Algorithm Resource that provides access to methods of analysis or generation of networks and graph data structures. - + @@ -2472,7 +2471,7 @@ we think this should be deleted Graph Alignment Resource that provides access to a graph algorithm that compares the similarity of graphs to each other. - + @@ -2482,7 +2481,7 @@ we think this should be deleted Graph Analysis Resource that provides access to software, applications, or toolkit that analyze biological graphs. - + @@ -2492,7 +2491,7 @@ we think this should be deleted Graph Viewer Resource that provides access to general graph visualization methods. - + @@ -2505,7 +2504,7 @@ we think this should be deleted true - + @@ -2515,7 +2514,7 @@ we think this should be deleted Graphical Composition Resource that provides access to software, application, or toolkit that enable graphical composition of applications. - + @@ -2525,7 +2524,7 @@ we think this should be deleted Graphical Integration Resource that provides access to software, application, or toolkit that enables software or application integration using graphical methods. - + @@ -2536,7 +2535,7 @@ we think this should be deleted Resource that provides access to software, applications, or toolkits that enable integration and interoperability tools that facilitate communication between software tools via graphical workflow pipelines. pending final vetting: review definition - + @@ -2546,7 +2545,7 @@ we think this should be deleted A resource that provides a combination of computational resources from multiple administrative domains, applied to a common task. Grid Computing - + @@ -2556,7 +2555,7 @@ we think this should be deleted Heat Map Resource that provides access to an interactive visualization tool that represents variables in a 2-D graph as colors. - + @@ -2569,7 +2568,7 @@ we think this should be deleted true - + @@ -2579,7 +2578,7 @@ we think this should be deleted Hierarchical Tree Resource that provides access to viewers of directed, acyclic tree-structures. - + @@ -2592,7 +2591,7 @@ we think this should be deleted true - + @@ -2602,7 +2601,7 @@ we think this should be deleted Homology Modeling Resource that provides access to software, applications, or toolkits that uses a proteins amino acid sequence and an experimental three-dimensional structure of a related homologous protein to generate an atomic-resolution model of the protein. - + @@ -2612,7 +2611,7 @@ we think this should be deleted A resource that provides a server for data or programs that another computer can access by means of a network. Hosting - + @@ -2622,7 +2621,7 @@ we think this should be deleted A resource that provides guidance and information regarding the use of embryos or human embryonic stem cells in research. Human Embryonic Stem Cell Resource - + @@ -2632,7 +2631,7 @@ we think this should be deleted A resource that provides guidelines and information related to research involving humans with the aim to protect the rights and welfare of research subjects. Such resources could supply consent forms, patient questionnaires, assist in ethical protocol designs, host seminars on conducting human studies, etc. Human Studies Compliance Resource - + @@ -2642,7 +2641,7 @@ we think this should be deleted Hyperbolic Graph Resource that provides access to hyperbolic space (hierarchical) graph/tree visualization tools. - + @@ -2652,7 +2651,7 @@ we think this should be deleted Hypothesis Testing Algorithm Resource that provides access to tools or functions for testing statistical hypothesis against data. - + @@ -2662,7 +2661,7 @@ we think this should be deleted A resource that provides software which maintains the identity of a software user with their software account. Identity Management - + @@ -2673,7 +2672,7 @@ we think this should be deleted Image pending final vetting: review location in hierarchy - + @@ -2683,7 +2682,7 @@ we think this should be deleted Image Algorithm Resource that provides access to methods basic numerical analysis or other canonical computational methods that act on 1, 2, 3 or 4 dimensional images. - + @@ -2694,7 +2693,7 @@ we think this should be deleted Resource that provides access to software, applications, or toolkits that performs image post processing (i.e., excludes image generation). pending final vetting: review location in hierarchy - + @@ -2704,7 +2703,7 @@ we think this should be deleted A resource that provides access to tools or function that are used to reconstruct 2D and 3D images based on projections of an object. Image Reconstruction - + @@ -2715,7 +2714,7 @@ we think this should be deleted Resource that provides access to software, application, or toolkit that enable visualization methods for imaging data. pending final vetting: rename this Imaging_Software (at least as it occurs in Software tree)? - + @@ -2725,7 +2724,7 @@ we think this should be deleted A facility or core for biomedical imaging. Imaging Facility - + @@ -2735,7 +2734,7 @@ we think this should be deleted A facility or core devoted to assessing effects on the human immune system (immunogenicity, immunocompetence, immune reconstitution, immunotoxicity, and immunopathology) of particular importance in the study of disease and therapeutics. Immune Monitoring Facility - + @@ -2745,7 +2744,7 @@ we think this should be deleted A facility or core devoted to localizing antigens (eg. proteins) in cells of a tissue section through antibodies binding specifically to antigens. Immunohistochemistry Facility - + @@ -2755,7 +2754,7 @@ we think this should be deleted A resource that provides clinical care data at the level of an individual. Individual Human Data - + @@ -2766,7 +2765,7 @@ we think this should be deleted Industry Partnership Expertise pending final vetting: refine definition - + @@ -2776,7 +2775,7 @@ we think this should be deleted Inference From Data Resource that provides access to software, applications, or toolkits, that generate a conclusion or finding based on applying logics and statistics to observations/hypothesis. - + @@ -2788,7 +2787,7 @@ we think this should be deleted Information Resource hasDbXref0000001 - + @@ -2798,7 +2797,7 @@ we think this should be deleted Information Retrieval Resource that provides access to software, applications, or toolkits that searches documents for information within the document and metadata about the document. - + @@ -2808,7 +2807,7 @@ we think this should be deleted Inhomogeneity Correction Resource that provides access to software, applications, or toolkits that performs methods for correction of image intensities where non-biological and non-physiological drift or noise is introduced by the scanning hardware. - + @@ -2819,7 +2818,7 @@ we think this should be deleted Instrument pending final vetting: review scope of BRO for child terms - + @@ -2829,7 +2828,7 @@ we think this should be deleted A resource that provides the manufacture of a piece of hardware. An example is producing a made to order microarray chip. Instrument Manufacture - + @@ -2840,7 +2839,7 @@ we think this should be deleted Integrated Hosting pending final vetting: refine definition - + @@ -2850,7 +2849,7 @@ we think this should be deleted Integration Resource that provides access to software, application, or toolkit that enables a software development tool that combines software documentation with generating source code. - + @@ -2860,7 +2859,7 @@ we think this should be deleted A resource that provides access to software or application that is used to enable (i) interoperability and association of data and/or (ii) pipeline of online tools. Integration and Interoperability Tool - + @@ -2873,7 +2872,7 @@ we think this should be deleted true - + @@ -2883,7 +2882,7 @@ we think this should be deleted A resource that provides legal counsel regarding contracts and agreements between an institution and various external parties. These resources may provide legal seminars along with training materials regarding intellectual property. Intellectual Property Resource - + @@ -2893,7 +2892,7 @@ we think this should be deleted Interaction Modeling Resource that provides access to software, applications, or toolkits that model or simulate interaction between biological components such as genes, proteins, cells, organs, populations. - + @@ -2903,7 +2902,7 @@ we think this should be deleted A resource that provides a network model that includes nodes and edges based on physical interactions between the entities represented by the nodes. Interaction Network - + @@ -2913,7 +2912,7 @@ we think this should be deleted Interactive Network Analysis Resource that provides access to software, application, or toolkit that analyze networks interactively with a user. - + @@ -2923,7 +2922,7 @@ we think this should be deleted Interactive Tool Resource that provides access to software, applications, or toolkits that are used to enable user input of data and display corresponding information. - + @@ -2935,7 +2934,7 @@ we think this should be deleted true - + @@ -2945,7 +2944,7 @@ we think this should be deleted Interactive Web-Based Tool Resource that provides access to software, application, or toolkit that enables hands-on resources for data management (entry, query, traversal, comparison, etc.) - + @@ -2955,7 +2954,7 @@ we think this should be deleted A resource that provides access to reports that are published journals Journal Article - + @@ -2968,7 +2967,7 @@ we think this should be deleted true - + @@ -2978,7 +2977,7 @@ we think this should be deleted Knowledge Extraction Resource that provides access to software, applications, or toolkits that recognize and report on entities and relations in text corpora. - + @@ -2989,7 +2988,7 @@ we think this should be deleted Knowledge Mining and Capturing Resource that provides access to software, applications, or toolkits that are used to extract hidden patterns from data. - + @@ -2999,7 +2998,7 @@ we think this should be deleted A resource that provides access to facts and/or information, often in the form of rules that describe the knowledge in a logically consistent manner. Knowledgebase - + @@ -3009,7 +3008,7 @@ we think this should be deleted A resource that provides items such as reagents, instruments, tissue samples or organisms for use in a laboratory. Laboratory Supply Resource - + @@ -3019,7 +3018,7 @@ we think this should be deleted Language Summarization Resource that provides access to applications, libraries, or software that creates a shortened version of text. - + @@ -3029,7 +3028,7 @@ we think this should be deleted Lexical Analysis Resource that provides access to applications, libraries, or software that converts a sequence of characters into a sequence of tokens. - + @@ -3039,7 +3038,7 @@ we think this should be deleted A resource that provides access to documented permission to do something, either from a government or under a law or regulation. License - + @@ -3052,7 +3051,7 @@ we think this should be deleted true - + @@ -3065,7 +3064,7 @@ we think this should be deleted true - + @@ -3076,7 +3075,7 @@ we think this should be deleted Light Microscope pending final vetting: work with eagle-i to define terms since out of scope of BRO - + @@ -3086,7 +3085,7 @@ we think this should be deleted A resource which provides access to tools or functions that compute linear calculations on vector spaces. Linear Algebra Tool - + @@ -3098,7 +3097,7 @@ we think this should be deleted true - + @@ -3110,7 +3109,7 @@ we think this should be deleted MRI Scanner pending final vetting: location in hierarchy and harmonize with OBI/eagle-i - + @@ -3120,7 +3119,7 @@ we think this should be deleted Mailing List Resource that provides access to software, application, or toolkit that enable interactive Web-based tool that can be used to send information to groups. - + @@ -3130,7 +3129,7 @@ we think this should be deleted Manifold Viewer Resource that provides access to general (hyper)volume visualization tools (e.g., volume rendering). - + @@ -3143,7 +3142,7 @@ we think this should be deleted true - + @@ -3153,7 +3152,7 @@ we think this should be deleted Mapper Resource that provides access to software, application, or toolkit that enables application integration using mapping. - + @@ -3163,7 +3162,7 @@ we think this should be deleted Mass Spectra Identification Resource that provides access to software, applications, or toolkits that calculates mass spectra sequence and related data from experimental mass spectra data. - + @@ -3174,7 +3173,7 @@ we think this should be deleted Mass Spectrometer pending final vetting: work with eagle-i to define terms since out of scope of BRO - + @@ -3184,7 +3183,7 @@ we think this should be deleted A resource that provides data from any material sample that was given to the service provider. This can also be a service which performs an experiment such as electrophysiological examination of LTP magnitude in the presence of a drug given to the service provider. Viewing this as an input/output relationship the input would involve a drug and the output would be data such as a dose response curve. Material Analysis Service - + @@ -3196,7 +3195,7 @@ we think this should be deleted BRO:0000001 Material Resource - + @@ -3206,7 +3205,7 @@ we think this should be deleted A resource that provides a service the output of which is a material object. That material object might be an instrument, a chemical, or an animal. Material Service - + @@ -3216,7 +3215,7 @@ we think this should be deleted A resource that provides material storage, maintenance and retrieval, such as the Harvard brain tissue bank. Material Storage Service - + @@ -3229,7 +3228,7 @@ we think this should be deleted true - + @@ -3239,7 +3238,7 @@ we think this should be deleted Mechanical Simulation Resource that provides access to software, applications, or toolkits that model mechanical forces. - + @@ -3249,7 +3248,7 @@ we think this should be deleted A resource that provides devices used for therapy, diagnosis or surgery. Medical Device - + @@ -3259,7 +3258,7 @@ we think this should be deleted Mesh Model Resource that provides access to software, applications, or toolkits that model or simulate biological processes using computational meshes. - + @@ -3269,7 +3268,7 @@ we think this should be deleted Meshing Resource that provides access to software, applications, or toolkits that create meshes in biological systems. - + @@ -3280,7 +3279,7 @@ we think this should be deleted Metabolism Facility pending final vetting: Refine definition - + @@ -3291,7 +3290,7 @@ we think this should be deleted Metabolomics Facility pending final vetting: Refine definition - + @@ -3301,7 +3300,7 @@ we think this should be deleted A facility or core devoted to cutting apart tissue on a very small scale such as at the level of individual cells. Micro Dissection Facility - + @@ -3312,7 +3311,7 @@ we think this should be deleted Microarray Scanner pending final vetting: work with eagle-i to define terms since out of scope of BRO - + @@ -3323,7 +3322,7 @@ we think this should be deleted Micromanipulator pending final vetting: work with eagle-i to define terms since out of scope of BRO - + @@ -3334,7 +3333,7 @@ we think this should be deleted Microscope pending final vetting: work with eagle-i to define terms since out of scope of BRO - + @@ -3344,7 +3343,7 @@ we think this should be deleted A facility that provides microscopes with which to view samples or objects. Microscopy Facility - + @@ -3355,7 +3354,7 @@ we think this should be deleted Microtome pending final vetting: work with eagle-i to define terms since out of scope of BRO - + @@ -3365,7 +3364,7 @@ we think this should be deleted A resource that provides tools or functions that aligns data with a model of the data. Model Fitting Algorithm - + @@ -3377,7 +3376,7 @@ we think this should be deleted Resource that provides access to software, applications, or toolkits that calculate solutions to models with closed form. pending final vetting: review location in hierarchy - + @@ -3387,7 +3386,7 @@ we think this should be deleted Modeling and Simulation Resource that provides access to software, applications, or toolkits that is used to model or simulate biological structures, kinetics, function, structure, random events, and genotype or phenotype in time and space. - + @@ -3400,7 +3399,7 @@ we think this should be deleted true - + @@ -3411,7 +3410,7 @@ we think this should be deleted Molecular Biology Facility pending final vetting: Refine definition - + @@ -3421,7 +3420,7 @@ we think this should be deleted Molecular Dynamics Resource that provides access to software, applications, or toolkits that involves atoms and molecules are allowed to interact for a period of time by approximations of known physics. - + @@ -3431,7 +3430,7 @@ we think this should be deleted Molecular Force Field Calculator Resource that provides access to software, applications, or toolkits that calculate molecular forces in a biomolecular system. - + @@ -3441,7 +3440,7 @@ we think this should be deleted A resource that provides data related to the measurement of interaction between molecules of any type. In version 3.2. Molecular Interaction. In version 3.2. - + @@ -3451,7 +3450,7 @@ we think this should be deleted Molecular Model Resource that provides access to software, applications, or toolkits that calculate time course of physico-chemical model that representation of a molecule or of the arrangement of molecules in a solid substance, with the purpose of visualizing some of its properties, such as the nature and relative positions of its atoms, the chemical bonds between them, the three-dimensional shape of the molecule, and how its shape can change by bending or rotation of the bonds. - + @@ -3462,7 +3461,7 @@ we think this should be deleted Resource that provides access to software, applications, or toolkits that calculate the time course of biomolecular configurations and their classification. pending final vetting: review definition - + @@ -3475,7 +3474,7 @@ we think this should be deleted true - + @@ -3488,7 +3487,7 @@ we think this should be deleted true - + @@ -3498,7 +3497,7 @@ we think this should be deleted Molecular Visualization Resource that provides access to software, applications, or toolkits that can be used to visualize a configuration of biomolecules in space and time. - + @@ -3508,7 +3507,7 @@ we think this should be deleted A resource that provides data related to molecular and cellular properties and their relationship to macroscopic parameters. Molecular and Cellular Data - + @@ -3519,7 +3518,7 @@ we think this should be deleted Monoclonal Antibody Facility pending final vetting: Refine definition - + @@ -3529,7 +3528,7 @@ we think this should be deleted A resource that provides access to tools or functions that model biological processes that involves random sampling in the algorithm. Monte Carlo Simulation - + @@ -3539,7 +3538,7 @@ we think this should be deleted Multibody Dynamics Resource that provides access to software, applications, or toolkits that can be used to calculate the time course of multibody dynamics. - + @@ -3550,7 +3549,7 @@ we think this should be deleted NMR Facility pending final vetting: Refine definition - + @@ -3561,7 +3560,7 @@ we think this should be deleted NMR Instrument pending final vetting: work with eagle-i to define terms since out of scope of BRO - + @@ -3571,7 +3570,7 @@ we think this should be deleted Named Entity Normalization Resource that provides access to applications, libraries, or software that map the recognized entities to unambiguous references to real world entities. - + @@ -3581,7 +3580,7 @@ we think this should be deleted Named Entity Recognition Resource that provides access to applications, libraries, or software that attempts to identify and classify atomic elements in text into predefined categories such as the organizations, locations, expressions of times, quantities, and names of people. - + @@ -3592,7 +3591,7 @@ we think this should be deleted Narrative Resource Work with NIF to define blog and wiki. - + @@ -3602,7 +3601,7 @@ we think this should be deleted A resource that provides access to software, library, or application that interprets human (natural) language into a machine-interpretable form. Natural Language Processing - + @@ -3612,7 +3611,7 @@ we think this should be deleted Network Characterization Resource that provides access to tools or functions that describe a connectivity between components at the genomic, molecular, cellular, tissue level, or population levels. - + @@ -3625,7 +3624,7 @@ we think this should be deleted true - + @@ -3635,7 +3634,7 @@ we think this should be deleted Network Interaction Model Resource that provides access to software, applications, or toolkits that can be used model a molecular, cellular, organ, or population network. - + @@ -3652,7 +3651,7 @@ we think this should be deleted e.g. Sage Bionetworks will be publishing exactly these types of models. - + @@ -3662,7 +3661,7 @@ e.g. Sage Bionetworks will be publishing exactly these types of models.A resource that provides access to or support for a system of interconnected computers able to share information. Network and Communication - + @@ -3675,7 +3674,7 @@ e.g. Sage Bionetworks will be publishing exactly these types of models.true - + @@ -3686,7 +3685,7 @@ e.g. Sage Bionetworks will be publishing exactly these types of models.Neurological Facility pending final vetting: Refine definition - + @@ -3696,7 +3695,7 @@ e.g. Sage Bionetworks will be publishing exactly these types of models.Neuromuscular Model Resource that provides access to software, applications, or toolkits that can be used to model combined biomechanical and neurological system. - + @@ -3706,7 +3705,7 @@ e.g. Sage Bionetworks will be publishing exactly these types of models.News Resource that provides news and RSS feed resources - + @@ -3717,7 +3716,7 @@ e.g. Sage Bionetworks will be publishing exactly these types of models.Next generation of High throughput DNA sequencer (http://en.wikipedia.org/wiki/DNA_sequencing) pending final vetting: work with eagle-i to define terms since out of scope of BRO - + @@ -3730,7 +3729,7 @@ e.g. Sage Bionetworks will be publishing exactly these types of models.true - + @@ -3743,7 +3742,7 @@ e.g. Sage Bionetworks will be publishing exactly these types of models.true - + @@ -3753,7 +3752,7 @@ e.g. Sage Bionetworks will be publishing exactly these types of models.Numerical Calculation of Electrostatic Potential Resource that provides access to software, applications, or toolkits that can be used to calculate the electrostatic potential of biomolecular configurations. - + @@ -3763,7 +3762,7 @@ e.g. Sage Bionetworks will be publishing exactly these types of models.Numerical Integrator Resource that provides access to tools or functions that calculate the numerical value of a definite integral. - + @@ -3775,7 +3774,7 @@ e.g. Sage Bionetworks will be publishing exactly these types of models.true - + @@ -3785,7 +3784,7 @@ e.g. Sage Bionetworks will be publishing exactly these types of models.Numerical Method Resource that provides access to methods of numerical analysis or computational tools (ala, GAMS: http://gams.nist.gov/). - + @@ -3798,7 +3797,7 @@ e.g. Sage Bionetworks will be publishing exactly these types of models.true - + @@ -3808,7 +3807,7 @@ e.g. Sage Bionetworks will be publishing exactly these types of models.Numerical Model Resource that provides access to software, applications, or toolkits that generate solutions from a numerical model. - + @@ -3819,7 +3818,7 @@ e.g. Sage Bionetworks will be publishing exactly these types of models.Nutrition Facility pending final vetting: Refine definition - + @@ -3829,7 +3828,7 @@ e.g. Sage Bionetworks will be publishing exactly these types of models.A resource that provides access to a database that represents information in the form of objects. Object Database - + @@ -3839,7 +3838,7 @@ e.g. Sage Bionetworks will be publishing exactly these types of models.Online Course Resource that provides online training and educational resources. - + @@ -3849,7 +3848,7 @@ e.g. Sage Bionetworks will be publishing exactly these types of models.Online Support Resource that provides access to software, application, or toolkit that enable help via internet accessible material. - + @@ -3859,7 +3858,7 @@ e.g. Sage Bionetworks will be publishing exactly these types of models.A resource that provides access to a set of concepts within a domain and the relationships between those concepts, used to reason about the objects within that domain. Ontology - + @@ -3869,7 +3868,7 @@ e.g. Sage Bionetworks will be publishing exactly these types of models.Ontology Development Resource that provides access to ontology and development management tool that allows a user to develop a set of terms, and the hierarchial relationship between them as well as metadata about the terms. - + @@ -3879,7 +3878,7 @@ e.g. Sage Bionetworks will be publishing exactly these types of models.Ontology Development and Management Resource that provides access to software development tool that can be used to build a set of terms and specify the relationship between the terms. - + @@ -3889,7 +3888,7 @@ e.g. Sage Bionetworks will be publishing exactly these types of models.Ontology Diff and Alignment Resource that provides access to an ontology and development management tool that identifies differences between two ontologies. - + @@ -3899,7 +3898,7 @@ e.g. Sage Bionetworks will be publishing exactly these types of models.Ontology Visualization Resource that provides access to a ontology development and management tool that is used to generate an image of the ontology. - + @@ -3909,7 +3908,7 @@ e.g. Sage Bionetworks will be publishing exactly these types of models.A resource that provides access to a tool or function that locates the extremum (usually minimum) of a cost function subject to constraints., Optimizer - + @@ -3920,7 +3919,7 @@ e.g. Sage Bionetworks will be publishing exactly these types of models.Oscillograph pending final vetting: work with eagle-i to define terms since out of scope of BRO - + @@ -3931,7 +3930,7 @@ e.g. Sage Bionetworks will be publishing exactly these types of models.Oscilloscope pending final vetting: work with eagle-i to define terms since out of scope of BRO - + @@ -3941,7 +3940,7 @@ e.g. Sage Bionetworks will be publishing exactly these types of models.Outlier Detection and Removal Resource that provides access to software, applications, or toolkits that perform quality assurance on data to detect and/or remove outliers. - + @@ -3951,7 +3950,7 @@ e.g. Sage Bionetworks will be publishing exactly these types of models.A resource that provides general education to the public. Outreach Program - + @@ -3962,7 +3961,7 @@ e.g. Sage Bionetworks will be publishing exactly these types of models.PCR Facility pending final vetting: Refine definition - + @@ -3973,7 +3972,7 @@ e.g. Sage Bionetworks will be publishing exactly these types of models.PCR Instrument pending final vetting: work with eagle-i to define terms since out of scope of BRO - + @@ -3983,7 +3982,7 @@ e.g. Sage Bionetworks will be publishing exactly these types of models.A resource that provides access to a tool or function that generates the solution of a partial differential equation subject to appropriate parameters and initial or boundary conditions. PDE Solver - + @@ -3996,7 +3995,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ PET Scanner pending final vetting: location in hierarchy and harmonize with OBI/eagle-i - + @@ -4006,7 +4005,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ An unpublished document, which may also be submitted to a publisher for publication. Paper - + @@ -4016,7 +4015,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ Parsing Resource that provides access to applications, libraries, or software that analyze text to detect language constructs or tokens such as noun phrases and verbs. - + @@ -4026,7 +4025,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ Partial Parsing Resource that provides access to applications, libraries, or software that parse part of a text or corpus. - + @@ -4039,7 +4038,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ true - + @@ -4049,7 +4048,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ A resource that provides access to documents describing the exclusive right granted by a government to an inventor to manufacture, use, or sell an invention for a certain number of years. Patent - + @@ -4059,7 +4058,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ A resource that provides the analysis of biological samples. An example is genotyping transgenic mice. Pathology Laboratory Screening - + @@ -4069,7 +4068,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ A resource that provides access to tools or functions that derive reduced significant information about experimental or synthetic data. Pattern Inference Algorithm - + @@ -4079,7 +4078,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ Pattern Recognition Resource that provides access to tools for the representation, modeling, analysis and visualization of biological patterns out of data. - + @@ -4089,7 +4088,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ Pattern and Motif Inference Resource that provides access to software, applications, or toolkits that generate patterns or motifs based on applying logics and statistics to observations/hypothesis. - + @@ -4101,20 +4100,20 @@ radionuclide (tracer), which is introduced into the body on a biologically activ BRO:0000002 I spent some time thinking about the distinction between People Resources and Services Resources. Then I spent some time thinking of what would be subclasses of people. Below is the list I came up with. However, it bares striking similarity to what we had envisioned for Related Activity or Area of Research. Looking over at NIF, they defined People Resource as "A resource that provides access to individual people based, for example, on expertise or affiliation" and do not have any child nodes. I think I've come around to the opinion that we should either adopt NIF's approach, or change from having the top level People Resource to Consulting Resource as a child of Service Resource. (then still tbd whether to have children of that- I think I'd vote for not.) Note that we're already not in complete alignment at the top level- NIF has "Job Resource". I look forward to discussion with the group. -- grant prep  -- business development    +- grant prep +- business development - industry partnership -- toxicology  -- funding discovery  -- legal counsel  -- intellectual property  -- IRB  -- community outreach  -- finance  -- regulatory compliance  -- minority health  -- study design    -- clinical trials   +- toxicology +- funding discovery +- legal counsel +- intellectual property +- IRB +- community outreach +- finance +- regulatory compliance +- minority health +- study design +- clinical trials - basic research - Informatics - Biostatistics @@ -4122,7 +4121,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ - development People Resource - + @@ -4132,7 +4131,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ A resource that provides access to a communication between an agent and one or more specific recipients., Personal Communication - + @@ -4143,7 +4142,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ Pharmacokinetics Pharmacodynamics Expertise pending final vetting: refine definition - + @@ -4154,7 +4153,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ Resource that provides access to applications, libraries, or software that perform inference and information retrieval on biological phenotype data. pending final vetting: review location in hierarchy - + @@ -4164,7 +4163,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ A resource that provides data related to any kind of measurement designed to describe an observable characteristic or trait. Phenotypic Measurement - + @@ -4174,7 +4173,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ A facility or core devoted to the act or practice of opening a vein by incision or puncture to remove blood. Phlebotomy Facility - + @@ -4184,7 +4183,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ Physico-Chemical Model Resource that provides access to software, applications, or toolkits that calculate solutions to physiological processes that involve chemical kinetics, compartments, or stochastic interactions. - + @@ -4195,7 +4194,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ Physiology Facility pending final vetting: Refine definition - + @@ -4205,7 +4204,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ Physioloigcal Model Resource that provides access to software, applications, or toolkits that can be used model physiology. - + @@ -4215,7 +4214,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ Pipeline Manager Resource that provides access to software, applications, or toolkits that manage software pipelines - + @@ -4228,7 +4227,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ Portal pending final vetting: review NIF hierarchy for source of children terms. - + @@ -4241,7 +4240,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ true - + @@ -4252,7 +4251,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ Power Conditioning Unit pending final vetting: work with eagle-i to define terms since out of scope of BRO - + @@ -4262,7 +4261,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ Pre-Processing Resource that provides access to software, applications, or toolkits that perform image pre-processing routines that are required as preliminary steps before standard image processing, analysis and visualization take place. - + @@ -4272,7 +4271,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ Prediction of Side-Chain Conformations Resource that provides access to software, applications, or toolkits that can be used to calculate the estimate of side chains of conformations in biomolecular configurations. - + @@ -4282,7 +4281,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ Pressure Regulator pending final vetting: work with eagle-i to define terms since out of scope of BRO - + @@ -4292,7 +4291,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ A funding resource where money is supplied by a non governmental organization, foundation, or company. Private Funding Resource - + @@ -4302,7 +4301,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ Processing Pipeline Resource that provides access to software, applications, or toolkits that enable execution processing. - + @@ -4313,7 +4312,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ Programmatic Access pending final vetting: propose to deprecate, but replacement term needed since this term is used in annotation - + @@ -4323,7 +4322,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ A resource that provides a description of the interaction network of proteins. Protein-Protein Interaction - + @@ -4333,7 +4332,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ A resource that provides data related to the presence and abundance of proteins from a cell or tissue sample. Protein Expression - + @@ -4343,7 +4342,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ Protein Interaction Modeling Resource that provides access to software, applications, or toolkits that can be used to model protein interactions. - + @@ -4353,7 +4352,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ Protein Model Resource that provides access to software, applications, or toolkits that can be used to specifically model protein structure and function. - + @@ -4364,7 +4363,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ Proteomics Facility pending final vetting: Refine definition - + @@ -4375,7 +4374,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ Protocol Development Expertise pending final vetting: refine definition - + @@ -4388,7 +4387,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ true - + @@ -4401,7 +4400,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ true - + @@ -4412,7 +4411,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ Psychometrics Expertise pending final vetting: refine definition - + @@ -4425,7 +4424,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ true - + @@ -4435,7 +4434,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ A resource that provides access to structured data that is formatted according to the Resource Description Framework, a language for representing information about resources in the World Wide Web. RDF Data - + @@ -4445,7 +4444,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ RNA Model Resource that provides access to software, applications, or toolkits that can be used to specifically model RNA structure and function., - + @@ -4456,7 +4455,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ Rack pending final vetting: work with eagle-i to define terms since out of scope of BRO - + @@ -4467,7 +4466,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ Radioisotopes Facility pending final vetting: Refine definition - + @@ -4477,7 +4476,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ Random Number Simulation Resource that provides access to software, applications, or toolkits that can be used perform simulations using sampling and re-sampling methods for random events. - + @@ -4487,7 +4486,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ A resource that manufactures a product that could have a role as reagent. Examples include producing antibodies to a particular antigen (Charles River custom antibody service) or designing drugs which fit a receptor. Reagent Manufacture - + @@ -4497,7 +4496,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ A material resource that provides access to reagents, such as antibodies or drugs. Included in this definition are sites designed to work with individual service providers of reagents such as ExactAntigen who do not sell antibodies directly, but provide a catalog with pricing information for most commercial and noncommercial antibody providers. Note, reagents may be of organismal origin or not, but must be classified as macromolecules or molecules. Reagent Resource - + @@ -4507,7 +4506,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ Registration Resource that provides access to software, applications, or toolkits that performs methods for co-registration, alignment and warping of imaging and hyper-imaging data. - + @@ -4517,7 +4516,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ Regularization and Smoothing Resource that provides access to software, applications, or toolkits that smooths time series data. - + @@ -4527,7 +4526,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ A resource that provides guidance related to ethical or legal matters concerning scientific research. These resources provide both information regarding ethical/legal research matters as well as methods for developing, applying, assessing and reviewing regulations (i.e. compliance documents, procedures, consent forms, etc). These resources can include both materials and documentation along with expertise in the form of personnel. Regulatory Compliance Resource - + @@ -4537,7 +4536,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ A resource that provides guidelines for complying with federal, state, and local regulations (e.g. research integrity office, research policy office, etc). The resource can provide seminars, documents, and other items regarding regulations. Regulatory Policy Resource - + @@ -4547,7 +4546,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ PML Resource that provides access to tools or functions that generate network maps of biological signaling or regulatory networks based on applying logic and statistics to observations/hypothesis. Regulatory Signaling Network Reconstruction - + @@ -4557,7 +4556,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ A resource that provides access to a database that comprises a normalized data set constructed according to a specific entity-relation data model. Relational Database - + @@ -4567,7 +4566,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ A resource that provides access to documents describing an account, event, situation, or the like, usually as the result of observation, inquiry, etc. Report - + @@ -4578,7 +4577,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ Research Animals Facility pending final vetting: Refine definition - + @@ -4591,7 +4590,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ true - + @@ -4600,7 +4599,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ An entity that provides access (either in the open community or within an organization) to material, intellectual, financial, technological, or electronic means of carrying out research and development. Resource - + @@ -4610,7 +4609,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ Resource Integration Component Resource that provides access to software, application, or toolkit that enable integration of diverse resources. - + @@ -4621,7 +4620,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ Robotic Arrayer pending final vetting: work with eagle-i to define terms since out of scope of BRO - + @@ -4631,7 +4630,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ A resource that provides access to a tool or function that finds a value x such that f(x) = 0, for a given function f. Such an x is called a root of the function f. Root Finder - + @@ -4644,7 +4643,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ true - + @@ -4657,7 +4656,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ true - + @@ -4667,7 +4666,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ Resource that provides access to software, applications, or toolkits that search, sort, or index on binary or textual formatted data. Searching Sorting and Indexing - + @@ -4677,7 +4676,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ Resource that provides access to software, applications, or toolkits that classify sub-regions of images. Segmentation - + @@ -4690,7 +4689,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ true - + @@ -4700,7 +4699,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ A resource that provides data that is partially structured. Semi-Structured Knowledge Resource - + @@ -4710,7 +4709,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ A resource that provides presentations from experts within their field. Seminar Series - + @@ -4720,7 +4719,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ Resource that provides access to applications, libraries, or software that divide sentences into components or fragments. Sentence Splitting - + @@ -4730,7 +4729,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ Resource that provides access to software, applications, or toolkits that compare two or more genomic sequences and provides summary information. Sequence Alignment - + @@ -4740,7 +4739,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ Resource that provides access to tools or functions that provide information beyond biological sequence, e.g., function. Sequence Annotation - + @@ -4750,7 +4749,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ Resource that provides access to tools or functions that perform similarity searching involving biological sequences. Sequence Similarity Searching - + @@ -4760,7 +4759,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ Resource that provides access to molecular sequence viewers. Sequence Visualization - + @@ -4773,7 +4772,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ true - + @@ -4784,7 +4783,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ As per alignment with NIF resource type hierarchy. Service Resource - + @@ -4794,7 +4793,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ Resource that provides access to tools representation, modeling, analysis and visualization of biological shape out of data. Shape Analysis - + @@ -4805,7 +4804,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ Resource that provides access to software, applications, or toolkits that analysis multi-dimensional spatio-temporal data. Signal Processing - + @@ -4816,7 +4815,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ Resource that provides access to software, applications, or toolkits that generate network maps of biological signaling networks based on applying logic and statistics to observations/hypothesis. Signaling Network Reconstruction - + @@ -4826,7 +4825,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ Resource that provides access to software, applications, or toolkits that methods for removing of segments from images, which have no valuable information about the biological object. For example, removing non-brain tissue from whole-brain MRI scans, for the purpose of doing quantitative evaluations of time or space changing brain anatomy. Skull Stripping - + @@ -4837,7 +4836,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ Resource that provides access usually through repositories or the Internet to computer executables, libraries, plugins, or source code. Software - + @@ -4847,7 +4846,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ A resource that provides the entire environment (applications, servers, network) that provides comprehensive facilities to computer programmers for software development. An SDE typically includes an integrated development environment (IDE, comprising source code editor, compiler, build automation, debugger), requirement management tools, design modeling tools, documentation generation tools, code analysis tools, and so on. Software Development Environment - + @@ -4857,7 +4856,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ Resource that provides access to software, application, or toolkit that enable interactive tools for generating a computer program. Software Development Resource - + @@ -4867,7 +4866,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ Resource that provides access to software, application, or toolkit that enable generic tools for software development, engineering and deployment. Software Development Tool - + @@ -4882,7 +4881,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ true - + @@ -4895,7 +4894,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ true - + @@ -4905,7 +4904,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ Resource that provides access to software, application, or toolkit that enables professional software engineering processes. Software Engineering Tool - + @@ -4915,7 +4914,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ A resource that provides access to information on how to implement and use a computer program. Software Technology Protocol - + @@ -4928,7 +4927,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ - + @@ -4941,7 +4940,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ true - + @@ -4951,7 +4950,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ Resource that provides access to software, application, or toolkit that enable software source control methods. Source Control - + @@ -4961,7 +4960,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ Resource that provides access to software, applications, or toolkits that perform spatial and frequency-type data transformations. Spectral Transform - + @@ -4974,7 +4973,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ true - + @@ -4984,7 +4983,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ A resource that provides access to a generally agreed upon set of rules for representation. Standard Specification - + @@ -4994,7 +4993,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ A funding resource that is provided by a state. State Funding Resource - + @@ -5004,7 +5003,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ Resource that provides access to tools or functions that calculate basic methods of statistics and biometrics. Statistical Algorithm - + @@ -5014,7 +5013,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ A resource that provides access to software, applications, or toolkits for basic statistical modeling and analysis. Statistical Analysis - + @@ -5024,7 +5023,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ A resource that provides access to self-contained tools, resources and packages for statistical modeling and data analysis (e.g., R, SOCR, SAS, SPSS, SYSTAT, etc.). Statistical Package - + @@ -5034,7 +5033,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ Resource that provides access to software, applications, or toolkits that performs statistical tests on text corpora. Statistical Text Analysis - + @@ -5044,7 +5043,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ A facility that provides resources for the development and growth of self-renewing cells that are capable of differentiation into a diverse range of specialized cells. Stem Cell Therapy Facility - + @@ -5055,7 +5054,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ Stimulator pending final vetting: work with eagle-i to define terms since out of scope of BRO - + @@ -5068,7 +5067,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ true - + @@ -5078,7 +5077,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ Resource that provides access to software, applications, or toolkits that can be used to model based on a coordinate-based mathematical description of a collection of biological structures. Structural Model - + @@ -5088,7 +5087,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ Resource that provides access to software, applications, or toolkits that can be used to classify protein shape and parameters. Structure-Based Protein Classification - + @@ -5101,7 +5100,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ true - + @@ -5111,7 +5110,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ A resource that provides access to an electronic document having and manifesting a clearly defined structure or organization that allows it to be executed. Structured File - + @@ -5121,7 +5120,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ A resource that provides access to collection of data records arranged according to some semantic framework. The semantic framework may be minimally expressive - such as a simple controlled vocabulary - or highly expressive such as a formally structured ontology. Such resources may include only a representation of universal/classes/categories or may be linked to individual instance data typed according to a set of asserted classes (i.e., a knowledgebase). Structured Knowledge Resource - + @@ -5134,7 +5133,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ true - + @@ -5147,7 +5146,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ true - + @@ -5157,7 +5156,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ Resource that provides access to methods of analysis and modeling that have closed-form analytical mathematical representations. Symbolic and Analytic Model - + @@ -5169,7 +5168,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ Technical Support pending final vetting: refine definition - + @@ -5180,7 +5179,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ Temperature Control Unit pending final vetting: work with eagle-i to define terms since out of scope of BRO - + @@ -5190,7 +5189,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ Resource that provides access to a software development tool to perform quality assurance of software. Testing Tools - + @@ -5201,7 +5200,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ Resource that provides access to software, applications, or toolkits that derives information from free text. Text Mining - + @@ -5211,7 +5210,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ A resource that provides access to a document created to summarize research findings associated with the completion of an academic degree. Thesis - + @@ -5221,7 +5220,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ A resource that provides image data consisting of length, width and depth. Three D Image - + @@ -5234,7 +5233,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ true - + @@ -5244,7 +5243,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ Resource that provides access to software, applications, or toolkits that includes methods for analyzing time series data in order to extract meaningful statistics and other characteristics of the data. Time Series Analysis - + @@ -5254,7 +5253,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ A facility that provides resources relating to tissues used in biomedical research. Tissue Organ Facility - + @@ -5267,7 +5266,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ true - + @@ -5278,7 +5277,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ Toxicology Expertise pending final vetting: refine definition - + @@ -5289,7 +5288,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ As per alignment with NIF resource type hierarchy. Training Resource - + @@ -5300,7 +5299,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ Training Service pending final vetting: review location in hierarchy - + @@ -5310,7 +5309,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ An educational resource that is interactive and teaches by example. Tutorial - + @@ -5323,7 +5322,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ true - + @@ -5333,7 +5332,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ A resource that provides image data consisting of length and width, but no depth. Two D Image - + @@ -5346,7 +5345,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ true - + @@ -5357,7 +5356,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ Suggested child terms: audio track, slide, and video per NIF. Work with NIF to generate definitions. Unstructured Knowledge Resource - + @@ -5370,7 +5369,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ true - + @@ -5380,7 +5379,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ A resource that provides a system for the management of multiple revisions of the same unit of information. It is most commonly used in engineering and software development to manage ongoing development of digital documents like application source code, art resources such as blueprints or electronic models, and other projects that may be worked on by a team of people. Version Source Control System - + @@ -5391,7 +5390,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ Vibration Isolation Table pending final vetting: work with eagle-i to define terms since out of scope of BRO - + @@ -5402,7 +5401,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ Vibrotome pending final vetting: work with eagle-i to define terms since out of scope of BRO - + @@ -5412,7 +5411,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ Resource that provides access to tools for graphical, interactive, multimodal and multidimensional data and result visualization. Visualization - + @@ -5423,7 +5422,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ Volume Model Scene Data pending final vetting: provide definition - + @@ -5433,7 +5432,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ Resource that provides access to software, applications, or toolkits that can be used model a system using or described by wavelets. Wavelet Model - + @@ -5443,7 +5442,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ Resource that provides access to software, applications, or toolkits that performs multi-dimensional wavelet transform. Wavelet Transform - + @@ -5453,7 +5452,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ Resource that provides access to an ontology development and management tool that can be accessed via the Web. Web Access - + @@ -5463,7 +5462,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ Resources that are disseminated on the Internet via HTTP, FTP and other web protocols. Web Posting - + @@ -5476,7 +5475,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ true - + @@ -5487,7 +5486,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ Resource that provides access to software, application, or toolkit that can develop access to a connected group of pages on the World Wide Web regarded as a single entity, usually maintained by one person or organization and devoted to a single topic or several closely related topics. Website - + @@ -5497,7 +5496,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ A resource that provides space for and access to a web server and content. Website Hosting - + @@ -5507,7 +5506,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ A publication that is an authoritative report or guide that often addresses issues and how to solve them. White Paper - + @@ -5518,7 +5517,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ Resource that provides access to software, applications, or toolkits that can be used to build or manage frameworks that provides sets of interoperable software tools. Workbench - + @@ -5529,7 +5528,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ X-Ray Crystallography Facility pending final vetting: Refine definition - + @@ -5539,7 +5538,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ A resource that provides access to structured data that is in XML, a self-descriptive format to store and transport data. XML Data - + @@ -5549,7 +5548,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ A resource that provides access to a database that stores XML. XML Database - + @@ -5562,7 +5561,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ true - + @@ -5571,7 +5570,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ Area of Research Area of research that may be related to a BRO:Resource. - + @@ -5581,7 +5580,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ As defined in http://en.wikipedia.org/wiki/Behavioral_science Behavioral Science - + @@ -5591,7 +5590,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ As defined in http://en.wikipedia.org/wiki/Bioinformatics Bioinformatics - + @@ -5601,7 +5600,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ As defined in http://en.wikipedia.org/wiki/Biostatistics Biostatistics - + @@ -5611,7 +5610,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ Clinical Studies or resources that help investigators do clinical studies or trials, including, epidemiology (http://en.wikipedia.org/wiki/Epidemiology), outcome development, physiological human studies, interventional trials, etc - + @@ -5621,7 +5620,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ As defined in http://en.wikipedia.org/wiki/Computational_biology Computational Biology - + @@ -5631,7 +5630,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ Former subclasses of area:Area_of_Research that have been deprecated and their usage is not recommended. true - + @@ -5641,7 +5640,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ As defined in http://en.wikipedia.org/wiki/Epidemiolgy Epidemiology - + @@ -5651,7 +5650,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ Genomics The study of all the genes of a cell, tissue, or organism at the DNA (genotype) or mRNA (transcriptome) levels. - + @@ -5661,7 +5660,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ As defined in http://en.wikipedia.org/wiki/Metabolomics Metabolomics - + @@ -5671,7 +5670,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ As defined in http://en.wikipedia.org/wiki/Nursing Nursing - + @@ -5681,7 +5680,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ As defined in http://en.wikipedia.org/wiki/Outcomes_research Outcomes Research - + @@ -5691,7 +5690,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ As defined in http://en.wikipedia.org/wiki/Pathology Pathology - + @@ -5701,7 +5700,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ As defined in http://en.wikipedia.org/wiki/Pediatrics Pediatrics - + @@ -5711,7 +5710,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ As defined in http://en.wikipedia.org/wiki/Pharmacokinetics and http://en.wikipedia.org/wiki/Pharmacodynamics Pharmacokinetics Pharmacodynamics - + @@ -5721,7 +5720,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ As defined in http://en.wikipedia.org/wiki/Physiology Physiology - + @@ -5731,7 +5730,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ Preclinical The stages of biomedical research which take place in model organisms and cell lines, prior to first-in-human application of a diagnostic or therapeutic intervention. - + @@ -5741,7 +5740,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ Proteomics The large-scale study of proteins - + @@ -5751,7 +5750,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ As defined in http://en.wikipedia.org/wiki/Psychometrics Psychometrics - + @@ -5761,7 +5760,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ Framework solutions that enable scientists to work smarter and ultimately increase the number of scientific discoveries made, as well as decrease the time to publish results. (http://en.wikipedia.org/wiki/Information_technology) Research IT - + @@ -5771,7 +5770,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ Toxicology defined in http://en.wikipedia.org/wiki/Toxicology - + @@ -5780,7 +5779,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ Biositemaps Information Model hasDbXref0000000 - + @@ -5789,7 +5788,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ Resource Description - + @@ -5798,16 +5797,16 @@ radionuclide (tracer), which is introduced into the body on a biologically activ Version Information - + - - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -6273,7 +6272,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ - + @@ -6281,7 +6280,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ - + @@ -6289,7 +6288,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ - + @@ -6297,7 +6296,7 @@ radionuclide (tracer), which is introduced into the body on a biologically activ - + @@ -6305,10 +6304,10 @@ radionuclide (tracer), which is introduced into the body on a biologically activ - - - + \ No newline at end of file diff --git a/test/data/ontology_files/CellLine_OWL_BioPortal_v1.0.owl b/test/data/ontology_files/CellLine_OWL_BioPortal_v1.0.owl index 27a0dcb01..317141372 100644 --- a/test/data/ontology_files/CellLine_OWL_BioPortal_v1.0.owl +++ b/test/data/ontology_files/CellLine_OWL_BioPortal_v1.0.owl @@ -763,10 +763,10 @@ http://creativecommons.org/licenses/by/3.0/ - - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -900,31 +900,31 @@ - + - + - + - + - + @@ -932,16 +932,16 @@ - + - - - + - + - + - + - + - - - + @@ -1002,7 +1002,7 @@ Liquid substances produced by living organisms to fulfill specific functions or excreted as waste. - + @@ -1013,7 +1013,7 @@ Liquid components of living organisms. - + @@ -1094,7 +1094,7 @@ The serous fluid of ascites, the accumulation of fluids in the peritoneal cavity. - + @@ -1147,7 +1147,7 @@ Fluid accumulation within the pericardium. Serous effusions are associated with pericardial diseases. Hemopericardium is associated with trauma. Lipid-containing effusion (chylopericardium) results from leakage of thorasic duct. Severe cases can lead to cardiac tamponade. - + @@ -1486,7 +1486,7 @@ Presence of fluid in the pleural cavity resulting from excessive transudation or exudation from the pleural surfaces. It is a sign of disease and not a diagnosis in itself. - + @@ -1496,7 +1496,7 @@ A biomolecule is any organic molecule that is produced by a living organism, including large polymeric molecules such as proteins, polysaccharides, and nucleic acids as well as small molecules such as primary metabolites, secondary metabolites, and natural products. - + @@ -1507,7 +1507,7 @@ A bacterial toxin is a type of toxin that is generated by bacteria. - + @@ -1517,7 +1517,7 @@ >cholera endotoxin - + @@ -1528,7 +1528,7 @@ Chemical substances having a specific regulatory effect on the activity of a certain organ or organs. The term was originally applied to substances secreted by various endocrine glands and transported in the bloodstream to the target organs. It is sometimes extended to include those substances that are not produced by the endocrine glands but that have similar effects. - + @@ -1540,7 +1540,7 @@ Hormones secreted from Adrenal cortex. - + @@ -1549,7 +1549,7 @@ glucocorticoids - + @@ -1561,7 +1561,7 @@ Hormones secreted from Pancreas - + @@ -1572,7 +1572,7 @@ A pancreatic polypeptide of about 110 amino acids, depending on the species, that is the precursor of insulin. Proinsulin, produced by the pancreatic beta cells, is comprised sequentially of the N-terminal B-chain, the proteolytically removable connecting C-peptide, and the C-terminal A-chain. It also contains three disulfide bonds, two between A-chain and B-chain. After cleavage at two locations, insulin and C-peptide are the secreted products. Intact proinsulin with low bioactivity also is secreted in small amounts. - + @@ -1589,7 +1589,7 @@ A 51-amino acid pancreatic hormone that plays a major role in the regulation of glucose metabolism, directly by suppressing endogenous glucose production (glycogenolysis; gluconeogenesis) and indirectly by suppressing glucagon secretion and lipolysis. Native insulin is a globular protein comprised of a zinc-coordinated hexamer. Each insulin monomer containing two chains, A (21 residues) and B (30 residues), linked by two disulfide bonds. Insulin is used as a drug to control insulin-dependent diabetes mellitus (Diabetes mellitus, type 1) - + @@ -1600,7 +1600,7 @@ Linear polypeptides that are synthesized on ribosomes and may be further modified, crosslinked, cleaved, or assembled into complex proteins with several subunits. The specific sequence of amino acids determines the shape the polypeptide will take, during protein folding, and the function of the protein. - + @@ -1675,7 +1675,7 @@ The androgen receptor gene is more than 90 kb long and codes for a protein that has 3 major functional domains: the N-terminal domain, DNA-binding domain, and androgen-binding domain. The protein functions as a steroid-hormone activated transcription factor. Upon binding the hormone ligand, the receptor dissociates from accessory proteins, translocates into the nucleus, dimerizes, and then stimulates transcription of androgen responsive genes. This gene contains 2 polymorphic trinucleotide repeat segments that encode polyglutamine and polyglycine tracts in the N-terminal transactivation domain of its protein. Expansion of the polyglutamine tract causes spinal bulbar muscular atrophy (Kennedy disease). Mutations in this gene are also associated with complete androgen insensitivity (CAIS). Two alternatively spliced variants encoding distinct isoforms have been described. - + @@ -1813,7 +1813,7 @@ This gene encodes a nuclear phosphoprotein that plays a role in maintaining genomic stability, and it also acts as a tumor suppressor. The encoded protein combines with other tumor suppressors, DNA damage sensors, and signal transducers to form a large multi-subunit protein complex known as the BRCA1-associated genome surveillance complex (BASC). This gene product associates with RNA polymerase II, and through the C-terminal domain, also interacts with histone deacetylase complexes. This protein thus plays a role in transcription, DNA repair of double-stranded breaks, and recombination. Mutations in this gene are responsible for approximately 40% of inherited breast cancers and more than 80% of inherited breast and ovarian cancers. Alternative splicing plays a role in modulating the subcellular localization and physiological function of this gene. Many alternatively spliced transcript variants, some of which are disease-associated mutations, have been described for this gene, but the full-length natures of only some of these variants has been described. A related pseudogene, which is also located on chromosome 17, has been identified. - + @@ -1853,7 +1853,7 @@ This gene encodes a high affinity receptor for the peptide hormone calcitonin and belongs to a subfamily of seven transmembrane-spanning G protein-coupled receptors. The encoded protein is involved in maintaining calcium homeostasis and in regulating osteoclast-mediated bone resorption. Polymorphisms in this gene have been associated with variations in bone mineral density and onset of osteoporosis. Alternate splicing results in multiple transcript variants. - + @@ -1910,7 +1910,7 @@ The protein encoded by this gene belongs to the highly conserved cyclin family, whose members are characterized by a dramatic periodicity in protein abundance throughout the cell cycle. Cyclins function as regulators of CDK kinases. Different cyclins exhibit distinct expression and degradation patterns which contribute to the temporal coordination of each mitotic event. This cyclin forms a complex with and functions as a regulatory subunit of CDK4 or CDK6, whose activity is required for cell cycle G1/S transition. This protein has been shown to interact with tumor suppressor protein Rb and the expression of this gene is regulated positively by Rb. Mutations, amplification and overexpression of this gene, which alters cell cycle progression, are observed frequently in a variety of tumors and may contribute to tumorigenesis. - + @@ -2012,7 +2012,7 @@ The protein encoded by this gene is a cell-surface glycoprotein involved in cell-cell interactions, cell adhesion and migration. It is a receptor for hyaluronic acid (HA) and can also interact with other ligands, such as osteopontin, collagens, and matrix metalloproteinases (MMPs). This protein participates in a wide variety of cellular functions including lymphocyte activation, recirculation and homing, hematopoiesis, and tumor metastasis. Transcripts for this gene undergo complex alternative splicing that results in many functionally distinct isoforms, however, the full length nature of some of these variants has not been determined. Alternative splicing is the basis for the structural and functional diversity of this protein, and may be related to tumor metastasis. - + @@ -2027,7 +2027,7 @@ - + @@ -2081,7 +2081,7 @@ - + @@ -2267,7 +2267,7 @@ This gene encodes a muscle-specific class III intermediate filament. Homopolymers of this protein form a stable intracytoplasmic filamentous network connecting myofibrils to each other and to the plasma membrane. Mutations in this gene are associated with desmin-related myopathy, a familial cardiac and skeletal myopathy (CSM), and with distal myopathies. - + @@ -2302,7 +2302,7 @@ Epidermal growth factor has a profound effect on the differentiation of specific cells in vivo and is a potent mitogenic factor for a variety of cultured cells of both ectodermal and mesodermal origin. The EGF precursor is believed to exist as a membrane-bound molecule which is proteolytically cleaved to generate the 53-amino acid peptide hormone that stimulates cells to divide. - + @@ -2413,7 +2413,7 @@ The protein encoded by this gene is a transmembrane glycoprotein that is a member of the protein kinase superfamily. This protein is a receptor for members of the epidermal growth factor family. EGFR is a cell surface protein that binds to epidermal growth factor. Binding of the protein to a ligand induces receptor dimerization and tyrosine autophosphorylation and leads to cell proliferation. Mutations in this gene are associated with lung cancer. - + @@ -2730,7 +2730,7 @@ This gene encodes a carcinoma-associated antigen and is a member of a family that includes at least two type I membrane proteins. This antigen is expressed on most normal epithelial cells and gastrointestinal carcinomas and functions as a homotypic calcium-independent cell adhesion molecule. The antigen is being used as a target for immunotherapy treatment of human carcinomas. Mutations in this gene result in congenital tufting enteropathy. - + @@ -3080,7 +3080,7 @@ This gene encodes a member of the epidermal growth factor (EGF) receptor family of receptor tyrosine kinases. This protein has no ligand binding domain of its own and therefore cannot bind growth factors. However, it does bind tightly to other ligand-bound EGF receptor family members to form a heterodimer, stabilizing ligand binding and enhancing kinase-mediated activation of downstream signalling pathways, such as those involving mitogen-activated protein kinase and phosphatidylinositol-3 kinase. Allelic variations at amino acid positions 654 and 655 of isoform a (positions 624 and 625 of isoform b) have been reported, with the most common allele, Ile654/Ile655, shown here. Amplification and/or overexpression of this gene has been reported in numerous cancers, including breast and ovarian tumors. Alternative splicing results in several additional transcript variants, some encoding different isoforms and others that have not been fully characterized. - + @@ -3180,7 +3180,7 @@ This gene encodes a member of the epidermal growth factor receptor (EGFR) family of receptor tyrosine kinases. This membrane-bound protein has a neuregulin binding domain but not an active kinase domain. It therefore can bind this ligand but not convey the signal into the cell through protein phosphorylation. However, it does form heterodimers with other EGF receptor family members which do have kinase activity. Heterodimerization leads to the activation of pathways which lead to cell proliferation or differentiation. Amplification of this gene and/or overexpression of its protein have been reported in numerous cancers, including prostate, bladder, and breast tumors. Alternate transcriptional splice variants encoding different isoforms have been characterized. One isoform lacks the intermembrane region and is secreted outside the cell. This form acts to modulate the activity of the membrane-bound form. Additional splice variants have also been reported, but they have not been thoroughly characterized. - + @@ -3251,7 +3251,7 @@ This gene is a member of the Tyr protein kinase family and the epidermal growth factor receptor subfamily. It encodes a single-pass type I membrane protein with multiple cysteine rich domains, a transmembrane domain, a tyrosine kinase domain, a phosphotidylinositol-3 kinase binding site and a PDZ domain binding motif. The protein binds to and is activated by neuregulins and other factors and induces a variety of cellular responses including mitogenesis and differentiation. Multiple proteolytic events allow for the release of a cytoplasmic fragment and an extracellular fragment. Mutations in this gene have been associated with cancer. Alternatively spliced variants which encode different protein isoforms have been described; however, not all variants have been fully characterized. - + @@ -3336,7 +3336,7 @@ This gene encodes an estrogen receptor, a ligand-activated transcription factor composed of several domains important for hormone binding, DNA binding, and activation of transcription. The protein localizes to the nucleus where it may form a homodimer or a heterodimer with estrogen receptor 2. Estrogen and its receptors are essential for sexual development and reproductive function, but also play a role in other tissues such as bone. Estrogen receptors are also involved in pathological processes including breast cancer, endometrial cancer, and osteoporosis. Alternative splicing results in several transcript variants, which differ in their 5' UTRs and use different promoters. - + @@ -3775,7 +3775,7 @@ Estrogen receptor is a ligand-activated transcription factor composed of several domains important for hormone binding, DNA binding, and activation of transcription. The protein localizes to the nucleus where it may form a homodimer or a heterodimer with estrogen receptor 2. Estrogen and its receptors are essential for sexual development and reproductive function, but also play a role in other tissues such as bone. Estrogen receptors are also involved in pathological processes including breast cancer, endometrial cancer, and osteoporosis. - + @@ -3871,7 +3871,7 @@ This gene encodes a member of the F-box protein family which is characterized by an approximately 40 amino acid motif, the F-box. The F-box proteins constitute one of the four subunits of ubiquitin protein ligase complex called SCFs (SKP1-cullin-F-box), which function in phosphorylation-dependent ubiquitination. The F-box proteins are divided into 3 classes: Fbws containing WD-40 domains, Fbls containing leucine-rich repeats, and Fbxs containing either different protein-protein interaction modules or no recognizable motifs. The protein encoded by this gene was previously referred to as FBX30, and belongs to the Fbws class; in addition to an F-box, this protein contains 7 tandem WD40 repeats. This protein binds directly to cyclin E and probably targets cyclin E for ubiquitin-mediated degradation. Mutations in this gene are detected in ovarian and breast cancer cell lines, implicating the gene's potential role in the pathogenesis of human cancers. Three transcript variants encoding three different isoforms have been found for this gene. - + @@ -3999,7 +3999,7 @@ The protein encoded by this gene is a member of the fibroblast growth factor receptor (FGFR) family, where amino acid sequence is highly conserved between members and throughout evolution. FGFR family members differ from one another in their ligand affinities and tissue distribution. A full-length representative protein consists of an extracellular region, composed of three immunoglobulin-like domains, a single hydrophobic membrane-spanning segment and a cytoplasmic tyrosine kinase domain. The extracellular portion of the protein interacts with fibroblast growth factors, setting in motion a cascade of downstream signals, ultimately influencing mitogenesis and differentiation. This particular family member binds both acidic and basic fibroblast growth factors and is involved in limb induction. Mutations in this gene have been associated with Pfeiffer syndrome, Jackson-Weiss syndrome, Antley-Bixler syndrome, osteoglophonic dysplasia, and autosomal dominant Kallmann syndrome 2. Chromosomal aberrations involving this gene are associated with stem cell myeloproliferative disorder and stem cell leukemia lymphoma syndrome. Alternatively spliced variants which encode different protein isoforms have been described; however, not all variants have been fully characterized. - + @@ -4115,7 +4115,7 @@ The protein encoded by this gene is a member of the fibroblast growth factor receptor family, where amino acid sequence is highly conserved between members and throughout evolution. FGFR family members differ from one another in their ligand affinities and tissue distribution. A full-length representative protein consists of an extracellular region, composed of three immunoglobulin-like domains, a single hydrophobic membrane-spanning segment and a cytoplasmic tyrosine kinase domain. The extracellular portion of the protein interacts with fibroblast growth factors, setting in motion a cascade of downstream signals, ultimately influencing mitogenesis and differentiation. This particular family member is a high-affinity receptor for acidic, basic and/or keratinocyte growth factor, depending on the isoform. Mutations in this gene are associated with Crouzon syndrome, Pfeiffer syndrome, Craniosynostosis, Apert syndrome, Jackson-Weiss syndrome, Beare-Stevenson cutis gyrata syndrome, Saethre-Chotzen syndrome, and syndromic craniosynostosis. Multiple alternatively spliced transcript variants encoding different isoforms have been noted for this gene. - + @@ -4152,7 +4152,7 @@ The fibroblast growth factor receptors consist of an extracellular ligand domain composed of three immunoglobulin-like domains, a single transmembrane helix domain, and an intracellular domain with tyrosine kinase activity. These receptors bind fibroblast growth factors, members of the largest family of growth factor ligands, comprising 22 members. So far, five distinct membrane FGFR have been identified in vertebrates and all of them belong to the tyrosine kinase superfamily (FGFR1 to FGFR4). - + @@ -4228,7 +4228,7 @@ This gene, a member of the histidine triad gene family, encodes a diadenosine 5',5'''-P1,P3-triphosphate hydrolase involved in purine metabolism. The gene encompasses the common fragile site FRA3B on chromosome 3, where carcinogen-induced damage can lead to translocations and aberrant transcripts of this gene. In fact, aberrant transcripts from this gene have been found in about half of all esophageal, stomach, and colon carcinomas. Alternatively spliced transcript variants have been found for this gene. - + @@ -4386,7 +4386,7 @@ This gene encodes one of the major intermediate filament proteins of mature astrocytes. It is used as a marker to distinguish astrocytes from other glial cells during development. Mutations in this gene cause Alexander disease, a rare disorder of astrocytes in the central nervous system. Alternative splicing results in multiple transcript variants encoding distinct isoforms. - + @@ -4415,7 +4415,7 @@ After removal of the precursor signal peptide, proinsulin is post-translationally cleaved into two chains (peptide A and peptide B) that are covalently linked via two disulfide bonds. Binding of this mature form of insulin to the insulin receptor (INSR) stimulates glucose uptake. A variety of mutant alleles with changes in the coding region have been identified. There is a read-through gene, INS-IGF2, which overlaps with this gene at the 5' region and with the IGF2 gene at the 3' region. - + @@ -4457,7 +4457,7 @@ After removal of the precursor signal peptide, the insulin receptor precursor is post-translationally cleaved into two chains (alpha and beta) that are covalently linked. Binding of insulin to the insulin receptor (INSR) stimulates glucose uptake. Two transcript variants encoding different isoforms have been found for this gene. - + @@ -4506,7 +4506,7 @@ This gene encodes a member of the type I (acidic) cytokeratin family, which belongs to the superfamily of intermediate filament (IF) proteins. Keratins are heteropolymeric structural proteins which form the intermediate filament. These filaments, along with actin microfilaments and microtubules, compose the cytoskeleton of epithelial cells. Mutations in this gene are associated with epidermolytic hyperkeratosis. This gene is located within a cluster of keratin family members on chromosome 17q21. - + @@ -4564,7 +4564,7 @@ The protein encoded by this gene is a member of the keratin gene family. The keratins are intermediate filament proteins responsible for the structural integrity of epithelial cells and are subdivided into cytokeratins and hair keratins. Most of the type I cytokeratins consist of acidic proteins which are arranged in pairs of heterotypic keratin chains. This type I cytokeratin is paired with keratin 4 and expressed in the suprabasal layers of non-cornified stratified epithelia. Mutations in this gene and keratin 4 have been associated with the autosomal dominant disorder White Sponge Nevus. The type I cytokeratins are clustered in a region of chromosome 17q21.2. Alternative splicing of this gene results in multiple transcript variants; however, not all variants have been described. - + @@ -4633,7 +4633,7 @@ This gene encodes a member of the keratin family, the most diverse group of intermediate filaments. This gene product, a type I keratin, is usually found as a heterotetramer with two keratin 5 molecules, a type II keratin. Together they form the cytoskeleton of epithelial cells. Mutations in the genes for these keratins are associated with epidermolysis bullosa simplex. At least one pseudogene has been identified at 17p12-p11. - + @@ -4704,7 +4704,7 @@ The protein encoded by this gene is a member of the keratin gene family. The keratins are intermediate filament proteins responsible for the structural integrity of epithelial cells and are subdivided into cytokeratins and hair keratins. Most of the type I cytokeratins consist of acidic proteins which are arranged in pairs of heterotypic keratin chains and are clustered in a region of chromosome 17q12-q21. This keratin has been coexpressed with keratin 14 in a number of epithelial tissues, including esophagus, tongue, and hair follicles. Mutations in this gene are associated with type 1 pachyonychia congenita, non-epidermolytic palmoplantar keratoderma and unilateral palmoplantar verrucous nevus. - + @@ -4883,7 +4883,7 @@ This gene encodes the type I intermediate filament chain keratin 17, expressed in nail bed, hair follicle, sebaceous glands, and other epidermal appendages. Mutations in this gene lead to Jackson-Lawler type pachyonychia congenita and steatocystoma multiplex. - + @@ -5077,7 +5077,7 @@ KRT18 encodes the type I intermediate filament chain keratin 18. Keratin 18, together with its filament partner keratin 8, are perhaps the most commonly found members of the intermediate filament gene family. They are expressed in single layer epithelial tissues of the body. Mutations in this gene have been linked to cryptogenic cirrhosis. Two transcript variants encoding the same protein have been found for this gene. - + @@ -5259,7 +5259,7 @@ The protein encoded by this gene is a member of the keratin family. The keratins are intermediate filament proteins responsible for the structural integrity of epithelial cells and are subdivided into cytokeratins and hair keratins. The type I cytokeratins consist of acidic proteins which are arranged in pairs of heterotypic keratin chains. Unlike its related family members, this smallest known acidic cytokeratin is not paired with a basic cytokeratin in epithelial cells. It is specifically expressed in the periderm, the transiently superficial layer that envelopes the developing epidermis. The type I cytokeratins are clustered in a region of chromosome 17q12-q21. - + @@ -5317,7 +5317,7 @@ The protein encoded by this gene is a member of the keratin gene family. The type II cytokeratins consist of basic or neutral proteins which are arranged in pairs of heterotypic keratin chains coexpressed during differentiation of simple and stratified epithelial tissues. This type II cytokeratin is specifically expressed in differentiated layers of the mucosal and esophageal epithelia with family member KRT13. Mutations in these genes have been associated with White Sponge Nevus, characterized by oral, esophageal, and anal leukoplakia. The type II cytokeratins are clustered in a region of chromosome 12q12-q13. - + @@ -5534,7 +5534,7 @@ The protein encoded by this gene is a member of the keratin gene family. The type II cytokeratins consist of basic or neutral proteins which are arranged in pairs of heterotypic keratin chains coexpressed during differentiation of simple and stratified epithelial tissues. This type II cytokeratin is specifically expressed in the simple epithelia lining the cavities of the internal organs and in the gland ducts and blood vessels. The genes encoding the type II cytokeratins are clustered in a region of chromosome 12q12-q13. Alternative splicing may result in several transcript variants; however, not all variants have been fully described. - + @@ -5744,7 +5744,7 @@ This gene is a member of the type II keratin family clustered on the long arm of chromosome 12. Type I and type II keratins heteropolymerize to form intermediate-sized filaments in the cytoplasm of epithelial cells. The product of this gene typically dimerizes with keratin 18 to form an intermediate filament in simple single-layered epithelial cells. This protein plays a role in maintaining cellular structural integrity and also functions in signal transduction and cellular differentiation. Mutations in this gene cause cryptogenic cirrhosis. - + @@ -5785,7 +5785,7 @@ The protein encoded by this gene is a member of the keratin gene family. The type II cytokeratins consist of basic or neutral proteins which are arranged in pairs of heterotypic keratin chains coexpressed during differentiation of simple and stratified epithelial tissues. As many as six of this type II cytokeratin (KRT6) have been identified; the multiplicity of the genes is attributed to successive gene duplication events. The genes are expressed with family members KRT16 and/or KRT17 in the filiform papillae of the tongue, the stratified epithelial lining of oral mucosa and esophagus, the outer root sheath of hair follicles, and the glandular epithelia. - + @@ -5916,7 +5916,7 @@ This gene is a member of the mucin family and encodes a membrane bound, glycosylated phosphoprotein. The protein is anchored to the apical surface of many epithelia by a transmembrane domain, with the degree of glycosylation varying with cell type. It also includes a 20 aa variable number tandem repeat (VNTR) domain, with the number of repeats varying from 20 to 120 in different individuals. The protein serves a protective function by binding to pathogens and also functions in a cell signaling capacity. Overexpression, aberrant intracellular localization, and changes in glycosylation of this protein have been associated with carcinomas. Multiple alternatively spliced transcript variants that encode different isoforms of this gene have been reported, but the full-length nature of only some has been determined. - + @@ -5957,7 +5957,7 @@ This gene encodes a member of the mucin protein family. Mucins are high molecular weight glycoproteins produced by many epithelial tissues. The protein encoded by this gene is secreted and forms an insoluble mucous barrier that protects the gut lumen. The protein polymerizes into a gel of which 80% is composed of oligosaccharide side chains by weight. The protein features a central domain containing tandem repeats rich in threonine and proline that varies between 50 and 115 copies in different individuals. Alternatively spliced transcript variants of this gene have been described, but their full-length nature is not known. - + @@ -6017,7 +6017,7 @@ The protein encoded by this gene is a multifunctional, nuclear phosphoprotein that plays a role in cell cycle progression, apoptosis and cellular transformation. It functions as a transcription factor that regulates transcription of specific target genes. Mutations, overexpression, rearrangement and translocation of this gene have been associated with a variety of hematopoietic tumors, leukemias and lymphomas, including Burkitt lymphoma. There is evidence to show that alternative translation initiations from an upstream, in-frame non-AUG (CUG) and a downstream AUG start site result in the production of two isoforms with distinct N-termini. The synthesis of non-AUG initiated protein is suppressed in Burkitt's lymphomas, suggesting its importance in the normal function of this gene. - + @@ -6053,7 +6053,7 @@ The mucin genes encode epithelial glycoproteins, some of which are secreted and some membrane bound. Each of the genes contains at least one large domain of tandemly repeated sequence that encodes the peptide sequence rich in serine and/or threonine residues, which carries most of the O-linked glycosylation. - + @@ -6102,7 +6102,7 @@ Receptor for glucocorticoids (GC). Has a dual mode of action: as a transcription factor that binds to glucocorticoid response elements (GRE) and as a modulator of other transcription factors. Affects inflammatory responses, cellular proliferation and differentiation in target tissues. Could act as a coactivator for STAT5-dependent transcription upon growth hormone (GH) stimulation and could reveal an essential role of hepatic GR in the control of body growth. Involved in chromatin remodeling. Plays a significant role in transactivation. Involved in nuclear translocation. - + @@ -6189,7 +6189,7 @@ The protein encoded by this gene was originally identified as a 44-kD glycoprotein that interacts with the NEU/ERBB2 receptor tyrosine kinase to increase its phosphorylation on tyrosine residues. This protein is a signaling protein that mediates cell-cell interactions and plays critical roles in the growth and development of multiple organ systems. It is known that an extraordinary variety of different isoforms are produced from this gene through alternative promoter usage and splicing. These isoforms are tissue-specifically expressed and differ significantly in their structure, and thereby these isoforms are classified into types I, II, III, IV, V and VI. The gene dysregulation has been linked to diseases such as cancer, schizophrenia and bipolar disorder (BPD). - + @@ -6621,7 +6621,7 @@ This gene encodes a member of the steroid receptor superfamily. The encoded protein mediates the physiological effects of progesterone, which plays a central role in reproductive events associated with the establishment and maintenance of pregnancy. This gene uses two distinct promotors and translation start sites in the first exon to produce two isoforms, A and B. The two isoforms are identical except for the additional 165 amino acids found in the N-terminus of isoform A only, and mediate their own response genes and physiologic effects with little overlap. The location of transcription initiation for isoform B has not been clearly determined. - + @@ -6687,7 +6687,7 @@ This gene was identified as a tumor suppressor that is mutated in a large number of cancers at high frequency. The protein encoded this gene is a phosphatidylinositol-3,4,5-trisphosphate 3-phosphatase. It contains a tensin like domain as well as a catalytic domain similar to that of the dual specificity protein tyrosine phosphatases. Unlike most of the protein tyrosine phosphatases, this protein preferentially dephosphorylates phosphoinositide substrates. It negatively regulates intracellular levels of phosphatidylinositol-3,4,5-trisphosphate in cells and functions as a tumor suppressor by negatively regulating AKT/PKB signaling pathway. - + @@ -6728,7 +6728,7 @@ P-glycoprotein is a well-characterized ABC-transporter of the MDR/TAP subfamily. The membrane-associated protein encoded by this gene is a member of the superfamily of ATP-binding cassette (ABC) transporters. ABC proteins transport various molecules across extra- and intra-cellular membranes. ABC genes are divided into seven distinct subfamilies (ABC1, MDR/TAP, MRP, ALD, OABP, GCN20, White). This protein is a member of the MDR/TAP subfamily. Members of the MDR/TAP subfamily are involved in multidrug resistance. - + @@ -6781,7 +6781,7 @@ This locus may represent a breast cancer candidate gene. It is located close to FGFR1 on a region of chromosome 8 that is amplified in some breast cancers. Three transcript variants encoding different isoforms have been found for this gene. - + @@ -6838,7 +6838,7 @@ This gene encodes a member of the transforming growth factor beta (TGFB) family of cytokines, which are multifunctional peptides that regulate proliferation, differentiation, adhesion, migration, and other functions in many cell types. Many cells have TGFB receptors, and the protein positively and negatively regulates many other growth factors. The secreted protein is cleaved into a latency-associated peptide (LAP) and a mature TGFB1 peptide, and is found in either a latent form composed of a TGFB1 homodimer, a LAP homodimer, and a latent TGFB1-binding protein, or in an active form composed of a TGFB1 homodimer. The mature peptide may also form heterodimers with other TGFB family members. This gene is frequently upregulated in tumor cells, and mutations in this gene result in Camurati-Engelmann disease. - + @@ -6939,7 +6939,7 @@ The protein encoded by this gene forms a heteromeric complex with type II TGF-beta receptors when bound to TGF-beta, transducing the TGF-beta signal from the cell surface to the cytoplasm. The encoded protein is a serine/threonine protein kinase. Mutations in this gene have been associated with Loeys-Dietz aortic aneurysm syndrome (LDAS). Multiple transcript variants encoding different isoforms have been found for this gene. - + @@ -7024,7 +7024,7 @@ This gene encodes a member of the Ser/Thr protein kinase family and the TGFB receptor subfamily. The encoded protein is a transmembrane protein that has a protein kinase domain, forms a heterodimeric complex with another receptor protein, and binds TGF-beta. This receptor/ligand complex phosphorylates proteins, which then enter the nucleus and regulate the transcription of a subset of genes related to cell proliferation. Mutations in this gene have been associated with Marfan Syndrome, Loeys-Deitz Aortic Aneurysm Syndrome, and the development of various types of tumors. Alternatively spliced transcript variants encoding different isoforms have been characterized. - + @@ -7108,7 +7108,7 @@ This gene encodes a multifunctional proinflammatory cytokine that belongs to the tumor necrosis factor (TNF) superfamily. This cytokine is mainly secreted by macrophages. It can bind to, and thus functions through its receptors TNFRSF1A/TNFR1 and TNFRSF1B/TNFBR. This cytokine is involved in the regulation of a wide spectrum of biological processes including cell proliferation, differentiation, apoptosis, lipid metabolism, and coagulation. This cytokine has been implicated in a variety of diseases, including autoimmune diseases, insulin resistance, and cancer. Knockout studies in mice also suggested the neuroprotective function of this cytokine. - + @@ -7422,7 +7422,7 @@ This gene encodes tumor protein p53, which responds to diverse cellular stresses to regulate target genes that induce cell cycle arrest, apoptosis, senescence, DNA repair, or changes in metabolism. p53 protein is expressed at low level in normal cells and at a high level in a variety of transformed cell lines, where it's believed to contribute to transformation and malignancy. p53 is a DNA-binding protein containing transcription activation, DNA-binding, and oligomerization domains. It is postulated to bind to a p53-binding site and activate expression of downstream genes that inhibit growth and/or invasion, and thus function as a tumor suppressor. Mutants of p53 that frequently occur in a number of different human cancers fail to bind the consensus DNA binding site, and hence cause the loss of tumor suppressor activity. Alterations of this gene occur not only as somatic mutations in human malignancies, but also as germline mutations in some cancer-prone families with Li-Fraumeni syndrome. Multiple p53 variants due to alternative promoters and multiple alternative splicing have been found. These variants encode distinct isoforms, which can regulate p53 transcriptional activity. - + @@ -7579,7 +7579,7 @@ This gene encodes a member of the intermediate filament family. Intermediate filamentents, along with microtubules and actin microfilaments, make up the cytoskeleton. The protein encoded by this gene is responsible for maintaining cell shape, integrity of the cytoplasm, and stabilizing cytoskeletal interactions. It is also involved in the immune response, and controls the transport of low-density lipoprotein (LDL)-derived cholesterol from a lysosome to the site of esterification. It functions as an organizer of a number of critical proteins involved in attachment, migration, and cell signaling. Mutations in this gene causes a dominant, pulverulent cataract. - + @@ -7628,7 +7628,7 @@ The WNT gene family consists of structurally related genes which encode secreted signaling proteins. These proteins have been implicated in oncogenesis and in several developmental processes, including regulation of cell fate and patterning during embryogenesis. This gene is a member of the WNT gene family. It encodes a protein which shows 98% amino acid identity to mouse Wnt3 protein, and 84% to human WNT3A protein, another WNT gene product. The mouse studies show the requirement of Wnt3 in primary axis formation in the mouse. Studies of the gene expression suggest that this gene may play a key role in some cases of human breast, rectal, lung, and gastric cancer through activation of the WNT-beta-catenin-TCF signaling pathway. This gene is clustered with WNT15, another family member, in the chromosome 17q21 region. - + @@ -7682,7 +7682,7 @@ The WNT gene family consists of structurally related genes which encode secreted signaling proteins. These proteins have been implicated in oncogenesis and in several developmental processes, including regulation of cell fate and patterning during embryogenesis. This gene is a member of the WNT gene family. It encodes a protein which shows 98%, 98% and 87% amino acid identity to the mouse, rat and the xenopus Wnt5A protein, respectively. The experiments performed in Xenopus laevis embryos identified that human frizzled-5 (hFz5) is the receptor for the Wnt5A ligand and the Wnt5A/hFz5 signaling mediates axis induction. - + @@ -7706,7 +7706,7 @@ This gene is a member of the WNT gene family, which consists of structurally related genes that encode secreted signaling proteins. These proteins have been implicated in oncogenesis and in several developmental processes, including regulation of cell fate and patterning during embryogenesis. Among members of the human WNT family, this gene product is most similar to WNT7A protein. - + @@ -7714,7 +7714,7 @@ cell line - + @@ -7731,7 +7731,7 @@ - + @@ -7741,7 +7741,7 @@ >normal human cell line - + @@ -7756,7 +7756,7 @@ - + @@ -7797,7 +7797,7 @@ - + @@ -7830,7 +7830,7 @@ - + @@ -7865,7 +7865,7 @@ - + @@ -7886,7 +7886,7 @@ - + @@ -7933,7 +7933,7 @@ - + @@ -7948,7 +7948,7 @@ - + @@ -7975,7 +7975,7 @@ - + @@ -8002,7 +8002,7 @@ - + @@ -8029,7 +8029,7 @@ - + @@ -8056,7 +8056,7 @@ - + @@ -8083,7 +8083,7 @@ - + @@ -8122,7 +8122,7 @@ - + @@ -8149,7 +8149,7 @@ - + @@ -8176,7 +8176,7 @@ - + @@ -8203,7 +8203,7 @@ - + @@ -8230,7 +8230,7 @@ - + @@ -8257,7 +8257,7 @@ - + @@ -8284,7 +8284,7 @@ - + @@ -8299,7 +8299,7 @@ - + @@ -8330,7 +8330,7 @@ MCF10A cells (human mammary epithelial cells) stably expressing c-Myc. - + @@ -8405,7 +8405,7 @@ - + @@ -8450,7 +8450,7 @@ - + @@ -8543,7 +8543,7 @@ - + @@ -8636,7 +8636,7 @@ - + @@ -8679,7 +8679,7 @@ Human non cancer breast epithelial cells immortalized by infection with the retrovirus pBabepuro+hTERT vectorline - + @@ -8695,7 +8695,7 @@ - + @@ -8705,7 +8705,7 @@ >pathological human cell line - + @@ -8738,7 +8738,7 @@ - + @@ -8771,7 +8771,7 @@ - + @@ -8840,7 +8840,7 @@ - + @@ -8947,7 +8947,7 @@ - + @@ -8974,7 +8974,7 @@ - + @@ -9063,7 +9063,7 @@ - + @@ -9170,7 +9170,7 @@ - + @@ -9301,7 +9301,7 @@ - + @@ -9354,7 +9354,7 @@ - + @@ -9425,7 +9425,7 @@ - + @@ -9506,7 +9506,7 @@ - + @@ -9593,7 +9593,7 @@ - + @@ -9674,7 +9674,7 @@ - + @@ -9743,7 +9743,7 @@ - + @@ -9814,7 +9814,7 @@ - + @@ -9895,7 +9895,7 @@ - + @@ -9978,7 +9978,7 @@ - + @@ -10059,7 +10059,7 @@ - + @@ -10164,7 +10164,7 @@ - + @@ -10269,7 +10269,7 @@ - + @@ -10374,7 +10374,7 @@ - + @@ -10443,7 +10443,7 @@ - + @@ -10482,7 +10482,7 @@ - + @@ -10503,7 +10503,7 @@ - + @@ -10548,7 +10548,7 @@ - + @@ -10631,7 +10631,7 @@ - + @@ -10750,7 +10750,7 @@ - + @@ -10827,7 +10827,7 @@ - + @@ -10904,7 +10904,7 @@ - + @@ -10981,7 +10981,7 @@ - + @@ -11076,7 +11076,7 @@ - + @@ -11171,7 +11171,7 @@ - + @@ -11284,7 +11284,7 @@ - + @@ -11379,7 +11379,7 @@ - + @@ -11414,7 +11414,7 @@ - + @@ -11509,7 +11509,7 @@ - + @@ -11658,7 +11658,7 @@ - + @@ -11729,7 +11729,7 @@ - + @@ -11806,7 +11806,7 @@ - + @@ -11877,7 +11877,7 @@ - + @@ -11930,7 +11930,7 @@ - + @@ -12019,7 +12019,7 @@ - + @@ -12070,7 +12070,7 @@ - + @@ -12157,7 +12157,7 @@ - + @@ -12238,7 +12238,7 @@ - + @@ -12265,7 +12265,7 @@ - + @@ -12388,7 +12388,7 @@ - + @@ -12441,7 +12441,7 @@ - + @@ -12482,7 +12482,7 @@ - + @@ -12523,7 +12523,7 @@ - + @@ -12564,7 +12564,7 @@ - + @@ -12605,7 +12605,7 @@ - + @@ -12646,7 +12646,7 @@ - + @@ -12687,7 +12687,7 @@ - + @@ -12756,7 +12756,7 @@ - + @@ -12797,7 +12797,7 @@ - + @@ -12838,7 +12838,7 @@ - + @@ -12879,7 +12879,7 @@ - + @@ -12920,7 +12920,7 @@ - + @@ -12961,7 +12961,7 @@ - + @@ -13002,7 +13002,7 @@ - + @@ -13043,7 +13043,7 @@ - + @@ -13076,7 +13076,7 @@ - + @@ -13103,7 +13103,7 @@ - + @@ -13130,7 +13130,7 @@ - + @@ -13243,7 +13243,7 @@ - + @@ -13324,7 +13324,7 @@ - + @@ -13369,7 +13369,7 @@ - + @@ -13408,7 +13408,7 @@ - + @@ -13435,7 +13435,7 @@ - + @@ -13462,7 +13462,7 @@ - + @@ -13490,7 +13490,7 @@ - + @@ -13511,7 +13511,7 @@ - + @@ -13558,7 +13558,7 @@ - + @@ -13609,7 +13609,7 @@ - + @@ -13678,7 +13678,7 @@ - + @@ -13735,7 +13735,7 @@ - + @@ -13804,7 +13804,7 @@ - + @@ -13825,7 +13825,7 @@ - + @@ -13846,7 +13846,7 @@ - + @@ -13873,7 +13873,7 @@ - + @@ -13894,7 +13894,7 @@ - + @@ -14023,7 +14023,7 @@ - + @@ -14062,7 +14062,7 @@ - + @@ -14101,7 +14101,7 @@ - + @@ -14140,7 +14140,7 @@ - + @@ -14185,7 +14185,7 @@ - + @@ -14230,7 +14230,7 @@ - + @@ -14275,7 +14275,7 @@ - + @@ -14314,7 +14314,7 @@ - + @@ -14341,7 +14341,7 @@ - + @@ -14362,7 +14362,7 @@ - + @@ -14401,7 +14401,7 @@ - + @@ -14422,7 +14422,7 @@ - + @@ -14491,7 +14491,7 @@ - + @@ -14524,7 +14524,7 @@ - + @@ -14563,7 +14563,7 @@ - + @@ -14617,7 +14617,7 @@ - + @@ -14638,7 +14638,7 @@ - + @@ -14692,7 +14692,7 @@ - + @@ -14725,7 +14725,7 @@ - + @@ -14782,7 +14782,7 @@ - + @@ -14835,7 +14835,7 @@ - + @@ -14912,7 +14912,7 @@ - + @@ -14971,7 +14971,7 @@ - + @@ -15030,7 +15030,7 @@ - + @@ -15119,7 +15119,7 @@ - + @@ -15152,7 +15152,7 @@ - + @@ -15185,7 +15185,7 @@ - + @@ -15232,7 +15232,7 @@ - + @@ -15303,7 +15303,7 @@ - + @@ -15362,7 +15362,7 @@ - + @@ -15421,7 +15421,7 @@ - + @@ -15534,7 +15534,7 @@ - + @@ -15629,7 +15629,7 @@ - + @@ -15675,7 +15675,7 @@ - + @@ -15780,7 +15780,7 @@ - + @@ -15861,7 +15861,7 @@ - + @@ -15882,7 +15882,7 @@ - + @@ -15927,7 +15927,7 @@ - + @@ -15966,7 +15966,7 @@ - + @@ -16005,7 +16005,7 @@ - + @@ -16038,7 +16038,7 @@ - + @@ -16133,7 +16133,7 @@ - + @@ -16168,7 +16168,7 @@ - + @@ -16203,7 +16203,7 @@ - + @@ -16272,7 +16272,7 @@ - + @@ -16311,7 +16311,7 @@ - + @@ -16376,7 +16376,7 @@ - + @@ -16415,7 +16415,7 @@ - + @@ -16460,7 +16460,7 @@ - + @@ -16505,7 +16505,7 @@ - + @@ -16556,7 +16556,7 @@ - + @@ -16589,7 +16589,7 @@ - + @@ -16700,7 +16700,7 @@ - + @@ -16807,7 +16807,7 @@ - + @@ -16848,7 +16848,7 @@ - + @@ -16959,7 +16959,7 @@ - + @@ -16992,7 +16992,7 @@ - + @@ -17033,7 +17033,7 @@ - + @@ -17054,7 +17054,7 @@ - + @@ -17135,7 +17135,7 @@ - + @@ -17216,7 +17216,7 @@ - + @@ -17237,7 +17237,7 @@ - + @@ -17258,7 +17258,7 @@ - + @@ -17279,7 +17279,7 @@ - + @@ -17360,7 +17360,7 @@ - + @@ -17381,7 +17381,7 @@ - + @@ -17408,7 +17408,7 @@ - + @@ -17471,7 +17471,7 @@ - + @@ -17492,7 +17492,7 @@ - + @@ -17513,7 +17513,7 @@ - + @@ -17552,7 +17552,7 @@ - + @@ -17562,7 +17562,7 @@ >pathological mouse cell line - + @@ -17603,7 +17603,7 @@ The 4T1 cell line was derived from a spontaneously arising BALB/c mammary tumor - + @@ -17612,7 +17612,7 @@ chemicals and drugs - + @@ -17624,7 +17624,7 @@ Inhibitors of hormonal activity - + @@ -17635,7 +17635,7 @@ Inhibitors of estrogen hormone activity - + @@ -17670,7 +17670,7 @@ - + @@ -17728,7 +17728,7 @@ - + @@ -17739,7 +17739,7 @@ A generic term for fats and lipoids, the alcohol-ether-soluble constituents of protoplasm, which are insoluble in water. They comprise the fats, fatty oils, essential oils, waxes, phospholipids, glycolipids, sulfolipids, aminolipids, chromolipids (lipochromes), and fatty acids. - + @@ -17799,7 +17799,7 @@ Organic, monobasic acids derived from hydrocarbons by the equivalent of oxidation of a methyl group to an alcohol, aldehyde, and then acid. Fatty acids are saturated and unsaturated. - + @@ -17830,7 +17830,7 @@ - + @@ -17842,7 +17842,7 @@ A broad class of substances containing carbon and its derivatives. Many of these chemicals will frequently contain hydrogen with or without oxygen, nitrogen, sulfur, phosphorus, and other elements. They exist in either carbon chain or carbon ring form. - + @@ -17851,7 +17851,7 @@ hydrocarbons - + @@ -17876,7 +17876,7 @@ A class of compounds composed of repeating 5-carbon units of hemiterpenes - + @@ -17901,7 +17901,7 @@ The general name for a group of fat-soluble pigments found in green, yellow, and leafy vegetables, and yellow fruits. They are aliphatic hydrocarbons consisting of a polyisoprene backbone. - + @@ -17912,7 +17912,7 @@ A group of tetraterpenes, with four terpene units joined head-to-tail. Biologically active members of this class are used clinically in the treatment of severe cystic acne; psoriasis; and other disorders of keratinization. - + @@ -17960,7 +17960,7 @@ Retinol and derivatives of retinol that play an essential role in metabolic functioning of the retina, the growth of and differentiation of epithelial tissue, the growth of bone, reproduction, and the immune response. Dietary vitamin A is derived from a variety of carotenoids found in plants. It is enriched in the liver, egg yolks, and the fat component of dairy products. - + @@ -18101,7 +18101,7 @@ An important regulator of gene expression during growth and development, and in neoplasms. Tretinoin, also known as retinoic acid and derived from maternal vitamin A, is essential for normal growth; and embryonic development. An excess of tretinoin can be teratogenic. It is used in the treatment of psoriasis; acne vulgaris; and several other skin diseases. It has also been approved for use in promyelocytic leukemia (leukemia, promyelocytic, acute). - + @@ -18158,7 +18158,7 @@ Twenty-carbon compounds derived from mavalonic acid or deoxyxylulose phosphate. - + @@ -18169,7 +18169,7 @@ The parent alcohol of the tumor promoting compounds from croton oil (Croton tiglium). - + @@ -18200,7 +18200,7 @@ Tumor-promoting compounds obtained from croton oil (Croton tiglium). Some of these are used in cell biological experiments as activators of protein kinase C. - + @@ -18284,7 +18284,7 @@ A phorbol ester found in croton oil with very effective tumor promoting activity. It stimulates the synthesis of both DNA and RNA. - + @@ -18296,7 +18296,7 @@ Compounds inhibiting receptor activity - + @@ -18308,7 +18308,7 @@ Compounds inhibitng ERBB2 receptor activity. - + @@ -18320,7 +18320,7 @@ Compounds used in treatment of various pathological conditions. - + @@ -18401,7 +18401,7 @@ Substances that reduce the growth or reproduction of bacteria. - + @@ -18428,7 +18428,7 @@ - + @@ -18464,7 +18464,7 @@ Zeocin is a member of the bleomycin/phleomycin family of antibiotics, known to bind and cleave DNA. - + @@ -18474,7 +18474,7 @@ >antineoplastic agent - + @@ -18730,7 +18730,7 @@ Antineoplastic antibiotic obtained from Streptomyces peucetius. It is a hydroxy derivative of daunorubicin. - + @@ -18877,7 +18877,7 @@ An anthracycline which is the 4'-epi-isomer of doxorubicin. The compound exerts its antitumor effects by interference with the synthesis and function of DNA. - + @@ -19143,7 +19143,7 @@ A semisynthetic derivative of podophyllotoxin that exhibits antitumor activity. Etoposide inhibits DNA synthesis by forming a complex with topoisomerase II and DNA. This complex induces breaks in double stranded DNA and prevents repair by topoisomerase II binding. Accumulated breaks in DNA prevent entry into the mitotic phase of cell division, and lead to cell death. Etoposide acts primarily in the G2 and S phases of the cell cycle. - + @@ -19173,7 +19173,7 @@ - + @@ -19354,7 +19354,7 @@ An anthracenedione-derived antineoplastic agent. - + @@ -19363,7 +19363,7 @@ genetic variation - + @@ -19373,7 +19373,7 @@ >chromosomal mutation - + @@ -19383,7 +19383,7 @@ >chromosomal deletion - + @@ -19394,7 +19394,7 @@ - + @@ -19404,7 +19404,7 @@ >deletion in short arm - + @@ -19426,7 +19426,7 @@ - + @@ -19448,7 +19448,7 @@ - + @@ -19470,7 +19470,7 @@ - + @@ -19479,7 +19479,7 @@ gene mutation - + @@ -19488,7 +19488,7 @@ deletion - + @@ -19497,7 +19497,7 @@ exon deletion - + @@ -19525,7 +19525,7 @@ - + @@ -19553,7 +19553,7 @@ - + @@ -19581,7 +19581,7 @@ - + @@ -19621,7 +19621,7 @@ - + @@ -19649,7 +19649,7 @@ - + @@ -19658,7 +19658,7 @@ duplication - + @@ -19668,7 +19668,7 @@ >exon duplication - + @@ -19697,7 +19697,7 @@ - + @@ -19725,7 +19725,7 @@ - + @@ -19735,7 +19735,7 @@ >gene duplication - + @@ -19763,7 +19763,7 @@ - + @@ -19827,7 +19827,7 @@ - + @@ -19873,7 +19873,7 @@ - + @@ -19901,7 +19901,7 @@ - + @@ -19929,7 +19929,7 @@ - + @@ -19957,7 +19957,7 @@ - + @@ -19966,7 +19966,7 @@ insertion - + @@ -19994,7 +19994,7 @@ - + @@ -20022,7 +20022,7 @@ - + @@ -20031,7 +20031,7 @@ point mutation - + @@ -20041,7 +20041,7 @@ >nonsense mutation - + @@ -20067,7 +20067,7 @@ - + @@ -20093,7 +20093,7 @@ - + @@ -20119,7 +20119,7 @@ - + @@ -20145,7 +20145,7 @@ - + @@ -20171,7 +20171,7 @@ - + @@ -20197,7 +20197,7 @@ - + @@ -20206,7 +20206,7 @@ transition - + @@ -20234,7 +20234,7 @@ - + @@ -20262,7 +20262,7 @@ - + @@ -20290,7 +20290,7 @@ - + @@ -20318,7 +20318,7 @@ - + @@ -20358,7 +20358,7 @@ - + @@ -20386,7 +20386,7 @@ - + @@ -20414,7 +20414,7 @@ - + @@ -20442,7 +20442,7 @@ - + @@ -20451,7 +20451,7 @@ transversion - + @@ -20479,7 +20479,7 @@ - + @@ -20507,7 +20507,7 @@ - + @@ -20535,7 +20535,7 @@ - + @@ -20563,7 +20563,7 @@ - + @@ -20591,7 +20591,7 @@ - + @@ -20619,7 +20619,7 @@ - + @@ -20647,7 +20647,7 @@ - + @@ -20656,7 +20656,7 @@ pathological condition - + @@ -20667,7 +20667,7 @@ New abnormal growth of tissue. Malignant neoplasms show a greater degree of anaplasia and have the properties of invasion and metastasis, compared to benign neoplasms. - + @@ -20697,7 +20697,7 @@ Invasive form of papillary ductal cercinoma of the breast. - + @@ -20709,7 +20709,7 @@ Benign tumors of the breast. - + @@ -20798,7 +20798,7 @@ A noninvasive (noninfiltrating) carcinoma of the breast characterized by a proliferation of malignant epithelial cells confined to the mammary ducts or lobules, without light-microscopy evidence of invasion through the basement membrane into the surrounding stroma. - + @@ -20810,7 +20810,7 @@ Although the name includes the term carcinoma, lobular carcinoma in situ (LCIS) is not really cancer, but rather a noninvasive condition that increases the risk of developing cancer in the future. LCIS, also known as lobular neoplasia or stage 0 breast cancer, occurs when abnormal cells accumulate in the breast lobules. Each breast has hundreds of milk producing lobules, which are connected to the milk ducts. In LCIS, the abnormal cells are often found throughout the breast lobules and both breasts are affected about 30 percent of the time. - + @@ -20828,7 +20828,7 @@ Primary acantholytic squamous cell carcinoma (ASCC) of the breast is a rare and aggressive variant of invasive breast cancer. - + @@ -20978,7 +20978,7 @@ Adenocarcinoma of the breast. - + @@ -21038,7 +21038,7 @@ Pathological processes of the breast. - + @@ -21214,7 +21214,7 @@ A common and benign breast disease characterized by varying degree of fibrocystic changes in the breast tissue. There are three major patterns of morphological changes, including fibrosis, formation of cysts, and proliferation of glandular tissue (adenosis). The fibrocystic breast has a dense irregular, lumpy, bumpy consistency. - + @@ -21433,7 +21433,7 @@ Neoplasm of the breast. - + @@ -22030,7 +22030,7 @@ An invasive (infiltrating) carcinoma of the mammary ductal system (mammary glands) in the human breast. - + @@ -22072,7 +22072,7 @@ Inflammatory Breast Cancer (IBC) is a very aggressive type of breast cancer in which the cancer cells block the lymph vessels in the skin of the breast. This type of breast cancer is called “inflammatory” because the breast often looks swollen and red, or “inflamed”, sometimes overnight and can be misdiagnosed as mastitis. Invasion of the local lymphatic ducts impairs drainage and causes edematous swelling of the breast. - + @@ -22306,7 +22306,7 @@ Metastatic carcinoma of the breast. - + @@ -22324,7 +22324,7 @@ Medullary carcinoma of the breast is a variant of breast cancer. These tumors have a similar presentation to other breast cancers but are distinguished by a characteristic histologic appearance. In addition, pure medullary carcinomas have a better prognosis than usual cases of infiltrating ductal carcinoma. - + @@ -22336,7 +22336,7 @@ Mucinous (colloid) carcinoma is a rare type of invasive breast cancer that is formed when cancer cells within your breast produce mucous. This mucous contains breast cancer cells that are easily distinguished from normal cells under a microscope. Together, the mucous and cancer cells form a jelly-like tumor. Most mucinous carcinomas of the breast are estrogen-receptor positive and HER2/neu negative. This type of breast cancer rarely spreads to your lymph nodes. - + @@ -22348,7 +22348,7 @@ Papillary carcinoma is a type of ductal carcinoma in situ (DCIS). This type of breast cancer is rarely invasive, and usually stays within the milk ducts of your breast. Papilla (a projection) refers to the microscopic shape of the cancer cells, which resemble fingers, or threads. - + @@ -22366,7 +22366,7 @@ An infiltrating ductal breast carcinoma associated with stromal fibrosis. - + @@ -22378,7 +22378,7 @@ SCC of the breast was first reported in 1908 by Troell. It is thought to arise directly from the epithelium of the mammary ducts, although an alternate theory is that the tumor arises from foci of squamous metaplasia within a preexisting adenocarcinoma of the breast. Squamous cell carcinoma (SCC) of the breast is rare and generally aggressive. - + @@ -22390,7 +22390,7 @@ Tubular carcinoma is a rare type of invasive ductal carcinoma of the breast. It takes its name from its microscopic appearance, in which the cancer cells resemble small tubes. Tubular carcinomas tend to be small, estrogen-receptor positive, HER2/neu negative. In some cases, tubular cancer cells are mixed with ductal or lobular cancer cells, giving a mixed-tumor diagnosis. - + @@ -22408,7 +22408,7 @@ Invasive Lobular Carcinoma (ILC) is a type of breast cancer that starts in the lobules of your breast, where milk is produced. At first, the cancer cells are at work in the lining of the milk lobes, but later these cells invade, or infiltrate, the nearby tissue outside of the lobes. As with invasive ductal carcinoma (IDC), ILC has the potential to spread, or metastasize, to other parts of your body. - + @@ -22420,7 +22420,7 @@ Within the abdominal cavity, nodes occur in chains along the main branches of the arteries of the intestine and the abdominal aorta. - + @@ -22431,7 +22431,7 @@ Biological entity, which constitutes the structural organization of a biological organism, or is an attribute of that organization. - + @@ -22449,7 +22449,7 @@ These nodes are in the underarm region and receive lymph from vessels that drain the arm, the walls of the thorax, the breast, and the upper walls of the abdomen. - + @@ -22461,7 +22461,7 @@ Anatomical areas of the body. - + @@ -22540,7 +22540,7 @@ The part of Central Nervous System that is contained within the skull (cranium). Arising from the neural tube, the embryonic brain is comprised of three major parts including prosencephalon (the forebrain); mesencephalon (the midbrain); and rhombencephalon (the hindbrain). The developed brain consists of cerebrum; cerebellum; and other structures in the brain stem. - + @@ -22569,7 +22569,7 @@ The main information-processing organs of the nervous system, consisting of the brain, spinal cord, and meninges. - + @@ -22587,7 +22587,7 @@ Nodules in chest wall - + @@ -22598,7 +22598,7 @@ Exocrine glands are glands that secrete their products (hormones) into ducts (duct glands) - + @@ -22609,7 +22609,7 @@ The body's defense mechanism against foreign organisms or substances and deviant native cells. It includes the humoral immune response and the cell-mediated response and consists of a complex of interrelated cellular, molecular, and genetic components. - + @@ -22621,7 +22621,7 @@ These nodes receive lymph from the legs, the outer portion of the genitalia and the lower abdominal wall. - + @@ -22680,7 +22680,7 @@ Either of the pair of organs occupying the cavity of the thorax that effect the aeration of the blood. - + @@ -22691,7 +22691,7 @@ They are oval or bean shaped bodies (1 - 30 mm in diameter) located along the lymphatic system. - + @@ -22703,7 +22703,7 @@ These nodes are grouped along the lower border of the jaw, in front of and behind the ears, and deep in the neck along the larger blood vessels. They drain the skin of the scalp, face, tissues of the nasal cavity, and the pharynx. - + @@ -22715,7 +22715,7 @@ A system of organs and tissues that process and transport immune cells and lymph. - + @@ -22797,7 +22797,7 @@ Specialized tissues that are components of the lymphatic system. They provide fixed locations within the body where a variety of lymphocytes can form, mature and multiply. The lymphoid tissues are connected by a network of lymphatic vessels. - + @@ -23980,7 +23980,7 @@ Glandular tissue in the breast that is under the influence of hormones such as estrogens; progestins; and prolactin. After parturition, the mammary glands secrete milk for the nourishment of the young. - + @@ -23991,7 +23991,7 @@ The entire nerve apparatus, composed of a central part, the brain and spinal cord, and a peripheral part, the cranial and spinal nerves, autonomic ganglia, and plexuses. - + @@ -24003,7 +24003,7 @@ The nodes here appear mostly along the paths of the blood vessels within the pelvic cavity and receive lymph from the lymphatic vessels in the area. - + @@ -24037,7 +24037,7 @@ The tubular and cavernous organs and structures, by means of which pulmonary ventilation and gas exchange between ambient air and the blood are brought about. - + @@ -24049,7 +24049,7 @@ These nodes occur between the lungs and along the windpipe and bronchi, and receive lymph from this area and from the internal wall of the thorax. - + @@ -24060,7 +24060,7 @@ The outer margins of the thorax containing skin, deep fascia; thorasic vertebrae; ribs; sternum; and muscles. - + @@ -24077,7 +24077,7 @@ The upper part of the trunk between the neck and the abdomen. It contains the chief organs of the circulatory and respiratory systems. - + @@ -24089,7 +24089,7 @@ Collections of differentiated cells, such as epithelium; connective tissue; muscles; and nerve tissue. Tissues are cooperatively arranged to form organs with specialized functions such as respiration; digestion; reproduction; movement; and others. - + @@ -24099,7 +24099,7 @@ Mouse embryo fibroblasts - + @@ -24119,7 +24119,7 @@ - + @@ -24139,7 +24139,7 @@ - + @@ -24153,7 +24153,7 @@ - + @@ -24173,7 +24173,7 @@ - + @@ -24187,7 +24187,7 @@ - + @@ -24201,7 +24201,7 @@ - + @@ -24223,7 +24223,7 @@ The 308 cell line is a papilloma-derived keratinocyte cell line from 7,12-dimethylbenz[a]anthracene-treated adult BALB/c mouse skin - + @@ -24233,7 +24233,7 @@ Mouse 30A5 preadipocytes is a cell line derived from 10Tl 2 fibroblasts - + @@ -24267,7 +24267,7 @@ An immortalized myeloblast-like cell line originally derived from long-term cultures of murine bone marrow. The most frequently employed subline is 32D clone 3 (32D cl3). - + @@ -24277,7 +24277,7 @@ Hematopoietic, immature myeloid, nontumorigenic, diploid cell line that is strictly dependent on exogenously supplied interleukin-3 (IL-3) for maintenance of its growth in culture. - + @@ -24287,7 +24287,7 @@ 3T3-C2 fibroblastic cells, a nondifferentiated subline of 3T3-L1, follow adipogenic process till mitotic clonal expansion stage (2 days after hormonal induction), but do not proceed to terminal differentitation. - + @@ -24297,7 +24297,7 @@ These cells (often just referred to as F442A cells) are one of several cloned cell lines established from disaggregated Swiss mouse embryos that are capable of differentiating into cells resembling adipocytes. The cells have the morphology of fibroblasts. When the cells reach confluence they spontaneously arrest growth and can be induced to differentiate into white adipocytes in vitro. They also yield a fully differentiated fat pad after subcutaneous injection into nude mice. These cells are used widely as a model system for pre-adypocytes to study the differentiation of adipocytes. - + @@ -24325,7 +24325,7 @@ L1 is a continuous substrain of 3T3 (Swiss albino) developed through clonal isolation. The cells undergo a pre-adipose to adipose like conversion as they progress from a rapidly dividing to a confluent and contact inhibited state. A high serum content in the medium enhances fat accumulation. - + @@ -24339,7 +24339,7 @@ - + @@ -24359,7 +24359,7 @@ - + @@ -24379,7 +24379,7 @@ - + @@ -24399,7 +24399,7 @@ - + @@ -24419,7 +24419,7 @@ - + @@ -24429,7 +24429,7 @@ Derived following HIV infection of A3.01. Contains a single integrated copy of defective HIV provirus - + @@ -24439,7 +24439,7 @@ Derivative of 8E5; retains HIV provirus but does not express HIV proteins. - + @@ -24453,7 +24453,7 @@ - + @@ -24473,7 +24473,7 @@ - + @@ -24493,7 +24493,7 @@ - + @@ -24515,7 +24515,7 @@ The A-431 cell line was derived from an epidermoid carcinoma excised from the skin tissue of an 85-year-old female. - + @@ -24531,7 +24531,7 @@ The A10 cell line was derived from the thoracic aorta of embryonic rat and is a commonly used model of vascular smooth muscle cells (VSMC). - + @@ -24545,7 +24545,7 @@ - + @@ -24555,7 +24555,7 @@ HAT-sensitive derivative of CEM obtained by treatment with 8-azaguanine. A3.01 is a hypoxanthine/aminopterin/thymidine-sensitive, human immunodeficiency virus-susceptible, human T cell line. - + @@ -24577,7 +24577,7 @@ This line was cloned by limiting dilution from the A375 melanoma cell line - + @@ -24597,7 +24597,7 @@ - + @@ -24607,7 +24607,7 @@ The ACH2 cell line is a clonal cell line derived following infection of A3.01 T cells with HIV-1. - + @@ -24627,7 +24627,7 @@ - + @@ -24641,7 +24641,7 @@ - + @@ -24693,7 +24693,7 @@ The AML12 (alpha mouse liver 12) cell line was established from hepatocytes from a mouse (CD1 strain, line MT42) transgenic for human TGF alpha. By electron microscopy, these cells exhibit typical hepatocyte features such as peroxisomes and bile canalicular like structure. AML12 cells retain the capacity to express high levels of mRNA for serum (albumin, alpha 1 antitrypsin and transferrin) and gap junction (connexins 26 and 32) proteins, and contain solely isoenzyme 5 of lactate dehydrogenase. - + @@ -24709,7 +24709,7 @@ Macrophage cell line derived from the bone marrow of C57BL/6 mice - + @@ -24731,7 +24731,7 @@ AR42J cells derive from azaserine-induced malignant nodules from the rat pancreas. AR42J cells represent the first amphicrine pancreatic cell line with the combined expression of exocrine and neuroendocrine secretory organelles, both of which follow a regulated secretory pathway in response to various secretory stimuli. - + @@ -24753,7 +24753,7 @@ Human anaplastic thyroid cancer cell line - + @@ -24769,7 +24769,7 @@ ARPE-19 is a human diploid retinal pigment epithelium (RPE) cell line, which is in many ways similar to RPE in vivo. - + @@ -24789,7 +24789,7 @@ - + @@ -24809,7 +24809,7 @@ - + @@ -24829,7 +24829,7 @@ - + @@ -24837,7 +24837,7 @@ - + @@ -24851,7 +24851,7 @@ - + @@ -24859,7 +24859,7 @@ - + @@ -24873,7 +24873,7 @@ - + @@ -24895,7 +24895,7 @@ An Epstein-Barr virus (EBV)-producer line, designated Akata, was established from a Japanese patient with Burkitt's lymphoma. The Akata line possessed the Burkitt's-type chromosome translocation, t(8q- ; 14q+), and was derived from the tumor cell. Akata cells produced a large quantity of transforming virus upon treatment of cells with anti-immunoglobulin antibodies. Southern blot analysis of viral DNA indicated that the Akata EBV is nondefective and more representative of wild-type viruses. Akata cells should be useful as a source of EBV. - + @@ -24909,7 +24909,7 @@ - + @@ -24917,7 +24917,7 @@ - + @@ -24931,7 +24931,7 @@ - + @@ -24939,7 +24939,7 @@ - + @@ -24947,7 +24947,7 @@ - + @@ -24955,7 +24955,7 @@ - + @@ -24977,7 +24977,7 @@ The line was derived from nude mouse xenografts initiated with cells from the ascites of a patient with cancer of the pancreas. - + @@ -24991,7 +24991,7 @@ - + @@ -24999,7 +24999,7 @@ - + @@ -25013,7 +25013,7 @@ - + @@ -25033,7 +25033,7 @@ - + @@ -25053,7 +25053,7 @@ - + @@ -25073,7 +25073,7 @@ - + @@ -25093,7 +25093,7 @@ - + @@ -25113,7 +25113,7 @@ - + @@ -25133,7 +25133,7 @@ - + @@ -25161,7 +25161,7 @@ TNF-alpha gene-transduced B78 melanoma cells - + @@ -25175,7 +25175,7 @@ - + @@ -25195,7 +25195,7 @@ - + @@ -25215,7 +25215,7 @@ - + @@ -25237,7 +25237,7 @@ A cell line established from a spontaneous lymphoma obtained from a female BALB/c mouse. - + @@ -25251,7 +25251,7 @@ - + @@ -25265,7 +25265,7 @@ - + @@ -25279,7 +25279,7 @@ - + @@ -25293,7 +25293,7 @@ - + @@ -25307,7 +25307,7 @@ - + @@ -25315,7 +25315,7 @@ - + @@ -25335,7 +25335,7 @@ - + @@ -25343,7 +25343,7 @@ - + @@ -25363,7 +25363,7 @@ - + @@ -25377,7 +25377,7 @@ - + @@ -25399,7 +25399,7 @@ The Ba/F3-mpI cell line was established by introduction of the cDNA encoding the entire cMpI receptor into the IL-3 dependent murine lymphobiastoid cell line Ba/F3. - + @@ -25415,7 +25415,7 @@ An immortalized murine bone marrow-derived pro-B-cell line. - + @@ -25423,7 +25423,7 @@ - + @@ -25449,7 +25449,7 @@ - + @@ -25457,7 +25457,7 @@ - + @@ -25465,7 +25465,7 @@ - + @@ -25473,7 +25473,7 @@ - + @@ -25511,7 +25511,7 @@ - + @@ -25519,7 +25519,7 @@ - + @@ -25527,7 +25527,7 @@ - + @@ -25553,7 +25553,7 @@ - + @@ -25603,7 +25603,7 @@ - + @@ -25611,7 +25611,7 @@ - + @@ -25637,7 +25637,7 @@ - + @@ -25645,7 +25645,7 @@ - + @@ -25659,7 +25659,7 @@ - + @@ -25667,7 +25667,7 @@ - + @@ -25681,7 +25681,7 @@ - + @@ -25695,7 +25695,7 @@ - + @@ -25715,7 +25715,7 @@ - + @@ -25729,7 +25729,7 @@ - + @@ -25737,7 +25737,7 @@ - + @@ -25751,7 +25751,7 @@ - + @@ -25765,7 +25765,7 @@ - + @@ -25779,7 +25779,7 @@ - + @@ -25799,7 +25799,7 @@ - + @@ -25813,7 +25813,7 @@ - + @@ -25833,7 +25833,7 @@ - + @@ -25847,7 +25847,7 @@ - + @@ -25861,7 +25861,7 @@ - + @@ -25881,7 +25881,7 @@ - + @@ -25895,7 +25895,7 @@ - + @@ -25911,7 +25911,7 @@ The CAD cell line is a variant of a CNS-derived Cath.a cell line - + @@ -25931,7 +25931,7 @@ - + @@ -25951,7 +25951,7 @@ - + @@ -25971,7 +25971,7 @@ - + @@ -25985,7 +25985,7 @@ - + @@ -25999,7 +25999,7 @@ - + @@ -26019,7 +26019,7 @@ - + @@ -26039,7 +26039,7 @@ - + @@ -26059,7 +26059,7 @@ - + @@ -26079,7 +26079,7 @@ - + @@ -26095,7 +26095,7 @@ CEM cells are a line of lymphoblastic cells originally derived from a child with acute lymphoblastic leukemia. Like all uncloned cell lines, the original CEM cells are a mixed population of clones with varied genotypes and phenotypes. - + @@ -26105,7 +26105,7 @@ glucocorticoid resistant clone of CEM - + @@ -26113,7 +26113,7 @@ - + @@ -26121,7 +26121,7 @@ - + @@ -26131,7 +26131,7 @@ glucocorticoid sensitive clone of CEM - + @@ -26139,7 +26139,7 @@ - + @@ -26149,7 +26149,7 @@ HAT sensitive derivative of CEM obtained by treatment with 8-azaguanine - + @@ -26169,7 +26169,7 @@ - + @@ -26189,7 +26189,7 @@ - + @@ -26209,7 +26209,7 @@ - + @@ -26229,7 +26229,7 @@ - + @@ -26249,7 +26249,7 @@ - + @@ -26269,7 +26269,7 @@ - + @@ -26289,7 +26289,7 @@ - + @@ -26309,7 +26309,7 @@ - + @@ -26323,7 +26323,7 @@ - + @@ -26343,7 +26343,7 @@ - + @@ -26351,7 +26351,7 @@ - + @@ -26359,7 +26359,7 @@ - + @@ -26367,7 +26367,7 @@ - + @@ -26375,7 +26375,7 @@ - + @@ -26383,7 +26383,7 @@ - + @@ -26391,7 +26391,7 @@ - + @@ -26417,7 +26417,7 @@ - + @@ -26425,7 +26425,7 @@ - + @@ -26445,7 +26445,7 @@ - + @@ -26453,7 +26453,7 @@ - + @@ -26479,7 +26479,7 @@ - + @@ -26487,7 +26487,7 @@ - + @@ -26501,7 +26501,7 @@ - + @@ -26539,7 +26539,7 @@ - + @@ -26553,7 +26553,7 @@ - + @@ -26573,7 +26573,7 @@ - + @@ -26695,7 +26695,7 @@ - + @@ -26817,7 +26817,7 @@ - + @@ -26825,7 +26825,7 @@ - + @@ -26833,7 +26833,7 @@ - + @@ -26853,7 +26853,7 @@ - + @@ -26879,7 +26879,7 @@ - + @@ -26887,7 +26887,7 @@ - + @@ -26901,7 +26901,7 @@ - + @@ -26915,7 +26915,7 @@ - + @@ -26935,7 +26935,7 @@ - + @@ -26955,7 +26955,7 @@ - + @@ -26975,7 +26975,7 @@ - + @@ -26995,7 +26995,7 @@ - + @@ -27003,7 +27003,7 @@ - + @@ -27011,7 +27011,7 @@ - + @@ -27019,7 +27019,7 @@ - + @@ -27027,7 +27027,7 @@ - + @@ -27035,7 +27035,7 @@ - + @@ -27043,7 +27043,7 @@ - + @@ -27051,7 +27051,7 @@ - + @@ -27071,7 +27071,7 @@ - + @@ -27097,7 +27097,7 @@ - + @@ -27111,7 +27111,7 @@ - + @@ -27125,7 +27125,7 @@ - + @@ -27133,7 +27133,7 @@ - + @@ -27141,7 +27141,7 @@ - + @@ -27149,7 +27149,7 @@ - + @@ -27169,7 +27169,7 @@ - + @@ -27189,7 +27189,7 @@ - + @@ -27203,7 +27203,7 @@ - + @@ -27217,7 +27217,7 @@ - + @@ -27237,7 +27237,7 @@ - + @@ -27245,7 +27245,7 @@ - + @@ -27253,7 +27253,7 @@ - + @@ -27273,7 +27273,7 @@ - + @@ -27287,7 +27287,7 @@ - + @@ -27307,7 +27307,7 @@ - + @@ -27327,7 +27327,7 @@ - + @@ -27347,7 +27347,7 @@ - + @@ -27367,7 +27367,7 @@ - + @@ -27381,7 +27381,7 @@ - + @@ -27401,7 +27401,7 @@ - + @@ -27415,7 +27415,7 @@ - + @@ -27429,7 +27429,7 @@ - + @@ -27443,7 +27443,7 @@ - + @@ -27463,7 +27463,7 @@ - + @@ -27479,7 +27479,7 @@ GP8 cells were isolated from rat brain cortex and immortalized with SV40 large T Ag - + @@ -27493,7 +27493,7 @@ - + @@ -27501,7 +27501,7 @@ - + @@ -27509,7 +27509,7 @@ - + @@ -27517,7 +27517,7 @@ - + @@ -27525,7 +27525,7 @@ - + @@ -27563,7 +27563,7 @@ - + @@ -27583,7 +27583,7 @@ - + @@ -27591,7 +27591,7 @@ - + @@ -27611,7 +27611,7 @@ - + @@ -27631,7 +27631,7 @@ - + @@ -27651,7 +27651,7 @@ - + @@ -27665,7 +27665,7 @@ - + @@ -27681,7 +27681,7 @@ HBE1 cell line is an immortalized line of normal human airway epithelial cells - + @@ -27695,7 +27695,7 @@ - + @@ -27715,7 +27715,7 @@ - + @@ -27735,7 +27735,7 @@ - + @@ -27755,7 +27755,7 @@ - + @@ -27775,7 +27775,7 @@ - + @@ -27795,7 +27795,7 @@ - + @@ -27809,7 +27809,7 @@ - + @@ -27823,7 +27823,7 @@ - + @@ -27843,7 +27843,7 @@ - + @@ -27857,7 +27857,7 @@ - + @@ -27873,7 +27873,7 @@ An immortalized proximal tubule epithelial cell line from normal adult human kidney. - + @@ -27893,7 +27893,7 @@ - + @@ -27913,7 +27913,7 @@ - + @@ -27933,7 +27933,7 @@ - + @@ -27953,7 +27953,7 @@ - + @@ -27973,7 +27973,7 @@ - + @@ -27987,7 +27987,7 @@ - + @@ -28001,7 +28001,7 @@ - + @@ -28021,7 +28021,7 @@ - + @@ -28041,7 +28041,7 @@ - + @@ -28061,7 +28061,7 @@ - + @@ -28081,7 +28081,7 @@ - + @@ -28095,7 +28095,7 @@ - + @@ -28111,7 +28111,7 @@ The HT22 nerve cell line is a subclone of HT4, derived from the mouse hippocampus. - + @@ -28131,7 +28131,7 @@ - + @@ -28151,7 +28151,7 @@ - + @@ -28171,7 +28171,7 @@ - + @@ -28179,7 +28179,7 @@ - + @@ -28193,7 +28193,7 @@ - + @@ -28213,7 +28213,7 @@ - + @@ -28233,7 +28233,7 @@ - + @@ -28253,7 +28253,7 @@ - + @@ -28273,7 +28273,7 @@ - + @@ -28293,7 +28293,7 @@ - + @@ -28415,7 +28415,7 @@ - + @@ -28423,7 +28423,7 @@ - + @@ -28443,7 +28443,7 @@ - + @@ -28463,7 +28463,7 @@ - + @@ -28483,7 +28483,7 @@ - + @@ -28503,7 +28503,7 @@ - + @@ -28523,7 +28523,7 @@ - + @@ -28543,7 +28543,7 @@ - + @@ -28557,7 +28557,7 @@ - + @@ -28577,7 +28577,7 @@ - + @@ -28591,7 +28591,7 @@ - + @@ -28605,7 +28605,7 @@ - + @@ -28619,7 +28619,7 @@ - + @@ -28639,7 +28639,7 @@ - + @@ -28659,7 +28659,7 @@ - + @@ -28673,7 +28673,7 @@ - + @@ -28693,7 +28693,7 @@ - + @@ -28713,7 +28713,7 @@ - + @@ -28727,7 +28727,7 @@ - + @@ -28747,7 +28747,7 @@ - + @@ -28779,7 +28779,7 @@ - + @@ -28787,7 +28787,7 @@ - + @@ -28819,7 +28819,7 @@ - + @@ -28827,7 +28827,7 @@ - + @@ -28841,7 +28841,7 @@ - + @@ -28861,7 +28861,7 @@ - + @@ -28881,7 +28881,7 @@ - + @@ -28901,7 +28901,7 @@ - + @@ -28921,7 +28921,7 @@ - + @@ -28941,7 +28941,7 @@ - + @@ -28961,7 +28961,7 @@ - + @@ -28981,7 +28981,7 @@ - + @@ -29001,7 +29001,7 @@ - + @@ -29015,7 +29015,7 @@ - + @@ -29035,7 +29035,7 @@ - + @@ -29055,7 +29055,7 @@ - + @@ -29075,7 +29075,7 @@ - + @@ -29091,7 +29091,7 @@ This human stromal cell line was obtained from adherent bone marrow cell layers of Dexter-type long-term BMC (bone marrow culture) after immortalisation with SV40. - + @@ -29113,7 +29113,7 @@ H4IIEC3 subclone - + @@ -29133,7 +29133,7 @@ - + @@ -29153,7 +29153,7 @@ - + @@ -29173,7 +29173,7 @@ - + @@ -29217,7 +29217,7 @@ - + @@ -29225,7 +29225,7 @@ - + @@ -29233,7 +29233,7 @@ - + @@ -29247,7 +29247,7 @@ - + @@ -29261,7 +29261,7 @@ - + @@ -29281,7 +29281,7 @@ - + @@ -29301,7 +29301,7 @@ - + @@ -29321,7 +29321,7 @@ - + @@ -29341,7 +29341,7 @@ - + @@ -29361,7 +29361,7 @@ - + @@ -29381,7 +29381,7 @@ - + @@ -29389,7 +29389,7 @@ - + @@ -29397,7 +29397,7 @@ - + @@ -29405,7 +29405,7 @@ - + @@ -29551,7 +29551,7 @@ - + @@ -29559,7 +29559,7 @@ - + @@ -29567,7 +29567,7 @@ - + @@ -29575,7 +29575,7 @@ - + @@ -29595,7 +29595,7 @@ - + @@ -29609,7 +29609,7 @@ - + @@ -29617,7 +29617,7 @@ - + @@ -29643,7 +29643,7 @@ - + @@ -29663,7 +29663,7 @@ - + @@ -29683,7 +29683,7 @@ - + @@ -29703,7 +29703,7 @@ - + @@ -29723,7 +29723,7 @@ - + @@ -29737,7 +29737,7 @@ - + @@ -29757,7 +29757,7 @@ - + @@ -29777,7 +29777,7 @@ - + @@ -29791,7 +29791,7 @@ - + @@ -29799,7 +29799,7 @@ - + @@ -29807,7 +29807,7 @@ - + @@ -29887,7 +29887,7 @@ - + @@ -29895,7 +29895,7 @@ - + @@ -29903,7 +29903,7 @@ - + @@ -29911,7 +29911,7 @@ - + @@ -29919,7 +29919,7 @@ - + @@ -29927,7 +29927,7 @@ - + @@ -29941,7 +29941,7 @@ - + @@ -29955,7 +29955,7 @@ - + @@ -29969,7 +29969,7 @@ - + @@ -29977,7 +29977,7 @@ - + @@ -29985,7 +29985,7 @@ - + @@ -29993,7 +29993,7 @@ - + @@ -30013,7 +30013,7 @@ - + @@ -30057,7 +30057,7 @@ - + @@ -30065,7 +30065,7 @@ - + @@ -30073,7 +30073,7 @@ - + @@ -30081,7 +30081,7 @@ - + @@ -30089,7 +30089,7 @@ - + @@ -30097,7 +30097,7 @@ - + @@ -30105,7 +30105,7 @@ - + @@ -30119,7 +30119,7 @@ - + @@ -30127,7 +30127,7 @@ - + @@ -30153,7 +30153,7 @@ - + @@ -30161,7 +30161,7 @@ - + @@ -30199,7 +30199,7 @@ - + @@ -30243,7 +30243,7 @@ - + @@ -30263,7 +30263,7 @@ - + @@ -30367,7 +30367,7 @@ - + @@ -30381,7 +30381,7 @@ - + @@ -30461,7 +30461,7 @@ - + @@ -30469,7 +30469,7 @@ - + @@ -30477,7 +30477,7 @@ - + @@ -30485,7 +30485,7 @@ - + @@ -30493,7 +30493,7 @@ - + @@ -30501,7 +30501,7 @@ - + @@ -30509,7 +30509,7 @@ - + @@ -30553,7 +30553,7 @@ - + @@ -30579,7 +30579,7 @@ - + @@ -30593,7 +30593,7 @@ - + @@ -30601,7 +30601,7 @@ - + @@ -30621,7 +30621,7 @@ - + @@ -30629,7 +30629,7 @@ - + @@ -30637,7 +30637,7 @@ - + @@ -30669,7 +30669,7 @@ - + @@ -30695,7 +30695,7 @@ - + @@ -30709,7 +30709,7 @@ - + @@ -30725,7 +30725,7 @@ RBE4 cells were isolated from rat brain cortex and immortalized with the plasmid pE1A-neo, containing the adenovirus E1A-encoding sequence followed by a neomycin resistance gene. - + @@ -30739,7 +30739,7 @@ - + @@ -30747,7 +30747,7 @@ - + @@ -30755,7 +30755,7 @@ - + @@ -30763,7 +30763,7 @@ - + @@ -30777,7 +30777,7 @@ - + @@ -30791,7 +30791,7 @@ - + @@ -30799,7 +30799,7 @@ - + @@ -30813,7 +30813,7 @@ - + @@ -30833,7 +30833,7 @@ - + @@ -30853,7 +30853,7 @@ - + @@ -30873,7 +30873,7 @@ - + @@ -30893,7 +30893,7 @@ - + @@ -30913,7 +30913,7 @@ - + @@ -30921,7 +30921,7 @@ - + @@ -30929,7 +30929,7 @@ - + @@ -30961,7 +30961,7 @@ - + @@ -30969,7 +30969,7 @@ - + @@ -31073,7 +31073,7 @@ - + @@ -31087,7 +31087,7 @@ - + @@ -31107,7 +31107,7 @@ - + @@ -31121,7 +31121,7 @@ - + @@ -31129,7 +31129,7 @@ - + @@ -31143,7 +31143,7 @@ - + @@ -31157,7 +31157,7 @@ - + @@ -31207,7 +31207,7 @@ - + @@ -31257,7 +31257,7 @@ - + @@ -31295,7 +31295,7 @@ - + @@ -31303,7 +31303,7 @@ - + @@ -31311,7 +31311,7 @@ - + @@ -31331,7 +31331,7 @@ - + @@ -31345,7 +31345,7 @@ - + @@ -31359,7 +31359,7 @@ - + @@ -31367,7 +31367,7 @@ - + @@ -31387,7 +31387,7 @@ - + @@ -31395,7 +31395,7 @@ - + @@ -31409,7 +31409,7 @@ - + @@ -31423,7 +31423,7 @@ - + @@ -31431,7 +31431,7 @@ - + @@ -31463,7 +31463,7 @@ - + @@ -31489,7 +31489,7 @@ - + @@ -31503,7 +31503,7 @@ - + @@ -31523,7 +31523,7 @@ - + @@ -31537,7 +31537,7 @@ - + @@ -31545,7 +31545,7 @@ - + @@ -31559,7 +31559,7 @@ - + @@ -31573,7 +31573,7 @@ - + @@ -31581,7 +31581,7 @@ - + @@ -31589,7 +31589,7 @@ - + @@ -31597,7 +31597,7 @@ - + @@ -31605,7 +31605,7 @@ - + @@ -31625,7 +31625,7 @@ - + @@ -31633,7 +31633,7 @@ - + @@ -31641,7 +31641,7 @@ - + @@ -31649,7 +31649,7 @@ - + @@ -31669,7 +31669,7 @@ - + @@ -31689,7 +31689,7 @@ - + @@ -31709,7 +31709,7 @@ - + @@ -31723,10 +31723,10 @@ - - - diff --git a/test/helpers/test_application_helper.rb b/test/helpers/test_application_helper.rb index 2315a677d..6a46a07e6 100644 --- a/test/helpers/test_application_helper.rb +++ b/test/helpers/test_application_helper.rb @@ -9,22 +9,22 @@ def before_suite def test_it_escapes_html escaped_html = helper.h("http://testlink.com") - assert escaped_html.eql?("<a>http://testlink.com</a>") + assert_equal "<a>http://testlink.com</a>", escaped_html end def test_ontologies_param - ids = @@ontologies.map {|o| o.id.to_s} - acronyms = @@ontologies.map {|o| o.id.to_s.split("/").last} - params = {"ontologies" => acronyms.join(",")} + ids = @@ontologies.map { |o| o.id.to_s } + acronyms = @@ontologies.map { |o| o.id.to_s.split("/").last } + params = { "ontologies" => acronyms.join(",") } ontologies = ontologies_param(params) assert ontologies == ids - params = {"ontologies" => ids.join(",")} + params = { "ontologies" => ids.join(",") } ontologies = ontologies_param(params) assert ontologies == ids id_acronym = ids + acronyms - params = {"ontologies" => id_acronym.join(",")} + params = { "ontologies" => id_acronym.join(",") } ontologies = ontologies_param(params) assert ontologies == (ids + ids) end @@ -48,16 +48,16 @@ def test_acronym_from_ontology_uri def test_bad_accept_header_handling # This accept header contains '*; q=.2', which isn't valid according to the spec, should be '*/*; q=.2' bad_accept_header = "text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2" - get "/ontologies", {}, {"HTTP_ACCEPT" => bad_accept_header} + get "/ontologies", {}, { "HTTP_ACCEPT" => bad_accept_header } assert last_response.status == 400 assert last_response.body.include?("Accept header `#{bad_accept_header}` is invalid") end def test_http_method_override - post "/ontologies", {}, {"HTTP_X_HTTP_METHOD_OVERRIDE" => "GET"} + post "/ontologies", {}, { "HTTP_X_HTTP_METHOD_OVERRIDE" => "GET" } assert last_response.ok? acronyms = @@ontologies.map {|o| o.bring(:acronym).acronym}.sort - resp_acronyms = MultiJson.load(last_response.body).map {|o| o["acronym"]}.sort + resp_acronyms = MultiJson.load(last_response.body).map { |o| o["acronym"] }.sort assert_equal acronyms, resp_acronyms end end diff --git a/test/helpers/test_slices_helper.rb b/test/helpers/test_slices_helper.rb index 9639c6b17..33ed36abd 100644 --- a/test/helpers/test_slices_helper.rb +++ b/test/helpers/test_slices_helper.rb @@ -4,6 +4,7 @@ class TestSlicesHelper < TestCaseHelpers def before_suite self.backend_4s_delete + LinkedData::Models::Class.indexClear @@orig_slices_setting = LinkedData.settings.enable_slices LinkedData.settings.enable_slices = true @@ -17,11 +18,11 @@ def before_suite end @@search_onts = LinkedData::SampleData::Ontology.create_ontologies_and_submissions({ - ont_count: 2, - submission_count: 1, - acronym: "PARSED", - process_submission: true - })[2] + ont_count: 2, + submission_count: 1, + acronym: "PARSED", + process_submission: true + })[2] @@search_onts.first.bring_remaining @@search_onts.first.group = [@@group] @@search_onts.first.save @@ -32,7 +33,6 @@ def before_suite end def after_suite - LinkedData.settings.enable_slices = @@orig_slices_setting self.backend_4s_delete end @@ -76,12 +76,28 @@ def test_search_slices assert results.all? {|r| group_ids.include?(r["links"]["ontology"])} end + def test_mappings_slices + LinkedData::Mappings.create_mapping_counts(Logger.new(TestLogFile.new)) + + get "/mappings/statistics/ontologies" + + expected_result_without_slice = ["PARSED-0", "PARSED-1"] + + assert_equal expected_result_without_slice, MultiJson.load(last_response.body).keys.sort + + get "http://#{@@group_acronym}/mappings/statistics/ontologies" + + expected_result_with_slice = ["PARSED-0"] + + assert_equal expected_result_with_slice, MultiJson.load(last_response.body).keys.sort + end + private def self._create_group LinkedData::Models::Group.new({ - acronym: @@group_acronym, - name: "Test Group" - }).save + acronym: @@group_acronym, + name: "Test Group" + }).save end -end +end \ No newline at end of file diff --git a/test/helpers/test_users_helper.rb b/test/helpers/test_users_helper.rb index 6ceb686f4..e3e4e5dcf 100644 --- a/test/helpers/test_users_helper.rb +++ b/test/helpers/test_users_helper.rb @@ -8,16 +8,16 @@ def before_suite @@non_custom_user = self.class._create_user("notcustom") @@onts = LinkedData::SampleData::Ontology.create_ontologies_and_submissions({ - ont_count: 5, - submission_count: 0 - })[2] + ont_count: 5, + submission_count: 0 + })[2] @@search_onts = LinkedData::SampleData::Ontology.create_ontologies_and_submissions({ - ont_count: 2, - submission_count: 1, - acronym: "PARSED", - process_submission: true - })[2] + ont_count: 2, + submission_count: 1, + acronym: "PARSED", + process_submission: true + })[2] @@user_ont_search = @@search_onts.first @@user_ont = @@onts.first @@ -42,6 +42,7 @@ def test_filtered_list end def test_search_custom_onts + skip "Test is not consistent, need to be fixed to work all the time" # Make sure group and non-group onts are in the search index get "/search?q=a*&pagesize=500&apikey=#{@@non_custom_user.apikey}" assert last_response.ok? @@ -56,14 +57,16 @@ def test_search_custom_onts assert results.all? {|r| @@custom_ont_ids.include?(r["links"]["ontology"])} end + private + def self._create_user(username = nil) username ||= "testuser" u = LinkedData::Models::User.new({ - username: username, - email: "#{username}@example.com", - password: "a_password" - }) - u.save + username: username, + email: "#{username}@example.com", + password: "a_password" + }) + u.save rescue binding.pry u end end diff --git a/test/middleware/test_rack_attack.rb b/test/middleware/test_rack_attack.rb index 92b4d6369..540f8a983 100644 --- a/test/middleware/test_rack_attack.rb +++ b/test/middleware/test_rack_attack.rb @@ -5,7 +5,7 @@ RACK_CONFIG = File.join([settings.root, "config.ru"]) class TestRackAttack < TestCase - + def before_suite # Store app settings @@auth_setting = LinkedData.settings.enable_security @@ -40,7 +40,7 @@ def before_suite # Fork the process to create two servers. This isolates the Rack::Attack configuration, which makes other tests fail if included. @@pid1 = fork do require_relative '../../config/rack_attack' - Rack::Server.start( + Rackup::Server.start( config: RACK_CONFIG, Port: @@port1 ) @@ -50,7 +50,7 @@ def before_suite @@port2 = unused_port @@pid2 = fork do require_relative '../../config/rack_attack' - Rack::Server.start( + Rackup::Server.start( config: RACK_CONFIG, Port: @@port2 ) @@ -90,7 +90,7 @@ def test_throttling_limit # TODO: Upgrading rack-attack from 5 to 6 causes this test to fail with a 500 Internal Server error. # Project is currently pinned at 5.4.2. Investigate failure at the time we decide to upgrade. def test_throttling_limit_with_forwarding - limit = LinkedData::OntologiesAPI.settings.req_per_second_per_ip + limit = LinkedData::OntologiesAPI.settings.req_per_second_per_ip headers = {"Authorization" => "apikey token=#{@@user.apikey}", "X-Forwarded-For" => "1.2.3.6"} exception = assert_raises(OpenURI::HTTPError) do diff --git a/test/test_case.rb b/test/test_case.rb index 5e8265b84..0bffc0221 100644 --- a/test/test_case.rb +++ b/test/test_case.rb @@ -28,21 +28,24 @@ require 'multi_json' require 'oj' require 'json-schema' - +require 'minitest/reporters' +Minitest::Reporters.use! [Minitest::Reporters::SpecReporter.new(:color => true), Minitest::Reporters::MeanTimeReporter.new] MAX_TEST_REDIS_SIZE = 10_000 # Check to make sure you want to run if not pointed at localhost safe_hosts = Regexp.new(/localhost|-ut|ncbo-dev*|ncbo-unittest*/) + def safe_redis_hosts?(sh) return [LinkedData.settings.http_redis_host, - Annotator.settings.annotator_redis_host, - LinkedData.settings.goo_redis_host].select { |x| + Annotator.settings.annotator_redis_host, + LinkedData.settings.goo_redis_host].select { |x| x.match(sh) }.length == 3 end + unless LinkedData.settings.goo_host.match(safe_hosts) && - safe_redis_hosts?(safe_hosts) && - LinkedData.settings.search_server_url.match(safe_hosts) + safe_redis_hosts?(safe_hosts) && + LinkedData.settings.search_server_url.match(safe_hosts) print "\n\n================================== WARNING ==================================\n" print "** TESTS CAN BE DESTRUCTIVE -- YOU ARE POINTING TO A POTENTIAL PRODUCTION/STAGE SERVER **\n" print "Servers:\n" @@ -76,12 +79,14 @@ def count_pattern(pattern) def backend_4s_delete if count_pattern("?s ?p ?o") < 400000 - LinkedData::Models::Ontology.where.include(:acronym).each do |o| - query = "submissionAcronym:#{o.acronym}" - LinkedData::Models::Ontology.unindexByQuery(query) + puts 'clear backend & index' + raise StandardError, 'Too many triples in KB, does not seem right to run tests' unless count_pattern('?s ?p ?o') < 400000 + + graphs = Goo.sparql_query_client.query("SELECT DISTINCT ?g WHERE { GRAPH ?g { ?s ?p ?o . } }") + graphs.each_solution do |sol| + Goo.sparql_data_client.delete_graph(sol[:g]) end - LinkedData::Models::Ontology.indexCommit() - Goo.sparql_update_client.update("DELETE {?s ?p ?o } WHERE { ?s ?p ?o }") + LinkedData::Models::SubmissionStatus.init_enum LinkedData::Models::OntologyType.init_enum LinkedData::Models::OntologyFormat.init_enum @@ -107,18 +112,37 @@ def before_all end def after_all + self.class.disable_security after_suite super end + + def _run_suite(suite, type) + begin + backend_4s_delete + LinkedData::Models::Ontology.indexClear + LinkedData::Models::Class.indexClear + LinkedData::Models::OntologyProperty.indexClear + suite.before_suite if suite.respond_to?(:before_suite) + super(suite, type) + rescue Exception => e + puts e.message + puts e.backtrace.join("\n\t") + puts "Traced from:" + raise e + ensure + backend_4s_delete + suite.after_suite if suite.respond_to?(:after_suite) + end + end end + # All tests should inherit from this class. # Use 'rake test' from the command line to run tests. # See http://www.sinatrarb.com/testing.html for testing information class TestCase < AppUnit include Rack::Test::Methods - - def app Sinatra::Application end @@ -132,7 +156,7 @@ def app # @option options [TrueClass, FalseClass] :process_submission Parse the test ontology file def create_ontologies_and_submissions(options = {}) if options[:process_submission] && options[:process_options].nil? - options[:process_options] = { process_rdf: true, extract_metadata: false, generate_missing_labels: false } + options[:process_options] = { process_rdf: true, extract_metadata: false, generate_missing_labels: false } end LinkedData::SampleData::Ontology.create_ontologies_and_submissions(options) end @@ -157,13 +181,13 @@ def delete_goo_models(gooModelArray) # @param [String] jsonData a json string that will be parsed by MultiJson.load # @param [String] jsonSchemaString a json schema string that will be parsed by MultiJson.load # @param [boolean] list set it true for jsonObj array of items to validate against jsonSchemaString - def validate_json(jsonData, jsonSchemaString, list=false) + def validate_json(jsonData, jsonSchemaString, list = false) schemaVer = :draft3 jsonObj = MultiJson.load(jsonData) jsonSchema = MultiJson.load(jsonSchemaString) assert( - JSON::Validator.validate(jsonSchema, jsonObj, :list => list, :version => schemaVer), - JSON::Validator.fully_validate(jsonSchema, jsonObj, :list => list, :version => schemaVer, :validate_schema => true).to_s + JSON::Validator.validate(jsonSchema, jsonObj, list: list, version: schemaVer), + JSON::Validator.fully_validate(jsonSchema, jsonObj, list: list, version: schemaVer, validate_schema: true).to_s ) end @@ -187,26 +211,29 @@ def self.enable_security LinkedData.settings.enable_security = true end - def self.reset_security(old_security = @@old_security_setting) + def self.disable_security + LinkedData.settings.enable_security = false + end + + def self.reset_security(old_security = @@old_security_setting) LinkedData.settings.enable_security = old_security end # Ensure a user exists; return it. Safe to call from anywhere. - def create_user(username, email: nil, password: "password") + def self.create_user(username, email: nil, password: "password") user = User.new(username: username, email: email || "#{username}@example.org", password: password) user.save if user.valid? user end - def ensure_user(username, email: nil, password: "password") + def self.ensure_user(username, email: nil, password: "password") User.find(username).first || create_user(username, email: email, password: password) end - def delete_user(username) + def self.delete_user(username) User.find(username).first&.delete end - def self.make_admin(user) user.bring_remaining user.role = [LinkedData::Models::Users::Role.find(LinkedData::Models::Users::Role::ADMIN).first] @@ -227,6 +254,7 @@ def unused_port end private + def port_in_use?(port) server = TCPServer.new(port) server.close @@ -236,3 +264,4 @@ def port_in_use?(port) end end +