diff --git a/.dockerignore b/.dockerignore index 9c895ca99..db4a640cd 100644 --- a/.dockerignore +++ b/.dockerignore @@ -39,7 +39,7 @@ build .env !launchers/.env.connector -!launchers/.env.broker +!launchers/.env.catalog-crawler # Log files *.log diff --git a/.editorconfig b/.editorconfig index 5d2208c46..41861c3d0 100644 --- a/.editorconfig +++ b/.editorconfig @@ -22,6 +22,17 @@ indent_size = 2 [*.{yml,yaml}] indent_size = 2 +[*.java] +max_line_length = 140 +ij_continuation_indent_size = 8 +ij_java_blank_lines_after_imports = 1 +ij_java_blank_lines_after_package = 1 +ij_java_line_comment_add_space = true +ij_java_imports_layout = *,|,java.**,javax.**,|,$* +ij_java_class_count_to_use_import_on_demand = 999 +ij_java_doc_align_param_comments = false + + [{*.kt,*.kts}] ij_kotlin_imports_layout = *, java.**, javax.**, kotlin.**, ^ ij_kotlin_packages_to_use_import_on_demand = explicitly-none diff --git a/.env b/.env index 0aa50efab..e415c2283 100644 --- a/.env +++ b/.env @@ -3,4 +3,3 @@ EDC_IMAGE=ghcr.io/sovity/edc-dev:8.1.0 TEST_BACKEND_IMAGE=ghcr.io/sovity/test-backend:8.1.0 EDC_UI_IMAGE=ghcr.io/sovity/edc-ui:3.2.2 EDC_UI_ACTIVE_PROFILE=sovity-open-source -BROKER_IMAGE=ghcr.io/sovity/broker-server-dev:8.1.0 diff --git a/.env.dev b/.env.dev index c6574ad4f..498abf37b 100644 --- a/.env.dev +++ b/.env.dev @@ -3,4 +3,3 @@ EDC_IMAGE=ghcr.io/sovity/edc-dev:latest TEST_BACKEND_IMAGE=ghcr.io/sovity/test-backend:latest EDC_UI_IMAGE=ghcr.io/sovity/edc-ui:latest EDC_UI_ACTIVE_PROFILE=sovity-open-source -BROKER_IMAGE=ghcr.io/sovity/broker-server-dev:latest diff --git a/.github/ISSUE_TEMPLATE/release.md b/.github/ISSUE_TEMPLATE/release.md index 1e37fe6e0..466f65ea1 100644 --- a/.github/ISSUE_TEMPLATE/release.md +++ b/.github/ISSUE_TEMPLATE/release.md @@ -46,8 +46,6 @@ Feel free to edit this release checklist in-progress depending on what tasks nee the [docker-compose's .env file](https://github.com/sovity/edc-ce/blob/main/.env). - [ ] Set the version for `TEST_BACKEND_IMAGE` of the [docker-compose's .env file](https://github.com/sovity/edc-ce/blob/main/.env). - - [ ] Set the version for `BROKER_IMAGE` of - the [docker-compose's .env file](https://github.com/sovity/edc-ce/blob/main/.env). - [ ] Set the UI release version for `EDC_UI_IMAGE` of the [docker-compose's .env file](https://github.com/sovity/edc-ce/blob/main/.env). - [ ] If the Eclipse EDC version changed, update @@ -58,13 +56,10 @@ Feel free to edit this release checklist in-progress depending on what tasks nee - [ ] Validate the image - [ ] Pull the latest edc-dev image: `docker image pull ghcr.io/sovity/edc-dev:latest`. - [ ] Check that your image was built recently `docker image ls | grep ghcr.io/sovity/edc-dev`. - - [ ] Test the release `docker-compose.yaml` with `EDC_IMAGE=ghcr.io/sovity/edc-dev:latest` and `BROKER_IMAGE=ghcr.io/sovity/broker-server-dev:latest` (at minimum execute a transfer between the two connectors). + - [ ] Test the release `docker-compose.yaml` with `EDC_IMAGE=ghcr.io/sovity/edc-dev:latest` (at minimum execute a transfer between the two connectors). - EDC - [ ] Test with `EDC_UI_ACTIVE_PROFILE=sovity-open-source` - [ ] Test with `EDC_UI_ACTIVE_PROFILE=mds-open-source` - - Broker - - [ ] Validate that the EDC is scanned. - - [ ] Validate that the index is searchable. - [ ] Ensure with a `docker ps -a` that all containers are healthy, and not `healthy: starting` or `healthy: unhealthy`. - [ ] [Create a release](https://github.com/sovity/edc-ce/releases/new) - [ ] In `Choose the tag`, type your new release version in the format `vx.y.z` (for instance `v1.2.3`) then click `+Create new tag vx.y.z on release`. diff --git a/.github/actions/build-connector-image/action.yml b/.github/actions/build-connector-image/action.yml index e9d991b56..099207c05 100644 --- a/.github/actions/build-connector-image/action.yml +++ b/.github/actions/build-connector-image/action.yml @@ -21,7 +21,7 @@ inputs: description: "EDC Connector Name in launchers/connectors/{connector-name}" deployment-type: required: true - description: "Type of deployment: 'connector' or 'broker'" + description: "Type of deployment: 'connector' or 'catalog-crawler'" title: required: true description: "Docker Image Title" diff --git a/.github/markdown-link-checker-config.jq b/.github/markdown-link-checker-config.jq index 8aec895b1..e73dc13c3 100755 --- a/.github/markdown-link-checker-config.jq +++ b/.github/markdown-link-checker-config.jq @@ -7,7 +7,6 @@ {"pattern": "^https://www\\.linkedin\\.com"}, {"pattern": "https://(.*?)\\.azure\\.sovity\\.io"}, {"pattern": "http://edc2?:"}, - {"pattern": "^https?://broker:"}, {"pattern": "^https?://connector:"} ], "replacementPatterns": [ diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 55d057c58..06a600619 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -104,30 +104,30 @@ jobs: deployment-type: "connector" title: "Test Data Source / Data Sink" description: "Provides a minimal data source / data sink for E2E tests." - - name: "Docker Image: broker-server-dev" + - name: "Docker Image: catalog-crawler-dev" uses: ./.github/actions/build-connector-image with: registry-url: ${{ env.REGISTRY_URL }} registry-user: ${{ env.REGISTRY_USER }} registry-password: ${{ secrets.GITHUB_TOKEN }} image-base-name: ${{ env.IMAGE_BASE_NAME }} - image-name: "broker-server-dev" - connector-name: "broker-server-dev" - deployment-type: "broker" - title: "Broker Server (Dev)" - description: "sovity EDC Broker Server. This dev version contains no auth and can be used to quickly start a locally running Broker Server + Broker UI." - - name: "Docker Image: broker-server-ce" + image-name: "catalog-crawler-dev" + connector-name: "catalog-crawler-dev" + deployment-type: "catalog-crawler" + title: "Catalog Crawler (Dev)" + description: "sovity CE Catalog crawler for the sovity CE Authority Portal. This dev version contains no auth and can be used to quickly start a locally running Catalog Crawler." + - name: "Docker Image: catalog-crawler-ce" uses: ./.github/actions/build-connector-image with: registry-url: ${{ env.REGISTRY_URL }} registry-user: ${{ env.REGISTRY_USER }} registry-password: ${{ secrets.GITHUB_TOKEN }} image-base-name: ${{ env.IMAGE_BASE_NAME }} - image-name: "broker-server-ce" - connector-name: "broker-server-ce" - deployment-type: "broker" - title: "Broker Server (Community Edition)" - description: "sovity EDC Broker Server. Requires dataspace credentials to join an existing dataspace." + image-name: "catalog-crawler-ce" + connector-name: "catalog-crawler-ce" + deployment-type: "catalog-crawler" + title: "Catalog Crawler (Community Edition, DAPS)" + description: "sovity CE Catalog crawler for the sovity CE Authority Portal. Requires DAPS dataspace credentials to join an existing dataspace." ts-api-client-library: name: TS API Client Library runs-on: ubuntu-latest @@ -181,57 +181,3 @@ jobs: env: NODE_USER: richardtreier-sovity NODE_AUTH_TOKEN: ${{ secrets.SOVITY_EDC_CLIENT_NPM_AUTH }} - ts-broker-api-client-library: - runs-on: ubuntu-latest - timeout-minutes: 30 - permissions: - contents: read - packages: write - - steps: - - uses: FranzDiebold/github-env-vars-action@v2 - - uses: actions/checkout@v4 - - uses: actions/setup-java@v3 - with: - distribution: 'temurin' - java-version: '17' - cache: 'gradle' - - uses: actions/setup-node@v4 - with: - node-version: 16 - cache: 'npm' - registry-url: 'https://registry.npmjs.org' - cache-dependency-path: ./extensions/broker-server-api/client-ts/package-lock.json - - name: Generate openapi.yaml & Client Code - run: | - ./gradlew :extensions:broker-server-api:api:clean :extensions:broker-server-api:api:build -x test --no-daemon - env: - USERNAME: ${{ github.actor }} - TOKEN: ${{ secrets.GITHUB_TOKEN }} - - name: NPM Package Dist Tag & Version - working-directory: ./extensions/broker-server-api/client-ts - run: | - if [ "${{ startsWith(github.ref, 'refs/tags/') }}" == "true" ]; then - # Full Release - VERSION="${GITHUB_REF#refs/tags/v}" - DIST_TAG=latest - else - VERSION="0.$(date '+%Y%m%d.%H%M%S')-main-$CI_SHA_SHORT" - DIST_TAG=main - fi - npm version $VERSION - echo "DIST_TAG=$DIST_TAG" >> $GITHUB_ENV - - name: Build NPM Library - working-directory: ./extensions/broker-server-api/client-ts - run: | - npm ci && npm run build - - name: Publish NPM Library - if: github.ref == 'refs/heads/main' || github.ref == 'refs/tags/v*' - working-directory: ./extensions/broker-server-api/client-ts - run: | - npm set //registry.npmjs.org/:_authToken $NODE_AUTH_TOKEN - npm set //registry.npmjs.org/:username $NODE_USER - npm publish --access public --tag "${{ env.DIST_TAG }}" - env: - NODE_USER: richardtreier-sovity - NODE_AUTH_TOKEN: ${{ secrets.SOVITY_BROKER_CLIENT_NPM_AUTH }} diff --git a/.github/workflows/license_scan.yml b/.github/workflows/license_scan.yml index 84d865164..fff50cc76 100644 --- a/.github/workflows/license_scan.yml +++ b/.github/workflows/license_scan.yml @@ -31,8 +31,6 @@ jobs: run: cd extensions/wrapper/clients/typescript-client && npm clean-install - name: npm install (typescript-client-example) run: cd extensions/wrapper/clients/typescript-client-example && npm clean-install - - name: npm install (client-ts) - run: cd extensions/broker-server-api/client-ts && npm clean-install - name: Run license scanner uses: aquasecurity/trivy-action@master with: diff --git a/.gitignore b/.gitignore index 44982a20d..c20b5c02c 100644 --- a/.gitignore +++ b/.gitignore @@ -40,7 +40,7 @@ build **/.env !.env !launchers/.env.connector -!launchers/.env.broker +!launchers/.env.catalog-crawler # Log files *.log diff --git a/CHANGELOG.md b/CHANGELOG.md index 4507377d1..06b4f7b35 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,12 +7,14 @@ please see [changelog_updates.md](docs/dev/changelog_updates.md). ### Overview -### EDC UI - -### EDC Extensions and Broker +### Detailed Changes #### Major Changes +- The Broker has been removed in favor of the Authority Portal and the new Deployment Unit, the "Data Catalog Crawler": + - Each "Data Catalog Crawler" connects to an existing Authority Portal Deployment's DB. + - Each "Data Catalog Crawler" is responsible for crawling exactly one environment. + - The Data Catalog functionality of the Broker has been integrated into the Authority Portal. - API Wrapper UI API: Moved to well-typed data sources, breaking changes to the asset model and API. #### Minor Changes @@ -25,8 +27,14 @@ please see [changelog_updates.md](docs/dev/changelog_updates.md). ### Deployment Migration Notes -The database migration system has been moved from multiple migration history tables to a single one. Although this -process has been extensively tested in the enterprise edition already, it should be tested once more on a copy of a productive connector. +- Connector: + - The database migration system has been moved from multiple migration history tables to a single one. Although this + process has been extensively tested in the enterprise edition already, it should be tested once more on a copy of a productive connector. +- Broker: + - The broker has been removed. For Authority Portal users, please check out the new + [Data Catalog Crawler Productive Deployment Guide](docs/deployment-guide/goals/catalog-crawler-production/README.md). + - Any previous broker deployment's database is not required anymore. + - Please care that only some environment variables look similar. It is recommended to create fresh deployments. ## [8.1.0] - 2024-06-14 @@ -42,7 +50,7 @@ Support for Multiplicity Constraints in the API Wrapper. #### Minor Changes -- API Wrapper +- API Wrapper - Support for Multiplicity Constraints (https://github.com/sovity/edc-ce/issues/968) - Providing `Prop` class from `json-and-jsonld-utils` to the java-client to make relevant Constants available @@ -88,7 +96,6 @@ The functionalities of each part, Broker and Extensions, on this release, is the - Broker CE: `ghcr.io/sovity/broker-server-ce:8.0.0` - Connector UI Docker Image: `ghcr.io/sovity/edc-ui:3.2.2` - ## [7.5.0] - 2024-05-16 ### Overview @@ -114,9 +121,9 @@ Security updates #### Compatible Versions - Connector Backend Docker Images: - - Dev EDC: `ghcr.io/sovity/edc-dev:7.5.0` - - sovity EDC CE: `ghcr.io/sovity/edc-ce:7.5.0` - - MDS EDC CE: `ghcr.io/sovity/edc-ce-mds:7.5.0` + - Dev EDC: `ghcr.io/sovity/edc-dev:7.5.0` + - sovity EDC CE: `ghcr.io/sovity/edc-ce:7.5.0` + - MDS EDC CE: `ghcr.io/sovity/edc-ce-mds:7.5.0` - Connector UI Docker Image: `ghcr.io/sovity/edc-ui:3.2.2` - Connector UI Release: https://github.com/sovity/edc-ui/releases/tag/v3.2.2 @@ -146,9 +153,9 @@ Contains DB migrations, DB backups advised. #### Compatible Versions - Connector Backend Docker Images: - - Dev EDC: `ghcr.io/sovity/edc-dev:7.4.2` - - sovity EDC CE: `ghcr.io/sovity/edc-ce:7.4.2` - - MDS EDC CE: `ghcr.io/sovity/edc-ce-mds:7.4.2` + - Dev EDC: `ghcr.io/sovity/edc-dev:7.4.2` + - sovity EDC CE: `ghcr.io/sovity/edc-ce:7.4.2` + - MDS EDC CE: `ghcr.io/sovity/edc-ce-mds:7.4.2` - Connector UI Docker Image: `ghcr.io/sovity/edc-ui:3.2.2` - Connector UI Release: https://github.com/sovity/edc-ui/releases/tag/v3.2.2 diff --git a/archived/broker/README.md b/archived/broker/README.md deleted file mode 100644 index 93e9ed983..000000000 --- a/archived/broker/README.md +++ /dev/null @@ -1,246 +0,0 @@ - - - - - -
-
- -Logo - - -

Broker Server

-

-Broker Backend & EDC Extensions. -
-Report Bug -· -Request Feature -

-
- - -
- Table of Contents -
    -
  1. About The Project
  2. -
  3. Development
  4. -
  5. Releasing
  6. -
  7. Deployment
  8. -
  9. License
  10. -
  11. Contact
  12. -
-
- -## About The Project - -[Eclipse Dataspace Components](https://github.com/eclipse-edc) (EDC) is a framework -for building dataspaces, exchanging data securely with ensured data sovereignty. - -[sovity](https://sovity.de/) extends the EDC Connector's functionality with extensions to offer -enterprise-ready managed services like "Connector-as-a-Service", out-of-the-box fully configured DAPS -and integrations to existing other dataspace technologies. - -An IDS Broker is a central component of a dataspace that operates on the IDS protocol, that aggregates and indexes -connectors and data offers. - -This IDS Broker is written on basis of the EDC and should be used in tandem with the Broker UI. - -

(back to top)

- -## Development - -### Local Development - -#### Local Backend Development - -For local backend development, access to the GitHub Maven Registry is required. - -To access the GitHub Maven Registry you need to provide the following properties, e.g. by providing -a `~/.gradle/gradle.properties`. - -```properties -gpr.user={your github username} -gpr.key={your github pat with packages.read} -``` - -Developing the Broker Backend tests are used to validate functionality: - -- There are Integration Tests using the Broker Server Java Client Library for testing API Endpoints of a running - backend. -- There are Integration Tests using the Broker Server Java Client Library and sovity EDC Extensions to integration - test the Broker with a running EDC where communication works through the Data Space Protocol (DSP). -- There are Unit Tests with Mockito for testing local complexity, e.g. mappers, data structures, utilities. - -

(back to top)

- -#### Local UI Development - -The Broker UI is a profile `broker` of the [EDC UI](https://github.com/sovity/edc-ui): - -The Broker UI depends on the NPM -Package [@sovity/broker-server-client](https://www.npmjs.com/package/@sovity.de/broker-server-client) built on the main -branch or on releases. - -Local Broker UI Development can start with the type-safe broker server fake backend once the Client Library version is -bumped to contain the up-to-date API Models. - -

(back to top)

- -### Local E2E Development - -There is currently no support for Local E2E Development (a locally running backend build server and a locally running -frontend build server). - -For debugging UI issues, however, the UI can be manually configured to use a live backend, e.g. one started via -the [docker-compose.yaml](#local-demo). - -

(back to top)

- -### Local Demo - -There is a [docker-compose.yaml](../../docker-compose.yaml) that starts a broker and a connector. - -At release time it is pinned down to the release versions. - -Mid-development it might be un-pinned back to latest versions. - -| | Broker | Conncetor | -|---------------------|------------------------------------------------------------------|:-----------------------------------------------------------------------------| -| Homepage | http://localhost:11000 | http://localhost:22000 | -| Management Endpoint | http://localhost:11002/api/management | http://localhost:22002/api/management | -| Management API Key | `ApiKeyDefaultValue` | `ApiKeyDefaultValue` | -| Connector Endpoint | http://broker:11003/api/dsp
Requires Docker Compose Network | http://connector:22003/api/dsp
Requires Docker Compose Network | - -

(back to top)

- -## Releasing - -[Create a Release Issue](https://github.com/sovity/edc-ce/issues/new?assignees=&labels=task%2Frelease%2Cscope%2Fmds&projects=&template=release.md&title=Release+x.x.x) and follow the instructions. - -

(back to top)

- -## Deployment - -### Deployment Units - -| Deployment Unit | Version / Details | -|----------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| Reverse Proxy that merges the UI+Backend and removes the ports | (deployment specific) | -| Postgresql | 15 or compatible version | -| Broker Backend | broker-server-ce, see [CHANGELOG.md](../../CHANGELOG.md) for version 8+ or [former CHANGELOG.md](https://github.com/sovity/edc-broker-server-extension/blob/v4.2.0/CHANGELOG.md) for compatible versions. | -| Broker UI | edc-ui, see [CHANGELOG.md](../../CHANGELOG.md) for version 8+ or [former CHANGELOG.md](https://github.com/sovity/edc-broker-server-extension/blob/v4.2.0/CHANGELOG.md) for compatible versions. | - -### Configuration - -There is a [docker-compose.yaml](../../docker-compose.yaml) to try out the broker locally. However, a productive release will require a few more configuration options, so you should only use it to check if the released version is roughly working or if it's broken. - -#### Reverse Proxy Configuration - -- The broker is meant to be served via TLS/HTTPS. -- The broker is meant to be deployed with a reverse proxy merging the following ports: - - The UI's `8080` port. - - The Backend's `11002` port. - - The Backend's `11003` port. -- The mapping should look like this: - - `https://[MY_EDC_FQDN]/backend/api/dsp` -> `broker-backend:11003/backend/api/dsp` - - `https://[MY_EDC_FQDN]/backend/api/management` -> `broker-backend:11002/backend/api/management` - - All other requests -> `broker-ui:8080` - -#### Backend Configuration - -A productive configuration will require you to join a DAPS. - -For that you will need a SKI/AKI ClientID. Please refer -to [edc-extension's Getting Started Guide](https://github.com/sovity/edc-ce/tree/main/docs/getting-started#faq) -on how to generate one. - -The DAPS needs to contain the claim `referringConnector=broker` for the broker. -The expected value `broker` could be overridden by specifying a different value for `MY_EDC_PARTICIPANT_ID`. - -```yaml -# Required: Fully Qualified Domain Name -MY_EDC_FQDN: "example.com" - -# Required: DB -MY_EDC_JDBC_URL: jdbc:postgresql://broker-postgresql:5432/edc -MY_EDC_JDBC_USER: edc -MY_EDC_JDBC_PASSWORD: edc - -# Required: List of EDCs to fetch -EDC_BROKER_SERVER_KNOWN_CONNECTORS: "https://connector-a/api/dsp,https://connector-b/api/dsp" - -# List of Data Space Names for special Connectors (default: '') -EDC_BROKER_SERVER_KNOWN_DATASPACE_CONNECTORS: "Mobilithek=https://some-connector/api/dsp,OtherDataspace=https://some-other-connector/api/dsp" - -# Required: DAPS credentials -EDC_OAUTH_TOKEN_URL: 'https://daps.test.mobility-dataspace.eu/token' -EDC_OAUTH_PROVIDER_JWKS_URL: 'https://daps.test.mobility-dataspace.eu/jwks.json' -EDC_OAUTH_CLIENT_ID: '_your SKI/AKI_' -EDC_KEYSTORE: '_your keystore file_' # Needs to be available as file in the running container -EDC_KEYSTORE_PASSWORD: '_your keystore password_' -EDC_OAUTH_CERTIFICATE_ALIAS: 1 -EDC_OAUTH_PRIVATE_KEY_ALIAS: 1 - -# Required: Management API Key -EDC_API_AUTH_KEY: "ApiKeyDefaultValue" - -# Required: Admin Api Key -EDC_BROKER_SERVER_ADMIN_API_KEY: DefaultBrokerServerAdminApiKey -``` - -All pre-configured config values for either the broker server or the underlying EDC can be found -in [launchers/.env.broker](../../launchers/.env.broker). - -#### UI Configuration - -```yaml -# Required: Profile -EDC_UI_ACTIVE_PROFILE: broker - -# Required: Management API URL -EDC_UI_MANAGEMENT_API_URL: https://my-broker.com/backend/api/management - -# Required: Management API Key -EDC_UI_MANAGEMENT_API_KEY: "ApiKeyDefaultValue" -``` - -#### Adding Connectors at runtime - -Connectors can be dynamically added at runtime by using the following endpoint: - -```shell script -# Response should be 204 No Content -curl --request PUT \ - --url 'http://localhost:11002/backend/api/management/wrapper/broker/connectors?adminApiKey=DefaultBrokerServerAdminApiKey' \ - --header 'Content-Type: application/json' \ - --header 'x-api-key: ApiKeyDefaultValue' \ - --data '["https://some-new-connector/api/dsp", "https://some-other-new-connector/api/dsp"]' -``` - -#### Removing Connectors at runtime - -Connectors can be dynamically removed at runtime by using the following endpoint: - -```shell script -# Response should be 204 No Content -curl --request DELETE \ - --url 'http://localhost:11002/backend/api/management/wrapper/broker/connectors?adminApiKey=DefaultBrokerServerAdminApiKey' \ - --header 'Content-Type: application/json' \ - --header 'x-api-key: ApiKeyDefaultValue' \ - --data '["https://some-connector-to-be-removed/api/dsp", "https://some-other-connector-to-be-removed/api/dsp"]' -``` - -

(back to top)

- -## License - -Distributed under the Apache 2.0 License. See `LICENSE` for more information. - -

(back to top)

- -## Contact - -contact@sovity.de - -

(back to top)

diff --git a/build.gradle.kts b/build.gradle.kts index 02b11e740..f9ff62348 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -122,6 +122,12 @@ subprojects { } } + tasks.register("printClasspath") { + group = libs.versions.edcGroup.get() + description = "The EdcRuntimeExtension JUnit Extension requires the gradle task 'printClasspath'" + println(sourceSets.main.get().runtimeClasspath.asPath); + } + java { withSourcesJar() withJavadocJar() diff --git a/connector/README.md b/connector/README.md deleted file mode 100644 index 95b296ad4..000000000 --- a/connector/README.md +++ /dev/null @@ -1,39 +0,0 @@ - -
-
- - Logo - - -

Broker Server:
Docker Images

- -

- Report Bug - · - Request Feature -

-
- -## Image Variants - -The Broker Server is built in different variants: - -| Docker Image | Type | Purpose | Features | -|----------------------------------------------------------------------------------------|-------------------|--------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------| -| [broker-server-dev](https://github.com/sovity/edc-ce/pkgs/container/broker-server-dev) | Development | | | -| [broker-server-ce](https://github.com/sovity/edc-ce/pkgs/container/broker-server-ce) | Community Edition | | | - -## Image Tags - -| Tag | Description | -|---------------|-----------------------------------| -| latest / main | latest version of our main branch | -| release | latest release of this repository | - -## License - -Apache License 2.0 - see [LICENSE](../LICENSE) - -## Contact - -sovity GmbH - contact@sovity.de diff --git a/docker-compose-dev.yaml b/docker-compose-dev.yaml index 0789fdcfb..01d93ec40 100644 --- a/docker-compose-dev.yaml +++ b/docker-compose-dev.yaml @@ -101,53 +101,6 @@ services: ports: - '33001:11001' - broker-ui: - image: ${EDC_UI_IMAGE} - ports: - - '44000:8080' - environment: - EDC_UI_ACTIVE_PROFILE: broker - EDC_UI_MANAGEMENT_API_URL: http://localhost:44002/backend/api/management - EDC_UI_MANAGEMENT_API_KEY: ApiKeyDefaultValue - NGINX_ACCESS_LOG: off - - broker: - image: ${BROKER_IMAGE} - depends_on: - broker-postgresql: - condition: service_healthy - edc: - condition: service_started - edc2: - condition: service_started - environment: - EDC_BROKER_SERVER_KNOWN_CONNECTORS: "http://edc:11003/api/dsp,http://edc2:11003/api/dsp" - EDC_BROKER_SERVER_KNOWN_DATASPACE_CONNECTORS: "Mobilithek=https://some-other-connector/api/dsp" - - # Hide offline data offers after 1 minute in dev - EDC_BROKER_SERVER_HIDE_OFFLINE_DATA_OFFERS_AFTER: "PT1M" - - MY_EDC_FQDN: "broker" - EDC_API_AUTH_KEY: ApiKeyDefaultValue - - MY_EDC_JDBC_URL: jdbc:postgresql://broker-postgresql:5432/edc - MY_EDC_JDBC_USER: edc - MY_EDC_JDBC_PASSWORD: edc - - # docker compose local dev environment overrides (don't use with non-dev images) - MY_EDC_PROTOCOL: "http://" - EDC_DSP_CALLBACK_ADDRESS: http://broker:44003/backend/api/dsp - EDC_WEB_REST_CORS_ENABLED: 'true' - EDC_WEB_REST_CORS_HEADERS: 'origin,content-type,accept,authorization,x-api-key' - EDC_WEB_REST_CORS_ORIGINS: '*' - EDC_AGENT_IDENTITY_KEY: 'client_id' # required for Mock IAM to work - ports: - - '44001:11001' - - '44002:11002' - - '44003:11003' - - '44004:11004' - - '44005:5005' - postgresql: image: docker.io/bitnami/postgresql:15 restart: always @@ -182,27 +135,8 @@ services: timeout: 5s retries: 10 - broker-postgresql: - image: docker.io/bitnami/postgresql:15 - restart: always - environment: - POSTGRESQL_USERNAME: edc - POSTGRESQL_PASSWORD: edc - POSTGRESQL_DATABASE: edc - ports: - - '54323:5432' - volumes: - - 'broker-postgresql:/bitnami/postgresql' - healthcheck: - test: ["CMD-SHELL", "pg_isready -U edc"] - interval: 1s - timeout: 5s - retries: 10 - volumes: postgresql: driver: local postgresql2: driver: local - broker-postgresql: - driver: local diff --git a/docker-compose.yaml b/docker-compose.yaml index 0789fdcfb..01d93ec40 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -101,53 +101,6 @@ services: ports: - '33001:11001' - broker-ui: - image: ${EDC_UI_IMAGE} - ports: - - '44000:8080' - environment: - EDC_UI_ACTIVE_PROFILE: broker - EDC_UI_MANAGEMENT_API_URL: http://localhost:44002/backend/api/management - EDC_UI_MANAGEMENT_API_KEY: ApiKeyDefaultValue - NGINX_ACCESS_LOG: off - - broker: - image: ${BROKER_IMAGE} - depends_on: - broker-postgresql: - condition: service_healthy - edc: - condition: service_started - edc2: - condition: service_started - environment: - EDC_BROKER_SERVER_KNOWN_CONNECTORS: "http://edc:11003/api/dsp,http://edc2:11003/api/dsp" - EDC_BROKER_SERVER_KNOWN_DATASPACE_CONNECTORS: "Mobilithek=https://some-other-connector/api/dsp" - - # Hide offline data offers after 1 minute in dev - EDC_BROKER_SERVER_HIDE_OFFLINE_DATA_OFFERS_AFTER: "PT1M" - - MY_EDC_FQDN: "broker" - EDC_API_AUTH_KEY: ApiKeyDefaultValue - - MY_EDC_JDBC_URL: jdbc:postgresql://broker-postgresql:5432/edc - MY_EDC_JDBC_USER: edc - MY_EDC_JDBC_PASSWORD: edc - - # docker compose local dev environment overrides (don't use with non-dev images) - MY_EDC_PROTOCOL: "http://" - EDC_DSP_CALLBACK_ADDRESS: http://broker:44003/backend/api/dsp - EDC_WEB_REST_CORS_ENABLED: 'true' - EDC_WEB_REST_CORS_HEADERS: 'origin,content-type,accept,authorization,x-api-key' - EDC_WEB_REST_CORS_ORIGINS: '*' - EDC_AGENT_IDENTITY_KEY: 'client_id' # required for Mock IAM to work - ports: - - '44001:11001' - - '44002:11002' - - '44003:11003' - - '44004:11004' - - '44005:5005' - postgresql: image: docker.io/bitnami/postgresql:15 restart: always @@ -182,27 +135,8 @@ services: timeout: 5s retries: 10 - broker-postgresql: - image: docker.io/bitnami/postgresql:15 - restart: always - environment: - POSTGRESQL_USERNAME: edc - POSTGRESQL_PASSWORD: edc - POSTGRESQL_DATABASE: edc - ports: - - '54323:5432' - volumes: - - 'broker-postgresql:/bitnami/postgresql' - healthcheck: - test: ["CMD-SHELL", "pg_isready -U edc"] - interval: 1s - timeout: 5s - retries: 10 - volumes: postgresql: driver: local postgresql2: driver: local - broker-postgresql: - driver: local diff --git a/docs/api/sovity-edc-api-wrapper.yaml b/docs/api/sovity-edc-api-wrapper.yaml index 8c5292975..13d5135d1 100644 --- a/docs/api/sovity-edc-api-wrapper.yaml +++ b/docs/api/sovity-edc-api-wrapper.yaml @@ -524,11 +524,11 @@ components: DataSourceType: type: string description: Supported Data Source Types by UiDataSource + default: CUSTOM enum: - HTTP_DATA - ON_REQUEST - CUSTOM - default: CUSTOM SecretValue: type: object properties: @@ -736,6 +736,7 @@ components: UiDataSourceHttpDataMethod: type: string description: Supported HTTP Methods by UiDataSource + default: GET enum: - GET - POST @@ -743,7 +744,6 @@ components: - PATCH - DELETE - OPTIONS - default: GET UiDataSourceOnRequest: required: - contactEmail @@ -1323,11 +1323,7 @@ components: items: $ref: '#/components/schemas/ContractAgreementTransferProcess' terminationStatus: - type: string - description: Contract Agreement's Termination Status - enum: - - ONGOING - - TERMINATED + $ref: '#/components/schemas/ContractTerminationStatus' terminationInformation: $ref: '#/components/schemas/ContractAgreementTerminationInfo' description: Contract Agreement for Contract Agreement Page @@ -1353,6 +1349,7 @@ components: - detail - reason - terminatedAt + - terminatedBy type: object properties: terminatedAt: @@ -1367,6 +1364,8 @@ components: type: string description: Detailed message from the terminating party about why the contract was terminated. + terminatedBy: + $ref: '#/components/schemas/ContractTerminatedBy' description: Contract's agreement metadata ContractAgreementTransferProcess: required: @@ -1388,6 +1387,19 @@ components: type: string description: Error Message description: A Contract Agreement's Transfer Process + ContractTerminatedBy: + type: string + description: Whether the contract termination was initiated by this EDC or a + counterparty EDC. + enum: + - SELF + - COUNTERPARTY + ContractTerminationStatus: + type: string + description: The contract termination status + enum: + - ONGOING + - TERMINATED TransferProcessSimplifiedState: type: string description: Simplified Transfer Process State to be used in UI @@ -1416,13 +1428,8 @@ components: ContractAgreementPageQuery: type: object properties: - status: - type: string - description: Optionally filter the resulting contract agreements by their - termination status. - enum: - - ONGOING - - TERMINATED + terminationStatus: + $ref: '#/components/schemas/ContractTerminationStatus' description: Filters for querying a Contract Contract Agreement Page ContractDefinitionEntry: required: diff --git a/docs/deployment-guide/goals/broker-production/README.md b/docs/deployment-guide/goals/broker-production/README.md deleted file mode 100644 index dbc3da385..000000000 --- a/docs/deployment-guide/goals/broker-production/README.md +++ /dev/null @@ -1,130 +0,0 @@ -# Broker Productive Deployment Guide - -## About this Guide - -This is a productive deployment guide for self-hosting a functional sovity Broker. - -## Deployment Units - -| Deployment Unit | Version / Details | -|----------------------------------------------------------------|-----------------------------------------------------------------------------------------| -| Reverse Proxy that merges the UI+Backend and removes the ports | (deployment specific) | -| Postgresql | 15 or compatible version | -| Broker Backend | broker-server-ce, see [CHANGELOG.md](../../../../CHANGELOG.md) for compatible versions. | -| Broker UI | edc-ui, see [CHANGELOG.md](../../../../CHANGELOG.md) for compatible versions. | - -### Configuration - -There is a [docker-compose.yaml](../../../../docker-compose.yaml) to try out the broker locally. -However, a productive release will require a few more configuration options, -so you should only use it to check if the released version is roughly working or if it's broken. - -#### Reverse Proxy Configuration - -- The broker is meant to be served via TLS/HTTPS. -- The broker is meant to be deployed with a reverse proxy merging the following ports: - - The UI's `8080` port. - - The Backend's `11002` port. - - The Backend's `11003` port. -- The mapping should look like this: - - `https://[MY_EDC_FQDN]/backend/api/dsp` -> `broker-backend:11003/backend/api/dsp` - - `https://[MY_EDC_FQDN]/backend/api/management` -> `broker-backend:11002/backend/api/management` - - All other requests -> `broker-ui:8080` - -#### Backend Configuration - -A productive configuration will require you to join a DAPS. - -For that you will need a SKI/AKI ClientID. Please refer -to [edc-extension's Getting Started Guide](https://github.com/sovity/edc-ce/tree/main/docs/getting-started#faq) -on how to generate one. - -The DAPS needs to contain the claim `referringConnector=broker` for the broker. -The expected value `broker` could be overridden by specifying a different value for `MY_EDC_PARTICIPANT_ID`. - -```yaml -# Required: Fully Qualified Domain Name -MY_EDC_FQDN: "example.com" - -# Required: DB -MY_EDC_JDBC_URL: jdbc:postgresql://broker-postgresql:5432/edc -MY_EDC_JDBC_USER: edc -MY_EDC_JDBC_PASSWORD: edc - -# Required: List of EDCs to fetch -EDC_BROKER_SERVER_KNOWN_CONNECTORS: "https://connector-a/api/dsp,https://connector-b/api/dsp" - -# List of Data Space Names for special Connectors (default: '') -EDC_BROKER_SERVER_KNOWN_DATASPACE_CONNECTORS: "Mobilithek=https://some-connector/api/dsp,OtherDataspace=https://some-other-connector/api/dsp" - -# Required: DAPS credentials -EDC_OAUTH_TOKEN_URL: 'https://daps.test.mobility-dataspace.eu/token' -EDC_OAUTH_PROVIDER_JWKS_URL: 'https://daps.test.mobility-dataspace.eu/jwks.json' -EDC_OAUTH_CLIENT_ID: '_your SKI/AKI_' -EDC_KEYSTORE: '_your keystore file_' # Needs to be available as file in the running container -EDC_KEYSTORE_PASSWORD: '_your keystore password_' -EDC_OAUTH_CERTIFICATE_ALIAS: 1 -EDC_OAUTH_PRIVATE_KEY_ALIAS: 1 - -# Required: Management API Key -EDC_API_AUTH_KEY: "ApiKeyDefaultValue" - -# Required: Admin Api Key -EDC_BROKER_SERVER_ADMIN_API_KEY: DefaultBrokerServerAdminApiKey -``` - -All pre-configured config values for either the broker server or the underlying EDC can be found -in [launcher/.env.broker](../../../../launchers/.env.broker). - -#### UI Configuration - -```yaml -# Required: Profile -EDC_UI_ACTIVE_PROFILE: broker - -# Required: Management API URL -EDC_UI_MANAGEMENT_API_URL: https://my-broker.com/backend/api/management - -# Required: Management API Key -EDC_UI_MANAGEMENT_API_KEY: "ApiKeyDefaultValue" -``` - -#### Adding Connectors at runtime - -Connectors can be dynamically added at runtime by using the following endpoint: - -```shell script -# Response should be 204 No Content -curl --request PUT \ - --url 'http://localhost:11002/backend/api/management/wrapper/broker/connectors?adminApiKey=DefaultBrokerServerAdminApiKey' \ - --header 'Content-Type: application/json' \ - --header 'x-api-key: ApiKeyDefaultValue' \ - --data '["https://some-new-connector/api/dsp", "https://some-other-new-connector/api/dsp"]' -``` - -#### Removing Connectors at runtime - -Connectors can be dynamically removed at runtime by using the following endpoint: - -```shell script -# Response should be 204 No Content -curl --request DELETE \ - --url 'http://localhost:11002/backend/api/management/wrapper/broker/connectors?adminApiKey=DefaultBrokerServerAdminApiKey' \ - --header 'Content-Type: application/json' \ - --header 'x-api-key: ApiKeyDefaultValue' \ - --data '["https://some-connector-to-be-removed/api/dsp", "https://some-other-connector-to-be-removed/api/dsp"]' -``` - -

(back to top)

- -## License - -Distributed under the Apache 2.0 License. See `LICENSE` for more information. - -

(back to top)

- -## Contact - -contact@sovity.de - -

(back to top)

diff --git a/docs/deployment-guide/goals/catalog-crawler-production/README.md b/docs/deployment-guide/goals/catalog-crawler-production/README.md new file mode 100644 index 000000000..5bbbddecf --- /dev/null +++ b/docs/deployment-guide/goals/catalog-crawler-production/README.md @@ -0,0 +1,55 @@ +# Catalog Crawler Productive Deployment Guide + +## About this Guide + +This is a productive deployment guide for self-hosting a single [catalog crawler](../../../../extensions/catalog-crawler/README.md). + +One catalog crawler per Authority Portal Deployment Environment must be deployed. + +## Deployment Units + +| Deployment Unit | Version / Details | +|-----------------|---------------------------------------------------------------------------------------------------------| +| Catalog Crawler | see the changelog for available versions. See the Authority Portal's Changelog for compatible versions. | + +#### Reverse Proxy Configuration + +- The catalog crawler is meant to be served via TLS/HTTPS. +- The catalog crawler is meant to be deployed with a reverse proxy terminating TLS / providing HTTPS. +- All requests are meant to be redirected to the deployment's `11003` port. + +#### Catalog Crawler Configuration + +A productive configuration will require you to join a DAPS. + +For that you will need a SKI/AKI client ID. Please refer +to [edc-extension's Getting Started Guide](https://github.com/sovity/edc-ce/tree/main/docs/getting-started#faq) +on how to generate one. + +The DAPS needs to contain the claim `referringConnector=broker` for the broker. +The expected value `broker` could be overridden by specifying a different value for `MY_EDC_PARTICIPANT_ID`. + +```yaml +# Required: Fully Qualified Domain Name +MY_EDC_FQDN: "crawler.test.example.com" + +# Required: Authority Portal Environment ID +CRAWLER_ENVIRONMENT_ID: test + +# Required: Authority Portal Postgresql DB Access +CRAWLER_DB_JDBC_URL: jdbc:postgresql://authority-portal:5432/portal +CRAWLER_DB_JDBC_USER: portal +CRAWLER_DB_JDBC_PASSWORD: portal + +# Required: DAPS credentials +EDC_OAUTH_TOKEN_URL: 'https://daps.test.mobility-dataspace.eu/token' +EDC_OAUTH_PROVIDER_JWKS_URL: 'https://daps.test.mobility-dataspace.eu/jwks.json' +EDC_OAUTH_CLIENT_ID: '_your SKI/AKI_' +EDC_KEYSTORE: '_your keystore file_' # Needs to be available as file in the running container +EDC_KEYSTORE_PASSWORD: '_your keystore password_' +EDC_OAUTH_CERTIFICATE_ALIAS: 1 +EDC_OAUTH_PRIVATE_KEY_ALIAS: 1 +``` + +All pre-configured config values for either the catalog crawler can be found +in [launcher/.env.catalog-crawler](../../../../launchers/.env.catalog-crawler). diff --git a/docs/deployment-guide/goals/local-demo/README.md b/docs/deployment-guide/goals/local-demo/README.md index fe90159a3..d52d6c1f5 100644 --- a/docs/deployment-guide/goals/local-demo/README.md +++ b/docs/deployment-guide/goals/local-demo/README.md @@ -52,15 +52,13 @@ EDC_UI_ACTIVE_PROFILE=mds-open-source docker compose up ## Quick Start: Default Configuration -The default configuration launches two local EDC Connectors and a Broker with the following credentials: - -| | First Connector | Second Connector | Broker | -|---------------------|---------------------------------------------------------------|:---------------------------------------------------------------|------------------------------------------------------------------| -| Homepage | http://localhost:11000 | http://localhost:22000 | http://localhost:44000 | -| Management Endpoint | http://localhost:11002/api/management | http://localhost:22002/api/management | http://localhost:44002/api/management | -| Management API Key | `ApiKeyDefaultValue` | `ApiKeyDefaultValue` | `ApiKeyDefaultValue` | -| Connector Endpoint | http://edc:11003/api/dsp
Requires Docker Compose Network | http://edc2:11003/api/dsp
Requires Docker Compose Network | http://broker:11003/api/dsp
Requires Docker Compose Network | - -The Broker is configured to scan both connectors. +The default configuration launches two local EDC Connectors with the following credentials: + +| | First Connector | Second Connector | +|---------------------|---------------------------------------------------------------|:---------------------------------------------------------------| +| Homepage | http://localhost:11000 | http://localhost:22000 | +| Management Endpoint | http://localhost:11002/api/management | http://localhost:22002/api/management | +| Management API Key | `ApiKeyDefaultValue` | `ApiKeyDefaultValue` | +| Connector Endpoint | http://edc:11003/api/dsp
Requires Docker Compose Network | http://edc2:11003/api/dsp
Requires Docker Compose Network |

(back to top)

diff --git a/docs/deployment-guide/goals/production/4.2.0/README.md b/docs/deployment-guide/goals/production/4.2.0/README.md index 59adef4aa..ee9f58d48 100644 --- a/docs/deployment-guide/goals/production/4.2.0/README.md +++ b/docs/deployment-guide/goals/production/4.2.0/README.md @@ -171,13 +171,12 @@ You can use a script (if you're on WSL or Linux) to generate the SKI, AKI and jk No, locally run connectors cannot exchange data with online connectors. A connector must have a proper URL + configuration and be accessible from the data provider via REST calls. -### (MDS Only) Can I disable the Broker- and/or ClearingHouse-Client-Extensions dynamically? +### (MDS Only) Can I disable the ClearingHouse-Client-Extensions dynamically? Yes, if the two extensions are included, they can still be disabled via properties. The default settings can be found in `docker-compose.yaml` and can be changed there. ```yaml # Extension Configuration -BROKER_CLIENT_EXTENSION_ENABLED: false # disabled by default CLEARINGHOUSE_CLIENT_EXTENSION_ENABLED: true # enabled by default ``` diff --git a/docs/dev/checkstyle/checkstyle-config.xml b/docs/dev/checkstyle/checkstyle-config.xml index 334a1d067..cf56b4068 100644 --- a/docs/dev/checkstyle/checkstyle-config.xml +++ b/docs/dev/checkstyle/checkstyle-config.xml @@ -181,7 +181,7 @@ - + @@ -197,27 +197,27 @@ value="Member name ''{0}'' must match pattern ''{1}''."/> - + - + - + - + - + @@ -232,7 +232,7 @@ value="Class type name ''{0}'' must match pattern ''{1}''."/> - + diff --git a/extensions/broker-server-api/api/README.md b/extensions/broker-server-api/api/README.md deleted file mode 100644 index addf0780c..000000000 --- a/extensions/broker-server-api/api/README.md +++ /dev/null @@ -1,27 +0,0 @@ - -
-
- - Logo - - -

Broker Server API Specification

- -

- Report Bug - · - Request Feature -

-
- -## About this component - -Specification of Broker Server API endpoints, for example endpoints for the Broker UI. - -## License - -Apache License 2.0 - see [LICENSE](../../../LICENSE) - -## Contact - -sovity GmbH - contact@sovity.de diff --git a/extensions/broker-server-api/api/build.gradle.kts b/extensions/broker-server-api/api/build.gradle.kts deleted file mode 100644 index a34c94429..000000000 --- a/extensions/broker-server-api/api/build.gradle.kts +++ /dev/null @@ -1,79 +0,0 @@ - -plugins { - `java-library` - `maven-publish` - alias(libs.plugins.swagger.plugin) //./gradlew clean resolve - alias(libs.plugins.hidetake.swaggerGenerator) //./gradlew generateSwaggerUI - alias(libs.plugins.openapi.generator7) //./gradlew openApiValidate && ./gradlew openApiGenerate -} - -dependencies { - annotationProcessor(libs.lombok) - compileOnly(libs.lombok) - - api(project(":extensions:wrapper:wrapper-common-api")) - - api(libs.jakarta.rsApi) - api(libs.jakarta.validationApi) - api(libs.swagger.annotationsJakarta) - api(libs.swagger.jaxrs2Jakarta) - api(libs.jakarta.servletApi) - - implementation(libs.apache.commonsLang) - implementation(libs.jakarta.validationApi) -} - -val openapiFileDir = project.layout.buildDirectory.get().asFile.resolve("swagger").path -val openapiFileFilename = "broker-server.yaml" -val openapiFile = "$openapiFileDir/$openapiFileFilename" - -tasks.withType { - outputDir = file(openapiFileDir) - outputFileName = openapiFileFilename.removeSuffix(".yaml") - prettyPrint = true - outputFormat = io.swagger.v3.plugins.gradle.tasks.ResolveTask.Format.YAML - classpath = java.sourceSets["main"].runtimeClasspath - buildClasspath = classpath - resourcePackages = setOf("") -} - -task("openApiGenerateTypeScriptClient") { - validateSpec.set(false) - dependsOn("resolve") - generatorName.set("typescript-fetch") - configOptions.set(mutableMapOf( - "supportsES6" to "true", - "npmVersion" to "8.15.0", - "typescriptThreePlus" to "true", - )) - - inputSpec.set(openapiFile) - val outputDirectory = buildFile.parentFile.resolve("../client-ts/src/generated").normalize() - outputDir.set(outputDirectory.toString()) - - doFirst { - project.delete(fileTree(outputDirectory).exclude("**/.gitignore")) - } - - doLast { - outputDirectory.resolve("src/generated").renameTo(outputDirectory) - } -} - -tasks.withType { - dependsOn("resolve") - dependsOn("openApiGenerateTypeScriptClient") - from(openapiFileDir) { - include(openapiFileFilename) - } -} - -group = libs.versions.sovityEdcExtensionGroup.get() - -publishing { - publications { - create(project.name) { - from(components["java"]) - } - } -} diff --git a/extensions/broker-server-api/api/src/main/java/de/sovity/edc/ext/brokerserver/api/ApiInformation.java b/extensions/broker-server-api/api/src/main/java/de/sovity/edc/ext/brokerserver/api/ApiInformation.java deleted file mode 100644 index 81f868094..000000000 --- a/extensions/broker-server-api/api/src/main/java/de/sovity/edc/ext/brokerserver/api/ApiInformation.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (c) 2023 sovity GmbH - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - * - * Contributors: - * sovity GmbH - initial API and implementation - * - */ - -package de.sovity.edc.ext.brokerserver.api; - -import io.swagger.v3.oas.annotations.ExternalDocumentation; -import io.swagger.v3.oas.annotations.OpenAPIDefinition; -import io.swagger.v3.oas.annotations.info.Contact; -import io.swagger.v3.oas.annotations.info.Info; -import io.swagger.v3.oas.annotations.info.License; - -@OpenAPIDefinition( - info = @Info( - title = "Broker Server API (Deprecated)", - version = "0.0.0", - description = "Broker Server API for the Broker Server built by sovity.", - contact = @Contact( - name = "sovity GmbH", - email = "contact@sovity.de", - url = "https://github.com/sovity/edc-ce/issues/new/choose" - ), - license = @License( - name = "Apache 2.0", - url = "https://github.com/sovity/edc-ce/blob/main/LICENSE" - ) - ), - externalDocs = @ExternalDocumentation( - description = "Broker Server API in sovity/ce", - url = "https://github.com/sovity/edc-broker-server-extension/tree/main/extensions/broker-server-api" - ) -) -public interface ApiInformation { -} diff --git a/extensions/broker-server-api/api/src/main/java/de/sovity/edc/ext/brokerserver/api/BrokerServerResource.java b/extensions/broker-server-api/api/src/main/java/de/sovity/edc/ext/brokerserver/api/BrokerServerResource.java deleted file mode 100644 index 5bcbfca82..000000000 --- a/extensions/broker-server-api/api/src/main/java/de/sovity/edc/ext/brokerserver/api/BrokerServerResource.java +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright (c) 2023 sovity GmbH - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - * - * Contributors: - * sovity GmbH - initial API and implementation - * - */ - -package de.sovity.edc.ext.brokerserver.api; - -import de.sovity.edc.ext.brokerserver.api.model.ConnectorCreationRequest; -import de.sovity.edc.ext.brokerserver.api.model.AuthorityPortalConnectorDataOfferInfo; -import de.sovity.edc.ext.brokerserver.api.model.AuthorityPortalConnectorInfo; -import de.sovity.edc.ext.brokerserver.api.model.AuthorityPortalOrganizationMetadataRequest; -import de.sovity.edc.ext.brokerserver.api.model.CatalogPageQuery; -import de.sovity.edc.ext.brokerserver.api.model.CatalogPageResult; -import de.sovity.edc.ext.brokerserver.api.model.ConnectorDetailPageQuery; -import de.sovity.edc.ext.brokerserver.api.model.ConnectorDetailPageResult; -import de.sovity.edc.ext.brokerserver.api.model.ConnectorPageQuery; -import de.sovity.edc.ext.brokerserver.api.model.ConnectorPageResult; -import de.sovity.edc.ext.brokerserver.api.model.DataOfferDetailPageQuery; -import de.sovity.edc.ext.brokerserver.api.model.DataOfferDetailPageResult; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.ws.rs.Consumes; -import jakarta.ws.rs.DELETE; -import jakarta.ws.rs.POST; -import jakarta.ws.rs.PUT; -import jakarta.ws.rs.Path; -import jakarta.ws.rs.Produces; -import jakarta.ws.rs.QueryParam; -import jakarta.ws.rs.core.MediaType; - -import java.util.List; - -@Path("wrapper/broker") -@Tag(name = "Broker Server", description = "Broker Server API Endpoints. Requires the Broker Server Extension") -public interface BrokerServerResource { - - @POST - @Path("catalog-page") - @Consumes(MediaType.APPLICATION_JSON) - @Produces(MediaType.APPLICATION_JSON) - @Operation(description = "Query the Broker's Catalog of Data Offers") - CatalogPageResult catalogPage(CatalogPageQuery query); - - @POST - @Path("connector-page") - @Consumes(MediaType.APPLICATION_JSON) - @Produces(MediaType.APPLICATION_JSON) - @Operation(description = "Query the List of Known Connectors") - ConnectorPageResult connectorPage(ConnectorPageQuery query); - - @POST - @Path("data-offer-detail-page") - @Consumes(MediaType.APPLICATION_JSON) - @Produces(MediaType.APPLICATION_JSON) - @Operation(description = "Query a Data Offer's Detail Page") - DataOfferDetailPageResult dataOfferDetailPage(DataOfferDetailPageQuery query); - - @POST - @Path("connector-detail-page") - @Consumes(MediaType.APPLICATION_JSON) - @Produces(MediaType.APPLICATION_JSON) - @Operation(description = "Query a known Connector's Detail Page") - ConnectorDetailPageResult connectorDetailPage(ConnectorDetailPageQuery query); - - @PUT - @Path("connectors") - @Consumes(MediaType.APPLICATION_JSON) - @Operation(description = "Add unknown Connectors to the Broker Server") - void addConnectors(List endpoints, @QueryParam("adminApiKey") String adminApiKey); - - @PUT - @Path("connectors-with-mdsid") - @Consumes(MediaType.APPLICATION_JSON) - @Operation(description = "Add unknown Connectors with MDS IDs to the Broker Server") - void addConnectorsWithMdsIds(ConnectorCreationRequest connectors, @QueryParam("adminApiKey") String adminApiKey); - - @DELETE - @Path("connectors") - @Consumes(MediaType.APPLICATION_JSON) - @Operation(description = "Delete known Connectors from the Broker Server") - void deleteConnectors(List endpoints, @QueryParam("adminApiKey") String adminApiKey); - - @POST - @Path("authority-portal-api/connectors") - @Consumes(MediaType.APPLICATION_JSON) - @Produces(MediaType.APPLICATION_JSON) - @Operation(description = "Provide Connector metadata by provided Connector Endpoints") - List getConnectorMetadata(List endpoints, @QueryParam("adminApiKey") String adminApiKey); - - @POST - @Path("authority-portal-api/organization-metadata") - @Consumes(MediaType.APPLICATION_JSON) - @Operation(description = "Update organization metadata. Organizations not contained in the payload will be deleted.") - void setOrganizationMetadata(AuthorityPortalOrganizationMetadataRequest organizationMetadataRequest, @QueryParam("adminApiKey") String adminApiKey); - - @POST - @Path("authority-portal-api/data-offer-info") - @Consumes(MediaType.APPLICATION_JSON) - @Produces(MediaType.APPLICATION_JSON) - @Operation(description = "Provides information about Data Offers for given Connectors.") - List getConnectorDataOffers(List endpoints, @QueryParam("adminApiKey") String adminApiKey); -} diff --git a/extensions/broker-server-api/api/src/main/java/de/sovity/edc/ext/brokerserver/api/model/AddedConnector.java b/extensions/broker-server-api/api/src/main/java/de/sovity/edc/ext/brokerserver/api/model/AddedConnector.java deleted file mode 100644 index 2a71d0e5e..000000000 --- a/extensions/broker-server-api/api/src/main/java/de/sovity/edc/ext/brokerserver/api/model/AddedConnector.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (c) 2024 sovity GmbH - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - * - * Contributors: - * sovity GmbH - initial API and implementation - * - */ -package de.sovity.edc.ext.brokerserver.api.model; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; -import lombok.ToString; - -@Getter -@Setter -@ToString -@NoArgsConstructor -@AllArgsConstructor -@Schema(description = "Information for adding an unknown connector.", requiredMode = Schema.RequiredMode.REQUIRED) -public class AddedConnector { - @Schema(description = "Connector Endpoint", requiredMode = Schema.RequiredMode.REQUIRED) - private String connectorEndpoint; - @Schema(description = "Organization MDS ID", requiredMode = Schema.RequiredMode.REQUIRED) - private String mdsId; -} diff --git a/extensions/broker-server-api/api/src/main/java/de/sovity/edc/ext/brokerserver/api/model/AuthorityPortalConnectorDataOfferDetails.java b/extensions/broker-server-api/api/src/main/java/de/sovity/edc/ext/brokerserver/api/model/AuthorityPortalConnectorDataOfferDetails.java deleted file mode 100644 index 4ef3d92af..000000000 --- a/extensions/broker-server-api/api/src/main/java/de/sovity/edc/ext/brokerserver/api/model/AuthorityPortalConnectorDataOfferDetails.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (c) 2023 sovity GmbH - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - * - * Contributors: - * sovity GmbH - initial API and implementation - * - */ - -package de.sovity.edc.ext.brokerserver.api.model; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; -import lombok.ToString; - -@Getter -@Setter -@ToString -@NoArgsConstructor -@AllArgsConstructor -@Schema(description = "Data offer details of a connector.") -public class AuthorityPortalConnectorDataOfferDetails { - @Schema(description = "Asset ID", requiredMode = Schema.RequiredMode.REQUIRED) - private String dataOfferId; - - @Schema(description = "Name of the asset", requiredMode = Schema.RequiredMode.REQUIRED) - private String dataOfferName; - -} - diff --git a/extensions/broker-server-api/api/src/main/java/de/sovity/edc/ext/brokerserver/api/model/AuthorityPortalConnectorDataOfferInfo.java b/extensions/broker-server-api/api/src/main/java/de/sovity/edc/ext/brokerserver/api/model/AuthorityPortalConnectorDataOfferInfo.java deleted file mode 100644 index 13f4792eb..000000000 --- a/extensions/broker-server-api/api/src/main/java/de/sovity/edc/ext/brokerserver/api/model/AuthorityPortalConnectorDataOfferInfo.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (c) 2023 sovity GmbH - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - * - * Contributors: - * sovity GmbH - initial API and implementation - * - */ - -package de.sovity.edc.ext.brokerserver.api.model; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; -import lombok.ToString; - -import java.time.OffsetDateTime; -import java.util.List; - -@Getter -@Setter -@ToString -@NoArgsConstructor -@AllArgsConstructor -@Schema(description = "Details of a Connector and its data offers.") -public class AuthorityPortalConnectorDataOfferInfo { - - @Schema(description = "Connector Endpoint", example = "https://my-test.connector/api/dsp", requiredMode = Schema.RequiredMode.REQUIRED) - private String connectorEndpoint; - - @Schema(description = "ID of participant", requiredMode = Schema.RequiredMode.REQUIRED) - private String participantId; - - @Schema(description = "Connector Online Status", requiredMode = Schema.RequiredMode.REQUIRED) - private ConnectorOnlineStatus onlineStatus; - - @Schema(description = "Date to be displayed as last update date, for online connectors it's the last refresh date, for offline connectors it's the creation date or last successful fetch.") - private OffsetDateTime offlineSinceOrLastUpdatedAt; - - @Schema(description = "Available Data Offers", requiredMode = Schema.RequiredMode.REQUIRED) - private List dataOffers; - -} diff --git a/extensions/broker-server-api/api/src/main/java/de/sovity/edc/ext/brokerserver/api/model/AuthorityPortalConnectorInfo.java b/extensions/broker-server-api/api/src/main/java/de/sovity/edc/ext/brokerserver/api/model/AuthorityPortalConnectorInfo.java deleted file mode 100644 index 7bc088765..000000000 --- a/extensions/broker-server-api/api/src/main/java/de/sovity/edc/ext/brokerserver/api/model/AuthorityPortalConnectorInfo.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (c) 2024 sovity GmbH - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - * - * Contributors: - * sovity GmbH - initial API and implementation - * - */ -package de.sovity.edc.ext.brokerserver.api.model; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; -import lombok.ToString; - -import java.time.OffsetDateTime; - -@Getter -@Setter -@ToString -@NoArgsConstructor -@AllArgsConstructor -@Schema(description = "Information for one connector, as required for the Authority Portal.", requiredMode = Schema.RequiredMode.REQUIRED) -public class AuthorityPortalConnectorInfo { - @Schema(description = "Connector Endpoint", requiredMode = Schema.RequiredMode.REQUIRED) - private String connectorEndpoint; - @Schema(description = "Connector Participant ID", requiredMode = Schema.RequiredMode.REQUIRED) - private String participantId; - @Schema(description = "Number of public Data Offers in this connector, as tracked by the broker", requiredMode = Schema.RequiredMode.REQUIRED) - private Integer dataOfferCount; - @Schema(description = "Connector Online Status", requiredMode = Schema.RequiredMode.REQUIRED) - private ConnectorOnlineStatus onlineStatus; - @Schema(description = "Last successful refresh time stamp of the online status", requiredMode = Schema.RequiredMode.REQUIRED) - private OffsetDateTime offlineSinceOrLastUpdatedAt; -} diff --git a/extensions/broker-server-api/api/src/main/java/de/sovity/edc/ext/brokerserver/api/model/AuthorityPortalOrganizationMetadata.java b/extensions/broker-server-api/api/src/main/java/de/sovity/edc/ext/brokerserver/api/model/AuthorityPortalOrganizationMetadata.java deleted file mode 100644 index 5acd846e1..000000000 --- a/extensions/broker-server-api/api/src/main/java/de/sovity/edc/ext/brokerserver/api/model/AuthorityPortalOrganizationMetadata.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (c) 2024 sovity GmbH - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - * - * Contributors: - * sovity GmbH - initial API and implementation - * - */ -package de.sovity.edc.ext.brokerserver.api.model; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; -import lombok.ToString; - -import java.time.OffsetDateTime; - -@Getter -@Setter -@ToString -@NoArgsConstructor -@AllArgsConstructor -@Schema(description = "Information about a single organization from the Authority Portal.") -public class AuthorityPortalOrganizationMetadata { - @Schema(description = "MDS-ID from the Authority Portal") - private String mdsId; - @Schema(description = "Company name") - private String name; -} diff --git a/extensions/broker-server-api/api/src/main/java/de/sovity/edc/ext/brokerserver/api/model/AuthorityPortalOrganizationMetadataRequest.java b/extensions/broker-server-api/api/src/main/java/de/sovity/edc/ext/brokerserver/api/model/AuthorityPortalOrganizationMetadataRequest.java deleted file mode 100644 index 68eb269eb..000000000 --- a/extensions/broker-server-api/api/src/main/java/de/sovity/edc/ext/brokerserver/api/model/AuthorityPortalOrganizationMetadataRequest.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (c) 2024 sovity GmbH - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - * - * Contributors: - * sovity GmbH - initial API and implementation - * - */ -package de.sovity.edc.ext.brokerserver.api.model; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; -import lombok.ToString; - -import java.util.List; - -@Getter -@Setter -@ToString -@NoArgsConstructor -@AllArgsConstructor -@Schema(description = "Information about organizations from the Authority Portal.") -public class AuthorityPortalOrganizationMetadataRequest { - @Schema(description = "Organization metadata") - private List organizations; -} diff --git a/extensions/broker-server-api/api/src/main/java/de/sovity/edc/ext/brokerserver/api/model/CatalogContractOffer.java b/extensions/broker-server-api/api/src/main/java/de/sovity/edc/ext/brokerserver/api/model/CatalogContractOffer.java deleted file mode 100644 index 31f4b02a9..000000000 --- a/extensions/broker-server-api/api/src/main/java/de/sovity/edc/ext/brokerserver/api/model/CatalogContractOffer.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (c) 2023 sovity GmbH - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - * - * Contributors: - * sovity GmbH - initial API and implementation - * - */ - -package de.sovity.edc.ext.brokerserver.api.model; - -import de.sovity.edc.ext.wrapper.api.common.model.UiPolicy; -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; -import lombok.ToString; - -import java.time.OffsetDateTime; - -@Getter -@Setter -@ToString -@NoArgsConstructor -@AllArgsConstructor -@Schema(description = "A contract offer a data offer is available under (as required by the catalog).") -public class CatalogContractOffer { - @Schema(description = "Contract Offer ID", requiredMode = Schema.RequiredMode.REQUIRED) - private String contractOfferId; - - @Schema(description = "Creation date in Broker", requiredMode = Schema.RequiredMode.REQUIRED) - private OffsetDateTime createdAt; - - @Schema(description = "Update date in Broker", requiredMode = Schema.RequiredMode.REQUIRED) - private OffsetDateTime updatedAt; - - @Schema(description = "Contract Policy", requiredMode = Schema.RequiredMode.REQUIRED) - private UiPolicy contractPolicy; -} - diff --git a/extensions/broker-server-api/api/src/main/java/de/sovity/edc/ext/brokerserver/api/model/CatalogDataOffer.java b/extensions/broker-server-api/api/src/main/java/de/sovity/edc/ext/brokerserver/api/model/CatalogDataOffer.java deleted file mode 100644 index 4c89b522b..000000000 --- a/extensions/broker-server-api/api/src/main/java/de/sovity/edc/ext/brokerserver/api/model/CatalogDataOffer.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (c) 2023 sovity GmbH - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - * - * Contributors: - * sovity GmbH - initial API and implementation - * - */ - -package de.sovity.edc.ext.brokerserver.api.model; - -import de.sovity.edc.ext.wrapper.api.common.model.UiAsset; -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; -import lombok.ToString; - -import java.time.OffsetDateTime; -import java.util.List; - -@Getter -@Setter -@ToString -@NoArgsConstructor -@AllArgsConstructor -@Schema(description = "Data Offer, meaning an offered asset.") -public class CatalogDataOffer { - @Schema(description = "ID of asset", requiredMode = Schema.RequiredMode.REQUIRED) - private String assetId; - - @Schema(description = "Connector Endpoint", example = "https://my-test.connector/api/dsp", requiredMode = Schema.RequiredMode.REQUIRED) - private String connectorEndpoint; - - @Schema(description = "Connector Online Status", requiredMode = Schema.RequiredMode.REQUIRED) - private ConnectorOnlineStatus connectorOnlineStatus; - - @Schema(description = "Date to be displayed as last update date, for online connectors it's the last refresh date, for offline connectors it's the creation date or last successful fetch.") - private OffsetDateTime connectorOfflineSinceOrLastUpdatedAt; - - @Schema(description = "Creation date in Broker", requiredMode = Schema.RequiredMode.REQUIRED) - private OffsetDateTime createdAt; - - @Schema(description = "Update date in Broker", requiredMode = Schema.RequiredMode.REQUIRED) - private OffsetDateTime updatedAt; - - @Schema(description = "Asset properties", requiredMode = Schema.RequiredMode.REQUIRED) - private UiAsset asset; - - @Schema(description = "Available Contract Offers", requiredMode = Schema.RequiredMode.REQUIRED) - private List contractOffers; -} - diff --git a/extensions/broker-server-api/api/src/main/java/de/sovity/edc/ext/brokerserver/api/model/CatalogPageQuery.java b/extensions/broker-server-api/api/src/main/java/de/sovity/edc/ext/brokerserver/api/model/CatalogPageQuery.java deleted file mode 100644 index a69f19e37..000000000 --- a/extensions/broker-server-api/api/src/main/java/de/sovity/edc/ext/brokerserver/api/model/CatalogPageQuery.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (c) 2023 sovity GmbH - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - * - * Contributors: - * sovity GmbH - initial API and implementation - * - */ - -package de.sovity.edc.ext.brokerserver.api.model; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; -import lombok.ToString; - -@Getter -@Setter -@ToString -@NoArgsConstructor -@AllArgsConstructor -@Schema(description = "Filterable Catalog Page Query") -public class CatalogPageQuery { - @Schema(description = "Selected filters") - private CnfFilterValue filter; - - @Schema(description = "Search query") - private String searchQuery; - - @Schema(description = "Sorting") - private CatalogPageSortingType sorting; - - @Schema(description = "Page number, one based, meaning the first page is page 1.", example = "1", defaultValue = "1", type = "n") - private Integer pageOneBased; -} - diff --git a/extensions/broker-server-api/api/src/main/java/de/sovity/edc/ext/brokerserver/api/model/CatalogPageResult.java b/extensions/broker-server-api/api/src/main/java/de/sovity/edc/ext/brokerserver/api/model/CatalogPageResult.java deleted file mode 100644 index 5b99be10e..000000000 --- a/extensions/broker-server-api/api/src/main/java/de/sovity/edc/ext/brokerserver/api/model/CatalogPageResult.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (c) 2023 sovity GmbH - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - * - * Contributors: - * sovity GmbH - initial API and implementation - * - */ - -package de.sovity.edc.ext.brokerserver.api.model; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; -import lombok.ToString; - -import java.util.List; - -@Getter -@Setter -@ToString -@NoArgsConstructor -@AllArgsConstructor -@Schema(description = "Catalog Page and visible filters") -public class CatalogPageResult { - @Schema(description = "Available filter options", requiredMode = Schema.RequiredMode.REQUIRED) - private CnfFilter availableFilters; - - @Schema(description = "Available sorting options", requiredMode = Schema.RequiredMode.REQUIRED) - private List availableSortings; - - @Schema(description = "Pagination Metadata", requiredMode = Schema.RequiredMode.REQUIRED) - private PaginationMetadata paginationMetadata; - - @Schema(description = "Current page of data offers", requiredMode = Schema.RequiredMode.REQUIRED) - private List dataOffers; -} - diff --git a/extensions/broker-server-api/api/src/main/java/de/sovity/edc/ext/brokerserver/api/model/CatalogPageSortingItem.java b/extensions/broker-server-api/api/src/main/java/de/sovity/edc/ext/brokerserver/api/model/CatalogPageSortingItem.java deleted file mode 100644 index ea1d1ed7d..000000000 --- a/extensions/broker-server-api/api/src/main/java/de/sovity/edc/ext/brokerserver/api/model/CatalogPageSortingItem.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (c) 2023 sovity GmbH - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - * - * Contributors: - * sovity GmbH - initial API and implementation - * - */ - -package de.sovity.edc.ext.brokerserver.api.model; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; -import lombok.ToString; - -@Getter -@Setter -@ToString -@NoArgsConstructor -@AllArgsConstructor -@Schema(description = "Available Catalog Page Sorting Item") -public class CatalogPageSortingItem { - @Schema(description = "Sorting ID", requiredMode = Schema.RequiredMode.REQUIRED) - private CatalogPageSortingType sorting; - @Schema(description = "Sorting Title", example = "By Relevance", requiredMode = Schema.RequiredMode.REQUIRED) - private String title; -} - diff --git a/extensions/broker-server-api/api/src/main/java/de/sovity/edc/ext/brokerserver/api/model/CnfFilter.java b/extensions/broker-server-api/api/src/main/java/de/sovity/edc/ext/brokerserver/api/model/CnfFilter.java deleted file mode 100644 index 54c9395c5..000000000 --- a/extensions/broker-server-api/api/src/main/java/de/sovity/edc/ext/brokerserver/api/model/CnfFilter.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (c) 2023 sovity GmbH - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - * - * Contributors: - * sovity GmbH - initial API and implementation - * - */ - -package de.sovity.edc.ext.brokerserver.api.model; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; -import lombok.ToString; - -import java.util.List; - -@Getter -@Setter -@ToString -@NoArgsConstructor -@AllArgsConstructor -@Schema(description = "Filter in form of a conjunctive normal form, meaning (A=X OR A=Y) AND (B=M or B=N). " + - "Not selected attributes default to TRUE. Used here to let the backend be a SSOT for the available filter options, " + - "e.g. Transport Mode, Data Model, etc.") -public class CnfFilter { - @Schema(description = "Available attributes to filter by.", requiredMode = Schema.RequiredMode.REQUIRED) - private List fields; -} - diff --git a/extensions/broker-server-api/api/src/main/java/de/sovity/edc/ext/brokerserver/api/model/CnfFilterAttribute.java b/extensions/broker-server-api/api/src/main/java/de/sovity/edc/ext/brokerserver/api/model/CnfFilterAttribute.java deleted file mode 100644 index 72687dde4..000000000 --- a/extensions/broker-server-api/api/src/main/java/de/sovity/edc/ext/brokerserver/api/model/CnfFilterAttribute.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (c) 2023 sovity GmbH - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - * - * Contributors: - * sovity GmbH - initial API and implementation - * - */ - -package de.sovity.edc.ext.brokerserver.api.model; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; -import lombok.ToString; - -import java.util.List; - -@Getter -@Setter -@ToString -@NoArgsConstructor -@AllArgsConstructor -@Schema(description = "Attribute, e.g. Language") -public class CnfFilterAttribute { - @Schema(description = "Attribute ID", example = "asset:prop:language", requiredMode = Schema.RequiredMode.REQUIRED) - private String id; - @Schema(description = "Attribute Title", example = "Language", requiredMode = Schema.RequiredMode.REQUIRED) - private String title; - @Schema(description = "Available values.", requiredMode = Schema.RequiredMode.REQUIRED) - private List values; -} - diff --git a/extensions/broker-server-api/api/src/main/java/de/sovity/edc/ext/brokerserver/api/model/CnfFilterItem.java b/extensions/broker-server-api/api/src/main/java/de/sovity/edc/ext/brokerserver/api/model/CnfFilterItem.java deleted file mode 100644 index 1b6489382..000000000 --- a/extensions/broker-server-api/api/src/main/java/de/sovity/edc/ext/brokerserver/api/model/CnfFilterItem.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (c) 2023 sovity GmbH - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - * - * Contributors: - * sovity GmbH - initial API and implementation - * - */ - -package de.sovity.edc.ext.brokerserver.api.model; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; -import lombok.ToString; - -@Getter -@Setter -@ToString -@NoArgsConstructor -@AllArgsConstructor -@Schema(description = "Attribute Value") -public class CnfFilterItem { - @Schema(description = "Value ID", example = "https://w3id.org/idsa/code/EN", requiredMode = Schema.RequiredMode.REQUIRED) - private String id; - @Schema(description = "Value Title", example = "English", requiredMode = Schema.RequiredMode.REQUIRED) - private String title; -} - diff --git a/extensions/broker-server-api/api/src/main/java/de/sovity/edc/ext/brokerserver/api/model/CnfFilterValue.java b/extensions/broker-server-api/api/src/main/java/de/sovity/edc/ext/brokerserver/api/model/CnfFilterValue.java deleted file mode 100644 index eb73b0449..000000000 --- a/extensions/broker-server-api/api/src/main/java/de/sovity/edc/ext/brokerserver/api/model/CnfFilterValue.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (c) 2023 sovity GmbH - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - * - * Contributors: - * sovity GmbH - initial API and implementation - * - */ - -package de.sovity.edc.ext.brokerserver.api.model; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; -import lombok.ToString; - -import java.util.List; - -@Getter -@Setter -@ToString -@NoArgsConstructor -@AllArgsConstructor -@Schema(description = "Cnf filter's selected value.") -public class CnfFilterValue { - @Schema(description = "Available attributes to filter by.", requiredMode = Schema.RequiredMode.REQUIRED) - private List selectedAttributeValues; -} - diff --git a/extensions/broker-server-api/api/src/main/java/de/sovity/edc/ext/brokerserver/api/model/CnfFilterValueAttribute.java b/extensions/broker-server-api/api/src/main/java/de/sovity/edc/ext/brokerserver/api/model/CnfFilterValueAttribute.java deleted file mode 100644 index a0ab4fcd1..000000000 --- a/extensions/broker-server-api/api/src/main/java/de/sovity/edc/ext/brokerserver/api/model/CnfFilterValueAttribute.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (c) 2023 sovity GmbH - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - * - * Contributors: - * sovity GmbH - initial API and implementation - * - */ - -package de.sovity.edc.ext.brokerserver.api.model; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; -import lombok.ToString; - -import java.util.List; - -@Getter -@Setter -@ToString -@NoArgsConstructor -@AllArgsConstructor -@Schema(description = "Single attribute of selected cnf filter's value") -public class CnfFilterValueAttribute { - @Schema(description = "Attribute ID", example = "asset:prop:language", requiredMode = Schema.RequiredMode.REQUIRED) - private String id; - @Schema(description = "Selected attribute values' IDs.", requiredMode = Schema.RequiredMode.REQUIRED) - private List selectedIds; -} - diff --git a/extensions/broker-server-api/api/src/main/java/de/sovity/edc/ext/brokerserver/api/model/ConnectorCreationRequest.java b/extensions/broker-server-api/api/src/main/java/de/sovity/edc/ext/brokerserver/api/model/ConnectorCreationRequest.java deleted file mode 100644 index a638df809..000000000 --- a/extensions/broker-server-api/api/src/main/java/de/sovity/edc/ext/brokerserver/api/model/ConnectorCreationRequest.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (c) 2024 sovity GmbH - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - * - * Contributors: - * sovity GmbH - initial API and implementation - * - */ -package de.sovity.edc.ext.brokerserver.api.model; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; -import lombok.ToString; - -import java.util.List; - -@Getter -@Setter -@ToString -@NoArgsConstructor -@AllArgsConstructor -@Schema(description = "Wrapper for adding unknown Connectors with MDS IDs.", requiredMode = Schema.RequiredMode.REQUIRED) -public class ConnectorCreationRequest { - @Schema(description = "Connectors", requiredMode = Schema.RequiredMode.REQUIRED) - private List connectors; -} diff --git a/extensions/broker-server-api/api/src/main/java/de/sovity/edc/ext/brokerserver/api/model/ConnectorDetailPageQuery.java b/extensions/broker-server-api/api/src/main/java/de/sovity/edc/ext/brokerserver/api/model/ConnectorDetailPageQuery.java deleted file mode 100644 index e43d2e273..000000000 --- a/extensions/broker-server-api/api/src/main/java/de/sovity/edc/ext/brokerserver/api/model/ConnectorDetailPageQuery.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (c) 2023 sovity GmbH - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - * - * Contributors: - * sovity GmbH - initial API and implementation - * - */ - -package de.sovity.edc.ext.brokerserver.api.model; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; -import lombok.ToString; - -@Getter -@Setter -@ToString -@NoArgsConstructor -@AllArgsConstructor -@Schema(description = "Connector Page Detail Query") -public class ConnectorDetailPageQuery { - @Schema(description = "Connector Endpoint1") - private String connectorEndpoint; -} - diff --git a/extensions/broker-server-api/api/src/main/java/de/sovity/edc/ext/brokerserver/api/model/ConnectorDetailPageResult.java b/extensions/broker-server-api/api/src/main/java/de/sovity/edc/ext/brokerserver/api/model/ConnectorDetailPageResult.java deleted file mode 100644 index 704d8d6cb..000000000 --- a/extensions/broker-server-api/api/src/main/java/de/sovity/edc/ext/brokerserver/api/model/ConnectorDetailPageResult.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (c) 2023 sovity GmbH - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - * - * Contributors: - * sovity GmbH - initial API and implementation - * - */ - -package de.sovity.edc.ext.brokerserver.api.model; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; -import lombok.ToString; - -import java.time.OffsetDateTime; - -@Getter -@Setter -@ToString -@NoArgsConstructor -@AllArgsConstructor -@Schema(description = "Connector Detail Page Data") -public class ConnectorDetailPageResult { - @Schema(description = "Connector Participant ID", example = "https://my-test.connector", requiredMode = Schema.RequiredMode.REQUIRED) - private String participantId; - - @Schema(description = "Connector Endpoint", example = "https://my-test.connector/api/dsp", requiredMode = Schema.RequiredMode.REQUIRED) - private String endpoint; - - @Schema(description = "Name of the responsible organization", requiredMode = Schema.RequiredMode.REQUIRED) - private String organizationName; - - @Schema(description = "Creation date in Broker", requiredMode = Schema.RequiredMode.REQUIRED) - private OffsetDateTime createdAt; - - @Schema(description = "Last time the connector was successfully refreshed.") - private OffsetDateTime lastSuccessfulRefreshAt; - - @Schema(description = "Last time the connector was tried to be refreshed.") - private OffsetDateTime lastRefreshAttemptAt; - - @Schema(description = "Connector Online Status", requiredMode = Schema.RequiredMode.REQUIRED) - private ConnectorOnlineStatus onlineStatus; - - @Schema(description = "Number of known data offerings") - private Integer numDataOffers; - - @Schema(description = "Average time to crawl the connector") - private Long connectorCrawlingTimeAvg; -} diff --git a/extensions/broker-server-api/api/src/main/java/de/sovity/edc/ext/brokerserver/api/model/ConnectorListEntry.java b/extensions/broker-server-api/api/src/main/java/de/sovity/edc/ext/brokerserver/api/model/ConnectorListEntry.java deleted file mode 100644 index d37dbcc78..000000000 --- a/extensions/broker-server-api/api/src/main/java/de/sovity/edc/ext/brokerserver/api/model/ConnectorListEntry.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (c) 2023 sovity GmbH - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - * - * Contributors: - * sovity GmbH - initial API and implementation - * - */ - -package de.sovity.edc.ext.brokerserver.api.model; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; -import lombok.ToString; - -import java.time.OffsetDateTime; - -@Getter -@Setter -@ToString -@NoArgsConstructor -@AllArgsConstructor -@Schema(description = "A Contract Offer's Connector Status") -public class ConnectorListEntry { - @Schema(description = "Connector Participant ID", example = "my-test-connector", requiredMode = Schema.RequiredMode.REQUIRED) - private String participantId; - - @Schema(description = "Connector Endpoint", example = "https://my-test.connector/api/dsp", requiredMode = Schema.RequiredMode.REQUIRED) - private String endpoint; - - @Schema(description = "Name of the responsible organization", requiredMode = Schema.RequiredMode.REQUIRED) - private String organizationName; - - @Schema(description = "Creation date in Broker", requiredMode = Schema.RequiredMode.REQUIRED) - private OffsetDateTime createdAt; - - @Schema(description = "Last time the connector was successfully refreshed.") - private OffsetDateTime lastSuccessfulRefreshAt; - - @Schema(description = "Last time the connector was tried to be refreshed.") - private OffsetDateTime lastRefreshAttemptAt; - - @Schema(description = "Connector Online Status", requiredMode = Schema.RequiredMode.REQUIRED) - private ConnectorOnlineStatus onlineStatus; - - @Schema(description = "Number of known data offerings") - private Integer numDataOffers; -} - diff --git a/extensions/broker-server-api/api/src/main/java/de/sovity/edc/ext/brokerserver/api/model/ConnectorPageQuery.java b/extensions/broker-server-api/api/src/main/java/de/sovity/edc/ext/brokerserver/api/model/ConnectorPageQuery.java deleted file mode 100644 index 38f3afad6..000000000 --- a/extensions/broker-server-api/api/src/main/java/de/sovity/edc/ext/brokerserver/api/model/ConnectorPageQuery.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (c) 2023 sovity GmbH - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - * - * Contributors: - * sovity GmbH - initial API and implementation - * - */ - -package de.sovity.edc.ext.brokerserver.api.model; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; -import lombok.ToString; - -@Getter -@Setter -@ToString -@NoArgsConstructor -@AllArgsConstructor -@Schema(description = "Filterable Connector Page Query") -public class ConnectorPageQuery { - @Schema(description = "Search query") - private String searchQuery; - - @Schema(description = "Sorting") - private ConnectorPageSortingType sorting; - - @Schema(description = "Page number, one based, meaning the first page is page 1.", example = "1", defaultValue = "1", type = "n") - private Integer pageOneBased; -} - diff --git a/extensions/broker-server-api/api/src/main/java/de/sovity/edc/ext/brokerserver/api/model/ConnectorPageResult.java b/extensions/broker-server-api/api/src/main/java/de/sovity/edc/ext/brokerserver/api/model/ConnectorPageResult.java deleted file mode 100644 index 247a701c0..000000000 --- a/extensions/broker-server-api/api/src/main/java/de/sovity/edc/ext/brokerserver/api/model/ConnectorPageResult.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (c) 2023 sovity GmbH - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - * - * Contributors: - * sovity GmbH - initial API and implementation - * - */ - -package de.sovity.edc.ext.brokerserver.api.model; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; -import lombok.ToString; - -import java.util.List; - -@Getter -@Setter -@ToString -@NoArgsConstructor -@AllArgsConstructor -@Schema(description = "Connector Page Data") -public class ConnectorPageResult { - @Schema(description = "Available sorting options", requiredMode = Schema.RequiredMode.REQUIRED) - private List availableSortings; - - @Schema(description = "Pagination Metadata", requiredMode = Schema.RequiredMode.REQUIRED) - private PaginationMetadata paginationMetadata; - - @Schema(description = "Current page of connector list entries", requiredMode = Schema.RequiredMode.REQUIRED) - private List connectors; -} diff --git a/extensions/broker-server-api/api/src/main/java/de/sovity/edc/ext/brokerserver/api/model/ConnectorPageSortingItem.java b/extensions/broker-server-api/api/src/main/java/de/sovity/edc/ext/brokerserver/api/model/ConnectorPageSortingItem.java deleted file mode 100644 index 1849de2fb..000000000 --- a/extensions/broker-server-api/api/src/main/java/de/sovity/edc/ext/brokerserver/api/model/ConnectorPageSortingItem.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (c) 2023 sovity GmbH - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - * - * Contributors: - * sovity GmbH - initial API and implementation - * - */ - -package de.sovity.edc.ext.brokerserver.api.model; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; -import lombok.ToString; - -@Getter -@Setter -@ToString -@NoArgsConstructor -@AllArgsConstructor -@Schema(description = "Available Connector Page Sorting Item") -public class ConnectorPageSortingItem { - @Schema(description = "Sorting ID", requiredMode = Schema.RequiredMode.REQUIRED) - private ConnectorPageSortingType sorting; - @Schema(description = "Sorting Title", example = "Alphabetically", requiredMode = Schema.RequiredMode.REQUIRED) - private String title; -} - diff --git a/extensions/broker-server-api/api/src/main/java/de/sovity/edc/ext/brokerserver/api/model/ConnectorPageSortingType.java b/extensions/broker-server-api/api/src/main/java/de/sovity/edc/ext/brokerserver/api/model/ConnectorPageSortingType.java deleted file mode 100644 index 0cc284233..000000000 --- a/extensions/broker-server-api/api/src/main/java/de/sovity/edc/ext/brokerserver/api/model/ConnectorPageSortingType.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (c) 2023 sovity GmbH - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - * - * Contributors: - * sovity GmbH - initial API and implementation - * - */ - -package de.sovity.edc.ext.brokerserver.api.model; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Getter; -import lombok.RequiredArgsConstructor; - -@Getter -@RequiredArgsConstructor -@Schema(description = "Connector List Page's known sorting option IDs") -public enum ConnectorPageSortingType { - ONLINE_STATUS("Online Status"), - MOST_RECENT("Most Recent"), - TITLE("By Title"); - - private final String title; -} - diff --git a/extensions/broker-server-api/api/src/main/java/de/sovity/edc/ext/brokerserver/api/model/DataOfferDetailContractOffer.java b/extensions/broker-server-api/api/src/main/java/de/sovity/edc/ext/brokerserver/api/model/DataOfferDetailContractOffer.java deleted file mode 100644 index c5554c765..000000000 --- a/extensions/broker-server-api/api/src/main/java/de/sovity/edc/ext/brokerserver/api/model/DataOfferDetailContractOffer.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (c) 2023 sovity GmbH - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - * - * Contributors: - * sovity GmbH - initial API and implementation - * - */ - -package de.sovity.edc.ext.brokerserver.api.model; - -import de.sovity.edc.ext.wrapper.api.common.model.UiPolicy; -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; -import lombok.ToString; - -import java.time.OffsetDateTime; - -@Getter -@Setter -@ToString -@NoArgsConstructor -@AllArgsConstructor -@Schema(description = "A contract offer a data offer is available under (as required by the data offer detail page).") -public class DataOfferDetailContractOffer { - @Schema(description = "Contract Offer ID", requiredMode = Schema.RequiredMode.REQUIRED) - private String contractOfferId; - - @Schema(description = "Creation date in Broker", requiredMode = Schema.RequiredMode.REQUIRED) - private OffsetDateTime createdAt; - - @Schema(description = "Update date in Broker", requiredMode = Schema.RequiredMode.REQUIRED) - private OffsetDateTime updatedAt; - - @Schema(description = "Contract Policy", requiredMode = Schema.RequiredMode.REQUIRED) - private UiPolicy contractPolicy; -} - diff --git a/extensions/broker-server-api/api/src/main/java/de/sovity/edc/ext/brokerserver/api/model/DataOfferDetailPageQuery.java b/extensions/broker-server-api/api/src/main/java/de/sovity/edc/ext/brokerserver/api/model/DataOfferDetailPageQuery.java deleted file mode 100644 index 7dc00ff72..000000000 --- a/extensions/broker-server-api/api/src/main/java/de/sovity/edc/ext/brokerserver/api/model/DataOfferDetailPageQuery.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (c) 2023 sovity GmbH - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - * - * Contributors: - * sovity GmbH - initial API and implementation - * - */ - -package de.sovity.edc.ext.brokerserver.api.model; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; -import lombok.ToString; - -@Getter -@Setter -@ToString -@NoArgsConstructor -@AllArgsConstructor -@Schema(description = "Data Offer Detail Page Query") -public class DataOfferDetailPageQuery { - @Schema(description = "Connector Endpoint") - private String connectorEndpoint; - - @Schema(description = "Asset ID") - private String assetId; -} - diff --git a/extensions/broker-server-api/api/src/main/java/de/sovity/edc/ext/brokerserver/api/model/DataOfferDetailPageResult.java b/extensions/broker-server-api/api/src/main/java/de/sovity/edc/ext/brokerserver/api/model/DataOfferDetailPageResult.java deleted file mode 100644 index 354a63c81..000000000 --- a/extensions/broker-server-api/api/src/main/java/de/sovity/edc/ext/brokerserver/api/model/DataOfferDetailPageResult.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (c) 2023 sovity GmbH - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - * - * Contributors: - * sovity GmbH - initial API and implementation - * - */ - -package de.sovity.edc.ext.brokerserver.api.model; - -import de.sovity.edc.ext.wrapper.api.common.model.UiAsset; -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; -import lombok.ToString; - -import java.time.OffsetDateTime; -import java.util.List; - -@Getter -@Setter -@ToString -@NoArgsConstructor -@AllArgsConstructor -@Schema(description = "Data Offer Detail Page.") -public class DataOfferDetailPageResult { - @Schema(description = "ID of asset", requiredMode = Schema.RequiredMode.REQUIRED) - private String assetId; - - @Schema(description = "Connector Endpoint", example = "https://my-test.connector/api/dsp", requiredMode = Schema.RequiredMode.REQUIRED) - private String connectorEndpoint; - - @Schema(description = "Connector Online Status", requiredMode = Schema.RequiredMode.REQUIRED) - private ConnectorOnlineStatus connectorOnlineStatus; - - @Schema(description = "Date to be displayed as last update date, for online connectors it's the last refresh date, for offline connectors it's the creation date or last successful fetch.") - private OffsetDateTime connectorOfflineSinceOrLastUpdatedAt; - - @Schema(description = "Creation date in Broker", requiredMode = Schema.RequiredMode.REQUIRED) - private OffsetDateTime createdAt; - - @Schema(description = "Update date in Broker", requiredMode = Schema.RequiredMode.REQUIRED) - private OffsetDateTime updatedAt; - - @Schema(description = "Asset properties", requiredMode = Schema.RequiredMode.REQUIRED) - private UiAsset asset; - - @Schema(description = "Available Contract Offers", requiredMode = Schema.RequiredMode.REQUIRED) - private List contractOffers; - - @Schema(description = "View Count", requiredMode = Schema.RequiredMode.REQUIRED) - private Integer viewCount; -} diff --git a/extensions/broker-server-api/api/src/main/java/de/sovity/edc/ext/brokerserver/api/model/PaginationMetadata.java b/extensions/broker-server-api/api/src/main/java/de/sovity/edc/ext/brokerserver/api/model/PaginationMetadata.java deleted file mode 100644 index 4edbebbfe..000000000 --- a/extensions/broker-server-api/api/src/main/java/de/sovity/edc/ext/brokerserver/api/model/PaginationMetadata.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (c) 2023 sovity GmbH - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - * - * Contributors: - * sovity GmbH - initial API and implementation - * - */ - -package de.sovity.edc.ext.brokerserver.api.model; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; -import lombok.ToString; - -@Getter -@Setter -@ToString -@NoArgsConstructor -@AllArgsConstructor -@Schema(description = "Pagination Metadata") -public class PaginationMetadata { - @Schema(description = "Total number of results", example = "368", type = "n", requiredMode = Schema.RequiredMode.REQUIRED) - private Integer numTotal; - - @Schema(description = "Visible number of results", example = "20", type = "n", requiredMode = Schema.RequiredMode.REQUIRED) - private Integer numVisible; - - @Schema(description = "Page number, one based, meaning the first page is page 1.", example = "1", defaultValue = "1", type = "n", requiredMode = Schema.RequiredMode.REQUIRED) - private Integer pageOneBased; - - @Schema(description = "Items per page", example = "20", type = "n", requiredMode = Schema.RequiredMode.REQUIRED) - private Integer pageSize; -} - diff --git a/extensions/broker-server-api/client-ts/.gitignore b/extensions/broker-server-api/client-ts/.gitignore deleted file mode 100644 index a547bf36d..000000000 --- a/extensions/broker-server-api/client-ts/.gitignore +++ /dev/null @@ -1,24 +0,0 @@ -# Logs -logs -*.log -npm-debug.log* -yarn-debug.log* -yarn-error.log* -pnpm-debug.log* -lerna-debug.log* - -node_modules -dist -dist-ssr -*.local - -# Editor directories and files -.vscode/* -!.vscode/extensions.json -.idea -.DS_Store -*.suo -*.ntvs* -*.njsproj -*.sln -*.sw? diff --git a/extensions/broker-server-api/client-ts/.prettierignore b/extensions/broker-server-api/client-ts/.prettierignore deleted file mode 100644 index de4d1f007..000000000 --- a/extensions/broker-server-api/client-ts/.prettierignore +++ /dev/null @@ -1,2 +0,0 @@ -dist -node_modules diff --git a/extensions/broker-server-api/client-ts/README.md b/extensions/broker-server-api/client-ts/README.md deleted file mode 100644 index 93c38d954..000000000 --- a/extensions/broker-server-api/client-ts/README.md +++ /dev/null @@ -1,55 +0,0 @@ - -
-
- - Logo - - -

Broker Server API TypeScript Client Library

- -

- Report Bug - · - Request Feature -

-
- -## About this component - -TypeScript Client Library to access APIs of our Broker Server Backend. - -## How to install - -Requires a NodeJS / NPM project. - -```shell script -npm i --save @sovity.de/broker-server-client -``` - -## How to use - -Configure your Broker Server Client and use endpoints of our Broker Server API: - -```typescript -import { - BrokerServerClient, - buildBrokerServerClient, - CatalogPageResult -} from '@sovity.de/broker-server-client'; - -const brokerServerClient: BrokerServerClient = buildBrokerServerClient({ - managementApiUrl: 'http://localhost:11002/api/management', - managementApiKey: 'ApiKeyDefaultValue', -}); - -let catalog: CatalogPageResult = await edcClient.brokerServerApi.catalogPage(); -``` - -## License - -Apache License 2.0 - see -[LICENSE](https://github.com/sovity/edc-ce/blob/main/LICENSE) - -## Contact - -sovity GmbH - contact@sovity.de diff --git a/extensions/broker-server-api/client-ts/index.html b/extensions/broker-server-api/client-ts/index.html deleted file mode 100644 index f49a7cf04..000000000 --- a/extensions/broker-server-api/client-ts/index.html +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - Client example - - -
- - - diff --git a/extensions/broker-server-api/client-ts/package-lock.json b/extensions/broker-server-api/client-ts/package-lock.json deleted file mode 100644 index 0ef861efc..000000000 --- a/extensions/broker-server-api/client-ts/package-lock.json +++ /dev/null @@ -1,3182 +0,0 @@ -{ - "name": "@sovity.de/broker-server-client", - "version": "0.0.0", - "lockfileVersion": 2, - "requires": true, - "packages": { - "": { - "name": "@sovity.de/broker-server-client", - "version": "0.0.0", - "license": "Apache-2.0", - "devDependencies": { - "@trivago/prettier-plugin-sort-imports": "^4.1.1", - "@types/node": "^18.15.11", - "prettier": "^2.8.7", - "typescript": "^4.9.3", - "vite": "^4.2.0", - "vite-plugin-dts": "^2.2.0" - } - }, - "node_modules/@babel/code-frame": { - "version": "7.22.13", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz", - "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==", - "dev": true, - "dependencies": { - "@babel/highlight": "^7.22.13", - "chalk": "^2.4.2" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/generator": { - "version": "7.17.7", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.17.7.tgz", - "integrity": "sha512-oLcVCTeIFadUoArDTwpluncplrYBmTCCZZgXCbgNGvOBBiSDDK3eWO4b/+eOTli5tKv1lg+a5/NAXg+nTcei1w==", - "dev": true, - "dependencies": { - "@babel/types": "^7.17.0", - "jsesc": "^2.5.1", - "source-map": "^0.5.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/generator/node_modules/source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/@babel/helper-environment-visitor": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", - "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-function-name": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", - "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", - "dev": true, - "dependencies": { - "@babel/template": "^7.22.15", - "@babel/types": "^7.23.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-function-name/node_modules/@babel/types": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.0.tgz", - "integrity": "sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==", - "dev": true, - "dependencies": { - "@babel/helper-string-parser": "^7.22.5", - "@babel/helper-validator-identifier": "^7.22.20", - "to-fast-properties": "^2.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-hoist-variables": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", - "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", - "dev": true, - "dependencies": { - "@babel/types": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-hoist-variables/node_modules/@babel/types": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.0.tgz", - "integrity": "sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==", - "dev": true, - "dependencies": { - "@babel/helper-string-parser": "^7.22.5", - "@babel/helper-validator-identifier": "^7.22.20", - "to-fast-properties": "^2.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-split-export-declaration": { - "version": "7.22.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", - "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", - "dev": true, - "dependencies": { - "@babel/types": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-split-export-declaration/node_modules/@babel/types": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.0.tgz", - "integrity": "sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==", - "dev": true, - "dependencies": { - "@babel/helper-string-parser": "^7.22.5", - "@babel/helper-validator-identifier": "^7.22.20", - "to-fast-properties": "^2.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-string-parser": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz", - "integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", - "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/highlight": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.20.tgz", - "integrity": "sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==", - "dev": true, - "dependencies": { - "@babel/helper-validator-identifier": "^7.22.20", - "chalk": "^2.4.2", - "js-tokens": "^4.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/parser": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.0.tgz", - "integrity": "sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==", - "dev": true, - "bin": { - "parser": "bin/babel-parser.js" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@babel/template": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz", - "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.22.13", - "@babel/parser": "^7.22.15", - "@babel/types": "^7.22.15" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/template/node_modules/@babel/types": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.0.tgz", - "integrity": "sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==", - "dev": true, - "dependencies": { - "@babel/helper-string-parser": "^7.22.5", - "@babel/helper-validator-identifier": "^7.22.20", - "to-fast-properties": "^2.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/traverse": { - "version": "7.23.2", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.2.tgz", - "integrity": "sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.22.13", - "@babel/generator": "^7.23.0", - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-function-name": "^7.23.0", - "@babel/helper-hoist-variables": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/parser": "^7.23.0", - "@babel/types": "^7.23.0", - "debug": "^4.1.0", - "globals": "^11.1.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/traverse/node_modules/@babel/generator": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.0.tgz", - "integrity": "sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g==", - "dev": true, - "dependencies": { - "@babel/types": "^7.23.0", - "@jridgewell/gen-mapping": "^0.3.2", - "@jridgewell/trace-mapping": "^0.3.17", - "jsesc": "^2.5.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/traverse/node_modules/@babel/types": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.0.tgz", - "integrity": "sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==", - "dev": true, - "dependencies": { - "@babel/helper-string-parser": "^7.22.5", - "@babel/helper-validator-identifier": "^7.22.20", - "to-fast-properties": "^2.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/types": { - "version": "7.17.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.17.0.tgz", - "integrity": "sha512-TmKSNO4D5rzhL5bjWFcVHHLETzfQ/AmbKpKPOSjlP0WoHZ6L911fgoOKY4Alp/emzG4cHJdyN49zpgkbXFEHHw==", - "dev": true, - "dependencies": { - "@babel/helper-validator-identifier": "^7.16.7", - "to-fast-properties": "^2.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@esbuild/android-arm": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.20.tgz", - "integrity": "sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/android-arm64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.18.20.tgz", - "integrity": "sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/android-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.18.20.tgz", - "integrity": "sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.18.20.tgz", - "integrity": "sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/darwin-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.18.20.tgz", - "integrity": "sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/freebsd-arm64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.18.20.tgz", - "integrity": "sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/freebsd-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.18.20.tgz", - "integrity": "sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-arm": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.18.20.tgz", - "integrity": "sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-arm64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.18.20.tgz", - "integrity": "sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.18.20.tgz", - "integrity": "sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.18.20.tgz", - "integrity": "sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg==", - "cpu": [ - "loong64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-mips64el": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.18.20.tgz", - "integrity": "sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ==", - "cpu": [ - "mips64el" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.18.20.tgz", - "integrity": "sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA==", - "cpu": [ - "ppc64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-riscv64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.18.20.tgz", - "integrity": "sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A==", - "cpu": [ - "riscv64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-s390x": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.18.20.tgz", - "integrity": "sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ==", - "cpu": [ - "s390x" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.18.20.tgz", - "integrity": "sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/netbsd-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.18.20.tgz", - "integrity": "sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.18.20.tgz", - "integrity": "sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.18.20.tgz", - "integrity": "sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/win32-arm64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.18.20.tgz", - "integrity": "sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/win32-ia32": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.18.20.tgz", - "integrity": "sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/win32-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.18.20.tgz", - "integrity": "sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", - "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", - "dev": true, - "dependencies": { - "@jridgewell/set-array": "^1.0.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", - "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==", - "dev": true, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/set-array": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", - "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", - "dev": true, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.14", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", - "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", - "dev": true - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.20", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.20.tgz", - "integrity": "sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q==", - "dev": true, - "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" - } - }, - "node_modules/@microsoft/api-extractor": { - "version": "7.37.1", - "resolved": "https://registry.npmjs.org/@microsoft/api-extractor/-/api-extractor-7.37.1.tgz", - "integrity": "sha512-wbTL7TZG+9SPvYKwk26390ltoP/uR5621dniqhVp+5OHcn7wIKsT7vX9d/wvdAXD3Ft+7pAiCt6y3dBLFfY/0w==", - "dev": true, - "dependencies": { - "@microsoft/api-extractor-model": "7.28.1", - "@microsoft/tsdoc": "0.14.2", - "@microsoft/tsdoc-config": "~0.16.1", - "@rushstack/node-core-library": "3.60.1", - "@rushstack/rig-package": "0.5.1", - "@rushstack/ts-command-line": "4.16.1", - "colors": "~1.2.1", - "lodash": "~4.17.15", - "resolve": "~1.22.1", - "semver": "~7.5.4", - "source-map": "~0.6.1", - "typescript": "~5.0.4" - }, - "bin": { - "api-extractor": "bin/api-extractor" - } - }, - "node_modules/@microsoft/api-extractor-model": { - "version": "7.28.1", - "resolved": "https://registry.npmjs.org/@microsoft/api-extractor-model/-/api-extractor-model-7.28.1.tgz", - "integrity": "sha512-1hD9gQRu8VR53/e8GI+aql7MtWXHE/XtpOSgphJ6SB7AswqJT0mRZVufUbg3D57UdrchvLKz9b+zqay0Oq2vgg==", - "dev": true, - "dependencies": { - "@microsoft/tsdoc": "0.14.2", - "@microsoft/tsdoc-config": "~0.16.1", - "@rushstack/node-core-library": "3.60.1" - } - }, - "node_modules/@microsoft/api-extractor/node_modules/typescript": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.0.4.tgz", - "integrity": "sha512-cW9T5W9xY37cc+jfEnaUvX91foxtHkza3Nw3wkoF4sSlKn0MONdkdEndig/qPBWXNkmplh3NzayQzCiHM4/hqw==", - "dev": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=12.20" - } - }, - "node_modules/@microsoft/tsdoc": { - "version": "0.14.2", - "resolved": "https://registry.npmjs.org/@microsoft/tsdoc/-/tsdoc-0.14.2.tgz", - "integrity": "sha512-9b8mPpKrfeGRuhFH5iO1iwCLeIIsV6+H1sRfxbkoGXIyQE2BTsPd9zqSqQJ+pv5sJ/hT5M1zvOFL02MnEezFug==", - "dev": true - }, - "node_modules/@microsoft/tsdoc-config": { - "version": "0.16.2", - "resolved": "https://registry.npmjs.org/@microsoft/tsdoc-config/-/tsdoc-config-0.16.2.tgz", - "integrity": "sha512-OGiIzzoBLgWWR0UdRJX98oYO+XKGf7tiK4Zk6tQ/E4IJqGCe7dvkTvgDZV5cFJUzLGDOjeAXrnZoA6QkVySuxw==", - "dev": true, - "dependencies": { - "@microsoft/tsdoc": "0.14.2", - "ajv": "~6.12.6", - "jju": "~1.4.0", - "resolve": "~1.19.0" - } - }, - "node_modules/@microsoft/tsdoc-config/node_modules/resolve": { - "version": "1.19.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.19.0.tgz", - "integrity": "sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg==", - "dev": true, - "dependencies": { - "is-core-module": "^2.1.0", - "path-parse": "^1.0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dev": true, - "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dev": true, - "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@rollup/pluginutils": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.0.2.tgz", - "integrity": "sha512-pTd9rIsP92h+B6wWwFbW8RkZv4hiR/xKsqre4SIuAOaOEQRxi0lqLke9k2/7WegC85GgUs9pjmOjCUi3In4vwA==", - "dev": true, - "dependencies": { - "@types/estree": "^1.0.0", - "estree-walker": "^2.0.2", - "picomatch": "^2.3.1" - }, - "engines": { - "node": ">=14.0.0" - }, - "peerDependencies": { - "rollup": "^1.20.0||^2.0.0||^3.0.0" - }, - "peerDependenciesMeta": { - "rollup": { - "optional": true - } - } - }, - "node_modules/@rushstack/node-core-library": { - "version": "3.60.1", - "resolved": "https://registry.npmjs.org/@rushstack/node-core-library/-/node-core-library-3.60.1.tgz", - "integrity": "sha512-cWKCImfezPvILKu5eUPkz0Mp/cO/zOSJdPD64KHliBcdmbPHg/sF4rEL7WJkWywXT1RQ/U/N8uKdXMe7jDCXNw==", - "dev": true, - "dependencies": { - "colors": "~1.2.1", - "fs-extra": "~7.0.1", - "import-lazy": "~4.0.0", - "jju": "~1.4.0", - "resolve": "~1.22.1", - "semver": "~7.5.4", - "z-schema": "~5.0.2" - }, - "peerDependencies": { - "@types/node": "*" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } - } - }, - "node_modules/@rushstack/node-core-library/node_modules/fs-extra": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", - "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.2", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - }, - "engines": { - "node": ">=6 <7 || >=8" - } - }, - "node_modules/@rushstack/node-core-library/node_modules/jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", - "dev": true, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/@rushstack/node-core-library/node_modules/universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", - "dev": true, - "engines": { - "node": ">= 4.0.0" - } - }, - "node_modules/@rushstack/rig-package": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/@rushstack/rig-package/-/rig-package-0.5.1.tgz", - "integrity": "sha512-pXRYSe29TjRw7rqxD4WS3HN/sRSbfr+tJs4a9uuaSIBAITbUggygdhuG0VrO0EO+QqH91GhYMN4S6KRtOEmGVA==", - "dev": true, - "dependencies": { - "resolve": "~1.22.1", - "strip-json-comments": "~3.1.1" - } - }, - "node_modules/@rushstack/ts-command-line": { - "version": "4.16.1", - "resolved": "https://registry.npmjs.org/@rushstack/ts-command-line/-/ts-command-line-4.16.1.tgz", - "integrity": "sha512-+OCsD553GYVLEmz12yiFjMOzuPeCiZ3f8wTiFHL30ZVXexTyPmgjwXEhg2K2P0a2lVf+8YBy7WtPoflB2Fp8/A==", - "dev": true, - "dependencies": { - "@types/argparse": "1.0.38", - "argparse": "~1.0.9", - "colors": "~1.2.1", - "string-argv": "~0.3.1" - } - }, - "node_modules/@trivago/prettier-plugin-sort-imports": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/@trivago/prettier-plugin-sort-imports/-/prettier-plugin-sort-imports-4.2.1.tgz", - "integrity": "sha512-iuy2MPVURGdxILTchHr15VAioItuYBejKfcTmQFlxIuqA7jeaT6ngr5aUIG6S6U096d6a6lJCgaOwlRrPLlOPg==", - "dev": true, - "dependencies": { - "@babel/generator": "7.17.7", - "@babel/parser": "^7.20.5", - "@babel/traverse": "7.23.2", - "@babel/types": "7.17.0", - "javascript-natural-sort": "0.7.1", - "lodash": "^4.17.21" - }, - "peerDependencies": { - "@vue/compiler-sfc": "3.x", - "prettier": "2.x - 3.x" - }, - "peerDependenciesMeta": { - "@vue/compiler-sfc": { - "optional": true - } - } - }, - "node_modules/@ts-morph/common": { - "version": "0.18.1", - "resolved": "https://registry.npmjs.org/@ts-morph/common/-/common-0.18.1.tgz", - "integrity": "sha512-RVE+zSRICWRsfrkAw5qCAK+4ZH9kwEFv5h0+/YeHTLieWP7F4wWq4JsKFuNWG+fYh/KF+8rAtgdj5zb2mm+DVA==", - "dev": true, - "dependencies": { - "fast-glob": "^3.2.12", - "minimatch": "^5.1.0", - "mkdirp": "^1.0.4", - "path-browserify": "^1.0.1" - } - }, - "node_modules/@types/argparse": { - "version": "1.0.38", - "resolved": "https://registry.npmjs.org/@types/argparse/-/argparse-1.0.38.tgz", - "integrity": "sha512-ebDJ9b0e702Yr7pWgB0jzm+CX4Srzz8RcXtLJDJB+BSccqMa36uyH/zUsSYao5+BD1ytv3k3rPYCq4mAE1hsXA==", - "dev": true - }, - "node_modules/@types/estree": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.0.tgz", - "integrity": "sha512-WulqXMDUTYAXCjZnk6JtIHPigp55cVtDgDrO2gHRwhyJto21+1zbVCtOYB2L1F9w4qCQ0rOGWBnBe0FNTiEJIQ==", - "dev": true - }, - "node_modules/@types/node": { - "version": "18.15.11", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.15.11.tgz", - "integrity": "sha512-E5Kwq2n4SbMzQOn6wnmBjuK9ouqlURrcZDVfbo9ftDDTFt3nk7ZKK4GMOzoYgnpQJKcxwQw+lGaBvvlMo0qN/Q==", - "dev": true - }, - "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "dependencies": { - "sprintf-js": "~1.0.2" - } - }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true - }, - "node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, - "dependencies": { - "fill-range": "^7.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/code-block-writer": { - "version": "11.0.3", - "resolved": "https://registry.npmjs.org/code-block-writer/-/code-block-writer-11.0.3.tgz", - "integrity": "sha512-NiujjUFB4SwScJq2bwbYUtXbZhBSlY6vYzm++3Q6oC+U+injTqfPYFK8wS9COOmb2lueqp0ZRB4nK1VYeHgNyw==", - "dev": true - }, - "node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true - }, - "node_modules/colors": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.2.5.tgz", - "integrity": "sha512-erNRLao/Y3Fv54qUa0LBB+//Uf3YwMUmdJinN20yMXm9zdKKqH9wt7R9IIVZ+K7ShzfpLV/Zg8+VyrBJYB4lpg==", - "dev": true, - "engines": { - "node": ">=0.1.90" - } - }, - "node_modules/commander": { - "version": "9.5.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz", - "integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==", - "dev": true, - "optional": true, - "engines": { - "node": "^12.20.0 || >=14" - } - }, - "node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/esbuild": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.18.20.tgz", - "integrity": "sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA==", - "dev": true, - "hasInstallScript": true, - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=12" - }, - "optionalDependencies": { - "@esbuild/android-arm": "0.18.20", - "@esbuild/android-arm64": "0.18.20", - "@esbuild/android-x64": "0.18.20", - "@esbuild/darwin-arm64": "0.18.20", - "@esbuild/darwin-x64": "0.18.20", - "@esbuild/freebsd-arm64": "0.18.20", - "@esbuild/freebsd-x64": "0.18.20", - "@esbuild/linux-arm": "0.18.20", - "@esbuild/linux-arm64": "0.18.20", - "@esbuild/linux-ia32": "0.18.20", - "@esbuild/linux-loong64": "0.18.20", - "@esbuild/linux-mips64el": "0.18.20", - "@esbuild/linux-ppc64": "0.18.20", - "@esbuild/linux-riscv64": "0.18.20", - "@esbuild/linux-s390x": "0.18.20", - "@esbuild/linux-x64": "0.18.20", - "@esbuild/netbsd-x64": "0.18.20", - "@esbuild/openbsd-x64": "0.18.20", - "@esbuild/sunos-x64": "0.18.20", - "@esbuild/win32-arm64": "0.18.20", - "@esbuild/win32-ia32": "0.18.20", - "@esbuild/win32-x64": "0.18.20" - } - }, - "node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/estree-walker": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", - "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", - "dev": true - }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true - }, - "node_modules/fast-glob": { - "version": "3.2.12", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz", - "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==", - "dev": true, - "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" - }, - "engines": { - "node": ">=8.6.0" - } - }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true - }, - "node_modules/fastq": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", - "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", - "dev": true, - "dependencies": { - "reusify": "^1.0.4" - } - }, - "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/fs-extra": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", - "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "dev": true, - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true - }, - "node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true - }, - "node_modules/has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, - "dependencies": { - "function-bind": "^1.1.1" - }, - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/import-lazy": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-4.0.0.tgz", - "integrity": "sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-core-module": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.11.0.tgz", - "integrity": "sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==", - "dev": true, - "dependencies": { - "has": "^1.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/javascript-natural-sort": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/javascript-natural-sort/-/javascript-natural-sort-0.7.1.tgz", - "integrity": "sha512-nO6jcEfZWQXDhOiBtG2KvKyEptz7RVbpGP4vTD2hLBdmNQSsCiicO2Ioinv6UI4y9ukqnBpy+XZ9H6uLNgJTlw==", - "dev": true - }, - "node_modules/jju": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/jju/-/jju-1.4.0.tgz", - "integrity": "sha512-8wb9Yw966OSxApiCt0K3yNJL8pnNeIv+OEq2YMidz4FKP6nonSRoOXc80iXY4JaN2FC11B9qsNmDsm+ZOfMROA==", - "dev": true - }, - "node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true - }, - "node_modules/jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", - "dev": true, - "bin": { - "jsesc": "bin/jsesc" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "node_modules/jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dev": true, - "dependencies": { - "universalify": "^2.0.0" - }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/kolorist": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/kolorist/-/kolorist-1.7.0.tgz", - "integrity": "sha512-ymToLHqL02udwVdbkowNpzjFd6UzozMtshPQKVi5k1EjKRqKqBrOnE9QbLEb0/pV76SAiIT13hdL8R6suc+f3g==", - "dev": true - }, - "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dev": true - }, - "node_modules/lodash.get": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", - "integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==", - "dev": true - }, - "node_modules/lodash.isequal": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", - "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==", - "dev": true - }, - "node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/magic-string": { - "version": "0.29.0", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.29.0.tgz", - "integrity": "sha512-WcfidHrDjMY+eLjlU+8OvwREqHwpgCeKVBUpQ3OhYYuvfaYCUgcbuBzappNzZvg/v8onU3oQj+BYpkOJe9Iw4Q==", - "dev": true, - "dependencies": { - "@jridgewell/sourcemap-codec": "^1.4.13" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", - "dev": true, - "dependencies": { - "braces": "^3.0.2", - "picomatch": "^2.3.1" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/minimatch": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", - "dev": true, - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "dev": true, - "bin": { - "mkdirp": "bin/cmd.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "node_modules/nanoid": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz", - "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, - "node_modules/path-browserify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", - "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==", - "dev": true - }, - "node_modules/path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true - }, - "node_modules/picocolors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", - "dev": true - }, - "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/postcss": { - "version": "8.4.31", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", - "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "dependencies": { - "nanoid": "^3.3.6", - "picocolors": "^1.0.0", - "source-map-js": "^1.0.2" - }, - "engines": { - "node": "^10 || ^12 || >=14" - } - }, - "node_modules/prettier": { - "version": "2.8.7", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.7.tgz", - "integrity": "sha512-yPngTo3aXUUmyuTjeTUT75txrf+aMh9FiD7q9ZE/i6r0bPb22g4FsE6Y338PQX1bmfy08i9QQCB7/rcUAVntfw==", - "dev": true, - "bin": { - "prettier": "bin-prettier.js" - }, - "engines": { - "node": ">=10.13.0" - }, - "funding": { - "url": "https://github.com/prettier/prettier?sponsor=1" - } - }, - "node_modules/punycode": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", - "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/resolve": { - "version": "1.22.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", - "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", - "dev": true, - "dependencies": { - "is-core-module": "^2.9.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "dev": true, - "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" - } - }, - "node_modules/rollup": { - "version": "3.29.4", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.29.4.tgz", - "integrity": "sha512-oWzmBZwvYrU0iJHtDmhsm662rC15FRXmcjCk1xD771dFDx5jJ02ufAQQTn0etB2emNk4J9EZg/yWKpsn9BWGRw==", - "dev": true, - "bin": { - "rollup": "dist/bin/rollup" - }, - "engines": { - "node": ">=14.18.0", - "npm": ">=8.0.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, - "node_modules/run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "queue-microtask": "^1.2.2" - } - }, - "node_modules/semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/source-map-js": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", - "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", - "dev": true - }, - "node_modules/string-argv": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.2.tgz", - "integrity": "sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==", - "dev": true, - "engines": { - "node": ">=0.6.19" - } - }, - "node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/ts-morph": { - "version": "17.0.1", - "resolved": "https://registry.npmjs.org/ts-morph/-/ts-morph-17.0.1.tgz", - "integrity": "sha512-10PkHyXmrtsTvZSL+cqtJLTgFXkU43Gd0JCc0Rw6GchWbqKe0Rwgt1v3ouobTZwQzF1mGhDeAlWYBMGRV7y+3g==", - "dev": true, - "dependencies": { - "@ts-morph/common": "~0.18.0", - "code-block-writer": "^11.0.3" - } - }, - "node_modules/typescript": { - "version": "4.9.5", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", - "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", - "dev": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=4.2.0" - } - }, - "node_modules/universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", - "dev": true, - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, - "dependencies": { - "punycode": "^2.1.0" - } - }, - "node_modules/validator": { - "version": "13.9.0", - "resolved": "https://registry.npmjs.org/validator/-/validator-13.9.0.tgz", - "integrity": "sha512-B+dGG8U3fdtM0/aNK4/X8CXq/EcxU2WPrPEkJGslb47qyHsxmbggTWK0yEA4qnYVNF+nxNlN88o14hIcPmSIEA==", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/vite": { - "version": "4.5.3", - "resolved": "https://registry.npmjs.org/vite/-/vite-4.5.3.tgz", - "integrity": "sha512-kQL23kMeX92v3ph7IauVkXkikdDRsYMGTVl5KY2E9OY4ONLvkHf04MDTbnfo6NKxZiDLWzVpP5oTa8hQD8U3dg==", - "dev": true, - "dependencies": { - "esbuild": "^0.18.10", - "postcss": "^8.4.27", - "rollup": "^3.27.1" - }, - "bin": { - "vite": "bin/vite.js" - }, - "engines": { - "node": "^14.18.0 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/vitejs/vite?sponsor=1" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - }, - "peerDependencies": { - "@types/node": ">= 14", - "less": "*", - "lightningcss": "^1.21.0", - "sass": "*", - "stylus": "*", - "sugarss": "*", - "terser": "^5.4.0" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - }, - "less": { - "optional": true - }, - "lightningcss": { - "optional": true - }, - "sass": { - "optional": true - }, - "stylus": { - "optional": true - }, - "sugarss": { - "optional": true - }, - "terser": { - "optional": true - } - } - }, - "node_modules/vite-plugin-dts": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/vite-plugin-dts/-/vite-plugin-dts-2.2.0.tgz", - "integrity": "sha512-XmZtv02I7eGWm3DrZbLo1AdJK5gCisk9GqJBpY4N63pDYR6AVUnlyjFP5FCBvSBUfgE0Ppl90bKgtJU9k3AzFw==", - "dev": true, - "dependencies": { - "@babel/parser": "^7.20.15", - "@microsoft/api-extractor": "^7.33.5", - "@rollup/pluginutils": "^5.0.2", - "@rushstack/node-core-library": "^3.53.2", - "debug": "^4.3.4", - "fast-glob": "^3.2.12", - "fs-extra": "^10.1.0", - "kolorist": "^1.6.0", - "magic-string": "^0.29.0", - "ts-morph": "17.0.1" - }, - "engines": { - "node": "^14.18.0 || >=16.0.0" - }, - "peerDependencies": { - "vite": ">=2.9.0" - } - }, - "node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, - "node_modules/z-schema": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/z-schema/-/z-schema-5.0.5.tgz", - "integrity": "sha512-D7eujBWkLa3p2sIpJA0d1pr7es+a7m0vFAnZLlCEKq/Ij2k0MLi9Br2UPxoxdYystm5K1yeBGzub0FlYUEWj2Q==", - "dev": true, - "dependencies": { - "lodash.get": "^4.4.2", - "lodash.isequal": "^4.5.0", - "validator": "^13.7.0" - }, - "bin": { - "z-schema": "bin/z-schema" - }, - "engines": { - "node": ">=8.0.0" - }, - "optionalDependencies": { - "commander": "^9.4.1" - } - } - }, - "dependencies": { - "@babel/code-frame": { - "version": "7.22.13", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz", - "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==", - "dev": true, - "requires": { - "@babel/highlight": "^7.22.13", - "chalk": "^2.4.2" - } - }, - "@babel/generator": { - "version": "7.17.7", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.17.7.tgz", - "integrity": "sha512-oLcVCTeIFadUoArDTwpluncplrYBmTCCZZgXCbgNGvOBBiSDDK3eWO4b/+eOTli5tKv1lg+a5/NAXg+nTcei1w==", - "dev": true, - "requires": { - "@babel/types": "^7.17.0", - "jsesc": "^2.5.1", - "source-map": "^0.5.0" - }, - "dependencies": { - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", - "dev": true - } - } - }, - "@babel/helper-environment-visitor": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", - "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", - "dev": true - }, - "@babel/helper-function-name": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", - "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", - "dev": true, - "requires": { - "@babel/template": "^7.22.15", - "@babel/types": "^7.23.0" - }, - "dependencies": { - "@babel/types": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.0.tgz", - "integrity": "sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==", - "dev": true, - "requires": { - "@babel/helper-string-parser": "^7.22.5", - "@babel/helper-validator-identifier": "^7.22.20", - "to-fast-properties": "^2.0.0" - } - } - } - }, - "@babel/helper-hoist-variables": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", - "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", - "dev": true, - "requires": { - "@babel/types": "^7.22.5" - }, - "dependencies": { - "@babel/types": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.0.tgz", - "integrity": "sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==", - "dev": true, - "requires": { - "@babel/helper-string-parser": "^7.22.5", - "@babel/helper-validator-identifier": "^7.22.20", - "to-fast-properties": "^2.0.0" - } - } - } - }, - "@babel/helper-split-export-declaration": { - "version": "7.22.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", - "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", - "dev": true, - "requires": { - "@babel/types": "^7.22.5" - }, - "dependencies": { - "@babel/types": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.0.tgz", - "integrity": "sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==", - "dev": true, - "requires": { - "@babel/helper-string-parser": "^7.22.5", - "@babel/helper-validator-identifier": "^7.22.20", - "to-fast-properties": "^2.0.0" - } - } - } - }, - "@babel/helper-string-parser": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz", - "integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==", - "dev": true - }, - "@babel/helper-validator-identifier": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", - "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", - "dev": true - }, - "@babel/highlight": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.20.tgz", - "integrity": "sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==", - "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.22.20", - "chalk": "^2.4.2", - "js-tokens": "^4.0.0" - } - }, - "@babel/parser": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.0.tgz", - "integrity": "sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==", - "dev": true - }, - "@babel/template": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz", - "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.22.13", - "@babel/parser": "^7.22.15", - "@babel/types": "^7.22.15" - }, - "dependencies": { - "@babel/types": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.0.tgz", - "integrity": "sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==", - "dev": true, - "requires": { - "@babel/helper-string-parser": "^7.22.5", - "@babel/helper-validator-identifier": "^7.22.20", - "to-fast-properties": "^2.0.0" - } - } - } - }, - "@babel/traverse": { - "version": "7.23.2", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.2.tgz", - "integrity": "sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.22.13", - "@babel/generator": "^7.23.0", - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-function-name": "^7.23.0", - "@babel/helper-hoist-variables": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/parser": "^7.23.0", - "@babel/types": "^7.23.0", - "debug": "^4.1.0", - "globals": "^11.1.0" - }, - "dependencies": { - "@babel/generator": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.0.tgz", - "integrity": "sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g==", - "dev": true, - "requires": { - "@babel/types": "^7.23.0", - "@jridgewell/gen-mapping": "^0.3.2", - "@jridgewell/trace-mapping": "^0.3.17", - "jsesc": "^2.5.1" - } - }, - "@babel/types": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.0.tgz", - "integrity": "sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==", - "dev": true, - "requires": { - "@babel/helper-string-parser": "^7.22.5", - "@babel/helper-validator-identifier": "^7.22.20", - "to-fast-properties": "^2.0.0" - } - } - } - }, - "@babel/types": { - "version": "7.17.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.17.0.tgz", - "integrity": "sha512-TmKSNO4D5rzhL5bjWFcVHHLETzfQ/AmbKpKPOSjlP0WoHZ6L911fgoOKY4Alp/emzG4cHJdyN49zpgkbXFEHHw==", - "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.16.7", - "to-fast-properties": "^2.0.0" - } - }, - "@esbuild/android-arm": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.20.tgz", - "integrity": "sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw==", - "dev": true, - "optional": true - }, - "@esbuild/android-arm64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.18.20.tgz", - "integrity": "sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==", - "dev": true, - "optional": true - }, - "@esbuild/android-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.18.20.tgz", - "integrity": "sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg==", - "dev": true, - "optional": true - }, - "@esbuild/darwin-arm64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.18.20.tgz", - "integrity": "sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA==", - "dev": true, - "optional": true - }, - "@esbuild/darwin-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.18.20.tgz", - "integrity": "sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ==", - "dev": true, - "optional": true - }, - "@esbuild/freebsd-arm64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.18.20.tgz", - "integrity": "sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw==", - "dev": true, - "optional": true - }, - "@esbuild/freebsd-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.18.20.tgz", - "integrity": "sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ==", - "dev": true, - "optional": true - }, - "@esbuild/linux-arm": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.18.20.tgz", - "integrity": "sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg==", - "dev": true, - "optional": true - }, - "@esbuild/linux-arm64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.18.20.tgz", - "integrity": "sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA==", - "dev": true, - "optional": true - }, - "@esbuild/linux-ia32": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.18.20.tgz", - "integrity": "sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA==", - "dev": true, - "optional": true - }, - "@esbuild/linux-loong64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.18.20.tgz", - "integrity": "sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg==", - "dev": true, - "optional": true - }, - "@esbuild/linux-mips64el": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.18.20.tgz", - "integrity": "sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ==", - "dev": true, - "optional": true - }, - "@esbuild/linux-ppc64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.18.20.tgz", - "integrity": "sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA==", - "dev": true, - "optional": true - }, - "@esbuild/linux-riscv64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.18.20.tgz", - "integrity": "sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A==", - "dev": true, - "optional": true - }, - "@esbuild/linux-s390x": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.18.20.tgz", - "integrity": "sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ==", - "dev": true, - "optional": true - }, - "@esbuild/linux-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.18.20.tgz", - "integrity": "sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==", - "dev": true, - "optional": true - }, - "@esbuild/netbsd-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.18.20.tgz", - "integrity": "sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A==", - "dev": true, - "optional": true - }, - "@esbuild/openbsd-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.18.20.tgz", - "integrity": "sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg==", - "dev": true, - "optional": true - }, - "@esbuild/sunos-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.18.20.tgz", - "integrity": "sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ==", - "dev": true, - "optional": true - }, - "@esbuild/win32-arm64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.18.20.tgz", - "integrity": "sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg==", - "dev": true, - "optional": true - }, - "@esbuild/win32-ia32": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.18.20.tgz", - "integrity": "sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g==", - "dev": true, - "optional": true - }, - "@esbuild/win32-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.18.20.tgz", - "integrity": "sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ==", - "dev": true, - "optional": true - }, - "@jridgewell/gen-mapping": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", - "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", - "dev": true, - "requires": { - "@jridgewell/set-array": "^1.0.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" - } - }, - "@jridgewell/resolve-uri": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", - "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==", - "dev": true - }, - "@jridgewell/set-array": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", - "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", - "dev": true - }, - "@jridgewell/sourcemap-codec": { - "version": "1.4.14", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", - "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", - "dev": true - }, - "@jridgewell/trace-mapping": { - "version": "0.3.20", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.20.tgz", - "integrity": "sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q==", - "dev": true, - "requires": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" - } - }, - "@microsoft/api-extractor": { - "version": "7.37.1", - "resolved": "https://registry.npmjs.org/@microsoft/api-extractor/-/api-extractor-7.37.1.tgz", - "integrity": "sha512-wbTL7TZG+9SPvYKwk26390ltoP/uR5621dniqhVp+5OHcn7wIKsT7vX9d/wvdAXD3Ft+7pAiCt6y3dBLFfY/0w==", - "dev": true, - "requires": { - "@microsoft/api-extractor-model": "7.28.1", - "@microsoft/tsdoc": "0.14.2", - "@microsoft/tsdoc-config": "~0.16.1", - "@rushstack/node-core-library": "3.60.1", - "@rushstack/rig-package": "0.5.1", - "@rushstack/ts-command-line": "4.16.1", - "colors": "~1.2.1", - "lodash": "~4.17.15", - "resolve": "~1.22.1", - "semver": "~7.5.4", - "source-map": "~0.6.1", - "typescript": "~5.0.4" - }, - "dependencies": { - "typescript": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.0.4.tgz", - "integrity": "sha512-cW9T5W9xY37cc+jfEnaUvX91foxtHkza3Nw3wkoF4sSlKn0MONdkdEndig/qPBWXNkmplh3NzayQzCiHM4/hqw==", - "dev": true - } - } - }, - "@microsoft/api-extractor-model": { - "version": "7.28.1", - "resolved": "https://registry.npmjs.org/@microsoft/api-extractor-model/-/api-extractor-model-7.28.1.tgz", - "integrity": "sha512-1hD9gQRu8VR53/e8GI+aql7MtWXHE/XtpOSgphJ6SB7AswqJT0mRZVufUbg3D57UdrchvLKz9b+zqay0Oq2vgg==", - "dev": true, - "requires": { - "@microsoft/tsdoc": "0.14.2", - "@microsoft/tsdoc-config": "~0.16.1", - "@rushstack/node-core-library": "3.60.1" - } - }, - "@microsoft/tsdoc": { - "version": "0.14.2", - "resolved": "https://registry.npmjs.org/@microsoft/tsdoc/-/tsdoc-0.14.2.tgz", - "integrity": "sha512-9b8mPpKrfeGRuhFH5iO1iwCLeIIsV6+H1sRfxbkoGXIyQE2BTsPd9zqSqQJ+pv5sJ/hT5M1zvOFL02MnEezFug==", - "dev": true - }, - "@microsoft/tsdoc-config": { - "version": "0.16.2", - "resolved": "https://registry.npmjs.org/@microsoft/tsdoc-config/-/tsdoc-config-0.16.2.tgz", - "integrity": "sha512-OGiIzzoBLgWWR0UdRJX98oYO+XKGf7tiK4Zk6tQ/E4IJqGCe7dvkTvgDZV5cFJUzLGDOjeAXrnZoA6QkVySuxw==", - "dev": true, - "requires": { - "@microsoft/tsdoc": "0.14.2", - "ajv": "~6.12.6", - "jju": "~1.4.0", - "resolve": "~1.19.0" - }, - "dependencies": { - "resolve": { - "version": "1.19.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.19.0.tgz", - "integrity": "sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg==", - "dev": true, - "requires": { - "is-core-module": "^2.1.0", - "path-parse": "^1.0.6" - } - } - } - }, - "@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dev": true, - "requires": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - } - }, - "@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "dev": true - }, - "@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dev": true, - "requires": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - } - }, - "@rollup/pluginutils": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.0.2.tgz", - "integrity": "sha512-pTd9rIsP92h+B6wWwFbW8RkZv4hiR/xKsqre4SIuAOaOEQRxi0lqLke9k2/7WegC85GgUs9pjmOjCUi3In4vwA==", - "dev": true, - "requires": { - "@types/estree": "^1.0.0", - "estree-walker": "^2.0.2", - "picomatch": "^2.3.1" - } - }, - "@rushstack/node-core-library": { - "version": "3.60.1", - "resolved": "https://registry.npmjs.org/@rushstack/node-core-library/-/node-core-library-3.60.1.tgz", - "integrity": "sha512-cWKCImfezPvILKu5eUPkz0Mp/cO/zOSJdPD64KHliBcdmbPHg/sF4rEL7WJkWywXT1RQ/U/N8uKdXMe7jDCXNw==", - "dev": true, - "requires": { - "colors": "~1.2.1", - "fs-extra": "~7.0.1", - "import-lazy": "~4.0.0", - "jju": "~1.4.0", - "resolve": "~1.22.1", - "semver": "~7.5.4", - "z-schema": "~5.0.2" - }, - "dependencies": { - "fs-extra": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", - "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - } - }, - "jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.6" - } - }, - "universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", - "dev": true - } - } - }, - "@rushstack/rig-package": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/@rushstack/rig-package/-/rig-package-0.5.1.tgz", - "integrity": "sha512-pXRYSe29TjRw7rqxD4WS3HN/sRSbfr+tJs4a9uuaSIBAITbUggygdhuG0VrO0EO+QqH91GhYMN4S6KRtOEmGVA==", - "dev": true, - "requires": { - "resolve": "~1.22.1", - "strip-json-comments": "~3.1.1" - } - }, - "@rushstack/ts-command-line": { - "version": "4.16.1", - "resolved": "https://registry.npmjs.org/@rushstack/ts-command-line/-/ts-command-line-4.16.1.tgz", - "integrity": "sha512-+OCsD553GYVLEmz12yiFjMOzuPeCiZ3f8wTiFHL30ZVXexTyPmgjwXEhg2K2P0a2lVf+8YBy7WtPoflB2Fp8/A==", - "dev": true, - "requires": { - "@types/argparse": "1.0.38", - "argparse": "~1.0.9", - "colors": "~1.2.1", - "string-argv": "~0.3.1" - } - }, - "@trivago/prettier-plugin-sort-imports": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/@trivago/prettier-plugin-sort-imports/-/prettier-plugin-sort-imports-4.2.1.tgz", - "integrity": "sha512-iuy2MPVURGdxILTchHr15VAioItuYBejKfcTmQFlxIuqA7jeaT6ngr5aUIG6S6U096d6a6lJCgaOwlRrPLlOPg==", - "dev": true, - "requires": { - "@babel/generator": "7.17.7", - "@babel/parser": "^7.20.5", - "@babel/traverse": "7.23.2", - "@babel/types": "7.17.0", - "javascript-natural-sort": "0.7.1", - "lodash": "^4.17.21" - } - }, - "@ts-morph/common": { - "version": "0.18.1", - "resolved": "https://registry.npmjs.org/@ts-morph/common/-/common-0.18.1.tgz", - "integrity": "sha512-RVE+zSRICWRsfrkAw5qCAK+4ZH9kwEFv5h0+/YeHTLieWP7F4wWq4JsKFuNWG+fYh/KF+8rAtgdj5zb2mm+DVA==", - "dev": true, - "requires": { - "fast-glob": "^3.2.12", - "minimatch": "^5.1.0", - "mkdirp": "^1.0.4", - "path-browserify": "^1.0.1" - } - }, - "@types/argparse": { - "version": "1.0.38", - "resolved": "https://registry.npmjs.org/@types/argparse/-/argparse-1.0.38.tgz", - "integrity": "sha512-ebDJ9b0e702Yr7pWgB0jzm+CX4Srzz8RcXtLJDJB+BSccqMa36uyH/zUsSYao5+BD1ytv3k3rPYCq4mAE1hsXA==", - "dev": true - }, - "@types/estree": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.0.tgz", - "integrity": "sha512-WulqXMDUTYAXCjZnk6JtIHPigp55cVtDgDrO2gHRwhyJto21+1zbVCtOYB2L1F9w4qCQ0rOGWBnBe0FNTiEJIQ==", - "dev": true - }, - "@types/node": { - "version": "18.15.11", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.15.11.tgz", - "integrity": "sha512-E5Kwq2n4SbMzQOn6wnmBjuK9ouqlURrcZDVfbo9ftDDTFt3nk7ZKK4GMOzoYgnpQJKcxwQw+lGaBvvlMo0qN/Q==", - "dev": true - }, - "ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "requires": { - "sprintf-js": "~1.0.2" - } - }, - "balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true - }, - "brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0" - } - }, - "braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, - "requires": { - "fill-range": "^7.0.1" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "code-block-writer": { - "version": "11.0.3", - "resolved": "https://registry.npmjs.org/code-block-writer/-/code-block-writer-11.0.3.tgz", - "integrity": "sha512-NiujjUFB4SwScJq2bwbYUtXbZhBSlY6vYzm++3Q6oC+U+injTqfPYFK8wS9COOmb2lueqp0ZRB4nK1VYeHgNyw==", - "dev": true - }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true - }, - "colors": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.2.5.tgz", - "integrity": "sha512-erNRLao/Y3Fv54qUa0LBB+//Uf3YwMUmdJinN20yMXm9zdKKqH9wt7R9IIVZ+K7ShzfpLV/Zg8+VyrBJYB4lpg==", - "dev": true - }, - "commander": { - "version": "9.5.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz", - "integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==", - "dev": true, - "optional": true - }, - "debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, - "requires": { - "ms": "2.1.2" - } - }, - "esbuild": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.18.20.tgz", - "integrity": "sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA==", - "dev": true, - "requires": { - "@esbuild/android-arm": "0.18.20", - "@esbuild/android-arm64": "0.18.20", - "@esbuild/android-x64": "0.18.20", - "@esbuild/darwin-arm64": "0.18.20", - "@esbuild/darwin-x64": "0.18.20", - "@esbuild/freebsd-arm64": "0.18.20", - "@esbuild/freebsd-x64": "0.18.20", - "@esbuild/linux-arm": "0.18.20", - "@esbuild/linux-arm64": "0.18.20", - "@esbuild/linux-ia32": "0.18.20", - "@esbuild/linux-loong64": "0.18.20", - "@esbuild/linux-mips64el": "0.18.20", - "@esbuild/linux-ppc64": "0.18.20", - "@esbuild/linux-riscv64": "0.18.20", - "@esbuild/linux-s390x": "0.18.20", - "@esbuild/linux-x64": "0.18.20", - "@esbuild/netbsd-x64": "0.18.20", - "@esbuild/openbsd-x64": "0.18.20", - "@esbuild/sunos-x64": "0.18.20", - "@esbuild/win32-arm64": "0.18.20", - "@esbuild/win32-ia32": "0.18.20", - "@esbuild/win32-x64": "0.18.20" - } - }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true - }, - "estree-walker": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", - "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", - "dev": true - }, - "fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true - }, - "fast-glob": { - "version": "3.2.12", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz", - "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==", - "dev": true, - "requires": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" - } - }, - "fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true - }, - "fastq": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", - "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", - "dev": true, - "requires": { - "reusify": "^1.0.4" - } - }, - "fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, - "requires": { - "to-regex-range": "^5.0.1" - } - }, - "fs-extra": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", - "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - } - }, - "fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "dev": true, - "optional": true - }, - "function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true - }, - "glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "requires": { - "is-glob": "^4.0.1" - } - }, - "globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true - }, - "graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true - }, - "has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, - "requires": { - "function-bind": "^1.1.1" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true - }, - "import-lazy": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-4.0.0.tgz", - "integrity": "sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw==", - "dev": true - }, - "is-core-module": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.11.0.tgz", - "integrity": "sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==", - "dev": true, - "requires": { - "has": "^1.0.3" - } - }, - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "dev": true - }, - "is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, - "requires": { - "is-extglob": "^2.1.1" - } - }, - "is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true - }, - "javascript-natural-sort": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/javascript-natural-sort/-/javascript-natural-sort-0.7.1.tgz", - "integrity": "sha512-nO6jcEfZWQXDhOiBtG2KvKyEptz7RVbpGP4vTD2hLBdmNQSsCiicO2Ioinv6UI4y9ukqnBpy+XZ9H6uLNgJTlw==", - "dev": true - }, - "jju": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/jju/-/jju-1.4.0.tgz", - "integrity": "sha512-8wb9Yw966OSxApiCt0K3yNJL8pnNeIv+OEq2YMidz4FKP6nonSRoOXc80iXY4JaN2FC11B9qsNmDsm+ZOfMROA==", - "dev": true - }, - "js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true - }, - "jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", - "dev": true - }, - "json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.6", - "universalify": "^2.0.0" - } - }, - "kolorist": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/kolorist/-/kolorist-1.7.0.tgz", - "integrity": "sha512-ymToLHqL02udwVdbkowNpzjFd6UzozMtshPQKVi5k1EjKRqKqBrOnE9QbLEb0/pV76SAiIT13hdL8R6suc+f3g==", - "dev": true - }, - "lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dev": true - }, - "lodash.get": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", - "integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==", - "dev": true - }, - "lodash.isequal": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", - "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==", - "dev": true - }, - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "requires": { - "yallist": "^4.0.0" - } - }, - "magic-string": { - "version": "0.29.0", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.29.0.tgz", - "integrity": "sha512-WcfidHrDjMY+eLjlU+8OvwREqHwpgCeKVBUpQ3OhYYuvfaYCUgcbuBzappNzZvg/v8onU3oQj+BYpkOJe9Iw4Q==", - "dev": true, - "requires": { - "@jridgewell/sourcemap-codec": "^1.4.13" - } - }, - "merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true - }, - "micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", - "dev": true, - "requires": { - "braces": "^3.0.2", - "picomatch": "^2.3.1" - } - }, - "minimatch": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", - "dev": true, - "requires": { - "brace-expansion": "^2.0.1" - } - }, - "mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "dev": true - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "nanoid": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz", - "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==", - "dev": true - }, - "path-browserify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", - "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==", - "dev": true - }, - "path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true - }, - "picocolors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", - "dev": true - }, - "picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true - }, - "postcss": { - "version": "8.4.31", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", - "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", - "dev": true, - "requires": { - "nanoid": "^3.3.6", - "picocolors": "^1.0.0", - "source-map-js": "^1.0.2" - } - }, - "prettier": { - "version": "2.8.7", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.7.tgz", - "integrity": "sha512-yPngTo3aXUUmyuTjeTUT75txrf+aMh9FiD7q9ZE/i6r0bPb22g4FsE6Y338PQX1bmfy08i9QQCB7/rcUAVntfw==", - "dev": true - }, - "punycode": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", - "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", - "dev": true - }, - "queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true - }, - "resolve": { - "version": "1.22.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", - "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", - "dev": true, - "requires": { - "is-core-module": "^2.9.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - } - }, - "reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "dev": true - }, - "rollup": { - "version": "3.29.4", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.29.4.tgz", - "integrity": "sha512-oWzmBZwvYrU0iJHtDmhsm662rC15FRXmcjCk1xD771dFDx5jJ02ufAQQTn0etB2emNk4J9EZg/yWKpsn9BWGRw==", - "dev": true, - "requires": { - "fsevents": "~2.3.2" - } - }, - "run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "dev": true, - "requires": { - "queue-microtask": "^1.2.2" - } - }, - "semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "source-map-js": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", - "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", - "dev": true - }, - "sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", - "dev": true - }, - "string-argv": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.2.tgz", - "integrity": "sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==", - "dev": true - }, - "strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - }, - "supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "dev": true - }, - "to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", - "dev": true - }, - "to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "requires": { - "is-number": "^7.0.0" - } - }, - "ts-morph": { - "version": "17.0.1", - "resolved": "https://registry.npmjs.org/ts-morph/-/ts-morph-17.0.1.tgz", - "integrity": "sha512-10PkHyXmrtsTvZSL+cqtJLTgFXkU43Gd0JCc0Rw6GchWbqKe0Rwgt1v3ouobTZwQzF1mGhDeAlWYBMGRV7y+3g==", - "dev": true, - "requires": { - "@ts-morph/common": "~0.18.0", - "code-block-writer": "^11.0.3" - } - }, - "typescript": { - "version": "4.9.5", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", - "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", - "dev": true - }, - "universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", - "dev": true - }, - "uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, - "requires": { - "punycode": "^2.1.0" - } - }, - "validator": { - "version": "13.9.0", - "resolved": "https://registry.npmjs.org/validator/-/validator-13.9.0.tgz", - "integrity": "sha512-B+dGG8U3fdtM0/aNK4/X8CXq/EcxU2WPrPEkJGslb47qyHsxmbggTWK0yEA4qnYVNF+nxNlN88o14hIcPmSIEA==", - "dev": true - }, - "vite": { - "version": "4.5.3", - "resolved": "https://registry.npmjs.org/vite/-/vite-4.5.3.tgz", - "integrity": "sha512-kQL23kMeX92v3ph7IauVkXkikdDRsYMGTVl5KY2E9OY4ONLvkHf04MDTbnfo6NKxZiDLWzVpP5oTa8hQD8U3dg==", - "dev": true, - "requires": { - "esbuild": "^0.18.10", - "fsevents": "~2.3.2", - "postcss": "^8.4.27", - "rollup": "^3.27.1" - } - }, - "vite-plugin-dts": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/vite-plugin-dts/-/vite-plugin-dts-2.2.0.tgz", - "integrity": "sha512-XmZtv02I7eGWm3DrZbLo1AdJK5gCisk9GqJBpY4N63pDYR6AVUnlyjFP5FCBvSBUfgE0Ppl90bKgtJU9k3AzFw==", - "dev": true, - "requires": { - "@babel/parser": "^7.20.15", - "@microsoft/api-extractor": "^7.33.5", - "@rollup/pluginutils": "^5.0.2", - "@rushstack/node-core-library": "^3.53.2", - "debug": "^4.3.4", - "fast-glob": "^3.2.12", - "fs-extra": "^10.1.0", - "kolorist": "^1.6.0", - "magic-string": "^0.29.0", - "ts-morph": "17.0.1" - } - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, - "z-schema": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/z-schema/-/z-schema-5.0.5.tgz", - "integrity": "sha512-D7eujBWkLa3p2sIpJA0d1pr7es+a7m0vFAnZLlCEKq/Ij2k0MLi9Br2UPxoxdYystm5K1yeBGzub0FlYUEWj2Q==", - "dev": true, - "requires": { - "commander": "^9.4.1", - "lodash.get": "^4.4.2", - "lodash.isequal": "^4.5.0", - "validator": "^13.7.0" - } - } - } -} diff --git a/extensions/broker-server-api/client-ts/package.json b/extensions/broker-server-api/client-ts/package.json deleted file mode 100644 index 101326fbf..000000000 --- a/extensions/broker-server-api/client-ts/package.json +++ /dev/null @@ -1,55 +0,0 @@ -{ - "name": "@sovity.de/broker-server-client", - "version": "0.0.0", - "description": "TypeScript API Client for the Broker Server developed by sovity.", - "author": "sovity GmbH", - "license": "Apache-2.0", - "homepage": "https://sovity.de", - "repository": { - "type": "git", - "url": "https://github.com/sovity/edc-broker-server-extension/" - }, - "publishConfig": { - "registry": "https://registry.npmjs.org/" - }, - "bugs": { - "url": "https://github.com/sovity/edc-broker-server-extension/issues/new/choose" - }, - "keywords": [ - "sovity", - "api client", - "edc", - "eclipse dataspace components", - "mobility data space", - "Catena-X", - "Mobilithek", - "broker" - ], - "type": "module", - "main": "./dist/sovity-broker-server-client.umd.cjs", - "module": "./dist/sovity-broker-server-client.js", - "types": "./dist/index.d.ts", - "exports": { - ".": { - "import": "./dist/sovity-broker-server-client.js", - "require": "./dist/sovity-broker-server-client.umd.cjs" - } - }, - "files": [ - "dist" - ], - "scripts": { - "dev": "vite", - "build": "npm run format-all && tsc && vite build", - "preview": "vite preview", - "format-all": "prettier --write ." - }, - "devDependencies": { - "@trivago/prettier-plugin-sort-imports": "^4.1.1", - "@types/node": "^18.15.11", - "prettier": "^2.8.7", - "typescript": "^4.9.3", - "vite": "^4.2.0", - "vite-plugin-dts": "^2.2.0" - } -} diff --git a/extensions/broker-server-api/client-ts/prettier.config.cjs b/extensions/broker-server-api/client-ts/prettier.config.cjs deleted file mode 100644 index fbcf1dc96..000000000 --- a/extensions/broker-server-api/client-ts/prettier.config.cjs +++ /dev/null @@ -1,26 +0,0 @@ -module.exports = { - tabWidth: 4, - useTabs: false, - singleQuote: true, - semi: true, - arrowParens: 'always', - trailingComma: 'all', - bracketSameLine: true, - printWidth: 80, - bracketSpacing: false, - proseWrap: 'always', - - // @trivago/prettier-plugin-sort-imports - importOrder: [ - '', - // rest after - '^[./]', - ], - importOrderParserPlugins: [ - 'typescript', - 'classProperties', - 'decorators-legacy', - ], - importOrderSeparation: false, - importOrderSortSpecifiers: true, -}; diff --git a/extensions/broker-server-api/client-ts/src/BrokerServerClient.ts b/extensions/broker-server-api/client-ts/src/BrokerServerClient.ts deleted file mode 100644 index f03bee56b..000000000 --- a/extensions/broker-server-api/client-ts/src/BrokerServerClient.ts +++ /dev/null @@ -1,42 +0,0 @@ -import { - BrokerServerApi, - Configuration, - ConfigurationParameters, -} from './generated'; - -/** - * API Client for our sovity Broker Server Client - */ -export interface BrokerServerClient { - brokerServerApi: BrokerServerApi; -} - -/** - * Configure & Build new Broker Server Client - * @param opts opts - */ -export function buildBrokerServerClient( - opts: BrokerServerClientOptions, -): BrokerServerClient { - const config = new Configuration({ - basePath: opts.managementApiUrl, - headers: { - 'x-api-key': opts.managementApiKey ?? 'ApiKeyDefaultValue', - }, - credentials: 'same-origin', - ...opts.configOverrides, - }); - - return { - brokerServerApi: new BrokerServerApi(config), - }; -} - -/** - * Options for instantiating an EDC API Client - */ -export interface BrokerServerClientOptions { - managementApiUrl: string; - managementApiKey?: string; - configOverrides?: Partial; -} diff --git a/extensions/broker-server-api/client-ts/src/generated/.gitignore b/extensions/broker-server-api/client-ts/src/generated/.gitignore deleted file mode 100644 index 654617bb0..000000000 --- a/extensions/broker-server-api/client-ts/src/generated/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -**/* -!.gitignore diff --git a/extensions/broker-server-api/client-ts/src/index.ts b/extensions/broker-server-api/client-ts/src/index.ts deleted file mode 100644 index 861cb71d7..000000000 --- a/extensions/broker-server-api/client-ts/src/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from './BrokerServerClient'; -export * from './generated'; diff --git a/extensions/broker-server-api/client-ts/src/vite-env.d.ts b/extensions/broker-server-api/client-ts/src/vite-env.d.ts deleted file mode 100644 index 11f02fe2a..000000000 --- a/extensions/broker-server-api/client-ts/src/vite-env.d.ts +++ /dev/null @@ -1 +0,0 @@ -/// diff --git a/extensions/broker-server-api/client-ts/tsconfig.json b/extensions/broker-server-api/client-ts/tsconfig.json deleted file mode 100644 index 138755d01..000000000 --- a/extensions/broker-server-api/client-ts/tsconfig.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "compilerOptions": { - "target": "ESNext", - "useDefineForClassFields": true, - "module": "ESNext", - "lib": ["ESNext", "DOM"], - "moduleResolution": "Node", - "strict": true, - "resolveJsonModule": true, - "isolatedModules": true, - "esModuleInterop": true, - "noEmit": true, - "noUnusedLocals": false, - "noUnusedParameters": false, - "noImplicitReturns": true, - "skipLibCheck": true - }, - "include": ["src"] -} diff --git a/extensions/broker-server-api/client-ts/vite.config.ts b/extensions/broker-server-api/client-ts/vite.config.ts deleted file mode 100644 index e8143fc31..000000000 --- a/extensions/broker-server-api/client-ts/vite.config.ts +++ /dev/null @@ -1,17 +0,0 @@ -// noinspection JSUnusedGlobalSymbols -import {resolve} from 'path'; -import {defineConfig} from 'vite'; -import dts from 'vite-plugin-dts'; - -// https://vitejs.dev/guide/build.html#library-mode -export default defineConfig({ - build: { - lib: { - entry: resolve(__dirname, 'src/index.ts'), - name: 'sovity-broker-server-client', - fileName: 'sovity-broker-server-client', - }, - sourcemap: true, - }, - plugins: [dts()], -}); diff --git a/extensions/broker-server-api/client/README.md b/extensions/broker-server-api/client/README.md deleted file mode 100644 index 1eed30e4f..000000000 --- a/extensions/broker-server-api/client/README.md +++ /dev/null @@ -1,69 +0,0 @@ - -
-
- - Logo - - -

Broker Server API Java Client Library

- -

- Report Bug - · - Request Feature -

-
- - -## About this component - -Java API Client Library to be imported and used in arbitrary applications like use-case backends. - -## Installation - -```xml - - - de.sovity.broker - client - ${sovity-edc-broker-server-extension.version} - -``` - -## Usage Example - -```java -import de.sovity.edc.ext.brokerserver.client.BrokerServerClient; -import de.sovity.edc.ext.brokerserver.client.gen.model.CatalogPageQuery; -import de.sovity.edc.ext.brokerserver.client.gen.model.CatalogPageResult; - -/** - * Example using the Broker Server API Java Client Library - */ -public class BrokerServerClientExample { - - public static final String BROKER_MANAGEMENT_API_URL = "http://localhost:11002/api/v1/management"; - public static final String BROKER_MANAGEMENT_API_KEY = "..."; - - public static void main(String[] args) { - // Configure Client - BrokerServerClient client = BrokerServerClient.builder() - .managementApiUrl(BROKER_MANAGEMENT_API_URL) - .managementApiKey(BROKER_MANAGEMENT_API_KEY) - .build(); - - // EDC API Wrapper APIs are now available for use - CatalogPageQuery catalogPageQuery = new CatalogPageQuery(); - CatalogPageResult catalogPageResult = client.brokerServerApi().catalogPage(catalogPageQuery); - System.out.println(catalogPageResult.getDataOffers()); - } -} -``` - -## License - -Apache License 2.0 - see [LICENSE](../../../LICENSE) - -## Contact - -sovity GmbH - contact@sovity.de diff --git a/extensions/broker-server-api/client/build.gradle.kts b/extensions/broker-server-api/client/build.gradle.kts deleted file mode 100644 index efabfe7b2..000000000 --- a/extensions/broker-server-api/client/build.gradle.kts +++ /dev/null @@ -1,137 +0,0 @@ - -plugins { - `java-library` - `maven-publish` - alias(libs.plugins.openapi.generator7) -} - -repositories { - mavenCentral() -} - -// By using a separate configuration we can skip having the Extension Jar in our runtime classpath -val openapiYaml = configurations.create("openapiGenerator") -val buildDir = layout.buildDirectory.get().asFile - -dependencies { - // We only need the openapi.yaml file from this dependency - openapiYaml(project(":extensions:broker-server-api:api")) { - isTransitive = false - } - - // Generated Client's Dependencies - implementation(libs.swagger.annotations) - implementation(libs.findbugs.jsr305) - implementation(libs.okhttp.okhttp) - implementation(libs.okhttp.loggingInterceptor) - implementation(libs.gson) - implementation(libs.gsonFire) - implementation(libs.openapi.jacksonDatabindNullable) - implementation(libs.apache.commonsLang) - implementation(libs.jakarta.annotationApi) - - // Lombok - compileOnly(libs.lombok) - annotationProcessor(libs.lombok) -} - -tasks.getByName("test") { - useJUnitPlatform() -} - -// Extract the openapi file from the JAR -val openapiFileName = "broker-server.yaml" -val targetLocation = buildDir.resolve("openapi") -val extractOpenapiYaml by tasks.registering(Copy::class) { - dependsOn(openapiYaml) - into(targetLocation) - from(zipTree(openapiYaml.singleFile)) { - include(openapiFileName) - } -} - -val openApiGenerate = tasks.getByName("openApiGenerate") { - dependsOn(extractOpenapiYaml) - generatorName.set("java") - configOptions.set( - mutableMapOf( - "invokerPackage" to "de.sovity.edc.ext.brokerserver.client.gen", - "apiPackage" to "de.sovity.edc.ext.brokerserver.client.gen.api", - "modelPackage" to "de.sovity.edc.ext.brokerserver.client.gen.model", - "caseInsensitiveResponseHeaders" to "true", - "additionalModelTypeAnnotations" to listOf( - "@lombok.AllArgsConstructor", - "@lombok.Builder", - "@SuppressWarnings(\"all\")" - ).joinToString("\n"), - "annotationLibrary" to "swagger1", - "hideGenerationTimestamp" to "true", - "useRuntimeException" to "true", - ) - ) - - inputSpec.set(targetLocation.resolve(openapiFileName).path) - outputDir.set("${buildDir}/generated/client-project") -} - -val postprocessGeneratedClient by tasks.registering(Copy::class) { - dependsOn(openApiGenerate) - from("${buildDir}/generated/client-project/src/main/java") - - // @lombok.Builder clashes with the following generated model file. - // It is the base class for OAS3 polymorphism via allOf/anyOf, which we won't use anyway. - exclude("**/AbstractOpenApiSchema.java") - - // The Jax-RS dependency suggested by the generated project was causing issues with quarkus. - // It was again only required for the polymorphism, which we won't use anyway. - filter { if (it == "import javax.ws.rs.core.GenericType;") "" else it } - - into("${buildDir}/generated/sources/openapi/java/main") -} -sourceSets["main"].java.srcDir("${buildDir}/generated/sources/openapi/java/main") - -checkstyle { - // Checkstyle loathes the generated files - // TODO make checkstyle skip generated files only - this.sourceSets = emptyList() -} - - -tasks.getByName("compileJava") { - dependsOn(postprocessGeneratedClient) - options.compilerArgs = listOf("-Xlint:none") -} - -val sourcesJar = tasks.getByName("sourcesJar") { - dependsOn(postprocessGeneratedClient) -} - -val javadocJar = tasks.getByName("javadocJar") { - dependsOn(postprocessGeneratedClient) -} - -artifacts { - add("archives", sourcesJar) - add("archives", javadocJar) -} - -java { - sourceCompatibility = JavaVersion.VERSION_11 - targetCompatibility = JavaVersion.VERSION_11 -} - -tasks.withType { - val fullOptions = this.options as StandardJavadocDocletOptions - fullOptions.tags = listOf("http.response.details:a:Http Response Details") - fullOptions.addStringOption("Xdoclint:none", "-quiet") -} - -group = libs.versions.sovityBrokerServerGroup.get() - -publishing { - publications { - create(project.name) { - from(components["java"]) - } - } -} diff --git a/extensions/broker-server-api/client/src/main/java/de/sovity/edc/ext/brokerserver/client/BrokerServerClient.java b/extensions/broker-server-api/client/src/main/java/de/sovity/edc/ext/brokerserver/client/BrokerServerClient.java deleted file mode 100644 index fcfec3d17..000000000 --- a/extensions/broker-server-api/client/src/main/java/de/sovity/edc/ext/brokerserver/client/BrokerServerClient.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (c) 2022 sovity GmbH - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - * - * Contributors: - * sovity GmbH - initial API and implementation - * - */ - -package de.sovity.edc.ext.brokerserver.client; - -import de.sovity.edc.ext.brokerserver.client.gen.api.BrokerServerApi; -import lombok.Value; -import lombok.experimental.Accessors; - -/** - * API Client for the Broker Server. - */ -@Value -@Accessors(fluent = true) -public class BrokerServerClient { - BrokerServerApi brokerServerApi; - - public static BrokerServerClientBuilder builder() { - return new BrokerServerClientBuilder(); - } -} diff --git a/extensions/broker-server-api/client/src/main/java/de/sovity/edc/ext/brokerserver/client/BrokerServerClientBuilder.java b/extensions/broker-server-api/client/src/main/java/de/sovity/edc/ext/brokerserver/client/BrokerServerClientBuilder.java deleted file mode 100644 index ce5d34e7b..000000000 --- a/extensions/broker-server-api/client/src/main/java/de/sovity/edc/ext/brokerserver/client/BrokerServerClientBuilder.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (c) 2022 sovity GmbH - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - * - * Contributors: - * sovity GmbH - initial API and implementation - * - */ - -package de.sovity.edc.ext.brokerserver.client; - -import lombok.Getter; -import lombok.Setter; -import lombok.experimental.Accessors; - -@Getter -@Setter -@Accessors(fluent = true, chain = true) -public class BrokerServerClientBuilder { - /** - * Management API Base URL, e.g. https://my-broker.com/backend/management - */ - private String managementApiUrl; - - /** - * Enables EDC Management API Key authentication. - */ - private String managementApiKey = "ApiKeyDefaultValue"; - - public BrokerServerClient build() { - return BrokerServerClientFactory.newClient(this); - } -} diff --git a/extensions/broker-server-api/client/src/main/java/de/sovity/edc/ext/brokerserver/client/BrokerServerClientFactory.java b/extensions/broker-server-api/client/src/main/java/de/sovity/edc/ext/brokerserver/client/BrokerServerClientFactory.java deleted file mode 100644 index 01bb388a4..000000000 --- a/extensions/broker-server-api/client/src/main/java/de/sovity/edc/ext/brokerserver/client/BrokerServerClientFactory.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (c) 2022 sovity GmbH - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - * - * Contributors: - * sovity GmbH - initial API and implementation - * - */ - -package de.sovity.edc.ext.brokerserver.client; - -import de.sovity.edc.ext.brokerserver.client.gen.ApiClient; -import de.sovity.edc.ext.brokerserver.client.gen.api.BrokerServerApi; -import lombok.AccessLevel; -import lombok.NoArgsConstructor; -import org.apache.commons.lang3.StringUtils; - -/** - * Builds {@link BrokerServerClient}s. - */ -@NoArgsConstructor(access = AccessLevel.PRIVATE) -public class BrokerServerClientFactory { - - public static BrokerServerClient newClient(BrokerServerClientBuilder builder) { - var apiClient = new ApiClient() - .setServerIndex(null) - .setBasePath(builder.managementApiUrl()); - - if (StringUtils.isNotBlank(builder.managementApiKey())) { - apiClient.addDefaultHeader("x-api-key", builder.managementApiKey()); - } - - return new BrokerServerClient( - new BrokerServerApi(apiClient) - ); - } -} diff --git a/extensions/broker-server-postgres-flyway-jooq/src/main/java/de/sovity/edc/ext/brokerserver/db/DslContextFactoryHijacker.java b/extensions/broker-server-postgres-flyway-jooq/src/main/java/de/sovity/edc/ext/brokerserver/db/DslContextFactoryHijacker.java deleted file mode 100644 index 3dd3c95e3..000000000 --- a/extensions/broker-server-postgres-flyway-jooq/src/main/java/de/sovity/edc/ext/brokerserver/db/DslContextFactoryHijacker.java +++ /dev/null @@ -1,38 +0,0 @@ -package de.sovity.edc.ext.brokerserver.db; - -import lombok.Getter; -import lombok.NoArgsConstructor; -import org.jooq.DSLContext; - -/** - * Hijack all {@link DslContextFactory}s from test code (single thread only) - */ -@NoArgsConstructor(access = lombok.AccessLevel.PRIVATE) -public class DslContextFactoryHijacker { - @Getter - private static DSLContext parentDslContext = null; - - /** - * Our tests currently have no access to the running extension's context, save for REST calls. - *
- * We use this class to hack all DslContextFactories via {@link #parentDslContext}. - *
- * If we set the {@link #parentDslContext} to one we created with a transaction we won't commit, we won't have to reset the DB between tests. - * - * @param testTransactionDslContext parent dsl context containing the parent transaction - * @param r code to run - */ - public static void withParentDslContext(DSLContext testTransactionDslContext, Runnable r) { - if (parentDslContext != null) { - throw new IllegalStateException("Tests are being run in parallel, which won't work with our current architecture."); - } - - DslContextFactoryHijacker.parentDslContext = testTransactionDslContext; - - try { - r.run(); - } finally { - DslContextFactoryHijacker.parentDslContext = null; - } - } -} diff --git a/extensions/broker-server-postgres-flyway-jooq/src/main/java/de/sovity/edc/ext/brokerserver/db/FlywayFactory.java b/extensions/broker-server-postgres-flyway-jooq/src/main/java/de/sovity/edc/ext/brokerserver/db/FlywayFactory.java deleted file mode 100644 index bee8c7b36..000000000 --- a/extensions/broker-server-postgres-flyway-jooq/src/main/java/de/sovity/edc/ext/brokerserver/db/FlywayFactory.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (c) 2023 sovity GmbH - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - * - * Contributors: - * sovity GmbH - initial implementation - * - */ - -package de.sovity.edc.ext.brokerserver.db; - -import lombok.RequiredArgsConstructor; -import org.eclipse.edc.spi.system.configuration.Config; -import org.flywaydb.core.Flyway; - -import javax.sql.DataSource; - -import static de.sovity.edc.ext.brokerserver.db.PostgresFlywayExtension.FLYWAY_CLEAN_ENABLE; - -/** - * Quickly launch {@link Flyway} from EDC Config - */ -@RequiredArgsConstructor -public class FlywayFactory { - private final Config config; - - /** - * Configure and launch {@link Flyway}. - * - * @param dataSource data source - * @return {@link Flyway} - */ - public Flyway setupFlyway(DataSource dataSource) { - return Flyway.configure() - .baselineOnMigrate(true) - .dataSource(dataSource) - .cleanDisabled(!config.getBoolean(FLYWAY_CLEAN_ENABLE, false)) - .table("flyway_schema_history") - .locations("classpath:db/migration") - .mixed(true) - .load(); - } -} diff --git a/extensions/broker-server-postgres-flyway-jooq/src/main/java/de/sovity/edc/ext/brokerserver/db/FlywayMigrator.java b/extensions/broker-server-postgres-flyway-jooq/src/main/java/de/sovity/edc/ext/brokerserver/db/FlywayMigrator.java deleted file mode 100644 index 92111349f..000000000 --- a/extensions/broker-server-postgres-flyway-jooq/src/main/java/de/sovity/edc/ext/brokerserver/db/FlywayMigrator.java +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright (c) 2023 sovity GmbH - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - * - * Contributors: - * sovity GmbH - initial implementation - * - */ - -package de.sovity.edc.ext.brokerserver.db; - -import lombok.RequiredArgsConstructor; -import org.eclipse.edc.spi.monitor.Monitor; -import org.eclipse.edc.spi.persistence.EdcPersistenceException; -import org.eclipse.edc.spi.system.configuration.Config; -import org.flywaydb.core.Flyway; -import org.flywaydb.core.api.FlywayException; - - -/** - * Custom flyway migration logic and logging. - */ -@RequiredArgsConstructor -public class FlywayMigrator { - private final Flyway flyway; - private final Config config; - private final Monitor monitor; - - /** - * Run migrations and potentially run flyway repair - */ - public void migrateAndRepair() { - if (config.getBoolean(PostgresFlywayExtension.FLYWAY_CLEAN, false)) { - monitor.info("Cleaning database before migrations, since %s=true and %s=true.".formatted( - PostgresFlywayExtension.FLYWAY_CLEAN_ENABLE, PostgresFlywayExtension.FLYWAY_CLEAN - )); - flyway.clean(); - } - try { - migrate(); - } catch (FlywayException e) { - if (isFlywayRepairEnabled()) { - try { - repair(); - migrate(); - } catch (FlywayException e2) { - throw migrationFailed(e2); - } - } else { - throw migrationFailed(e); - } - } - } - - private void migrate() { - var migrateResult = flyway.migrate(); - if (migrateResult.migrationsExecuted > 0) { - monitor.info(String.format( - "Successfully migrated database from version %s to version %s", - migrateResult.initialSchemaVersion, - migrateResult.targetSchemaVersion - )); - } else { - monitor.info(String.format( - "No migration necessary. Current version is %s", - migrateResult.initialSchemaVersion - )); - } - } - - private void repair() { - var repairResult = flyway.repair(); - if (!repairResult.repairActions.isEmpty()) { - var repairActions = String.join(", ", repairResult.repairActions); - monitor.info(String.format("Flyway Repair actions: %s", repairActions)); - } - - if (!repairResult.warnings.isEmpty()) { - var warnings = String.join(", ", repairResult.warnings); - throw new EdcPersistenceException(String.format("Flyway Repair failed: %s", warnings)); - } - } - - private boolean isFlywayRepairEnabled() { - return config.getBoolean(PostgresFlywayExtension.FLYWAY_REPAIR, true); - } - - - private EdcPersistenceException migrationFailed(FlywayException e) { - return new EdcPersistenceException("Flyway migration failed", e); - } -} diff --git a/extensions/broker-server-postgres-flyway-jooq/src/main/java/de/sovity/edc/ext/brokerserver/db/PostgresFlywayExtension.java b/extensions/broker-server-postgres-flyway-jooq/src/main/java/de/sovity/edc/ext/brokerserver/db/PostgresFlywayExtension.java deleted file mode 100644 index c887c9a1b..000000000 --- a/extensions/broker-server-postgres-flyway-jooq/src/main/java/de/sovity/edc/ext/brokerserver/db/PostgresFlywayExtension.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (c) 2023 sovity GmbH - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - * - * Contributors: - * sovity GmbH - initial implementation - * - */ - -package de.sovity.edc.ext.brokerserver.db; - -import com.zaxxer.hikari.HikariDataSource; -import org.eclipse.edc.runtime.metamodel.annotation.Setting; -import org.eclipse.edc.spi.system.ServiceExtension; -import org.eclipse.edc.spi.system.ServiceExtensionContext; - -public class PostgresFlywayExtension implements ServiceExtension { - @Setting(required = true) - public static final String JDBC_URL = "edc.datasource.default.url"; - @Setting(required = true) - public static final String JDBC_USER = "edc.datasource.default.user"; - @Setting(required = true) - public static final String JDBC_PASSWORD = "edc.datasource.default.password"; - @Setting - public static final String FLYWAY_REPAIR = "edc.flyway.repair"; - @Setting - public static final String FLYWAY_CLEAN_ENABLE = "edc.flyway.clean.enable"; - @Setting - public static final String FLYWAY_CLEAN = "edc.flyway.clean"; - @Setting - public static final String DB_CONNECTION_POOL_SIZE = "edc.broker.server.db.connection.pool.size"; - @Setting - public static final String DB_CONNECTION_TIMEOUT_IN_MS = "edc.broker.server.db.connection.timeout.in.ms"; - - private HikariDataSource dataSource; - - @Override - public String name() { - return "Postgres Flyway Extension (Broker Server)"; - } - - @Override - public void initialize(ServiceExtensionContext context) { - var config = context.getConfig(); - var monitor = context.getMonitor(); - - var dataSourceFactory = new DataSourceFactory(config); - dataSource = dataSourceFactory.newDataSource(); - - var flywayFactory = new FlywayFactory(config); - var flyway = flywayFactory.setupFlyway(dataSource); - var flywayMigrator = new FlywayMigrator(flyway, config, monitor); - flywayMigrator.migrateAndRepair(); - } - - @Override - public void shutdown() { - dataSource.close(); - } -} diff --git a/extensions/broker-server-postgres-flyway-jooq/src/main/java/de/sovity/edc/ext/brokerserver/db/utils/ConfigUtils.java b/extensions/broker-server-postgres-flyway-jooq/src/main/java/de/sovity/edc/ext/brokerserver/db/utils/ConfigUtils.java deleted file mode 100644 index 0efef4996..000000000 --- a/extensions/broker-server-postgres-flyway-jooq/src/main/java/de/sovity/edc/ext/brokerserver/db/utils/ConfigUtils.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (c) 2023 sovity GmbH - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - * - * Contributors: - * sovity GmbH - initial implementation - * - */ - -package de.sovity.edc.ext.brokerserver.db.utils; - -import lombok.AccessLevel; -import lombok.NoArgsConstructor; -import org.apache.commons.lang3.Validate; -import org.eclipse.edc.spi.system.configuration.Config; - -@NoArgsConstructor(access = AccessLevel.PRIVATE) -public class ConfigUtils { - - public static String getRequiredStringProperty(Config config, String name) { - String value = config.getString(name, ""); - Validate.notBlank(value, "EDC Property '%s' is required".formatted(name)); - return value; - } -} diff --git a/extensions/broker-server-postgres-flyway-jooq/src/main/java/de/sovity/edc/ext/brokerserver/db/utils/JdbcCredentials.java b/extensions/broker-server-postgres-flyway-jooq/src/main/java/de/sovity/edc/ext/brokerserver/db/utils/JdbcCredentials.java deleted file mode 100644 index e6d664ce2..000000000 --- a/extensions/broker-server-postgres-flyway-jooq/src/main/java/de/sovity/edc/ext/brokerserver/db/utils/JdbcCredentials.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (c) 2023 sovity GmbH - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - * - * Contributors: - * sovity GmbH - initial implementation - * - */ - -package de.sovity.edc.ext.brokerserver.db.utils; - -import de.sovity.edc.ext.brokerserver.db.PostgresFlywayExtension; -import org.eclipse.edc.spi.system.configuration.Config; - -/** - * JDBC Credentials - * - * @param jdbcUrl JDBC URL without credentials - * @param jdbcUser JDBC User - * @param jdbcPassword JDBC Password - */ -public record JdbcCredentials( - String jdbcUrl, - String jdbcUser, - String jdbcPassword -) { - public static JdbcCredentials fromConfig(Config config) { - return new JdbcCredentials( - ConfigUtils.getRequiredStringProperty(config, PostgresFlywayExtension.JDBC_URL), - ConfigUtils.getRequiredStringProperty(config, PostgresFlywayExtension.JDBC_USER), - ConfigUtils.getRequiredStringProperty(config, PostgresFlywayExtension.JDBC_PASSWORD) - ); - } -} diff --git a/extensions/broker-server-postgres-flyway-jooq/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension b/extensions/broker-server-postgres-flyway-jooq/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension deleted file mode 100644 index 1f8b84893..000000000 --- a/extensions/broker-server-postgres-flyway-jooq/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension +++ /dev/null @@ -1 +0,0 @@ -de.sovity.edc.ext.brokerserver.db.PostgresFlywayExtension \ No newline at end of file diff --git a/extensions/broker-server-postgres-flyway-jooq/src/main/resources/db/migration/V1__MS8.sql b/extensions/broker-server-postgres-flyway-jooq/src/main/resources/db/migration/V1__MS8.sql deleted file mode 100644 index 9c5ff65f3..000000000 --- a/extensions/broker-server-postgres-flyway-jooq/src/main/resources/db/migration/V1__MS8.sql +++ /dev/null @@ -1,529 +0,0 @@ --- --- Copyright (c) 2022 Daimler TSS GmbH --- --- This program and the accompanying materials are made available under the --- terms of the Apache License, Version 2.0 which is available at --- https://www.apache.org/licenses/LICENSE-2.0 --- --- SPDX-License-Identifier: Apache-2.0 --- --- Contributors: --- Daimler TSS GmbH - Initial SQL Query --- - --- THIS SCHEMA HAS BEEN WRITTEN AND TESTED ONLY FOR POSTGRES - --- table: edc_asset -CREATE TABLE IF NOT EXISTS edc_asset -( - asset_id VARCHAR NOT NULL, - PRIMARY KEY (asset_id) -); - --- table: edc_asset_dataaddress -CREATE TABLE IF NOT EXISTS edc_asset_dataaddress -( - asset_id_fk VARCHAR NOT NULL, - properties JSON NOT NULL, - PRIMARY KEY (asset_id_fk), - FOREIGN KEY (asset_id_fk) REFERENCES edc_asset (asset_id) ON DELETE CASCADE -); -COMMENT ON COLUMN edc_asset_dataaddress.properties IS 'DataAddress properties serialized as JSON'; - --- table: edc_asset_property -CREATE TABLE IF NOT EXISTS edc_asset_property -( - asset_id_fk VARCHAR NOT NULL, - property_name VARCHAR NOT NULL, - property_value VARCHAR NOT NULL, - property_type VARCHAR NOT NULL, - PRIMARY KEY (asset_id_fk, property_name), - FOREIGN KEY (asset_id_fk) REFERENCES edc_asset (asset_id) ON DELETE CASCADE -); - -COMMENT ON COLUMN edc_asset_property.property_name IS - 'Asset property key'; -COMMENT ON COLUMN edc_asset_property.property_value IS - 'Asset property value'; -COMMENT ON COLUMN edc_asset_property.property_type IS - 'Asset property class name'; - -CREATE INDEX IF NOT EXISTS idx_edc_asset_property_value - ON edc_asset_property (property_name, property_value); - --- --- Copyright (c) 2023 sovity GmbH --- --- This program and the accompanying materials are made available under the --- terms of the Apache License, Version 2.0 which is available at --- https://www.apache.org/licenses/LICENSE-2.0 --- --- SPDX-License-Identifier: Apache-2.0 --- --- Contributors: --- sovity GmbH - Update Tables to Milestone-7 EDC --- --- - -ALTER TABLE edc_asset - ADD created_at BIGINT; - -UPDATE edc_asset -SET created_at=EXTRACT(EPOCH FROM CURRENT_TIMESTAMP) * 1000; - -ALTER TABLE edc_asset - ALTER COLUMN created_at SET NOT NULL; - --- --- Copyright (c) 2022 Daimler TSS GmbH --- --- This program and the accompanying materials are made available under the --- terms of the Apache License, Version 2.0 which is available at --- https://www.apache.org/licenses/LICENSE-2.0 --- --- SPDX-License-Identifier: Apache-2.0 --- --- Contributors: --- Daimler TSS GmbH - Initial SQL Query --- Microsoft Corporation - refactoring --- - --- table: edc_contract_definitions --- only intended for and tested with H2 and Postgres! -CREATE TABLE IF NOT EXISTS edc_contract_definitions -( - contract_definition_id VARCHAR NOT NULL, - access_policy_id VARCHAR NOT NULL, - contract_policy_id VARCHAR NOT NULL, - selector_expression JSON NOT NULL, - PRIMARY KEY (contract_definition_id) -); - --- --- Copyright (c) 2023 sovity GmbH --- --- This program and the accompanying materials are made available under the --- terms of the Apache License, Version 2.0 which is available at --- https://www.apache.org/licenses/LICENSE-2.0 --- --- SPDX-License-Identifier: Apache-2.0 --- --- Contributors: --- sovity GmbH - Update Tables to Milestone-7 EDC --- --- -ALTER TABLE edc_contract_definitions - ADD created_at BIGINT; - -UPDATE edc_contract_definitions -SET created_at=EXTRACT(EPOCH FROM CURRENT_TIMESTAMP) * 1000; - -ALTER TABLE edc_contract_definitions - ALTER COLUMN created_at SET NOT NULL; - --- --- Copyright (c) 2023 sovity GmbH --- --- This program and the accompanying materials are made available under the --- terms of the Apache License, Version 2.0 which is available at --- https://www.apache.org/licenses/LICENSE-2.0 --- --- SPDX-License-Identifier: Apache-2.0 --- --- Contributors: --- sovity GmbH - Update Tables to Milestone-8 EDC --- --- - -ALTER TABLE edc_contract_definitions - ADD validity BIGINT; --- --- Copyright (c) 2023 sovity GmbH --- --- This program and the accompanying materials are made available under the --- terms of the Apache License, Version 2.0 which is available at --- https://www.apache.org/licenses/LICENSE-2.0 --- --- SPDX-License-Identifier: Apache-2.0 --- --- Contributors: --- sovity GmbH - Update Tables to Milestone-8 EDC --- --- -UPDATE edc_contract_definitions -SET validity=60 * 60 * 24 * 365 -WHERE validity IS NULL; - --- Statements are designed for and tested with Postgres only! - -CREATE TABLE IF NOT EXISTS edc_lease -( - leased_by VARCHAR NOT NULL, - leased_at BIGINT, - lease_duration INTEGER DEFAULT 60000 NOT NULL, - lease_id VARCHAR NOT NULL - CONSTRAINT lease_pk - PRIMARY KEY -); - -COMMENT ON COLUMN edc_lease.leased_at IS 'posix timestamp of lease'; - -COMMENT ON COLUMN edc_lease.lease_duration IS 'duration of lease in milliseconds'; - - -CREATE UNIQUE INDEX IF NOT EXISTS lease_lease_id_uindex - ON edc_lease (lease_id); - - - -CREATE TABLE IF NOT EXISTS edc_contract_agreement -( - agr_id VARCHAR NOT NULL - CONSTRAINT contract_agreement_pk - PRIMARY KEY, - provider_agent_id VARCHAR, - consumer_agent_id VARCHAR, - signing_date BIGINT, - start_date BIGINT, - end_date INTEGER, - asset_id VARCHAR NOT NULL, - policy JSON -); - - -CREATE TABLE IF NOT EXISTS edc_contract_negotiation -( - id VARCHAR NOT NULL - CONSTRAINT contract_negotiation_pk - PRIMARY KEY, - correlation_id VARCHAR, - counterparty_id VARCHAR NOT NULL, - counterparty_address VARCHAR NOT NULL, - protocol VARCHAR DEFAULT 'ids-multipart'::CHARACTER VARYING NOT NULL, - type INTEGER DEFAULT 0 NOT NULL, - state INTEGER DEFAULT 0 NOT NULL, - state_count INTEGER DEFAULT 0, - state_timestamp BIGINT, - error_detail VARCHAR, - agreement_id VARCHAR - CONSTRAINT contract_negotiation_contract_agreement_id_fk - REFERENCES edc_contract_agreement, - contract_offers JSON, - trace_context JSON, - lease_id VARCHAR - CONSTRAINT contract_negotiation_lease_lease_id_fk - REFERENCES edc_lease - ON DELETE SET NULL, - CONSTRAINT provider_correlation_id CHECK (type = '0' OR correlation_id IS NOT NULL) -); - -COMMENT ON COLUMN edc_contract_negotiation.agreement_id IS 'ContractAgreement serialized as JSON'; - -COMMENT ON COLUMN edc_contract_negotiation.contract_offers IS 'List serialized as JSON'; - -COMMENT ON COLUMN edc_contract_negotiation.trace_context IS 'Map serialized as JSON'; - - -CREATE INDEX IF NOT EXISTS contract_negotiation_correlationid_index - ON edc_contract_negotiation (correlation_id); - -CREATE UNIQUE INDEX IF NOT EXISTS contract_negotiation_id_uindex - ON edc_contract_negotiation (id); - -CREATE UNIQUE INDEX IF NOT EXISTS contract_agreement_id_uindex - ON edc_contract_agreement (agr_id); - --- --- Copyright (c) 2023 sovity GmbH --- --- This program and the accompanying materials are made available under the --- terms of the Apache License, Version 2.0 which is available at --- https://www.apache.org/licenses/LICENSE-2.0 --- --- SPDX-License-Identifier: Apache-2.0 --- --- Contributors: --- sovity GmbH - Update Tables to Milestone-7 EDC --- --- -ALTER TABLE edc_contract_negotiation - ADD created_at BIGINT, - ADD updated_at BIGINT; - -UPDATE edc_contract_negotiation -SET created_at=EXTRACT(EPOCH FROM CURRENT_TIMESTAMP) * 1000; -UPDATE edc_contract_negotiation -SET updated_at=created_at; - -ALTER TABLE edc_contract_negotiation - ALTER COLUMN created_at SET NOT NULL; -ALTER TABLE edc_contract_negotiation - ALTER COLUMN updated_at SET NOT NULL; - --- --- Copyright (c) 2023 sovity GmbH --- --- This program and the accompanying materials are made available under the --- terms of the Apache License, Version 2.0 which is available at --- https://www.apache.org/licenses/LICENSE-2.0 --- --- SPDX-License-Identifier: Apache-2.0 --- --- Contributors: --- sovity GmbH - Update Tables to Milestone-7 EDC --- --- - -UPDATE edc_contract_negotiation -SET contract_offers = co.contract_offers_edited -FROM (SELECT cn.id, - jsonb_agg( - jsonb_set( - jsonb_set( - elems, - '{contractStart}', - to_json(to_char(to_timestamp(created_at / 1000) AT TIME ZONE 'UTC', - 'YYYY-MM-DD"T"HH24:MI:SS.MS"Z"')::text)::jsonb - ), - '{contractEnd}', - to_json(to_char(to_timestamp((created_at / 1000) + 60 * 60 * 24 * 365) AT TIME ZONE 'UTC', - 'YYYY-MM-DD"T"HH24:MI:SS.MS"Z"')::text)::jsonb - ) - )::json as contract_offers_edited - FROM edc_contract_negotiation cn, - jsonb_array_elements(cn.contract_offers::jsonb) elems - GROUP BY cn.id) co -WHERE edc_contract_negotiation.id = co.id; - --- --- Copyright (c) 2023 sovity GmbH --- --- This program and the accompanying materials are made available under the --- terms of the Apache License, Version 2.0 which is available at --- https://www.apache.org/licenses/LICENSE-2.0 --- --- SPDX-License-Identifier: Apache-2.0 --- --- Contributors: --- sovity GmbH - initial API and implementation for DataplaneInstances --- --- -CREATE TABLE IF NOT EXISTS edc_data_plane_instance -( - id VARCHAR NOT NULL, - data JSON NOT NULL, - PRIMARY KEY (id) -); - --- --- Copyright (c) 2022 ZF Friedrichshafen AG --- --- This program and the accompanying materials are made available under the --- terms of the Apache License, Version 2.0 which is available at --- https://www.apache.org/licenses/LICENSE-2.0 --- --- SPDX-License-Identifier: Apache-2.0 --- --- Contributors: --- ZF Friedrichshafen AG - Initial SQL Query --- - --- Statements are designed for and tested with Postgres only! - --- table: edc_policydefinitions -CREATE TABLE IF NOT EXISTS edc_policydefinitions -( - policy_id VARCHAR NOT NULL, - permissions JSON, - prohibitions JSON, - duties JSON, - extensible_properties JSON, - inherits_from VARCHAR, - assigner VARCHAR, - assignee VARCHAR, - target VARCHAR, - policy_type VARCHAR NOT NULL, - PRIMARY KEY (policy_id) -); - -COMMENT ON COLUMN edc_policydefinitions.permissions IS 'Java List serialized as JSON'; -COMMENT ON COLUMN edc_policydefinitions.prohibitions IS 'Java List serialized as JSON'; -COMMENT ON COLUMN edc_policydefinitions.duties IS 'Java List serialized as JSON'; -COMMENT ON COLUMN edc_policydefinitions.extensible_properties IS 'Java Map serialized as JSON'; -COMMENT ON COLUMN edc_policydefinitions.policy_type IS 'Java PolicyType serialized as JSON'; - -CREATE UNIQUE INDEX IF NOT EXISTS edc_policydefinitions_id_uindex - ON edc_policydefinitions (policy_id); - --- --- Copyright (c) 2023 sovity GmbH --- --- This program and the accompanying materials are made available under the --- terms of the Apache License, Version 2.0 which is available at --- https://www.apache.org/licenses/LICENSE-2.0 --- --- SPDX-License-Identifier: Apache-2.0 --- --- Contributors: --- sovity GmbH - Update Tables to Milestone-7 EDC --- --- -ALTER TABLE edc_policydefinitions - ADD created_at BIGINT; - -UPDATE edc_policydefinitions -SET created_at=EXTRACT(EPOCH FROM CURRENT_TIMESTAMP) * 1000; - -ALTER TABLE edc_policydefinitions - ALTER COLUMN created_at SET NOT NULL; - --- Statements are designed for and tested with Postgres only! - -CREATE TABLE IF NOT EXISTS edc_lease -( - leased_by VARCHAR NOT NULL, - leased_at BIGINT, - lease_duration INTEGER NOT NULL, - lease_id VARCHAR NOT NULL - CONSTRAINT lease_pk - PRIMARY KEY -); - -COMMENT ON COLUMN edc_lease.leased_at IS 'posix timestamp of lease'; - -COMMENT ON COLUMN edc_lease.lease_duration IS 'duration of lease in milliseconds'; - -CREATE TABLE IF NOT EXISTS edc_transfer_process -( - transferprocess_id VARCHAR NOT NULL - CONSTRAINT transfer_process_pk - PRIMARY KEY, - type VARCHAR NOT NULL, - state INTEGER NOT NULL, - state_count INTEGER DEFAULT 0 NOT NULL, - state_time_stamp BIGINT, - created_time_stamp BIGINT, - trace_context JSON, - error_detail VARCHAR, - resource_manifest JSON, - provisioned_resource_set JSON, - content_data_address JSON, - deprovisioned_resources JSON, - lease_id VARCHAR - CONSTRAINT transfer_process_lease_lease_id_fk - REFERENCES edc_lease - ON DELETE SET NULL -); - -COMMENT ON COLUMN edc_transfer_process.trace_context IS 'Java Map serialized as JSON'; - -COMMENT ON COLUMN edc_transfer_process.resource_manifest IS 'java ResourceManifest serialized as JSON'; - -COMMENT ON COLUMN edc_transfer_process.provisioned_resource_set IS 'ProvisionedResourceSet serialized as JSON'; - -COMMENT ON COLUMN edc_transfer_process.content_data_address IS 'DataAddress serialized as JSON'; - -COMMENT ON COLUMN edc_transfer_process.deprovisioned_resources IS 'List of deprovisioned resources, serialized as JSON'; - - -CREATE UNIQUE INDEX IF NOT EXISTS transfer_process_id_uindex - ON edc_transfer_process (transferprocess_id); - -CREATE TABLE IF NOT EXISTS edc_data_request -( - datarequest_id VARCHAR NOT NULL - CONSTRAINT data_request_pk - PRIMARY KEY, - process_id VARCHAR NOT NULL, - connector_address VARCHAR NOT NULL, - protocol VARCHAR NOT NULL, - connector_id VARCHAR, - asset_id VARCHAR NOT NULL, - contract_id VARCHAR NOT NULL, - data_destination JSON NOT NULL, - managed_resources BOOLEAN DEFAULT TRUE, - properties JSON, - transfer_type JSON, - transfer_process_id VARCHAR NOT NULL - CONSTRAINT data_request_transfer_process_id_fk - REFERENCES edc_transfer_process - ON UPDATE RESTRICT ON DELETE CASCADE -); - -COMMENT ON COLUMN edc_data_request.data_destination IS 'DataAddress serialized as JSON'; - -COMMENT ON COLUMN edc_data_request.properties IS 'java Map serialized as JSON'; - -COMMENT ON COLUMN edc_data_request.transfer_type IS 'TransferType serialized as JSON'; - - -CREATE UNIQUE INDEX IF NOT EXISTS data_request_id_uindex - ON edc_data_request (datarequest_id); - -CREATE UNIQUE INDEX IF NOT EXISTS lease_lease_id_uindex - ON edc_lease (lease_id); - --- --- Copyright (c) 2023 sovity GmbH --- --- This program and the accompanying materials are made available under the --- terms of the Apache License, Version 2.0 which is available at --- https://www.apache.org/licenses/LICENSE-2.0 --- --- SPDX-License-Identifier: Apache-2.0 --- --- Contributors: --- sovity GmbH - Update Tables to Milestone-7 EDC --- --- - -ALTER TABLE edc_transfer_process - RENAME COLUMN created_time_stamp TO created_at; - -UPDATE edc_transfer_process -SET created_at = EXTRACT(EPOCH FROM CURRENT_TIMESTAMP) * 1000 -WHERE created_at = NULL; - -ALTER TABLE edc_transfer_process - ADD updated_at BIGINT; - -UPDATE edc_transfer_process -SET updated_at=created_at; - -ALTER TABLE edc_transfer_process - ALTER COLUMN updated_at SET NOT NULL; -ALTER TABLE edc_transfer_process - ALTER COLUMN created_at SET NOT NULL; - --- --- Copyright (c) 2023 sovity GmbH --- --- This program and the accompanying materials are made available under the --- terms of the Apache License, Version 2.0 which is available at --- https://www.apache.org/licenses/LICENSE-2.0 --- --- SPDX-License-Identifier: Apache-2.0 --- --- Contributors: --- sovity GmbH - Update Tables to Milestone-8 EDC --- --- -ALTER TABLE edc_transfer_process - ADD transferprocess_properties JSON; - --- --- Copyright (c) 2023 sovity GmbH --- --- This program and the accompanying materials are made available under the --- terms of the Apache License, Version 2.0 which is available at --- https://www.apache.org/licenses/LICENSE-2.0 --- --- SPDX-License-Identifier: Apache-2.0 --- --- Contributors: --- sovity GmbH - Update Tables to Milestone-8 EDC --- --- -UPDATE edc_transfer_process -SET transferprocess_properties = '{}'::json -WHERE transferprocess_properties IS NULL; diff --git a/extensions/broker-server-postgres-flyway-jooq/src/main/resources/db/migration/V2__PoC.sql b/extensions/broker-server-postgres-flyway-jooq/src/main/resources/db/migration/V2__PoC.sql deleted file mode 100644 index 45481e629..000000000 --- a/extensions/broker-server-postgres-flyway-jooq/src/main/resources/db/migration/V2__PoC.sql +++ /dev/null @@ -1,94 +0,0 @@ -create type connector_online_status as enum ('ONLINE', 'OFFLINE'); -create type measurement_type as enum ('CONNECTOR_REFRESH'); -create type measurement_error_status as enum ('ERROR', 'OK'); - -create table connector -( - endpoint text not null, - connector_id text not null, - created_at timestamp with time zone not null, - last_refresh_attempt_at timestamp with time zone, - last_successful_refresh_at timestamp with time zone, - online_status connector_online_status not null, - - PRIMARY KEY (endpoint) -); - -create table data_offer -( - connector_endpoint text not null, - asset_id text not null, - asset_properties jsonb not null, - created_at timestamp with time zone not null, - updated_at timestamp with time zone, - - PRIMARY KEY (connector_endpoint, asset_id), - FOREIGN KEY (connector_endpoint) REFERENCES connector (endpoint) -); - -create table data_offer_contract_offer -( - contract_offer_id text not null, - connector_endpoint text not null, - asset_id text not null, - policy jsonb not null, - created_at timestamp with time zone not null, - updated_at timestamp with time zone, - - PRIMARY KEY (contract_offer_id), - FOREIGN KEY (connector_endpoint, asset_id) REFERENCES data_offer (connector_endpoint, asset_id), - FOREIGN KEY (connector_endpoint) REFERENCES connector (endpoint) -); - -create type broker_event_type as enum ( - --Connector was successfully updated, and changes were incorporated - 'CONNECTOR_UPDATED', - - --Connector went online - 'CONNECTOR_STATUS_CHANGE_ONLINE', - - --Connector went offline - 'CONNECTOR_STATUS_CHANGE_OFFLINE', - - --Connector was "force deleted" - 'CONNECTOR_STATUS_CHANGE_FORCE_DELETED', - - --Contract Offer was updated - 'CONTRACT_OFFER_UPDATED', - - --Contract Offer was clicked - 'CONTRACT_OFFER_CLICK' -); - -create type broker_event_status as enum ( - -- Default - 'OK', - - -- Failures - 'ERROR' -); - -create table broker_event_log -( - id serial primary key, - created_at timestamp with time zone not null, - user_message text not null, - event broker_event_type not null, - event_status broker_event_status not null, - connector_endpoint text, - asset_id text, - error_stack text, - duration_in_ms bigint -); - -create table broker_execution_time_measurement -( - id serial primary key, - created_at timestamp with time zone not null, - connector_endpoint text not null, - duration_in_ms bigint not null, - type measurement_type not null, - error_status measurement_error_status not null -); - -create index speedup on broker_event_log (connector_endpoint, asset_id, event_status); diff --git a/extensions/broker-server-postgres-flyway-jooq/src/main/resources/db/migration/V3_1__MvP.sql b/extensions/broker-server-postgres-flyway-jooq/src/main/resources/db/migration/V3_1__MvP.sql deleted file mode 100644 index ecffc4e51..000000000 --- a/extensions/broker-server-postgres-flyway-jooq/src/main/resources/db/migration/V3_1__MvP.sql +++ /dev/null @@ -1,36 +0,0 @@ -create collation if not exists alphanumeric_with_natural_sort (provider = icu, locale = 'en-u-kn-true'); - -create type connector_data_offers_exceeded as enum ('OK', 'EXCEEDED'); -create type connector_contract_offers_exceeded as enum ('OK', 'EXCEEDED'); - -alter table broker_event_log - drop column duration_in_ms; - -alter table connector - alter column endpoint type text collate alphanumeric_with_natural_sort, - add column data_offers_exceeded connector_data_offers_exceeded, - add column contract_offers_exceeded connector_contract_offers_exceeded; - -update connector -set data_offers_exceeded = 'OK', - contract_offers_exceeded = 'OK'; - -alter table connector - alter column data_offers_exceeded set not null, - alter column contract_offers_exceeded set not null; - -alter table data_offer - alter column asset_id type text collate alphanumeric_with_natural_sort, - add column asset_name text collate alphanumeric_with_natural_sort; - -update data_offer -set asset_name = coalesce(asset_properties ->> 'asset:prop:name', asset_id); - -alter table data_offer - alter column asset_name set not null; - --- update contract offer table's primary key -alter table data_offer_contract_offer - drop constraint data_offer_contract_offer_pkey; -alter table data_offer_contract_offer - add primary key (connector_endpoint, asset_id, contract_offer_id); diff --git a/extensions/broker-server-postgres-flyway-jooq/src/main/resources/db/migration/V3_2__MvP_Non_Transactional.sql b/extensions/broker-server-postgres-flyway-jooq/src/main/resources/db/migration/V3_2__MvP_Non_Transactional.sql deleted file mode 100644 index c39525a59..000000000 --- a/extensions/broker-server-postgres-flyway-jooq/src/main/resources/db/migration/V3_2__MvP_Non_Transactional.sql +++ /dev/null @@ -1,10 +0,0 @@ --- Changes to Enums are non-transactional and must be supplied in a separate migration script for flyway - --- Connector Data Offer Limit was exceeded -alter type broker_event_type add value 'CONNECTOR_DATA_OFFER_LIMIT_EXCEEDED'; --- Connector Data Offer Limit was not exceeded -alter type broker_event_type add value 'CONNECTOR_DATA_OFFER_LIMIT_OK'; --- Connector Contract Offer Limit was exceeded -alter type broker_event_type add value 'CONNECTOR_CONTRACT_OFFER_LIMIT_EXCEEDED'; --- Connector Contract Offer Limit was not exceeded -alter type broker_event_type add value 'CONNECTOR_CONTRACT_OFFER_LIMIT_OK'; diff --git a/extensions/broker-server-postgres-flyway-jooq/src/main/resources/db/migration/V4_1__MvP_Bugfixes_1_1_0.sql b/extensions/broker-server-postgres-flyway-jooq/src/main/resources/db/migration/V4_1__MvP_Bugfixes_1_1_0.sql deleted file mode 100644 index da600f9e5..000000000 --- a/extensions/broker-server-postgres-flyway-jooq/src/main/resources/db/migration/V4_1__MvP_Bugfixes_1_1_0.sql +++ /dev/null @@ -1,9 +0,0 @@ -create table data_offer_view_count ( - id serial primary key, - connector_endpoint text not null, - asset_id text not null, - date timestamp with time zone not null -); - -create index data_offer_view_count_speedup on data_offer_view_count (connector_endpoint, asset_id); - diff --git a/extensions/broker-server-postgres-flyway-jooq/src/main/resources/db/migration/V4_2__MvP_Bugfixes_Non_Transactional.sql b/extensions/broker-server-postgres-flyway-jooq/src/main/resources/db/migration/V4_2__MvP_Bugfixes_Non_Transactional.sql deleted file mode 100644 index 986e58cfd..000000000 --- a/extensions/broker-server-postgres-flyway-jooq/src/main/resources/db/migration/V4_2__MvP_Bugfixes_Non_Transactional.sql +++ /dev/null @@ -1,5 +0,0 @@ --- Changes to Enums are non-transactional and must be supplied in a separate migration script for flyway - --- Connector deleted due to being offline for too long -alter type broker_event_type add value 'CONNECTOR_KILLED_DUE_TO_OFFLINE_FOR_TOO_LONG'; -alter type connector_online_status add value 'DEAD'; diff --git a/extensions/broker-server-postgres-flyway-jooq/src/main/resources/db/migration/V5_1__MvP_Fix_Asset_JSON_Properties.sql b/extensions/broker-server-postgres-flyway-jooq/src/main/resources/db/migration/V5_1__MvP_Fix_Asset_JSON_Properties.sql deleted file mode 100644 index fea8c8173..000000000 --- a/extensions/broker-server-postgres-flyway-jooq/src/main/resources/db/migration/V5_1__MvP_Fix_Asset_JSON_Properties.sql +++ /dev/null @@ -1,18 +0,0 @@ --- Maps JSON Asset Properties to String --- '{"a": "b", "c": [1, 2], "d": true}'::jsonb becomes '{"a": "b", "c": "[1, 2]", "d": "true"}'::jsonb -create -or replace function pg_temp.migrate_asset_properties(asset_properties jsonb) returns jsonb as -$$ -begin -return (select jsonb_object_agg(key, case when jsonb_typeof(value) = 'string' then value #>> '{}' else value::text end) - from jsonb_each(asset_properties)); -end; -$$ -language plpgsql; - --- Fix existing data offer asssets -update data_offer -set asset_properties = pg_temp.migrate_asset_properties(asset_properties); - --- Add new Event Log Status -alter type broker_event_type add value 'CONNECTOR_DELETED'; diff --git a/extensions/broker-server-postgres-flyway-jooq/src/main/resources/db/migration/V6__EDC0.sql b/extensions/broker-server-postgres-flyway-jooq/src/main/resources/db/migration/V6__EDC0.sql deleted file mode 100644 index c8edbe6fc..000000000 --- a/extensions/broker-server-postgres-flyway-jooq/src/main/resources/db/migration/V6__EDC0.sql +++ /dev/null @@ -1,166 +0,0 @@ --- Migration Script for Broker from MS8 to EDC 0 - --- Migrates an Asset ID -create - or replace function pg_temp.migrate_asset_id(asset_id text) returns text as -$$ -begin - return replace(replace(asset_id::text, 'urn:artifact:', ''), ':', '-'); -end; -$$ - language plpgsql; - --- Migrates a Connector Endpoint to EDC 0 -create - or replace function pg_temp.migrate_connector_endpoint(endpoint text) returns text as -$$ -begin - return pg_temp.replace_suffix(endpoint, '/api/v1/ids/data', '/api/dsp'); -end; -$$ - language plpgsql; - --- Creates a valid Asset JSON-LD from an Asset ID and Asset Title -create - or replace function pg_temp.build_asset_json_ld(asset_id text, asset_title text) returns jsonb as -$$ -begin - return jsonb_build_object( - '@id', asset_id, - 'https://w3id.org/edc/v0.0.1/ns/properties', jsonb_build_object( - 'https://w3id.org/edc/v0.0.1/ns/id', asset_id, - 'http://purl.org/dc/terms/title', asset_title - ) - ); -end; -$$ - language plpgsql; - --- Utility Function: replaceSuffix -create - or replace function pg_temp.replace_suffix(str text, old_suffix text, new_suffix text) returns text as -$$ -begin - return case - when pg_temp.ends_with(str, old_suffix) then - left(str, length(str) - length(old_suffix)) || new_suffix - else - str - end; -end; -$$ - language plpgsql; - --- Utility Function: endsWith -create or replace function pg_temp.ends_with(str text, suffix text) - returns boolean as -$$ -begin - return right(str, length(suffix)) = suffix; -end; -$$ language plpgsql; - --- Utility Function: Drops fkey constraints that have auto-generated names. Different Postgresql versions generated different names. -create or replace function pg_temp.drop_constraints_containing_fkey(table_name text) - returns void as -$$ -declare - i record; -begin - for i in (select conname - from pg_catalog.pg_constraint con - inner join pg_catalog.pg_class rel on rel.oid = con.conrelid - inner join pg_catalog.pg_namespace nsp on nsp.oid = connamespace - where rel.relname = table_name - and conname like '%fkey%') - loop - execute format('alter table %s drop constraint %s', table_name, i.conname); - end loop; -end; -$$ language plpgsql; - - --- Remove Connector Tables --- All connector tables should be empty --- There should be no references from broker tables to connector tables -drop table edc_asset cascade; -drop table edc_asset_dataaddress cascade; -drop table edc_asset_property cascade; -drop table edc_contract_agreement cascade; -drop table edc_contract_definitions cascade; -drop table edc_contract_negotiation cascade; -drop table edc_data_plane_instance cascade; -drop table edc_data_request cascade; -drop table edc_lease cascade; -drop table edc_policydefinitions cascade; -drop table edc_transfer_process cascade; - - --- Drop constraints -select pg_temp.drop_constraints_containing_fkey('data_offer'); -select pg_temp.drop_constraints_containing_fkey('data_offer_contract_offer'); - --- Migrate Connector Endpoints -update broker_event_log -set connector_endpoint = pg_temp.migrate_connector_endpoint(connector_endpoint); -update broker_execution_time_measurement -set connector_endpoint = pg_temp.migrate_connector_endpoint(connector_endpoint); -update connector -set endpoint = pg_temp.migrate_connector_endpoint(endpoint); -update data_offer -set connector_endpoint = pg_temp.migrate_connector_endpoint(connector_endpoint); -update data_offer_contract_offer -set connector_endpoint = pg_temp.migrate_connector_endpoint(connector_endpoint); -update data_offer_view_count -set connector_endpoint = pg_temp.migrate_connector_endpoint(connector_endpoint); - - --- Migrate Asset IDs -update broker_event_log -set asset_id = pg_temp.migrate_asset_id(asset_id); -update data_offer -set asset_id = pg_temp.migrate_asset_id(asset_id); -update data_offer_contract_offer -set asset_id = pg_temp.migrate_asset_id(asset_id); -update data_offer_view_count -set asset_id = pg_temp.migrate_asset_id(asset_id); - --- Rename data_offer_contract_offer to contract_offer -alter table data_offer_contract_offer - rename to contract_offer; - --- Rename Connector ID to Participant ID -alter table connector - rename column connector_id to participant_id; - --- Add constraints -alter table data_offer - add constraint data_offer_connector_endpoint_fkey - foreign key (connector_endpoint) references connector (endpoint); -alter table contract_offer - add constraint contract_offer_data_offer_fkey - foreign key (connector_endpoint, asset_id) references data_offer (connector_endpoint, asset_id); -alter table contract_offer - add constraint contract_offer_connector_fkey - foreign key (connector_endpoint) references connector (endpoint); - --- Migrate to Asset JSON-LD -alter table data_offer - rename column asset_properties to asset_json_ld; -alter table data_offer - rename column asset_name to asset_title; -update data_offer -set asset_json_ld = pg_temp.build_asset_json_ld(asset_id, asset_title); - --- Extracted Asset Metadata from the JSON-LD for Search / Filtering -alter table data_offer - add column description text not null default '', - add column curator_organization_name text not null default '', - add column data_category text not null default '', - add column data_subcategory text not null default '', - add column data_model text not null default '', - add column transport_mode text not null default '', - add column geo_reference_method text not null default '', - add column keywords text[] not null default '{}', - -- comma joined keywords for easier search - add column keywords_comma_joined text not null default ''; diff --git a/extensions/broker-server-postgres-flyway-jooq/src/main/resources/db/migration/V7__Organization_Metadata.sql b/extensions/broker-server-postgres-flyway-jooq/src/main/resources/db/migration/V7__Organization_Metadata.sql deleted file mode 100644 index d3e19bca0..000000000 --- a/extensions/broker-server-postgres-flyway-jooq/src/main/resources/db/migration/V7__Organization_Metadata.sql +++ /dev/null @@ -1,11 +0,0 @@ --- Create table for organization metadata -create table organization_metadata -( - mds_id text not null primary key, - name text not null -); - --- Add MDS-ID column to organization table -alter table connector add column mds_id text; -update connector set mds_id = split_part(participant_id, '.', 1) -where participant_id ~ '^MDSL[A-Za-z0-9]+\.C[A-Za-z0-9]+$'; diff --git a/extensions/broker-server-postgres-flyway-jooq/src/main/resources/db/testdata/V2_1__PoC_Test_Data.sql b/extensions/broker-server-postgres-flyway-jooq/src/main/resources/db/testdata/V2_1__PoC_Test_Data.sql deleted file mode 100644 index fd42a12dd..000000000 --- a/extensions/broker-server-postgres-flyway-jooq/src/main/resources/db/testdata/V2_1__PoC_Test_Data.sql +++ /dev/null @@ -1,69 +0,0 @@ --- Test Data to be added after V2 so we can test subsequent migrations - -insert into connector (endpoint, connector_id, created_at, last_refresh_attempt_at, last_successful_refresh_at, - online_status) -values ('https://my-connector.com/api/v1/ids/data', 'test-connector-1', '2019-01-01 00:00:00', - '2019-01-01 00:00:00', '2019-01-01 00:00:00', 'ONLINE'); -insert into data_offer (connector_endpoint, asset_id, asset_properties, created_at, updated_at) -values ('https://my-connector.com/api/v1/ids/data', - 'test-asset-1', - '{ - "asset:prop:id": "test-asset-1" - }', - '2019-01-01 00:00:00', - '2019-01-01 00:00:00'), - ('https://my-connector.com/api/v1/ids/data', - 'test-asset-2', - '{ - "asset:prop:id": "urn:artifact:db-rail-network-2023-jan", - "asset:prop:name": "Rail Network DB 2023 January", - "asset:prop:version": "1.1", - "asset:prop:originator": "https://example-connector.rail-mgmt.bahn.de/api/v1/api/v1/ids/data", - "asset:prop:originatorOrganization": "Deutsche Bahn AG", - "asset:prop:keywords": "db, bahn, rail, Rail-Designer", - "asset:prop:contenttype": "application/json", - "asset:prop:description": "Train Network Map released on 10.01.2023, valid until 31.02.2023. \nFile format is xyz as exported by Rail-Designer.", - "asset:prop:language": "https://w3id.org/idsa/code/EN", - "asset:prop:publisher": "https://my.cool-api.gg/about", - "asset:prop:standardLicense": "https://my.cool-api.gg/license", - "asset:prop:endpointDocumentation": "https://my.cool-api.gg/docs", - "http://w3id.org/mds#dataCategory": "Infrastructure and Logistics", - "http://w3id.org/mds#dataSubcategory": "General Information About Planning Of Routes", - "http://w3id.org/mds#dataModel": "my-data-model-001", - "http://w3id.org/mds#geoReferenceMethod": "my-geo-reference-method", - "http://w3id.org/mds#transportMode": "Rail" - }', - '2019-01-01 00:00:00', - '2019-01-01 00:00:00'); - -insert into data_offer_contract_offer (contract_offer_id, connector_endpoint, asset_id, policy, created_at, updated_at) -values ('test-contract-offer-1', - 'https://my-connector.com/api/v1/ids/data', - 'test-asset-1', - '"test-policy-1"', - '2019-01-01 00:00:00', - '2019-01-01 00:00:00'), - ('test-contract-offer-2', - 'https://my-connector.com/api/v1/ids/data', - 'test-asset-2', - '"test-policy-2"', - '2019-01-01 00:00:00', - '2019-01-01 00:00:00'); - -insert into broker_event_log (created_at, user_message, event, event_status, connector_endpoint, asset_id, error_stack, - duration_in_ms) -values ('2019-01-01 00:00:00', - 'Connector was successfully updated, and changes were incorporated', - 'CONNECTOR_UPDATED', - 'OK', - 'https://my-connector.com/api/v1/ids/data', - 'test-asset-1', - null, - 100); - -insert into broker_execution_time_measurement (connector_endpoint, created_at, type, error_status, duration_in_ms) -values ('https://my-connector.com/api/v1/ids/data', - '2019-01-01 00:00:00', - 'CONNECTOR_REFRESH', - 'OK', - 100); diff --git a/extensions/broker-server/README.md b/extensions/broker-server/README.md deleted file mode 100644 index 103af330b..000000000 --- a/extensions/broker-server/README.md +++ /dev/null @@ -1,38 +0,0 @@ - -
-
- - Logo - - -

EDC-Connector Extension:
Broker Server

- -

- Report Bug - · - Request Feature -

-
- -## About this Extension - -Implementation of an EDC Broker backend as an EDC Extension. - -This extension does multiple things: - -- Storage of Connectors and Data Offers -- Connector Crawling -- Connector Discovery -- API implementations for our the full management capabilities of our Broker UI - -## Why does this extension exist? - -To let the broker easily be a part of a data space we are implementing it on an EDC basis. - -## License - -Apache License 2.0 - see [LICENSE](../../LICENSE) - -## Contact - -sovity GmbH - contact@sovity.de diff --git a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/BrokerServerExtension.java b/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/BrokerServerExtension.java deleted file mode 100644 index 3b288ea13..000000000 --- a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/BrokerServerExtension.java +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Copyright (c) 2023 sovity GmbH - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - * - * Contributors: - * sovity GmbH - initial API and implementation - * - */ - -package de.sovity.edc.ext.brokerserver; - -import org.eclipse.edc.connector.api.management.configuration.ManagementApiConfiguration; -import org.eclipse.edc.connector.api.management.configuration.transform.ManagementApiTypeTransformerRegistry; -import org.eclipse.edc.connector.spi.catalog.CatalogService; -import org.eclipse.edc.jsonld.spi.JsonLd; -import org.eclipse.edc.runtime.metamodel.annotation.Inject; -import org.eclipse.edc.runtime.metamodel.annotation.Setting; -import org.eclipse.edc.spi.system.ServiceExtension; -import org.eclipse.edc.spi.system.ServiceExtensionContext; -import org.eclipse.edc.spi.types.TypeManager; -import org.eclipse.edc.web.spi.WebService; - -import static de.sovity.edc.ext.brokerserver.services.config.EdcConfigPropertyUtils.toEdcProp; - -public class BrokerServerExtension implements ServiceExtension { - - public static final String EXTENSION_NAME = "BrokerServerExtension"; - - @Setting - public static final String ADMIN_API_KEY = toEdcProp("EDC_BROKER_SERVER_ADMIN_API_KEY"); - - @Setting - public static final String KNOWN_CONNECTORS = toEdcProp("EDC_BROKER_SERVER_KNOWN_CONNECTORS"); - - @Setting - public static final String CRON_ONLINE_CONNECTOR_REFRESH = toEdcProp("EDC_BROKER_SERVER_CRON_ONLINE_CONNECTOR_REFRESH"); - - @Setting - public static final String CRON_OFFLINE_CONNECTOR_REFRESH = toEdcProp("EDC_BROKER_SERVER_CRON_OFFLINE_CONNECTOR_REFRESH"); - - @Setting - public static final String CRON_DEAD_CONNECTOR_REFRESH = toEdcProp("EDC_BROKER_SERVER_CRON_DEAD_CONNECTOR_REFRESH"); - - @Setting - public static final String NUM_THREADS = toEdcProp("EDC_BROKER_SERVER_NUM_THREADS"); - - @Setting - public static final String HIDE_OFFLINE_DATA_OFFERS_AFTER = toEdcProp("EDC_BROKER_SERVER_HIDE_OFFLINE_DATA_OFFERS_AFTER"); - - @Setting - public static final String MAX_DATA_OFFERS_PER_CONNECTOR = toEdcProp("EDC_BROKER_SERVER_MAX_DATA_OFFERS_PER_CONNECTOR"); - - @Setting - public static final String MAX_CONTRACT_OFFERS_PER_DATA_OFFER = toEdcProp("EDC_BROKER_SERVER_MAX_CONTRACT_OFFERS_PER_DATA_OFFER"); - - @Setting - public static final String CATALOG_PAGE_PAGE_SIZE = toEdcProp("EDC_BROKER_SERVER_CATALOG_PAGE_PAGE_SIZE"); - - @Setting - public static final String DEFAULT_CONNECTOR_DATASPACE = toEdcProp("EDC_BROKER_SERVER_DEFAULT_DATASPACE"); - - @Setting - public static final String KNOWN_DATASPACE_CONNECTORS = toEdcProp("EDC_BROKER_SERVER_KNOWN_DATASPACE_CONNECTORS"); - - @Setting - public static final String KILL_OFFLINE_CONNECTORS_AFTER = toEdcProp("EDC_BROKER_SERVER_KILL_OFFLINE_CONNECTORS_AFTER"); - - @Setting - public static final String SCHEDULED_KILL_OFFLINE_CONNECTORS = toEdcProp("EDC_BROKER_SERVER_SCHEDULED_KILL_OFFLINE_CONNECTORS"); - - @Inject - private ManagementApiConfiguration managementApiConfiguration; - - @Inject - private WebService webService; - - @Inject - private TypeManager typeManager; - - @Inject - private ManagementApiTypeTransformerRegistry typeTransformerRegistry; - - @Inject - private JsonLd jsonLd; - - @Inject - private CatalogService catalogService; - - /** - * Manual Dependency Injection Result - */ - private BrokerServerExtensionContext services; - - @Override - public String name() { - return EXTENSION_NAME; - } - - @Override - public void initialize(ServiceExtensionContext context) { - services = BrokerServerExtensionContextBuilder.buildContext( - context.getConfig(), - context.getMonitor(), - typeManager, - typeTransformerRegistry, - jsonLd, - catalogService - ); - - // This is a hack for tests, so we can access the running context from tests. - BrokerServerExtensionContext.instance = services; - - var managementApiGroup = managementApiConfiguration.getContextAlias(); - webService.registerResource(managementApiGroup, services.brokerServerResource()); - } - - @Override - public void start() { - services.brokerServerInitializer().onStartup(); - } -} diff --git a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/BrokerServerExtensionContext.java b/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/BrokerServerExtensionContext.java deleted file mode 100644 index 3dd8bd2fa..000000000 --- a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/BrokerServerExtensionContext.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (c) 2023 sovity GmbH - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - * - * Contributors: - * sovity GmbH - initial API and implementation - * - */ - -package de.sovity.edc.ext.brokerserver; - -import de.sovity.edc.ext.brokerserver.api.BrokerServerResource; -import de.sovity.edc.ext.brokerserver.services.BrokerServerInitializer; -import de.sovity.edc.ext.brokerserver.services.ConnectorCreator; -import de.sovity.edc.ext.brokerserver.services.refreshing.ConnectorUpdater; -import de.sovity.edc.ext.brokerserver.services.refreshing.offers.DataOfferRecordUpdater; -import de.sovity.edc.ext.brokerserver.services.refreshing.offers.FetchedCatalogBuilder; -import de.sovity.edc.ext.wrapper.api.common.mappers.PolicyMapper; - - -/** - * Manual Dependency Injection result - * - * @param brokerServerResource REST Resource with API Endpoint implementations - * @param brokerServerInitializer Startup Logic - */ -public record BrokerServerExtensionContext( - BrokerServerResource brokerServerResource, - BrokerServerInitializer brokerServerInitializer, - - // Required for Integration Tests - ConnectorUpdater connectorUpdater, - ConnectorCreator connectorCreator, - PolicyMapper policyMapper, - FetchedCatalogBuilder fetchedCatalogBuilder, - DataOfferRecordUpdater dataOfferRecordUpdater -) { - /** - * This is a hack for our tests. - *

- * Right now we have no good way to access the context from tests. - */ - public static BrokerServerExtensionContext instance; -} diff --git a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/BrokerServerExtensionContextBuilder.java b/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/BrokerServerExtensionContextBuilder.java deleted file mode 100644 index 8f78ffa67..000000000 --- a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/BrokerServerExtensionContextBuilder.java +++ /dev/null @@ -1,394 +0,0 @@ -/* - * Copyright (c) 2023 sovity GmbH - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - * - * Contributors: - * sovity GmbH - initial API and implementation - * - */ - -package de.sovity.edc.ext.brokerserver; - -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.SerializationFeature; -import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; -import de.sovity.edc.ext.brokerserver.dao.ConnectorQueries; -import de.sovity.edc.ext.brokerserver.dao.ContractOfferQueries; -import de.sovity.edc.ext.brokerserver.dao.DataOfferQueries; -import de.sovity.edc.ext.brokerserver.dao.pages.catalog.CatalogQueryAvailableFilterFetcher; -import de.sovity.edc.ext.brokerserver.dao.pages.catalog.CatalogQueryContractOfferFetcher; -import de.sovity.edc.ext.brokerserver.dao.pages.catalog.CatalogQueryDataOfferFetcher; -import de.sovity.edc.ext.brokerserver.dao.pages.catalog.CatalogQueryFilterService; -import de.sovity.edc.ext.brokerserver.dao.pages.catalog.CatalogQueryService; -import de.sovity.edc.ext.brokerserver.dao.pages.catalog.CatalogQuerySortingService; -import de.sovity.edc.ext.brokerserver.dao.pages.connector.ConnectorDetailQueryService; -import de.sovity.edc.ext.brokerserver.dao.pages.connector.ConnectorListQueryService; -import de.sovity.edc.ext.brokerserver.dao.pages.dataoffer.DataOfferDetailPageQueryService; -import de.sovity.edc.ext.brokerserver.dao.pages.dataoffer.ViewCountLogger; -import de.sovity.edc.ext.brokerserver.db.DataSourceFactory; -import de.sovity.edc.ext.brokerserver.db.DslContextFactory; -import de.sovity.edc.ext.brokerserver.services.BrokerServerInitializer; -import de.sovity.edc.ext.brokerserver.services.ConnectorCleaner; -import de.sovity.edc.ext.brokerserver.services.ConnectorCreator; -import de.sovity.edc.ext.brokerserver.services.ConnectorKiller; -import de.sovity.edc.ext.brokerserver.services.KnownConnectorsInitializer; -import de.sovity.edc.ext.brokerserver.services.OfflineConnectorKiller; -import de.sovity.edc.ext.brokerserver.services.api.AuthorityPortalConnectorDataOfferApiService; -import de.sovity.edc.ext.brokerserver.services.api.AuthorityPortalConnectorMetadataApiService; -import de.sovity.edc.ext.brokerserver.services.api.AuthorityPortalConnectorQueryService; -import de.sovity.edc.ext.brokerserver.services.api.AuthorityPortalOrganizationMetadataApiService; -import de.sovity.edc.ext.brokerserver.services.api.CatalogApiService; -import de.sovity.edc.ext.brokerserver.services.api.ConnectorApiService; -import de.sovity.edc.ext.brokerserver.services.api.ConnectorDetailApiService; -import de.sovity.edc.ext.brokerserver.services.api.ConnectorListApiService; -import de.sovity.edc.ext.brokerserver.services.api.ConnectorOnlineStatusMapper; -import de.sovity.edc.ext.brokerserver.services.api.ConnectorService; -import de.sovity.edc.ext.brokerserver.services.api.DataOfferDetailApiService; -import de.sovity.edc.ext.brokerserver.services.api.DataOfferMappingUtils; -import de.sovity.edc.ext.brokerserver.services.api.PaginationMetadataUtils; -import de.sovity.edc.ext.brokerserver.services.api.filtering.CatalogFilterAttributeDefinitionService; -import de.sovity.edc.ext.brokerserver.services.api.filtering.CatalogFilterService; -import de.sovity.edc.ext.brokerserver.services.api.filtering.CatalogSearchService; -import de.sovity.edc.ext.brokerserver.services.config.AdminApiKeyValidator; -import de.sovity.edc.ext.brokerserver.services.config.BrokerServerSettingsFactory; -import de.sovity.edc.ext.brokerserver.services.logging.BrokerEventLogger; -import de.sovity.edc.ext.brokerserver.services.logging.BrokerExecutionTimeLogger; -import de.sovity.edc.ext.brokerserver.services.queue.ConnectorQueue; -import de.sovity.edc.ext.brokerserver.services.queue.ConnectorQueueFiller; -import de.sovity.edc.ext.brokerserver.services.queue.ThreadPool; -import de.sovity.edc.ext.brokerserver.services.queue.ThreadPoolTaskQueue; -import de.sovity.edc.ext.brokerserver.services.refreshing.ConnectorUpdateFailureWriter; -import de.sovity.edc.ext.brokerserver.services.refreshing.ConnectorUpdateSuccessWriter; -import de.sovity.edc.ext.brokerserver.services.refreshing.ConnectorUpdater; -import de.sovity.edc.ext.brokerserver.services.refreshing.offers.CatalogFetcher; -import de.sovity.edc.ext.brokerserver.services.refreshing.offers.ContractOfferRecordUpdater; -import de.sovity.edc.ext.brokerserver.services.refreshing.offers.DataOfferLimitsEnforcer; -import de.sovity.edc.ext.brokerserver.services.refreshing.offers.DataOfferPatchApplier; -import de.sovity.edc.ext.brokerserver.services.refreshing.offers.DataOfferPatchBuilder; -import de.sovity.edc.ext.brokerserver.services.refreshing.offers.DataOfferRecordUpdater; -import de.sovity.edc.ext.brokerserver.services.refreshing.offers.DataOfferWriter; -import de.sovity.edc.ext.brokerserver.services.refreshing.offers.FetchedCatalogBuilder; -import de.sovity.edc.ext.brokerserver.services.schedules.DeadConnectorRefreshJob; -import de.sovity.edc.ext.brokerserver.services.schedules.OfflineConnectorKillerJob; -import de.sovity.edc.ext.brokerserver.services.schedules.OfflineConnectorRefreshJob; -import de.sovity.edc.ext.brokerserver.services.schedules.OnlineConnectorRefreshJob; -import de.sovity.edc.ext.brokerserver.services.schedules.QuartzScheduleInitializer; -import de.sovity.edc.ext.brokerserver.services.schedules.utils.CronJobRef; -import de.sovity.edc.ext.wrapper.api.common.mappers.AssetMapper; -import de.sovity.edc.ext.wrapper.api.common.mappers.PolicyMapper; -import de.sovity.edc.ext.wrapper.api.common.mappers.asset.AssetEditRequestMapper; -import de.sovity.edc.ext.wrapper.api.common.mappers.asset.AssetJsonLdBuilder; -import de.sovity.edc.ext.wrapper.api.common.mappers.asset.AssetJsonLdParser; -import de.sovity.edc.ext.wrapper.api.common.mappers.asset.utils.AssetJsonLdUtils; -import de.sovity.edc.ext.wrapper.api.common.mappers.asset.utils.EdcPropertyUtils; -import de.sovity.edc.ext.wrapper.api.common.mappers.asset.utils.ShortDescriptionBuilder; -import de.sovity.edc.ext.wrapper.api.common.mappers.dataaddress.DataSourceMapper; -import de.sovity.edc.ext.wrapper.api.common.mappers.dataaddress.http.HttpDataSourceMapper; -import de.sovity.edc.ext.wrapper.api.common.mappers.dataaddress.http.HttpHeaderMapper; -import de.sovity.edc.ext.wrapper.api.common.mappers.policy.AtomicConstraintMapper; -import de.sovity.edc.ext.wrapper.api.common.mappers.policy.ConstraintExtractor; -import de.sovity.edc.ext.wrapper.api.common.mappers.policy.LiteralMapper; -import de.sovity.edc.ext.wrapper.api.common.mappers.policy.OperatorMapper; -import de.sovity.edc.ext.wrapper.api.common.mappers.policy.PolicyValidator; -import de.sovity.edc.utils.catalog.DspCatalogService; -import de.sovity.edc.utils.catalog.mapper.DspDataOfferBuilder; -import lombok.NoArgsConstructor; -import org.eclipse.edc.connector.spi.catalog.CatalogService; -import org.eclipse.edc.jsonld.spi.JsonLd; -import org.eclipse.edc.runtime.metamodel.annotation.Inject; -import org.eclipse.edc.spi.CoreConstants; -import org.eclipse.edc.spi.monitor.Monitor; -import org.eclipse.edc.spi.system.configuration.Config; -import org.eclipse.edc.spi.types.TypeManager; -import org.eclipse.edc.transform.spi.TypeTransformerRegistry; -import org.jetbrains.annotations.NotNull; - -import java.util.List; - - -/** - * Manual Dependency Injection (DYDI). - *

- * We want to develop as Java Backend Development is done, but we have - * no CDI / DI Framework to rely on. - *

- * EDC {@link Inject} only works in {@link BrokerServerExtension}. - */ -@NoArgsConstructor(access = lombok.AccessLevel.PRIVATE) -public class BrokerServerExtensionContextBuilder { - - public static BrokerServerExtensionContext buildContext( - Config config, - Monitor monitor, - TypeManager typeManager, - TypeTransformerRegistry typeTransformerRegistry, - JsonLd jsonLd, - CatalogService catalogService - ) { - var brokerServerSettingsFactory = new BrokerServerSettingsFactory(config, monitor); - var brokerServerSettings = brokerServerSettingsFactory.buildBrokerServerSettings(); - var adminApiKeyValidator = new AdminApiKeyValidator(brokerServerSettings); - - // Dao - var dataOfferQueries = new DataOfferQueries(); - var dataSourceFactory = new DataSourceFactory(config); - var dataSource = dataSourceFactory.newDataSource(); - var dslContextFactory = new DslContextFactory(dataSource); - var connectorQueries = new ConnectorQueries(); - var catalogQuerySortingService = new CatalogQuerySortingService(); - var catalogSearchService = new CatalogSearchService(); - var catalogQueryFilterService = new CatalogQueryFilterService(brokerServerSettings, catalogSearchService); - var catalogQueryContractOfferFetcher = new CatalogQueryContractOfferFetcher(); - var catalogQueryDataOfferFetcher = new CatalogQueryDataOfferFetcher( - catalogQuerySortingService, - catalogQueryFilterService, - catalogQueryContractOfferFetcher - ); - var catalogQueryAvailableFilterFetcher = new CatalogQueryAvailableFilterFetcher(catalogQueryFilterService); - var catalogQueryService = new CatalogQueryService( - catalogQueryDataOfferFetcher, - catalogQueryAvailableFilterFetcher, - brokerServerSettings - ); - var connectorListQueryService = new ConnectorListQueryService(); - var connectorDetailQueryService = new ConnectorDetailQueryService(); - var dataOfferDetailPageQueryService = new DataOfferDetailPageQueryService( - catalogQueryContractOfferFetcher, brokerServerSettings); - - - // Services - var objectMapperJsonLd = getJsonLdObjectMapper(typeManager); - var brokerEventLogger = new BrokerEventLogger(); - var brokerExecutionTimeLogger = new BrokerExecutionTimeLogger(); - var contractOfferRecordUpdater = new ContractOfferRecordUpdater(); - var dataOfferRecordUpdater = new DataOfferRecordUpdater(); - var contractOfferQueries = new ContractOfferQueries(); - var dataOfferLimitsEnforcer = new DataOfferLimitsEnforcer(brokerServerSettings, brokerEventLogger); - var dataOfferPatchBuilder = new DataOfferPatchBuilder( - contractOfferQueries, - dataOfferQueries, - dataOfferRecordUpdater, - contractOfferRecordUpdater - ); - var dataOfferPatchApplier = new DataOfferPatchApplier(); - var dataOfferWriter = new DataOfferWriter(dataOfferPatchBuilder, dataOfferPatchApplier); - var connectorUpdateSuccessWriter = new ConnectorUpdateSuccessWriter( - brokerEventLogger, - dataOfferWriter, - dataOfferLimitsEnforcer - ); - var assetMapper = newAssetMapper(typeTransformerRegistry, jsonLd); - var fetchedDataOfferBuilder = new FetchedCatalogBuilder(assetMapper); - var dspDataOfferBuilder = new DspDataOfferBuilder(jsonLd); - var dspCatalogService = new DspCatalogService( - catalogService, - dspDataOfferBuilder - ); - var dataOfferFetcher = new CatalogFetcher(dspCatalogService, fetchedDataOfferBuilder); - var connectorUpdateFailureWriter = new ConnectorUpdateFailureWriter(brokerEventLogger, monitor); - var connectorUpdater = new ConnectorUpdater( - dataOfferFetcher, - connectorUpdateSuccessWriter, - connectorUpdateFailureWriter, - connectorQueries, - dslContextFactory, - monitor, - brokerExecutionTimeLogger - ); - var paginationMetadataUtils = new PaginationMetadataUtils(); - var threadPoolTaskQueue = new ThreadPoolTaskQueue(); - var threadPool = new ThreadPool(threadPoolTaskQueue, brokerServerSettings, monitor); - var connectorQueue = new ConnectorQueue(connectorUpdater, threadPool); - var connectorQueueFiller = new ConnectorQueueFiller(connectorQueue, connectorQueries); - var connectorCreator = new ConnectorCreator(connectorQueries); - var knownConnectorsInitializer = new KnownConnectorsInitializer( - config, - connectorQueue, - connectorCreator - ); - var catalogFilterAttributeDefinitionService = new CatalogFilterAttributeDefinitionService(); - var catalogFilterService = new CatalogFilterService(catalogFilterAttributeDefinitionService); - var viewCountLogger = new ViewCountLogger(); - var connectorService = new ConnectorService(connectorCreator, connectorQueue); - var connectorKiller = new ConnectorKiller(); - var connectorClearer = new ConnectorCleaner(); - var offlineConnectorKiller = new OfflineConnectorKiller( - brokerServerSettings, - connectorQueries, - brokerEventLogger, - connectorKiller, - connectorClearer - ); - var operatorMapper = new OperatorMapper(); - var literalMapper = new LiteralMapper( - objectMapperJsonLd - ); - var atomicConstraintMapper = new AtomicConstraintMapper( - literalMapper, - operatorMapper - ); - var policyValidator = new PolicyValidator(); - var constraintExtractor = new ConstraintExtractor( - policyValidator, - atomicConstraintMapper - ); - var policyMapper = new PolicyMapper( - constraintExtractor, - atomicConstraintMapper, - typeTransformerRegistry - ); - var dataOfferMappingUtils = new DataOfferMappingUtils( - policyMapper, - assetMapper - ); - var connectorOnlineStatusMapper = new ConnectorOnlineStatusMapper(); - - // Schedules - List> jobs = List.of( - getOnlineConnectorRefreshCronJob(dslContextFactory, connectorQueueFiller), - getOfflineConnectorRefreshCronJob(dslContextFactory, connectorQueueFiller), - getDeadConnectorRefreshCronJob(dslContextFactory, connectorQueueFiller), - getOfflineConnectorKillerCronJob(dslContextFactory, offlineConnectorKiller) - ); - - // Startup - var quartzScheduleInitializer = new QuartzScheduleInitializer(config, monitor, jobs); - var brokerServerInitializer = new BrokerServerInitializer( - dslContextFactory, - knownConnectorsInitializer, - quartzScheduleInitializer - ); - - // UI Capabilities - var catalogApiService = new CatalogApiService( - paginationMetadataUtils, - catalogQueryService, - dataOfferMappingUtils, - catalogFilterService, - brokerServerSettings - ); - var connectorApiService = new ConnectorApiService( - connectorService, - brokerEventLogger, - connectorQueries - ); - var dataOfferDetailApiService = new DataOfferDetailApiService( - dataOfferDetailPageQueryService, - viewCountLogger, - dataOfferMappingUtils - ); - var connectorQueryService = new AuthorityPortalConnectorQueryService(); - var dataOfferCountApiService = new AuthorityPortalConnectorMetadataApiService( - connectorQueryService, - connectorOnlineStatusMapper - ); - var connectorDetailApiService = new ConnectorDetailApiService(connectorDetailQueryService, connectorOnlineStatusMapper); - var connectorListApiService = new ConnectorListApiService(connectorListQueryService, connectorOnlineStatusMapper, paginationMetadataUtils); - var authorityPortalOrganizationMetadataApiService = new AuthorityPortalOrganizationMetadataApiService(); - var authorityPortalDataOfferApiService = new AuthorityPortalConnectorDataOfferApiService(connectorQueryService, connectorOnlineStatusMapper); - var brokerServerResource = new BrokerServerResourceImpl( - dslContextFactory, - connectorApiService, - connectorListApiService, - connectorDetailApiService, - catalogApiService, - dataOfferDetailApiService, - adminApiKeyValidator, - dataOfferCountApiService, - authorityPortalDataOfferApiService, - authorityPortalOrganizationMetadataApiService - ); - - return new BrokerServerExtensionContext( - brokerServerResource, - brokerServerInitializer, - connectorUpdater, - connectorCreator, - policyMapper, - fetchedDataOfferBuilder, - dataOfferRecordUpdater - ); - } - - @NotNull - private static CronJobRef getOfflineConnectorKillerCronJob(DslContextFactory dslContextFactory, OfflineConnectorKiller offlineConnectorKiller) { - return new CronJobRef<>( - BrokerServerExtension.SCHEDULED_KILL_OFFLINE_CONNECTORS, - OfflineConnectorKillerJob.class, - () -> new OfflineConnectorKillerJob(dslContextFactory, offlineConnectorKiller) - ); - } - - @NotNull - private static CronJobRef getOnlineConnectorRefreshCronJob(DslContextFactory dslContextFactory, ConnectorQueueFiller connectorQueueFiller) { - return new CronJobRef<>( - BrokerServerExtension.CRON_ONLINE_CONNECTOR_REFRESH, - OnlineConnectorRefreshJob.class, - () -> new OnlineConnectorRefreshJob(dslContextFactory, connectorQueueFiller) - ); - } - - @NotNull - private static CronJobRef getOfflineConnectorRefreshCronJob(DslContextFactory dslContextFactory, ConnectorQueueFiller connectorQueueFiller) { - return new CronJobRef<>( - BrokerServerExtension.CRON_OFFLINE_CONNECTOR_REFRESH, - OfflineConnectorRefreshJob.class, - () -> new OfflineConnectorRefreshJob(dslContextFactory, connectorQueueFiller) - ); - } - - @NotNull - private static CronJobRef getDeadConnectorRefreshCronJob(DslContextFactory dslContextFactory, ConnectorQueueFiller connectorQueueFiller) { - return new CronJobRef<>( - BrokerServerExtension.CRON_DEAD_CONNECTOR_REFRESH, - DeadConnectorRefreshJob.class, - () -> new DeadConnectorRefreshJob(dslContextFactory, connectorQueueFiller) - ); - } - - private static ObjectMapper getJsonLdObjectMapper(TypeManager typeManager) { - var objectMapper = typeManager.getMapper(CoreConstants.JSON_LD); - - // Fixes Dates in JSON-LD Object Mapper - // The Core EDC uses longs over OffsetDateTime, so they never fixed the date format - objectMapper.registerModule(new JavaTimeModule()); - objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); - - return objectMapper; - } - - @NotNull - private static AssetMapper newAssetMapper(TypeTransformerRegistry typeTransformerRegistry, JsonLd jsonLd) { - var edcPropertyUtils = new EdcPropertyUtils(); - var assetJsonLdUtils = new AssetJsonLdUtils(); - var assetEditRequestMapper = new AssetEditRequestMapper(); - var shortDescriptionBuilder = new ShortDescriptionBuilder(); - var assetJsonLdParser = new AssetJsonLdParser( - assetJsonLdUtils, - shortDescriptionBuilder, - endpoint -> false - ); - var httpHeaderMapper = new HttpHeaderMapper(); - var httpDataSourceMapper = new HttpDataSourceMapper(httpHeaderMapper); - var dataSourceMapper = new DataSourceMapper( - edcPropertyUtils, - httpDataSourceMapper - ); - var assetJsonLdBuilder = new AssetJsonLdBuilder( - dataSourceMapper, - assetJsonLdParser, - assetEditRequestMapper - ); - return new AssetMapper( - typeTransformerRegistry, - assetJsonLdBuilder, - assetJsonLdParser, - jsonLd - ); - } -} diff --git a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/BrokerServerResourceImpl.java b/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/BrokerServerResourceImpl.java deleted file mode 100644 index 7f38ea0d1..000000000 --- a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/BrokerServerResourceImpl.java +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Copyright (c) 2023 sovity GmbH - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - * - * Contributors: - * sovity GmbH - initial API and implementation - * - */ - -package de.sovity.edc.ext.brokerserver; - -import de.sovity.edc.ext.brokerserver.api.BrokerServerResource; -import de.sovity.edc.ext.brokerserver.api.model.AuthorityPortalConnectorDataOfferInfo; -import de.sovity.edc.ext.brokerserver.api.model.AuthorityPortalConnectorInfo; -import de.sovity.edc.ext.brokerserver.api.model.AuthorityPortalOrganizationMetadataRequest; -import de.sovity.edc.ext.brokerserver.api.model.CatalogPageQuery; -import de.sovity.edc.ext.brokerserver.api.model.CatalogPageResult; -import de.sovity.edc.ext.brokerserver.api.model.ConnectorCreationRequest; -import de.sovity.edc.ext.brokerserver.api.model.ConnectorDetailPageQuery; -import de.sovity.edc.ext.brokerserver.api.model.ConnectorDetailPageResult; -import de.sovity.edc.ext.brokerserver.api.model.ConnectorPageQuery; -import de.sovity.edc.ext.brokerserver.api.model.ConnectorPageResult; -import de.sovity.edc.ext.brokerserver.api.model.DataOfferDetailPageQuery; -import de.sovity.edc.ext.brokerserver.api.model.DataOfferDetailPageResult; -import de.sovity.edc.ext.brokerserver.db.DslContextFactory; -import de.sovity.edc.ext.brokerserver.services.api.AuthorityPortalConnectorDataOfferApiService; -import de.sovity.edc.ext.brokerserver.services.api.AuthorityPortalConnectorMetadataApiService; -import de.sovity.edc.ext.brokerserver.services.api.AuthorityPortalOrganizationMetadataApiService; -import de.sovity.edc.ext.brokerserver.services.api.CatalogApiService; -import de.sovity.edc.ext.brokerserver.services.api.ConnectorApiService; -import de.sovity.edc.ext.brokerserver.services.api.ConnectorDetailApiService; -import de.sovity.edc.ext.brokerserver.services.api.ConnectorListApiService; -import de.sovity.edc.ext.brokerserver.services.api.DataOfferDetailApiService; -import de.sovity.edc.ext.brokerserver.services.config.AdminApiKeyValidator; -import lombok.RequiredArgsConstructor; - -import java.util.List; - - -/** - * Implementation of {@link BrokerServerResource} - */ -@RequiredArgsConstructor -public class BrokerServerResourceImpl implements BrokerServerResource { - private final DslContextFactory dslContextFactory; - private final ConnectorApiService connectorApiService; - private final ConnectorListApiService connectorListApiService; - private final ConnectorDetailApiService connectorDetailApiService; - private final CatalogApiService catalogApiService; - private final DataOfferDetailApiService dataOfferDetailApiService; - private final AdminApiKeyValidator adminApiKeyValidator; - private final AuthorityPortalConnectorMetadataApiService authorityPortalConnectorMetadataApiService; - private final AuthorityPortalConnectorDataOfferApiService authorityPortalConnectorDataOffersApiService; - private final AuthorityPortalOrganizationMetadataApiService authorityPortalOrganizationMetadataApiService; - - @Override - public CatalogPageResult catalogPage(CatalogPageQuery query) { - return dslContextFactory.transactionResult(dsl -> catalogApiService.catalogPage(dsl, query)); - } - - @Override - public ConnectorPageResult connectorPage(ConnectorPageQuery query) { - return dslContextFactory.transactionResult(dsl -> connectorListApiService.connectorListPage(dsl, query)); - } - - @Override - public DataOfferDetailPageResult dataOfferDetailPage(DataOfferDetailPageQuery query) { - return dslContextFactory.transactionResult(dsl -> dataOfferDetailApiService.dataOfferDetailPage(dsl, query)); - } - - @Override - public ConnectorDetailPageResult connectorDetailPage(ConnectorDetailPageQuery query) { - return dslContextFactory.transactionResult(dsl -> connectorDetailApiService.connectorDetailPage(dsl, query)); - } - - @Override - public void addConnectors(List endpoints, String adminApiKey) { - adminApiKeyValidator.validateAdminApiKey(adminApiKey); - dslContextFactory.transaction(dsl -> connectorApiService.addConnectors(dsl, endpoints)); - } - - @Override - public void addConnectorsWithMdsIds(ConnectorCreationRequest connectors, String adminApiKey) { - adminApiKeyValidator.validateAdminApiKey(adminApiKey); - dslContextFactory.transaction(dsl -> connectorApiService.addConnectorsWithMdsIds(dsl, connectors)); - } - - @Override - public void deleteConnectors(List endpoints, String adminApiKey) { - adminApiKeyValidator.validateAdminApiKey(adminApiKey); - dslContextFactory.transaction(dsl -> connectorApiService.deleteConnectors(dsl, endpoints)); - } - - @Override - public List getConnectorMetadata(List endpoints, String adminApiKey) { - adminApiKeyValidator.validateAdminApiKey(adminApiKey); - return dslContextFactory.transactionResult(dsl -> authorityPortalConnectorMetadataApiService.getMetadataByEndpoints(dsl, endpoints)); - } - - @Override - public void setOrganizationMetadata(AuthorityPortalOrganizationMetadataRequest organizationMetadataRequest, String adminApiKey) { - adminApiKeyValidator.validateAdminApiKey(adminApiKey); - dslContextFactory.transaction(dsl -> authorityPortalOrganizationMetadataApiService.setOrganizationMetadata(dsl, organizationMetadataRequest.getOrganizations())); - } - - @Override - public List getConnectorDataOffers(List endpoints, String adminApiKey) { - adminApiKeyValidator.validateAdminApiKey(adminApiKey); - return dslContextFactory.transactionResult(dsl -> authorityPortalConnectorDataOffersApiService.getConnectorDataOffersByEndpoints(dsl, endpoints)); - } -} diff --git a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/dao/ConnectorQueries.java b/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/dao/ConnectorQueries.java deleted file mode 100644 index 31fd44a7f..000000000 --- a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/dao/ConnectorQueries.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (c) 2023 sovity GmbH - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - * - * Contributors: - * sovity GmbH - initial API and implementation - * - */ - -package de.sovity.edc.ext.brokerserver.dao; - -import de.sovity.edc.ext.brokerserver.dao.utils.PostgresqlUtils; -import de.sovity.edc.ext.brokerserver.db.jooq.Tables; -import de.sovity.edc.ext.brokerserver.db.jooq.enums.ConnectorOnlineStatus; -import de.sovity.edc.ext.brokerserver.db.jooq.tables.records.ConnectorRecord; -import org.jooq.DSLContext; - -import java.time.Duration; -import java.time.OffsetDateTime; -import java.util.Collection; -import java.util.List; -import java.util.Set; - -public class ConnectorQueries { - - public ConnectorRecord findByEndpoint(DSLContext dsl, String endpoint) { - var c = Tables.CONNECTOR; - return dsl.selectFrom(c).where(c.ENDPOINT.eq(endpoint)).fetchOne(); - } - - public Set findConnectorsForScheduledRefresh(DSLContext dsl, ConnectorOnlineStatus onlineStatus) { - var c = Tables.CONNECTOR; - return dsl.select(c.ENDPOINT).from(c).where(c.ONLINE_STATUS.eq(onlineStatus)).fetchSet(c.ENDPOINT); - } - - public Set findExistingConnectors(DSLContext dsl, Collection connectorEndpoints) { - var c = Tables.CONNECTOR; - return dsl.select(c.ENDPOINT).from(c) - .where(PostgresqlUtils.in(c.ENDPOINT, connectorEndpoints)) - .fetchSet(c.ENDPOINT); - } - - public List findAllConnectorsForKilling(DSLContext dsl, Duration deleteOfflineConnectorsAfter) { - var c = Tables.CONNECTOR; - return dsl.select(c.ENDPOINT).from(c) - .where(c.LAST_SUCCESSFUL_REFRESH_AT.lt(OffsetDateTime.now().minus(deleteOfflineConnectorsAfter))) - .fetch(c.ENDPOINT); - } -} diff --git a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/dao/pages/catalog/CatalogQueryAvailableFilterFetcher.java b/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/dao/pages/catalog/CatalogQueryAvailableFilterFetcher.java deleted file mode 100644 index ee3fdd7aa..000000000 --- a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/dao/pages/catalog/CatalogQueryAvailableFilterFetcher.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (c) 2023 sovity GmbH - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - * - * Contributors: - * sovity GmbH - initial API and implementation - * - */ - -package de.sovity.edc.ext.brokerserver.dao.pages.catalog; - -import de.sovity.edc.ext.brokerserver.dao.pages.catalog.models.CatalogQueryFilter; -import de.sovity.edc.ext.brokerserver.utils.CollectionUtils2; -import lombok.RequiredArgsConstructor; -import org.jooq.Field; -import org.jooq.JSON; -import org.jooq.impl.DSL; -import org.jooq.impl.SQLDataType; - -import java.util.ArrayList; -import java.util.List; - -@RequiredArgsConstructor -public class CatalogQueryAvailableFilterFetcher { - private final CatalogQueryFilterService catalogQueryFilterService; - - /** - * Query available filter values. - * - * @param fields query fields - * @param searchQuery search query - * @param filters filters (values + filter clauses) - * @return {@link Field} with field[iFilter][iValue] - */ - public Field queryAvailableFilterValues( - CatalogQueryFields fields, - String searchQuery, - List filters - ) { - List> resultFields = new ArrayList<>(); - for (int i = 0; i < filters.size(); i++) { - // When querying a filter's values we apply all filters except for the current filter's values - var currentFilter = filters.get(i); - var otherFilters = CollectionUtils2.allElementsExceptForIndex(filters, i); - var resultField = queryFilterValues(fields, currentFilter, searchQuery, otherFilters); - resultFields.add(resultField); - } - return DSL.select(DSL.jsonArray(resultFields)).asField(); - } - - private Field queryFilterValues( - CatalogQueryFields parentQueryFields, - CatalogQueryFilter currentFilter, - String searchQuery, - List otherFilters - ) { - var fields = parentQueryFields.withSuffix("filter_" + currentFilter.name()); - var c = fields.getConnectorTable(); - var d = fields.getDataOfferTable(); - - var value = currentFilter.valueQuery().getAttributeValueField(fields); - - return DSL.select(DSL.coalesce(DSL.arrayAggDistinct(value), DSL.array().cast(SQLDataType.VARCHAR.array()))) - .from(d) - .leftJoin(c).on(c.ENDPOINT.eq(d.CONNECTOR_ENDPOINT)) - .where(catalogQueryFilterService.filterDbQuery(fields, searchQuery, otherFilters)) - .asField(); - } -} diff --git a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/dao/pages/catalog/CatalogQueryContractOfferFetcher.java b/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/dao/pages/catalog/CatalogQueryContractOfferFetcher.java deleted file mode 100644 index d2e370c5c..000000000 --- a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/dao/pages/catalog/CatalogQueryContractOfferFetcher.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (c) 2023 sovity GmbH - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - * - * Contributors: - * sovity GmbH - initial API and implementation - * - */ - -package de.sovity.edc.ext.brokerserver.dao.pages.catalog; - -import de.sovity.edc.ext.brokerserver.dao.pages.dataoffer.model.ContractOfferRs; -import de.sovity.edc.ext.brokerserver.dao.utils.MultisetUtils; -import de.sovity.edc.ext.brokerserver.db.jooq.Tables; -import de.sovity.edc.ext.brokerserver.db.jooq.tables.DataOffer; -import lombok.RequiredArgsConstructor; -import org.jooq.Field; -import org.jooq.impl.DSL; - -import java.util.List; - -@RequiredArgsConstructor -public class CatalogQueryContractOfferFetcher { - - /** - * Query a data offer's contract offers. - * - * @param d Data offer table - * @return {@link Field} of {@link ContractOfferRs}s - */ - public Field> getContractOffers(DataOffer d) { - var co = Tables.CONTRACT_OFFER; - - var query = DSL.select( - co.CONTRACT_OFFER_ID, - co.POLICY.cast(String.class).as("policyJson"), - co.CREATED_AT, - co.UPDATED_AT - ).from(co).where( - co.CONNECTOR_ENDPOINT.eq(d.CONNECTOR_ENDPOINT), - co.ASSET_ID.eq(d.ASSET_ID)).orderBy(co.CREATED_AT.desc() - ); - - return MultisetUtils.multiset(query, ContractOfferRs.class); - } -} diff --git a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/dao/pages/catalog/CatalogQueryDataOfferFetcher.java b/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/dao/pages/catalog/CatalogQueryDataOfferFetcher.java deleted file mode 100644 index 24cbb3282..000000000 --- a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/dao/pages/catalog/CatalogQueryDataOfferFetcher.java +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright (c) 2023 sovity GmbH - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - * - * Contributors: - * sovity GmbH - initial API and implementation - * - */ - -package de.sovity.edc.ext.brokerserver.dao.pages.catalog; - -import de.sovity.edc.ext.brokerserver.api.model.CatalogPageSortingType; -import de.sovity.edc.ext.brokerserver.dao.pages.catalog.models.CatalogQueryFilter; -import de.sovity.edc.ext.brokerserver.dao.pages.catalog.models.DataOfferListEntryRs; -import de.sovity.edc.ext.brokerserver.dao.pages.catalog.models.PageQuery; -import de.sovity.edc.ext.brokerserver.dao.utils.MultisetUtils; -import lombok.RequiredArgsConstructor; -import org.jooq.Field; -import org.jooq.Record; -import org.jooq.SelectOnConditionStep; -import org.jooq.SelectSelectStep; -import org.jooq.impl.DSL; - -import java.util.List; - -@RequiredArgsConstructor -public class CatalogQueryDataOfferFetcher { - private final CatalogQuerySortingService catalogQuerySortingService; - private final CatalogQueryFilterService catalogQueryFilterService; - private final CatalogQueryContractOfferFetcher catalogQueryContractOfferFetcher; - - /** - * Query data offers - * - * @param fields query fields - * @param searchQuery search query - * @param filters filters (queries + filter clauses) - * @param sorting sorting - * @param pageQuery pagination - * @return {@link Field} of {@link DataOfferListEntryRs}s - */ - public Field> queryDataOffers( - CatalogQueryFields fields, - String searchQuery, - List filters, - CatalogPageSortingType sorting, - PageQuery pageQuery - ) { - var c = fields.getConnectorTable(); - var d = fields.getDataOfferTable(); - - var select = DSL.select( - d.ASSET_ID.as("assetId"), - d.ASSET_JSON_LD.cast(String.class).as("assetJsonLd"), - d.CREATED_AT, - d.UPDATED_AT, - catalogQueryContractOfferFetcher.getContractOffers(d).as("contractOffers"), - c.ENDPOINT.as("connectorEndpoint"), - c.ONLINE_STATUS.as("connectorOnlineStatus"), - c.PARTICIPANT_ID.as("connectorParticipantId"), - fields.getOrganizationName().as("organizationName"), - fields.getOfflineSinceOrLastUpdatedAt().as("connectorOfflineSinceOrLastUpdatedAt") - ); - - var query = from(select, fields) - .where(catalogQueryFilterService.filterDbQuery(fields, searchQuery, filters)) - .orderBy(catalogQuerySortingService.getOrderBy(fields, sorting)) - .limit(pageQuery.offset(), pageQuery.limit()); - - return MultisetUtils.multiset(query, DataOfferListEntryRs.class); - } - - /** - * Query number of data offers - * - * @param fields query fields - * @param searchQuery search query - * @param filters filters (queries + filter clauses) - * @return {@link Field} with number of data offers - */ - public Field queryNumDataOffers(CatalogQueryFields fields, String searchQuery, List filters) { - var query = from(DSL.select(DSL.count()), fields) - .where(catalogQueryFilterService.filterDbQuery(fields, searchQuery, filters)); - return DSL.field(query); - } - - private SelectOnConditionStep from(SelectSelectStep select, CatalogQueryFields fields) { - var c = fields.getConnectorTable(); - var d = fields.getDataOfferTable(); - return select.from(d).leftJoin(c).on(c.ENDPOINT.eq(d.CONNECTOR_ENDPOINT)); - } -} diff --git a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/dao/pages/catalog/CatalogQueryFields.java b/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/dao/pages/catalog/CatalogQueryFields.java deleted file mode 100644 index 747f0707d..000000000 --- a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/dao/pages/catalog/CatalogQueryFields.java +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Copyright (c) 2023 sovity GmbH - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - * - * Contributors: - * sovity GmbH - initial API and implementation - * - */ - -package de.sovity.edc.ext.brokerserver.dao.pages.catalog; - -import de.sovity.edc.ext.brokerserver.db.jooq.Tables; -import de.sovity.edc.ext.brokerserver.db.jooq.tables.Connector; -import de.sovity.edc.ext.brokerserver.db.jooq.tables.DataOffer; -import de.sovity.edc.ext.brokerserver.db.jooq.tables.DataOfferViewCount; -import de.sovity.edc.ext.brokerserver.services.config.DataSpaceConfig; -import lombok.AccessLevel; -import lombok.Getter; -import lombok.experimental.FieldDefaults; -import org.jooq.Field; -import org.jooq.Table; -import org.jooq.impl.DSL; - -import java.time.OffsetDateTime; - -import static org.jooq.impl.DSL.coalesce; - -/** - * Tables and fields used in the catalog page query. - *

- * Having this as a class makes access to computed fields (e.g. asset properties) easier. - */ -@Getter -@FieldDefaults(level = AccessLevel.PRIVATE, makeFinal = true) -public class CatalogQueryFields { - Connector connectorTable; - DataOffer dataOfferTable; - DataOfferViewCount dataOfferViewCountTable; - - // Asset Properties from JSON to be used in sorting / filtering - Field dataSpace; - - // This date should always be non-null - // It's used in the UI to display the last relevant change date of a connector - Field offlineSinceOrLastUpdatedAt; - - DataSpaceConfig dataSpaceConfig; - - public CatalogQueryFields( - Connector connectorTable, - DataOffer dataOfferTable, - DataOfferViewCount dataOfferViewCountTable, - DataSpaceConfig dataSpaceConfig - ) { - this.connectorTable = connectorTable; - this.dataOfferTable = dataOfferTable; - this.dataOfferViewCountTable = dataOfferViewCountTable; - this.dataSpaceConfig = dataSpaceConfig; - offlineSinceOrLastUpdatedAt = offlineSinceOrLastUpdatedAt(connectorTable); - - dataSpace = buildDataSpaceField(connectorTable, dataSpaceConfig); - } - - private Field buildDataSpaceField(Connector connectorTable, DataSpaceConfig dataSpaceConfig) { - var endpoint = connectorTable.ENDPOINT; - - var connectors = dataSpaceConfig.dataSpaceConnectors(); - if (connectors.isEmpty()) { - return DSL.val(dataSpaceConfig.defaultDataSpace()); - } - - var first = connectors.get(0); - var dspCase = DSL.case_(endpoint).when(first.endpoint(), first.dataSpaceName()); - - for (var dsp : connectors.subList(1, connectors.size())) { - dspCase = dspCase.when(dsp.endpoint(), dsp.dataSpaceName()); - } - - return dspCase.else_(DSL.val(dataSpaceConfig.defaultDataSpace())); - } - - public CatalogQueryFields withSuffix(String additionalSuffix) { - return new CatalogQueryFields( - connectorTable.as(withSuffix(connectorTable, additionalSuffix)), - dataOfferTable.as(withSuffix(dataOfferTable, additionalSuffix)), - dataOfferViewCountTable.as(withSuffix(dataOfferViewCountTable, additionalSuffix)), - dataSpaceConfig - ); - } - - private String withSuffix(Table table, String additionalSuffix) { - return "%s_%s".formatted(table.getName(), additionalSuffix); - } - - public Field getViewCount() { - var subquery = DSL.select(DSL.count()) - .from(dataOfferViewCountTable) - .where(dataOfferViewCountTable.ASSET_ID.eq(dataOfferTable.ASSET_ID) - .and(dataOfferViewCountTable.CONNECTOR_ENDPOINT.eq(connectorTable.ENDPOINT))); - - return subquery.asField(); - } - - public Field getOrganizationName() { - return organizationName(connectorTable.MDS_ID); - } - - public static Field offlineSinceOrLastUpdatedAt(Connector connectorTable) { - return DSL.coalesce( - connectorTable.LAST_SUCCESSFUL_REFRESH_AT, - connectorTable.CREATED_AT - ); - } - - public static Field organizationName(Field mdsId) { - var om = Tables.ORGANIZATION_METADATA; - var organizationName = DSL.select(om.NAME) - .from(om) - .where(om.MDS_ID.eq(mdsId)) - .asField() - .cast(String.class); - return coalesce(organizationName, "Unknown"); - } -} diff --git a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/dao/pages/catalog/CatalogQueryFilterService.java b/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/dao/pages/catalog/CatalogQueryFilterService.java deleted file mode 100644 index b92af8920..000000000 --- a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/dao/pages/catalog/CatalogQueryFilterService.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (c) 2023 sovity GmbH - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - * - * Contributors: - * sovity GmbH - initial API and implementation - * - */ - -package de.sovity.edc.ext.brokerserver.dao.pages.catalog; - -import de.sovity.edc.ext.brokerserver.dao.pages.catalog.models.CatalogQueryFilter; -import de.sovity.edc.ext.brokerserver.db.jooq.enums.ConnectorOnlineStatus; -import de.sovity.edc.ext.brokerserver.db.jooq.tables.Connector; -import de.sovity.edc.ext.brokerserver.services.api.filtering.CatalogSearchService; -import de.sovity.edc.ext.brokerserver.services.config.BrokerServerSettings; -import lombok.RequiredArgsConstructor; -import org.jetbrains.annotations.NotNull; -import org.jooq.Condition; -import org.jooq.impl.DSL; - -import java.time.OffsetDateTime; -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; - -@RequiredArgsConstructor -public class CatalogQueryFilterService { - private final BrokerServerSettings brokerServerSettings; - private final CatalogSearchService catalogSearchService; - - public Condition filterDbQuery(CatalogQueryFields fields, String searchQuery, List filters) { - var conditions = new ArrayList(); - conditions.add(catalogSearchService.filterBySearch(fields, searchQuery)); - conditions.add(onlyOnlineOrRecentlyOfflineConnectors(fields.getConnectorTable())); - conditions.addAll(filters.stream().map(CatalogQueryFilter::queryFilterClauseOrNull) - .filter(Objects::nonNull).map(it -> it.filterDataOffers(fields)).toList()); - return DSL.and(conditions); - } - - @NotNull - private Condition onlyOnlineOrRecentlyOfflineConnectors(Connector c) { - var maxOfflineDuration = brokerServerSettings.getHideOfflineDataOffersAfter(); - - Condition maxOfflineDurationNotExceeded; - if (maxOfflineDuration == null) { - maxOfflineDurationNotExceeded = DSL.trueCondition(); - } else { - maxOfflineDurationNotExceeded = c.LAST_SUCCESSFUL_REFRESH_AT.greaterThan(OffsetDateTime.now().minus(maxOfflineDuration)); - } - - return DSL.or( - c.ONLINE_STATUS.eq(ConnectorOnlineStatus.ONLINE), - maxOfflineDurationNotExceeded - ); - } -} diff --git a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/dao/pages/catalog/CatalogQueryService.java b/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/dao/pages/catalog/CatalogQueryService.java deleted file mode 100644 index 04a585e35..000000000 --- a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/dao/pages/catalog/CatalogQueryService.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (c) 2023 sovity GmbH - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - * - * Contributors: - * sovity GmbH - initial API and implementation - * - */ - -package de.sovity.edc.ext.brokerserver.dao.pages.catalog; - -import de.sovity.edc.ext.brokerserver.api.model.CatalogPageSortingType; -import de.sovity.edc.ext.brokerserver.dao.pages.catalog.models.CatalogPageRs; -import de.sovity.edc.ext.brokerserver.dao.pages.catalog.models.CatalogQueryFilter; -import de.sovity.edc.ext.brokerserver.dao.pages.catalog.models.PageQuery; -import de.sovity.edc.ext.brokerserver.db.jooq.Tables; -import de.sovity.edc.ext.brokerserver.services.config.BrokerServerSettings; -import lombok.RequiredArgsConstructor; -import org.jooq.DSLContext; - -import java.util.List; - -@RequiredArgsConstructor -public class CatalogQueryService { - private final CatalogQueryDataOfferFetcher catalogQueryDataOfferFetcher; - private final CatalogQueryAvailableFilterFetcher catalogQueryAvailableFilterFetcher; - private final BrokerServerSettings brokerServerSettings; - - /** - * Query all data required for the catalog page - * - * @param dsl transaction - * @param searchQuery search query - * @param filters filters (queries + filter clauses) - * @param sorting sorting - * @param pageQuery pagination - * @return {@link CatalogPageRs} - */ - public CatalogPageRs queryCatalogPage( - DSLContext dsl, - String searchQuery, - List filters, - CatalogPageSortingType sorting, - PageQuery pageQuery - ) { - var fields = new CatalogQueryFields( - Tables.CONNECTOR, - Tables.DATA_OFFER, - Tables.DATA_OFFER_VIEW_COUNT, - brokerServerSettings.getDataSpaceConfig() - ); - - var availableFilterValues = catalogQueryAvailableFilterFetcher - .queryAvailableFilterValues(fields, searchQuery, filters); - - var dataOffers = catalogQueryDataOfferFetcher.queryDataOffers(fields, searchQuery, filters, sorting, pageQuery); - - var numTotalDataOffers = catalogQueryDataOfferFetcher.queryNumDataOffers(fields, searchQuery, filters); - - return dsl.select( - dataOffers.as("dataOffers"), - availableFilterValues.as("availableFilterValues"), - numTotalDataOffers.as("numTotalDataOffers") - ).fetchOneInto(CatalogPageRs.class); - } - -} diff --git a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/dao/pages/catalog/CatalogQuerySortingService.java b/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/dao/pages/catalog/CatalogQuerySortingService.java deleted file mode 100644 index c06aaecb1..000000000 --- a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/dao/pages/catalog/CatalogQuerySortingService.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (c) 2023 sovity GmbH - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - * - * Contributors: - * sovity GmbH - initial API and implementation - * - */ - -package de.sovity.edc.ext.brokerserver.dao.pages.catalog; - -import de.sovity.edc.ext.brokerserver.api.model.CatalogPageSortingType; -import lombok.NonNull; -import lombok.RequiredArgsConstructor; -import org.jetbrains.annotations.NotNull; -import org.jooq.OrderField; - -import java.util.List; - -@RequiredArgsConstructor -public class CatalogQuerySortingService { - @NotNull - public List> getOrderBy(CatalogQueryFields fields, @NonNull CatalogPageSortingType sorting) { - List> orderBy; - if (sorting == CatalogPageSortingType.TITLE) { - orderBy = List.of( - fields.getDataOfferTable().ASSET_TITLE.asc(), - fields.getConnectorTable().ENDPOINT.asc() - ); - } else if (sorting == CatalogPageSortingType.MOST_RECENT) { - orderBy = List.of( - fields.getDataOfferTable().CREATED_AT.desc(), - fields.getConnectorTable().ENDPOINT.asc() - ); - } else if (sorting == CatalogPageSortingType.ORIGINATOR) { - orderBy = List.of( - fields.getConnectorTable().ENDPOINT.asc(), - fields.getDataOfferTable().ASSET_TITLE.asc() - ); - } else if (sorting == CatalogPageSortingType.VIEW_COUNT) { - orderBy = List.of( - fields.getViewCount().desc(), - fields.getConnectorTable().ENDPOINT.asc() - ); - } else { - throw new IllegalArgumentException("Unknown %s: %s".formatted(CatalogPageSortingType.class.getName(), sorting)); - } - return orderBy; - } -} diff --git a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/dao/pages/catalog/models/AvailableFilterValuesQuery.java b/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/dao/pages/catalog/models/AvailableFilterValuesQuery.java deleted file mode 100644 index 9dabec513..000000000 --- a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/dao/pages/catalog/models/AvailableFilterValuesQuery.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (c) 2023 sovity GmbH - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - * - * Contributors: - * sovity GmbH - initial API and implementation - * - */ - -package de.sovity.edc.ext.brokerserver.dao.pages.catalog.models; - -import de.sovity.edc.ext.brokerserver.dao.pages.catalog.CatalogQueryFields; -import org.jooq.Field; - -@FunctionalInterface -public interface AvailableFilterValuesQuery { - - /** - * Gets the values for a given filter attribute from a list of data offers. - * - * @param fields a - * @return field / multiset field that will contain the available values - */ - Field getAttributeValueField(CatalogQueryFields fields); -} diff --git a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/dao/pages/catalog/models/CatalogPageRs.java b/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/dao/pages/catalog/models/CatalogPageRs.java deleted file mode 100644 index 88a199df1..000000000 --- a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/dao/pages/catalog/models/CatalogPageRs.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (c) 2023 sovity GmbH - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - * - * Contributors: - * sovity GmbH - initial API and implementation - * - */ - -package de.sovity.edc.ext.brokerserver.dao.pages.catalog.models; - -import lombok.AccessLevel; -import lombok.Getter; -import lombok.Setter; -import lombok.experimental.FieldDefaults; - -import java.util.List; - -@Getter -@Setter -@FieldDefaults(level = AccessLevel.PRIVATE) -public class CatalogPageRs { - String availableFilterValues; - List dataOffers; - int numTotalDataOffers; -} diff --git a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/dao/pages/catalog/models/CatalogQueryFilter.java b/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/dao/pages/catalog/models/CatalogQueryFilter.java deleted file mode 100644 index 9dcccd038..000000000 --- a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/dao/pages/catalog/models/CatalogQueryFilter.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright (c) 2023 sovity GmbH - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - * - * Contributors: - * sovity GmbH - initial API and implementation - * - */ - -package de.sovity.edc.ext.brokerserver.dao.pages.catalog.models; - -import lombok.NonNull; - -public record CatalogQueryFilter( - @NonNull String name, - @NonNull AvailableFilterValuesQuery valueQuery, - CatalogQuerySelectedFilterQuery queryFilterClauseOrNull -) { -} diff --git a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/dao/pages/catalog/models/CatalogQuerySelectedFilterQuery.java b/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/dao/pages/catalog/models/CatalogQuerySelectedFilterQuery.java deleted file mode 100644 index a3b2bcfa3..000000000 --- a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/dao/pages/catalog/models/CatalogQuerySelectedFilterQuery.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (c) 2023 sovity GmbH - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - * - * Contributors: - * sovity GmbH - initial API and implementation - * - */ - -package de.sovity.edc.ext.brokerserver.dao.pages.catalog.models; - -import de.sovity.edc.ext.brokerserver.dao.pages.catalog.CatalogQueryFields; -import org.jooq.Condition; - -@FunctionalInterface -public interface CatalogQuerySelectedFilterQuery { - - /** - * Adds a filter to a Catalog Query. - * - * @param fields fields and tables available in the catalog query - * @return {@link Condition} - */ - Condition filterDataOffers(CatalogQueryFields fields); -} diff --git a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/dao/pages/catalog/models/DataOfferListEntryRs.java b/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/dao/pages/catalog/models/DataOfferListEntryRs.java deleted file mode 100644 index 1c97cf430..000000000 --- a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/dao/pages/catalog/models/DataOfferListEntryRs.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (c) 2023 sovity GmbH - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - * - * Contributors: - * sovity GmbH - initial API and implementation - * - */ - -package de.sovity.edc.ext.brokerserver.dao.pages.catalog.models; - -import de.sovity.edc.ext.brokerserver.dao.pages.dataoffer.model.ContractOfferRs; -import de.sovity.edc.ext.brokerserver.db.jooq.enums.ConnectorOnlineStatus; -import lombok.AccessLevel; -import lombok.Getter; -import lombok.Setter; -import lombok.experimental.FieldDefaults; - -import java.time.OffsetDateTime; -import java.util.List; - -@Getter -@Setter -@FieldDefaults(level = AccessLevel.PRIVATE) -public class DataOfferListEntryRs { - String assetId; - String assetJsonLd; - OffsetDateTime createdAt; - OffsetDateTime updatedAt; - List contractOffers; - String connectorEndpoint; - ConnectorOnlineStatus connectorOnlineStatus; - String connectorParticipantId; - String organizationName; - OffsetDateTime connectorOfflineSinceOrLastUpdatedAt; -} diff --git a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/dao/pages/catalog/models/PageQuery.java b/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/dao/pages/catalog/models/PageQuery.java deleted file mode 100644 index c5cd659bb..000000000 --- a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/dao/pages/catalog/models/PageQuery.java +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Copyright (c) 2023 sovity GmbH - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - * - * Contributors: - * sovity GmbH - initial API and implementation - * - */ - -package de.sovity.edc.ext.brokerserver.dao.pages.catalog.models; - -public record PageQuery(int offset, int limit) { -} diff --git a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/dao/pages/connector/ConnectorDetailQueryService.java b/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/dao/pages/connector/ConnectorDetailQueryService.java deleted file mode 100644 index f4acc2589..000000000 --- a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/dao/pages/connector/ConnectorDetailQueryService.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (c) 2023 sovity GmbH - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - * - * Contributors: - * sovity GmbH - initial API and implementation - * - */ - -package de.sovity.edc.ext.brokerserver.dao.pages.connector; - -import de.sovity.edc.ext.brokerserver.dao.pages.catalog.CatalogQueryFields; -import de.sovity.edc.ext.brokerserver.dao.pages.connector.model.ConnectorDetailsRs; -import de.sovity.edc.ext.brokerserver.db.jooq.Tables; -import de.sovity.edc.ext.brokerserver.db.jooq.enums.MeasurementErrorStatus; -import de.sovity.edc.ext.brokerserver.db.jooq.tables.Connector; -import org.jetbrains.annotations.NotNull; -import org.jooq.DSLContext; -import org.jooq.Field; -import org.jooq.impl.DSL; - -import java.math.BigDecimal; - -public class ConnectorDetailQueryService { - public ConnectorDetailsRs queryConnectorDetailPage(DSLContext dsl, String connectorEndpoint) { - var c = Tables.CONNECTOR; - - return dsl.select( - c.ENDPOINT.as("endpoint"), - c.PARTICIPANT_ID.as("participantId"), - CatalogQueryFields.organizationName(c.MDS_ID).as("organizationName"), - c.CREATED_AT.as("createdAt"), - c.LAST_SUCCESSFUL_REFRESH_AT.as("lastSuccessfulRefreshAt"), - c.LAST_REFRESH_ATTEMPT_AT.as("lastRefreshAttemptAt"), - c.ONLINE_STATUS.as("onlineStatus"), - dataOfferCount(c.ENDPOINT).as("numDataOffers"), - getAvgSuccessfulCrawlTimeInMs(c).as("connectorCrawlingTimeAvg")) - .from(c) - .where(c.ENDPOINT.eq(connectorEndpoint)) - .groupBy(c.ENDPOINT) - .fetchOneInto(ConnectorDetailsRs.class); - } - - @NotNull - private Field getAvgSuccessfulCrawlTimeInMs(Connector c) { - var betm = Tables.BROKER_EXECUTION_TIME_MEASUREMENT; - return DSL.select(DSL.avg(betm.DURATION_IN_MS)) - .from(betm) - .where(betm.CONNECTOR_ENDPOINT.eq(c.ENDPOINT), betm.ERROR_STATUS.eq(MeasurementErrorStatus.OK)) - .asField(); - } - - private Field dataOfferCount(Field endpoint) { - var d = Tables.DATA_OFFER; - return DSL.select(DSL.count()).from(d).where(d.CONNECTOR_ENDPOINT.eq(endpoint)).asField(); - } -} diff --git a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/dao/pages/connector/ConnectorListQueryService.java b/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/dao/pages/connector/ConnectorListQueryService.java deleted file mode 100644 index 524631b69..000000000 --- a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/dao/pages/connector/ConnectorListQueryService.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (c) 2023 sovity GmbH - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - * - * Contributors: - * sovity GmbH - initial API and implementation - * - */ - -package de.sovity.edc.ext.brokerserver.dao.pages.connector; - -import de.sovity.edc.ext.brokerserver.api.model.ConnectorPageSortingType; -import de.sovity.edc.ext.brokerserver.dao.pages.catalog.CatalogQueryFields; -import de.sovity.edc.ext.brokerserver.dao.pages.connector.model.ConnectorListEntryRs; -import de.sovity.edc.ext.brokerserver.dao.utils.SearchUtils; -import de.sovity.edc.ext.brokerserver.db.jooq.Tables; -import de.sovity.edc.ext.brokerserver.db.jooq.enums.ConnectorOnlineStatus; -import de.sovity.edc.ext.brokerserver.db.jooq.tables.Connector; -import lombok.NonNull; -import org.jetbrains.annotations.NotNull; -import org.jooq.DSLContext; -import org.jooq.Field; -import org.jooq.OrderField; -import org.jooq.impl.DSL; - -import java.util.List; - -public class ConnectorListQueryService { - public List queryConnectorPage(DSLContext dsl, String searchQuery, ConnectorPageSortingType sorting) { - var c = Tables.CONNECTOR; - var filterBySearchQuery = SearchUtils.simpleSearch(searchQuery, List.of( - c.ENDPOINT, - c.PARTICIPANT_ID, - CatalogQueryFields.organizationName(c.MDS_ID) - )); - - return dsl.select( - c.ENDPOINT.as("endpoint"), - c.PARTICIPANT_ID.as("participantId"), - CatalogQueryFields.organizationName(c.MDS_ID).as("organizationName"), - c.CREATED_AT.as("createdAt"), - c.LAST_SUCCESSFUL_REFRESH_AT.as("lastSuccessfulRefreshAt"), - c.LAST_REFRESH_ATTEMPT_AT.as("lastRefreshAttemptAt"), - c.ONLINE_STATUS.as("onlineStatus"), - dataOfferCount(c.ENDPOINT).as("numDataOffers") - ) - .from(c) - .where(filterBySearchQuery) - .orderBy(sortConnectorPage(c, sorting)) - .fetchInto(ConnectorListEntryRs.class); - } - - @NotNull - private List> sortConnectorPage(Connector c, @NonNull ConnectorPageSortingType sorting) { - var alphabetically = c.ENDPOINT.asc(); - var recentFirst = c.CREATED_AT.desc(); - var onlineStatus = DSL.case_(c.ONLINE_STATUS) - .when(ConnectorOnlineStatus.ONLINE, 1) - .when(ConnectorOnlineStatus.OFFLINE, 2) - .else_(3) - .asc(); - - if (sorting == ConnectorPageSortingType.ONLINE_STATUS) { - return List.of(onlineStatus, alphabetically); - } else if (sorting == ConnectorPageSortingType.TITLE) { - return List.of(alphabetically, recentFirst); - } else if (sorting == ConnectorPageSortingType.MOST_RECENT) { - return List.of(recentFirst, alphabetically); - } - - throw new IllegalArgumentException("Unhandled sorting type: " + sorting); - } - - private Field dataOfferCount(Field endpoint) { - var d = Tables.DATA_OFFER; - return DSL.select(DSL.count()).from(d).where(d.CONNECTOR_ENDPOINT.eq(endpoint)).asField(); - } -} diff --git a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/dao/pages/connector/model/ConnectorDetailsRs.java b/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/dao/pages/connector/model/ConnectorDetailsRs.java deleted file mode 100644 index 071d8e5ce..000000000 --- a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/dao/pages/connector/model/ConnectorDetailsRs.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (c) 2023 sovity GmbH - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - * - * Contributors: - * sovity GmbH - initial API and implementation - * - */ - -package de.sovity.edc.ext.brokerserver.dao.pages.connector.model; - -import de.sovity.edc.ext.brokerserver.db.jooq.enums.ConnectorOnlineStatus; -import lombok.AccessLevel; -import lombok.Getter; -import lombok.Setter; -import lombok.experimental.FieldDefaults; - -import java.time.OffsetDateTime; - -@Getter -@Setter -@FieldDefaults(level = AccessLevel.PRIVATE) -public class ConnectorDetailsRs { - String endpoint; - String participantId; - String organizationName; - OffsetDateTime createdAt; - OffsetDateTime lastSuccessfulRefreshAt; - OffsetDateTime lastRefreshAttemptAt; - ConnectorOnlineStatus onlineStatus; - Integer numDataOffers; - Long connectorCrawlingTimeAvg; -} diff --git a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/dao/pages/connector/model/ConnectorListEntryRs.java b/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/dao/pages/connector/model/ConnectorListEntryRs.java deleted file mode 100644 index 96ba710f6..000000000 --- a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/dao/pages/connector/model/ConnectorListEntryRs.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (c) 2023 sovity GmbH - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - * - * Contributors: - * sovity GmbH - initial API and implementation - * - */ - -package de.sovity.edc.ext.brokerserver.dao.pages.connector.model; - -import de.sovity.edc.ext.brokerserver.db.jooq.enums.ConnectorOnlineStatus; -import lombok.AccessLevel; -import lombok.Getter; -import lombok.Setter; -import lombok.experimental.FieldDefaults; - -import java.time.OffsetDateTime; - -@Getter -@Setter -@FieldDefaults(level = AccessLevel.PRIVATE) -public class ConnectorListEntryRs { - String endpoint; - String participantId; - String organizationName; - OffsetDateTime createdAt; - OffsetDateTime lastSuccessfulRefreshAt; - OffsetDateTime lastRefreshAttemptAt; - ConnectorOnlineStatus onlineStatus; - Integer numDataOffers; -} diff --git a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/dao/pages/dataoffer/DataOfferDetailPageQueryService.java b/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/dao/pages/dataoffer/DataOfferDetailPageQueryService.java deleted file mode 100644 index f597ac124..000000000 --- a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/dao/pages/dataoffer/DataOfferDetailPageQueryService.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (c) 2023 sovity GmbH - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - * - * Contributors: - * sovity GmbH - initial API and implementation - * - */ - -package de.sovity.edc.ext.brokerserver.dao.pages.dataoffer; - -import de.sovity.edc.ext.brokerserver.dao.pages.catalog.CatalogQueryContractOfferFetcher; -import de.sovity.edc.ext.brokerserver.dao.pages.catalog.CatalogQueryFields; -import de.sovity.edc.ext.brokerserver.dao.pages.dataoffer.model.DataOfferDetailRs; -import de.sovity.edc.ext.brokerserver.db.jooq.Tables; -import de.sovity.edc.ext.brokerserver.services.config.BrokerServerSettings; -import lombok.RequiredArgsConstructor; -import org.jooq.DSLContext; - -@RequiredArgsConstructor -public class DataOfferDetailPageQueryService { - private final CatalogQueryContractOfferFetcher catalogQueryContractOfferFetcher; - private final BrokerServerSettings brokerServerSettings; - - public DataOfferDetailRs queryDataOfferDetailsPage(DSLContext dsl, String assetId, String endpoint) { - // We are re-using the catalog page query stuff as long as we can get away with it - var fields = new CatalogQueryFields( - Tables.CONNECTOR, - Tables.DATA_OFFER, - Tables.DATA_OFFER_VIEW_COUNT, - brokerServerSettings.getDataSpaceConfig() - ); - - var d = fields.getDataOfferTable(); - var c = fields.getConnectorTable(); - - return dsl.select( - d.ASSET_ID, - d.ASSET_JSON_LD.cast(String.class).as("assetJsonLd"), - d.CREATED_AT, - d.UPDATED_AT, - catalogQueryContractOfferFetcher.getContractOffers(fields.getDataOfferTable()).as("contractOffers"), - fields.getOfflineSinceOrLastUpdatedAt().as("connectorOfflineSinceOrLastUpdatedAt"), - c.ENDPOINT.as("connectorEndpoint"), - c.ONLINE_STATUS.as("connectorOnlineStatus"), - c.PARTICIPANT_ID.as("connectorParticipantId"), - fields.getOrganizationName().as("organizationName"), - fields.getViewCount().as("viewCount")) - .from(d) - .leftJoin(c).on(c.ENDPOINT.eq(d.CONNECTOR_ENDPOINT)) - .where(d.ASSET_ID.eq(assetId).and(d.CONNECTOR_ENDPOINT.eq(endpoint))) - .fetchOneInto(DataOfferDetailRs.class); - } -} diff --git a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/dao/pages/dataoffer/ViewCountLogger.java b/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/dao/pages/dataoffer/ViewCountLogger.java deleted file mode 100644 index 377abeafa..000000000 --- a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/dao/pages/dataoffer/ViewCountLogger.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (c) 2023 sovity GmbH - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - * - * Contributors: - * sovity GmbH - initial API and implementation - * - */ - -package de.sovity.edc.ext.brokerserver.dao.pages.dataoffer; - -import de.sovity.edc.ext.brokerserver.db.jooq.Tables; -import org.jooq.DSLContext; - -import java.time.OffsetDateTime; - -public class ViewCountLogger { - public void increaseDataOfferViewCount(DSLContext dsl, String assetId, String endpoint) { - var v = Tables.DATA_OFFER_VIEW_COUNT; - dsl.insertInto(v, v.ASSET_ID, v.CONNECTOR_ENDPOINT, v.DATE).values(assetId, endpoint, OffsetDateTime.now()).execute(); - } -} diff --git a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/dao/pages/dataoffer/model/ContractOfferRs.java b/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/dao/pages/dataoffer/model/ContractOfferRs.java deleted file mode 100644 index f10d1dd1e..000000000 --- a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/dao/pages/dataoffer/model/ContractOfferRs.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (c) 2023 sovity GmbH - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - * - * Contributors: - * sovity GmbH - initial API and implementation - * - */ - -package de.sovity.edc.ext.brokerserver.dao.pages.dataoffer.model; - -import lombok.AccessLevel; -import lombok.Getter; -import lombok.Setter; -import lombok.experimental.FieldDefaults; - -import java.time.OffsetDateTime; - -@Getter -@Setter -@FieldDefaults(level = AccessLevel.PRIVATE) -public class ContractOfferRs { - String contractOfferId; - String policyJson; - OffsetDateTime createdAt; - OffsetDateTime updatedAt; -} diff --git a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/dao/pages/dataoffer/model/DataOfferDetailRs.java b/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/dao/pages/dataoffer/model/DataOfferDetailRs.java deleted file mode 100644 index 0b575849c..000000000 --- a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/dao/pages/dataoffer/model/DataOfferDetailRs.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (c) 2023 sovity GmbH - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - * - * Contributors: - * sovity GmbH - initial API and implementation - * - */ - -package de.sovity.edc.ext.brokerserver.dao.pages.dataoffer.model; - -import de.sovity.edc.ext.brokerserver.db.jooq.enums.ConnectorOnlineStatus; -import lombok.AccessLevel; -import lombok.Getter; -import lombok.Setter; -import lombok.experimental.FieldDefaults; - -import java.time.OffsetDateTime; -import java.util.List; - -@Getter -@Setter -@FieldDefaults(level = AccessLevel.PRIVATE) -public class DataOfferDetailRs { - String assetId; - String assetJsonLd; - OffsetDateTime createdAt; - OffsetDateTime updatedAt; - List contractOffers; - String connectorEndpoint; - ConnectorOnlineStatus connectorOnlineStatus; - String connectorParticipantId; - String organizationName; - OffsetDateTime connectorOfflineSinceOrLastUpdatedAt; - Integer viewCount; -} diff --git a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/dao/utils/JsonDeserializationUtils.java b/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/dao/utils/JsonDeserializationUtils.java deleted file mode 100644 index 1c3f4e2f9..000000000 --- a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/dao/utils/JsonDeserializationUtils.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (c) 2023 sovity GmbH - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - * - * Contributors: - * sovity GmbH - initial API and implementation - * - */ - -package de.sovity.edc.ext.brokerserver.dao.utils; - -import com.fasterxml.jackson.core.type.TypeReference; -import com.fasterxml.jackson.databind.ObjectMapper; -import lombok.AccessLevel; -import lombok.NoArgsConstructor; -import lombok.SneakyThrows; - -import java.util.List; - -/** - * Some things are easier to fetch as json into a string with JooQ. - * In that case we need to deserialize that string into an object of our choice afterwards. - */ -@NoArgsConstructor(access = AccessLevel.PRIVATE) -public class JsonDeserializationUtils { - private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); - private static final TypeReference>> TYPE_STRING_LIST_2 = new TypeReference<>() { - }; - - @SneakyThrows - public static List> read2dStringList(String json) { - return OBJECT_MAPPER.readValue(json, TYPE_STRING_LIST_2); - } -} diff --git a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/dao/utils/LikeUtils.java b/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/dao/utils/LikeUtils.java deleted file mode 100644 index c3823b04a..000000000 --- a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/dao/utils/LikeUtils.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (c) 2023 sovity GmbH - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - * - * Contributors: - * sovity GmbH - initial API and implementation - * - */ - -package de.sovity.edc.ext.brokerserver.dao.utils; - -import lombok.AccessLevel; -import lombok.NoArgsConstructor; -import org.apache.commons.lang3.StringUtils; -import org.jooq.Condition; -import org.jooq.Field; -import org.jooq.impl.DSL; - -/** - * Utilities for dealing with PostgreSQL Like Operation values - */ -@NoArgsConstructor(access = AccessLevel.PRIVATE) -public class LikeUtils { - - /** - * Create LIKE condition value for "field contains word". - * - * @param field field - * @param lowercaseWord word - * @return "%escapedWord%" - */ - public static Condition contains(Field field, String lowercaseWord) { - if (StringUtils.isBlank(lowercaseWord)) { - return DSL.trueCondition(); - } - - return field.likeIgnoreCase("%" + escape(lowercaseWord) + "%"); - } - - - /** - * Escapes "\", "%", "_" in given string for a LIKE operation - * - * @param string unescaped string - * @return escaped string - */ - public static String escape(String string) { - return string.replace("\\", "\\\\") - .replace("%", "\\%") - .replace("_", "\\_"); - } -} diff --git a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/dao/utils/MultisetUtils.java b/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/dao/utils/MultisetUtils.java deleted file mode 100644 index 9cdcdd84d..000000000 --- a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/dao/utils/MultisetUtils.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (c) 2023 sovity GmbH - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - * - * Contributors: - * sovity GmbH - initial API and implementation - * - */ - -package de.sovity.edc.ext.brokerserver.dao.utils; - -import lombok.AccessLevel; -import lombok.NoArgsConstructor; -import org.jooq.Field; -import org.jooq.TableLike; -import org.jooq.impl.DSL; - -import java.util.List; - -@NoArgsConstructor(access = AccessLevel.PRIVATE) -public class MultisetUtils { - public static Field> multiset(TableLike table, Class type) { - return DSL.multiset(table).convertFrom(it -> it.into(type)); - } -} diff --git a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/dao/utils/SearchUtils.java b/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/dao/utils/SearchUtils.java deleted file mode 100644 index e8a6ef310..000000000 --- a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/dao/utils/SearchUtils.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (c) 2023 sovity GmbH - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - * - * Contributors: - * sovity GmbH - initial API and implementation - * - */ - -package de.sovity.edc.ext.brokerserver.dao.utils; - -import de.sovity.edc.ext.brokerserver.utils.StringUtils2; -import lombok.AccessLevel; -import lombok.NoArgsConstructor; -import org.jooq.Condition; -import org.jooq.Field; -import org.jooq.impl.DSL; - -import java.util.List; - -/** - * DB Search Queries - */ -@NoArgsConstructor(access = AccessLevel.PRIVATE) -public class SearchUtils { - - /** - * Simple search - *
- * All search query words must be contained in at least one search target. - * - * @param searchQuery search query - * @param searchTargets target fields - * @return JOOQ Condition - */ - public static Condition simpleSearch(String searchQuery, List> searchTargets) { - var words = StringUtils2.lowercaseWords(searchQuery); - return DSL.and(words.stream() - .map(word -> anySearchTargetContains(searchTargets, word)) - .toList()); - } - - private static Condition anySearchTargetContains(List> searchTargets, String word) { - return DSL.or(searchTargets.stream().map(field -> LikeUtils.contains(field, word)).toList()); - } -} diff --git a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/ConnectorCleaner.java b/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/ConnectorCleaner.java deleted file mode 100644 index b21cc2787..000000000 --- a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/ConnectorCleaner.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (c) 2023 sovity GmbH - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - * - * Contributors: - * sovity GmbH - initial API and implementation - * - */ - -package de.sovity.edc.ext.brokerserver.services; - -import de.sovity.edc.ext.brokerserver.dao.utils.PostgresqlUtils; -import de.sovity.edc.ext.brokerserver.db.jooq.Tables; -import org.jooq.DSLContext; - -import java.util.Collection; - -public class ConnectorCleaner { - public void removeDataForDeadConnectors(DSLContext dsl, Collection endpoints) { - var doco = Tables.CONTRACT_OFFER; - var dof = Tables.DATA_OFFER; - dsl.deleteFrom(doco).where(PostgresqlUtils.in(doco.CONNECTOR_ENDPOINT, endpoints)).execute(); - dsl.deleteFrom(dof).where(PostgresqlUtils.in(dof.CONNECTOR_ENDPOINT, endpoints)).execute(); - } -} diff --git a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/ConnectorCreator.java b/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/ConnectorCreator.java deleted file mode 100644 index 51b5f461e..000000000 --- a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/ConnectorCreator.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (c) 2023 sovity GmbH - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - * - * Contributors: - * sovity GmbH - initial API and implementation - * - */ - -package de.sovity.edc.ext.brokerserver.services; - -import de.sovity.edc.ext.brokerserver.dao.ConnectorQueries; -import de.sovity.edc.ext.brokerserver.db.jooq.enums.ConnectorContractOffersExceeded; -import de.sovity.edc.ext.brokerserver.db.jooq.enums.ConnectorDataOffersExceeded; -import de.sovity.edc.ext.brokerserver.db.jooq.enums.ConnectorOnlineStatus; -import de.sovity.edc.ext.brokerserver.db.jooq.tables.records.ConnectorRecord; -import de.sovity.edc.ext.brokerserver.utils.CollectionUtils2; -import lombok.RequiredArgsConstructor; -import org.jetbrains.annotations.NotNull; -import org.jooq.DSLContext; - -import java.time.OffsetDateTime; -import java.util.Collection; -import java.util.List; - -@RequiredArgsConstructor -public class ConnectorCreator { - private final ConnectorQueries connectorQueries; - - public void addConnector(DSLContext dsl, String connectorEndpoint) { - addConnectors(dsl, List.of(connectorEndpoint)); - } - - public void addConnectors(DSLContext dsl, Collection connectorEndpoints) { - // Don't create connectors that already exist - var existingConnectors = connectorQueries.findExistingConnectors(dsl, connectorEndpoints); - var newConnectors = CollectionUtils2.difference(connectorEndpoints, existingConnectors); - - var connectorRecords = newConnectors.stream() - .map(String::trim) - .map(this::newConnectorRow) - .toList(); - - if (!connectorRecords.isEmpty()) { - dsl.batchStore(connectorRecords).execute(); - } - } - - @NotNull - private ConnectorRecord newConnectorRow(String endpoint) { - var connector = new ConnectorRecord(); - connector.setEndpoint(endpoint); - connector.setParticipantId(""); - connector.setCreatedAt(OffsetDateTime.now()); - connector.setOnlineStatus(ConnectorOnlineStatus.OFFLINE); - connector.setDataOffersExceeded(ConnectorDataOffersExceeded.OK); - connector.setContractOffersExceeded(ConnectorContractOffersExceeded.OK); - return connector; - } -} diff --git a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/ConnectorKiller.java b/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/ConnectorKiller.java deleted file mode 100644 index f44353fdb..000000000 --- a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/ConnectorKiller.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (c) 2023 sovity GmbH - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - * - * Contributors: - * sovity GmbH - initial API and implementation - * - */ - -package de.sovity.edc.ext.brokerserver.services; - -import de.sovity.edc.ext.brokerserver.dao.utils.PostgresqlUtils; -import de.sovity.edc.ext.brokerserver.db.jooq.Tables; -import de.sovity.edc.ext.brokerserver.db.jooq.enums.ConnectorOnlineStatus; -import org.jooq.DSLContext; - -import java.util.Collection; - -public class ConnectorKiller { - public void killConnectors(DSLContext dsl, Collection endpoints) { - var c = Tables.CONNECTOR; - dsl.update(c).set(c.ONLINE_STATUS, ConnectorOnlineStatus.DEAD).where(PostgresqlUtils.in(c.ENDPOINT, endpoints)).execute(); - } -} diff --git a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/KnownConnectorsInitializer.java b/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/KnownConnectorsInitializer.java deleted file mode 100644 index 117bdfbe8..000000000 --- a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/KnownConnectorsInitializer.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (c) 2023 sovity GmbH - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - * - * Contributors: - * sovity GmbH - initial API and implementation - * - */ - -package de.sovity.edc.ext.brokerserver.services; - -import de.sovity.edc.ext.brokerserver.BrokerServerExtension; -import de.sovity.edc.ext.brokerserver.services.queue.ConnectorQueue; -import de.sovity.edc.ext.brokerserver.services.queue.ConnectorRefreshPriority; -import lombok.RequiredArgsConstructor; -import org.apache.commons.lang3.StringUtils; -import org.eclipse.edc.spi.system.configuration.Config; -import org.jooq.DSLContext; - -import java.util.Arrays; -import java.util.List; - -@RequiredArgsConstructor -public class KnownConnectorsInitializer { - private final Config config; - private final ConnectorQueue connectorQueue; - private final ConnectorCreator connectorCreator; - - public void addKnownConnectorsOnStartup(DSLContext dsl) { - var connectorEndpoints = getKnownConnectorsConfigValue(); - connectorCreator.addConnectors(dsl, connectorEndpoints); - connectorQueue.addAll(connectorEndpoints, ConnectorRefreshPriority.ADDED_ON_STARTUP); - } - - private List getKnownConnectorsConfigValue() { - var knownConnectorsString = config.getString(BrokerServerExtension.KNOWN_CONNECTORS, ""); - return Arrays.stream(knownConnectorsString.split(",")).map(String::trim).filter(StringUtils::isNotBlank).distinct().toList(); - } -} diff --git a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/OfflineConnectorKiller.java b/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/OfflineConnectorKiller.java deleted file mode 100644 index 8b46d9c81..000000000 --- a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/OfflineConnectorKiller.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (c) 2023 sovity GmbH - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - * - * Contributors: - * sovity GmbH - initial API and implementation - * - */ - -package de.sovity.edc.ext.brokerserver.services; - -import de.sovity.edc.ext.brokerserver.dao.ConnectorQueries; -import de.sovity.edc.ext.brokerserver.services.config.BrokerServerSettings; -import de.sovity.edc.ext.brokerserver.services.logging.BrokerEventLogger; -import lombok.RequiredArgsConstructor; -import org.jooq.DSLContext; - -@RequiredArgsConstructor -public class OfflineConnectorKiller { - private final BrokerServerSettings brokerServerSettings; - private final ConnectorQueries connectorQueries; - private final BrokerEventLogger brokerEventLogger; - private final ConnectorKiller connectorKiller; - private final ConnectorCleaner connectorClearer; - - public void killIfOfflineTooLong(DSLContext dsl) { - var killOfflineConnectorsAfter = brokerServerSettings.getKillOfflineConnectorsAfter(); - var toKill = connectorQueries.findAllConnectorsForKilling(dsl, killOfflineConnectorsAfter); - - connectorClearer.removeDataForDeadConnectors(dsl, toKill); - connectorKiller.killConnectors(dsl, toKill); - - brokerEventLogger.addKilledDueToOfflineTooLongMessages(dsl, toKill); - } -} diff --git a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/api/AssetPropertyParser.java b/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/api/AssetPropertyParser.java deleted file mode 100644 index 2cb4fdf2c..000000000 --- a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/api/AssetPropertyParser.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (c) 2023 sovity GmbH - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - * - * Contributors: - * sovity GmbH - initial API and implementation - * - */ - -package de.sovity.edc.ext.brokerserver.services.api; - -import com.fasterxml.jackson.core.type.TypeReference; -import com.fasterxml.jackson.databind.ObjectMapper; -import lombok.RequiredArgsConstructor; -import lombok.SneakyThrows; - -import java.util.Map; - -@RequiredArgsConstructor -public class AssetPropertyParser { - private final ObjectMapper objectMapper; - - private final TypeReference> typeToken = new TypeReference<>() { - }; - - @SneakyThrows - public Map parsePropertiesFromJsonString(String assetPropertiesJson) { - return objectMapper.readValue(assetPropertiesJson, typeToken); - } -} diff --git a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/api/AuthorityPortalConnectorDataOfferApiService.java b/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/api/AuthorityPortalConnectorDataOfferApiService.java deleted file mode 100644 index baf08bc02..000000000 --- a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/api/AuthorityPortalConnectorDataOfferApiService.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (c) 2023 sovity GmbH - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - * - * Contributors: - * sovity GmbH - initial API and implementation - * - */ - -package de.sovity.edc.ext.brokerserver.services.api; - -import de.sovity.edc.ext.brokerserver.api.model.AuthorityPortalConnectorDataOfferInfo; -import de.sovity.edc.ext.brokerserver.api.model.AuthorityPortalConnectorDataOfferDetails; -import lombok.RequiredArgsConstructor; -import org.jooq.DSLContext; - -import java.util.List; - -@RequiredArgsConstructor -public class AuthorityPortalConnectorDataOfferApiService { - private final AuthorityPortalConnectorQueryService authorityPortalConnectorQueryService; - private final ConnectorOnlineStatusMapper connectorOnlineStatusMapper; - - public List getConnectorDataOffersByEndpoints(DSLContext dsl, List endpoints) { - return authorityPortalConnectorQueryService.getConnectorsDataOffers(dsl, endpoints).stream() - .map(it -> new AuthorityPortalConnectorDataOfferInfo( - it.getConnectorEndpoint(), - it.getParticipantId(), - connectorOnlineStatusMapper.getOnlineStatus(it.getOnlineStatus()), - it.getOfflineSinceOrLastUpdatedAt(), - it.getDataOffers().stream().map(dataOffer -> new AuthorityPortalConnectorDataOfferDetails(dataOffer.getDataOfferId(), dataOffer.getDataOfferName())).toList() - )) - .toList(); - } - -} diff --git a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/api/AuthorityPortalConnectorMetadataApiService.java b/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/api/AuthorityPortalConnectorMetadataApiService.java deleted file mode 100644 index 60d103bef..000000000 --- a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/api/AuthorityPortalConnectorMetadataApiService.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (c) 2023 sovity GmbH - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - * - * Contributors: - * sovity GmbH - initial API and implementation - * - */ - -package de.sovity.edc.ext.brokerserver.services.api; - -import de.sovity.edc.ext.brokerserver.api.model.AuthorityPortalConnectorInfo; -import lombok.RequiredArgsConstructor; -import org.jooq.DSLContext; - -import java.util.List; - -@RequiredArgsConstructor -public class AuthorityPortalConnectorMetadataApiService { - private final AuthorityPortalConnectorQueryService authorityPortalConnectorQueryService; - private final ConnectorOnlineStatusMapper connectorOnlineStatusMapper; - - public List getMetadataByEndpoints(DSLContext dsl, List endpoints) { - - return authorityPortalConnectorQueryService.getConnectorMetadata(dsl, endpoints).stream() - .map(it -> new AuthorityPortalConnectorInfo( - it.getConnectorEndpoint(), - it.getParticipantId(), - it.getDataOfferCount(), - connectorOnlineStatusMapper.getOnlineStatus(it.getOnlineStatus()), - it.getOfflineSinceOrLastUpdatedAt() - )) - .toList(); - } -} diff --git a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/api/AuthorityPortalConnectorQueryService.java b/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/api/AuthorityPortalConnectorQueryService.java deleted file mode 100644 index bb432ae5c..000000000 --- a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/api/AuthorityPortalConnectorQueryService.java +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Copyright (c) 2023 sovity GmbH - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - * - * Contributors: - * sovity GmbH - initial API and implementation - * - */ - -package de.sovity.edc.ext.brokerserver.services.api; - -import de.sovity.edc.ext.brokerserver.dao.pages.catalog.CatalogQueryFields; -import de.sovity.edc.ext.brokerserver.dao.utils.PostgresqlUtils; -import de.sovity.edc.ext.brokerserver.db.jooq.Tables; -import de.sovity.edc.ext.brokerserver.db.jooq.enums.ConnectorOnlineStatus; -import lombok.AccessLevel; -import lombok.Data; -import lombok.RequiredArgsConstructor; -import lombok.experimental.FieldDefaults; -import org.jetbrains.annotations.NotNull; -import org.jooq.DSLContext; -import org.jooq.Field; -import org.jooq.impl.DSL; - -import java.time.OffsetDateTime; -import java.util.List; - -import static org.jooq.impl.DSL.coalesce; -import static org.jooq.impl.DSL.count; -import static org.jooq.impl.DSL.select; - -@RequiredArgsConstructor -public class AuthorityPortalConnectorQueryService { - - @Data - @FieldDefaults(level = AccessLevel.PRIVATE) - public static class ConnectorMetadataRs { - String connectorEndpoint; - String participantId; - ConnectorOnlineStatus onlineStatus; - OffsetDateTime offlineSinceOrLastUpdatedAt; - Integer dataOfferCount; - } - - @Data - @FieldDefaults(level = AccessLevel.PRIVATE) - public static class ConnectorDetailsRs { - String connectorEndpoint; - String participantId; - ConnectorOnlineStatus onlineStatus; - OffsetDateTime offlineSinceOrLastUpdatedAt; - List dataOffers; - } - - @Data - @FieldDefaults(level = AccessLevel.PRIVATE) - public static class DataOfferRs { - String dataOfferId; - String dataOfferName; - } - - @NotNull - public List getConnectorMetadata(DSLContext dsl, List endpoints) { - var c = Tables.CONNECTOR; - - return dsl.select( - c.ENDPOINT.as("connectorEndpoint"), - c.PARTICIPANT_ID.as("participantId"), - c.ONLINE_STATUS.as("onlineStatus"), - CatalogQueryFields.offlineSinceOrLastUpdatedAt(c).as("offlineSinceOrLastUpdatedAt"), - getDataOfferCount(c.ENDPOINT).as("dataOfferCount") - ) - .from(c) - .where(PostgresqlUtils.in(c.ENDPOINT, endpoints)) - .fetchInto(ConnectorMetadataRs.class); - } - - @NotNull - public Field getDataOfferCount(Field connectorEndpoint) { - var d = Tables.DATA_OFFER; - - return select(coalesce(count().cast(Integer.class), DSL.value(0))) - .from(d) - .where(d.CONNECTOR_ENDPOINT.eq(connectorEndpoint)) - .asField(); - } - - @NotNull - public List getDataOffers(DSLContext dsl, String connectorEndpoint) { - var d = Tables.DATA_OFFER; - - return dsl.select( - d.ASSET_TITLE.as("dataOfferName"), - d.ASSET_ID.as("dataOfferId") - ) - .from(d) - .where(d.CONNECTOR_ENDPOINT.eq(connectorEndpoint)) - .fetchInto(DataOfferRs.class); - } - - - @NotNull - public List getConnectorsDataOffers(DSLContext dsl, List endpoints) { - var c = Tables.CONNECTOR; - - var connectors = dsl.select( - c.ENDPOINT.as("connectorEndpoint"), - c.PARTICIPANT_ID.as("participantId"), - c.ONLINE_STATUS.as("onlineStatus"), - CatalogQueryFields.offlineSinceOrLastUpdatedAt(c).as("offlineSinceOrLastUpdatedAt") - ) - .from(c) - .where(PostgresqlUtils.in(c.ENDPOINT, endpoints)) - .fetchInto(ConnectorDetailsRs.class); - connectors.forEach(connector -> connector.dataOffers = getDataOffers(dsl, connector.connectorEndpoint)); - return connectors; - } -} diff --git a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/api/AuthorityPortalOrganizationMetadataApiService.java b/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/api/AuthorityPortalOrganizationMetadataApiService.java deleted file mode 100644 index 84086463b..000000000 --- a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/api/AuthorityPortalOrganizationMetadataApiService.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (c) 2023 sovity GmbH - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - * - * Contributors: - * sovity GmbH - initial API and implementation - * - */ - -package de.sovity.edc.ext.brokerserver.services.api; - -import de.sovity.edc.ext.brokerserver.api.model.AuthorityPortalOrganizationMetadata; -import de.sovity.edc.ext.brokerserver.db.jooq.Tables; -import de.sovity.edc.ext.brokerserver.db.jooq.tables.records.OrganizationMetadataRecord; -import lombok.RequiredArgsConstructor; -import org.jetbrains.annotations.NotNull; -import org.jooq.DSLContext; - -import java.util.List; - -@RequiredArgsConstructor -public class AuthorityPortalOrganizationMetadataApiService { - - public void setOrganizationMetadata(DSLContext dsl, List organizationMetadata) { - var records = organizationMetadata.stream().map(this::buildRecord).toList(); - - dsl.deleteFrom(Tables.ORGANIZATION_METADATA).execute(); - dsl.batchInsert(records).execute(); - } - - @NotNull - private OrganizationMetadataRecord buildRecord(AuthorityPortalOrganizationMetadata it) { - var record = new OrganizationMetadataRecord(); - record.setMdsId(it.getMdsId()); - record.setName(it.getName()); - - return record; - } -} diff --git a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/api/CatalogApiService.java b/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/api/CatalogApiService.java deleted file mode 100644 index d83d1cef5..000000000 --- a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/api/CatalogApiService.java +++ /dev/null @@ -1,143 +0,0 @@ -/* - * Copyright (c) 2023 sovity GmbH - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - * - * Contributors: - * sovity GmbH - initial API and implementation - * - */ - -package de.sovity.edc.ext.brokerserver.services.api; - -import de.sovity.edc.ext.brokerserver.api.model.CatalogContractOffer; -import de.sovity.edc.ext.brokerserver.api.model.CatalogDataOffer; -import de.sovity.edc.ext.brokerserver.api.model.CatalogPageQuery; -import de.sovity.edc.ext.brokerserver.api.model.CatalogPageResult; -import de.sovity.edc.ext.brokerserver.api.model.CatalogPageSortingItem; -import de.sovity.edc.ext.brokerserver.api.model.CatalogPageSortingType; -import de.sovity.edc.ext.brokerserver.api.model.ConnectorOnlineStatus; -import de.sovity.edc.ext.brokerserver.dao.pages.catalog.CatalogQueryService; -import de.sovity.edc.ext.brokerserver.dao.pages.catalog.models.DataOfferListEntryRs; -import de.sovity.edc.ext.brokerserver.dao.pages.dataoffer.model.ContractOfferRs; -import de.sovity.edc.ext.brokerserver.services.api.filtering.CatalogFilterService; -import de.sovity.edc.ext.brokerserver.services.config.BrokerServerSettings; -import lombok.RequiredArgsConstructor; -import org.jooq.DSLContext; - -import java.util.List; -import java.util.Objects; -import java.util.stream.Stream; - -@RequiredArgsConstructor -public class CatalogApiService { - private final PaginationMetadataUtils paginationMetadataUtils; - private final CatalogQueryService catalogQueryService; - private final DataOfferMappingUtils dataOfferMappingUtils; - private final CatalogFilterService catalogFilterService; - private final BrokerServerSettings brokerServerSettings; - - public CatalogPageResult catalogPage(DSLContext dsl, CatalogPageQuery query) { - Objects.requireNonNull(query, "query must not be null"); - - - var filters = catalogFilterService.getCatalogQueryFilters(query.getFilter()); - - var pageQuery = paginationMetadataUtils.getPageQuery( - query.getPageOneBased(), - brokerServerSettings.getCatalogPagePageSize() - ); - - var availableSortings = buildAvailableSortings(); - var sorting = query.getSorting(); - if (sorting == null) { - sorting = availableSortings.get(0).getSorting(); - } - - // execute db query - var catalogPageRs = catalogQueryService.queryCatalogPage( - dsl, - query.getSearchQuery(), - filters, - sorting, - pageQuery - ); - - var paginationMetadata = paginationMetadataUtils.buildPaginationMetadata( - query.getPageOneBased(), - brokerServerSettings.getCatalogPagePageSize(), - catalogPageRs.getDataOffers().size(), - catalogPageRs.getNumTotalDataOffers() - ); - - var result = new CatalogPageResult(); - result.setAvailableSortings(availableSortings); - result.setPaginationMetadata(paginationMetadata); - result.setAvailableFilters(catalogFilterService.buildAvailableFilters(catalogPageRs.getAvailableFilterValues())); - result.setDataOffers(buildCatalogDataOffers(catalogPageRs.getDataOffers())); - return result; - } - - private List buildCatalogDataOffers(List dataOfferRs) { - return dataOfferRs.stream() - .map(this::buildCatalogDataOffer) - .toList(); - } - - private CatalogDataOffer buildCatalogDataOffer(DataOfferListEntryRs dataOfferRs) { - var asset = dataOfferMappingUtils.buildUiAsset( - dataOfferRs.getAssetJsonLd(), - dataOfferRs.getConnectorEndpoint(), - dataOfferRs.getConnectorParticipantId(), - dataOfferRs.getOrganizationName() - ); - - var dataOffer = new CatalogDataOffer(); - dataOffer.setAssetId(dataOfferRs.getAssetId()); - dataOffer.setCreatedAt(dataOfferRs.getCreatedAt()); - dataOffer.setUpdatedAt(dataOfferRs.getUpdatedAt()); - dataOffer.setAsset(asset); - dataOffer.setContractOffers(buildCatalogContractOffers(dataOfferRs)); - dataOffer.setConnectorEndpoint(dataOfferRs.getConnectorEndpoint()); - dataOffer.setConnectorOfflineSinceOrLastUpdatedAt(dataOfferRs.getConnectorOfflineSinceOrLastUpdatedAt()); - dataOffer.setConnectorOnlineStatus(getOnlineStatus(dataOfferRs)); - return dataOffer; - } - - private List buildCatalogContractOffers(DataOfferListEntryRs dataOfferRs) { - return dataOfferRs.getContractOffers().stream() - .map(this::buildCatalogContractOffer) - .toList(); - } - - private CatalogContractOffer buildCatalogContractOffer(ContractOfferRs contractOfferDbRow) { - var contractOffer = new CatalogContractOffer(); - contractOffer.setContractOfferId(contractOfferDbRow.getContractOfferId()); - contractOffer.setContractPolicy(dataOfferMappingUtils.buildUiPolicy(contractOfferDbRow.getPolicyJson())); - contractOffer.setCreatedAt(contractOfferDbRow.getCreatedAt()); - contractOffer.setUpdatedAt(contractOfferDbRow.getUpdatedAt()); - return contractOffer; - } - - private ConnectorOnlineStatus getOnlineStatus(DataOfferListEntryRs dataOfferRs) { - return switch (dataOfferRs.getConnectorOnlineStatus()) { - case ONLINE -> ConnectorOnlineStatus.ONLINE; - case OFFLINE -> ConnectorOnlineStatus.OFFLINE; - case DEAD -> ConnectorOnlineStatus.DEAD; - default -> throw new IllegalStateException("Unknown ConnectorOnlineStatus from DAO for API: " + dataOfferRs.getConnectorOnlineStatus()); - }; - } - - private static List buildAvailableSortings() { - return Stream.of( - CatalogPageSortingType.MOST_RECENT, - CatalogPageSortingType.TITLE, - CatalogPageSortingType.ORIGINATOR, - CatalogPageSortingType.VIEW_COUNT - ).map(it -> new CatalogPageSortingItem(it, it.getTitle())).toList(); - } -} diff --git a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/api/ConnectorApiService.java b/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/api/ConnectorApiService.java deleted file mode 100644 index ffa3c9c5e..000000000 --- a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/api/ConnectorApiService.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright (c) 2023 sovity GmbH - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - * - * Contributors: - * sovity GmbH - initial API and implementation - * - */ - -package de.sovity.edc.ext.brokerserver.services.api; - -import de.sovity.edc.ext.brokerserver.api.model.ConnectorCreationRequest; -import de.sovity.edc.ext.brokerserver.api.model.AddedConnector; -import de.sovity.edc.ext.brokerserver.dao.ConnectorQueries; -import de.sovity.edc.ext.brokerserver.services.logging.BrokerEventLogger; -import de.sovity.edc.ext.brokerserver.utils.MdsIdUtils; -import de.sovity.edc.ext.brokerserver.utils.UrlUtils; -import lombok.RequiredArgsConstructor; -import org.jooq.DSLContext; - -import java.util.List; -import java.util.Objects; - -import static de.sovity.edc.ext.brokerserver.services.queue.ConnectorRefreshPriority.ADDED_ON_API_CALL; -import static java.util.stream.Collectors.toSet; - -@RequiredArgsConstructor -public class ConnectorApiService { - private final ConnectorService connectorService; - private final BrokerEventLogger brokerEventLogger; - private final ConnectorQueries connectorQueries; - - - public void addConnectors(DSLContext dsl, List connectorEndpoints) { - var existingEndpoints = connectorService.getConnectorEndpoints(dsl); - var endpoints = connectorEndpoints.stream() - .filter(Objects::nonNull) - .map(String::trim) - .filter(UrlUtils::isValidUrl) - .filter(endpoint -> !existingEndpoints.contains(endpoint)) - .collect(toSet()); - connectorService.addConnectors(dsl, endpoints, ADDED_ON_API_CALL); - } - - public void addConnectorsWithMdsIds(DSLContext dsl, ConnectorCreationRequest connectorCreationRequests) { - var connectors = connectorCreationRequests.getConnectors(); - var existingEndpoints = connectorService.getConnectorEndpoints(dsl); - - connectors.removeIf(it -> it.getConnectorEndpoint() == null || it.getMdsId() == null); - connectors.forEach(it -> { - it.setConnectorEndpoint(it.getConnectorEndpoint().trim()); - it.setMdsId(it.getMdsId().trim()); - }); - connectors.removeIf(it -> - !UrlUtils.isValidUrl(it.getConnectorEndpoint()) - || !MdsIdUtils.isValidMdsId(it.getMdsId()) - || existingEndpoints.contains(it.getConnectorEndpoint()) - ); - - var endpoints = connectors.stream().map(AddedConnector::getConnectorEndpoint).collect(toSet()); - connectorService.addConnectors(dsl, endpoints, ADDED_ON_API_CALL); - addMdsIdsToConnectors(dsl, connectors); - } - - public void deleteConnectors(DSLContext dsl, List connectorEndpoints) { - connectorService.deleteConnectors(dsl, connectorEndpoints); - brokerEventLogger.logConnectorsDeleted(dsl, connectorEndpoints); - } - - private void addMdsIdsToConnectors(DSLContext dsl, List connectors) { - connectors.forEach(it -> { - var connector = connectorQueries.findByEndpoint(dsl, it.getConnectorEndpoint()); - if (connector != null) { - connector.setMdsId(it.getMdsId()); - connector.update(); - } - }); - } -} diff --git a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/api/ConnectorDetailApiService.java b/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/api/ConnectorDetailApiService.java deleted file mode 100644 index f44097b6e..000000000 --- a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/api/ConnectorDetailApiService.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (c) 2023 sovity GmbH - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - * - * Contributors: - * sovity GmbH - initial API and implementation - * - */ - -package de.sovity.edc.ext.brokerserver.services.api; - -import de.sovity.edc.ext.brokerserver.api.model.ConnectorDetailPageQuery; -import de.sovity.edc.ext.brokerserver.api.model.ConnectorDetailPageResult; -import de.sovity.edc.ext.brokerserver.dao.pages.connector.ConnectorDetailQueryService; -import lombok.RequiredArgsConstructor; -import org.jooq.DSLContext; - -import java.util.Objects; - -@RequiredArgsConstructor -public class ConnectorDetailApiService { - private final ConnectorDetailQueryService connectorDetailQueryService; - private final ConnectorOnlineStatusMapper connectorOnlineStatusMapper; - - public ConnectorDetailPageResult connectorDetailPage(DSLContext dsl, ConnectorDetailPageQuery query) { - Objects.requireNonNull(query, "query must not be null"); - - var connectorDbRow = connectorDetailQueryService.queryConnectorDetailPage(dsl, query.getConnectorEndpoint()); - var dto = new ConnectorDetailPageResult(); - dto.setParticipantId(connectorDbRow.getParticipantId()); - dto.setEndpoint(connectorDbRow.getEndpoint()); - dto.setOrganizationName(connectorDbRow.getOrganizationName()); - dto.setCreatedAt(connectorDbRow.getCreatedAt()); - dto.setLastRefreshAttemptAt(connectorDbRow.getLastRefreshAttemptAt()); - dto.setLastSuccessfulRefreshAt(connectorDbRow.getLastSuccessfulRefreshAt()); - dto.setOnlineStatus(connectorOnlineStatusMapper.getOnlineStatus(connectorDbRow.getOnlineStatus())); - dto.setNumDataOffers(connectorDbRow.getNumDataOffers()); - dto.setConnectorCrawlingTimeAvg(connectorDbRow.getConnectorCrawlingTimeAvg()); - return dto; - } - -} diff --git a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/api/ConnectorListApiService.java b/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/api/ConnectorListApiService.java deleted file mode 100644 index ca0a8d965..000000000 --- a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/api/ConnectorListApiService.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (c) 2023 sovity GmbH - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - * - * Contributors: - * sovity GmbH - initial API and implementation - * - */ - -package de.sovity.edc.ext.brokerserver.services.api; - -import de.sovity.edc.ext.brokerserver.api.model.ConnectorListEntry; -import de.sovity.edc.ext.brokerserver.api.model.ConnectorPageQuery; -import de.sovity.edc.ext.brokerserver.api.model.ConnectorPageResult; -import de.sovity.edc.ext.brokerserver.api.model.ConnectorPageSortingItem; -import de.sovity.edc.ext.brokerserver.api.model.ConnectorPageSortingType; -import de.sovity.edc.ext.brokerserver.dao.pages.connector.ConnectorListQueryService; -import de.sovity.edc.ext.brokerserver.dao.pages.connector.model.ConnectorListEntryRs; -import lombok.RequiredArgsConstructor; -import org.jooq.DSLContext; - -import java.util.List; -import java.util.Objects; -import java.util.stream.Stream; - -@RequiredArgsConstructor -public class ConnectorListApiService { - private final ConnectorListQueryService connectorListQueryService; - private final ConnectorOnlineStatusMapper connectorOnlineStatusMapper; - private final PaginationMetadataUtils paginationMetadataUtils; - - public ConnectorPageResult connectorListPage(DSLContext dsl, ConnectorPageQuery query) { - Objects.requireNonNull(query, "query must not be null"); - - var availableSortings = buildAvailableSortings(); - var sorting = query.getSorting(); - if (sorting == null) { - sorting = availableSortings.get(0).getSorting(); - } - - var connectorDbRows = connectorListQueryService.queryConnectorPage(dsl, query.getSearchQuery(), sorting); - - var result = new ConnectorPageResult(); - result.setAvailableSortings(availableSortings); - result.setPaginationMetadata(paginationMetadataUtils.buildDummyPaginationMetadata(connectorDbRows.size())); - result.setConnectors(buildConnectorListEntries(connectorDbRows)); - return result; - } - - private List buildConnectorListEntries(List connectors) { - return connectors.stream().map(this::buildConnectorListEntry).toList(); - } - - private ConnectorListEntry buildConnectorListEntry(ConnectorListEntryRs connector) { - var dto = new ConnectorListEntry(); - dto.setParticipantId(connector.getParticipantId()); - dto.setEndpoint(connector.getEndpoint()); - dto.setOrganizationName(connector.getOrganizationName()); - dto.setCreatedAt(connector.getCreatedAt()); - dto.setLastRefreshAttemptAt(connector.getLastRefreshAttemptAt()); - dto.setLastSuccessfulRefreshAt(connector.getLastSuccessfulRefreshAt()); - dto.setOnlineStatus(connectorOnlineStatusMapper.getOnlineStatus(connector.getOnlineStatus())); - dto.setNumDataOffers(connector.getNumDataOffers()); - return dto; - } - - private List buildAvailableSortings() { - return Stream.of( - ConnectorPageSortingType.MOST_RECENT, - ConnectorPageSortingType.TITLE - ).map(it -> new ConnectorPageSortingItem(it, it.getTitle())).toList(); - } -} diff --git a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/api/ConnectorOnlineStatusMapper.java b/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/api/ConnectorOnlineStatusMapper.java deleted file mode 100644 index 15f204711..000000000 --- a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/api/ConnectorOnlineStatusMapper.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (c) 2023 sovity GmbH - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - * - * Contributors: - * sovity GmbH - initial API and implementation - * - */ - -package de.sovity.edc.ext.brokerserver.services.api; - -import de.sovity.edc.ext.brokerserver.api.model.ConnectorOnlineStatus; -import lombok.RequiredArgsConstructor; - -@RequiredArgsConstructor -public class ConnectorOnlineStatusMapper { - - public ConnectorOnlineStatus getOnlineStatus(de.sovity.edc.ext.brokerserver.db.jooq.enums.ConnectorOnlineStatus onlineStatus) { - return switch (onlineStatus) { - case ONLINE -> ConnectorOnlineStatus.ONLINE; - case OFFLINE -> ConnectorOnlineStatus.OFFLINE; - case DEAD -> ConnectorOnlineStatus.DEAD; - default -> throw new IllegalStateException("Unknown ConnectorOnlineStatus from DAO for API: " + onlineStatus); - }; - } -} diff --git a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/api/ConnectorService.java b/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/api/ConnectorService.java deleted file mode 100644 index b3996dcb8..000000000 --- a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/api/ConnectorService.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (c) 2023 sovity GmbH - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - * - * Contributors: - * sovity GmbH - initial API and implementation - * - */ - -package de.sovity.edc.ext.brokerserver.services.api; - -import de.sovity.edc.ext.brokerserver.db.jooq.Tables; -import de.sovity.edc.ext.brokerserver.services.ConnectorCreator; -import de.sovity.edc.ext.brokerserver.services.queue.ConnectorQueue; -import lombok.RequiredArgsConstructor; -import org.jooq.DSLContext; -import org.jooq.Record; -import org.jooq.TableField; - -import java.util.Collection; -import java.util.Set; - -@RequiredArgsConstructor -public class ConnectorService { - private final ConnectorCreator connectorCreator; - private final ConnectorQueue connectorQueue; - - public void addConnectors(DSLContext dsl, Collection connectorEndpoints, int priority) { - connectorCreator.addConnectors(dsl, connectorEndpoints); - connectorQueue.addAll(connectorEndpoints, priority); - } - - public void deleteConnectors(DSLContext dsl, Collection endpoints) { - removeConnectorRows(dsl, Tables.BROKER_EXECUTION_TIME_MEASUREMENT.CONNECTOR_ENDPOINT, endpoints); - removeConnectorRows(dsl, Tables.CONTRACT_OFFER.CONNECTOR_ENDPOINT, endpoints); - removeConnectorRows(dsl, Tables.DATA_OFFER.CONNECTOR_ENDPOINT, endpoints); - removeConnectorRows(dsl, Tables.DATA_OFFER_VIEW_COUNT.CONNECTOR_ENDPOINT, endpoints); - removeConnectorRows(dsl, Tables.CONNECTOR.ENDPOINT, endpoints); - } - - public Set getConnectorEndpoints(DSLContext dsl) { - return dsl.select(Tables.CONNECTOR.ENDPOINT).from(Tables.CONNECTOR).fetchSet(Tables.CONNECTOR.ENDPOINT); - } - - private void removeConnectorRows( - DSLContext dsl, - TableField endpointField, - Collection endpoints - ) { - dsl.deleteFrom(endpointField.getTable()).where(endpointField.in(endpoints)).execute(); - } -} diff --git a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/api/DataOfferDetailApiService.java b/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/api/DataOfferDetailApiService.java deleted file mode 100644 index a79bd8b96..000000000 --- a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/api/DataOfferDetailApiService.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright (c) 2023 sovity GmbH - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - * - * Contributors: - * sovity GmbH - initial API and implementation - * - */ - -package de.sovity.edc.ext.brokerserver.services.api; - -import de.sovity.edc.ext.brokerserver.api.model.ConnectorOnlineStatus; -import de.sovity.edc.ext.brokerserver.api.model.DataOfferDetailContractOffer; -import de.sovity.edc.ext.brokerserver.api.model.DataOfferDetailPageQuery; -import de.sovity.edc.ext.brokerserver.api.model.DataOfferDetailPageResult; -import de.sovity.edc.ext.brokerserver.dao.pages.dataoffer.DataOfferDetailPageQueryService; -import de.sovity.edc.ext.brokerserver.dao.pages.dataoffer.ViewCountLogger; -import de.sovity.edc.ext.brokerserver.dao.pages.dataoffer.model.ContractOfferRs; -import lombok.RequiredArgsConstructor; -import org.jetbrains.annotations.NotNull; -import org.jooq.DSLContext; - -import java.util.List; -import java.util.Objects; - -@RequiredArgsConstructor -public class DataOfferDetailApiService { - private final DataOfferDetailPageQueryService dataOfferDetailPageQueryService; - private final ViewCountLogger viewCountLogger; - private final DataOfferMappingUtils dataOfferMappingUtils; - - public DataOfferDetailPageResult dataOfferDetailPage(DSLContext dsl, DataOfferDetailPageQuery query) { - Objects.requireNonNull(query, "query must not be null"); - - var dataOffer = dataOfferDetailPageQueryService.queryDataOfferDetailsPage(dsl, query.getAssetId(), query.getConnectorEndpoint()); - var asset = dataOfferMappingUtils.buildUiAsset( - dataOffer.getAssetJsonLd(), - dataOffer.getConnectorEndpoint(), - dataOffer.getConnectorParticipantId(), - dataOffer.getOrganizationName() - ); - viewCountLogger.increaseDataOfferViewCount(dsl, query.getAssetId(), query.getConnectorEndpoint()); - - var result = new DataOfferDetailPageResult(); - result.setAssetId(dataOffer.getAssetId()); - result.setConnectorEndpoint(dataOffer.getConnectorEndpoint()); - result.setConnectorOnlineStatus(mapConnectorOnlineStatus(dataOffer.getConnectorOnlineStatus())); - result.setConnectorOfflineSinceOrLastUpdatedAt(dataOffer.getConnectorOfflineSinceOrLastUpdatedAt()); - result.setAsset(asset); - result.setCreatedAt(dataOffer.getCreatedAt()); - result.setUpdatedAt(dataOffer.getUpdatedAt()); - result.setContractOffers(buildDataOfferDetailContractOffers(dataOffer.getContractOffers())); - result.setViewCount(dataOffer.getViewCount()); - return result; - } - - private ConnectorOnlineStatus mapConnectorOnlineStatus( - de.sovity.edc.ext.brokerserver.db.jooq.enums.ConnectorOnlineStatus connectorOnlineStatus - ) { - if (connectorOnlineStatus == null) { - return ConnectorOnlineStatus.OFFLINE; - } - - return switch (connectorOnlineStatus) { - case ONLINE -> ConnectorOnlineStatus.ONLINE; - case OFFLINE -> ConnectorOnlineStatus.OFFLINE; - case DEAD -> ConnectorOnlineStatus.DEAD; - }; - } - - private List buildDataOfferDetailContractOffers(List contractOffers) { - return contractOffers.stream().map(this::buildDataOfferDetailContractOffer).toList(); - } - - @NotNull - private DataOfferDetailContractOffer buildDataOfferDetailContractOffer(ContractOfferRs offer) { - var newOffer = new DataOfferDetailContractOffer(); - newOffer.setCreatedAt(offer.getCreatedAt()); - newOffer.setUpdatedAt(offer.getUpdatedAt()); - newOffer.setContractOfferId(offer.getContractOfferId()); - newOffer.setContractPolicy(dataOfferMappingUtils.buildUiPolicy(offer.getPolicyJson())); - return newOffer; - } -} diff --git a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/api/DataOfferMappingUtils.java b/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/api/DataOfferMappingUtils.java deleted file mode 100644 index 77f0cd8f4..000000000 --- a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/api/DataOfferMappingUtils.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (c) 2023 sovity GmbH - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - * - * Contributors: - * sovity GmbH - initial API and implementation - * - */ - -package de.sovity.edc.ext.brokerserver.services.api; - -import de.sovity.edc.ext.wrapper.api.common.mappers.AssetMapper; -import de.sovity.edc.ext.wrapper.api.common.mappers.PolicyMapper; -import de.sovity.edc.ext.wrapper.api.common.model.UiAsset; -import de.sovity.edc.ext.wrapper.api.common.model.UiPolicy; -import de.sovity.edc.utils.JsonUtils; -import lombok.RequiredArgsConstructor; - -@RequiredArgsConstructor -public class DataOfferMappingUtils { - private final PolicyMapper policyMapper; - private final AssetMapper assetMapper; - - public UiAsset buildUiAsset(String assetJsonLd, String endpoint, String participantId, String organizationName) { - var asset = assetMapper.buildAsset(JsonUtils.parseJsonObj(assetJsonLd)); - var uiAsset = assetMapper.buildUiAsset(asset, endpoint, participantId); - uiAsset.setCreatorOrganizationName(organizationName); - return uiAsset; - } - - public UiPolicy buildUiPolicy(String policyJson) { - var policy = policyMapper.buildPolicy(policyJson); - return policyMapper.buildUiPolicy(policy); - } -} diff --git a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/api/PaginationMetadataUtils.java b/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/api/PaginationMetadataUtils.java deleted file mode 100644 index d69cbb707..000000000 --- a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/api/PaginationMetadataUtils.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (c) 2023 sovity GmbH - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - * - * Contributors: - * sovity GmbH - initial API and implementation - * - */ - -package de.sovity.edc.ext.brokerserver.services.api; - -import de.sovity.edc.ext.brokerserver.api.model.PaginationMetadata; -import de.sovity.edc.ext.brokerserver.dao.pages.catalog.models.PageQuery; -import lombok.RequiredArgsConstructor; -import org.jetbrains.annotations.NotNull; - -@RequiredArgsConstructor -public class PaginationMetadataUtils { - - @NotNull - public PaginationMetadata buildDummyPaginationMetadata(int numResults) { - return new PaginationMetadata(numResults, numResults, 1, numResults); - } - - public PageQuery getPageQuery(Integer pageOneBased, int pageSize) { - int pageZeroBased = getPageZeroBased(pageOneBased); - int offset = pageZeroBased * pageSize; - return new PageQuery(offset, pageSize); - } - - public PaginationMetadata buildPaginationMetadata(Integer pageOneBased, int pageSize, int numVisible, int numTotalResults) { - int pageZeroBased = getPageZeroBased(pageOneBased); - var paginationMetadata = new PaginationMetadata(); - paginationMetadata.setNumTotal(numTotalResults); - paginationMetadata.setNumVisible(numVisible); - paginationMetadata.setPageOneBased(pageZeroBased + 1); - paginationMetadata.setPageSize(pageSize); - return paginationMetadata; - } - - private int getPageZeroBased(Integer pageOneBased) { - return pageOneBased == null ? 0 : (pageOneBased - 1); - } -} diff --git a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/api/filtering/AttributeFilterQuery.java b/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/api/filtering/AttributeFilterQuery.java deleted file mode 100644 index 18c9218ba..000000000 --- a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/api/filtering/AttributeFilterQuery.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (c) 2023 sovity GmbH - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - * - * Contributors: - * sovity GmbH - initial API and implementation - * - */ - -package de.sovity.edc.ext.brokerserver.services.api.filtering; - -import de.sovity.edc.ext.brokerserver.dao.pages.catalog.CatalogQueryFields; -import org.jooq.Condition; - -import java.util.Collection; - -@FunctionalInterface -public interface AttributeFilterQuery { - - /** - * Filters a Catalog DB Query for a given Filter Attribute with selected values - * - * @param fields available tables and fields during the catalog query - * @param values values to be filtered by. Usually this should mean that only one of the values needs to be present. - * @return {@link Condition} - */ - Condition filterDataOffers(CatalogQueryFields fields, Collection values); - -} diff --git a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/api/filtering/CatalogFilterAttributeDefinition.java b/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/api/filtering/CatalogFilterAttributeDefinition.java deleted file mode 100644 index 9d13a2c00..000000000 --- a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/api/filtering/CatalogFilterAttributeDefinition.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (c) 2023 sovity GmbH - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - * - * Contributors: - * sovity GmbH - initial API and implementation - * - */ - -package de.sovity.edc.ext.brokerserver.services.api.filtering; - -import de.sovity.edc.ext.brokerserver.dao.pages.catalog.models.AvailableFilterValuesQuery; - -/** - * Implementation of a filter attribute definition for the catalog. - * - * @param name technical id of the attribute - * @param label UI showing label for the attribute - * @param valueGetter query existing values from DB - * @param filterApplier apply a filter to a data offer query - */ -public record CatalogFilterAttributeDefinition( - String name, - String label, - AvailableFilterValuesQuery valueGetter, - AttributeFilterQuery filterApplier -) { -} diff --git a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/api/filtering/CatalogFilterAttributeDefinitionService.java b/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/api/filtering/CatalogFilterAttributeDefinitionService.java deleted file mode 100644 index 088b2cc84..000000000 --- a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/api/filtering/CatalogFilterAttributeDefinitionService.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (c) 2023 sovity GmbH - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - * - * Contributors: - * sovity GmbH - initial API and implementation - * - */ - -package de.sovity.edc.ext.brokerserver.services.api.filtering; - -import de.sovity.edc.ext.brokerserver.dao.pages.catalog.CatalogQueryFields; -import de.sovity.edc.ext.brokerserver.dao.utils.PostgresqlUtils; -import org.jooq.Field; - -import java.util.function.Function; - -public class CatalogFilterAttributeDefinitionService { - - public CatalogFilterAttributeDefinition forField( - Function> fieldExtractor, - String name, - String label - ) { - return new CatalogFilterAttributeDefinition( - name, - label, - fieldExtractor::apply, - (fields, values) -> PostgresqlUtils.in(fieldExtractor.apply(fields), values) - ); - } - - public CatalogFilterAttributeDefinition buildDataSpaceFilter() { - return new CatalogFilterAttributeDefinition( - "dataSpace", - "Data Space", - CatalogQueryFields::getDataSpace, - (fields, values) -> PostgresqlUtils.in(fields.getDataSpace(), values) - ); - } - - public CatalogFilterAttributeDefinition buildConnectorEndpointFilter() { - return new CatalogFilterAttributeDefinition( - "connectorEndpoint", - "Connector", - fields -> fields.getDataOfferTable().CONNECTOR_ENDPOINT, - (fields, values) -> PostgresqlUtils.in(fields.getDataOfferTable().CONNECTOR_ENDPOINT, values) - ); - } -} diff --git a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/api/filtering/CatalogFilterService.java b/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/api/filtering/CatalogFilterService.java deleted file mode 100644 index 860a796ab..000000000 --- a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/api/filtering/CatalogFilterService.java +++ /dev/null @@ -1,161 +0,0 @@ -/* - * Copyright (c) 2023 sovity GmbH - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - * - * Contributors: - * sovity GmbH - initial API and implementation - * - */ - -package de.sovity.edc.ext.brokerserver.services.api.filtering; - -import de.sovity.edc.ext.brokerserver.api.model.CnfFilter; -import de.sovity.edc.ext.brokerserver.api.model.CnfFilterAttribute; -import de.sovity.edc.ext.brokerserver.api.model.CnfFilterItem; -import de.sovity.edc.ext.brokerserver.api.model.CnfFilterValue; -import de.sovity.edc.ext.brokerserver.api.model.CnfFilterValueAttribute; -import de.sovity.edc.ext.brokerserver.dao.pages.catalog.CatalogQueryFields; -import de.sovity.edc.ext.brokerserver.dao.pages.catalog.models.CatalogQueryFilter; -import de.sovity.edc.ext.brokerserver.dao.pages.catalog.models.CatalogQuerySelectedFilterQuery; -import de.sovity.edc.ext.brokerserver.dao.utils.JsonDeserializationUtils; -import de.sovity.edc.ext.brokerserver.utils.CollectionUtils2; -import lombok.RequiredArgsConstructor; -import org.apache.commons.lang3.Validate; -import org.jooq.impl.DSL; - -import java.util.Comparator; -import java.util.List; -import java.util.Map; -import java.util.stream.Stream; - -import static java.util.stream.Collectors.toMap; - -@RequiredArgsConstructor -public class CatalogFilterService { - private final CatalogFilterAttributeDefinitionService catalogFilterAttributeDefinitionService; - - private final Comparator caseInsensitiveEmptyStringLast = (s1, s2) -> { - int result = s1.compareToIgnoreCase(s2); - if (s1.isEmpty() && !s2.isEmpty()) { - return 1; - } else if (!s1.isEmpty() && s2.isEmpty()) { - return -1; - } else { - return result; - } - }; - - - /** - * Currently supported filters for the catalog page. - * - * @return attribute definitions - */ - private List getAvailableFilters() { - return List.of( - catalogFilterAttributeDefinitionService.buildDataSpaceFilter(), - catalogFilterAttributeDefinitionService.forField( - fields -> fields.getDataOfferTable().DATA_CATEGORY, - "dataCategory", - "Data Category" - ), - catalogFilterAttributeDefinitionService.forField( - fields -> fields.getDataOfferTable().DATA_SUBCATEGORY, - "dataSubcategory", - "Data Subcategory" - ), - catalogFilterAttributeDefinitionService.forField( - fields -> fields.getDataOfferTable().DATA_MODEL, - "dataModel", - "Data Model" - ), - catalogFilterAttributeDefinitionService.forField( - fields -> fields.getDataOfferTable().TRANSPORT_MODE, - "transportMode", - "Transport Mode" - ), - catalogFilterAttributeDefinitionService.forField( - fields -> fields.getDataOfferTable().GEO_REFERENCE_METHOD, - "geoReferenceMethod", - "Geo Reference Method" - ), - catalogFilterAttributeDefinitionService.forField( - CatalogQueryFields::getOrganizationName, - "curatorOrganizationName", - "Organization Name" - ), - catalogFilterAttributeDefinitionService.forField( - fields -> DSL.coalesce(fields.getConnectorTable().MDS_ID, "Unknown"), - "curatorMdsId", - "MDS ID" - ), - catalogFilterAttributeDefinitionService.buildConnectorEndpointFilter() - ); - } - - public List getCatalogQueryFilters(CnfFilterValue cnfFilterValue) { - var values = getCnfFilterValuesMap(cnfFilterValue); - return getAvailableFilters().stream() - .map(filter -> new CatalogQueryFilter( - filter.name(), - filter.valueGetter(), - getQueryFilter(filter, values.get(filter.name())) - )) - .toList(); - } - - private CatalogQuerySelectedFilterQuery getQueryFilter(CatalogFilterAttributeDefinition filter, List values) { - if (CollectionUtils2.isNotEmpty(values)) { - return fields -> filter.filterApplier().filterDataOffers(fields, values); - } - return null; - } - - public CnfFilter buildAvailableFilters(String filterValuesJson) { - var filterValues = JsonDeserializationUtils.read2dStringList(filterValuesJson); - var filterAttributes = zipAvailableFilters(getAvailableFilters(), filterValues) - .map(availableFilter -> new CnfFilterAttribute( - availableFilter.definition().name(), - availableFilter.definition().label(), - buildAvailableFilterValues(availableFilter) - )) - .toList(); - return new CnfFilter(filterAttributes); - } - - private List buildAvailableFilterValues(AvailableFilter availableFilter) { - return availableFilter.availableValues().stream() - .sorted(caseInsensitiveEmptyStringLast) - .map(value -> new CnfFilterItem(value, value)) - .toList(); - } - - private Stream zipAvailableFilters(List availableFilters, List> filterValues) { - Validate.isTrue( - availableFilters.size() == filterValues.size(), - "Number of available filters and filter values must match: %d != %d", - availableFilters.size(), - filterValues.size() - ); - return Stream.iterate(0, i -> i + 1) - .limit(availableFilters.size()) - .map(i -> new AvailableFilter(availableFilters.get(i), filterValues.get(i))); - } - - private record AvailableFilter(CatalogFilterAttributeDefinition definition, List availableValues) { - } - - private Map> getCnfFilterValuesMap(CnfFilterValue cnfFilterValue) { - if (cnfFilterValue == null || cnfFilterValue.getSelectedAttributeValues() == null) { - return Map.of(); - } - return cnfFilterValue.getSelectedAttributeValues().stream() - .filter(it -> it.getId() != null && CollectionUtils2.isNotEmpty(it.getSelectedIds())) - .collect(toMap(CnfFilterValueAttribute::getId, CnfFilterValueAttribute::getSelectedIds)); - } -} diff --git a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/api/filtering/CatalogSearchService.java b/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/api/filtering/CatalogSearchService.java deleted file mode 100644 index b7abd8b6e..000000000 --- a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/api/filtering/CatalogSearchService.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (c) 2023 sovity GmbH - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - * - * Contributors: - * sovity GmbH - initial API and implementation - * - */ - -package de.sovity.edc.ext.brokerserver.services.api.filtering; - -import de.sovity.edc.ext.brokerserver.dao.pages.catalog.CatalogQueryFields; -import de.sovity.edc.ext.brokerserver.dao.utils.SearchUtils; -import lombok.RequiredArgsConstructor; -import org.jooq.Condition; - -import java.util.List; - -@RequiredArgsConstructor -public class CatalogSearchService { - - public Condition filterBySearch(CatalogQueryFields fields, String searchQuery) { - return SearchUtils.simpleSearch(searchQuery, List.of( - fields.getDataOfferTable().ASSET_ID, - fields.getDataOfferTable().ASSET_TITLE, - fields.getDataOfferTable().DATA_CATEGORY, - fields.getDataOfferTable().DATA_SUBCATEGORY, - fields.getDataOfferTable().DESCRIPTION, - fields.getDataOfferTable().CURATOR_ORGANIZATION_NAME, - fields.getDataOfferTable().KEYWORDS_COMMA_JOINED, - fields.getConnectorTable().ENDPOINT, - fields.getConnectorTable().PARTICIPANT_ID, - fields.getOrganizationName() - )); - } -} diff --git a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/config/AdminApiKeyValidator.java b/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/config/AdminApiKeyValidator.java deleted file mode 100644 index e5f9571b9..000000000 --- a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/config/AdminApiKeyValidator.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (c) 2023 sovity GmbH - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - * - * Contributors: - * sovity GmbH - initial API and implementation - * - */ - -package de.sovity.edc.ext.brokerserver.services.config; - -import jakarta.ws.rs.WebApplicationException; -import jakarta.ws.rs.core.Response; -import lombok.RequiredArgsConstructor; - -@RequiredArgsConstructor -public class AdminApiKeyValidator { - private final BrokerServerSettings brokerServerSettings; - - public void validateAdminApiKey(String adminApiKey) { - if (!brokerServerSettings.getAdminApiKey().equals(adminApiKey)) { - throw new WebApplicationException("Invalid admin API key", Response.Status.UNAUTHORIZED); - } - } -} diff --git a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/config/BrokerServerSettingsFactory.java b/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/config/BrokerServerSettingsFactory.java deleted file mode 100644 index a09814341..000000000 --- a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/config/BrokerServerSettingsFactory.java +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright (c) 2023 sovity GmbH - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - * - * Contributors: - * sovity GmbH - initial API and implementation - * - */ - -package de.sovity.edc.ext.brokerserver.services.config; - -import de.sovity.edc.ext.brokerserver.BrokerServerExtension; -import lombok.NonNull; -import lombok.RequiredArgsConstructor; -import org.apache.commons.lang3.StringUtils; -import org.apache.commons.lang3.Validate; -import org.eclipse.edc.spi.monitor.Monitor; -import org.eclipse.edc.spi.system.configuration.Config; - -import java.time.Duration; -import java.util.Arrays; -import java.util.List; - -@RequiredArgsConstructor -public class BrokerServerSettingsFactory { - private final Config config; - private final Monitor monitor; - - public BrokerServerSettings buildBrokerServerSettings() { - var adminApiKey = Validate.notBlank(config.getString(BrokerServerExtension.ADMIN_API_KEY), - "Need to configure %s.".formatted(BrokerServerExtension.ADMIN_API_KEY)); - var hideOfflineDataOffersAfter = getDuration(BrokerServerExtension.HIDE_OFFLINE_DATA_OFFERS_AFTER, null); - var catalogPagePageSize = config.getInteger(BrokerServerExtension.CATALOG_PAGE_PAGE_SIZE, 20); - var dataSpaceConfig = buildDataSpaceConfig(config); - var numThreads = config.getInteger(BrokerServerExtension.NUM_THREADS, 1); - var killOfflineConnectorsAfter = getDuration(BrokerServerExtension.KILL_OFFLINE_CONNECTORS_AFTER, Duration.ofDays(5)); - var maxDataOffers = config.getInteger(BrokerServerExtension.MAX_DATA_OFFERS_PER_CONNECTOR, -1); - var maxContractOffers = config.getInteger(BrokerServerExtension.MAX_CONTRACT_OFFERS_PER_DATA_OFFER, -1); - - return BrokerServerSettings.builder() - .adminApiKey(adminApiKey) - .hideOfflineDataOffersAfter(hideOfflineDataOffersAfter) - .catalogPagePageSize(catalogPagePageSize) - .dataSpaceConfig(dataSpaceConfig) - .numThreads(numThreads) - .killOfflineConnectorsAfter(killOfflineConnectorsAfter) - .maxDataOffersPerConnector(maxDataOffers) - .maxContractOffersPerDataOffer(maxContractOffers) - .build(); - } - - private DataSpaceConfig buildDataSpaceConfig(Config config) { - var dataSpaceConfig = new DataSpaceConfig(getKnownDataSpaceEndpoints(config), getDefaultDataSpace(config)); - monitor.info("Default Dataspace Name: %s".formatted(dataSpaceConfig.defaultDataSpace())); - dataSpaceConfig.dataSpaceConnectors().forEach(dataSpaceConnector -> monitor.info("Using Dataspace Name %s for %s." - .formatted(dataSpaceConnector.dataSpaceName(), dataSpaceConnector.endpoint()))); - if (dataSpaceConfig.dataSpaceConnectors().isEmpty()) { - monitor.info("No additional data space names configured."); - } - return dataSpaceConfig; - } - - private List getKnownDataSpaceEndpoints(Config config) { - // Example: "Example1=http://connector-endpoint1.org,Example2=http://connector-endpoint2.org" - var dataSpacesConfig = config.getString(BrokerServerExtension.KNOWN_DATASPACE_CONNECTORS, ""); - - return Arrays.stream(dataSpacesConfig.split(",")) - .map(String::trim) - .map(it -> it.split("=")) - .filter(it -> it.length == 2) - .map(it -> { - var dataSpaceName = it[0].trim(); - var dataSpaceEndpoint = it[1].trim(); - return new DataSpaceConnector(dataSpaceEndpoint, dataSpaceName); - }) - .filter(it -> StringUtils.isNotBlank(it.endpoint()) && StringUtils.isNotBlank(it.endpoint())) - .toList(); - } - - private String getDefaultDataSpace(Config config) { - return config.getString(BrokerServerExtension.DEFAULT_CONNECTOR_DATASPACE, "Default"); - } - - private Duration getDuration(@NonNull String configProperty, Duration defaultValue) { - var value = config.getString(configProperty, ""); - - if (StringUtils.isBlank(value)) { - return defaultValue; - } - - return Duration.parse(value); - } -} diff --git a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/config/DataSpaceConfig.java b/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/config/DataSpaceConfig.java deleted file mode 100644 index 705a5c1cc..000000000 --- a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/config/DataSpaceConfig.java +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright (c) 2023 sovity GmbH - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - * - * Contributors: - * sovity GmbH - initial API and implementation - * - */ - -package de.sovity.edc.ext.brokerserver.services.config; - -import java.util.List; - -public record DataSpaceConfig(List dataSpaceConnectors, String defaultDataSpace) { -} diff --git a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/config/DataSpaceConnector.java b/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/config/DataSpaceConnector.java deleted file mode 100644 index 589f08aa0..000000000 --- a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/config/DataSpaceConnector.java +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright (c) 2023 sovity GmbH - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - * - * Contributors: - * sovity GmbH - initial API and implementation - * - */ - -package de.sovity.edc.ext.brokerserver.services.config; - -/** - * We have special connectors that represent entire other data spaces. - * Here we associate the name of the data space with the connector endpoint. - */ -public record DataSpaceConnector(String endpoint, String dataSpaceName) { -} diff --git a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/logging/BrokerEventLogger.java b/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/logging/BrokerEventLogger.java deleted file mode 100644 index 439e81be0..000000000 --- a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/logging/BrokerEventLogger.java +++ /dev/null @@ -1,131 +0,0 @@ -/* - * Copyright (c) 2023 sovity GmbH - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - * - * Contributors: - * sovity GmbH - initial API and implementation - * - */ - -package de.sovity.edc.ext.brokerserver.services.logging; - -import de.sovity.edc.ext.brokerserver.db.jooq.Tables; -import de.sovity.edc.ext.brokerserver.db.jooq.enums.BrokerEventStatus; -import de.sovity.edc.ext.brokerserver.db.jooq.enums.BrokerEventType; -import lombok.RequiredArgsConstructor; -import org.jooq.DSLContext; - -import java.time.OffsetDateTime; -import java.util.Collection; -import java.util.List; -import java.util.stream.Collectors; - -/** - * Updates a single connector. - */ -@RequiredArgsConstructor -public class BrokerEventLogger { - - public void logConnectorsDeleted(DSLContext dsl, Collection connectorEndpoints) { - var records = connectorEndpoints.stream().map(connectorEndpoint -> { - var logEntry = dsl.newRecord(Tables.BROKER_EVENT_LOG); - logEntry.setEvent(BrokerEventType.CONNECTOR_DELETED); - logEntry.setEventStatus(BrokerEventStatus.OK); - logEntry.setConnectorEndpoint(connectorEndpoint); - logEntry.setCreatedAt(OffsetDateTime.now()); - logEntry.setUserMessage("Connector was deleted."); - return logEntry; - }).toList(); - dsl.batchInsert(records).execute(); - } - - public void logConnectorUpdated(DSLContext dsl, String connectorEndpoint, ConnectorChangeTracker changes) { - var logEntry = dsl.newRecord(Tables.BROKER_EVENT_LOG); - logEntry.setEvent(BrokerEventType.CONNECTOR_UPDATED); - logEntry.setEventStatus(BrokerEventStatus.OK); - logEntry.setConnectorEndpoint(connectorEndpoint); - logEntry.setCreatedAt(OffsetDateTime.now()); - logEntry.setUserMessage(changes.toString()); - logEntry.insert(); - } - - public void logConnectorOffline(DSLContext dsl, String connectorEndpoint, BrokerEventErrorMessage errorMessage) { - var logEntry = dsl.newRecord(Tables.BROKER_EVENT_LOG); - logEntry.setEvent(BrokerEventType.CONNECTOR_STATUS_CHANGE_OFFLINE); - logEntry.setEventStatus(BrokerEventStatus.ERROR); - logEntry.setConnectorEndpoint(connectorEndpoint); - logEntry.setCreatedAt(OffsetDateTime.now()); - logEntry.setUserMessage("Connector is offline."); - logEntry.setErrorStack(errorMessage.stackTraceOrNull()); - logEntry.insert(); - } - - public void logConnectorOnline(DSLContext dsl, String connectorEndpoint) { - var logEntry = dsl.newRecord(Tables.BROKER_EVENT_LOG); - logEntry.setEvent(BrokerEventType.CONNECTOR_STATUS_CHANGE_ONLINE); - logEntry.setEventStatus(BrokerEventStatus.OK); - logEntry.setConnectorEndpoint(connectorEndpoint); - logEntry.setCreatedAt(OffsetDateTime.now()); - logEntry.setUserMessage("Connector is online."); - logEntry.insert(); - } - - public void logConnectorUpdateDataOfferLimitExceeded(DSLContext dsl, Integer maxDataOffersPerConnector, String endpoint) { - var logEntry = dsl.newRecord(Tables.BROKER_EVENT_LOG); - logEntry.setEvent(BrokerEventType.CONNECTOR_DATA_OFFER_LIMIT_EXCEEDED); - logEntry.setEventStatus(BrokerEventStatus.OK); - logEntry.setConnectorEndpoint(endpoint); - logEntry.setUserMessage("Connector has more than %d data offers. Exceeding data offers will be ignored.".formatted(maxDataOffersPerConnector)); - logEntry.setCreatedAt(OffsetDateTime.now()); - logEntry.insert(); - } - - public void logConnectorUpdateDataOfferLimitOk(DSLContext dsl, String endpoint) { - var logEntry = dsl.newRecord(Tables.BROKER_EVENT_LOG); - logEntry.setEvent(BrokerEventType.CONNECTOR_DATA_OFFER_LIMIT_OK); - logEntry.setEventStatus(BrokerEventStatus.OK); - logEntry.setConnectorEndpoint(endpoint); - logEntry.setUserMessage("Connector is not exceeding the maximum number of data offers limit anymore."); - logEntry.setCreatedAt(OffsetDateTime.now()); - logEntry.insert(); - } - - public void logConnectorUpdateContractOfferLimitExceeded(DSLContext dsl, Integer maxContractOffersPerConnector, String endpoint) { - var logEntry = dsl.newRecord(Tables.BROKER_EVENT_LOG); - logEntry.setEvent(BrokerEventType.CONNECTOR_CONTRACT_OFFER_LIMIT_EXCEEDED); - logEntry.setEventStatus(BrokerEventStatus.OK); - logEntry.setConnectorEndpoint(endpoint); - logEntry.setUserMessage("Some data offers have more than %d contract offers. Exceeding contract offers will be ignored.: ".formatted(maxContractOffersPerConnector)); - logEntry.setCreatedAt(OffsetDateTime.now()); - logEntry.insert(); - } - - public void logConnectorUpdateContractOfferLimitOk(DSLContext dsl, String endpoint) { - var logEntry = dsl.newRecord(Tables.BROKER_EVENT_LOG); - logEntry.setEvent(BrokerEventType.CONNECTOR_CONTRACT_OFFER_LIMIT_OK); - logEntry.setEventStatus(BrokerEventStatus.OK); - logEntry.setConnectorEndpoint(endpoint); - logEntry.setUserMessage("Connector is not exceeding the maximum number of contract offers per data offer limit anymore."); - logEntry.setCreatedAt(OffsetDateTime.now()); - logEntry.insert(); - } - - public void addKilledDueToOfflineTooLongMessages(DSLContext dsl, List deletedConnectorEndpoints) { - var logEntries = deletedConnectorEndpoints.stream().map(endpoint -> { - var logEntry = dsl.newRecord(Tables.BROKER_EVENT_LOG); - logEntry.setEvent(BrokerEventType.CONNECTOR_KILLED_DUE_TO_OFFLINE_FOR_TOO_LONG); - logEntry.setEventStatus(BrokerEventStatus.OK); - logEntry.setCreatedAt(OffsetDateTime.now()); - logEntry.setUserMessage("Connector was marked as dead for being offline too long."); - logEntry.setConnectorEndpoint(endpoint); - return logEntry; - }).collect(Collectors.toList()); - - dsl.batchInsert(logEntries).execute(); - } -} diff --git a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/logging/BrokerExecutionTimeLogger.java b/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/logging/BrokerExecutionTimeLogger.java deleted file mode 100644 index 7743ac753..000000000 --- a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/logging/BrokerExecutionTimeLogger.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (c) 2023 sovity GmbH - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - * - * Contributors: - * sovity GmbH - initial API and implementation - * - */ - -package de.sovity.edc.ext.brokerserver.services.logging; - -import de.sovity.edc.ext.brokerserver.db.jooq.Tables; -import de.sovity.edc.ext.brokerserver.db.jooq.enums.MeasurementErrorStatus; -import de.sovity.edc.ext.brokerserver.db.jooq.enums.MeasurementType; -import lombok.RequiredArgsConstructor; -import org.jooq.DSLContext; - -import java.time.OffsetDateTime; - -/** - * Updates a single connector. - */ -@RequiredArgsConstructor -public class BrokerExecutionTimeLogger { - public void logExecutionTime(DSLContext dsl, String connectorEndpoint, long executionTimeInMs, MeasurementErrorStatus errorStatus) { - var logEntry = dsl.newRecord(Tables.BROKER_EXECUTION_TIME_MEASUREMENT); - logEntry.setConnectorEndpoint(connectorEndpoint); - logEntry.setDurationInMs(executionTimeInMs); - logEntry.setType(MeasurementType.CONNECTOR_REFRESH); - logEntry.setErrorStatus(errorStatus); - logEntry.setConnectorEndpoint(connectorEndpoint); - logEntry.setCreatedAt(OffsetDateTime.now()); - logEntry.insert(); - } -} diff --git a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/queue/ConnectorQueue.java b/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/queue/ConnectorQueue.java deleted file mode 100644 index a1d790494..000000000 --- a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/queue/ConnectorQueue.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (c) 2023 sovity GmbH - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - * - * Contributors: - * sovity GmbH - initial API and implementation - * - */ - -package de.sovity.edc.ext.brokerserver.services.queue; - -import de.sovity.edc.ext.brokerserver.services.refreshing.ConnectorUpdater; -import lombok.RequiredArgsConstructor; - -import java.util.ArrayList; -import java.util.Collection; - -@RequiredArgsConstructor -public class ConnectorQueue { - private final ConnectorUpdater connectorUpdater; - private final ThreadPool threadPool; - - /** - * Enqueues connectors for update. - * - * @param endpoints connector endpoints - * @param priority priority from {@link ConnectorRefreshPriority} - */ - public void addAll(Collection endpoints, int priority) { - var queuedConnectorEndpoints = threadPool.getQueuedConnectorEndpoints(); - endpoints = new ArrayList<>(endpoints); - endpoints.removeIf(queuedConnectorEndpoints::contains); - - for (String endpoint : endpoints) { - threadPool.enqueueConnectorRefreshTask(priority, () -> connectorUpdater.updateConnector(endpoint), endpoint); - } - } -} diff --git a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/refreshing/ConnectorUpdateSuccessWriter.java b/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/refreshing/ConnectorUpdateSuccessWriter.java deleted file mode 100644 index 51172fd21..000000000 --- a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/refreshing/ConnectorUpdateSuccessWriter.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (c) 2023 sovity GmbH - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - * - * Contributors: - * sovity GmbH - initial API and implementation - * - */ - -package de.sovity.edc.ext.brokerserver.services.refreshing; - -import de.sovity.edc.ext.brokerserver.db.jooq.enums.ConnectorOnlineStatus; -import de.sovity.edc.ext.brokerserver.db.jooq.tables.records.ConnectorRecord; -import de.sovity.edc.ext.brokerserver.services.logging.BrokerEventLogger; -import de.sovity.edc.ext.brokerserver.services.logging.ConnectorChangeTracker; -import de.sovity.edc.ext.brokerserver.services.refreshing.offers.DataOfferLimitsEnforcer; -import de.sovity.edc.ext.brokerserver.services.refreshing.offers.DataOfferWriter; -import de.sovity.edc.ext.brokerserver.services.refreshing.offers.model.FetchedCatalog; -import de.sovity.edc.ext.brokerserver.utils.MdsIdUtils; -import lombok.RequiredArgsConstructor; -import org.jooq.DSLContext; - -import java.time.OffsetDateTime; -import java.util.Objects; - -@RequiredArgsConstructor -public class ConnectorUpdateSuccessWriter { - private final BrokerEventLogger brokerEventLogger; - private final DataOfferWriter dataOfferWriter; - private final DataOfferLimitsEnforcer dataOfferLimitsEnforcer; - - public void handleConnectorOnline( - DSLContext dsl, - ConnectorRecord connector, - FetchedCatalog catalog - ) { - // Limit data offers and log limitation if necessary - var limitedDataOffers = dataOfferLimitsEnforcer.enforceLimits(catalog.getDataOffers()); - dataOfferLimitsEnforcer.logEnforcedLimitsIfChanged(dsl, connector, limitedDataOffers); - - // Log Status Change and set status to online if necessary - if (connector.getOnlineStatus() != ConnectorOnlineStatus.ONLINE || connector.getLastRefreshAttemptAt() == null) { - brokerEventLogger.logConnectorOnline(dsl, connector.getEndpoint()); - connector.setOnlineStatus(ConnectorOnlineStatus.ONLINE); - } - - // Track changes for final log message - var changes = new ConnectorChangeTracker(); - updateConnector(connector, catalog, changes); - - // Update data offers - dataOfferWriter.updateDataOffers(dsl, connector.getEndpoint(), limitedDataOffers.abbreviatedDataOffers(), changes); - - // Log event if changes are present - if (!changes.isEmpty()) { - brokerEventLogger.logConnectorUpdated(dsl, connector.getEndpoint(), changes); - } - } - - private static void updateConnector(ConnectorRecord connector, FetchedCatalog catalog, ConnectorChangeTracker changes) { - var now = OffsetDateTime.now(); - var participantId = catalog.getParticipantId(); - - connector.setLastSuccessfulRefreshAt(now); - connector.setLastRefreshAttemptAt(now); - if (!Objects.equals(connector.getParticipantId(), participantId)) { - connector.setParticipantId(participantId); - connector.setMdsId(MdsIdUtils.getMdsIdFromParticipantId(participantId)); - changes.setParticipantIdChanged(participantId); - } - connector.update(); - } -} diff --git a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/refreshing/exceptions/ConnectorUnreachableException.java b/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/refreshing/exceptions/ConnectorUnreachableException.java deleted file mode 100644 index de9172f2a..000000000 --- a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/refreshing/exceptions/ConnectorUnreachableException.java +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (c) 2023 sovity GmbH - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - * - * Contributors: - * sovity GmbH - initial API and implementation - * - */ - -package de.sovity.edc.ext.brokerserver.services.refreshing.exceptions; - -public class ConnectorUnreachableException extends RuntimeException { - public ConnectorUnreachableException(String message, Throwable cause) { - super(message, cause); - } -} diff --git a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/refreshing/offers/DataOfferPatchApplier.java b/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/refreshing/offers/DataOfferPatchApplier.java deleted file mode 100644 index 91cb0395f..000000000 --- a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/refreshing/offers/DataOfferPatchApplier.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (c) 2023 sovity GmbH - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - * - * Contributors: - * sovity GmbH - initial API and implementation - * - */ - -package de.sovity.edc.ext.brokerserver.services.refreshing.offers; - -import de.sovity.edc.ext.brokerserver.services.refreshing.offers.model.DataOfferPatch; -import lombok.RequiredArgsConstructor; -import lombok.SneakyThrows; -import org.jooq.DSLContext; - -@RequiredArgsConstructor -public class DataOfferPatchApplier { - - @SneakyThrows - public void writeDataOfferPatch(DSLContext dsl, DataOfferPatch dataOfferPatch) { - if (!dataOfferPatch.getDataOffersToUpdate().isEmpty()) { - dsl.batchUpdate(dataOfferPatch.getDataOffersToUpdate()).execute(); - } - if (!dataOfferPatch.getContractOffersToUpdate().isEmpty()) { - dsl.batchUpdate(dataOfferPatch.getContractOffersToUpdate()).execute(); - } - - // insert: parent entity first - if (!dataOfferPatch.getDataOffersToInsert().isEmpty()) { - dsl.batchInsert(dataOfferPatch.getDataOffersToInsert()).execute(); - } - if (!dataOfferPatch.getContractOffersToInsert().isEmpty()) { - dsl.batchInsert(dataOfferPatch.getContractOffersToInsert()).execute(); - } - - // delete: child entity first - if (!dataOfferPatch.getContractOffersToDelete().isEmpty()) { - dsl.batchDelete(dataOfferPatch.getContractOffersToDelete()).execute(); - } - if (!dataOfferPatch.getDataOffersToDelete().isEmpty()) { - dsl.batchDelete(dataOfferPatch.getDataOffersToDelete()).execute(); - } - } -} diff --git a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/refreshing/offers/DataOfferRecordUpdater.java b/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/refreshing/offers/DataOfferRecordUpdater.java deleted file mode 100644 index 97b1e2102..000000000 --- a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/refreshing/offers/DataOfferRecordUpdater.java +++ /dev/null @@ -1,206 +0,0 @@ -/* - * Copyright (c) 2023 sovity GmbH - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - * - * Contributors: - * sovity GmbH - initial API and implementation - * - */ - -package de.sovity.edc.ext.brokerserver.services.refreshing.offers; - -import de.sovity.edc.ext.brokerserver.dao.utils.JsonbUtils; -import de.sovity.edc.ext.brokerserver.db.jooq.tables.records.DataOfferRecord; -import de.sovity.edc.ext.brokerserver.services.refreshing.offers.model.FetchedDataOffer; -import de.sovity.edc.ext.brokerserver.utils.JsonUtils2; -import lombok.RequiredArgsConstructor; -import org.jooq.JSONB; - -import java.time.OffsetDateTime; -import java.util.Arrays; -import java.util.HashSet; -import java.util.List; -import java.util.Objects; -import java.util.function.Consumer; -import java.util.function.Function; - -/** - * Creates or updates {@link DataOfferRecord} DB Rows. - *

- * (Or at least prepares them for batch inserts / updates) - */ -@RequiredArgsConstructor -public class DataOfferRecordUpdater { - /** - * Create a new {@link DataOfferRecord}. - * - * @param connectorEndpoint connector endpoint - * @param fetchedDataOffer new db row data - * @return new db row - */ - public DataOfferRecord newDataOffer(String connectorEndpoint, FetchedDataOffer fetchedDataOffer) { - var dataOffer = new DataOfferRecord(); - dataOffer.setConnectorEndpoint(connectorEndpoint); - dataOffer.setAssetId(fetchedDataOffer.getAssetId()); - dataOffer.setCreatedAt(OffsetDateTime.now()); - updateDataOffer(dataOffer, fetchedDataOffer, true); - return dataOffer; - } - - - /** - * Update existing {@link DataOfferRecord}. - * - * @param dataOffer existing row - * @param fetchedDataOffer changes to be incorporated - * @param changed whether the data offer should be marked as updated simply because the contract offers changed - * @return whether any fields were updated - */ - public boolean updateDataOffer( - DataOfferRecord dataOffer, - FetchedDataOffer fetchedDataOffer, - boolean changed - ) { - changed |= updateField( - dataOffer, - fetchedDataOffer, - FetchedDataOffer::getAssetTitle, - DataOfferRecord::getAssetTitle, - dataOffer::setAssetTitle - ); - - changed |= updateField( - dataOffer, - fetchedDataOffer, - FetchedDataOffer::getDescription, - DataOfferRecord::getDescription, - dataOffer::setDescription - ); - - changed |= updateField( - dataOffer, - fetchedDataOffer, - FetchedDataOffer::getCuratorOrganizationName, - DataOfferRecord::getCuratorOrganizationName, - dataOffer::setCuratorOrganizationName - ); - - changed |= updateField( - dataOffer, - fetchedDataOffer, - FetchedDataOffer::getDataCategory, - DataOfferRecord::getDataCategory, - dataOffer::setDataCategory - ); - - changed |= updateField( - dataOffer, - fetchedDataOffer, - FetchedDataOffer::getDataSubcategory, - DataOfferRecord::getDataSubcategory, - dataOffer::setDataSubcategory - ); - - changed |= updateField( - dataOffer, - fetchedDataOffer, - FetchedDataOffer::getDataModel, - DataOfferRecord::getDataModel, - dataOffer::setDataModel - ); - - changed |= updateField( - dataOffer, - fetchedDataOffer, - FetchedDataOffer::getTransportMode, - DataOfferRecord::getTransportMode, - dataOffer::setTransportMode - ); - - changed |= updateField( - dataOffer, - fetchedDataOffer, - FetchedDataOffer::getGeoReferenceMethod, - DataOfferRecord::getGeoReferenceMethod, - dataOffer::setGeoReferenceMethod - ); - - changed |= updateKeywords(dataOffer, fetchedDataOffer); - - changed |= updateAssetJsonLd(dataOffer, fetchedDataOffer); - - if (changed) { - dataOffer.setUpdatedAt(OffsetDateTime.now()); - } - - return changed; - } - - private boolean updateField( - DataOfferRecord dataOffer, - FetchedDataOffer fetchedDataOffer, - Function fetchedField, - Function existingField, - Consumer setter - ) { - var fetched = fetchedField.apply(fetchedDataOffer); - if (fetched == null) { - fetched = ""; - } - - var existing = existingField.apply(dataOffer); - if (existing == null) { - existing = ""; - } - - - if (Objects.equals(fetched, existing)) { - return false; - } - - setter.accept(fetched); - return true; - } - - private boolean updateKeywords( - DataOfferRecord dataOffer, - FetchedDataOffer fetchedDataOffer - ) { - List fetched = fetchedDataOffer.getKeywords(); - if (fetched == null) { - fetched = List.of(); - } - - String[] existing = dataOffer.getKeywords(); - if (existing == null) { - existing = new String[0]; - } - - if (Objects.equals(new HashSet<>(fetched), new HashSet<>(Arrays.asList(existing)))) { - return false; - } - - dataOffer.setKeywords(fetched.toArray(new String[0])); - dataOffer.setKeywordsCommaJoined(String.join(",", fetched)); - return true; - } - - private boolean updateAssetJsonLd( - DataOfferRecord dataOffer, - FetchedDataOffer fetchedDataOffer - ) { - String existing = JsonbUtils.getDataOrNull(dataOffer.getAssetJsonLd()); - var fetched = fetchedDataOffer.getAssetJsonLd(); - if (JsonUtils2.isEqualJson(fetched, existing)) { - return false; - } - - dataOffer.setAssetJsonLd(JSONB.jsonb(fetched)); - return true; - } -} diff --git a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/refreshing/offers/DataOfferWriter.java b/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/refreshing/offers/DataOfferWriter.java deleted file mode 100644 index e69e446ee..000000000 --- a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/refreshing/offers/DataOfferWriter.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (c) 2023 sovity GmbH - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - * - * Contributors: - * sovity GmbH - initial API and implementation - * - */ - -package de.sovity.edc.ext.brokerserver.services.refreshing.offers; - -import de.sovity.edc.ext.brokerserver.services.logging.ConnectorChangeTracker; -import de.sovity.edc.ext.brokerserver.services.refreshing.offers.model.FetchedDataOffer; -import lombok.RequiredArgsConstructor; -import lombok.SneakyThrows; -import org.jooq.DSLContext; - -import java.util.Collection; - -@RequiredArgsConstructor -public class DataOfferWriter { - private final DataOfferPatchBuilder dataOfferPatchBuilder; - private final DataOfferPatchApplier dataOfferPatchApplier; - - /** - * Updates a connector's data offers with given {@link FetchedDataOffer}s. - * - * @param dsl dsl - * @param connectorEndpoint connector endpoint - * @param fetchedDataOffers fetched data offers - * @param changes change tracker for log message - */ - @SneakyThrows - public void updateDataOffers(DSLContext dsl, String connectorEndpoint, Collection fetchedDataOffers, ConnectorChangeTracker changes) { - var patch = dataOfferPatchBuilder.buildDataOfferPatch(dsl, connectorEndpoint, fetchedDataOffers); - changes.setNumOffersAdded(patch.getDataOffersToInsert().size()); - changes.setNumOffersUpdated(patch.getDataOffersToUpdate().size()); - changes.setNumOffersDeleted(patch.getDataOffersToDelete().size()); - dataOfferPatchApplier.writeDataOfferPatch(dsl, patch); - } -} diff --git a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/refreshing/offers/FetchedCatalogBuilder.java b/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/refreshing/offers/FetchedCatalogBuilder.java deleted file mode 100644 index 64d850281..000000000 --- a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/refreshing/offers/FetchedCatalogBuilder.java +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright (c) 2023 sovity GmbH - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - * - * Contributors: - * sovity GmbH - initial API and implementation - * - */ - -package de.sovity.edc.ext.brokerserver.services.refreshing.offers; - -import de.sovity.edc.ext.brokerserver.services.refreshing.offers.model.FetchedCatalog; -import de.sovity.edc.ext.brokerserver.services.refreshing.offers.model.FetchedContractOffer; -import de.sovity.edc.ext.brokerserver.services.refreshing.offers.model.FetchedDataOffer; -import de.sovity.edc.ext.wrapper.api.common.mappers.AssetMapper; -import de.sovity.edc.utils.JsonUtils; -import de.sovity.edc.utils.catalog.model.DspCatalog; -import de.sovity.edc.utils.catalog.model.DspContractOffer; -import de.sovity.edc.utils.catalog.model.DspDataOffer; -import jakarta.json.JsonObject; -import lombok.RequiredArgsConstructor; -import org.jetbrains.annotations.NotNull; - -import java.util.List; - -@RequiredArgsConstructor -public class FetchedCatalogBuilder { - private final AssetMapper assetMapper; - - public FetchedCatalog buildFetchedCatalog(DspCatalog catalog) { - var participantId = catalog.getParticipantId(); - - var fetchedDataOffers = catalog.getDataOffers().stream() - .map(dspDataOffer -> buildFetchedDataOffer(dspDataOffer, participantId)) - .toList(); - - var fetchedCatalog = new FetchedCatalog(); - fetchedCatalog.setParticipantId(participantId); - fetchedCatalog.setDataOffers(fetchedDataOffers); - - return fetchedCatalog; - } - - @NotNull - private FetchedDataOffer buildFetchedDataOffer(DspDataOffer dspDataOffer, String participantId) { - var assetJsonLd = assetMapper.buildAssetJsonLdFromDatasetProperties(dspDataOffer.getAssetPropertiesJsonLd()); - - var fetchedDataOffer = new FetchedDataOffer(); - setAssetMetadata(fetchedDataOffer, assetJsonLd, participantId); - fetchedDataOffer.setContractOffers(buildFetchedContractOffers(dspDataOffer.getContractOffers())); - return fetchedDataOffer; - } - - @NotNull - private List buildFetchedContractOffers(List offers) { - return offers.stream() - .map(this::buildFetchedContractOffer) - .toList(); - } - - @NotNull - private FetchedContractOffer buildFetchedContractOffer(DspContractOffer offer) { - var contractOffer = new FetchedContractOffer(); - contractOffer.setContractOfferId(offer.getContractOfferId()); - contractOffer.setPolicyJson(JsonUtils.toJson(offer.getPolicyJsonLd())); - return contractOffer; - } - - /** - * This method was extract so tests could re-use the logic of assetJsonLd -> fetchedDataOffer -> dataOfferRecord - * - * @param fetchedDataOffer fetchedDataOffer - * @param assetJsonLd assetJsonLd - */ - public void setAssetMetadata(FetchedDataOffer fetchedDataOffer, JsonObject assetJsonLd, String participantId) { - var uiAsset = assetMapper.buildUiAsset(assetJsonLd, "http://if-you-see-this-this-is-a-bug", participantId); - fetchedDataOffer.setAssetId(uiAsset.getAssetId()); - fetchedDataOffer.setAssetJsonLd(JsonUtils.toJson(assetJsonLd)); - - // Most of these fields are extracted so our DB does not need to - // semantically interpret JSON-LD when sorting, searching and filtering - fetchedDataOffer.setAssetTitle(uiAsset.getTitle()); - fetchedDataOffer.setDescription(uiAsset.getDescription()); - fetchedDataOffer.setCuratorOrganizationName(uiAsset.getCreatorOrganizationName()); - - fetchedDataOffer.setDataCategory(uiAsset.getDataCategory()); - fetchedDataOffer.setDataSubcategory(uiAsset.getDataSubcategory()); - fetchedDataOffer.setDataModel(uiAsset.getDataModel()); - fetchedDataOffer.setGeoReferenceMethod(uiAsset.getGeoReferenceMethod()); - fetchedDataOffer.setTransportMode(uiAsset.getTransportMode()); - fetchedDataOffer.setKeywords(uiAsset.getKeywords()); - } -} diff --git a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/refreshing/offers/model/DataOfferPatch.java b/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/refreshing/offers/model/DataOfferPatch.java deleted file mode 100644 index a7a2b49bd..000000000 --- a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/refreshing/offers/model/DataOfferPatch.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (c) 2023 sovity GmbH - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - * - * Contributors: - * sovity GmbH - initial API and implementation - * - */ - -package de.sovity.edc.ext.brokerserver.services.refreshing.offers.model; - -import de.sovity.edc.ext.brokerserver.db.jooq.tables.records.ContractOfferRecord; -import de.sovity.edc.ext.brokerserver.db.jooq.tables.records.DataOfferRecord; -import lombok.AccessLevel; -import lombok.Getter; -import lombok.Setter; -import lombok.experimental.FieldDefaults; - -import java.util.ArrayList; -import java.util.List; - -/** - * Contains planned DB Row changes to be applied as batch. - */ -@Getter -@Setter -@FieldDefaults(level = AccessLevel.PRIVATE) -public class DataOfferPatch { - List dataOffersToInsert = new ArrayList<>(); - List dataOffersToUpdate = new ArrayList<>(); - List dataOffersToDelete = new ArrayList<>(); - - List contractOffersToInsert = new ArrayList<>(); - List contractOffersToUpdate = new ArrayList<>(); - List contractOffersToDelete = new ArrayList<>(); - - public void insertDataOffer(DataOfferRecord offer) { - dataOffersToInsert.add(offer); - } - - public void updateDataOffer(DataOfferRecord offer) { - dataOffersToUpdate.add(offer); - } - - public void deleteDataOffer(DataOfferRecord offer) { - dataOffersToDelete.add(offer); - } - - public void insertContractOffer(ContractOfferRecord offer) { - contractOffersToInsert.add(offer); - } - - public void updateContractOffer(ContractOfferRecord offer) { - contractOffersToUpdate.add(offer); - } - - public void deleteContractOffer(ContractOfferRecord offer) { - contractOffersToDelete.add(offer); - } -} diff --git a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/utils/MdsIdUtils.java b/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/utils/MdsIdUtils.java deleted file mode 100644 index a832e20b6..000000000 --- a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/utils/MdsIdUtils.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (c) 2023 sovity GmbH - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - * - * Contributors: - * sovity GmbH - initial API and implementation - * - */ - -package de.sovity.edc.ext.brokerserver.utils; - -import lombok.AccessLevel; -import lombok.NoArgsConstructor; - -@NoArgsConstructor(access = AccessLevel.PRIVATE) -public class MdsIdUtils { - public static String getMdsIdFromParticipantId(String participantId) { - if (participantId == null || !participantId.matches("^MDSL[A-Za-z0-9]+\\.C[A-Za-z0-9]+")) { - return null; - } - - return participantId.split("\\.")[0]; - } - - public static Boolean isValidMdsId(String mdsId) { - return mdsId != null && mdsId.matches("^MDSL[A-Za-z0-9]+"); - } -} diff --git a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/utils/StreamUtils2.java b/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/utils/StreamUtils2.java deleted file mode 100644 index 8a5701286..000000000 --- a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/utils/StreamUtils2.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (c) 2023 sovity GmbH - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - * - * Contributors: - * sovity GmbH - initial API and implementation - * - */ - -package de.sovity.edc.ext.brokerserver.utils; - -import lombok.AccessLevel; -import lombok.NoArgsConstructor; - -import java.util.HashSet; -import java.util.function.Function; -import java.util.function.Predicate; - -@NoArgsConstructor(access = AccessLevel.PRIVATE) -public class StreamUtils2 { - - /** - * Returns a predicate that filters out all elements that have the same key as a previous element. - * - * @param keyFn key extractor - * @param item type - * @param key type - * @return predicate to be used in {@link java.util.stream.Stream#filter(Predicate)} - */ - public static Predicate distinctByKey(Function keyFn) { - var keys = new HashSet<>(); - return t -> keys.add(keyFn.apply(t)); - } -} diff --git a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/utils/UrlUtils.java b/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/utils/UrlUtils.java deleted file mode 100644 index ae720063b..000000000 --- a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/utils/UrlUtils.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (c) 2023 sovity GmbH - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - * - * Contributors: - * sovity GmbH - initial API and implementation - * - */ - -package de.sovity.edc.ext.brokerserver.utils; - -import lombok.AccessLevel; -import lombok.NoArgsConstructor; - -import java.net.MalformedURLException; -import java.net.URISyntaxException; -import java.net.URL; - -@NoArgsConstructor(access = AccessLevel.PRIVATE) -public class UrlUtils { - - public static boolean isValidUrl(String url) { - try { - new URL(url).toURI(); - return true; - } catch (MalformedURLException | URISyntaxException e) { - return false; - } - } -} diff --git a/extensions/broker-server/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension b/extensions/broker-server/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension deleted file mode 100644 index 80d56e9c3..000000000 --- a/extensions/broker-server/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension +++ /dev/null @@ -1 +0,0 @@ -de.sovity.edc.ext.brokerserver.BrokerServerExtension diff --git a/extensions/broker-server/src/test/java/de/sovity/edc/ext/brokerserver/TestAsset.java b/extensions/broker-server/src/test/java/de/sovity/edc/ext/brokerserver/TestAsset.java deleted file mode 100644 index 5680a20c1..000000000 --- a/extensions/broker-server/src/test/java/de/sovity/edc/ext/brokerserver/TestAsset.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright (c) 2023 sovity GmbH - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - * - * Contributors: - * sovity GmbH - initial API and implementation - * - */ - -package de.sovity.edc.ext.brokerserver; - -import de.sovity.edc.ext.brokerserver.db.jooq.tables.records.DataOfferRecord; -import de.sovity.edc.ext.brokerserver.services.refreshing.offers.model.FetchedDataOffer; -import de.sovity.edc.ext.wrapper.api.common.mappers.asset.AssetEditRequestMapper; -import de.sovity.edc.ext.wrapper.api.common.mappers.asset.AssetJsonLdBuilder; -import de.sovity.edc.ext.wrapper.api.common.mappers.asset.AssetJsonLdParser; -import de.sovity.edc.ext.wrapper.api.common.mappers.asset.utils.AssetJsonLdUtils; -import de.sovity.edc.ext.wrapper.api.common.mappers.asset.utils.EdcPropertyUtils; -import de.sovity.edc.ext.wrapper.api.common.mappers.asset.utils.ShortDescriptionBuilder; -import de.sovity.edc.ext.wrapper.api.common.mappers.dataaddress.DataSourceMapper; -import de.sovity.edc.ext.wrapper.api.common.mappers.dataaddress.http.HttpDataSourceMapper; -import de.sovity.edc.ext.wrapper.api.common.mappers.dataaddress.http.HttpHeaderMapper; -import de.sovity.edc.ext.wrapper.api.common.model.DataSourceType; -import de.sovity.edc.ext.wrapper.api.common.model.UiAssetCreateRequest; -import de.sovity.edc.ext.wrapper.api.common.model.UiDataSource; -import de.sovity.edc.ext.wrapper.api.common.model.UiDataSourceHttpData; -import jakarta.json.JsonObject; -import lombok.AccessLevel; -import lombok.NoArgsConstructor; -import org.jetbrains.annotations.NotNull; - -@NoArgsConstructor(access = AccessLevel.PRIVATE) -public class TestAsset { - - public static JsonObject getAssetJsonLd(String assetId) { - return getAssetJsonLd( - UiAssetCreateRequest.builder() - .id(assetId) - .build() - ); - } - - public static JsonObject getAssetJsonLd(UiAssetCreateRequest request) { - var dataSource = UiDataSource.builder() - .type(DataSourceType.HTTP_DATA) - .httpData(UiDataSourceHttpData.builder() - .baseUrl("https://example.com") - .build()) - .build(); - var withDataSource = request.toBuilder().dataSource(dataSource).build(); - return buildAssetJsonLdBuilder().createAssetJsonLd(withDataSource, "orgName"); - } - - /** - * Sets assetJsonLd and other extracted fields. - *

- * This method keeps our tests consistent if we change the extracted fields. - * - * @param dataOfferRecord data offer record to be updated - * @param assetJsonLd asset json ld - * @param participantId required because the organization name will default to the participant id if unset - */ - public static void setDataOfferAssetMetadata(DataOfferRecord dataOfferRecord, JsonObject assetJsonLd, String participantId) { - // We trickily use the real code to update all the extracted values from the asset JSON-LD - var fetchedCatalogBuilder = BrokerServerExtensionContext.instance.fetchedCatalogBuilder(); - var dataOfferRecordUpdater = BrokerServerExtensionContext.instance.dataOfferRecordUpdater(); - - var fetchedDataOffer = new FetchedDataOffer(); - fetchedCatalogBuilder.setAssetMetadata(fetchedDataOffer, assetJsonLd, participantId); - - dataOfferRecord.setAssetId(fetchedDataOffer.getAssetId()); - dataOfferRecordUpdater.updateDataOffer(dataOfferRecord, fetchedDataOffer, false); - } - - public static AssetJsonLdBuilder buildAssetJsonLdBuilder() { - return new AssetJsonLdBuilder( - new DataSourceMapper( - new EdcPropertyUtils(), - new HttpDataSourceMapper(new HttpHeaderMapper()) - ), - buildAssetJsonLdParser(), - new AssetEditRequestMapper() - ); - } - - @NotNull - private static AssetJsonLdParser buildAssetJsonLdParser() { - return new AssetJsonLdParser( - new AssetJsonLdUtils(), - new ShortDescriptionBuilder(), - "https://my-connector"::equals - ); - } -} diff --git a/extensions/broker-server/src/test/java/de/sovity/edc/ext/brokerserver/TestPolicy.java b/extensions/broker-server/src/test/java/de/sovity/edc/ext/brokerserver/TestPolicy.java deleted file mode 100644 index 3087968d9..000000000 --- a/extensions/broker-server/src/test/java/de/sovity/edc/ext/brokerserver/TestPolicy.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (c) 2023 sovity GmbH - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - * - * Contributors: - * sovity GmbH - initial API and implementation - * - */ - -package de.sovity.edc.ext.brokerserver; - -import de.sovity.edc.ext.brokerserver.client.gen.JSON; -import de.sovity.edc.ext.wrapper.api.common.model.OperatorDto; -import de.sovity.edc.ext.wrapper.api.common.model.UiPolicyConstraint; -import de.sovity.edc.ext.wrapper.api.common.model.UiPolicyCreateRequest; -import de.sovity.edc.ext.wrapper.api.common.model.UiPolicyLiteral; -import de.sovity.edc.ext.wrapper.api.common.model.UiPolicyLiteralType; -import de.sovity.edc.utils.JsonUtils; -import org.jooq.JSONB; - -import java.time.OffsetDateTime; -import java.util.List; - -public class TestPolicy { - private static OffsetDateTime today = OffsetDateTime.now(); - - public static UiPolicyConstraint createAfterYesterdayConstraint() { - return UiPolicyConstraint.builder() - .left("POLICY_EVALUATION_TIME") - .operator(OperatorDto.GT) - .right(UiPolicyLiteral.builder() - .type(UiPolicyLiteralType.STRING) - .value(today.minusDays(1).toString()) - .build()) - .build(); - } - - public static de.sovity.edc.client.gen.model.UiPolicyCreateRequest createAfterYesterdayPolicyEdcGen() { - return jsonCast(createAfterYesterdayPolicy(), de.sovity.edc.client.gen.model.UiPolicyCreateRequest.class); - } - - private static R jsonCast(T obj, Class clazz) { - return JSON.deserialize(JSON.serialize(obj), clazz); - } - - public static UiPolicyCreateRequest createAfterYesterdayPolicy() { - return UiPolicyCreateRequest.builder() - .constraints(List.of(createAfterYesterdayConstraint())) - .build(); - } - - public static JSONB createAfterYesterdayPolicyJson() { - var createRequest = TestPolicy.createAfterYesterdayPolicy(); - return getPolicyJsonLd(createRequest); - } - - /** - * This method only works in integration tests, because it depends on the broker server extension context. - */ - public static JSONB getPolicyJsonLd(UiPolicyCreateRequest createRequest) { - var policyMapper = BrokerServerExtensionContext.instance.policyMapper(); - var jsonLd = policyMapper.buildPolicyJsonLd(policyMapper.buildPolicy(createRequest)); - return JSONB.jsonb(JsonUtils.toJson(jsonLd)); - } -} diff --git a/extensions/broker-server/src/test/java/de/sovity/edc/ext/brokerserver/TestUtils.java b/extensions/broker-server/src/test/java/de/sovity/edc/ext/brokerserver/TestUtils.java deleted file mode 100644 index 54a2218d9..000000000 --- a/extensions/broker-server/src/test/java/de/sovity/edc/ext/brokerserver/TestUtils.java +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Copyright (c) 2023 sovity GmbH - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - * - * Contributors: - * sovity GmbH - initial API and implementation - * - */ - -package de.sovity.edc.ext.brokerserver; - -import de.sovity.edc.ext.brokerserver.client.BrokerServerClient; -import de.sovity.edc.ext.brokerserver.client.gen.ApiException; -import de.sovity.edc.ext.brokerserver.db.PostgresFlywayExtension; -import de.sovity.edc.ext.brokerserver.db.TestDatabase; -import org.assertj.core.api.ThrowableAssert; -import org.jetbrains.annotations.NotNull; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static org.eclipse.edc.junit.testfixtures.TestUtils.getFreePort; - -public class TestUtils { - private static final int MANAGEMENT_PORT = getFreePort(); - private static final int PROTOCOL_PORT = getFreePort(); - private static final String MANAGEMENT_PATH = "/api/management"; - private static final String PROTOCOL_PATH = "/api/dsp"; - public static final String MANAGEMENT_API_KEY = "123456"; - public static final String MANAGEMENT_ENDPOINT = "http://localhost:" + MANAGEMENT_PORT + MANAGEMENT_PATH; - public static final String ADMIN_API_KEY = "123456"; - - - public static final String PROTOCOL_HOST = "http://localhost:" + PROTOCOL_PORT; - public static final String PROTOCOL_ENDPOINT = PROTOCOL_HOST + PROTOCOL_PATH; - public static final String PARTICIPANT_ID = "MDSL1234ZZ.C4321AA"; - public static final String CURATOR_NAME = "My Org"; - - @NotNull - public static Map createConfiguration( - TestDatabase testDatabase, - Map additionalConfigProperties - ) { - Map config = new HashMap<>(); - - config.put("web.http.port", String.valueOf(getFreePort())); - config.put("web.http.path", "/api"); - config.put("web.http.management.port", String.valueOf(MANAGEMENT_PORT)); - config.put("web.http.management.path", MANAGEMENT_PATH); - config.put("web.http.protocol.port", String.valueOf(PROTOCOL_PORT)); - config.put("web.http.protocol.path", PROTOCOL_PATH); - config.put("edc.api.auth.key", MANAGEMENT_API_KEY); - config.put("edc.dsp.callback.address", PROTOCOL_ENDPOINT); - config.put("edc.oauth.provider.audience", "idsc:IDS_CONNECTORS_ALL"); - - config.put("edc.participant.id", PARTICIPANT_ID); - config.put("my.edc.participant.id", PARTICIPANT_ID); - config.put("my.edc.title", "My Connector"); - config.put("my.edc.description", "My Connector Description"); - config.put("my.edc.curator.url", "https://connector.my-org"); - config.put("my.edc.curator.name", CURATOR_NAME); - config.put("my.edc.maintainer.url", "https://maintainer-org"); - config.put("my.edc.maintainer.name", "Maintainer Org"); - - config.put(PostgresFlywayExtension.JDBC_URL, testDatabase.getJdbcUrl()); - config.put(PostgresFlywayExtension.JDBC_USER, testDatabase.getJdbcUser()); - config.put(PostgresFlywayExtension.JDBC_PASSWORD, testDatabase.getJdbcPassword()); - config.put(PostgresFlywayExtension.DB_CONNECTION_POOL_SIZE, "20"); - config.put(PostgresFlywayExtension.DB_CONNECTION_TIMEOUT_IN_MS, "3000"); - config.put(PostgresFlywayExtension.FLYWAY_CLEAN_ENABLE, "true"); - config.put(PostgresFlywayExtension.FLYWAY_CLEAN, "true"); - config.put(BrokerServerExtension.NUM_THREADS, "0"); - config.put(BrokerServerExtension.ADMIN_API_KEY, ADMIN_API_KEY); - config.putAll(getCoreEdcJdbcConfig(testDatabase)); - config.putAll(additionalConfigProperties); - return config; - } - - private static Map getCoreEdcJdbcConfig(TestDatabase testDatabase) { - Map config = new HashMap<>(); - List.of("asset", - "contractdefinition", - "contractnegotiation", - "policy", - "transferprocess", - "dataplaneinstance" - ).forEach(it -> { - config.put("edc.datasource.%s.name".formatted(it), it); - config.put("edc.datasource.%s.url".formatted(it), testDatabase.getJdbcUrl()); - config.put("edc.datasource.%s.user".formatted(it), testDatabase.getJdbcUser()); - config.put("edc.datasource.%s.password".formatted(it), testDatabase.getJdbcPassword()); - }); - return config; - } - - public static BrokerServerClient brokerServerClient() { - return BrokerServerClient.builder() - .managementApiUrl(TestUtils.MANAGEMENT_ENDPOINT) - .managementApiKey(TestUtils.MANAGEMENT_API_KEY) - .build(); - } - - - public static void assertIs401(ThrowableAssert.ThrowingCallable callable) { - assertThatThrownBy(callable) - .isInstanceOf(ApiException.class) - .satisfies(ex -> { - var apiException = (ApiException) ex; - assertThat(apiException.getCode()).isEqualTo(401); - }); - } -} diff --git a/extensions/broker-server/src/test/java/de/sovity/edc/ext/brokerserver/dao/utils/LikeUtilsTest.java b/extensions/broker-server/src/test/java/de/sovity/edc/ext/brokerserver/dao/utils/LikeUtilsTest.java deleted file mode 100644 index 13fe324ec..000000000 --- a/extensions/broker-server/src/test/java/de/sovity/edc/ext/brokerserver/dao/utils/LikeUtilsTest.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (c) 2023 sovity GmbH - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - * - * Contributors: - * sovity GmbH - initial API and implementation - * - */ - -package de.sovity.edc.ext.brokerserver.dao.utils; - -import org.junit.jupiter.api.Test; - -import static org.assertj.core.api.Assertions.assertThat; - -class LikeUtilsTest { - @Test - void escape() { - assertThat(LikeUtils.escape("a\\b_c%d")).isEqualTo("a\\\\b\\_c\\%d"); - } -} diff --git a/extensions/broker-server/src/test/java/de/sovity/edc/ext/brokerserver/db/FlywayTestUtils.java b/extensions/broker-server/src/test/java/de/sovity/edc/ext/brokerserver/db/FlywayTestUtils.java deleted file mode 100644 index 059f81474..000000000 --- a/extensions/broker-server/src/test/java/de/sovity/edc/ext/brokerserver/db/FlywayTestUtils.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (c) 2023 sovity GmbH - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - * - * Contributors: - * sovity GmbH - initial implementation - * - */ - -package de.sovity.edc.ext.brokerserver.db; - -import lombok.AccessLevel; -import lombok.NoArgsConstructor; -import org.eclipse.edc.spi.monitor.ConsoleMonitor; -import org.eclipse.edc.spi.system.configuration.Config; - -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -@NoArgsConstructor(access = AccessLevel.PRIVATE) -public class FlywayTestUtils { - - public static void migrate(TestDatabase testDatabase) { - var monitor = new ConsoleMonitor(); - var config = mock(Config.class); - when(config.getBoolean(eq(PostgresFlywayExtension.FLYWAY_CLEAN_ENABLE), any())).thenReturn(true); - when(config.getBoolean(eq(PostgresFlywayExtension.FLYWAY_CLEAN), any())).thenReturn(true); - - var flywayFactory = new FlywayFactory(config); - var dataSource = testDatabase.getDataSource(); - var flyway = flywayFactory.setupFlyway(dataSource); - var flywayMigrator = new FlywayMigrator(flyway, config, monitor); - flywayMigrator.migrateAndRepair(); - } -} diff --git a/extensions/broker-server/src/test/java/de/sovity/edc/ext/brokerserver/db/TestDatabase.java b/extensions/broker-server/src/test/java/de/sovity/edc/ext/brokerserver/db/TestDatabase.java deleted file mode 100644 index e593df41c..000000000 --- a/extensions/broker-server/src/test/java/de/sovity/edc/ext/brokerserver/db/TestDatabase.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (c) 2023 sovity GmbH - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - * - * Contributors: - * sovity GmbH - initial implementation - * - */ - -package de.sovity.edc.ext.brokerserver.db; - -import de.sovity.edc.ext.brokerserver.db.utils.JdbcCredentials; -import org.jooq.DSLContext; -import org.junit.jupiter.api.extension.AfterAllCallback; -import org.junit.jupiter.api.extension.BeforeAllCallback; - -import javax.sql.DataSource; -import java.util.function.Consumer; - -public interface TestDatabase extends BeforeAllCallback, AfterAllCallback { - String getJdbcUrl(); - - String getJdbcUser(); - - String getJdbcPassword(); - - /** - * New {@link DslContextFactory} from the test database's credentials - * - * @return {@link DslContextFactory} - */ - default DslContextFactory getDslContextFactory() { - var dataSource = getDataSource(); - return new DslContextFactory(dataSource); - } - - /** - * Returns a {@link DataSource} to the test database - * - * @return {@link DataSource} - */ - default DataSource getDataSource() { - var jdbcCredentials = new JdbcCredentials(getJdbcUrl(), getJdbcUser(), getJdbcPassword()); - return DataSourceFactory.newDataSource(jdbcCredentials, 20, 30_000); - } - - /** - * Runs given code within a test transaction. - *
- * Globally hijacks all {@link DslContextFactory}s to use this test transaction. - * - * @param code code to run within the test transaction - */ - default void testTransaction(Consumer code) { - try { - getDslContextFactory().transaction(dsl -> DslContextFactoryHijacker.withParentDslContext(dsl, () -> { - code.accept(dsl); - throw new TestDatabaseCancelTransactionException(); - })); - } catch (TestDatabaseCancelTransactionException e) { - // Ignore - } - } -} diff --git a/extensions/broker-server/src/test/java/de/sovity/edc/ext/brokerserver/db/TestDatabaseFactory.java b/extensions/broker-server/src/test/java/de/sovity/edc/ext/brokerserver/db/TestDatabaseFactory.java deleted file mode 100644 index cc272fcb8..000000000 --- a/extensions/broker-server/src/test/java/de/sovity/edc/ext/brokerserver/db/TestDatabaseFactory.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (c) 2023 sovity GmbH - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - * - * Contributors: - * sovity GmbH - initial implementation - * - */ - -package de.sovity.edc.ext.brokerserver.db; - -import lombok.AccessLevel; -import lombok.NoArgsConstructor; - -@NoArgsConstructor(access = AccessLevel.PRIVATE) -public class TestDatabaseFactory { - - /** - * Returns a JUnit 5 Extension that launches a testcontainer. - * - * @return {@link TestDatabase} - */ - public static TestDatabase getTestDatabase() { - return new TestDatabaseViaTestcontainers(); - } -} diff --git a/extensions/broker-server/src/test/java/de/sovity/edc/ext/brokerserver/db/TestDatabaseViaEnv.java b/extensions/broker-server/src/test/java/de/sovity/edc/ext/brokerserver/db/TestDatabaseViaEnv.java deleted file mode 100644 index ad2a5c5f9..000000000 --- a/extensions/broker-server/src/test/java/de/sovity/edc/ext/brokerserver/db/TestDatabaseViaEnv.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (c) 2023 sovity GmbH - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - * - * Contributors: - * sovity GmbH - initial implementation - * - */ - -package de.sovity.edc.ext.brokerserver.db; - -import org.apache.commons.lang3.Validate; -import org.junit.jupiter.api.extension.ExtensionContext; - -public class TestDatabaseViaEnv implements TestDatabase { - public static final String SKIP_TESTCONTAINERS = "SKIP_TESTCONTAINERS"; - public static final String TEST_POSTGRES_JDBC_URL = "TEST_POSTGRES_JDBC_URL"; - public static final String TEST_POSTGRES_JDBC_USER = "TEST_POSTGRES_JDBC_USER"; - public static final String TEST_POSTGRES_JDBC_PASSWORD = "TEST_POSTGRES_JDBC_PASSWORD"; - - @Override - public void afterAll(ExtensionContext context) throws Exception { - - } - - @Override - public void beforeAll(ExtensionContext context) throws Exception { - - } - - public String getJdbcUrl() { - return getRequiredEnv(TEST_POSTGRES_JDBC_URL); - } - - public String getJdbcUser() { - return getRequiredEnv(TEST_POSTGRES_JDBC_USER); - } - - public String getJdbcPassword() { - return getRequiredEnv(TEST_POSTGRES_JDBC_PASSWORD); - } - - private static String getRequiredEnv(String name) { - String value = System.getenv(name); - Validate.notBlank(value, "Need env var %s since %s is true", name, SKIP_TESTCONTAINERS); - return value; - } - - public static boolean isSkipTestcontainers() { - return "true".equals(System.getenv(SKIP_TESTCONTAINERS)); - } -} diff --git a/extensions/broker-server/src/test/java/de/sovity/edc/ext/brokerserver/db/TestDatabaseViaTestcontainers.java b/extensions/broker-server/src/test/java/de/sovity/edc/ext/brokerserver/db/TestDatabaseViaTestcontainers.java deleted file mode 100644 index fd3d1caf0..000000000 --- a/extensions/broker-server/src/test/java/de/sovity/edc/ext/brokerserver/db/TestDatabaseViaTestcontainers.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (c) 2023 sovity GmbH - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - * - * Contributors: - * sovity GmbH - initial implementation - * - */ - -package de.sovity.edc.ext.brokerserver.db; - -import de.sovity.edc.utils.versions.GradleVersions; -import org.junit.jupiter.api.extension.ExtensionContext; -import org.testcontainers.containers.PostgreSQLContainer; - -public class TestDatabaseViaTestcontainers implements TestDatabase { - private PostgreSQLContainer container = new PostgreSQLContainer<>(GradleVersions.POSTGRES_IMAGE_TAG) - .withUsername("edc") - .withPassword("edc"); - - @Override - public void afterAll(ExtensionContext context) throws Exception { - container.stop(); - } - - @Override - public void beforeAll(ExtensionContext context) throws Exception { - container.start(); - } - - public String getJdbcUrl() { - return container.getJdbcUrl(); - } - - public String getJdbcUser() { - return container.getUsername(); - } - - public String getJdbcPassword() { - return container.getPassword(); - } -} diff --git a/extensions/broker-server/src/test/java/de/sovity/edc/ext/brokerserver/services/api/AddConnectorsApiTest.java b/extensions/broker-server/src/test/java/de/sovity/edc/ext/brokerserver/services/api/AddConnectorsApiTest.java deleted file mode 100644 index 058882217..000000000 --- a/extensions/broker-server/src/test/java/de/sovity/edc/ext/brokerserver/services/api/AddConnectorsApiTest.java +++ /dev/null @@ -1,163 +0,0 @@ -/* - * Copyright (c) 2023 sovity GmbH - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - * - * Contributors: - * sovity GmbH - initial implementation - * - */ - -package de.sovity.edc.ext.brokerserver.services.api; - -import de.sovity.edc.ext.brokerserver.TestUtils; -import de.sovity.edc.ext.brokerserver.client.BrokerServerClient; -import de.sovity.edc.ext.brokerserver.client.gen.model.AddedConnector; -import de.sovity.edc.ext.brokerserver.client.gen.model.ConnectorCreationRequest; -import de.sovity.edc.ext.brokerserver.client.gen.model.ConnectorListEntry; -import de.sovity.edc.ext.brokerserver.client.gen.model.ConnectorPageQuery; -import de.sovity.edc.ext.brokerserver.db.TestDatabase; -import de.sovity.edc.ext.brokerserver.db.TestDatabaseFactory; -import org.eclipse.edc.junit.annotations.ApiTest; -import org.eclipse.edc.junit.extensions.EdcExtension; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.junit.jupiter.api.extension.RegisterExtension; - -import java.util.Arrays; -import java.util.List; -import java.util.Map; - -import static de.sovity.edc.ext.brokerserver.TestUtils.ADMIN_API_KEY; -import static de.sovity.edc.ext.brokerserver.TestUtils.brokerServerClient; -import static de.sovity.edc.ext.brokerserver.TestUtils.createConfiguration; -import static org.assertj.core.api.Assertions.assertThat; - -@ApiTest -@ExtendWith(EdcExtension.class) -class AddConnectorsApiTest { - BrokerServerClient client; - - @RegisterExtension - private static final TestDatabase TEST_DATABASE = TestDatabaseFactory.getTestDatabase(); - - @BeforeEach - void setUp(EdcExtension extension) { - extension.setConfiguration(createConfiguration(TEST_DATABASE, Map.of())); - client = brokerServerClient(); - } - - @Test - void testAddConnectors() { - TEST_DATABASE.testTransaction(dsl -> { - client.brokerServerApi().addConnectors(ADMIN_API_KEY, List.of()); - - client.brokerServerApi().addConnectors(ADMIN_API_KEY, Arrays.asList( - null, - "", - " ", - "\t", - "http://a", - "http://b" - )); - - assertThat(client.brokerServerApi().connectorPage(new ConnectorPageQuery()).getConnectors()) - .extracting(ConnectorListEntry::getEndpoint) - .containsExactlyInAnyOrder("http://a", "http://b"); - - client.brokerServerApi().addConnectors(ADMIN_API_KEY, Arrays.asList( - "http://b", - " http://b\r\n", - "http://c" - )); - - assertThat(client.brokerServerApi().connectorPage(new ConnectorPageQuery()).getConnectors()) - .extracting(ConnectorListEntry::getEndpoint) - .containsExactlyInAnyOrder("http://a", "http://b", "http://c"); - }); - } - - @Test - void testAddConnectorsWithMdsIds() { - TEST_DATABASE.testTransaction(dsl -> { - client.brokerServerApi().addConnectorsWithMdsIds(ADMIN_API_KEY, new ConnectorCreationRequest(List.of())); - - client.brokerServerApi().addConnectorsWithMdsIds(ADMIN_API_KEY, new ConnectorCreationRequest(Arrays.asList( - new AddedConnector( - null, - "MDSL1234" - ), - new AddedConnector( - "", - "MDSL1234" - ), - new AddedConnector( - " ", - "MDSL1234" - ), - new AddedConnector( - "\t", - "MDSL1234" - ), - new AddedConnector( - "http://a", - "MDSL1234" - ), - new AddedConnector( - " http://b\r\n", - "MDSL1234" - ), - new AddedConnector( - "http://c", - null - ), - new AddedConnector( - "http://d", - "" - ), - new AddedConnector( - "http://e", - " " - ), - new AddedConnector( - "http://f", - "\t" - ) - ))); - - assertThat(client.brokerServerApi().connectorPage(new ConnectorPageQuery()).getConnectors()) - .extracting(ConnectorListEntry::getEndpoint) - .containsExactlyInAnyOrder("http://a", "http://b"); - - client.brokerServerApi().addConnectorsWithMdsIds(ADMIN_API_KEY, new ConnectorCreationRequest(Arrays.asList( - new AddedConnector( - "http://b", - "MDSL1234" - ), - new AddedConnector( - " http://b\r\n", - "MDSL1234" - ), - new AddedConnector( - "http://c", - "MDSL1234" - ) - ))); - - assertThat(client.brokerServerApi().connectorPage(new ConnectorPageQuery()).getConnectors()) - .extracting(ConnectorListEntry::getEndpoint) - .containsExactlyInAnyOrder("http://a", "http://b", "http://c"); - }); - } - - @Test - void testAddWrongApiKey() { - TEST_DATABASE.testTransaction(dsl -> TestUtils.assertIs401(() -> - client.brokerServerApi().addConnectors("wrong-api-key", List.of()))); - } -} diff --git a/extensions/broker-server/src/test/java/de/sovity/edc/ext/brokerserver/services/api/AuthorityPortalConnectorMetadataApiTest.java b/extensions/broker-server/src/test/java/de/sovity/edc/ext/brokerserver/services/api/AuthorityPortalConnectorMetadataApiTest.java deleted file mode 100644 index f8c230ab6..000000000 --- a/extensions/broker-server/src/test/java/de/sovity/edc/ext/brokerserver/services/api/AuthorityPortalConnectorMetadataApiTest.java +++ /dev/null @@ -1,149 +0,0 @@ -/* - * Copyright (c) 2023 sovity GmbH - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - * - * Contributors: - * sovity GmbH - initial API and implementation - * - */ - -package de.sovity.edc.ext.brokerserver.services.api; - -import de.sovity.edc.ext.brokerserver.TestPolicy; -import de.sovity.edc.ext.brokerserver.client.gen.model.AuthorityPortalConnectorInfo; -import de.sovity.edc.ext.brokerserver.db.TestDatabase; -import de.sovity.edc.ext.brokerserver.db.TestDatabaseFactory; -import de.sovity.edc.ext.brokerserver.db.jooq.Tables; -import de.sovity.edc.ext.brokerserver.db.jooq.enums.ConnectorContractOffersExceeded; -import de.sovity.edc.ext.brokerserver.db.jooq.enums.ConnectorDataOffersExceeded; -import de.sovity.edc.ext.brokerserver.db.jooq.enums.ConnectorOnlineStatus; -import org.eclipse.edc.junit.annotations.ApiTest; -import org.eclipse.edc.junit.extensions.EdcExtension; -import org.jooq.DSLContext; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.junit.jupiter.api.extension.RegisterExtension; - -import java.time.OffsetDateTime; -import java.util.Arrays; -import java.util.List; -import java.util.Map; - -import static de.sovity.edc.ext.brokerserver.TestAsset.getAssetJsonLd; -import static de.sovity.edc.ext.brokerserver.TestAsset.setDataOfferAssetMetadata; -import static de.sovity.edc.ext.brokerserver.TestUtils.ADMIN_API_KEY; -import static de.sovity.edc.ext.brokerserver.TestUtils.brokerServerClient; -import static de.sovity.edc.ext.brokerserver.TestUtils.createConfiguration; -import static org.assertj.core.api.Assertions.assertThat; - -@ApiTest -@ExtendWith(EdcExtension.class) -class AuthorityPortalConnectorMetadataApiTest { - - @RegisterExtension - private static final TestDatabase TEST_DATABASE = TestDatabaseFactory.getTestDatabase(); - - @BeforeEach - void setUp(EdcExtension extension) { - extension.setConfiguration(createConfiguration(TEST_DATABASE, Map.of())); - } - - @Test - void testConnectorMetadataByEndpoints() { - TEST_DATABASE.testTransaction(dsl -> { - // arrange - var now = OffsetDateTime.now().withNano(0); - - createConnector(dsl, now, 1); - createDataOffer(dsl, now, 1, 1); - createDataOffer(dsl, now, 1, 2); - - createConnector(dsl, now, 2); - createDataOffer(dsl, now, 2, 1); - - createConnector(dsl, now, 3); - createDataOffer(dsl, now, 3, 1); - - createConnector(dsl, now, 4); - - // act - var actual = brokerServerClient().brokerServerApi().getConnectorMetadata( - ADMIN_API_KEY, - Arrays.asList( - getEndpoint(1), - getEndpoint(1), // having this twice should not crash the query - getEndpoint(2), - getEndpoint(4), - getEndpoint(5) // having this not existing should not crash the query - )); - - // assert - var first = forConnector(actual, 1); - assertThat(first.getParticipantId()).isEqualTo("my-connector"); - assertThat(first.getDataOfferCount()).isEqualTo(2); - assertThat(first.getOnlineStatus()).isEqualTo(AuthorityPortalConnectorInfo.OnlineStatusEnum.ONLINE); - assertThat(first.getOfflineSinceOrLastUpdatedAt()).isEqualTo(now); - var second = forConnector(actual, 2); - assertThat(second.getDataOfferCount()).isEqualTo(1); - assertThat(second.getOnlineStatus()).isEqualTo(AuthorityPortalConnectorInfo.OnlineStatusEnum.ONLINE); - assertThat(second.getOfflineSinceOrLastUpdatedAt()).isEqualTo(now); - var fourth = forConnector(actual, 4); - assertThat(fourth.getDataOfferCount()).isEqualTo(0); - assertThat(fourth.getOnlineStatus()).isEqualTo(AuthorityPortalConnectorInfo.OnlineStatusEnum.ONLINE); - assertThat(fourth.getOfflineSinceOrLastUpdatedAt()).isEqualTo(now); - }); - } - - private AuthorityPortalConnectorInfo forConnector(List actual, int iConnector) { - return actual.stream() - .filter(connectorMetadata -> - getEndpoint(iConnector).equals(connectorMetadata.getConnectorEndpoint()) - ) - .findFirst() - .orElseThrow(); - } - - private void createConnector(DSLContext dsl, OffsetDateTime now, int iConnector) { - var connector = dsl.newRecord(Tables.CONNECTOR); - connector.setParticipantId("my-connector"); - connector.setEndpoint(getEndpoint(iConnector)); - connector.setOnlineStatus(ConnectorOnlineStatus.ONLINE); - connector.setCreatedAt(now.minusDays(1)); - connector.setLastRefreshAttemptAt(now); - connector.setLastSuccessfulRefreshAt(now); - connector.setDataOffersExceeded(ConnectorDataOffersExceeded.OK); - connector.setContractOffersExceeded(ConnectorContractOffersExceeded.OK); - connector.insert(); - } - - private String getEndpoint(int iConnector) { - return "https://connector-%d".formatted(iConnector); - } - - private void createDataOffer(DSLContext dsl, OffsetDateTime now, int iConnector, int iDataOffer) { - var connectorEndpoint = getEndpoint(iConnector); - var assetJsonLd = getAssetJsonLd("my-asset-%d".formatted(iDataOffer)); - - var dataOffer = dsl.newRecord(Tables.DATA_OFFER); - setDataOfferAssetMetadata(dataOffer, assetJsonLd, "my-participant-id"); - dataOffer.setConnectorEndpoint(connectorEndpoint); - dataOffer.setCreatedAt(now.minusDays(5)); - dataOffer.setUpdatedAt(now); - dataOffer.insert(); - - var contractOffer = dsl.newRecord(Tables.CONTRACT_OFFER); - contractOffer.setContractOfferId("my-contract-offer-1"); - contractOffer.setConnectorEndpoint(connectorEndpoint); - contractOffer.setAssetId(dataOffer.getAssetId()); - contractOffer.setCreatedAt(now.minusDays(5)); - contractOffer.setUpdatedAt(now); - contractOffer.setPolicy(TestPolicy.createAfterYesterdayPolicyJson()); - contractOffer.insert(); - } -} diff --git a/extensions/broker-server/src/test/java/de/sovity/edc/ext/brokerserver/services/api/AuthorityPortalDataOfferApiTest.java b/extensions/broker-server/src/test/java/de/sovity/edc/ext/brokerserver/services/api/AuthorityPortalDataOfferApiTest.java deleted file mode 100644 index 9cd29b55f..000000000 --- a/extensions/broker-server/src/test/java/de/sovity/edc/ext/brokerserver/services/api/AuthorityPortalDataOfferApiTest.java +++ /dev/null @@ -1,180 +0,0 @@ -/* - * Copyright (c) 2023 sovity GmbH - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - * - * Contributors: - * sovity GmbH - initial API and implementation - * - */ - -package de.sovity.edc.ext.brokerserver.services.api; - -import de.sovity.edc.ext.brokerserver.TestPolicy; -import de.sovity.edc.ext.brokerserver.client.gen.ApiException; -import de.sovity.edc.ext.brokerserver.client.gen.model.AuthorityPortalConnectorDataOfferInfo; -import de.sovity.edc.ext.brokerserver.client.gen.model.AuthorityPortalConnectorInfo; -import de.sovity.edc.ext.brokerserver.db.TestDatabase; -import de.sovity.edc.ext.brokerserver.db.TestDatabaseFactory; -import de.sovity.edc.ext.brokerserver.db.jooq.Tables; -import de.sovity.edc.ext.brokerserver.db.jooq.enums.ConnectorContractOffersExceeded; -import de.sovity.edc.ext.brokerserver.db.jooq.enums.ConnectorDataOffersExceeded; -import de.sovity.edc.ext.brokerserver.db.jooq.enums.ConnectorOnlineStatus; -import org.eclipse.edc.junit.annotations.ApiTest; -import org.eclipse.edc.junit.extensions.EdcExtension; -import org.jooq.DSLContext; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.junit.jupiter.api.extension.RegisterExtension; - -import java.time.OffsetDateTime; -import java.util.Arrays; -import java.util.List; -import java.util.Map; - -import static de.sovity.edc.ext.brokerserver.TestAsset.getAssetJsonLd; -import static de.sovity.edc.ext.brokerserver.TestAsset.setDataOfferAssetMetadata; -import static de.sovity.edc.ext.brokerserver.TestUtils.ADMIN_API_KEY; -import static de.sovity.edc.ext.brokerserver.TestUtils.brokerServerClient; -import static de.sovity.edc.ext.brokerserver.TestUtils.createConfiguration; -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.Assert.assertThrows; - -@ApiTest -@ExtendWith(EdcExtension.class) -class AuthorityPortalDataOfferApiTest { - - @RegisterExtension - private static final TestDatabase TEST_DATABASE = TestDatabaseFactory.getTestDatabase(); - - @BeforeEach - void setUp(EdcExtension extension) { - extension.setConfiguration(createConfiguration(TEST_DATABASE, Map.of())); - } - - @Test - void testAuthenticationOfEndpoints() { - TEST_DATABASE.testTransaction(dsl -> { - var code = assertThrows(ApiException.class, () -> brokerServerClient().brokerServerApi().getConnectorDataOffers( - ADMIN_API_KEY + "invalid", - List.of())).getCode(); - assertThat(code).isEqualTo(401); - }); - } - - @Test - void testConnectorMetadataByEndpoints() { - TEST_DATABASE.testTransaction(dsl -> { - // arrange - var now = OffsetDateTime.now().withNano(0); - - createConnector(dsl, now, 1); - createDataOffer(dsl, now, 1, 1); - createDataOffer(dsl, now, 1, 2); - - createConnector(dsl, now, 2); - createDataOffer(dsl, now, 2, 1); - - createConnector(dsl, now, 4); - - // act - var actual = brokerServerClient().brokerServerApi().getConnectorDataOffers( - ADMIN_API_KEY, - Arrays.asList( - getEndpoint(1), - getEndpoint(2), - getEndpoint(4) - )); - - // assert - // connector 1 with two data offer - var connector1 = forConnector(actual, 1); - assertThat(connector1.getConnectorEndpoint()).isEqualTo(getEndpoint(1)); - assertThat(connector1.getParticipantId()).isEqualTo("my-connector"); - assertThat(connector1.getOnlineStatus().getValue()).isEqualTo(AuthorityPortalConnectorInfo.OnlineStatusEnum.ONLINE.getValue()); - assertThat(connector1.getOfflineSinceOrLastUpdatedAt()).isEqualTo(now); - assertThat(connector1.getDataOffers().size()).isEqualTo(2); - var connector1asset1 = connector1.getDataOffers().stream().filter(dataOffer -> dataOffer.getDataOfferId().equals(getAssetId(1))).findFirst().orElseThrow(); - assertThat(connector1asset1.getDataOfferId()).isEqualTo("my-asset-1"); - assertThat(connector1asset1.getDataOfferName()).isEqualTo("my-asset-1"); - var connector1asset2 = connector1.getDataOffers().stream().filter(dataOffer -> dataOffer.getDataOfferId().equals(getAssetId(2))).findFirst().orElseThrow(); - assertThat(connector1asset2.getDataOfferId()).isEqualTo("my-asset-2"); - assertThat(connector1asset2.getDataOfferName()).isEqualTo("my-asset-2"); - - // connector 2 with one data offer - var connector2 = forConnector(actual, 2); - assertThat(connector2.getConnectorEndpoint()).isEqualTo(getEndpoint(2)); - assertThat(connector2.getParticipantId()).isEqualTo("my-connector"); - assertThat(connector2.getOnlineStatus().getValue()).isEqualTo(AuthorityPortalConnectorInfo.OnlineStatusEnum.ONLINE.getValue()); - assertThat(connector2.getOfflineSinceOrLastUpdatedAt()).isEqualTo(now); - assertThat(connector2.getDataOffers().size()).isEqualTo(1); - var connector2asset1 = connector2.getDataOffers().stream().filter(dataOffer -> dataOffer.getDataOfferId().equals(getAssetId(1))).findFirst().orElseThrow(); - assertThat(connector2asset1.getDataOfferId()).isEqualTo("my-asset-1"); - assertThat(connector2asset1.getDataOfferName()).isEqualTo("my-asset-1"); - - // connector 4 without data offers - var connector4 = forConnector(actual, 4); - assertThat(connector4.getConnectorEndpoint()).isEqualTo(getEndpoint(4)); - assertThat(connector4.getParticipantId()).isEqualTo("my-connector"); - assertThat(connector4.getOnlineStatus().getValue()).isEqualTo(AuthorityPortalConnectorInfo.OnlineStatusEnum.ONLINE.getValue()); - assertThat(connector4.getOfflineSinceOrLastUpdatedAt()).isEqualTo(now); - assertThat(connector4.getDataOffers().size()).isEqualTo(0); - }); - } - - private AuthorityPortalConnectorDataOfferInfo forConnector(List actual, int iConnector) { - return actual.stream() - .filter(connectorMetadata -> - getEndpoint(iConnector).equals(connectorMetadata.getConnectorEndpoint()) - ) - .findFirst() - .orElseThrow(); - } - - private void createConnector(DSLContext dsl, OffsetDateTime now, int iConnector) { - var connector = dsl.newRecord(Tables.CONNECTOR); - connector.setParticipantId("my-connector"); - connector.setEndpoint(getEndpoint(iConnector)); - connector.setOnlineStatus(ConnectorOnlineStatus.ONLINE); - connector.setCreatedAt(now.minusDays(1)); - connector.setLastRefreshAttemptAt(now); - connector.setLastSuccessfulRefreshAt(now); - connector.setDataOffersExceeded(ConnectorDataOffersExceeded.OK); - connector.setContractOffersExceeded(ConnectorContractOffersExceeded.OK); - connector.insert(); - } - - private String getEndpoint(int iConnector) { - return "https://connector-%d".formatted(iConnector); - } - - private String getAssetId(int iDataOffer) { - return "my-asset-%d".formatted(iDataOffer); - } - - private void createDataOffer(DSLContext dsl, OffsetDateTime now, int iConnector, int iDataOffer) { - var connectorEndpoint = getEndpoint(iConnector); - var assetJsonLd = getAssetJsonLd(getAssetId(iDataOffer)); - - var dataOffer = dsl.newRecord(Tables.DATA_OFFER); - setDataOfferAssetMetadata(dataOffer, assetJsonLd, "my-participant-id"); - dataOffer.setConnectorEndpoint(connectorEndpoint); - dataOffer.setCreatedAt(now.minusDays(5)); - dataOffer.setUpdatedAt(now); - dataOffer.insert(); - - var contractOffer = dsl.newRecord(Tables.CONTRACT_OFFER); - contractOffer.setContractOfferId("my-contract-offer-1"); - contractOffer.setConnectorEndpoint(connectorEndpoint); - contractOffer.setAssetId(dataOffer.getAssetId()); - contractOffer.setCreatedAt(now.minusDays(5)); - contractOffer.setUpdatedAt(now); - contractOffer.setPolicy(TestPolicy.createAfterYesterdayPolicyJson()); - contractOffer.insert(); - } -} diff --git a/extensions/broker-server/src/test/java/de/sovity/edc/ext/brokerserver/services/api/AuthorityPortalOrganizationMetadataApiTest.java b/extensions/broker-server/src/test/java/de/sovity/edc/ext/brokerserver/services/api/AuthorityPortalOrganizationMetadataApiTest.java deleted file mode 100644 index fa907770b..000000000 --- a/extensions/broker-server/src/test/java/de/sovity/edc/ext/brokerserver/services/api/AuthorityPortalOrganizationMetadataApiTest.java +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright (c) 2023 sovity GmbH - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - * - * Contributors: - * sovity GmbH - initial API and implementation - * - */ - -package de.sovity.edc.ext.brokerserver.services.api; - -import de.sovity.edc.ext.brokerserver.client.gen.model.AuthorityPortalOrganizationMetadata; -import de.sovity.edc.ext.brokerserver.client.gen.model.AuthorityPortalOrganizationMetadataRequest; -import de.sovity.edc.ext.brokerserver.db.TestDatabase; -import de.sovity.edc.ext.brokerserver.db.TestDatabaseFactory; -import de.sovity.edc.ext.brokerserver.db.jooq.Tables; -import de.sovity.edc.ext.brokerserver.db.jooq.tables.records.OrganizationMetadataRecord; -import org.eclipse.edc.junit.annotations.ApiTest; -import org.eclipse.edc.junit.extensions.EdcExtension; -import org.jooq.DSLContext; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.junit.jupiter.api.extension.RegisterExtension; - -import java.util.List; -import java.util.Map; - -import static de.sovity.edc.ext.brokerserver.TestUtils.ADMIN_API_KEY; -import static de.sovity.edc.ext.brokerserver.TestUtils.brokerServerClient; -import static de.sovity.edc.ext.brokerserver.TestUtils.createConfiguration; -import static org.assertj.core.api.Assertions.assertThat; - -@ApiTest -@ExtendWith(EdcExtension.class) -class AuthorityPortalOrganizationMetadataApiTest { - - @RegisterExtension - private static final TestDatabase TEST_DATABASE = TestDatabaseFactory.getTestDatabase(); - - @BeforeEach - void setUp(EdcExtension extension) { - extension.setConfiguration(createConfiguration(TEST_DATABASE, Map.of())); - } - - @Test - void testSetOrganizationMetadata() { - TEST_DATABASE.testTransaction(dsl -> { - // arrange - createOrgMetadataInDb(dsl, "MDSL1111AA", "Test Org A"); - createOrgMetadataInDb(dsl, "MDSL2222BB", "Test Org B"); - createOrgMetadataInDb(dsl, "MDSL3333CC", "Test Org C"); - - // act - var orgMetadataRequest = new AuthorityPortalOrganizationMetadataRequest(); - orgMetadataRequest.setOrganizations(List.of( - buildOrgMetadataRequestEntry("MDSL2222BB", "Test Org B"), - buildOrgMetadataRequestEntry("MDSL3333CC", "Test Org C new"), - buildOrgMetadataRequestEntry("MDSL4444DD", "Test Org D") - )); - - brokerServerClient().brokerServerApi().setOrganizationMetadata( - ADMIN_API_KEY, - orgMetadataRequest - ); - - // assert - var orgMetadata = getOrgMetadataFromDb(dsl); - assertThat(orgMetadata).hasSize(3); - assertThat(orgMetadata).extracting(OrganizationMetadataRecord::getName).containsExactlyInAnyOrder("Test Org B", "Test Org C new", "Test Org D"); - }); - } - - @Test - void testSetEmptyOrganizationMetadata() { - TEST_DATABASE.testTransaction(dsl -> { - // arrange - createOrgMetadataInDb(dsl, "MDSL1111AA", "Test Org A"); - - // act - var orgMetadataRequest = new AuthorityPortalOrganizationMetadataRequest(); - orgMetadataRequest.setOrganizations(List.of()); - - brokerServerClient().brokerServerApi().setOrganizationMetadata( - ADMIN_API_KEY, - orgMetadataRequest - ); - - // assert - var orgMetadata = getOrgMetadataFromDb(dsl); - assertThat(orgMetadata).isEmpty(); - }); - } - - private void createOrgMetadataInDb(DSLContext dsl, String mdsId, String name) { - var organizationMetadata = dsl.newRecord(Tables.ORGANIZATION_METADATA); - organizationMetadata.setMdsId(mdsId); - organizationMetadata.setName(name); - organizationMetadata.insert(); - } - - private List getOrgMetadataFromDb(DSLContext dsl) { - return dsl.selectFrom(Tables.ORGANIZATION_METADATA).fetch(); - } - - private AuthorityPortalOrganizationMetadata buildOrgMetadataRequestEntry(String mdsId, String name) { - var orgMetadata = new AuthorityPortalOrganizationMetadata(); - orgMetadata.setMdsId(mdsId); - orgMetadata.setName(name); - return orgMetadata; - } -} diff --git a/extensions/broker-server/src/test/java/de/sovity/edc/ext/brokerserver/services/api/CatalogApiTest.java b/extensions/broker-server/src/test/java/de/sovity/edc/ext/brokerserver/services/api/CatalogApiTest.java deleted file mode 100644 index fb508c39d..000000000 --- a/extensions/broker-server/src/test/java/de/sovity/edc/ext/brokerserver/services/api/CatalogApiTest.java +++ /dev/null @@ -1,708 +0,0 @@ -/* - * Copyright (c) 2023 sovity GmbH - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - * - * Contributors: - * sovity GmbH - initial implementation - * - */ - -package de.sovity.edc.ext.brokerserver.services.api; - -import com.fasterxml.jackson.databind.ObjectMapper; -import de.sovity.edc.ext.brokerserver.BrokerServerExtension; -import de.sovity.edc.ext.brokerserver.client.gen.model.CatalogDataOffer; -import de.sovity.edc.ext.brokerserver.client.gen.model.CatalogPageQuery; -import de.sovity.edc.ext.brokerserver.client.gen.model.CatalogPageResult; -import de.sovity.edc.ext.brokerserver.client.gen.model.CnfFilterAttribute; -import de.sovity.edc.ext.brokerserver.client.gen.model.CnfFilterItem; -import de.sovity.edc.ext.brokerserver.client.gen.model.CnfFilterValue; -import de.sovity.edc.ext.brokerserver.client.gen.model.CnfFilterValueAttribute; -import de.sovity.edc.ext.brokerserver.client.gen.model.DataOfferDetailPageQuery; -import de.sovity.edc.ext.brokerserver.client.gen.model.DataOfferDetailPageResult; -import de.sovity.edc.ext.brokerserver.db.TestDatabase; -import de.sovity.edc.ext.brokerserver.db.TestDatabaseFactory; -import de.sovity.edc.ext.brokerserver.db.jooq.Tables; -import de.sovity.edc.ext.brokerserver.db.jooq.enums.ConnectorContractOffersExceeded; -import de.sovity.edc.ext.brokerserver.db.jooq.enums.ConnectorDataOffersExceeded; -import de.sovity.edc.ext.brokerserver.db.jooq.enums.ConnectorOnlineStatus; -import de.sovity.edc.ext.wrapper.api.common.model.UiAssetCreateRequest; -import jakarta.json.JsonObject; -import lombok.SneakyThrows; -import org.eclipse.edc.junit.annotations.ApiTest; -import org.eclipse.edc.junit.extensions.EdcExtension; -import org.eclipse.edc.policy.model.Policy; -import org.eclipse.edc.policy.model.PolicyType; -import org.jooq.DSLContext; -import org.jooq.JSONB; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.junit.jupiter.api.extension.RegisterExtension; - -import java.time.OffsetDateTime; -import java.util.List; -import java.util.Map; - -import static de.sovity.edc.ext.brokerserver.TestAsset.getAssetJsonLd; -import static de.sovity.edc.ext.brokerserver.TestAsset.setDataOfferAssetMetadata; -import static de.sovity.edc.ext.brokerserver.TestUtils.brokerServerClient; -import static de.sovity.edc.ext.brokerserver.TestUtils.createConfiguration; -import static java.util.stream.IntStream.range; -import static org.assertj.core.api.Assertions.assertThat; - -@ApiTest -@ExtendWith(EdcExtension.class) -class CatalogApiTest { - - @RegisterExtension - private static final TestDatabase TEST_DATABASE = TestDatabaseFactory.getTestDatabase(); - - @BeforeEach - void setUp(EdcExtension extension) { - extension.setConfiguration(createConfiguration(TEST_DATABASE, Map.of( - BrokerServerExtension.CATALOG_PAGE_PAGE_SIZE, "10", - BrokerServerExtension.DEFAULT_CONNECTOR_DATASPACE, "MDS", - BrokerServerExtension.KNOWN_DATASPACE_CONNECTORS, "Example1=https://my-connector2/api/dsp,Example2=https://my-connector3/api/dsp" - ))); - } - - @Test - void testDataSpace_two_dataspaces_filter_for_one() { - TEST_DATABASE.testTransaction(dsl -> { - // arrange - var today = OffsetDateTime.now().withNano(0); - - var assetJsonLd = getAssetJsonLd( - UiAssetCreateRequest.builder() - .id("my-asset") - .title("My Asset") - .build() - ); - - // Dataspace: MDS - createConnector(dsl, today, "https://my-connector/api/dsp"); - createDataOffer(dsl, today, "https://my-connector/api/dsp", assetJsonLd); - - // Dataspace: Example1 - createConnector(dsl, today, "https://my-connector2/api/dsp"); - createDataOffer(dsl, today, "https://my-connector2/api/dsp", assetJsonLd); - - var query = new CatalogPageQuery(); - query.setFilter(new CnfFilterValue(List.of( - new CnfFilterValueAttribute("dataSpace", List.of("Example1")) - ))); - - var result = brokerServerClient().brokerServerApi().catalogPage(query); - assertThat(result.getDataOffers()).hasSize(1); - - var dataOfferResult = result.getDataOffers().get(0); - assertThat(dataOfferResult.getConnectorEndpoint()).isEqualTo("https://my-connector2/api/dsp"); - }); - } - - @Test - void testConnectorEndpointFilter_two_connectors_filter_for_one() { - TEST_DATABASE.testTransaction(dsl -> { - // arrange - var today = OffsetDateTime.now().withNano(0); - - var assetJsonLd = getAssetJsonLd( - UiAssetCreateRequest.builder() - .id("my-asset") - .title("My Asset") - .build() - ); - - createConnector(dsl, today, "https://my-connector/api/dsp"); - createDataOffer(dsl, today, "https://my-connector/api/dsp", assetJsonLd); - - createConnector(dsl, today, "https://my-connector2/api/dsp"); - createDataOffer(dsl, today, "https://my-connector2/api/dsp", assetJsonLd); - - var query = new CatalogPageQuery(); - query.setFilter(new CnfFilterValue(List.of( - new CnfFilterValueAttribute("connectorEndpoint", List.of("https://my-connector/api/dsp")) - ))); - - var result = brokerServerClient().brokerServerApi().catalogPage(query); - assertThat(result.getDataOffers()).extracting(CatalogDataOffer::getConnectorEndpoint).containsExactly("https://my-connector/api/dsp"); - }); - } - - @Test - void test_available_filter_values_to_filter_by() { - TEST_DATABASE.testTransaction(dsl -> { - // arrange - var today = OffsetDateTime.now().withNano(0); - - createConnector(dsl, today, "https://my-connector/api/dsp"); // Dataspace: MDS - createConnector(dsl, today, "https://my-connector2/api/dsp"); // Dataspace: Example1 - createConnector(dsl, today, "https://my-connector3/api/dsp"); // Dataspace: Example2 - - var assetJsonLd1 = getAssetJsonLd("my-asset-1"); - var assetJsonLd2 = getAssetJsonLd("my-asset-2"); - var assetJsonLd3 = getAssetJsonLd("my-asset-3"); - - createDataOffer(dsl, today, "https://my-connector/api/dsp", assetJsonLd1); // Dataspace: MDS - createDataOffer(dsl, today, "https://my-connector2/api/dsp", assetJsonLd1); // Dataspace: Example1 - createDataOffer(dsl, today, "https://my-connector2/api/dsp", assetJsonLd2); // Dataspace: Example1 - createDataOffer(dsl, today, "https://my-connector3/api/dsp", assetJsonLd3); // Dataspace: Example2 - - // get all available filter values - var result = brokerServerClient().brokerServerApi().catalogPage(new CatalogPageQuery()); - - // assert that the filter values are correct - var dataSpace = getAvailableFilter(result, "dataSpace"); - assertThat(dataSpace.getValues()).containsExactly( - new CnfFilterItem("Example1", "Example1"), - new CnfFilterItem("Example2", "Example2"), - new CnfFilterItem("MDS", "MDS") - ); - }); - } - - @Test - void testDataOfferDetails() { - TEST_DATABASE.testTransaction(dsl -> { - // arrange - var today = OffsetDateTime.now().withNano(0); - - var assetJsonLd = getAssetJsonLd( - UiAssetCreateRequest.builder() - .id("my-asset") - .title("My Asset") - .build() - ); - - createConnector(dsl, today, "https://my-connector/api/dsp"); - createDataOffer(dsl, today, "https://my-connector/api/dsp", assetJsonLd); - - var result = brokerServerClient().brokerServerApi().catalogPage(new CatalogPageQuery()); - assertThat(result.getDataOffers()).hasSize(1); - - var dataOfferResult = result.getDataOffers().get(0); - assertThat(dataOfferResult.getConnectorEndpoint()).isEqualTo("https://my-connector/api/dsp"); - assertThat(dataOfferResult.getConnectorOfflineSinceOrLastUpdatedAt()).isEqualTo(today); - assertThat(dataOfferResult.getConnectorOnlineStatus()).isEqualTo(CatalogDataOffer.ConnectorOnlineStatusEnum.ONLINE); - assertThat(dataOfferResult.getAssetId()).isEqualTo("my-asset"); - assertThat(dataOfferResult.getAsset().getAssetId()).isEqualTo("my-asset"); - assertThat(dataOfferResult.getAsset().getTitle()).isEqualTo("My Asset"); - assertThat(dataOfferResult.getCreatedAt()).isEqualTo(today.minusDays(5)); - }); - } - - /** - * Tests against an issue where empty available filter values resulted in NULLs - */ - @Test - void testEmptyConnector() { - TEST_DATABASE.testTransaction(dsl -> { - // arrange - var today = OffsetDateTime.now().withNano(0); - createConnector(dsl, today, "https://my-connector/api/dsp"); - - // act - var result = brokerServerClient().brokerServerApi().catalogPage(new CatalogPageQuery()); - - // assert - assertThat(result.getDataOffers()).isEmpty(); - assertThat(result.getAvailableFilters().getFields()).isNotEmpty(); - assertThat(result.getAvailableSortings()).isNotEmpty(); - - // the most important thing is that the above code ran through as it crashed before - }); - } - - @Test - void testAvailableFilters_noFilter() { - TEST_DATABASE.testTransaction(dsl -> { - // arrange - var today = OffsetDateTime.now().withNano(0); - - var assetJsonLd1 = getAssetJsonLd( - UiAssetCreateRequest.builder() - .id("my-asset-1") - .dataCategory("my-category-1") - .transportMode("MY-TRANSPORT-MODE-1") - .dataSubcategory("MY-SUBCATEGORY-2") - .dataModel("my-data-model") - .geoReferenceMethod("my-geo-ref") - .build() - ); - - var assetJsonLd2 = getAssetJsonLd( - UiAssetCreateRequest.builder() - .id("my-asset-2") - .dataCategory("my-category-1") - .transportMode("my-transport-mode-2") - .dataSubcategory("MY-SUBCATEGORY-2") - .build() - ); - - var assetJsonLd3 = getAssetJsonLd( - UiAssetCreateRequest.builder() - .id("my-asset-3") - .dataCategory("my-category-1") - .transportMode("MY-TRANSPORT-MODE-1") - .dataSubcategory("my-subcategory-1") - .build() - ); - - var assetJsonLd4 = getAssetJsonLd( - UiAssetCreateRequest.builder() - .id("my-asset-4") - .dataCategory("my-category-1") - .transportMode("") - .build() - ); - - createOrganizationMetadata(dsl, "MDSL123456AA", "Test Org"); - createConnector(dsl, today, "https://my-connector/api/dsp", "MDSL123456AA"); - createDataOffer(dsl, today, "https://my-connector/api/dsp", assetJsonLd1); - createDataOffer(dsl, today, "https://my-connector/api/dsp", assetJsonLd2); - createDataOffer(dsl, today, "https://my-connector/api/dsp", assetJsonLd3); - createDataOffer(dsl, today, "https://my-connector/api/dsp", assetJsonLd4); - - var result = brokerServerClient().brokerServerApi().catalogPage(new CatalogPageQuery()); - - assertThat(result.getAvailableFilters().getFields()) - .extracting(CnfFilterAttribute::getId) - .containsExactly( - "dataSpace", - "dataCategory", - "dataSubcategory", - "dataModel", - "transportMode", - "geoReferenceMethod", - "curatorOrganizationName", - "curatorMdsId", - "connectorEndpoint" - ); - - assertThat(result.getAvailableFilters().getFields()) - .extracting(CnfFilterAttribute::getTitle) - .containsExactly( - "Data Space", - "Data Category", - "Data Subcategory", - "Data Model", - "Transport Mode", - "Geo Reference Method", - "Organization Name", - "MDS ID", - "Connector" - ); - - var dataSpace = getAvailableFilter(result, "dataSpace"); - assertThat(dataSpace.getValues()).extracting(CnfFilterItem::getId).containsExactly("MDS"); - assertThat(dataSpace.getValues()).extracting(CnfFilterItem::getTitle).containsExactly("MDS"); - - var dataCategory = getAvailableFilter(result, "dataCategory"); - assertThat(dataCategory.getValues()).extracting(CnfFilterItem::getId).containsExactly("my-category-1"); - assertThat(dataCategory.getValues()).extracting(CnfFilterItem::getTitle).containsExactly("my-category-1"); - - var dataSubcategory = getAvailableFilter(result, "dataSubcategory"); - assertThat(dataSubcategory.getValues()).extracting(CnfFilterItem::getId).containsExactly("my-subcategory-1", "MY-SUBCATEGORY-2", ""); - assertThat(dataSubcategory.getValues()).extracting(CnfFilterItem::getTitle).containsExactly("my-subcategory-1", "MY-SUBCATEGORY-2", ""); - - var dataModel = getAvailableFilter(result, "dataModel"); - assertThat(dataModel.getValues()).extracting(CnfFilterItem::getId).containsExactly("my-data-model", ""); - assertThat(dataModel.getValues()).extracting(CnfFilterItem::getTitle).containsExactly("my-data-model", ""); - - var transportMode = getAvailableFilter(result, "transportMode"); - assertThat(transportMode.getValues()).extracting(CnfFilterItem::getId).containsExactly("MY-TRANSPORT-MODE-1", "my-transport-mode-2", ""); - assertThat(transportMode.getValues()).extracting(CnfFilterItem::getTitle).containsExactly("MY-TRANSPORT-MODE-1", "my-transport-mode-2", ""); - - var geoReferenceMethod = getAvailableFilter(result, "geoReferenceMethod"); - assertThat(geoReferenceMethod.getValues()).extracting(CnfFilterItem::getId).containsExactly("my-geo-ref", ""); - assertThat(geoReferenceMethod.getValues()).extracting(CnfFilterItem::getTitle).containsExactly("my-geo-ref", ""); - - var curatorOrganizationName = getAvailableFilter(result, "curatorOrganizationName"); - assertThat(curatorOrganizationName.getValues()).extracting(CnfFilterItem::getId).containsExactly("Test Org"); - assertThat(curatorOrganizationName.getValues()).extracting(CnfFilterItem::getTitle).containsExactly("Test Org"); - - var curatorMdsId = getAvailableFilter(result, "curatorMdsId"); - assertThat(curatorMdsId.getValues()).extracting(CnfFilterItem::getId).containsExactly("MDSL123456AA"); - assertThat(curatorMdsId.getValues()).extracting(CnfFilterItem::getTitle).containsExactly("MDSL123456AA"); - - var connectorEndpoint = getAvailableFilter(result, "connectorEndpoint"); - assertThat(connectorEndpoint.getValues()).extracting(CnfFilterItem::getId).containsExactly("https://my-connector/api/dsp"); - assertThat(connectorEndpoint.getValues()).extracting(CnfFilterItem::getTitle).containsExactly("https://my-connector/api/dsp"); - }); - } - - - /** - * Regression Test against bug where asset names with capital letters were not hit by search. - *
- * It was caused by search terms getting lower cased while the LIKE operation being case-sensitive. - */ - @Test - void testSearchCaseInsensitive() { - TEST_DATABASE.testTransaction(dsl -> { - // arrange - var today = OffsetDateTime.now().withNano(0); - - var assetJsonLd = getAssetJsonLd( - UiAssetCreateRequest.builder() - .id("123") - .title("Hello") - .build() - ); - - createConnector(dsl, today, "https://my-connector/api/dsp"); - createDataOffer(dsl, today, "https://my-connector/api/dsp", assetJsonLd); - - - // act - var query = new CatalogPageQuery(); - query.setSearchQuery("Hello"); - var result = brokerServerClient().brokerServerApi().catalogPage(query); - - // assert - assertThat(result.getDataOffers()).extracting(CatalogDataOffer::getAssetId).containsExactly("123"); - }); - } - - private CnfFilterAttribute getAvailableFilter(CatalogPageResult result, String filterId) { - return result.getAvailableFilters().getFields().stream() - .filter(it -> it.getId().equals(filterId)).findFirst() - .orElseThrow(() -> new IllegalStateException("Filter not found")); - } - - @Test - void testAvailableFilters_withFilter() { - TEST_DATABASE.testTransaction(dsl -> { - // arrange - var today = OffsetDateTime.now().withNano(0); - - var assetJsonLd1 = getAssetJsonLd( - UiAssetCreateRequest.builder() - .id("my-asset-1") - .dataCategory("my-category") - .dataSubcategory("my-subcategory") - .build() - ); - - var assetJsonLd2 = getAssetJsonLd( - UiAssetCreateRequest.builder() - .id("my-asset-2") - .dataSubcategory("my-other-subcategory") - .build() - ); - - createConnector(dsl, today, "https://my-connector/api/dsp"); - createDataOffer(dsl, today, "https://my-connector/api/dsp", assetJsonLd1); - createDataOffer(dsl, today, "https://my-connector/api/dsp", assetJsonLd2); - - var query = new CatalogPageQuery(); - query.setFilter(new CnfFilterValue(List.of( - new CnfFilterValueAttribute("dataCategory", List.of("")) - ))); - - var result = brokerServerClient().brokerServerApi().catalogPage(query); - - var dataCategory = getAvailableFilter(result, "dataCategory"); - assertThat(dataCategory.getValues()).extracting(CnfFilterItem::getId).containsExactly("my-category", ""); - assertThat(dataCategory.getValues()).extracting(CnfFilterItem::getTitle).containsExactly("my-category", ""); - - var dataSubcategory = getAvailableFilter(result, "dataSubcategory"); - assertThat(dataSubcategory.getValues()).extracting(CnfFilterItem::getId).containsExactly("my-other-subcategory"); - assertThat(dataSubcategory.getValues()).extracting(CnfFilterItem::getTitle).containsExactly("my-other-subcategory"); - }); - } - - @Test - void testPagination_firstPage() { - TEST_DATABASE.testTransaction(dsl -> { - // arrange - var today = OffsetDateTime.now().withNano(0); - - createConnector(dsl, today, "https://my-connector/api/dsp"); - range(0, 15).forEach(i -> createDataOffer(dsl, today, "https://my-connector/api/dsp", getAssetJsonLd("my-asset-%d".formatted(i)))); - range(0, 15).forEach(i -> createDataOffer(dsl, today, "https://my-connector/api/dsp", getAssetJsonLd("some-other-asset-%d".formatted(i)))); - - var query = new CatalogPageQuery(); - query.setSearchQuery("my-asset"); - query.setSorting(CatalogPageQuery.SortingEnum.TITLE); - - var result = brokerServerClient().brokerServerApi().catalogPage(query); - assertThat(result.getDataOffers()).extracting(CatalogDataOffer::getAssetId) - .isEqualTo(range(0, 10).mapToObj("my-asset-%d"::formatted).toList()); - - var actual = result.getPaginationMetadata(); - assertThat(actual.getPageOneBased()).isEqualTo(1); - assertThat(actual.getPageSize()).isEqualTo(10); - assertThat(actual.getNumVisible()).isEqualTo(10); - assertThat(actual.getNumTotal()).isEqualTo(15); - }); - } - - @Test - void testPagination_secondPage() { - TEST_DATABASE.testTransaction(dsl -> { - // arrange - var today = OffsetDateTime.now().withNano(0); - - createConnector(dsl, today, "https://my-connector/api/dsp"); - range(0, 15).forEach(i -> createDataOffer(dsl, today, "https://my-connector/api/dsp", getAssetJsonLd("my-asset-%d".formatted(i)))); - range(0, 15).forEach(i -> createDataOffer(dsl, today, "https://my-connector/api/dsp", getAssetJsonLd("some-other-asset-%d".formatted(i)))); - - - var query = new CatalogPageQuery(); - query.setSearchQuery("my-asset"); - query.setPageOneBased(2); - query.setSorting(CatalogPageQuery.SortingEnum.TITLE); - - var result = brokerServerClient().brokerServerApi().catalogPage(query); - - assertThat(result.getDataOffers()).extracting(CatalogDataOffer::getAssetId) - .isEqualTo(range(10, 15).mapToObj("my-asset-%d"::formatted).toList()); - - var actual = result.getPaginationMetadata(); - assertThat(actual.getPageOneBased()).isEqualTo(2); - assertThat(actual.getPageSize()).isEqualTo(10); - assertThat(actual.getNumVisible()).isEqualTo(5); - assertThat(actual.getNumTotal()).isEqualTo(15); - }); - } - - @Test - void testSortingByPopularity() { - TEST_DATABASE.testTransaction(dsl -> { - // arrange - var today = OffsetDateTime.now().withNano(0); - - var endpoint = "https://my-connector/api/dsp"; - createConnector(dsl, today, endpoint); - createDataOffer(dsl, today, endpoint, getAssetJsonLd("asset-1")); - createDataOffer(dsl, today, endpoint, getAssetJsonLd("asset-2")); - createDataOffer(dsl, today, endpoint, getAssetJsonLd("asset-3")); - - range(0, 3).forEach(i -> dataOfferDetails(endpoint, "asset-1")); - range(0, 5).forEach(i -> dataOfferDetails(endpoint, "asset-2")); - - - var query = new CatalogPageQuery(); - query.setSorting(CatalogPageQuery.SortingEnum.VIEW_COUNT); - - var result = brokerServerClient().brokerServerApi().catalogPage(query); - assertThat(result.getDataOffers()).extracting(CatalogDataOffer::getAssetId).containsExactly( - "asset-2", - "asset-1", - "asset-3" - ); - }); - } - - @Test - void testFilterByOrgName() { - TEST_DATABASE.testTransaction(dsl -> { - // arrange - var today = OffsetDateTime.now().withNano(0); - - var endpoint1 = "https://my-connector-1/api/dsp"; - createConnector(dsl, today, endpoint1, "MDSL1111AA"); - createDataOffer(dsl, today, endpoint1, getAssetJsonLd("asset-1")); - - var endpoint2 = "https://my-connector-2/api/dsp"; - createConnector(dsl, today, endpoint2, "MDSL2222BB"); - createDataOffer(dsl, today, endpoint2, getAssetJsonLd("asset-2")); - - createOrganizationMetadata(dsl, "MDSL1111AA", "Test Org"); - - // act - var query = new CatalogPageQuery(); - query.setFilter(new CnfFilterValue(List.of( - new CnfFilterValueAttribute("curatorOrganizationName", List.of("Test Org")) - ))); - - var actual = brokerServerClient().brokerServerApi().catalogPage(query); - - // assert - assertThat(actual.getDataOffers()).extracting(CatalogDataOffer::getConnectorEndpoint).containsExactly(endpoint1); - }); - } - - @Test - void testSearchForOrgName() { - TEST_DATABASE.testTransaction(dsl -> { - // arrange - var today = OffsetDateTime.now().withNano(0); - - var endpoint1 = "https://my-connector-1/api/dsp"; - createConnector(dsl, today, endpoint1, "MDSL1111AA"); - createDataOffer(dsl, today, endpoint1, getAssetJsonLd("asset-1")); - - var endpoint2 = "https://my-connector-2/api/dsp"; - createConnector(dsl, today, endpoint2, "MDSL2222BB"); - createDataOffer(dsl, today, endpoint2, getAssetJsonLd("asset-2")); - - createOrganizationMetadata(dsl, "MDSL1111AA", "Test Org"); - - // act - var query = new CatalogPageQuery(); - query.setSearchQuery("tEsT"); - - var actual = brokerServerClient().brokerServerApi().catalogPage(query); - - // assert - assertThat(actual.getDataOffers()).extracting(CatalogDataOffer::getConnectorEndpoint).containsExactly(endpoint1); - }); - } - - @Test - void testFilterByMdsId() { - TEST_DATABASE.testTransaction(dsl -> { - // arrange - var today = OffsetDateTime.now().withNano(0); - - var endpoint1 = "https://my-connector-1/api/dsp"; - createConnector(dsl, today, endpoint1, "MDSL1111AA"); - createDataOffer(dsl, today, endpoint1, getAssetJsonLd("asset-1")); - - var endpoint2 = "https://my-connector-2/api/dsp"; - createConnector(dsl, today, endpoint2, "MDSL2222BB"); - createDataOffer(dsl, today, endpoint2, getAssetJsonLd("asset-2")); - - // act - var query = new CatalogPageQuery(); - query.setFilter(new CnfFilterValue(List.of( - new CnfFilterValueAttribute("curatorMdsId", List.of("MDSL1111AA")) - ))); - - var actual = brokerServerClient().brokerServerApi().catalogPage(query); - - // assert - assertThat(actual.getDataOffers()).extracting(CatalogDataOffer::getConnectorEndpoint).containsExactly(endpoint1); - }); - } - - @Test - void testFilterByUnknown() { - TEST_DATABASE.testTransaction(dsl -> { - // arrange - var today = OffsetDateTime.now().withNano(0); - - var endpoint1 = "https://my-connector-1/api/dsp"; - createConnector(dsl, today, endpoint1, "MDSL1111AA"); - createDataOffer(dsl, today, endpoint1, getAssetJsonLd("asset-1")); - - var endpoint2 = "https://my-connector-2/api/dsp"; - createConnector(dsl, today, endpoint2, "MDSL2222BB"); - createDataOffer(dsl, today, endpoint2, getAssetJsonLd("asset-2")); - - createOrganizationMetadata(dsl, "MDSL1111AA", "Test Org"); - - // act - var query = new CatalogPageQuery(); - query.setFilter(new CnfFilterValue(List.of( - new CnfFilterValueAttribute("curatorOrganizationName", List.of("Unknown")) - ))); - - var actual = brokerServerClient().brokerServerApi().catalogPage(query); - - // assert - assertThat(actual.getDataOffers()).extracting(CatalogDataOffer::getConnectorEndpoint).containsExactly(endpoint2); - }); - } - - @Test - void testSearchForUnknown() { - TEST_DATABASE.testTransaction(dsl -> { - // arrange - var today = OffsetDateTime.now().withNano(0); - - var endpoint1 = "https://my-connector-1/api/dsp"; - createConnector(dsl, today, endpoint1, "MDSL1111AA"); - createDataOffer(dsl, today, endpoint1, getAssetJsonLd("asset-1")); - - var endpoint2 = "https://my-connector-2/api/dsp"; - createConnector(dsl, today, endpoint2, "MDSL2222BB"); - createDataOffer(dsl, today, endpoint2, getAssetJsonLd("asset-2")); - - createOrganizationMetadata(dsl, "MDSL1111AA", "Test Org"); - - // act - var query = new CatalogPageQuery(); - query.setSearchQuery("uNkN"); - - var actual = brokerServerClient().brokerServerApi().catalogPage(query); - - // assert - assertThat(actual.getDataOffers()).extracting(CatalogDataOffer::getConnectorEndpoint).containsExactly(endpoint2); - }); - } - - private void createDataOffer(DSLContext dsl, OffsetDateTime today, String connectorEndpoint, JsonObject assetJsonLd) { - var dataOffer = dsl.newRecord(Tables.DATA_OFFER); - setDataOfferAssetMetadata(dataOffer, assetJsonLd, "my-participant-id"); - dataOffer.setConnectorEndpoint(connectorEndpoint); - dataOffer.setCreatedAt(today.minusDays(5)); - dataOffer.setUpdatedAt(today); - dataOffer.insert(); - - var contractOffer = dsl.newRecord(Tables.CONTRACT_OFFER); - contractOffer.setContractOfferId("my-contract-offer-1"); - contractOffer.setConnectorEndpoint(connectorEndpoint); - contractOffer.setAssetId(dataOffer.getAssetId()); - contractOffer.setCreatedAt(today.minusDays(5)); - contractOffer.setUpdatedAt(today); - contractOffer.setPolicy(JSONB.jsonb(policyToJson(dummyPolicy()))); - contractOffer.insert(); - } - - private void createConnector(DSLContext dsl, OffsetDateTime today, String connectorEndpoint) { - createConnector(dsl, today, connectorEndpoint, null); - } - - private void createConnector(DSLContext dsl, OffsetDateTime today, String connectorEndpoint, String mdsId) { - var connector = dsl.newRecord(Tables.CONNECTOR); - connector.setParticipantId("my-connector"); - connector.setMdsId(mdsId); - connector.setEndpoint(connectorEndpoint); - connector.setOnlineStatus(ConnectorOnlineStatus.ONLINE); - connector.setCreatedAt(today.minusDays(1)); - connector.setLastRefreshAttemptAt(today); - connector.setLastSuccessfulRefreshAt(today); - connector.setDataOffersExceeded(ConnectorDataOffersExceeded.OK); - connector.setContractOffersExceeded(ConnectorContractOffersExceeded.OK); - connector.insert(); - } - - private void createOrganizationMetadata(DSLContext dsl, String mdsId, String name) { - var organizationMetadata = dsl.newRecord(Tables.ORGANIZATION_METADATA); - organizationMetadata.setMdsId(mdsId); - organizationMetadata.setName(name); - organizationMetadata.insert(); - } - - private Policy dummyPolicy() { - return Policy.Builder.newInstance() - .type(PolicyType.SET) - .build(); - } - - private DataOfferDetailPageResult dataOfferDetails(String endpoint, String assetId) { - var query = DataOfferDetailPageQuery.builder() - .connectorEndpoint(endpoint) - .assetId(assetId) - .build(); - return brokerServerClient().brokerServerApi().dataOfferDetailPage(query); - } - - private String policyToJson(Policy policy) { - return toJson(policy); - } - - @SneakyThrows - private String toJson(Object o) { - return new ObjectMapper().writeValueAsString(o); - } -} diff --git a/extensions/broker-server/src/test/java/de/sovity/edc/ext/brokerserver/services/api/ConnectorApiTest.java b/extensions/broker-server/src/test/java/de/sovity/edc/ext/brokerserver/services/api/ConnectorApiTest.java deleted file mode 100644 index fa3419438..000000000 --- a/extensions/broker-server/src/test/java/de/sovity/edc/ext/brokerserver/services/api/ConnectorApiTest.java +++ /dev/null @@ -1,159 +0,0 @@ -/* - * Copyright (c) 2023 sovity GmbH - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - * - * Contributors: - * sovity GmbH - initial implementation - * - */ - -package de.sovity.edc.ext.brokerserver.services.api; - -import de.sovity.edc.ext.brokerserver.TestPolicy; -import de.sovity.edc.ext.brokerserver.client.gen.model.ConnectorDetailPageQuery; -import de.sovity.edc.ext.brokerserver.client.gen.model.ConnectorPageQuery; -import de.sovity.edc.ext.brokerserver.db.TestDatabase; -import de.sovity.edc.ext.brokerserver.db.TestDatabaseFactory; -import de.sovity.edc.ext.brokerserver.db.jooq.Tables; -import de.sovity.edc.ext.brokerserver.db.jooq.enums.ConnectorContractOffersExceeded; -import de.sovity.edc.ext.brokerserver.db.jooq.enums.ConnectorDataOffersExceeded; -import de.sovity.edc.ext.brokerserver.db.jooq.enums.ConnectorOnlineStatus; -import de.sovity.edc.ext.brokerserver.db.jooq.enums.MeasurementErrorStatus; -import de.sovity.edc.ext.brokerserver.db.jooq.enums.MeasurementType; -import de.sovity.edc.ext.brokerserver.db.jooq.tables.records.ConnectorRecord; -import de.sovity.edc.ext.wrapper.api.common.model.UiAssetCreateRequest; -import jakarta.json.JsonObject; -import org.eclipse.edc.junit.annotations.ApiTest; -import org.eclipse.edc.junit.extensions.EdcExtension; -import org.jooq.DSLContext; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.junit.jupiter.api.extension.RegisterExtension; - -import java.time.OffsetDateTime; -import java.util.Map; - -import static de.sovity.edc.ext.brokerserver.TestAsset.getAssetJsonLd; -import static de.sovity.edc.ext.brokerserver.TestAsset.setDataOfferAssetMetadata; -import static de.sovity.edc.ext.brokerserver.TestUtils.brokerServerClient; -import static de.sovity.edc.ext.brokerserver.TestUtils.createConfiguration; -import static org.assertj.core.api.Assertions.assertThat; - -@ApiTest -@ExtendWith(EdcExtension.class) -class ConnectorApiTest { - - @RegisterExtension - private static final TestDatabase TEST_DATABASE = TestDatabaseFactory.getTestDatabase(); - - @BeforeEach - void setUp(EdcExtension extension) { - extension.setConfiguration(createConfiguration(TEST_DATABASE, Map.of())); - } - - @Test - void testQueryConnectors() { - TEST_DATABASE.testTransaction(dsl -> { - var today = OffsetDateTime.now().withNano(0); - - var assetJsonLd = getAssetJsonLd( - UiAssetCreateRequest.builder() - .id("my-asset-1") - .title("My Asset 1") - .dataCategory("my-category") - .build() - ); - - createConnector(dsl, today, "https://my-connector/api/dsp"); - createDataOffer(dsl, today, "https://my-connector/api/dsp", assetJsonLd); - - var result = brokerServerClient().brokerServerApi().connectorPage(new ConnectorPageQuery()); - assertThat(result.getConnectors()).hasSize(1); - - var connector = result.getConnectors().get(0); - assertThat(connector.getParticipantId()).isEqualTo("my-participant-id"); - assertThat(connector.getEndpoint()).isEqualTo("https://my-connector/api/dsp"); - assertThat(connector.getCreatedAt()).isEqualTo(today.minusDays(1)); - assertThat(connector.getLastRefreshAttemptAt()).isEqualTo(today); - assertThat(connector.getLastSuccessfulRefreshAt()).isEqualTo(today); - assertThat(connector.getNumDataOffers()).isEqualTo(1); - }); - } - - @Test - void testQueryConnectorDetails() { - TEST_DATABASE.testTransaction(dsl -> { - var today = OffsetDateTime.now().withNano(0); - - var assetJsonLd = getAssetJsonLd( - UiAssetCreateRequest.builder() - .id("my-asset-1") - .title("My Asset 1") - .dataCategory("my-category") - .build() - ); - - createConnector(dsl, today, "https://my-connector/api/dsp"); - createConnector(dsl, today, "https://my-connector2/api/dsp"); - createDataOffer(dsl, today, "https://my-connector/api/dsp", assetJsonLd); - - var connector = brokerServerClient().brokerServerApi().connectorDetailPage(new ConnectorDetailPageQuery("https://my-connector/api/dsp")); - assertThat(connector.getParticipantId()).isEqualTo("my-participant-id"); - assertThat(connector.getEndpoint()).isEqualTo("https://my-connector/api/dsp"); - assertThat(connector.getCreatedAt()).isEqualTo(today.minusDays(1)); - assertThat(connector.getLastRefreshAttemptAt()).isEqualTo(today); - assertThat(connector.getLastSuccessfulRefreshAt()).isEqualTo(today); - assertThat(connector.getConnectorCrawlingTimeAvg()).isEqualTo(150L); - }); - } - - private void createConnector(DSLContext dsl, OffsetDateTime today, String connectorEndpoint) { - var connector = dsl.newRecord(Tables.CONNECTOR); - connector.setParticipantId("my-participant-id"); - connector.setEndpoint(connectorEndpoint); - connector.setOnlineStatus(ConnectorOnlineStatus.ONLINE); - connector.setCreatedAt(today.minusDays(1)); - connector.setLastRefreshAttemptAt(today); - connector.setLastSuccessfulRefreshAt(today); - connector.setDataOffersExceeded(ConnectorDataOffersExceeded.OK); - connector.setContractOffersExceeded(ConnectorContractOffersExceeded.OK); - connector.insert(); - - addCrawlingTime(dsl, today, connector, 100L); - addCrawlingTime(dsl, today.plusHours(5), connector, 200L); - } - - private static void addCrawlingTime(DSLContext dsl, OffsetDateTime today, ConnectorRecord connector, Long duration) { - var crawlingTime = dsl.newRecord(Tables.BROKER_EXECUTION_TIME_MEASUREMENT); - crawlingTime.setConnectorEndpoint(connector.getEndpoint()); - crawlingTime.setDurationInMs(duration); - crawlingTime.setCreatedAt(today); - crawlingTime.setType(MeasurementType.CONNECTOR_REFRESH); - crawlingTime.setErrorStatus(MeasurementErrorStatus.OK); - crawlingTime.insert(); - } - - private void createDataOffer(DSLContext dsl, OffsetDateTime today, String connectorEndpoint, JsonObject assetJsonLd) { - var dataOffer = dsl.newRecord(Tables.DATA_OFFER); - setDataOfferAssetMetadata(dataOffer, assetJsonLd, "my-participant-id"); - dataOffer.setConnectorEndpoint(connectorEndpoint); - dataOffer.setCreatedAt(today.minusDays(5)); - dataOffer.setUpdatedAt(today); - dataOffer.insert(); - - var contractOffer = dsl.newRecord(Tables.CONTRACT_OFFER); - contractOffer.setContractOfferId("my-contract-offer-1"); - contractOffer.setConnectorEndpoint(connectorEndpoint); - contractOffer.setAssetId(dataOffer.getAssetId()); - contractOffer.setCreatedAt(today.minusDays(5)); - contractOffer.setUpdatedAt(today); - contractOffer.setPolicy(TestPolicy.createAfterYesterdayPolicyJson()); - contractOffer.insert(); - } -} diff --git a/extensions/broker-server/src/test/java/de/sovity/edc/ext/brokerserver/services/api/DataOfferDetailApiTest.java b/extensions/broker-server/src/test/java/de/sovity/edc/ext/brokerserver/services/api/DataOfferDetailApiTest.java deleted file mode 100644 index 007ac7ffc..000000000 --- a/extensions/broker-server/src/test/java/de/sovity/edc/ext/brokerserver/services/api/DataOfferDetailApiTest.java +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Copyright (c) 2023 sovity GmbH - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - * - * Contributors: - * sovity GmbH - initial implementation - * - */ - -package de.sovity.edc.ext.brokerserver.services.api; - -import de.sovity.edc.ext.brokerserver.client.gen.model.DataOfferDetailPageQuery; -import de.sovity.edc.ext.brokerserver.client.gen.model.DataOfferDetailPageResult; -import de.sovity.edc.ext.brokerserver.db.TestDatabase; -import de.sovity.edc.ext.brokerserver.db.TestDatabaseFactory; -import de.sovity.edc.ext.brokerserver.db.jooq.Tables; -import de.sovity.edc.ext.brokerserver.db.jooq.enums.ConnectorContractOffersExceeded; -import de.sovity.edc.ext.brokerserver.db.jooq.enums.ConnectorDataOffersExceeded; -import de.sovity.edc.ext.brokerserver.db.jooq.enums.ConnectorOnlineStatus; -import de.sovity.edc.ext.wrapper.api.common.model.UiAssetCreateRequest; -import jakarta.json.JsonObject; -import org.eclipse.edc.junit.annotations.ApiTest; -import org.eclipse.edc.junit.extensions.EdcExtension; -import org.jooq.DSLContext; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.junit.jupiter.api.extension.RegisterExtension; - -import java.time.OffsetDateTime; -import java.util.Map; - -import static de.sovity.edc.ext.brokerserver.AssertionUtils.assertEqualUsingJson; -import static de.sovity.edc.ext.brokerserver.TestAsset.getAssetJsonLd; -import static de.sovity.edc.ext.brokerserver.TestAsset.setDataOfferAssetMetadata; -import static de.sovity.edc.ext.brokerserver.TestPolicy.createAfterYesterdayConstraint; -import static de.sovity.edc.ext.brokerserver.TestPolicy.createAfterYesterdayPolicyJson; -import static de.sovity.edc.ext.brokerserver.TestUtils.brokerServerClient; -import static de.sovity.edc.ext.brokerserver.TestUtils.createConfiguration; -import static org.assertj.core.api.Assertions.assertThat; - -@ApiTest -@ExtendWith(EdcExtension.class) -class DataOfferDetailApiTest { - - @RegisterExtension - private static final TestDatabase TEST_DATABASE = TestDatabaseFactory.getTestDatabase(); - - @BeforeEach - void setUp(EdcExtension extension) { - extension.setConfiguration(createConfiguration(TEST_DATABASE, Map.of( - ))); - } - - @Test - void testQueryDataOfferDetails() { - TEST_DATABASE.testTransaction(dsl -> { - var today = OffsetDateTime.now().withNano(0); - - var assetJsonLd1 = getAssetJsonLd( - UiAssetCreateRequest.builder() - .id("my-asset-1") - .title("My Asset 1") - .dataCategory("my-category") - .build() - ); - - var assetJsonLd2 = getAssetJsonLd( - UiAssetCreateRequest.builder() - .id("my-asset-2") - .title("My Asset 2") - .dataCategory("my-category-2") - .build() - ); - - createConnector(dsl, today, "https://my-connector/api/dsp"); - createDataOffer(dsl, today, "https://my-connector/api/dsp", assetJsonLd1); - - createDataOfferView(dsl, today, "https://my-connector/api/dsp", "my-asset-1"); - createDataOfferView(dsl, today, "https://my-connector/api/dsp", "my-asset-1"); - - createConnector(dsl, today, "https://my-connector2/api/dsp"); - createDataOffer(dsl, today, "https://my-connector2/api/dsp", assetJsonLd2); - - var actual = brokerServerClient().brokerServerApi().dataOfferDetailPage(new DataOfferDetailPageQuery("https://my-connector/api/dsp", "my-asset-1")); - assertThat(actual.getAssetId()).isEqualTo("my-asset-1"); - assertThat(actual.getConnectorEndpoint()).isEqualTo("https://my-connector/api/dsp"); - assertThat(actual.getConnectorOfflineSinceOrLastUpdatedAt()).isEqualTo(today); - assertThat(actual.getConnectorOnlineStatus()).isEqualTo(DataOfferDetailPageResult.ConnectorOnlineStatusEnum.ONLINE); - assertThat(actual.getCreatedAt()).isEqualTo(today.minusDays(5)); - assertThat(actual.getAsset().getAssetId()).isEqualTo("my-asset-1"); - assertThat(actual.getAsset().getDataCategory()).isEqualTo("my-category"); - assertThat(actual.getAsset().getTitle()).isEqualTo("My Asset 1"); - assertThat(actual.getUpdatedAt()).isEqualTo(today); - assertThat(actual.getContractOffers()).hasSize(1); - var contractOffer = actual.getContractOffers().get(0); - assertThat(contractOffer.getContractOfferId()).isEqualTo("my-contract-offer-1"); - assertEqualUsingJson(contractOffer.getContractPolicy().getConstraints().get(0), createAfterYesterdayConstraint()); - assertThat(contractOffer.getCreatedAt()).isEqualTo(today.minusDays(5)); - assertThat(contractOffer.getUpdatedAt()).isEqualTo(today); - assertThat(actual.getViewCount()).isEqualTo(2); - }); - } - - private void createConnector(DSLContext dsl, OffsetDateTime today, String connectorEndpoint) { - var connector = dsl.newRecord(Tables.CONNECTOR); - connector.setParticipantId("my-connector"); - connector.setEndpoint(connectorEndpoint); - connector.setOnlineStatus(ConnectorOnlineStatus.ONLINE); - connector.setCreatedAt(today.minusDays(1)); - connector.setLastRefreshAttemptAt(today); - connector.setLastSuccessfulRefreshAt(today); - connector.setDataOffersExceeded(ConnectorDataOffersExceeded.OK); - connector.setContractOffersExceeded(ConnectorContractOffersExceeded.OK); - connector.insert(); - } - - private void createDataOffer(DSLContext dsl, OffsetDateTime today, String connectorEndpoint, JsonObject assetJsonLd) { - var dataOffer = dsl.newRecord(Tables.DATA_OFFER); - setDataOfferAssetMetadata(dataOffer, assetJsonLd, "my-participant-id"); - dataOffer.setConnectorEndpoint(connectorEndpoint); - dataOffer.setCreatedAt(today.minusDays(5)); - dataOffer.setUpdatedAt(today); - dataOffer.insert(); - - var contractOffer = dsl.newRecord(Tables.CONTRACT_OFFER); - contractOffer.setContractOfferId("my-contract-offer-1"); - contractOffer.setConnectorEndpoint(connectorEndpoint); - contractOffer.setAssetId(dataOffer.getAssetId()); - contractOffer.setCreatedAt(today.minusDays(5)); - contractOffer.setUpdatedAt(today); - contractOffer.setPolicy(createAfterYesterdayPolicyJson()); - contractOffer.insert(); - } - - private static void createDataOfferView(DSLContext dsl, OffsetDateTime date, String connectorEndpoint, String assetId) { - var view = dsl.newRecord(Tables.DATA_OFFER_VIEW_COUNT); - view.setAssetId(assetId); - view.setConnectorEndpoint(connectorEndpoint); - view.setDate(date); - view.insert(); - } -} diff --git a/extensions/broker-server/src/test/java/de/sovity/edc/ext/brokerserver/services/api/DeleteConnectorsApiTest.java b/extensions/broker-server/src/test/java/de/sovity/edc/ext/brokerserver/services/api/DeleteConnectorsApiTest.java deleted file mode 100644 index fb6ba3aca..000000000 --- a/extensions/broker-server/src/test/java/de/sovity/edc/ext/brokerserver/services/api/DeleteConnectorsApiTest.java +++ /dev/null @@ -1,158 +0,0 @@ -/* - * Copyright (c) 2023 sovity GmbH - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - * - * Contributors: - * sovity GmbH - initial implementation - * - */ - -package de.sovity.edc.ext.brokerserver.services.api; - -import de.sovity.edc.ext.brokerserver.TestPolicy; -import de.sovity.edc.ext.brokerserver.TestUtils; -import de.sovity.edc.ext.brokerserver.client.BrokerServerClient; -import de.sovity.edc.ext.brokerserver.client.gen.model.ConnectorListEntry; -import de.sovity.edc.ext.brokerserver.client.gen.model.ConnectorPageQuery; -import de.sovity.edc.ext.brokerserver.db.TestDatabase; -import de.sovity.edc.ext.brokerserver.db.TestDatabaseFactory; -import de.sovity.edc.ext.brokerserver.db.jooq.Tables; -import de.sovity.edc.ext.brokerserver.db.jooq.enums.BrokerEventStatus; -import de.sovity.edc.ext.brokerserver.db.jooq.enums.BrokerEventType; -import de.sovity.edc.ext.brokerserver.db.jooq.enums.MeasurementErrorStatus; -import de.sovity.edc.ext.brokerserver.db.jooq.enums.MeasurementType; -import org.eclipse.edc.junit.annotations.ApiTest; -import org.eclipse.edc.junit.extensions.EdcExtension; -import org.jooq.DSLContext; -import org.jooq.Record; -import org.jooq.TableField; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.junit.jupiter.api.extension.RegisterExtension; - -import java.time.OffsetDateTime; -import java.util.Collection; -import java.util.List; -import java.util.Map; - -import static de.sovity.edc.ext.brokerserver.TestAsset.getAssetJsonLd; -import static de.sovity.edc.ext.brokerserver.TestAsset.setDataOfferAssetMetadata; -import static de.sovity.edc.ext.brokerserver.TestUtils.ADMIN_API_KEY; -import static de.sovity.edc.ext.brokerserver.TestUtils.brokerServerClient; -import static de.sovity.edc.ext.brokerserver.TestUtils.createConfiguration; -import static org.assertj.core.api.Assertions.assertThat; - -@ApiTest -@ExtendWith(EdcExtension.class) -class DeleteConnectorsApiTest { - BrokerServerClient client; - String firstConnector = "http://a"; - String otherConnector = "http://b"; - - @RegisterExtension - private static final TestDatabase TEST_DATABASE = TestDatabaseFactory.getTestDatabase(); - - @BeforeEach - void setUp(EdcExtension extension) { - extension.setConfiguration(createConfiguration(TEST_DATABASE, Map.of())); - client = brokerServerClient(); - } - - @Test - void testRemoveConnectors() { - TEST_DATABASE.testTransaction(dsl -> { - // arrange - setupConnectorData(dsl, firstConnector); - setupConnectorData(dsl, otherConnector); - - var connectorsBefore = List.of(firstConnector, otherConnector); - assertContainsEndpoints(dsl, Tables.BROKER_EXECUTION_TIME_MEASUREMENT.CONNECTOR_ENDPOINT, connectorsBefore); - assertContainsEndpoints(dsl, Tables.CONTRACT_OFFER.CONNECTOR_ENDPOINT, connectorsBefore); - assertContainsEndpoints(dsl, Tables.DATA_OFFER.CONNECTOR_ENDPOINT, connectorsBefore); - assertContainsEndpoints(dsl, Tables.DATA_OFFER_VIEW_COUNT.CONNECTOR_ENDPOINT, connectorsBefore); - assertContainsEndpoints(dsl, Tables.CONNECTOR.ENDPOINT, connectorsBefore); - - // act - client.brokerServerApi().deleteConnectors(ADMIN_API_KEY, List.of(firstConnector)); - - // assert - assertThat(client.brokerServerApi().connectorPage(new ConnectorPageQuery()).getConnectors()) - .extracting(ConnectorListEntry::getEndpoint) - .containsExactly(otherConnector); - - var connectorsAfter = List.of(otherConnector); - assertContainsEndpoints(dsl, Tables.BROKER_EXECUTION_TIME_MEASUREMENT.CONNECTOR_ENDPOINT, connectorsAfter); - assertContainsEndpoints(dsl, Tables.CONTRACT_OFFER.CONNECTOR_ENDPOINT, connectorsAfter); - assertContainsEndpoints(dsl, Tables.DATA_OFFER.CONNECTOR_ENDPOINT, connectorsAfter); - assertContainsEndpoints(dsl, Tables.DATA_OFFER_VIEW_COUNT.CONNECTOR_ENDPOINT, connectorsAfter); - assertContainsEndpoints(dsl, Tables.CONNECTOR.ENDPOINT, connectorsAfter); - }); - } - - private void assertContainsEndpoints( - DSLContext dsl, - TableField endpointField, - Collection expected - ) { - var actual = dsl.select(endpointField).from(endpointField.getTable()).fetchSet(endpointField); - assertThat(actual).containsExactlyInAnyOrderElementsOf(expected); - } - - public void setupConnectorData(DSLContext dsl, String endpoint) { - client.brokerServerApi().addConnectors(ADMIN_API_KEY, List.of(endpoint)); - - var assetId = "my-asset"; - - var dataOffer = dsl.newRecord(Tables.DATA_OFFER); - setDataOfferAssetMetadata(dataOffer, getAssetJsonLd("my-asset"), "my-participant-id"); - dataOffer.setConnectorEndpoint(endpoint); - dataOffer.setCreatedAt(OffsetDateTime.now()); - dataOffer.setUpdatedAt(OffsetDateTime.now()); - dataOffer.insert(); - - var contractOffer = dsl.newRecord(Tables.CONTRACT_OFFER); - contractOffer.setAssetId(assetId); - contractOffer.setConnectorEndpoint(endpoint); - contractOffer.setContractOfferId("my-asset-co"); - contractOffer.setCreatedAt(OffsetDateTime.now()); - contractOffer.setPolicy(TestPolicy.createAfterYesterdayPolicyJson()); - contractOffer.setUpdatedAt(OffsetDateTime.now()); - contractOffer.insert(); - - var logEntry = dsl.newRecord(Tables.BROKER_EVENT_LOG); - logEntry.setEvent(BrokerEventType.CONNECTOR_UPDATED); - logEntry.setUserMessage("Hello World!"); - logEntry.setAssetId(assetId); - logEntry.setCreatedAt(OffsetDateTime.now()); - logEntry.setConnectorEndpoint(endpoint); - logEntry.setEventStatus(BrokerEventStatus.OK); - logEntry.insert(); - - var measurement = dsl.newRecord(Tables.BROKER_EXECUTION_TIME_MEASUREMENT); - measurement.setConnectorEndpoint(endpoint); - measurement.setCreatedAt(OffsetDateTime.now()); - measurement.setDurationInMs(500L); - measurement.setErrorStatus(MeasurementErrorStatus.OK); - measurement.setType(MeasurementType.CONNECTOR_REFRESH); - measurement.insert(); - - var view = dsl.newRecord(Tables.DATA_OFFER_VIEW_COUNT); - view.setConnectorEndpoint(endpoint); - view.setAssetId(assetId); - view.setDate(OffsetDateTime.now()); - view.insert(); - } - - - @Test - void testDeleteWrongApiKey() { - TEST_DATABASE.testTransaction(dsl -> TestUtils.assertIs401(() -> - client.brokerServerApi().deleteConnectors("wrong-api-key", List.of()))); - } -} diff --git a/extensions/broker-server/src/test/java/de/sovity/edc/ext/brokerserver/services/logging/BrokerEventLoggerTest.java b/extensions/broker-server/src/test/java/de/sovity/edc/ext/brokerserver/services/logging/BrokerEventLoggerTest.java deleted file mode 100644 index eee984c6f..000000000 --- a/extensions/broker-server/src/test/java/de/sovity/edc/ext/brokerserver/services/logging/BrokerEventLoggerTest.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (c) 2023 sovity GmbH - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - * - * Contributors: - * sovity GmbH - initial API and implementation - * - */ - -package de.sovity.edc.ext.brokerserver.services.logging; - -import de.sovity.edc.ext.brokerserver.db.FlywayTestUtils; -import de.sovity.edc.ext.brokerserver.db.TestDatabase; -import de.sovity.edc.ext.brokerserver.db.TestDatabaseFactory; -import de.sovity.edc.ext.brokerserver.db.jooq.Tables; -import org.jooq.DSLContext; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.RegisterExtension; - -import java.util.Set; - -import static org.assertj.core.api.Assertions.assertThat; - -class BrokerEventLoggerTest { - @RegisterExtension - private static final TestDatabase TEST_DATABASE = TestDatabaseFactory.getTestDatabase(); - - @BeforeAll - static void setup() { - FlywayTestUtils.migrate(TEST_DATABASE); - } - - @Test - void testDataOfferWriter_allSortsOfUpdates() { - TEST_DATABASE.testTransaction(dsl -> { - var brokerEventLogger = new BrokerEventLogger(); - - // Test that insertions insert required fields and don't cause DB errors - String endpoint = "https://example.com/api/dsp"; - brokerEventLogger.logConnectorUpdated(dsl, endpoint, new ConnectorChangeTracker()); - brokerEventLogger.logConnectorOnline(dsl, endpoint); - brokerEventLogger.logConnectorOffline(dsl, endpoint, new BrokerEventErrorMessage("Message", "Stacktrace")); - brokerEventLogger.logConnectorUpdateContractOfferLimitExceeded(dsl, 10, endpoint); - brokerEventLogger.logConnectorUpdateContractOfferLimitOk(dsl, endpoint); - brokerEventLogger.logConnectorUpdateDataOfferLimitExceeded(dsl, 10, endpoint); - brokerEventLogger.logConnectorUpdateDataOfferLimitOk(dsl, endpoint); - brokerEventLogger.logConnectorsDeleted(dsl, Set.of(endpoint)); - - assertThat(numLogEntries(dsl)).isEqualTo(8); - }); - } - - private Integer numLogEntries(DSLContext dsl) { - return dsl.selectCount().from(Tables.BROKER_EVENT_LOG).fetchOne().component1(); - } -} diff --git a/extensions/broker-server/src/test/java/de/sovity/edc/ext/brokerserver/services/queue/ThreadPoolQueueTest.java b/extensions/broker-server/src/test/java/de/sovity/edc/ext/brokerserver/services/queue/ThreadPoolQueueTest.java deleted file mode 100644 index 55b2b1efa..000000000 --- a/extensions/broker-server/src/test/java/de/sovity/edc/ext/brokerserver/services/queue/ThreadPoolQueueTest.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (c) 2023 sovity GmbH - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - * - * Contributors: - * sovity GmbH - initial API and implementation - * - */ - -package de.sovity.edc.ext.brokerserver.services.queue; - -import org.junit.jupiter.api.Test; - -import java.util.ArrayList; - -import static org.assertj.core.api.Assertions.assertThat; - -class ThreadPoolQueueTest { - - - /** - * Regression against bug where the queue did not act like a queue. - */ - @Test - void testOrdering() { - Runnable noop = () -> { - }; - - var queue = new ThreadPoolTaskQueue(); - queue.add(new ThreadPoolTask(1, noop, "1.0")); - queue.add(new ThreadPoolTask(2, noop, "2.0")); - queue.add(new ThreadPoolTask(1, noop, "1.1")); - queue.add(new ThreadPoolTask(2, noop, "2.1")); - queue.add(new ThreadPoolTask(0, noop, "0.0")); - - var result = new ArrayList(); - queue.getQueue().drainTo(result); - - assertThat(result).extracting(ThreadPoolTask::getConnectorEndpoint) - .containsExactly("0.0", "1.0", "1.1", "2.0", "2.1"); - } -} diff --git a/extensions/broker-server/src/test/java/de/sovity/edc/ext/brokerserver/services/queue/ThreadPoolTest.java b/extensions/broker-server/src/test/java/de/sovity/edc/ext/brokerserver/services/queue/ThreadPoolTest.java deleted file mode 100644 index a45e23d0b..000000000 --- a/extensions/broker-server/src/test/java/de/sovity/edc/ext/brokerserver/services/queue/ThreadPoolTest.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright (c) 2023 sovity GmbH - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - * - * Contributors: - * sovity GmbH - initial API and implementation - * - */ - -package de.sovity.edc.ext.brokerserver.services.queue; - -import de.sovity.edc.ext.brokerserver.services.config.BrokerServerSettings; -import lombok.SneakyThrows; -import org.apache.commons.lang3.Validate; -import org.eclipse.edc.spi.monitor.Monitor; -import org.jetbrains.annotations.NotNull; -import org.junit.jupiter.api.Test; - -import java.util.ArrayList; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.locks.ReentrantLock; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -class ThreadPoolTest { - - /** - * Regression against bug where parallelity wasn't actually enabled - */ - @Test - @SneakyThrows - void testParallelExecution() { - ThreadPool threadPool = newThreadPool(2); - var latch = new CountDownLatch(2); - var result = new ArrayList(); - - var a = new BlockedRunnable(() -> { - result.add("a"); - latch.countDown(); - }); - var b = new BlockedRunnable(() -> { - result.add("b"); - latch.countDown(); - }); - - threadPool.enqueueConnectorRefreshTask(0, a, "a"); - threadPool.enqueueConnectorRefreshTask(0, b, "b"); - - b.release(); - Thread.sleep(250); // For some reason this is required - a.release(); - - Validate.isTrue(latch.await(500, TimeUnit.MILLISECONDS), "latch timed out"); - assertThat(result).containsExactly("b", "a"); - } - - - @NotNull - private ThreadPool newThreadPool(int numThreads) { - var monitor = mock(Monitor.class); - var brokerServerSettings = mock(BrokerServerSettings.class); - when(brokerServerSettings.getNumThreads()).thenReturn(numThreads); - var queue = new ThreadPoolTaskQueue(); - return new ThreadPool(queue, brokerServerSettings, monitor); - } - - private static class BlockedRunnable implements Runnable { - private static final Object GLOBAL_LOCK = new Object(); - private final Runnable runnable; - private final ReentrantLock lock = new ReentrantLock(); - - private BlockedRunnable(Runnable runnable) { - this.runnable = runnable; - lock.lock(); - } - - public void release() { - lock.unlock(); - } - - @Override - @SneakyThrows - public void run() { - var ok = lock.tryLock(10, TimeUnit.SECONDS); - Validate.isTrue(ok, "Program is stuck!"); - - // Prevent concurrency issues within the test code - synchronized (GLOBAL_LOCK) { - runnable.run(); - } - } - } -} diff --git a/extensions/broker-server/src/test/java/de/sovity/edc/ext/brokerserver/services/refreshing/ConnectorUpdaterTest.java b/extensions/broker-server/src/test/java/de/sovity/edc/ext/brokerserver/services/refreshing/ConnectorUpdaterTest.java deleted file mode 100644 index 3e8b82369..000000000 --- a/extensions/broker-server/src/test/java/de/sovity/edc/ext/brokerserver/services/refreshing/ConnectorUpdaterTest.java +++ /dev/null @@ -1,206 +0,0 @@ -/* - * Copyright (c) 2023 sovity GmbH - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - * - * Contributors: - * sovity GmbH - initial implementation - * - */ - -package de.sovity.edc.ext.brokerserver.services.refreshing; - -import de.sovity.edc.client.EdcClient; -import de.sovity.edc.client.gen.model.ContractDefinitionRequest; -import de.sovity.edc.client.gen.model.DataSourceType; -import de.sovity.edc.client.gen.model.PolicyDefinitionCreateRequest; -import de.sovity.edc.client.gen.model.UiAssetCreateRequest; -import de.sovity.edc.client.gen.model.UiCriterion; -import de.sovity.edc.client.gen.model.UiCriterionLiteral; -import de.sovity.edc.client.gen.model.UiCriterionLiteralType; -import de.sovity.edc.client.gen.model.UiCriterionOperator; -import de.sovity.edc.client.gen.model.UiDataSource; -import de.sovity.edc.client.gen.model.UiDataSourceHttpData; -import de.sovity.edc.ext.brokerserver.AssertionUtils; -import de.sovity.edc.ext.brokerserver.BrokerServerExtensionContext; -import de.sovity.edc.ext.brokerserver.TestUtils; -import de.sovity.edc.ext.brokerserver.client.BrokerServerClient; -import de.sovity.edc.ext.brokerserver.client.gen.model.CatalogPageQuery; -import de.sovity.edc.ext.brokerserver.client.gen.model.ConnectorListEntry; -import de.sovity.edc.ext.brokerserver.client.gen.model.ConnectorPageQuery; -import de.sovity.edc.ext.brokerserver.db.TestDatabase; -import de.sovity.edc.ext.brokerserver.db.TestDatabaseFactory; -import de.sovity.edc.ext.brokerserver.db.jooq.Tables; -import de.sovity.edc.utils.jsonld.vocab.Prop; -import org.eclipse.edc.junit.annotations.ApiTest; -import org.eclipse.edc.junit.extensions.EdcExtension; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.RegisterExtension; - -import java.time.OffsetDateTime; -import java.time.temporal.ChronoUnit; -import java.util.List; -import java.util.Map; - -import static de.sovity.edc.ext.brokerserver.TestPolicy.createAfterYesterdayConstraint; -import static de.sovity.edc.ext.brokerserver.TestPolicy.createAfterYesterdayPolicyEdcGen; -import static de.sovity.edc.ext.brokerserver.TestUtils.createConfiguration; -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.within; - -@ApiTest -class ConnectorUpdaterTest { - - @RegisterExtension - private static final TestDatabase TEST_DATABASE = TestDatabaseFactory.getTestDatabase(); - - @RegisterExtension - static EdcExtension consumerEdcContext = new EdcExtension(); - - private EdcClient providerClient; - - private BrokerServerClient brokerServerClient; - - @BeforeEach - void setUp(EdcExtension extension) { - extension.setConfiguration(createConfiguration(TEST_DATABASE, Map.of())); - - providerClient = EdcClient.builder() - .managementApiUrl(TestUtils.MANAGEMENT_ENDPOINT) - .managementApiKey(TestUtils.MANAGEMENT_API_KEY) - .build(); - - brokerServerClient = BrokerServerClient.builder() - .managementApiUrl(TestUtils.MANAGEMENT_ENDPOINT) - .managementApiKey(TestUtils.MANAGEMENT_API_KEY) - .build(); - } - - @Test - void testConnectorUpdate() { - TEST_DATABASE.testTransaction(dsl -> { - // arrange - var connectorUpdater = BrokerServerExtensionContext.instance.connectorUpdater(); - var connectorCreator = BrokerServerExtensionContext.instance.connectorCreator(); - String connectorEndpoint = TestUtils.PROTOCOL_ENDPOINT; - - var policyId = createPolicyDefinition(); - var assetId = createAsset(); - createContractDefinition(policyId, assetId); - connectorCreator.addConnector(dsl, connectorEndpoint); - - // act - connectorUpdater.updateConnector(connectorEndpoint); - var connectorPage = brokerServerClient.brokerServerApi().connectorPage(new ConnectorPageQuery()); - - // assert - var catalog = brokerServerClient.brokerServerApi().catalogPage(new CatalogPageQuery()); - assertThat(catalog.getDataOffers()).hasSize(1); - var dataOffer = catalog.getDataOffers().get(0); - assertThat(dataOffer.getContractOffers()).hasSize(1); - var contractOffer = dataOffer.getContractOffers().get(0); - var asset = dataOffer.getAsset(); - assertThat(asset.getAssetId()).isEqualTo(assetId); - assertThat(asset.getTitle()).isEqualTo("AssetName"); - assertThat(asset.getConnectorEndpoint()).isEqualTo(TestUtils.PROTOCOL_ENDPOINT); - assertThat(asset.getParticipantId()).isEqualTo(TestUtils.PARTICIPANT_ID); - assertThat(asset.getKeywords()).isEqualTo(List.of("keyword1", "keyword2")); - assertThat(asset.getDescription()).isEqualTo("AssetDescription"); - assertThat(asset.getVersion()).isEqualTo("1.0.0"); - assertThat(asset.getLanguage()).isEqualTo("en"); - assertThat(asset.getMediaType()).isEqualTo("application/json"); - assertThat(asset.getDataCategory()).isEqualTo("dataCategory"); - assertThat(asset.getDataSubcategory()).isEqualTo("dataSubcategory"); - assertThat(asset.getDataModel()).isEqualTo("dataModel"); - assertThat(asset.getGeoReferenceMethod()).isEqualTo("geoReferenceMethod"); - assertThat(asset.getTransportMode()).isEqualTo("transportMode"); - assertThat(asset.getLicenseUrl()).isEqualTo("https://license-url"); - assertThat(asset.getKeywords()).isEqualTo(List.of("keyword1", "keyword2")); - assertThat(asset.getCreatorOrganizationName()).isEqualTo("Unknown"); - assertThat(asset.getPublisherHomepage()).isEqualTo("publisherHomepage"); - assertThat(asset.getHttpDatasourceHintsProxyMethod()).isFalse(); - assertThat(asset.getHttpDatasourceHintsProxyPath()).isFalse(); - assertThat(asset.getHttpDatasourceHintsProxyQueryParams()).isFalse(); - assertThat(asset.getHttpDatasourceHintsProxyBody()).isFalse(); - assertThat(asset.getCustomJsonAsString()) - .isEqualTo("{\"a\":\"x\"}"); - assertThat(dataOffer.getAsset().getCustomJsonLdAsString()) - .isEqualTo("{\"http://unknown/b\":{\"http://unknown/c\":\"y\"}}"); - assertThat(dataOffer.getAsset().getPrivateCustomJsonAsString()).isNull(); - assertThat(dataOffer.getAsset().getPrivateCustomJsonLdAsString()).isEqualTo("{}"); - var policy = contractOffer.getContractPolicy(); - assertThat(policy.getConstraints()).hasSize(1); - AssertionUtils.assertEqualUsingJson(policy.getConstraints().get(0), createAfterYesterdayConstraint()); - - var connector = connectorPage.getConnectors().get(0); - assertThat(connector.getOnlineStatus()).isEqualTo(ConnectorListEntry.OnlineStatusEnum.ONLINE); - assertThat(connector.getParticipantId()).isEqualTo(TestUtils.PARTICIPANT_ID); - assertThat(connector.getOrganizationName()).isEqualTo("Unknown"); - assertThat(connector.getLastRefreshAttemptAt()).isCloseTo(OffsetDateTime.now(), within(1, ChronoUnit.SECONDS)); - - var connectorRecord = dsl.selectFrom(Tables.CONNECTOR).fetchOne(); - assertThat(connectorRecord.getMdsId()).isEqualTo("MDSL1234ZZ"); - }); - } - - private String createPolicyDefinition() { - var policyDefinition = PolicyDefinitionCreateRequest.builder() - .policyDefinitionId("policy-1") - .policy(createAfterYesterdayPolicyEdcGen()) - .build(); - - return providerClient.uiApi().createPolicyDefinition(policyDefinition).getId(); - } - - public void createContractDefinition(String policyId, String assetId) { - providerClient.uiApi().createContractDefinition(ContractDefinitionRequest.builder() - .contractDefinitionId("cd-1") - .accessPolicyId(policyId) - .contractPolicyId(policyId) - .assetSelector(List.of(UiCriterion.builder() - .operandLeft(Prop.Edc.ID) - .operator(UiCriterionOperator.EQ) - .operandRight(UiCriterionLiteral.builder() - .type(UiCriterionLiteralType.VALUE) - .value(assetId) - .build()) - .build())) - .build()); - } - - private String createAsset() { - var dataSource = UiDataSource.builder() - .type(DataSourceType.HTTP_DATA) - .httpData(UiDataSourceHttpData.builder() - .baseUrl("http://some.url") - .build()) - .build(); - - return providerClient.uiApi().createAsset(UiAssetCreateRequest.builder() - .id("asset-1") - .title("AssetName") - .description("AssetDescription") - .licenseUrl("https://license-url") - .version("1.0.0") - .language("en") - .mediaType("application/json") - .dataCategory("dataCategory") - .dataSubcategory("dataSubcategory") - .dataModel("dataModel") - .geoReferenceMethod("geoReferenceMethod") - .transportMode("transportMode") - .keywords(List.of("keyword1", "keyword2")) - .publisherHomepage("publisherHomepage") - .dataSource(dataSource) - .customJsonAsString("{\"a\":\"x\"}") - .customJsonLdAsString("{\"http://unknown/b\":{\"http://unknown/c\":\"y\"}}") - .privateCustomJsonAsString("{\"a-private\":\"x-private\"}") - .privateCustomJsonLdAsString("{\"http://unknown/b-private\":{\"http://unknown/c-private\":\"y-private\"}}") - .build()).getId(); - } -} diff --git a/extensions/broker-server/src/test/java/de/sovity/edc/ext/brokerserver/services/refreshing/offers/DataOfferWriterTestDydi.java b/extensions/broker-server/src/test/java/de/sovity/edc/ext/brokerserver/services/refreshing/offers/DataOfferWriterTestDydi.java deleted file mode 100644 index d44383937..000000000 --- a/extensions/broker-server/src/test/java/de/sovity/edc/ext/brokerserver/services/refreshing/offers/DataOfferWriterTestDydi.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (c) 2023 sovity GmbH - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - * - * Contributors: - * sovity GmbH - initial implementation - * - */ - -package de.sovity.edc.ext.brokerserver.services.refreshing.offers; - -import de.sovity.edc.ext.brokerserver.dao.ContractOfferQueries; -import de.sovity.edc.ext.brokerserver.dao.DataOfferQueries; -import de.sovity.edc.ext.brokerserver.services.config.BrokerServerSettings; -import lombok.Value; -import org.eclipse.edc.spi.system.configuration.Config; - -import static org.mockito.Mockito.mock; - -@Value -class DataOfferWriterTestDydi { - Config config = mock(Config.class); - BrokerServerSettings brokerServerSettings = mock(BrokerServerSettings.class); - DataOfferQueries dataOfferQueries = new DataOfferQueries(); - ContractOfferQueries contractOfferQueries = new ContractOfferQueries(); - ContractOfferRecordUpdater contractOfferRecordUpdater = new ContractOfferRecordUpdater(); - DataOfferRecordUpdater dataOfferRecordUpdater = new DataOfferRecordUpdater(); - DataOfferPatchBuilder dataOfferPatchBuilder = new DataOfferPatchBuilder( - contractOfferQueries, - dataOfferQueries, - dataOfferRecordUpdater, - contractOfferRecordUpdater - ); - DataOfferPatchApplier dataOfferPatchApplier = new DataOfferPatchApplier(); - DataOfferWriter dataOfferWriter = new DataOfferWriter(dataOfferPatchBuilder, dataOfferPatchApplier); -} diff --git a/extensions/broker-server/src/test/java/de/sovity/edc/ext/brokerserver/services/schedules/OfflineConnectorRemovalJobTest.java b/extensions/broker-server/src/test/java/de/sovity/edc/ext/brokerserver/services/schedules/OfflineConnectorRemovalJobTest.java deleted file mode 100644 index feb69efc4..000000000 --- a/extensions/broker-server/src/test/java/de/sovity/edc/ext/brokerserver/services/schedules/OfflineConnectorRemovalJobTest.java +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Copyright (c) 2023 sovity GmbH - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - * - * Contributors: - * sovity GmbH - initial API and implementation - * - */ - -package de.sovity.edc.ext.brokerserver.services.schedules; - -import de.sovity.edc.ext.brokerserver.dao.ConnectorQueries; -import de.sovity.edc.ext.brokerserver.db.FlywayTestUtils; -import de.sovity.edc.ext.brokerserver.db.TestDatabase; -import de.sovity.edc.ext.brokerserver.db.TestDatabaseFactory; -import de.sovity.edc.ext.brokerserver.db.jooq.enums.ConnectorContractOffersExceeded; -import de.sovity.edc.ext.brokerserver.db.jooq.enums.ConnectorDataOffersExceeded; -import de.sovity.edc.ext.brokerserver.db.jooq.enums.ConnectorOnlineStatus; -import de.sovity.edc.ext.brokerserver.services.ConnectorCleaner; -import de.sovity.edc.ext.brokerserver.services.ConnectorKiller; -import de.sovity.edc.ext.brokerserver.services.OfflineConnectorKiller; -import de.sovity.edc.ext.brokerserver.services.config.BrokerServerSettings; -import de.sovity.edc.ext.brokerserver.services.logging.BrokerEventLogger; -import org.jooq.DSLContext; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.RegisterExtension; - -import java.time.Duration; -import java.time.OffsetDateTime; - -import static de.sovity.edc.ext.brokerserver.db.jooq.tables.Connector.CONNECTOR; -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -class OfflineConnectorRemovalJobTest { - - @RegisterExtension - private static final TestDatabase TEST_DATABASE = TestDatabaseFactory.getTestDatabase(); - - BrokerServerSettings brokerServerSettings; - OfflineConnectorKiller offlineConnectorKiller; - - @BeforeAll - static void beforeAll() { - FlywayTestUtils.migrate(TEST_DATABASE); - } - - @BeforeEach - void beforeEach() { - brokerServerSettings = mock(BrokerServerSettings.class); - offlineConnectorKiller = new OfflineConnectorKiller( - brokerServerSettings, - new ConnectorQueries(), - new BrokerEventLogger(), - new ConnectorKiller(), - new ConnectorCleaner() - ); - } - - @Test - void test_offlineConnectorKiller_should_be_dead() { - TEST_DATABASE.testTransaction(dsl -> { - // arrange - when(brokerServerSettings.getKillOfflineConnectorsAfter()).thenReturn(Duration.ofDays(5)); - createConnector(dsl, 6); - - // act - offlineConnectorKiller.killIfOfflineTooLong(dsl); - - // assert - dsl.select().from(CONNECTOR).fetch().forEach(record -> { - assertThat(record.get(CONNECTOR.ENDPOINT)).isEqualTo("https://my-connector/api/dsp"); - assertThat(record.get(CONNECTOR.ONLINE_STATUS)).isEqualTo(ConnectorOnlineStatus.DEAD); - }); - }); - } - - @Test - void test_offlineConnectorKiller_should_not_be_dead() { - TEST_DATABASE.testTransaction(dsl -> { - // arrange - when(brokerServerSettings.getKillOfflineConnectorsAfter()).thenReturn(Duration.ofDays(5)); - createConnector(dsl, 2); - - // act - offlineConnectorKiller.killIfOfflineTooLong(dsl); - - // assert - dsl.select().from(CONNECTOR).fetch().forEach(record -> { - assertThat(record.get(CONNECTOR.ENDPOINT)).isEqualTo("https://my-connector/api/dsp"); - assertThat(record.get(CONNECTOR.ONLINE_STATUS)).isNotEqualTo(ConnectorOnlineStatus.DEAD); - }); - }); - } - - private static void createConnector(DSLContext dsl, int createdDaysAgo) { - dsl.insertInto(CONNECTOR) - .set(CONNECTOR.ENDPOINT, "https://my-connector/api/dsp") - .set(CONNECTOR.PARTICIPANT_ID, "my-connector") - .set(CONNECTOR.ONLINE_STATUS, ConnectorOnlineStatus.OFFLINE) - .set(CONNECTOR.LAST_SUCCESSFUL_REFRESH_AT, OffsetDateTime.now().minusDays(createdDaysAgo)) - .set(CONNECTOR.CREATED_AT, OffsetDateTime.now().minusDays(6)) - .set(CONNECTOR.DATA_OFFERS_EXCEEDED, ConnectorDataOffersExceeded.OK) - .set(CONNECTOR.CONTRACT_OFFERS_EXCEEDED, ConnectorContractOffersExceeded.OK).execute(); - } -} diff --git a/extensions/broker-server/src/test/java/de/sovity/edc/ext/brokerserver/utils/UrlUtilsTest.java b/extensions/broker-server/src/test/java/de/sovity/edc/ext/brokerserver/utils/UrlUtilsTest.java deleted file mode 100644 index 72a223007..000000000 --- a/extensions/broker-server/src/test/java/de/sovity/edc/ext/brokerserver/utils/UrlUtilsTest.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (c) 2023 sovity GmbH - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - * - * Contributors: - * sovity GmbH - initial API and implementation - * - */ - -package de.sovity.edc.ext.brokerserver.utils; - -import org.junit.jupiter.api.Test; - -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertTrue; - -class UrlUtilsTest { - @Test - void test_urlUtils() { - assertTrue(UrlUtils.isValidUrl("http://localhost:8080")); - assertTrue(UrlUtils.isValidUrl(" http://localhost:8080")); - - assertFalse(UrlUtils.isValidUrl("test")); - assertFalse(UrlUtils.isValidUrl("")); - assertFalse(UrlUtils.isValidUrl(" ")); - assertFalse(UrlUtils.isValidUrl(null)); - } -} diff --git a/extensions/catalog-crawler/README.md b/extensions/catalog-crawler/README.md new file mode 100644 index 000000000..28de136de --- /dev/null +++ b/extensions/catalog-crawler/README.md @@ -0,0 +1,39 @@ + +
+

+ + Logo + + +

EDC-Connector Extension:
Catalog Crawler

+ +

+ Report Bug + · + Request Feature +

+
+ +## About this Extension + +The catalog crawler is a deployment unit depending on an existing Authority Portal's database: + +- It periodically checks the Authority Portal's connector list for its environment. +- It crawls the given connectors in regular intervals. +- It writes the data offers and connector statuses back into the Authority Portal DB. +- Each Environment configured in the Authority Portal requires its own Catalog Crawler with credentials for that environment's DAPS. + +## Why does this component exist? + +The Authority Portal uses a non-EDC stack, and the EDC stack cannot handle multiple sources of authority at once. + +With the `DB -> UI` part of the broker having been moved to the Authority Portal, only the `Catalog -> DB` part remains as the Catalog Crawler, +as it requires Connector-to-Connector IAM within the given Dataspace. + +## License + +Apache License 2.0 - see [LICENSE](../../LICENSE) + +## Contact + +sovity GmbH - contact@sovity.de diff --git a/extensions/broker-server-postgres-flyway-jooq/build.gradle.kts b/extensions/catalog-crawler/catalog-crawler-db/build.gradle.kts similarity index 78% rename from extensions/broker-server-postgres-flyway-jooq/build.gradle.kts rename to extensions/catalog-crawler/catalog-crawler-db/build.gradle.kts index 9320b4c62..5c97eb9c4 100644 --- a/extensions/broker-server-postgres-flyway-jooq/build.gradle.kts +++ b/extensions/catalog-crawler/catalog-crawler-db/build.gradle.kts @@ -7,9 +7,8 @@ val jooqDbType = "org.jooq.meta.postgres.PostgresDatabase" val jdbcDriver = "org.postgresql.Driver" val postgresContainer = libs.versions.postgresDbImage.get() -val migrationsDir = "src/main/resources/db/migration" -val testDataDir = "src/main/resources/db/testdata" -val jooqTargetPackage = "de.sovity.edc.ext.brokerserver.db.jooq" +val migrationsDir = "src/main/resources/db-crawler/migration" +val jooqTargetPackage = "de.sovity.edc.ext.catalog.crawler.db.jooq" val jooqTargetSourceRoot = "build/generated/jooq" val jooqTargetDir = jooqTargetSourceRoot + "/" + jooqTargetPackage.replace(".", "/") @@ -34,20 +33,9 @@ dependencies { jooqGenerator(libs.postgres) flywayMigration(libs.postgres) - implementation(libs.hikari) - - annotationProcessor(libs.lombok) - compileOnly(libs.lombok) - implementation(libs.apache.commonsLang) - - implementation(libs.edc.coreSpi) // Adds Database-Related EDC-Extensions (EDC-SQL-Stores, JDBC-Driver, Pool and Transactions) implementation(libs.postgres) - - api(libs.flyway.core) - - testImplementation(libs.edc.junit) } sourceSets { @@ -71,20 +59,20 @@ fun isTestcontainersEnabled(): Boolean { fun jdbcUrl(): String { return container?.jdbcUrl - ?: System.getenv()[jdbcUrlEnvVarName] - ?: error("Need $jdbcUrlEnvVarName since $skipTestcontainersEnvVarName=true") + ?: System.getenv()[jdbcUrlEnvVarName] + ?: error("Need $jdbcUrlEnvVarName since $skipTestcontainersEnvVarName=true") } fun jdbcUser(): String { return container?.username - ?: System.getenv()[jdbcUserEnvVarName] - ?: error("Need $jdbcUserEnvVarName since $skipTestcontainersEnvVarName=true") + ?: System.getenv()[jdbcUserEnvVarName] + ?: error("Need $jdbcUserEnvVarName since $skipTestcontainersEnvVarName=true") } fun jdbcPassword(): String { return container?.password - ?: System.getenv()[jdbcPasswordEnvVarName] - ?: error("Need $jdbcPasswordEnvVarName since $skipTestcontainersEnvVarName=true") + ?: System.getenv()[jdbcPasswordEnvVarName] + ?: error("Need $jdbcPasswordEnvVarName since $skipTestcontainersEnvVarName=true") } @@ -107,8 +95,9 @@ flyway { cleanDisabled = false cleanOnValidationError = true baselineOnMigrate = true - locations = arrayOf("filesystem:${migrationsDir}", "filesystem:${testDataDir}") + locations = arrayOf("filesystem:${migrationsDir}") configurations = arrayOf("flywayMigration") + failOnMissingLocations = true mixed = true } @@ -159,15 +148,15 @@ jooq { tasks.withType { dependsOn.add("flywayMigrate") inputs.files(fileTree(migrationsDir)) - .withPropertyName("migrations") - .withPathSensitivity(PathSensitivity.RELATIVE) + .withPropertyName("migrations") + .withPathSensitivity(PathSensitivity.RELATIVE) allInputsDeclared.set(true) outputs.cacheIf { true } doFirst { require(this is nu.studer.gradle.jooq.JooqGenerate) val jooqConfiguration = nu.studer.gradle.jooq.JooqGenerate::class.java.getDeclaredField("jooqConfiguration") - .also { it.isAccessible = true }.get(this) as org.jooq.meta.jaxb.Configuration + .also { it.isAccessible = true }.get(this) as org.jooq.meta.jaxb.Configuration jooqConfiguration.jdbc.apply { url = jdbcUrl() @@ -180,7 +169,7 @@ tasks.withType { } } -group = libs.versions.sovityBrokerServerGroup.get() +group = libs.versions.sovityCatalogCrawlerGroup.get() publishing { publications { diff --git a/extensions/catalog-crawler/catalog-crawler-db/src/main/resources/db-crawler/migration-test-utils/V9999__Make_Columns_Nullable.sql b/extensions/catalog-crawler/catalog-crawler-db/src/main/resources/db-crawler/migration-test-utils/V9999__Make_Columns_Nullable.sql new file mode 100644 index 000000000..bc4f9fd8c --- /dev/null +++ b/extensions/catalog-crawler/catalog-crawler-db/src/main/resources/db-crawler/migration-test-utils/V9999__Make_Columns_Nullable.sql @@ -0,0 +1,25 @@ +do +$$ + declare + r record; + begin + for r in (select 'alter table "' || c.table_schema || '"."' || c.table_name || '" alter column "' || c.column_name || + '" drop not null;' as command + from information_schema.columns c + where c.table_schema not in ('pg_catalog', 'information_schema') -- exclude system schemas + and c.table_name in ('connector', 'organization', 'user') -- only selected AP tables + and c.is_nullable = 'NO' + and not exists (SELECT tc.constraint_type + FROM information_schema.table_constraints AS tc + JOIN information_schema.key_column_usage AS kcu + ON tc.constraint_name = kcu.constraint_name + AND tc.table_schema = kcu.table_schema + WHERE tc.table_schema = c.table_schema + and tc.table_name = c.table_name + AND kcu.column_name = c.column_name + AND tc.constraint_type = 'PRIMARY KEY')) -- exclude primary keys + loop + execute r.command; + end loop; + end +$$; diff --git a/extensions/catalog-crawler/catalog-crawler-db/src/main/resources/db-crawler/migration/V1__Initial_Schema.sql b/extensions/catalog-crawler/catalog-crawler-db/src/main/resources/db-crawler/migration/V1__Initial_Schema.sql new file mode 100644 index 000000000..bd792737a --- /dev/null +++ b/extensions/catalog-crawler/catalog-crawler-db/src/main/resources/db-crawler/migration/V1__Initial_Schema.sql @@ -0,0 +1,50 @@ +-- User +create type user_registration_status as enum ('FIRST_USER', 'CREATED', 'PENDING', 'APPROVED', 'REJECTED'); + +create table "user" +( + id text not null primary key, + organization_mds_id text, + registration_status user_registration_status not null +); + +-- Organization +create type organization_registration_status as enum ('PENDING', 'APPROVED', 'REJECTED'); + +create table "organization" +( + mds_id text not null primary key, + name text not null, + address text not null, + duns text not null, + url text not null, + security_email text not null, + created_by text not null, + registration_status organization_registration_status not null, + constraint fk_organization_created_by foreign key (created_by) references "user" (id) +); + +alter table "user" + add constraint fk_user_organization_id + foreign key (organization_mds_id) references "organization" (mds_id); + +-- Connector +create type connector_type as enum ('OWN', 'PROVIDED', 'CAAS'); + +create table "connector" +( + connector_id text not null primary key, + mds_id text not null, + provider_mds_id text not null, + type connector_type not null, + environment text not null, + client_id text not null, + name text not null, + location text not null, + url text not null, + created_by text not null, + created_at timestamp with time zone not null, + constraint fk_connector_organization_id foreign key (mds_id) references "organization" (mds_id), + constraint fk_connector_provider_id foreign key (provider_mds_id) references "organization" (mds_id), + constraint fk_connector_created_by foreign key (created_by) references "user" (id) +); diff --git a/extensions/catalog-crawler/catalog-crawler-db/src/main/resources/db-crawler/migration/V2__Schema_Extension.sql b/extensions/catalog-crawler/catalog-crawler-db/src/main/resources/db-crawler/migration/V2__Schema_Extension.sql new file mode 100644 index 000000000..599d64773 --- /dev/null +++ b/extensions/catalog-crawler/catalog-crawler-db/src/main/resources/db-crawler/migration/V2__Schema_Extension.sql @@ -0,0 +1,12 @@ +-- User +alter type user_registration_status add value 'INVITED' before 'CREATED'; +alter type user_registration_status add value 'DEACTIVATED' after 'REJECTED'; +alter type user_registration_status rename value 'APPROVED' to 'ACTIVE'; + +alter table "user" add column created_at timestamp with time zone not null default now(); + +-- Organization +alter type organization_registration_status add value 'INVITED' before 'PENDING'; +alter type organization_registration_status rename value 'APPROVED' to 'ACTIVE'; + +alter table "organization" add column created_at timestamp with time zone not null default now(); diff --git a/extensions/catalog-crawler/catalog-crawler-db/src/main/resources/db-crawler/migration/V3__Schema_Extension.sql b/extensions/catalog-crawler/catalog-crawler-db/src/main/resources/db-crawler/migration/V3__Schema_Extension.sql new file mode 100644 index 000000000..e9aafee70 --- /dev/null +++ b/extensions/catalog-crawler/catalog-crawler-db/src/main/resources/db-crawler/migration/V3__Schema_Extension.sql @@ -0,0 +1,28 @@ +-- User +ALTER TABLE "user" + ADD COLUMN email text, + ADD COLUMN first_name text, + ADD COLUMN last_name text, + ADD COLUMN job_title text, + ADD COLUMN phone text; + +-- Organization +ALTER TABLE "organization" + ADD COLUMN business_unit text, + ADD COLUMN billing_address text, + ADD COLUMN tax_id text, + ADD COLUMN commerce_register_number text, + ADD COLUMN commerce_register_location text, + ADD COLUMN main_contact_name text, + ADD COLUMN main_contact_email text, + ADD COLUMN main_contact_phone text, + ADD COLUMN tech_contact_name text, + ADD COLUMN tech_contact_email text, + ADD COLUMN tech_contact_phone text; + +UPDATE "organization" SET main_contact_email = security_email; + +ALTER TABLE "organization" + DROP COLUMN duns, + DROP COLUMN security_email; + diff --git a/extensions/catalog-crawler/catalog-crawler-db/src/main/resources/db-crawler/migration/V4__Schema_Extension.sql b/extensions/catalog-crawler/catalog-crawler-db/src/main/resources/db-crawler/migration/V4__Schema_Extension.sql new file mode 100644 index 000000000..bfe8162fa --- /dev/null +++ b/extensions/catalog-crawler/catalog-crawler-db/src/main/resources/db-crawler/migration/V4__Schema_Extension.sql @@ -0,0 +1,14 @@ +-- Components +create table "component" ( + id text primary key, + mds_id text not null, + name text not null, + homepage_url text, + endpoint_url text not null, + environment text not null, + client_id text not null, + created_by text not null, + created_at timestamp with time zone not null default now(), + constraint fk_component_created_by foreign key (created_by) references "user" (id), + constraint fk_component_organization_id foreign key (mds_id) references "organization" (mds_id) +); diff --git a/extensions/catalog-crawler/catalog-crawler-db/src/main/resources/db-crawler/migration/V5__Schema_Extension.sql b/extensions/catalog-crawler/catalog-crawler-db/src/main/resources/db-crawler/migration/V5__Schema_Extension.sql new file mode 100644 index 000000000..ec89fa6bb --- /dev/null +++ b/extensions/catalog-crawler/catalog-crawler-db/src/main/resources/db-crawler/migration/V5__Schema_Extension.sql @@ -0,0 +1,46 @@ +-- User +create type user_onboarding_type as enum ('INVITATION', 'SELF_REGISTRATION'); + +alter table "user" + add column onboarding_type user_onboarding_type, + add column invited_by text, + add constraint fk_invited_by foreign key (invited_by) references "user" (id); + +update "user" set onboarding_type = 'SELF_REGISTRATION' where onboarding_type is null; + +-- Connector +create type connector_broker_registration_status as enum ('REGISTERED', 'UNREGISTERED'); +create type caas_status as enum ('INIT', 'PROVISIONING', 'AWAITING_RUNNING', 'RUNNING', 'DEPROVISIONING', 'AWAITING_STOPPED', 'STOPPED', 'ERROR', 'NOT_FOUND'); + +alter table "connector" + add column broker_registration_status connector_broker_registration_status not null default 'UNREGISTERED', + add column management_url text, + add column endpoint_url text, + add column jwks_url text, + add column caas_status caas_status, + alter column provider_mds_id drop not null, + alter column url drop not null; + +alter table "connector" + rename column url to frontend_url; + +-- Fallback in case someone tries to migrate from 0.x to 1.0 +update "connector" +set management_url = frontend_url || '/api/management' where management_url is null; + +update "connector" +set endpoint_url = frontend_url || '/api/dsp' where endpoint_url is null; + +-- Organization id type +create type organization_legal_id_type as enum ('TAX_ID', 'COMMERCE_REGISTER_INFO'); +alter table "organization" + add column legal_id_type organization_legal_id_type, + add column description text, + alter column address drop not null, + alter column url drop not null; +update organization set legal_id_type = 'TAX_ID' where organization.tax_id is not null; +update organization set legal_id_type = 'COMMERCE_REGISTER_INFO' where organization.commerce_register_number is not null and tax_id is null; + +-- New registration flow +alter type user_registration_status add value 'ONBOARDING' after 'CREATED'; +alter type organization_registration_status add value 'ONBOARDING' after 'INVITED'; diff --git a/extensions/catalog-crawler/catalog-crawler-db/src/main/resources/db-crawler/migration/V6__AP_Release_1_0_0.sql b/extensions/catalog-crawler/catalog-crawler-db/src/main/resources/db-crawler/migration/V6__AP_Release_1_0_0.sql new file mode 100644 index 000000000..1aef70850 --- /dev/null +++ b/extensions/catalog-crawler/catalog-crawler-db/src/main/resources/db-crawler/migration/V6__AP_Release_1_0_0.sql @@ -0,0 +1,39 @@ +-- Edit Enum: Remove UserRegistrationStatus.CREATED, UserRegistrationStatus.FIRST_USER +delete +from "user" +where registration_status = 'CREATED' + or registration_status = 'FIRST_USER'; + +create type tmp_enum AS ENUM ('INVITED', 'ONBOARDING', 'PENDING', 'ACTIVE', 'REJECTED', 'DEACTIVATED'); + +alter table "user" + alter column registration_status type tmp_enum + using (registration_status::text::tmp_enum); + +drop type user_registration_status; + +alter type tmp_enum rename to user_registration_status; + +-- Component & Connector online status +create type component_type as enum ('BROKER', 'DAPS', 'LOGGING_HOUSE'); +create type component_online_status as enum ('UP', 'DOWN', 'PENDING', 'MAINTENANCE'); +create table "component_downtimes" +( + component component_type not null, + status component_online_status not null, + environment text not null, + time_stamp timestamp with time zone not null, + primary key (component, environment, time_stamp) +); +create index component_downtimes_time_stamp_index on "component_downtimes" (time_stamp); + +create type connector_uptime_status as enum ('UP', 'DOWN', 'DEAD'); +create table "connector_downtimes" +( + connector_id text not null, + status connector_uptime_status not null, + environment text not null, + time_stamp timestamp with time zone not null, + primary key (connector_id, time_stamp) +); +create index connector_downtimes_time_stamp_index on "connector_downtimes" (time_stamp); diff --git a/extensions/catalog-crawler/catalog-crawler-db/src/main/resources/db-crawler/migration/V7__Schema_Extension.sql b/extensions/catalog-crawler/catalog-crawler-db/src/main/resources/db-crawler/migration/V7__Schema_Extension.sql new file mode 100644 index 000000000..0818d9c03 --- /dev/null +++ b/extensions/catalog-crawler/catalog-crawler-db/src/main/resources/db-crawler/migration/V7__Schema_Extension.sql @@ -0,0 +1,3 @@ +-- Organization +alter table "organization" + add column industry text; diff --git a/extensions/catalog-crawler/catalog-crawler-db/src/main/resources/db-crawler/migration/V8__Schema_Extension.sql b/extensions/catalog-crawler/catalog-crawler-db/src/main/resources/db-crawler/migration/V8__Schema_Extension.sql new file mode 100644 index 000000000..4a9e7b810 --- /dev/null +++ b/extensions/catalog-crawler/catalog-crawler-db/src/main/resources/db-crawler/migration/V8__Schema_Extension.sql @@ -0,0 +1,4 @@ +-- Fix invalid DB state +delete +from "user" +where organization_mds_id is null; diff --git a/extensions/catalog-crawler/catalog-crawler-db/src/main/resources/db-crawler/migration/V9__Broker_Integration.sql b/extensions/catalog-crawler/catalog-crawler-db/src/main/resources/db-crawler/migration/V9__Broker_Integration.sql new file mode 100644 index 000000000..a93987578 --- /dev/null +++ b/extensions/catalog-crawler/catalog-crawler-db/src/main/resources/db-crawler/migration/V9__Broker_Integration.sql @@ -0,0 +1,107 @@ +create collation if not exists alphanumeric_with_natural_sort (provider = icu, locale = 'en-u-kn-true'); + +-- Creating missing enums +create type connector_online_status as enum ('ONLINE', 'OFFLINE', 'DEAD'); +create type connector_data_offers_exceeded as enum ('OK', 'EXCEEDED'); +create type connector_contract_offers_exceeded as enum ('OK', 'EXCEEDED'); +create type measurement_type as enum ('CONNECTOR_REFRESH'); +create type measurement_error_status as enum ('ERROR', 'OK'); +create type crawler_event_status as enum ('OK', 'ERROR'); +create type crawler_event_type as enum ( + 'CONNECTOR_UPDATED', + 'CONNECTOR_STATUS_CHANGE_ONLINE', + 'CONNECTOR_STATUS_CHANGE_OFFLINE', + 'CONNECTOR_STATUS_CHANGE_FORCE_DELETED', + 'CONTRACT_OFFER_UPDATED', + 'CONTRACT_OFFER_CLICK', + 'CONNECTOR_DATA_OFFER_LIMIT_EXCEEDED', + 'CONNECTOR_DATA_OFFER_LIMIT_OK', + 'CONNECTOR_CONTRACT_OFFER_LIMIT_EXCEEDED', + 'CONNECTOR_CONTRACT_OFFER_LIMIT_OK', + 'CONNECTOR_KILLED_DUE_TO_OFFLINE_FOR_TOO_LONG', + 'CONNECTOR_DELETED'); + +-- Adding missing columns from the crawler to the connector table +alter table connector + add column last_refresh_attempt_at timestamp with time zone, + add column last_successful_refresh_at timestamp with time zone, + add column online_status connector_online_status not null default 'OFFLINE', + add column data_offers_exceeded connector_data_offers_exceeded not null default 'OK', + add column contract_offers_exceeded connector_contract_offers_exceeded not null default 'OK'; + +-- Data offers, additionally keyed by env ID +create table data_offer +( + connector_id text not null, + asset_id text not null, + ui_asset_json jsonb not null, + created_at timestamp with time zone not null, + updated_at timestamp with time zone, + asset_title text collate alphanumeric_with_natural_sort not null, + description_no_markdown text not null default ''::text, + short_description_no_markdown text not null default ''::text, + data_category text not null default ''::text, + data_subcategory text not null default ''::text, + data_model text not null default ''::text, + transport_mode text not null default ''::text, + geo_reference_method text not null default ''::text, + keywords text[] not null default '{}'::text[], + keywords_comma_joined text not null default ''::text, + version text not null default ''::text, + primary key (connector_id, asset_id), + constraint data_offer_connector_fkey foreign key (connector_id) references connector (connector_id) +); + +-- Data offer Viewcount +create table data_offer_view_count +( + id serial primary key, + connector_id text not null, + asset_id text not null, + date timestamp with time zone not null +); + +create index data_offer_view_count_speedup on data_offer_view_count (connector_id, asset_id); + +-- Contract offers, additionally keyed by env ID +create table contract_offer +( + contract_offer_id text not null, + connector_id text not null, + asset_id text not null, + ui_policy_json jsonb not null, + created_at timestamp with time zone not null, + updated_at timestamp with time zone, + primary key (contract_offer_id, connector_id, asset_id), + constraint contract_offer_connector_fkey foreign key (connector_id) references connector (connector_id), + constraint contract_offer_data_offer_fkey foreign key (connector_id, asset_id) references data_offer (connector_id, asset_id) +); + +-- Event Log +create table crawler_event_log +( + id uuid not null primary key, + environment text not null, + created_at timestamp with time zone not null, + user_message text not null, + event crawler_event_type not null, + event_status crawler_event_status not null, + connector_id text, + asset_id text, + error_stack text +); +create index crawler_event_log_speedup on crawler_event_log (environment, connector_id, asset_id, event_status); + +-- Crawling exec time measurements +create table crawler_execution_time_measurement +( + id uuid not null primary key, + environment text not null, + connector_id text not null, + created_at timestamp with time zone not null, + duration_in_ms bigint not null, + type measurement_type not null, + error_status measurement_error_status not null +); + + diff --git a/extensions/catalog-crawler/catalog-crawler-e2e-test/build.gradle.kts b/extensions/catalog-crawler/catalog-crawler-e2e-test/build.gradle.kts new file mode 100644 index 000000000..6cc40c67d --- /dev/null +++ b/extensions/catalog-crawler/catalog-crawler-e2e-test/build.gradle.kts @@ -0,0 +1,44 @@ +plugins { + `java-library` +} + +dependencies { + compileOnly(project(":launchers:connectors:catalog-crawler-dev")) + compileOnly(project(":launchers:connectors:sovity-dev")) + + testAnnotationProcessor(libs.lombok) + testCompileOnly(libs.lombok) + + testImplementation(project(":utils:versions")) + testImplementation(project(":utils:test-connector-remote")) + testImplementation(project(":utils:json-and-jsonld-utils")) + testImplementation(project(":extensions:catalog-crawler:catalog-crawler-db")) + testImplementation(project(":extensions:wrapper:clients:java-client")) + testImplementation(project(":extensions:catalog-crawler:catalog-crawler")) + + testImplementation(libs.assertj.core) + testImplementation(libs.mockito.core) + testImplementation(libs.mockito.inline) + testImplementation(libs.edc.junit) + testImplementation(libs.restAssured.restAssured) + testImplementation(libs.testcontainers.testcontainers) + testImplementation(libs.flyway.core) + testImplementation(libs.testcontainers.junitJupiter) + testImplementation(libs.testcontainers.postgresql) + testImplementation(libs.junit.api) + testImplementation(libs.jsonAssert) + testRuntimeOnly(libs.junit.engine) +} + +tasks.getByName("test") { + useJUnitPlatform() + maxParallelForks = 1 +} + +publishing { + publications { + create(project.name) { + from(components["java"]) + } + } +} diff --git a/extensions/catalog-crawler/catalog-crawler-e2e-test/src/test/java/de/sovity/edc/ext/catalog/crawler/CrawlerE2eTest.java b/extensions/catalog-crawler/catalog-crawler-e2e-test/src/test/java/de/sovity/edc/ext/catalog/crawler/CrawlerE2eTest.java new file mode 100644 index 000000000..3fedd0961 --- /dev/null +++ b/extensions/catalog-crawler/catalog-crawler-e2e-test/src/test/java/de/sovity/edc/ext/catalog/crawler/CrawlerE2eTest.java @@ -0,0 +1,234 @@ +/* + * Copyright (c) 2023 sovity GmbH + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + * + * Contributors: + * sovity GmbH - init + */ + +package de.sovity.edc.ext.catalog.crawler; + +import de.sovity.edc.client.EdcClient; +import de.sovity.edc.client.gen.model.ContractDefinitionRequest; +import de.sovity.edc.client.gen.model.DataSourceType; +import de.sovity.edc.client.gen.model.OperatorDto; +import de.sovity.edc.client.gen.model.PolicyDefinitionCreateRequest; +import de.sovity.edc.client.gen.model.UiAssetCreateRequest; +import de.sovity.edc.client.gen.model.UiCriterion; +import de.sovity.edc.client.gen.model.UiCriterionLiteral; +import de.sovity.edc.client.gen.model.UiCriterionLiteralType; +import de.sovity.edc.client.gen.model.UiCriterionOperator; +import de.sovity.edc.client.gen.model.UiDataSource; +import de.sovity.edc.client.gen.model.UiDataSourceHttpData; +import de.sovity.edc.client.gen.model.UiPolicyConstraint; +import de.sovity.edc.client.gen.model.UiPolicyCreateRequest; +import de.sovity.edc.client.gen.model.UiPolicyLiteral; +import de.sovity.edc.client.gen.model.UiPolicyLiteralType; +import de.sovity.edc.ext.catalog.crawler.dao.connectors.ConnectorRef; +import de.sovity.edc.ext.catalog.crawler.db.jooq.Tables; +import de.sovity.edc.ext.catalog.crawler.db.jooq.enums.ConnectorOnlineStatus; +import de.sovity.edc.ext.catalog.crawler.utils.CrawlerDbAccess; +import de.sovity.edc.ext.catalog.crawler.utils.TestData; +import de.sovity.edc.extension.e2e.connector.config.ConnectorConfig; +import de.sovity.edc.extension.e2e.db.EdcRuntimeExtensionWithTestDatabase; +import de.sovity.edc.utils.jsonld.vocab.Prop; +import org.awaitility.Awaitility; +import org.awaitility.core.ThrowingRunnable; +import org.jooq.DSLContext; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import java.time.OffsetDateTime; +import java.util.HashMap; +import java.util.List; +import java.util.concurrent.TimeUnit; +import java.util.function.Consumer; + +import static de.sovity.edc.extension.e2e.connector.config.ConnectorConfigFactory.forTestDatabase; +import static de.sovity.edc.extension.e2e.connector.config.ConnectorConfigFactory.getFreePortRange; +import static de.sovity.edc.extension.e2e.connector.config.api.EdcApiConfigFactory.configureApi; +import static org.assertj.core.api.Assertions.assertThat; + +class CrawlerE2eTest { + private static ConnectorConfig connectorConfig; + private static EdcClient connectorClient; + + @RegisterExtension + static EdcRuntimeExtensionWithTestDatabase providerExtension = new EdcRuntimeExtensionWithTestDatabase( + ":launchers:connectors:sovity-dev", + "provider", + testDatabase -> { + connectorConfig = forTestDatabase("MDSL1234XX.C1234XX", testDatabase); + connectorClient = EdcClient.builder() + .managementApiUrl(connectorConfig.getManagementEndpoint().getUri().toString()) + .managementApiKey(connectorConfig.getProperties().get("edc.api.auth.key")) + .build(); + return connectorConfig.getProperties(); + } + ); + + @RegisterExtension + static EdcRuntimeExtensionWithTestDatabase crawlerExtension = new EdcRuntimeExtensionWithTestDatabase( + ":launchers:connectors:catalog-crawler-dev", + "crawler", + testDatabase -> { + var firstPort = getFreePortRange(5); + + var props = new HashMap(); + props.put("edc.participant.id", "broker"); + props.put(CrawlerExtension.EXTENSION_ENABLED, "true"); + props.put(CrawlerExtension.ENVIRONMENT_ID, "test"); + props.put(CrawlerExtension.JDBC_URL, testDatabase.getJdbcCredentials().jdbcUrl()); + props.put(CrawlerExtension.JDBC_USER, testDatabase.getJdbcCredentials().jdbcUser()); + props.put(CrawlerExtension.JDBC_PASSWORD, testDatabase.getJdbcCredentials().jdbcPassword()); + props.put(CrawlerExtension.DB_CONNECTION_POOL_SIZE, "30"); + props.put(CrawlerExtension.DB_CONNECTION_TIMEOUT_IN_MS, "1000"); + props.put(CrawlerExtension.DB_MIGRATE, "true"); + props.put(CrawlerExtension.DB_CLEAN, "true"); + props.put(CrawlerExtension.DB_CLEAN_ENABLED, "true"); + props.put(CrawlerExtension.DB_ADDITIONAL_FLYWAY_MIGRATION_LOCATIONS, "classpath:db-crawler/migration-test-utils"); + props.put(CrawlerExtension.NUM_THREADS, "2"); + props.put(CrawlerExtension.MAX_DATA_OFFERS_PER_CONNECTOR, "100"); + props.put(CrawlerExtension.MAX_CONTRACT_OFFERS_PER_DATA_OFFER, "100"); + props.putAll(configureApi(firstPort, "managementApiKey").getProperties()); + + var everySeconds = "* * * * * ?"; + props.put(CrawlerExtension.CRON_ONLINE_CONNECTOR_REFRESH, everySeconds); + props.put(CrawlerExtension.CRON_OFFLINE_CONNECTOR_REFRESH, everySeconds); + props.put(CrawlerExtension.CRON_DEAD_CONNECTOR_REFRESH, everySeconds); + props.put(CrawlerExtension.SCHEDULED_KILL_OFFLINE_CONNECTORS, everySeconds); + props.put(CrawlerExtension.KILL_OFFLINE_CONNECTORS_AFTER, "P1D"); + + return props; + } + ); + + private final String dataOfferId = "my-data-offer"; + + @Test + void crawlSingleDataOffer() { + // arrange + createPolicy(); + createAsset(); + createContractDefinition(); + + var connectorRef = new ConnectorRef( + "MDSL1234XX.C1234XX", + "test", + "My Org", + "MDSL1234XX", + connectorConfig.getProtocolEndpoint().getUri().toString() + ); + + crawlerTransaction(dsl -> { + TestData.insertConnector(dsl, connectorRef, connectorRecord -> { + connectorRecord.setOnlineStatus(ConnectorOnlineStatus.OFFLINE); + connectorRecord.setCreatedAt(OffsetDateTime.now()); + }); + }); + + // act / await crawl + Awaitility.await().atMost(10, TimeUnit.SECONDS) + .untilAsserted(mapExceptionsToAssertionError(() -> + crawlerTransaction(dsl -> assertDataOfferInCatalog(dsl, connectorRef)))); + } + + private void assertDataOfferInCatalog(DSLContext dsl, ConnectorRef connectorRef) { + var c = Tables.CONNECTOR; + var connector = dsl.fetchOne(c, c.CONNECTOR_ID.eq(connectorRef.getConnectorId())); + assertThat(connector).isNotNull(); + assertThat(connector.getOnlineStatus()).isEqualTo(ConnectorOnlineStatus.ONLINE); + + var d = Tables.DATA_OFFER; + var dataOffers = dsl.fetch(d, d.CONNECTOR_ID.eq(connectorRef.getConnectorId())); + assertThat(dataOffers).hasSize(1); + assertThat(dataOffers.get(0).getAssetId()).isEqualTo(dataOfferId); + assertThat(dataOffers.get(0).getAssetTitle()).isEqualTo("My Data Offer"); + } + + private void createAsset() { + var asset = UiAssetCreateRequest.builder() + .id(dataOfferId) + .title("My Data Offer") + .description("Example Data Offer.") + .version("2023-11") + .language("EN") + .publisherHomepage("https://my-department.my-org.com/my-data-offer") + .licenseUrl("https://my-department.my-org.com/my-data-offer#license") + .dataSource(UiDataSource.builder() + .type(DataSourceType.HTTP_DATA) + .httpData(UiDataSourceHttpData.builder() + .baseUrl("http://0.0.0.0") + .build()) + .build()) + .build(); + + connectorClient.uiApi().createAsset(asset); + } + + private void createPolicy() { + var afterYesterday = UiPolicyConstraint.builder() + .left("POLICY_EVALUATION_TIME") + .operator(OperatorDto.GT) + .right(UiPolicyLiteral.builder() + .type(UiPolicyLiteralType.STRING) + .value(OffsetDateTime.now().minusDays(1).toString()) + .build()) + .build(); + + var beforeTomorrow = UiPolicyConstraint.builder() + .left("POLICY_EVALUATION_TIME") + .operator(OperatorDto.LT) + .right(UiPolicyLiteral.builder() + .type(UiPolicyLiteralType.STRING) + .value(OffsetDateTime.now().plusDays(1).toString()) + .build()) + .build(); + + var policyDefinition = PolicyDefinitionCreateRequest.builder() + .policyDefinitionId(dataOfferId) + .policy(UiPolicyCreateRequest.builder() + .constraints(List.of(afterYesterday, beforeTomorrow)) + .build()) + .build(); + + connectorClient.uiApi().createPolicyDefinition(policyDefinition); + } + + private void createContractDefinition() { + var contractDefinition = ContractDefinitionRequest.builder() + .contractDefinitionId(dataOfferId) + .accessPolicyId(dataOfferId) + .contractPolicyId(dataOfferId) + .assetSelector(List.of(UiCriterion.builder() + .operandLeft(Prop.Edc.ID) + .operator(UiCriterionOperator.EQ) + .operandRight(UiCriterionLiteral.builder() + .type(UiCriterionLiteralType.VALUE) + .value(dataOfferId) + .build()) + .build())) + .build(); + + connectorClient.uiApi().createContractDefinition(contractDefinition); + } + + private void crawlerTransaction(Consumer withDsl) { + CrawlerDbAccess.transaction(crawlerExtension.getTestDatabase(), withDsl); + } + + private ThrowingRunnable mapExceptionsToAssertionError(ThrowingRunnable runnable) { + return () -> { + try { + runnable.run(); + } catch (Exception e) { + throw new AssertionError(e); + } + }; + } +} diff --git a/extensions/catalog-crawler/catalog-crawler-e2e-test/src/test/java/de/sovity/edc/ext/catalog/crawler/utils/CrawlerDbAccess.java b/extensions/catalog-crawler/catalog-crawler-e2e-test/src/test/java/de/sovity/edc/ext/catalog/crawler/utils/CrawlerDbAccess.java new file mode 100644 index 000000000..3dd2751db --- /dev/null +++ b/extensions/catalog-crawler/catalog-crawler-e2e-test/src/test/java/de/sovity/edc/ext/catalog/crawler/utils/CrawlerDbAccess.java @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2023 sovity GmbH + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + * + * Contributors: + * sovity GmbH - initial implementation + * + */ + +package de.sovity.edc.ext.catalog.crawler.utils; + +import de.sovity.edc.extension.e2e.db.TestDatabase; +import lombok.experimental.UtilityClass; +import org.jooq.DSLContext; +import org.jooq.impl.DSL; + +import java.util.function.Consumer; + +@UtilityClass +public class CrawlerDbAccess { + + public static void transaction(TestDatabase testDatabase, Consumer consumer) { + var credentials = testDatabase.getJdbcCredentials(); + try (var dslContext = DSL.using(credentials.jdbcUrl(), credentials.jdbcUser(), credentials.jdbcPassword())) { + dslContext.transaction(configuration -> { + var dsl = DSL.using(configuration); + consumer.accept(dsl); + }); + } + } +} diff --git a/extensions/catalog-crawler/catalog-crawler-e2e-test/src/test/java/de/sovity/edc/ext/catalog/crawler/utils/TestData.java b/extensions/catalog-crawler/catalog-crawler-e2e-test/src/test/java/de/sovity/edc/ext/catalog/crawler/utils/TestData.java new file mode 100644 index 000000000..77e056a98 --- /dev/null +++ b/extensions/catalog-crawler/catalog-crawler-e2e-test/src/test/java/de/sovity/edc/ext/catalog/crawler/utils/TestData.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2023 sovity GmbH + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + * + * Contributors: + * sovity GmbH - initial implementation + * + */ + +package de.sovity.edc.ext.catalog.crawler.utils; + +import de.sovity.edc.ext.catalog.crawler.dao.connectors.ConnectorRef; +import de.sovity.edc.ext.catalog.crawler.db.jooq.Tables; +import de.sovity.edc.ext.catalog.crawler.db.jooq.enums.ConnectorContractOffersExceeded; +import de.sovity.edc.ext.catalog.crawler.db.jooq.enums.ConnectorDataOffersExceeded; +import de.sovity.edc.ext.catalog.crawler.db.jooq.enums.ConnectorOnlineStatus; +import de.sovity.edc.ext.catalog.crawler.db.jooq.tables.records.ConnectorRecord; +import lombok.experimental.UtilityClass; +import org.jooq.DSLContext; + +import java.time.OffsetDateTime; +import java.util.function.Consumer; + +@UtilityClass +public class TestData { + + public static void insertConnector( + DSLContext dsl, + ConnectorRef connectorRef, + Consumer applier + ) { + var organization = dsl.newRecord(Tables.ORGANIZATION); + organization.setMdsId(connectorRef.getOrganizationId()); + organization.setName(connectorRef.getOrganizationLegalName()); + organization.insert(); + + var connector = dsl.newRecord(Tables.CONNECTOR); + connector.setEnvironment(connectorRef.getEnvironmentId()); + connector.setMdsId(connectorRef.getOrganizationId()); + connector.setConnectorId(connectorRef.getConnectorId()); + connector.setName(connectorRef.getConnectorId() + " Name"); + connector.setEndpointUrl(connectorRef.getEndpoint()); + connector.setOnlineStatus(ConnectorOnlineStatus.OFFLINE); + connector.setLastRefreshAttemptAt(null); + connector.setLastSuccessfulRefreshAt(null); + connector.setCreatedAt(OffsetDateTime.now()); + connector.setDataOffersExceeded(ConnectorDataOffersExceeded.OK); + connector.setContractOffersExceeded(ConnectorContractOffersExceeded.OK); + applier.accept(connector); + connector.insert(); + } +} diff --git a/extensions/broker-server/src/test/resources/logging.properties b/extensions/catalog-crawler/catalog-crawler-e2e-test/src/test/resources/logging.properties similarity index 88% rename from extensions/broker-server/src/test/resources/logging.properties rename to extensions/catalog-crawler/catalog-crawler-e2e-test/src/test/resources/logging.properties index d2212b2a2..471bd20d6 100644 --- a/extensions/broker-server/src/test/resources/logging.properties +++ b/extensions/catalog-crawler/catalog-crawler-e2e-test/src/test/resources/logging.properties @@ -3,4 +3,4 @@ org.eclipse.edc.level=ALL handlers=java.util.logging.ConsoleHandler java.util.logging.ConsoleHandler.formatter=java.util.logging.SimpleFormatter java.util.logging.ConsoleHandler.level=ALL -java.util.logging.SimpleFormatter.format=[%1$tY-%1$tm-%1$td %1$tH:%1$tM:%1$tS] [%4$-7s] %5$s%6$s%n \ No newline at end of file +java.util.logging.SimpleFormatter.format=[%1$tY-%1$tm-%1$td %1$tH:%1$tM:%1$tS] [%4$-7s] %5$s%6$s%n diff --git a/extensions/catalog-crawler/catalog-crawler-launcher-base/build.gradle.kts b/extensions/catalog-crawler/catalog-crawler-launcher-base/build.gradle.kts new file mode 100644 index 000000000..2c376a085 --- /dev/null +++ b/extensions/catalog-crawler/catalog-crawler-launcher-base/build.gradle.kts @@ -0,0 +1,19 @@ +plugins { + `java-library` +} + +dependencies { + // A minimal EDC that can request catalogs + api(libs.edc.controlPlaneCore) + api(libs.edc.dataPlaneSelectorCore) + api(libs.edc.configurationFilesystem) + api(libs.edc.controlPlaneAggregateServices) + api(libs.edc.http) + api(libs.edc.dsp) + api(libs.edc.jsonLd) + + // Data Catalog Crawler + api(project(":extensions:catalog-crawler:catalog-crawler")) +} + +group = libs.versions.sovityEdcGroup.get() diff --git a/extensions/broker-server/build.gradle.kts b/extensions/catalog-crawler/catalog-crawler/build.gradle.kts similarity index 55% rename from extensions/broker-server/build.gradle.kts rename to extensions/catalog-crawler/catalog-crawler/build.gradle.kts index c53445e15..b63b7004f 100644 --- a/extensions/broker-server/build.gradle.kts +++ b/extensions/catalog-crawler/catalog-crawler/build.gradle.kts @@ -2,65 +2,44 @@ plugins { `java-library` } -configurations.all { - resolutionStrategy.cacheChangingModulesFor(0, TimeUnit.SECONDS) -} - dependencies { annotationProcessor(libs.lombok) compileOnly(libs.lombok) - implementation(libs.apache.commonsLang) - - api(project(":utils:catalog-parser")) - api(project(":utils:json-and-jsonld-utils")) - api(project(":extensions:wrapper:wrapper-common-mappers")) - implementation(libs.edc.controlPlaneSpi) implementation(libs.edc.managementApiConfiguration) - api(project(":extensions:broker-server-postgres-flyway-jooq")) - implementation(project(":extensions:broker-server-api:api")) + implementation(libs.quartz.quartz) + implementation(libs.apache.commonsLang) implementation(project(":utils:versions")) - implementation(libs.okhttp.okhttp) + api(project(":utils:catalog-parser")) + api(project(":utils:json-and-jsonld-utils")) + api(project(":extensions:wrapper:wrapper-common-mappers")) + api(project(":extensions:catalog-crawler:catalog-crawler-db")) + api(project(":extensions:postgres-flyway-core")) testAnnotationProcessor(libs.lombok) testCompileOnly(libs.lombok) - testImplementation(project(":extensions:wrapper:clients:java-client")) - testImplementation(project(":extensions:sovity-edc-extensions-package")) + testImplementation(project(":utils:test-connector-remote")) testImplementation(libs.assertj.core) testImplementation(libs.mockito.core) testImplementation(libs.mockito.inline) - testImplementation(libs.edc.controlPlaneCore) - testImplementation(libs.edc.dataPlaneSelectorCore) - testImplementation(libs.edc.junit) - testImplementation(libs.edc.http) - testImplementation(libs.edc.iamMock) - testImplementation(libs.edc.dsp) - testImplementation(libs.edc.jsonLd) - testImplementation(libs.edc.monitorJdkLogger) - testImplementation(libs.edc.configurationFilesystem) - testImplementation(project(":extensions:broker-server-api:client")) testImplementation(libs.restAssured.restAssured) testImplementation(libs.testcontainers.testcontainers) + testImplementation(libs.flyway.core) testImplementation(libs.testcontainers.junitJupiter) testImplementation(libs.testcontainers.postgresql) testImplementation(libs.junit.api) testImplementation(libs.jsonAssert) testRuntimeOnly(libs.junit.engine) - - implementation(libs.quartz.quartz) } tasks.getByName("test") { useJUnitPlatform() + maxParallelForks = 1 } -tasks.register("prepareKotlinBuildScriptModel") {} - -group = libs.versions.sovityBrokerServerGroup.get() - publishing { publications { create(project.name) { diff --git a/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/CrawlerExtension.java b/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/CrawlerExtension.java new file mode 100644 index 000000000..290c5c2c3 --- /dev/null +++ b/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/CrawlerExtension.java @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2023 sovity GmbH + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + * + * Contributors: + * sovity GmbH - initial API and implementation + * + */ + +package de.sovity.edc.ext.catalog.crawler; + +import org.eclipse.edc.connector.api.management.configuration.transform.ManagementApiTypeTransformerRegistry; +import org.eclipse.edc.connector.spi.catalog.CatalogService; +import org.eclipse.edc.jsonld.spi.JsonLd; +import org.eclipse.edc.runtime.metamodel.annotation.Inject; +import org.eclipse.edc.runtime.metamodel.annotation.Provides; +import org.eclipse.edc.runtime.metamodel.annotation.Setting; +import org.eclipse.edc.spi.system.ServiceExtension; +import org.eclipse.edc.spi.system.ServiceExtensionContext; +import org.eclipse.edc.spi.types.TypeManager; + +import static de.sovity.edc.ext.catalog.crawler.orchestration.config.EdcConfigPropertyUtils.toEdcProp; + +@Provides({CrawlerExtensionContext.class}) +public class CrawlerExtension implements ServiceExtension { + + public static final String EXTENSION_NAME = "Authority Portal Data Catalog Crawler"; + + @Setting(required = true) + public static final String EXTENSION_ENABLED = toEdcProp("CRAWLER_EXTENSION_ENABLED"); + + @Setting(required = true) + public static final String ENVIRONMENT_ID = toEdcProp("CRAWLER_ENVIRONMENT_ID"); + + @Setting(required = true) + public static final String JDBC_URL = toEdcProp("CRAWLER_DB_JDBC_URL"); + + @Setting(required = true) + public static final String JDBC_USER = toEdcProp("CRAWLER_DB_JDBC_USER"); + + @Setting(required = true) + public static final String JDBC_PASSWORD = toEdcProp("CRAWLER_DB_JDBC_PASSWORD"); + + @Setting + public static final String DB_CONNECTION_POOL_SIZE = toEdcProp("CRAWLER_DB_CONNECTION_POOL_SIZE"); + + @Setting + public static final String DB_CONNECTION_TIMEOUT_IN_MS = toEdcProp("CRAWLER_DB_CONNECTION_TIMEOUT_IN_MS"); + + @Setting + public static final String DB_MIGRATE = toEdcProp("CRAWLER_DB_MIGRATE"); + + @Setting + public static final String DB_CLEAN = toEdcProp("CRAWLER_DB_CLEAN"); + + @Setting + public static final String DB_CLEAN_ENABLED = toEdcProp("CRAWLER_DB_CLEAN_ENABLED"); + + @Setting + public static final String DB_ADDITIONAL_FLYWAY_MIGRATION_LOCATIONS = toEdcProp("CRAWLER_DB_ADDITIONAL_FLYWAY_LOCATIONS"); + + @Setting + public static final String NUM_THREADS = toEdcProp("CRAWLER_NUM_THREADS"); + + @Setting + public static final String MAX_DATA_OFFERS_PER_CONNECTOR = toEdcProp("CRAWLER_MAX_DATA_OFFERS_PER_CONNECTOR"); + + @Setting + public static final String MAX_CONTRACT_OFFERS_PER_DATA_OFFER = toEdcProp("CRAWLER_MAX_CONTRACT_OFFERS_PER_DATA_OFFER"); + + @Setting + public static final String CRON_ONLINE_CONNECTOR_REFRESH = toEdcProp("CRAWLER_CRON_ONLINE_CONNECTOR_REFRESH"); + + @Setting + public static final String CRON_OFFLINE_CONNECTOR_REFRESH = toEdcProp("CRAWLER_CRON_OFFLINE_CONNECTOR_REFRESH"); + + @Setting + public static final String CRON_DEAD_CONNECTOR_REFRESH = toEdcProp("CRAWLER_CRON_DEAD_CONNECTOR_REFRESH"); + + @Setting + public static final String SCHEDULED_KILL_OFFLINE_CONNECTORS = toEdcProp("CRAWLER_SCHEDULED_KILL_OFFLINE_CONNECTORS"); + @Setting + public static final String KILL_OFFLINE_CONNECTORS_AFTER = toEdcProp("CRAWLER_KILL_OFFLINE_CONNECTORS_AFTER"); + + @Inject + private TypeManager typeManager; + + @Inject + private ManagementApiTypeTransformerRegistry typeTransformerRegistry; + + @Inject + private JsonLd jsonLd; + + @Inject + private CatalogService catalogService; + + /** + * Manual Dependency Injection Result + */ + private CrawlerExtensionContext services; + + @Override + public String name() { + return EXTENSION_NAME; + } + + @Override + public void initialize(ServiceExtensionContext context) { + if (!Boolean.TRUE.equals(context.getConfig().getBoolean(EXTENSION_ENABLED, false))) { + context.getMonitor().info("Crawler extension is disabled."); + return; + } + + services = CrawlerExtensionContextBuilder.buildContext( + context.getConfig(), + context.getMonitor(), + typeManager, + typeTransformerRegistry, + jsonLd, + catalogService + ); + + // Provide access for the tests + context.registerService(CrawlerExtensionContext.class, services); + } + + @Override + public void start() { + if (services == null) { + return; + } + services.crawlerInitializer().onStartup(); + } + + @Override + public void shutdown() { + if (services == null) { + return; + } + services.dataSource().close(); + } +} diff --git a/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/CrawlerExtensionContext.java b/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/CrawlerExtensionContext.java new file mode 100644 index 000000000..264831fe8 --- /dev/null +++ b/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/CrawlerExtensionContext.java @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2023 sovity GmbH + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + * + * Contributors: + * sovity GmbH - initial API and implementation + * + */ + +package de.sovity.edc.ext.catalog.crawler; + +import com.zaxxer.hikari.HikariDataSource; +import de.sovity.edc.ext.catalog.crawler.crawling.ConnectorCrawler; +import de.sovity.edc.ext.catalog.crawler.crawling.fetching.FetchedCatalogBuilder; +import de.sovity.edc.ext.catalog.crawler.dao.config.DslContextFactory; +import de.sovity.edc.ext.catalog.crawler.dao.data_offers.DataOfferRecordUpdater; +import de.sovity.edc.ext.wrapper.api.common.mappers.PolicyMapper; + + +/** + * Manual Dependency Injection result + * + * @param crawlerInitializer Startup Logic + */ +public record CrawlerExtensionContext( + CrawlerInitializer crawlerInitializer, + // Required for stopping connections on closing + HikariDataSource dataSource, + DslContextFactory dslContextFactory, + + // Required for Integration Tests + ConnectorCrawler connectorCrawler, + PolicyMapper policyMapper, + FetchedCatalogBuilder catalogPatchBuilder, + DataOfferRecordUpdater dataOfferRecordUpdater +) { +} diff --git a/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/CrawlerExtensionContextBuilder.java b/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/CrawlerExtensionContextBuilder.java new file mode 100644 index 000000000..2437dd751 --- /dev/null +++ b/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/CrawlerExtensionContextBuilder.java @@ -0,0 +1,313 @@ +/* + * Copyright (c) 2023 sovity GmbH + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + * + * Contributors: + * sovity GmbH - initial API and implementation + * + */ + +package de.sovity.edc.ext.catalog.crawler; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +import de.sovity.edc.ext.catalog.crawler.crawling.ConnectorCrawler; +import de.sovity.edc.ext.catalog.crawler.crawling.OfflineConnectorCleaner; +import de.sovity.edc.ext.catalog.crawler.crawling.fetching.FetchedCatalogBuilder; +import de.sovity.edc.ext.catalog.crawler.crawling.fetching.FetchedCatalogMappingUtils; +import de.sovity.edc.ext.catalog.crawler.crawling.fetching.FetchedCatalogService; +import de.sovity.edc.ext.catalog.crawler.crawling.logging.CrawlerEventLogger; +import de.sovity.edc.ext.catalog.crawler.crawling.logging.CrawlerExecutionTimeLogger; +import de.sovity.edc.ext.catalog.crawler.crawling.writing.CatalogPatchBuilder; +import de.sovity.edc.ext.catalog.crawler.crawling.writing.ConnectorUpdateCatalogWriter; +import de.sovity.edc.ext.catalog.crawler.crawling.writing.ConnectorUpdateFailureWriter; +import de.sovity.edc.ext.catalog.crawler.crawling.writing.ConnectorUpdateSuccessWriter; +import de.sovity.edc.ext.catalog.crawler.crawling.writing.DataOfferLimitsEnforcer; +import de.sovity.edc.ext.catalog.crawler.dao.CatalogCleaner; +import de.sovity.edc.ext.catalog.crawler.dao.CatalogPatchApplier; +import de.sovity.edc.ext.catalog.crawler.dao.config.DataSourceFactory; +import de.sovity.edc.ext.catalog.crawler.dao.config.DslContextFactory; +import de.sovity.edc.ext.catalog.crawler.dao.config.FlywayService; +import de.sovity.edc.ext.catalog.crawler.dao.connectors.ConnectorQueries; +import de.sovity.edc.ext.catalog.crawler.dao.connectors.ConnectorStatusUpdater; +import de.sovity.edc.ext.catalog.crawler.dao.contract_offers.ContractOfferQueries; +import de.sovity.edc.ext.catalog.crawler.dao.contract_offers.ContractOfferRecordUpdater; +import de.sovity.edc.ext.catalog.crawler.dao.data_offers.DataOfferQueries; +import de.sovity.edc.ext.catalog.crawler.dao.data_offers.DataOfferRecordUpdater; +import de.sovity.edc.ext.catalog.crawler.orchestration.config.CrawlerConfigFactory; +import de.sovity.edc.ext.catalog.crawler.orchestration.queue.ConnectorQueue; +import de.sovity.edc.ext.catalog.crawler.orchestration.queue.ConnectorQueueFiller; +import de.sovity.edc.ext.catalog.crawler.orchestration.queue.ThreadPool; +import de.sovity.edc.ext.catalog.crawler.orchestration.queue.ThreadPoolTaskQueue; +import de.sovity.edc.ext.catalog.crawler.orchestration.schedules.DeadConnectorRefreshJob; +import de.sovity.edc.ext.catalog.crawler.orchestration.schedules.OfflineConnectorCleanerJob; +import de.sovity.edc.ext.catalog.crawler.orchestration.schedules.OfflineConnectorRefreshJob; +import de.sovity.edc.ext.catalog.crawler.orchestration.schedules.OnlineConnectorRefreshJob; +import de.sovity.edc.ext.catalog.crawler.orchestration.schedules.QuartzScheduleInitializer; +import de.sovity.edc.ext.catalog.crawler.orchestration.schedules.utils.CronJobRef; +import de.sovity.edc.ext.wrapper.api.common.mappers.AssetMapper; +import de.sovity.edc.ext.wrapper.api.common.mappers.PolicyMapper; +import de.sovity.edc.ext.wrapper.api.common.mappers.asset.AssetEditRequestMapper; +import de.sovity.edc.ext.wrapper.api.common.mappers.asset.AssetJsonLdBuilder; +import de.sovity.edc.ext.wrapper.api.common.mappers.asset.AssetJsonLdParser; +import de.sovity.edc.ext.wrapper.api.common.mappers.asset.utils.AssetJsonLdUtils; +import de.sovity.edc.ext.wrapper.api.common.mappers.asset.utils.EdcPropertyUtils; +import de.sovity.edc.ext.wrapper.api.common.mappers.asset.utils.ShortDescriptionBuilder; +import de.sovity.edc.ext.wrapper.api.common.mappers.dataaddress.DataSourceMapper; +import de.sovity.edc.ext.wrapper.api.common.mappers.dataaddress.http.HttpDataSourceMapper; +import de.sovity.edc.ext.wrapper.api.common.mappers.dataaddress.http.HttpHeaderMapper; +import de.sovity.edc.ext.wrapper.api.common.mappers.policy.AtomicConstraintMapper; +import de.sovity.edc.ext.wrapper.api.common.mappers.policy.ConstraintExtractor; +import de.sovity.edc.ext.wrapper.api.common.mappers.policy.LiteralMapper; +import de.sovity.edc.ext.wrapper.api.common.mappers.policy.OperatorMapper; +import de.sovity.edc.ext.wrapper.api.common.mappers.policy.PolicyValidator; +import de.sovity.edc.utils.catalog.DspCatalogService; +import de.sovity.edc.utils.catalog.mapper.DspDataOfferBuilder; +import lombok.NoArgsConstructor; +import org.eclipse.edc.connector.spi.catalog.CatalogService; +import org.eclipse.edc.jsonld.spi.JsonLd; +import org.eclipse.edc.runtime.metamodel.annotation.Inject; +import org.eclipse.edc.spi.CoreConstants; +import org.eclipse.edc.spi.monitor.Monitor; +import org.eclipse.edc.spi.system.configuration.Config; +import org.eclipse.edc.spi.types.TypeManager; +import org.eclipse.edc.transform.spi.TypeTransformerRegistry; +import org.jetbrains.annotations.NotNull; + +import java.util.List; + + +/** + * Manual Dependency Injection (DYDI). + *

+ * We want to develop as Java Backend Development is done, but we have + * no CDI / DI Framework to rely on. + *

+ * EDC {@link Inject} only works in {@link CrawlerExtension}. + */ +@NoArgsConstructor(access = lombok.AccessLevel.PRIVATE) +public class CrawlerExtensionContextBuilder { + + public static CrawlerExtensionContext buildContext( + Config config, + Monitor monitor, + TypeManager typeManager, + TypeTransformerRegistry typeTransformerRegistry, + JsonLd jsonLd, + CatalogService catalogService + ) { + // Config + var crawlerConfigFactory = new CrawlerConfigFactory(config); + var crawlerConfig = crawlerConfigFactory.buildCrawlerConfig(); + + // DB + var dataSourceFactory = new DataSourceFactory(config); + var dataSource = dataSourceFactory.newDataSource(); + var flywayService = new FlywayService(config, monitor, dataSource); + flywayService.validateOrMigrateInTests(); + + // Dao + var dataOfferQueries = new DataOfferQueries(); + var dslContextFactory = new DslContextFactory(dataSource); + var connectorQueries = new ConnectorQueries(crawlerConfig); + + // Services + var objectMapperJsonLd = getJsonLdObjectMapper(typeManager); + var assetMapper = newAssetMapper(typeTransformerRegistry, jsonLd); + var policyMapper = newPolicyMapper(typeTransformerRegistry, objectMapperJsonLd); + var crawlerEventLogger = new CrawlerEventLogger(); + var crawlerExecutionTimeLogger = new CrawlerExecutionTimeLogger(); + var dataOfferMappingUtils = new FetchedCatalogMappingUtils( + policyMapper, + assetMapper, + objectMapperJsonLd + ); + var contractOfferRecordUpdater = new ContractOfferRecordUpdater(); + var shortDescriptionBuilder = new ShortDescriptionBuilder(); + var dataOfferRecordUpdater = new DataOfferRecordUpdater(shortDescriptionBuilder); + var contractOfferQueries = new ContractOfferQueries(); + var dataOfferLimitsEnforcer = new DataOfferLimitsEnforcer(crawlerConfig, crawlerEventLogger); + var dataOfferPatchBuilder = new CatalogPatchBuilder( + contractOfferQueries, + dataOfferQueries, + dataOfferRecordUpdater, + contractOfferRecordUpdater + ); + var dataOfferPatchApplier = new CatalogPatchApplier(); + var dataOfferWriter = new ConnectorUpdateCatalogWriter(dataOfferPatchBuilder, dataOfferPatchApplier); + var connectorUpdateSuccessWriter = new ConnectorUpdateSuccessWriter( + crawlerEventLogger, + dataOfferWriter, + dataOfferLimitsEnforcer + ); + var fetchedDataOfferBuilder = new FetchedCatalogBuilder(dataOfferMappingUtils); + var dspDataOfferBuilder = new DspDataOfferBuilder(jsonLd); + var dspCatalogService = new DspCatalogService( + catalogService, + dspDataOfferBuilder + ); + var dataOfferFetcher = new FetchedCatalogService(dspCatalogService, fetchedDataOfferBuilder); + var connectorUpdateFailureWriter = new ConnectorUpdateFailureWriter(crawlerEventLogger, monitor); + var connectorUpdater = new ConnectorCrawler( + dataOfferFetcher, + connectorUpdateSuccessWriter, + connectorUpdateFailureWriter, + connectorQueries, + dslContextFactory, + monitor, + crawlerExecutionTimeLogger + ); + + var threadPoolTaskQueue = new ThreadPoolTaskQueue(); + var threadPool = new ThreadPool(threadPoolTaskQueue, crawlerConfig, monitor); + var connectorQueue = new ConnectorQueue(connectorUpdater, threadPool); + var connectorQueueFiller = new ConnectorQueueFiller(connectorQueue, connectorQueries); + var connectorStatusUpdater = new ConnectorStatusUpdater(); + var catalogCleaner = new CatalogCleaner(); + var offlineConnectorCleaner = new OfflineConnectorCleaner( + crawlerConfig, + connectorQueries, + crawlerEventLogger, + connectorStatusUpdater, + catalogCleaner + ); + + // Schedules + List> jobs = List.of( + getOnlineConnectorRefreshCronJob(dslContextFactory, connectorQueueFiller), + getOfflineConnectorRefreshCronJob(dslContextFactory, connectorQueueFiller), + getDeadConnectorRefreshCronJob(dslContextFactory, connectorQueueFiller), + getOfflineConnectorCleanerCronJob(dslContextFactory, offlineConnectorCleaner) + ); + + // Startup + var quartzScheduleInitializer = new QuartzScheduleInitializer(config, monitor, jobs); + var crawlerInitializer = new CrawlerInitializer(quartzScheduleInitializer); + + return new CrawlerExtensionContext( + crawlerInitializer, + dataSource, + dslContextFactory, + connectorUpdater, + policyMapper, + fetchedDataOfferBuilder, + dataOfferRecordUpdater + ); + } + + @NotNull + private static PolicyMapper newPolicyMapper(TypeTransformerRegistry typeTransformerRegistry, ObjectMapper objectMapperJsonLd) { + var operatorMapper = new OperatorMapper(); + var literalMapper = new LiteralMapper( + objectMapperJsonLd + ); + var atomicConstraintMapper = new AtomicConstraintMapper( + literalMapper, + operatorMapper + ); + var policyValidator = new PolicyValidator(); + var constraintExtractor = new ConstraintExtractor( + policyValidator, + atomicConstraintMapper + ); + return new PolicyMapper( + constraintExtractor, + atomicConstraintMapper, + typeTransformerRegistry + ); + } + + @NotNull + private static AssetMapper newAssetMapper( + TypeTransformerRegistry typeTransformerRegistry, + JsonLd jsonLd + ) { + var edcPropertyUtils = new EdcPropertyUtils(); + var assetJsonLdUtils = new AssetJsonLdUtils(); + var assetEditRequestMapper = new AssetEditRequestMapper(); + var shortDescriptionBuilder = new ShortDescriptionBuilder(); + var assetJsonLdParser = new AssetJsonLdParser( + assetJsonLdUtils, + shortDescriptionBuilder, + endpoint -> false + ); + var httpHeaderMapper = new HttpHeaderMapper(); + var httpDataSourceMapper = new HttpDataSourceMapper(httpHeaderMapper); + var dataSourceMapper = new DataSourceMapper( + edcPropertyUtils, + httpDataSourceMapper + ); + var assetJsonLdBuilder = new AssetJsonLdBuilder( + dataSourceMapper, + assetJsonLdParser, + assetEditRequestMapper + ); + return new AssetMapper( + typeTransformerRegistry, + assetJsonLdBuilder, + assetJsonLdParser, + jsonLd + ); + } + + @NotNull + private static CronJobRef getOfflineConnectorCleanerCronJob(DslContextFactory dslContextFactory, + OfflineConnectorCleaner offlineConnectorCleaner) { + return new CronJobRef<>( + CrawlerExtension.SCHEDULED_KILL_OFFLINE_CONNECTORS, + OfflineConnectorCleanerJob.class, + () -> new OfflineConnectorCleanerJob(dslContextFactory, offlineConnectorCleaner) + ); + } + + @NotNull + private static CronJobRef getOnlineConnectorRefreshCronJob( + DslContextFactory dslContextFactory, + ConnectorQueueFiller connectorQueueFiller + ) { + return new CronJobRef<>( + CrawlerExtension.CRON_ONLINE_CONNECTOR_REFRESH, + OnlineConnectorRefreshJob.class, + () -> new OnlineConnectorRefreshJob(dslContextFactory, connectorQueueFiller) + ); + } + + @NotNull + private static CronJobRef getOfflineConnectorRefreshCronJob( + DslContextFactory dslContextFactory, + ConnectorQueueFiller connectorQueueFiller + ) { + return new CronJobRef<>( + CrawlerExtension.CRON_OFFLINE_CONNECTOR_REFRESH, + OfflineConnectorRefreshJob.class, + () -> new OfflineConnectorRefreshJob(dslContextFactory, connectorQueueFiller) + ); + } + + @NotNull + private static CronJobRef getDeadConnectorRefreshCronJob(DslContextFactory dslContextFactory, + ConnectorQueueFiller connectorQueueFiller) { + return new CronJobRef<>( + CrawlerExtension.CRON_DEAD_CONNECTOR_REFRESH, + DeadConnectorRefreshJob.class, + () -> new DeadConnectorRefreshJob(dslContextFactory, connectorQueueFiller) + ); + } + + private static ObjectMapper getJsonLdObjectMapper(TypeManager typeManager) { + var objectMapper = typeManager.getMapper(CoreConstants.JSON_LD); + + // Fixes Dates in JSON-LD Object Mapper + // The Core EDC uses longs over OffsetDateTime, so they never fixed the date format + objectMapper.registerModule(new JavaTimeModule()); + objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); + + return objectMapper; + } +} diff --git a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/BrokerServerInitializer.java b/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/CrawlerInitializer.java similarity index 56% rename from extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/BrokerServerInitializer.java rename to extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/CrawlerInitializer.java index 4f1ca59f2..719ace1c3 100644 --- a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/BrokerServerInitializer.java +++ b/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/CrawlerInitializer.java @@ -12,20 +12,16 @@ * */ -package de.sovity.edc.ext.brokerserver.services; +package de.sovity.edc.ext.catalog.crawler; -import de.sovity.edc.ext.brokerserver.db.DslContextFactory; -import de.sovity.edc.ext.brokerserver.services.schedules.QuartzScheduleInitializer; +import de.sovity.edc.ext.catalog.crawler.orchestration.schedules.QuartzScheduleInitializer; import lombok.RequiredArgsConstructor; @RequiredArgsConstructor -public class BrokerServerInitializer { - private final DslContextFactory dslContextFactory; - private final KnownConnectorsInitializer knownConnectorsInitializer; +public class CrawlerInitializer { private final QuartzScheduleInitializer quartzScheduleInitializer; public void onStartup() { - dslContextFactory.transaction(knownConnectorsInitializer::addKnownConnectorsOnStartup); quartzScheduleInitializer.startSchedules(); } } diff --git a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/refreshing/ConnectorUpdater.java b/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/crawling/ConnectorCrawler.java similarity index 53% rename from extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/refreshing/ConnectorUpdater.java rename to extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/crawling/ConnectorCrawler.java index 5a759fab0..dca422308 100644 --- a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/refreshing/ConnectorUpdater.java +++ b/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/crawling/ConnectorCrawler.java @@ -12,14 +12,16 @@ * */ -package de.sovity.edc.ext.brokerserver.services.refreshing; +package de.sovity.edc.ext.catalog.crawler.crawling; -import de.sovity.edc.ext.brokerserver.dao.ConnectorQueries; -import de.sovity.edc.ext.brokerserver.db.DslContextFactory; -import de.sovity.edc.ext.brokerserver.db.jooq.enums.MeasurementErrorStatus; -import de.sovity.edc.ext.brokerserver.db.jooq.tables.records.ConnectorRecord; -import de.sovity.edc.ext.brokerserver.services.logging.BrokerExecutionTimeLogger; -import de.sovity.edc.ext.brokerserver.services.refreshing.offers.CatalogFetcher; +import de.sovity.edc.ext.catalog.crawler.crawling.fetching.FetchedCatalogService; +import de.sovity.edc.ext.catalog.crawler.crawling.logging.CrawlerExecutionTimeLogger; +import de.sovity.edc.ext.catalog.crawler.crawling.writing.ConnectorUpdateFailureWriter; +import de.sovity.edc.ext.catalog.crawler.crawling.writing.ConnectorUpdateSuccessWriter; +import de.sovity.edc.ext.catalog.crawler.dao.config.DslContextFactory; +import de.sovity.edc.ext.catalog.crawler.dao.connectors.ConnectorQueries; +import de.sovity.edc.ext.catalog.crawler.dao.connectors.ConnectorRef; +import de.sovity.edc.ext.catalog.crawler.db.jooq.enums.MeasurementErrorStatus; import lombok.RequiredArgsConstructor; import org.apache.commons.lang3.time.StopWatch; import org.eclipse.edc.spi.monitor.Monitor; @@ -30,41 +32,41 @@ * Updates a single connector. */ @RequiredArgsConstructor -public class ConnectorUpdater { - private final CatalogFetcher catalogFetcher; +public class ConnectorCrawler { + private final FetchedCatalogService fetchedCatalogService; private final ConnectorUpdateSuccessWriter connectorUpdateSuccessWriter; private final ConnectorUpdateFailureWriter connectorUpdateFailureWriter; private final ConnectorQueries connectorQueries; private final DslContextFactory dslContextFactory; private final Monitor monitor; - private final BrokerExecutionTimeLogger brokerExecutionTimeLogger; + private final CrawlerExecutionTimeLogger crawlerExecutionTimeLogger; /** * Updates single connector. * - * @param connectorEndpoint connector endpoint + * @param connectorRef connector */ - public void updateConnector(String connectorEndpoint) { + public void crawlConnector(ConnectorRef connectorRef) { var executionTime = StopWatch.createStarted(); var failed = false; try { - monitor.info("Updating connector: " + connectorEndpoint); + monitor.info("Updating connector: " + connectorRef); - var catalog = catalogFetcher.fetchCatalog(connectorEndpoint); + var catalog = fetchedCatalogService.fetchCatalog(connectorRef); // Update connector in a single transaction dslContextFactory.transaction(dsl -> { - ConnectorRecord connectorRecord = connectorQueries.findByEndpoint(dsl, connectorEndpoint); - connectorUpdateSuccessWriter.handleConnectorOnline(dsl, connectorRecord, catalog); + var connectorRecord = connectorQueries.findByConnectorId(dsl, connectorRef.getConnectorId()); + connectorUpdateSuccessWriter.handleConnectorOnline(dsl, connectorRef, connectorRecord, catalog); }); } catch (Exception e) { failed = true; try { // Update connector in a single transaction dslContextFactory.transaction(dsl -> { - ConnectorRecord connectorRecord = connectorQueries.findByEndpoint(dsl, connectorEndpoint); - connectorUpdateFailureWriter.handleConnectorOffline(dsl, connectorRecord, e); + var connectorRecord = connectorQueries.findByConnectorId(dsl, connectorRef.getConnectorId()); + connectorUpdateFailureWriter.handleConnectorOffline(dsl, connectorRef, connectorRecord, e); }); } catch (Exception e1) { e1.addSuppressed(e); @@ -74,9 +76,12 @@ public void updateConnector(String connectorEndpoint) { executionTime.stop(); try { var status = failed ? MeasurementErrorStatus.ERROR : MeasurementErrorStatus.OK; - dslContextFactory.transaction(dsl -> { - brokerExecutionTimeLogger.logExecutionTime(dsl, connectorEndpoint, executionTime.getTime(TimeUnit.MILLISECONDS), status); - }); + dslContextFactory.transaction(dsl -> crawlerExecutionTimeLogger.logExecutionTime( + dsl, + connectorRef, + executionTime.getTime(TimeUnit.MILLISECONDS), + status + )); } catch (Exception e) { monitor.severe("Failed logging connector update execution time.", e); } diff --git a/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/crawling/OfflineConnectorCleaner.java b/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/crawling/OfflineConnectorCleaner.java new file mode 100644 index 000000000..51f5c9bd4 --- /dev/null +++ b/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/crawling/OfflineConnectorCleaner.java @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2023 sovity GmbH + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + * + * Contributors: + * sovity GmbH - initial API and implementation + * + */ + +package de.sovity.edc.ext.catalog.crawler.crawling; + +import de.sovity.edc.ext.catalog.crawler.crawling.logging.CrawlerEventLogger; +import de.sovity.edc.ext.catalog.crawler.dao.CatalogCleaner; +import de.sovity.edc.ext.catalog.crawler.dao.connectors.ConnectorQueries; +import de.sovity.edc.ext.catalog.crawler.dao.connectors.ConnectorStatusUpdater; +import de.sovity.edc.ext.catalog.crawler.orchestration.config.CrawlerConfig; +import lombok.RequiredArgsConstructor; +import org.jooq.DSLContext; + +@RequiredArgsConstructor +public class OfflineConnectorCleaner { + private final CrawlerConfig crawlerConfig; + private final ConnectorQueries connectorQueries; + private final CrawlerEventLogger crawlerEventLogger; + private final ConnectorStatusUpdater connectorStatusUpdater; + private final CatalogCleaner catalogCleaner; + + public void cleanConnectorsIfOfflineTooLong(DSLContext dsl) { + var killOfflineConnectorsAfter = crawlerConfig.getKillOfflineConnectorsAfter(); + var connectorsToKill = connectorQueries.findAllConnectorsForKilling(dsl, killOfflineConnectorsAfter); + + catalogCleaner.removeCatalogByConnectors(dsl, connectorsToKill); + connectorStatusUpdater.markAsDead(dsl, connectorsToKill); + + crawlerEventLogger.addKilledDueToOfflineTooLongMessages(dsl, connectorsToKill); + } +} diff --git a/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/crawling/fetching/FetchedCatalogBuilder.java b/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/crawling/fetching/FetchedCatalogBuilder.java new file mode 100644 index 000000000..2ef73ffa2 --- /dev/null +++ b/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/crawling/fetching/FetchedCatalogBuilder.java @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2023 sovity GmbH + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + * + * Contributors: + * sovity GmbH - initial API and implementation + * + */ + +package de.sovity.edc.ext.catalog.crawler.crawling.fetching; + +import de.sovity.edc.ext.catalog.crawler.crawling.fetching.model.FetchedCatalog; +import de.sovity.edc.ext.catalog.crawler.crawling.fetching.model.FetchedContractOffer; +import de.sovity.edc.ext.catalog.crawler.crawling.fetching.model.FetchedDataOffer; +import de.sovity.edc.ext.catalog.crawler.dao.connectors.ConnectorRef; +import de.sovity.edc.utils.catalog.model.DspCatalog; +import de.sovity.edc.utils.catalog.model.DspContractOffer; +import de.sovity.edc.utils.catalog.model.DspDataOffer; +import lombok.RequiredArgsConstructor; +import org.apache.commons.lang3.Validate; +import org.jetbrains.annotations.NotNull; + +import java.util.List; + +@RequiredArgsConstructor +public class FetchedCatalogBuilder { + private final FetchedCatalogMappingUtils fetchedCatalogMappingUtils; + + public FetchedCatalog buildFetchedCatalog(DspCatalog catalog, ConnectorRef connectorRef) { + assertEqualEndpoint(catalog, connectorRef); + assertEqualParticipantId(catalog, connectorRef); + + var fetchedDataOffers = catalog.getDataOffers().stream() + .map(dspDataOffer -> buildFetchedDataOffer(dspDataOffer, connectorRef)) + .toList(); + + var fetchedCatalog = new FetchedCatalog(); + fetchedCatalog.setConnectorRef(connectorRef); + fetchedCatalog.setDataOffers(fetchedDataOffers); + return fetchedCatalog; + } + + private void assertEqualParticipantId(DspCatalog catalog, ConnectorRef connectorRef) { + Validate.isTrue( + connectorRef.getConnectorId().equals(catalog.getParticipantId()), + String.format( + "Connector connectorId does not match the participantId: connectorId %s, participantId %s", + connectorRef.getConnectorId(), + catalog.getParticipantId() + ) + ); + } + + private void assertEqualEndpoint(DspCatalog catalog, ConnectorRef connectorRef) { + Validate.isTrue( + connectorRef.getEndpoint().equals(catalog.getEndpoint()), + String.format( + "Connector endpoint mismatch: expected %s, got %s", + connectorRef.getEndpoint(), + catalog.getEndpoint() + ) + ); + } + + @NotNull + private FetchedDataOffer buildFetchedDataOffer( + DspDataOffer dspDataOffer, + ConnectorRef connectorRef + ) { + var uiAsset = fetchedCatalogMappingUtils.buildUiAsset(dspDataOffer, connectorRef); + var uiAssetJson = fetchedCatalogMappingUtils.buildUiAssetJson(uiAsset); + + var fetchedDataOffer = new FetchedDataOffer(); + fetchedDataOffer.setAssetId(uiAsset.getAssetId()); + fetchedDataOffer.setUiAsset(uiAsset); + fetchedDataOffer.setUiAssetJson(uiAssetJson); + fetchedDataOffer.setContractOffers(buildFetchedContractOffers(dspDataOffer.getContractOffers())); + return fetchedDataOffer; + } + + @NotNull + private List buildFetchedContractOffers(List offers) { + return offers.stream() + .map(this::buildFetchedContractOffer) + .toList(); + } + + @NotNull + private FetchedContractOffer buildFetchedContractOffer(DspContractOffer offer) { + var uiPolicyJson = fetchedCatalogMappingUtils.buildUiPolicyJson(offer.getPolicyJsonLd()); + var contractOffer = new FetchedContractOffer(); + contractOffer.setContractOfferId(offer.getContractOfferId()); + contractOffer.setUiPolicyJson(uiPolicyJson); + return contractOffer; + } + +} diff --git a/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/crawling/fetching/FetchedCatalogMappingUtils.java b/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/crawling/fetching/FetchedCatalogMappingUtils.java new file mode 100644 index 000000000..1ed02ef3e --- /dev/null +++ b/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/crawling/fetching/FetchedCatalogMappingUtils.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2023 sovity GmbH + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + * + * Contributors: + * sovity GmbH - initial API and implementation + * + */ + +package de.sovity.edc.ext.catalog.crawler.crawling.fetching; + +import com.fasterxml.jackson.databind.ObjectMapper; +import de.sovity.edc.ext.catalog.crawler.dao.connectors.ConnectorRef; +import de.sovity.edc.ext.wrapper.api.common.mappers.AssetMapper; +import de.sovity.edc.ext.wrapper.api.common.mappers.PolicyMapper; +import de.sovity.edc.ext.wrapper.api.common.model.UiAsset; +import de.sovity.edc.utils.catalog.model.DspDataOffer; +import jakarta.json.JsonObject; +import lombok.RequiredArgsConstructor; +import lombok.SneakyThrows; + +@RequiredArgsConstructor +public class FetchedCatalogMappingUtils { + private final PolicyMapper policyMapper; + private final AssetMapper assetMapper; + private final ObjectMapper objectMapper; + + public UiAsset buildUiAsset( + DspDataOffer dspDataOffer, + ConnectorRef connectorRef + ) { + var assetJsonLd = assetMapper.buildAssetJsonLdFromDatasetProperties(dspDataOffer.getAssetPropertiesJsonLd()); + var asset = assetMapper.buildAsset(assetJsonLd); + var uiAsset = assetMapper.buildUiAsset(asset, connectorRef.getEndpoint(), connectorRef.getConnectorId()); + uiAsset.setCreatorOrganizationName(connectorRef.getOrganizationLegalName()); + uiAsset.setParticipantId(connectorRef.getConnectorId()); + return uiAsset; + } + + @SneakyThrows + public String buildUiAssetJson(UiAsset uiAsset) { + return objectMapper.writeValueAsString(uiAsset); + } + + @SneakyThrows + public String buildUiPolicyJson(JsonObject policyJsonLd) { + var policy = policyMapper.buildPolicy(policyJsonLd); + var uiPolicy = policyMapper.buildUiPolicy(policy); + return objectMapper.writeValueAsString(uiPolicy); + } +} diff --git a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/refreshing/offers/CatalogFetcher.java b/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/crawling/fetching/FetchedCatalogService.java similarity index 59% rename from extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/refreshing/offers/CatalogFetcher.java rename to extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/crawling/fetching/FetchedCatalogService.java index 2b7da851c..c55973bbe 100644 --- a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/refreshing/offers/CatalogFetcher.java +++ b/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/crawling/fetching/FetchedCatalogService.java @@ -12,29 +12,30 @@ * */ -package de.sovity.edc.ext.brokerserver.services.refreshing.offers; +package de.sovity.edc.ext.catalog.crawler.crawling.fetching; -import de.sovity.edc.ext.brokerserver.services.refreshing.offers.model.FetchedCatalog; -import de.sovity.edc.ext.brokerserver.services.refreshing.offers.model.FetchedDataOffer; +import de.sovity.edc.ext.catalog.crawler.crawling.fetching.model.FetchedCatalog; +import de.sovity.edc.ext.catalog.crawler.crawling.fetching.model.FetchedDataOffer; +import de.sovity.edc.ext.catalog.crawler.dao.connectors.ConnectorRef; import de.sovity.edc.utils.catalog.DspCatalogService; import lombok.RequiredArgsConstructor; import lombok.SneakyThrows; import org.eclipse.edc.connector.contract.spi.types.offer.ContractOffer; @RequiredArgsConstructor -public class CatalogFetcher { +public class FetchedCatalogService { private final DspCatalogService dspCatalogService; - private final FetchedCatalogBuilder fetchedCatalogBuilder; + private final FetchedCatalogBuilder catalogPatchBuilder; /** * Fetches {@link ContractOffer}s and de-duplicates them into {@link FetchedDataOffer}s. * - * @param connectorEndpoint connector endpoint + * @param connectorRef connector * @return updated connector db row */ @SneakyThrows - public FetchedCatalog fetchCatalog(String connectorEndpoint) { - var dspCatalog = dspCatalogService.fetchDataOffers(connectorEndpoint); - return fetchedCatalogBuilder.buildFetchedCatalog(dspCatalog); + public FetchedCatalog fetchCatalog(ConnectorRef connectorRef) { + var dspCatalog = dspCatalogService.fetchDataOffers(connectorRef.getEndpoint()); + return catalogPatchBuilder.buildFetchedCatalog(dspCatalog, connectorRef); } } diff --git a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/refreshing/offers/model/FetchedCatalog.java b/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/crawling/fetching/model/FetchedCatalog.java similarity index 68% rename from extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/refreshing/offers/model/FetchedCatalog.java rename to extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/crawling/fetching/model/FetchedCatalog.java index 550dd0657..027d2c8b3 100644 --- a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/refreshing/offers/model/FetchedCatalog.java +++ b/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/crawling/fetching/model/FetchedCatalog.java @@ -12,10 +12,14 @@ * */ -package de.sovity.edc.ext.brokerserver.services.refreshing.offers.model; +package de.sovity.edc.ext.catalog.crawler.crawling.fetching.model; +import de.sovity.edc.ext.catalog.crawler.dao.connectors.ConnectorRef; import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Builder; import lombok.Getter; +import lombok.RequiredArgsConstructor; import lombok.Setter; import lombok.experimental.FieldDefaults; @@ -26,8 +30,11 @@ */ @Getter @Setter +@Builder +@RequiredArgsConstructor +@AllArgsConstructor @FieldDefaults(level = AccessLevel.PRIVATE) public class FetchedCatalog { - String participantId; + ConnectorRef connectorRef; List dataOffers; } diff --git a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/refreshing/offers/model/FetchedContractOffer.java b/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/crawling/fetching/model/FetchedContractOffer.java similarity index 72% rename from extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/refreshing/offers/model/FetchedContractOffer.java rename to extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/crawling/fetching/model/FetchedContractOffer.java index b2d566f70..2b1993749 100644 --- a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/refreshing/offers/model/FetchedContractOffer.java +++ b/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/crawling/fetching/model/FetchedContractOffer.java @@ -12,17 +12,23 @@ * */ -package de.sovity.edc.ext.brokerserver.services.refreshing.offers.model; +package de.sovity.edc.ext.catalog.crawler.crawling.fetching.model; import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Builder; import lombok.Getter; +import lombok.NoArgsConstructor; import lombok.Setter; import lombok.experimental.FieldDefaults; @Getter @Setter +@Builder +@NoArgsConstructor +@AllArgsConstructor @FieldDefaults(level = AccessLevel.PRIVATE) public class FetchedContractOffer { String contractOfferId; - String policyJson; + String uiPolicyJson; } diff --git a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/refreshing/offers/model/FetchedDataOffer.java b/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/crawling/fetching/model/FetchedDataOffer.java similarity index 68% rename from extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/refreshing/offers/model/FetchedDataOffer.java rename to extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/crawling/fetching/model/FetchedDataOffer.java index d93306613..a2e6fe99b 100644 --- a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/refreshing/offers/model/FetchedDataOffer.java +++ b/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/crawling/fetching/model/FetchedDataOffer.java @@ -12,10 +12,14 @@ * */ -package de.sovity.edc.ext.brokerserver.services.refreshing.offers.model; +package de.sovity.edc.ext.catalog.crawler.crawling.fetching.model; +import de.sovity.edc.ext.wrapper.api.common.model.UiAsset; import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Builder; import lombok.Getter; +import lombok.NoArgsConstructor; import lombok.Setter; import lombok.experimental.FieldDefaults; @@ -26,18 +30,13 @@ */ @Getter @Setter +@Builder +@NoArgsConstructor +@AllArgsConstructor @FieldDefaults(level = AccessLevel.PRIVATE) public class FetchedDataOffer { String assetId; - String assetTitle; - String description; - String curatorOrganizationName; - String dataCategory; - String dataSubcategory; - String dataModel; - String transportMode; - String geoReferenceMethod; - List keywords; - String assetJsonLd; + UiAsset uiAsset; + String uiAssetJson; List contractOffers; } diff --git a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/logging/ConnectorChangeTracker.java b/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/crawling/logging/ConnectorChangeTracker.java similarity index 96% rename from extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/logging/ConnectorChangeTracker.java rename to extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/crawling/logging/ConnectorChangeTracker.java index 1513c1f5e..e87eabb01 100644 --- a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/logging/ConnectorChangeTracker.java +++ b/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/crawling/logging/ConnectorChangeTracker.java @@ -12,7 +12,7 @@ * */ -package de.sovity.edc.ext.brokerserver.services.logging; +package de.sovity.edc.ext.catalog.crawler.crawling.logging; import lombok.Getter; import lombok.Setter; diff --git a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/logging/BrokerEventErrorMessage.java b/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/crawling/logging/CrawlerEventErrorMessage.java similarity index 57% rename from extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/logging/BrokerEventErrorMessage.java rename to extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/crawling/logging/CrawlerEventErrorMessage.java index b3746df1f..9d7ca039a 100644 --- a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/logging/BrokerEventErrorMessage.java +++ b/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/crawling/logging/CrawlerEventErrorMessage.java @@ -12,32 +12,32 @@ * */ -package de.sovity.edc.ext.brokerserver.services.logging; +package de.sovity.edc.ext.catalog.crawler.crawling.logging; -import de.sovity.edc.ext.brokerserver.utils.StringUtils2; +import de.sovity.edc.ext.catalog.crawler.utils.StringUtils2; import lombok.NonNull; import org.apache.commons.lang3.exception.ExceptionUtils; /** * Helper Dto that contains User Message + Error Stack Trace to be written into - * {@link de.sovity.edc.ext.brokerserver.db.jooq.tables.BrokerEventLog}. + * {@link de.sovity.edc.ext.catalog.crawler.db.jooq.tables.CrawlerEventLog}. *
* This class exists so that logging exceptions has a consistent format. * - * @param message message + * @param message message * @param stackTraceOrNull stack trace */ -public record BrokerEventErrorMessage(String message, String stackTraceOrNull) { +public record CrawlerEventErrorMessage(String message, String stackTraceOrNull) { - public static BrokerEventErrorMessage ofMessage(@NonNull String message) { - return new BrokerEventErrorMessage(message, null); + public static CrawlerEventErrorMessage ofMessage(@NonNull String message) { + return new CrawlerEventErrorMessage(message, null); } - public static BrokerEventErrorMessage ofStackTrace(@NonNull String baseMessage, @NonNull Throwable cause) { + public static CrawlerEventErrorMessage ofStackTrace(@NonNull String baseMessage, @NonNull Throwable cause) { var message = baseMessage; message = StringUtils2.removeSuffix(message, "."); message = StringUtils2.removeSuffix(message, ":"); message = "%s: %s".formatted(message, cause.getClass().getName()); - return new BrokerEventErrorMessage(message, ExceptionUtils.getStackTrace(cause)); + return new CrawlerEventErrorMessage(message, ExceptionUtils.getStackTrace(cause)); } } diff --git a/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/crawling/logging/CrawlerEventLogger.java b/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/crawling/logging/CrawlerEventLogger.java new file mode 100644 index 000000000..396e2095e --- /dev/null +++ b/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/crawling/logging/CrawlerEventLogger.java @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2023 sovity GmbH + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + * + * Contributors: + * sovity GmbH - initial API and implementation + * + */ + +package de.sovity.edc.ext.catalog.crawler.crawling.logging; + +import de.sovity.edc.ext.catalog.crawler.dao.connectors.ConnectorRef; +import de.sovity.edc.ext.catalog.crawler.db.jooq.Tables; +import de.sovity.edc.ext.catalog.crawler.db.jooq.enums.CrawlerEventStatus; +import de.sovity.edc.ext.catalog.crawler.db.jooq.enums.CrawlerEventType; +import de.sovity.edc.ext.catalog.crawler.db.jooq.tables.records.CrawlerEventLogRecord; +import lombok.RequiredArgsConstructor; +import org.jooq.DSLContext; + +import java.time.OffsetDateTime; +import java.util.Collection; +import java.util.UUID; + +/** + * Updates a single connector. + */ +@RequiredArgsConstructor +public class CrawlerEventLogger { + + public void logConnectorUpdated(DSLContext dsl, ConnectorRef connectorRef, ConnectorChangeTracker changes) { + var logEntry = newLogEntry(dsl, connectorRef); + logEntry.setEvent(CrawlerEventType.CONNECTOR_UPDATED); + logEntry.setEventStatus(CrawlerEventStatus.OK); + logEntry.setUserMessage(changes.toString()); + logEntry.insert(); + } + + public void logConnectorOffline(DSLContext dsl, ConnectorRef connectorRef, CrawlerEventErrorMessage errorMessage) { + var logEntry = newLogEntry(dsl, connectorRef); + logEntry.setEvent(CrawlerEventType.CONNECTOR_STATUS_CHANGE_OFFLINE); + logEntry.setEventStatus(CrawlerEventStatus.ERROR); + logEntry.setUserMessage("Connector is offline."); + logEntry.setErrorStack(errorMessage.stackTraceOrNull()); + logEntry.insert(); + } + + public void logConnectorOnline(DSLContext dsl, ConnectorRef connectorRef) { + var logEntry = newLogEntry(dsl, connectorRef); + logEntry.setEvent(CrawlerEventType.CONNECTOR_STATUS_CHANGE_ONLINE); + logEntry.setEventStatus(CrawlerEventStatus.OK); + logEntry.setUserMessage("Connector is online."); + logEntry.insert(); + } + + public void logConnectorUpdateDataOfferLimitExceeded( + DSLContext dsl, + ConnectorRef connectorRef, + Integer maxDataOffersPerConnector + ) { + var logEntry = newLogEntry(dsl, connectorRef); + logEntry.setEvent(CrawlerEventType.CONNECTOR_DATA_OFFER_LIMIT_EXCEEDED); + logEntry.setEventStatus(CrawlerEventStatus.OK); + logEntry.setUserMessage( + "Connector has more than %d data offers. Exceeding data offers will be ignored.".formatted(maxDataOffersPerConnector)); + logEntry.insert(); + } + + public void logConnectorUpdateDataOfferLimitOk(DSLContext dsl, ConnectorRef connectorRef) { + var logEntry = newLogEntry(dsl, connectorRef); + logEntry.setEvent(CrawlerEventType.CONNECTOR_DATA_OFFER_LIMIT_OK); + logEntry.setEventStatus(CrawlerEventStatus.OK); + logEntry.setUserMessage("Connector is not exceeding the maximum number of data offers limit anymore."); + logEntry.insert(); + } + + public void logConnectorUpdateContractOfferLimitExceeded( + DSLContext dsl, + ConnectorRef connectorRef, + Integer maxContractOffersPerConnector + ) { + var logEntry = newLogEntry(dsl, connectorRef); + logEntry.setEvent(CrawlerEventType.CONNECTOR_CONTRACT_OFFER_LIMIT_EXCEEDED); + logEntry.setEventStatus(CrawlerEventStatus.OK); + logEntry.setUserMessage(String.format( + "Some data offers have more than %d contract offers. Exceeding contract offers will be ignored.: ", + maxContractOffersPerConnector + )); + logEntry.insert(); + } + + public void logConnectorUpdateContractOfferLimitOk(DSLContext dsl, ConnectorRef connectorRef) { + var logEntry = newLogEntry(dsl, connectorRef); + logEntry.setEvent(CrawlerEventType.CONNECTOR_CONTRACT_OFFER_LIMIT_OK); + logEntry.setEventStatus(CrawlerEventStatus.OK); + logEntry.setUserMessage("Connector is not exceeding the maximum number of contract offers per data offer limit anymore."); + logEntry.insert(); + } + + public void addKilledDueToOfflineTooLongMessages(DSLContext dsl, Collection connectorRefs) { + var logEntries = connectorRefs.stream() + .map(connectorRef -> buildKilledDueToOfflineTooLongMessage(dsl, connectorRef)) + .toList(); + dsl.batchInsert(logEntries).execute(); + } + + private CrawlerEventLogRecord buildKilledDueToOfflineTooLongMessage(DSLContext dsl, ConnectorRef connectorRef) { + var logEntry = newLogEntry(dsl, connectorRef); + logEntry.setEvent(CrawlerEventType.CONNECTOR_KILLED_DUE_TO_OFFLINE_FOR_TOO_LONG); + logEntry.setEventStatus(CrawlerEventStatus.OK); + logEntry.setUserMessage("Connector was marked as dead for being offline too long."); + return logEntry; + } + + private CrawlerEventLogRecord newLogEntry(DSLContext dsl, ConnectorRef connectorRef) { + var logEntry = dsl.newRecord(Tables.CRAWLER_EVENT_LOG); + logEntry.setId(UUID.randomUUID()); + logEntry.setEnvironment(connectorRef.getEnvironmentId()); + logEntry.setConnectorId(connectorRef.getConnectorId()); + logEntry.setCreatedAt(OffsetDateTime.now()); + return logEntry; + } +} diff --git a/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/crawling/logging/CrawlerExecutionTimeLogger.java b/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/crawling/logging/CrawlerExecutionTimeLogger.java new file mode 100644 index 000000000..b04e757f4 --- /dev/null +++ b/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/crawling/logging/CrawlerExecutionTimeLogger.java @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2023 sovity GmbH + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + * + * Contributors: + * sovity GmbH - initial API and implementation + * + */ + +package de.sovity.edc.ext.catalog.crawler.crawling.logging; + +import de.sovity.edc.ext.catalog.crawler.dao.connectors.ConnectorRef; +import de.sovity.edc.ext.catalog.crawler.db.jooq.Tables; +import de.sovity.edc.ext.catalog.crawler.db.jooq.enums.MeasurementErrorStatus; +import de.sovity.edc.ext.catalog.crawler.db.jooq.enums.MeasurementType; +import lombok.RequiredArgsConstructor; +import org.jooq.DSLContext; + +import java.time.OffsetDateTime; +import java.util.UUID; + +/** + * Updates a single connector. + */ +@RequiredArgsConstructor +public class CrawlerExecutionTimeLogger { + public void logExecutionTime(DSLContext dsl, ConnectorRef connectorRef, long executionTimeInMs, MeasurementErrorStatus errorStatus) { + var logEntry = dsl.newRecord(Tables.CRAWLER_EXECUTION_TIME_MEASUREMENT); + logEntry.setId(UUID.randomUUID()); + logEntry.setEnvironment(connectorRef.getEnvironmentId()); + logEntry.setConnectorId(connectorRef.getConnectorId()); + logEntry.setDurationInMs(executionTimeInMs); + logEntry.setType(MeasurementType.CONNECTOR_REFRESH); + logEntry.setErrorStatus(errorStatus); + logEntry.setCreatedAt(OffsetDateTime.now()); + logEntry.insert(); + } +} diff --git a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/refreshing/offers/DataOfferPatchBuilder.java b/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/crawling/writing/CatalogPatchBuilder.java similarity index 67% rename from extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/refreshing/offers/DataOfferPatchBuilder.java rename to extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/crawling/writing/CatalogPatchBuilder.java index 8b7dcc6be..309e8d8fc 100644 --- a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/refreshing/offers/DataOfferPatchBuilder.java +++ b/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/crawling/writing/CatalogPatchBuilder.java @@ -12,15 +12,19 @@ * */ -package de.sovity.edc.ext.brokerserver.services.refreshing.offers; - -import de.sovity.edc.ext.brokerserver.dao.ContractOfferQueries; -import de.sovity.edc.ext.brokerserver.dao.DataOfferQueries; -import de.sovity.edc.ext.brokerserver.db.jooq.tables.records.ContractOfferRecord; -import de.sovity.edc.ext.brokerserver.db.jooq.tables.records.DataOfferRecord; -import de.sovity.edc.ext.brokerserver.services.refreshing.offers.model.DataOfferPatch; -import de.sovity.edc.ext.brokerserver.services.refreshing.offers.model.FetchedContractOffer; -import de.sovity.edc.ext.brokerserver.services.refreshing.offers.model.FetchedDataOffer; +package de.sovity.edc.ext.catalog.crawler.crawling.writing; + +import de.sovity.edc.ext.catalog.crawler.crawling.fetching.model.FetchedContractOffer; +import de.sovity.edc.ext.catalog.crawler.crawling.fetching.model.FetchedDataOffer; +import de.sovity.edc.ext.catalog.crawler.crawling.writing.utils.DiffUtils; +import de.sovity.edc.ext.catalog.crawler.dao.CatalogPatch; +import de.sovity.edc.ext.catalog.crawler.dao.connectors.ConnectorRef; +import de.sovity.edc.ext.catalog.crawler.dao.contract_offers.ContractOfferQueries; +import de.sovity.edc.ext.catalog.crawler.dao.contract_offers.ContractOfferRecordUpdater; +import de.sovity.edc.ext.catalog.crawler.dao.data_offers.DataOfferQueries; +import de.sovity.edc.ext.catalog.crawler.dao.data_offers.DataOfferRecordUpdater; +import de.sovity.edc.ext.catalog.crawler.db.jooq.tables.records.ContractOfferRecord; +import de.sovity.edc.ext.catalog.crawler.db.jooq.tables.records.DataOfferRecord; import lombok.RequiredArgsConstructor; import org.jooq.DSLContext; @@ -31,7 +35,7 @@ import static java.util.stream.Collectors.groupingBy; @RequiredArgsConstructor -public class DataOfferPatchBuilder { +public class CatalogPatchBuilder { private final ContractOfferQueries contractOfferQueries; private final DataOfferQueries dataOfferQueries; private final DataOfferRecordUpdater dataOfferRecordUpdater; @@ -40,19 +44,19 @@ public class DataOfferPatchBuilder { /** * Fetches existing data offers of given connector endpoint and compares them with fetched data offers. * - * @param dsl dsl - * @param connectorEndpoint connector endpoint + * @param dsl dsl + * @param connectorRef connector * @param fetchedDataOffers fetched data offers * @return change list / patch */ - public DataOfferPatch buildDataOfferPatch( + public CatalogPatch buildDataOfferPatch( DSLContext dsl, - String connectorEndpoint, + ConnectorRef connectorRef, Collection fetchedDataOffers ) { - var patch = new DataOfferPatch(); - var dataOffers = dataOfferQueries.findByConnectorEndpoint(dsl, connectorEndpoint); - var contractOffersByAssetId = contractOfferQueries.findByConnectorEndpoint(dsl, connectorEndpoint) + var patch = new CatalogPatch(); + var dataOffers = dataOfferQueries.findByConnectorId(dsl, connectorRef.getConnectorId()); + var contractOffersByAssetId = contractOfferQueries.findByConnectorId(dsl, connectorRef.getConnectorId()) .stream() .collect(groupingBy(ContractOfferRecord::getAssetId)); @@ -64,8 +68,8 @@ public DataOfferPatch buildDataOfferPatch( ); diff.added().forEach(fetched -> { - var newRecord = dataOfferRecordUpdater.newDataOffer(connectorEndpoint, fetched); - patch.insertDataOffer(newRecord); + var newRecord = dataOfferRecordUpdater.newDataOffer(connectorRef, fetched); + patch.dataOffers().insert(newRecord); patchContractOffers(patch, newRecord, List.of(), fetched.getContractOffers()); }); @@ -81,21 +85,21 @@ public DataOfferPatch buildDataOfferPatch( changed = dataOfferRecordUpdater.updateDataOffer(existing, fetched, changed); if (changed) { - patch.updateDataOffer(existing); + patch.dataOffers().update(existing); } }); diff.removed().forEach(dataOffer -> { - patch.deleteDataOffer(dataOffer); + patch.dataOffers().delete(dataOffer); var contractOffers = contractOffersByAssetId.getOrDefault(dataOffer.getAssetId(), List.of()); - contractOffers.forEach(patch::deleteContractOffer); + contractOffers.forEach(it -> patch.contractOffers().delete(it)); }); return patch; } private boolean patchContractOffers( - DataOfferPatch patch, + CatalogPatch patch, DataOfferRecord dataOffer, Collection contractOffers, Collection fetchedContractOffers @@ -111,7 +115,7 @@ private boolean patchContractOffers( diff.added().forEach(fetched -> { var newRecord = contractOfferRecordUpdater.newContractOffer(dataOffer, fetched); - patch.insertContractOffer(newRecord); + patch.contractOffers().insert(newRecord); hasUpdates.set(true); }); @@ -120,13 +124,13 @@ private boolean patchContractOffers( var fetched = match.fetched(); if (contractOfferRecordUpdater.updateContractOffer(existing, fetched)) { - patch.updateContractOffer(existing); + patch.contractOffers().update(existing); hasUpdates.set(true); } }); diff.removed().forEach(existing -> { - patch.deleteContractOffer(existing); + patch.contractOffers().delete(existing); hasUpdates.set(true); }); diff --git a/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/crawling/writing/ConnectorUpdateCatalogWriter.java b/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/crawling/writing/ConnectorUpdateCatalogWriter.java new file mode 100644 index 000000000..ec67dd2a2 --- /dev/null +++ b/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/crawling/writing/ConnectorUpdateCatalogWriter.java @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2023 sovity GmbH + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + * + * Contributors: + * sovity GmbH - initial API and implementation + * + */ + +package de.sovity.edc.ext.catalog.crawler.crawling.writing; + +import de.sovity.edc.ext.catalog.crawler.crawling.fetching.model.FetchedDataOffer; +import de.sovity.edc.ext.catalog.crawler.crawling.logging.ConnectorChangeTracker; +import de.sovity.edc.ext.catalog.crawler.dao.CatalogPatchApplier; +import de.sovity.edc.ext.catalog.crawler.dao.connectors.ConnectorRef; +import lombok.RequiredArgsConstructor; +import lombok.SneakyThrows; +import org.jooq.DSLContext; + +import java.util.Collection; + +@RequiredArgsConstructor +public class ConnectorUpdateCatalogWriter { + private final CatalogPatchBuilder catalogPatchBuilder; + private final CatalogPatchApplier catalogPatchApplier; + + /** + * Updates a connector's data offers with given {@link FetchedDataOffer}s. + * + * @param dsl dsl + * @param connectorRef connector + * @param fetchedDataOffers fetched data offers + * @param changes change tracker for log message + */ + @SneakyThrows + public void updateDataOffers( + DSLContext dsl, + ConnectorRef connectorRef, + Collection fetchedDataOffers, + ConnectorChangeTracker changes + ) { + var patch = catalogPatchBuilder.buildDataOfferPatch(dsl, connectorRef, fetchedDataOffers); + changes.setNumOffersAdded(patch.dataOffers().getInsertions().size()); + changes.setNumOffersUpdated(patch.dataOffers().getUpdates().size()); + changes.setNumOffersDeleted(patch.dataOffers().getDeletions().size()); + catalogPatchApplier.applyDbUpdatesBatched(dsl, patch); + } +} diff --git a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/refreshing/ConnectorUpdateFailureWriter.java b/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/crawling/writing/ConnectorUpdateFailureWriter.java similarity index 51% rename from extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/refreshing/ConnectorUpdateFailureWriter.java rename to extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/crawling/writing/ConnectorUpdateFailureWriter.java index 87dd61389..05b7f1bb1 100644 --- a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/refreshing/ConnectorUpdateFailureWriter.java +++ b/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/crawling/writing/ConnectorUpdateFailureWriter.java @@ -12,12 +12,13 @@ * */ -package de.sovity.edc.ext.brokerserver.services.refreshing; +package de.sovity.edc.ext.catalog.crawler.crawling.writing; -import de.sovity.edc.ext.brokerserver.db.jooq.enums.ConnectorOnlineStatus; -import de.sovity.edc.ext.brokerserver.db.jooq.tables.records.ConnectorRecord; -import de.sovity.edc.ext.brokerserver.services.logging.BrokerEventErrorMessage; -import de.sovity.edc.ext.brokerserver.services.logging.BrokerEventLogger; +import de.sovity.edc.ext.catalog.crawler.crawling.logging.CrawlerEventErrorMessage; +import de.sovity.edc.ext.catalog.crawler.crawling.logging.CrawlerEventLogger; +import de.sovity.edc.ext.catalog.crawler.dao.connectors.ConnectorRef; +import de.sovity.edc.ext.catalog.crawler.db.jooq.enums.ConnectorOnlineStatus; +import de.sovity.edc.ext.catalog.crawler.db.jooq.tables.records.ConnectorRecord; import lombok.RequiredArgsConstructor; import org.eclipse.edc.spi.monitor.Monitor; import org.jooq.DSLContext; @@ -26,14 +27,19 @@ @RequiredArgsConstructor public class ConnectorUpdateFailureWriter { - private final BrokerEventLogger brokerEventLogger; + private final CrawlerEventLogger crawlerEventLogger; private final Monitor monitor; - public void handleConnectorOffline(DSLContext dsl, ConnectorRecord connector, Throwable e) { + public void handleConnectorOffline( + DSLContext dsl, + ConnectorRef connectorRef, + ConnectorRecord connector, + Throwable e + ) { // Log Status Change and set status to offline if necessary if (connector.getOnlineStatus() == ConnectorOnlineStatus.ONLINE || connector.getLastRefreshAttemptAt() == null) { - monitor.info("Connector is offline: " + connector.getEndpoint(), e); - brokerEventLogger.logConnectorOffline(dsl, connector.getEndpoint(), getFailureMessage(e)); + monitor.info("Connector is offline: " + connector.getEndpointUrl(), e); + crawlerEventLogger.logConnectorOffline(dsl, connectorRef, getFailureMessage(e)); connector.setOnlineStatus(ConnectorOnlineStatus.OFFLINE); } @@ -41,7 +47,7 @@ public void handleConnectorOffline(DSLContext dsl, ConnectorRecord connector, Th connector.update(); } - public BrokerEventErrorMessage getFailureMessage(Throwable e) { - return BrokerEventErrorMessage.ofStackTrace("Unexpected exception during connector update.", e); + public CrawlerEventErrorMessage getFailureMessage(Throwable e) { + return CrawlerEventErrorMessage.ofStackTrace("Unexpected exception during connector update.", e); } } diff --git a/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/crawling/writing/ConnectorUpdateSuccessWriter.java b/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/crawling/writing/ConnectorUpdateSuccessWriter.java new file mode 100644 index 000000000..32b5ebe5e --- /dev/null +++ b/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/crawling/writing/ConnectorUpdateSuccessWriter.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2023 sovity GmbH + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + * + * Contributors: + * sovity GmbH - initial API and implementation + * + */ + +package de.sovity.edc.ext.catalog.crawler.crawling.writing; + +import de.sovity.edc.ext.catalog.crawler.crawling.fetching.model.FetchedCatalog; +import de.sovity.edc.ext.catalog.crawler.crawling.logging.ConnectorChangeTracker; +import de.sovity.edc.ext.catalog.crawler.crawling.logging.CrawlerEventLogger; +import de.sovity.edc.ext.catalog.crawler.dao.connectors.ConnectorRef; +import de.sovity.edc.ext.catalog.crawler.db.jooq.enums.ConnectorOnlineStatus; +import de.sovity.edc.ext.catalog.crawler.db.jooq.tables.records.ConnectorRecord; +import lombok.RequiredArgsConstructor; +import org.jooq.DSLContext; + +import java.time.OffsetDateTime; + +@RequiredArgsConstructor +public class ConnectorUpdateSuccessWriter { + private final CrawlerEventLogger crawlerEventLogger; + private final ConnectorUpdateCatalogWriter connectorUpdateCatalogWriter; + private final DataOfferLimitsEnforcer dataOfferLimitsEnforcer; + + public void handleConnectorOnline( + DSLContext dsl, + ConnectorRef connectorRef, + ConnectorRecord connector, + FetchedCatalog catalog + ) { + // Limit data offers and log limitation if necessary + var limitedDataOffers = dataOfferLimitsEnforcer.enforceLimits(catalog.getDataOffers()); + dataOfferLimitsEnforcer.logEnforcedLimitsIfChanged(dsl, connectorRef, connector, limitedDataOffers); + + // Log Status Change and set status to online if necessary + if (connector.getOnlineStatus() != ConnectorOnlineStatus.ONLINE || connector.getLastRefreshAttemptAt() == null) { + crawlerEventLogger.logConnectorOnline(dsl, connectorRef); + connector.setOnlineStatus(ConnectorOnlineStatus.ONLINE); + } + + // Track changes for final log message + var changes = new ConnectorChangeTracker(); + var now = OffsetDateTime.now(); + connector.setLastSuccessfulRefreshAt(now); + connector.setLastRefreshAttemptAt(now); + connector.update(); + + // Update data offers + connectorUpdateCatalogWriter.updateDataOffers( + dsl, + connectorRef, + limitedDataOffers.abbreviatedDataOffers(), + changes + ); + + // Log event if changes are present + if (!changes.isEmpty()) { + crawlerEventLogger.logConnectorUpdated(dsl, connectorRef, changes); + } + } + +} diff --git a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/refreshing/offers/DataOfferLimitsEnforcer.java b/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/crawling/writing/DataOfferLimitsEnforcer.java similarity index 62% rename from extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/refreshing/offers/DataOfferLimitsEnforcer.java rename to extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/crawling/writing/DataOfferLimitsEnforcer.java index b4d067881..0583b93b3 100644 --- a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/refreshing/offers/DataOfferLimitsEnforcer.java +++ b/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/crawling/writing/DataOfferLimitsEnforcer.java @@ -12,14 +12,15 @@ * */ -package de.sovity.edc.ext.brokerserver.services.refreshing.offers; +package de.sovity.edc.ext.catalog.crawler.crawling.writing; -import de.sovity.edc.ext.brokerserver.db.jooq.enums.ConnectorContractOffersExceeded; -import de.sovity.edc.ext.brokerserver.db.jooq.enums.ConnectorDataOffersExceeded; -import de.sovity.edc.ext.brokerserver.db.jooq.tables.records.ConnectorRecord; -import de.sovity.edc.ext.brokerserver.services.config.BrokerServerSettings; -import de.sovity.edc.ext.brokerserver.services.logging.BrokerEventLogger; -import de.sovity.edc.ext.brokerserver.services.refreshing.offers.model.FetchedDataOffer; +import de.sovity.edc.ext.catalog.crawler.crawling.fetching.model.FetchedDataOffer; +import de.sovity.edc.ext.catalog.crawler.crawling.logging.CrawlerEventLogger; +import de.sovity.edc.ext.catalog.crawler.dao.connectors.ConnectorRef; +import de.sovity.edc.ext.catalog.crawler.db.jooq.enums.ConnectorContractOffersExceeded; +import de.sovity.edc.ext.catalog.crawler.db.jooq.enums.ConnectorDataOffersExceeded; +import de.sovity.edc.ext.catalog.crawler.db.jooq.tables.records.ConnectorRecord; +import de.sovity.edc.ext.catalog.crawler.orchestration.config.CrawlerConfig; import lombok.RequiredArgsConstructor; import org.jooq.DSLContext; @@ -29,8 +30,8 @@ @RequiredArgsConstructor public class DataOfferLimitsEnforcer { - private final BrokerServerSettings brokerServerSettings; - private final BrokerEventLogger brokerEventLogger; + private final CrawlerConfig crawlerConfig; + private final CrawlerEventLogger crawlerEventLogger; public record DataOfferLimitsEnforced( Collection abbreviatedDataOffers, @@ -41,8 +42,8 @@ public record DataOfferLimitsEnforced( public DataOfferLimitsEnforced enforceLimits(Collection dataOffers) { // Get limits from config - var maxDataOffers = brokerServerSettings.getMaxDataOffersPerConnector(); - var maxContractOffers = brokerServerSettings.getMaxContractOffersPerDataOffer(); + var maxDataOffers = crawlerConfig.getMaxDataOffersPerConnector(); + var maxContractOffers = crawlerConfig.getMaxContractOffersPerDataOffer(); List offerList = new ArrayList<>(dataOffers); // No limits set @@ -70,26 +71,31 @@ public DataOfferLimitsEnforced enforceLimits(Collection dataOf return new DataOfferLimitsEnforced(offerList, dataOfferLimitsExceeded, contractOfferLimitsExceeded); } - public void logEnforcedLimitsIfChanged(DSLContext dsl, ConnectorRecord connector, DataOfferLimitsEnforced enforcedLimits) { - String endpoint = connector.getEndpoint(); + public void logEnforcedLimitsIfChanged( + DSLContext dsl, + ConnectorRef connectorRef, + ConnectorRecord connector, + DataOfferLimitsEnforced enforcedLimits + ) { // DataOffer if (enforcedLimits.dataOfferLimitsExceeded() && connector.getDataOffersExceeded() == ConnectorDataOffersExceeded.OK) { - var maxDataOffers = brokerServerSettings.getMaxDataOffersPerConnector(); - brokerEventLogger.logConnectorUpdateDataOfferLimitExceeded(dsl, maxDataOffers, endpoint); + var maxDataOffers = crawlerConfig.getMaxDataOffersPerConnector(); + crawlerEventLogger.logConnectorUpdateDataOfferLimitExceeded(dsl, connectorRef, maxDataOffers); connector.setDataOffersExceeded(ConnectorDataOffersExceeded.EXCEEDED); } else if (!enforcedLimits.dataOfferLimitsExceeded() && connector.getDataOffersExceeded() == ConnectorDataOffersExceeded.EXCEEDED) { - brokerEventLogger.logConnectorUpdateDataOfferLimitOk(dsl, endpoint); + crawlerEventLogger.logConnectorUpdateDataOfferLimitOk(dsl, connectorRef); connector.setDataOffersExceeded(ConnectorDataOffersExceeded.OK); } // ContractOffer if (enforcedLimits.contractOfferLimitsExceeded() && connector.getContractOffersExceeded() == ConnectorContractOffersExceeded.OK) { - var maxContractOffers = brokerServerSettings.getMaxContractOffersPerDataOffer(); - brokerEventLogger.logConnectorUpdateContractOfferLimitExceeded(dsl, maxContractOffers, endpoint); + var maxContractOffers = crawlerConfig.getMaxContractOffersPerDataOffer(); + crawlerEventLogger.logConnectorUpdateContractOfferLimitExceeded(dsl, connectorRef, maxContractOffers); connector.setContractOffersExceeded(ConnectorContractOffersExceeded.EXCEEDED); - } else if (!enforcedLimits.contractOfferLimitsExceeded() && connector.getContractOffersExceeded() == ConnectorContractOffersExceeded.EXCEEDED) { - brokerEventLogger.logConnectorUpdateContractOfferLimitOk(dsl, endpoint); + } else if (!enforcedLimits.contractOfferLimitsExceeded() && + connector.getContractOffersExceeded() == ConnectorContractOffersExceeded.EXCEEDED) { + crawlerEventLogger.logConnectorUpdateContractOfferLimitOk(dsl, connectorRef); connector.setContractOffersExceeded(ConnectorContractOffersExceeded.OK); } } diff --git a/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/crawling/writing/utils/ChangeTracker.java b/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/crawling/writing/utils/ChangeTracker.java new file mode 100644 index 000000000..dad7f9cae --- /dev/null +++ b/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/crawling/writing/utils/ChangeTracker.java @@ -0,0 +1,36 @@ +package de.sovity.edc.ext.catalog.crawler.crawling.writing.utils; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.util.Objects; +import java.util.function.BiPredicate; +import java.util.function.Consumer; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class ChangeTracker { + private boolean changed = false; + + public void setIfChanged( + T existing, + T fetched, + Consumer setter + ) { + setIfChanged(existing, fetched, setter, Objects::equals); + } + + public void setIfChanged( + T existing, + T fetched, + Consumer setter, + BiPredicate equalityChecker + ) { + if (!equalityChecker.test(existing, fetched)) { + setter.accept(fetched); + changed = true; + } + } +} diff --git a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/refreshing/offers/DiffUtils.java b/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/crawling/writing/utils/DiffUtils.java similarity index 72% rename from extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/refreshing/offers/DiffUtils.java rename to extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/crawling/writing/utils/DiffUtils.java index 413ba77a2..7db2dac4f 100644 --- a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/refreshing/offers/DiffUtils.java +++ b/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/crawling/writing/utils/DiffUtils.java @@ -12,9 +12,9 @@ * */ -package de.sovity.edc.ext.brokerserver.services.refreshing.offers; +package de.sovity.edc.ext.catalog.crawler.crawling.writing.utils; -import de.sovity.edc.ext.brokerserver.utils.MapUtils; +import de.sovity.edc.ext.catalog.crawler.utils.MapUtils; import lombok.AccessLevel; import lombok.NoArgsConstructor; @@ -30,13 +30,13 @@ public class DiffUtils { /** * Tries to match two collections by a key, then collects planned change sets as {@link DiffResult}. * - * @param existing list of existing elements + * @param existing list of existing elements * @param existingKeyFn existing elements key extractor - * @param fetched list of fetched elements - * @param fetchedKeyFn fetched elements key extractor - * @param first collection type - * @param second collection type - * @param key type + * @param fetched list of fetched elements + * @param fetchedKeyFn fetched elements key extractor + * @param first collection type + * @param second collection type + * @param key type */ public static DiffResult compareLists( Collection existing, @@ -71,13 +71,13 @@ public static DiffResult compareLists( /** * Result of comparing two collections by keys. * - * @param added elements that are present in fetched collection but not in existing + * @param added elements that are present in fetched collection but not in existing * @param updated elements that are present in both collections * @param removed elements that are present in existing collection but not in fetched - * @param existing item type - * @param fetched item type + * @param existing item type + * @param fetched item type */ - record DiffResult(List added, List> updated, List removed) { + public record DiffResult(List added, List> updated, List removed) { DiffResult() { this(new ArrayList<>(), new ArrayList<>(), new ArrayList<>()); } @@ -87,10 +87,10 @@ record DiffResult(List added, List> updated, List * Pair of elements that are present in both collections. * * @param existing existing item - * @param fetched fetched item - * @param existing item type - * @param fetched item type + * @param fetched fetched item + * @param existing item type + * @param fetched item type */ - record DiffResultMatch(A existing, B fetched) { + public record DiffResultMatch(A existing, B fetched) { } } diff --git a/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/dao/CatalogCleaner.java b/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/dao/CatalogCleaner.java new file mode 100644 index 000000000..87b17d337 --- /dev/null +++ b/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/dao/CatalogCleaner.java @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2023 sovity GmbH + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + * + * Contributors: + * sovity GmbH - initial API and implementation + * + */ + +package de.sovity.edc.ext.catalog.crawler.dao; + +import de.sovity.edc.ext.catalog.crawler.dao.connectors.ConnectorRef; +import de.sovity.edc.ext.catalog.crawler.dao.utils.PostgresqlUtils; +import de.sovity.edc.ext.catalog.crawler.db.jooq.Tables; +import lombok.RequiredArgsConstructor; +import org.jooq.DSLContext; + +import java.util.Collection; + +import static java.util.stream.Collectors.toSet; + +@RequiredArgsConstructor +public class CatalogCleaner { + + public void removeCatalogByConnectors(DSLContext dsl, Collection connectorRefs) { + var co = Tables.CONTRACT_OFFER; + var d = Tables.DATA_OFFER; + + var connectorIds = connectorRefs.stream().map(ConnectorRef::getConnectorId).collect(toSet()); + + dsl.deleteFrom(co).where(PostgresqlUtils.in(co.CONNECTOR_ID, connectorIds)).execute(); + dsl.deleteFrom(d).where(PostgresqlUtils.in(d.CONNECTOR_ID, connectorIds)).execute(); + } +} diff --git a/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/dao/CatalogPatch.java b/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/dao/CatalogPatch.java new file mode 100644 index 000000000..8ad4ebc1e --- /dev/null +++ b/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/dao/CatalogPatch.java @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2023 sovity GmbH + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + * + * Contributors: + * sovity GmbH - initial API and implementation + * + */ + +package de.sovity.edc.ext.catalog.crawler.dao; + +import de.sovity.edc.ext.catalog.crawler.dao.utils.RecordPatch; +import de.sovity.edc.ext.catalog.crawler.db.jooq.tables.records.ContractOfferRecord; +import de.sovity.edc.ext.catalog.crawler.db.jooq.tables.records.DataOfferRecord; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.Setter; +import lombok.experimental.Accessors; +import lombok.experimental.FieldDefaults; + +import java.util.List; + +/** + * Contains planned DB Row changes to be applied as batch. + */ +@Getter +@Setter +@Accessors(fluent = true) +@FieldDefaults(level = AccessLevel.PRIVATE) +public class CatalogPatch { + RecordPatch dataOffers = new RecordPatch<>(); + RecordPatch contractOffers = new RecordPatch<>(); + + public List> insertionOrder() { + return List.of(dataOffers, contractOffers); + } +} diff --git a/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/dao/CatalogPatchApplier.java b/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/dao/CatalogPatchApplier.java new file mode 100644 index 000000000..9dce2fc9d --- /dev/null +++ b/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/dao/CatalogPatchApplier.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2023 sovity GmbH + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + * + * Contributors: + * sovity GmbH - initial API and implementation + * + */ + +package de.sovity.edc.ext.catalog.crawler.dao; + +import de.sovity.edc.ext.catalog.crawler.dao.utils.RecordPatch; +import de.sovity.edc.ext.catalog.crawler.utils.CollectionUtils2; +import lombok.RequiredArgsConstructor; +import lombok.SneakyThrows; +import org.jooq.DSLContext; + +@RequiredArgsConstructor +public class CatalogPatchApplier { + + @SneakyThrows + public void applyDbUpdatesBatched(DSLContext dsl, CatalogPatch catalogPatch) { + var insertionOrder = catalogPatch.insertionOrder(); + var deletionOrder = CollectionUtils2.reverse(insertionOrder); + + insertionOrder.stream() + .map(RecordPatch::getInsertions) + .filter(CollectionUtils2::isNotEmpty) + .forEach(it -> dsl.batchInsert(it).execute()); + + insertionOrder.stream() + .map(RecordPatch::getUpdates) + .filter(CollectionUtils2::isNotEmpty) + .forEach(it -> dsl.batchUpdate(it).execute()); + + deletionOrder.stream() + .map(RecordPatch::getDeletions) + .filter(CollectionUtils2::isNotEmpty) + .forEach(it -> dsl.batchDelete(it).execute()); + } +} diff --git a/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/dao/config/DataSourceFactory.java b/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/dao/config/DataSourceFactory.java new file mode 100644 index 000000000..b66997470 --- /dev/null +++ b/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/dao/config/DataSourceFactory.java @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2023 sovity GmbH + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + * + * Contributors: + * sovity GmbH - initial implementation + * + */ + +package de.sovity.edc.ext.catalog.crawler.dao.config; + +import com.zaxxer.hikari.HikariDataSource; +import de.sovity.edc.ext.catalog.crawler.CrawlerExtension; +import de.sovity.edc.extension.postgresql.HikariDataSourceFactory; +import de.sovity.edc.extension.postgresql.JdbcCredentials; +import lombok.RequiredArgsConstructor; +import org.apache.commons.lang3.Validate; +import org.eclipse.edc.spi.system.configuration.Config; + +import javax.sql.DataSource; + +@RequiredArgsConstructor +public class DataSourceFactory { + private final Config config; + + + /** + * Create a new {@link DataSource} from EDC Config. + * + * @return {@link DataSource}. + */ + public HikariDataSource newDataSource() { + var jdbcCredentials = getJdbcCredentials(); + int maxPoolSize = config.getInteger(CrawlerExtension.DB_CONNECTION_POOL_SIZE); + int connectionTimeoutInMs = config.getInteger(CrawlerExtension.DB_CONNECTION_TIMEOUT_IN_MS); + return HikariDataSourceFactory.newDataSource( + jdbcCredentials, + maxPoolSize, + connectionTimeoutInMs + ); + } + + + public JdbcCredentials getJdbcCredentials() { + return new JdbcCredentials( + getRequiredStringProperty(config, CrawlerExtension.JDBC_URL), + getRequiredStringProperty(config, CrawlerExtension.JDBC_USER), + getRequiredStringProperty(config, CrawlerExtension.JDBC_PASSWORD) + ); + } + + private String getRequiredStringProperty(Config config, String name) { + String value = config.getString(name, ""); + Validate.notBlank(value, "EDC Property '%s' is required".formatted(name)); + return value; + } + +} diff --git a/extensions/broker-server-postgres-flyway-jooq/src/main/java/de/sovity/edc/ext/brokerserver/db/DslContextFactory.java b/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/dao/config/DslContextFactory.java similarity index 67% rename from extensions/broker-server-postgres-flyway-jooq/src/main/java/de/sovity/edc/ext/brokerserver/db/DslContextFactory.java rename to extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/dao/config/DslContextFactory.java index 4aafd44fe..6f97871bb 100644 --- a/extensions/broker-server-postgres-flyway-jooq/src/main/java/de/sovity/edc/ext/brokerserver/db/DslContextFactory.java +++ b/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/dao/config/DslContextFactory.java @@ -1,11 +1,10 @@ -package de.sovity.edc.ext.brokerserver.db; +package de.sovity.edc.ext.catalog.crawler.dao.config; import lombok.RequiredArgsConstructor; import org.jooq.DSLContext; import org.jooq.SQLDialect; import org.jooq.impl.DSL; -import java.util.Objects; import java.util.function.Consumer; import java.util.function.Function; import javax.sql.DataSource; @@ -23,8 +22,7 @@ public class DslContextFactory { * @return new {@link DSLContext} */ public DSLContext newDslContext() { - var globalDslContextForDbTests = DslContextFactoryHijacker.getParentDslContext(); - return Objects.requireNonNullElseGet(globalDslContextForDbTests, () -> DSL.using(dataSource, SQLDialect.POSTGRES)); + return DSL.using(dataSource, SQLDialect.POSTGRES); } /** @@ -47,4 +45,23 @@ public R transactionResult(Function function) { public void transaction(Consumer function) { newDslContext().transaction(transaction -> function.accept(transaction.dsl())); } + + /** + * Runs given code within a test transaction. + * + * @param code code to run within the test transaction + */ + public void testTransaction(Consumer code) { + try { + transaction(dsl -> { + code.accept(dsl); + throw new TestTransactionNoopException(); + }); + } catch (TestTransactionNoopException e) { + // Ignore + } + } + + private static class TestTransactionNoopException extends RuntimeException { + } } diff --git a/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/dao/config/FlywayService.java b/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/dao/config/FlywayService.java new file mode 100644 index 000000000..dee88e32b --- /dev/null +++ b/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/dao/config/FlywayService.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2023 sovity GmbH + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + * + * Contributors: + * sovity GmbH - initial implementation + * + */ + +package de.sovity.edc.ext.catalog.crawler.dao.config; + +import de.sovity.edc.ext.catalog.crawler.CrawlerExtension; +import de.sovity.edc.extension.postgresql.FlywayExecutionParams; +import de.sovity.edc.extension.postgresql.FlywayUtils; +import lombok.RequiredArgsConstructor; +import org.eclipse.edc.spi.monitor.Monitor; +import org.eclipse.edc.spi.system.configuration.Config; + +import javax.sql.DataSource; + +@RequiredArgsConstructor +public class FlywayService { + private final Config config; + private final Monitor monitor; + private final DataSource dataSource; + + public void validateOrMigrateInTests() { + var additionalLocations = config.getString(CrawlerExtension.DB_ADDITIONAL_FLYWAY_MIGRATION_LOCATIONS, ""); + + var params = baseConfig(additionalLocations) + .clean(config.getBoolean(CrawlerExtension.DB_CLEAN, false)) + .cleanEnabled(config.getBoolean(CrawlerExtension.DB_CLEAN_ENABLED, false)) + .migrate(config.getBoolean(CrawlerExtension.DB_MIGRATE, false)) + .infoLogger(monitor::info) + .build(); + + FlywayUtils.cleanAndMigrate(params, dataSource); + } + + public static FlywayExecutionParams.FlywayExecutionParamsBuilder baseConfig(String additionalMigrationLocations) { + var migrationLocations = FlywayUtils.parseFlywayLocations( + "classpath:db-crawler/migration,%s".formatted(additionalMigrationLocations) + ); + + return FlywayExecutionParams.builder() + .migrationLocations(migrationLocations) + .table("flyway_schema_history"); + } +} diff --git a/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/dao/connectors/ConnectorQueries.java b/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/dao/connectors/ConnectorQueries.java new file mode 100644 index 000000000..4c3e3843b --- /dev/null +++ b/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/dao/connectors/ConnectorQueries.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2023 sovity GmbH + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + * + * Contributors: + * sovity GmbH - initial API and implementation + * + */ + +package de.sovity.edc.ext.catalog.crawler.dao.connectors; + +import de.sovity.edc.ext.catalog.crawler.db.jooq.Tables; +import de.sovity.edc.ext.catalog.crawler.db.jooq.enums.ConnectorOnlineStatus; +import de.sovity.edc.ext.catalog.crawler.db.jooq.tables.Connector; +import de.sovity.edc.ext.catalog.crawler.db.jooq.tables.Organization; +import de.sovity.edc.ext.catalog.crawler.db.jooq.tables.records.ConnectorRecord; +import de.sovity.edc.ext.catalog.crawler.orchestration.config.CrawlerConfig; +import lombok.RequiredArgsConstructor; +import org.jetbrains.annotations.NotNull; +import org.jooq.Condition; +import org.jooq.DSLContext; + +import java.time.Duration; +import java.time.OffsetDateTime; +import java.util.HashSet; +import java.util.Set; +import java.util.function.BiFunction; + +@RequiredArgsConstructor +public class ConnectorQueries { + private final CrawlerConfig crawlerConfig; + + public ConnectorRecord findByConnectorId(DSLContext dsl, String connectorId) { + var c = Tables.CONNECTOR; + return dsl.fetchOne(c, c.CONNECTOR_ID.eq(connectorId)); + } + + public Set findConnectorsForScheduledRefresh(DSLContext dsl, ConnectorOnlineStatus onlineStatus) { + return queryConnectorRefs(dsl, (c, o) -> c.ONLINE_STATUS.eq(onlineStatus)); + } + + public Set findAllConnectorsForKilling(DSLContext dsl, Duration deleteOfflineConnectorsAfter) { + var minLastRefresh = OffsetDateTime.now().minus(deleteOfflineConnectorsAfter); + return queryConnectorRefs(dsl, (c, o) -> c.LAST_SUCCESSFUL_REFRESH_AT.lt(minLastRefresh)); + } + + @NotNull + private Set queryConnectorRefs( + DSLContext dsl, + BiFunction condition + ) { + var c = Tables.CONNECTOR; + var o = Tables.ORGANIZATION; + var query = dsl.select( + c.CONNECTOR_ID.as("connectorId"), + c.ENVIRONMENT.as("environmentId"), + o.NAME.as("organizationLegalName"), + o.MDS_ID.as("organizationId"), + c.ENDPOINT_URL.as("endpoint") + ) + .from(c) + .leftJoin(o).on(c.MDS_ID.eq(o.MDS_ID)) + .where(condition.apply(c, o), c.ENVIRONMENT.eq(crawlerConfig.getEnvironmentId())) + .fetchInto(ConnectorRef.class); + + return new HashSet<>(query); + } +} diff --git a/extensions/broker-server-api/api/src/main/java/de/sovity/edc/ext/brokerserver/api/model/CatalogPageSortingType.java b/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/dao/connectors/ConnectorRef.java similarity index 51% rename from extensions/broker-server-api/api/src/main/java/de/sovity/edc/ext/brokerserver/api/model/CatalogPageSortingType.java rename to extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/dao/connectors/ConnectorRef.java index 38e404bb5..3d94fca72 100644 --- a/extensions/broker-server-api/api/src/main/java/de/sovity/edc/ext/brokerserver/api/model/CatalogPageSortingType.java +++ b/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/dao/connectors/ConnectorRef.java @@ -12,21 +12,21 @@ * */ -package de.sovity.edc.ext.brokerserver.api.model; +package de.sovity.edc.ext.catalog.crawler.dao.connectors; -import io.swagger.v3.oas.annotations.media.Schema; +import lombok.EqualsAndHashCode; import lombok.Getter; import lombok.RequiredArgsConstructor; +import lombok.ToString; @Getter @RequiredArgsConstructor -@Schema(description = "Catalog's sorting options") -public enum CatalogPageSortingType { - VIEW_COUNT("By Popularity"), - MOST_RECENT("Most Recent"), - TITLE("By Title"), - ORIGINATOR("By Connector"); - - private final String title; +@EqualsAndHashCode(of = "connectorId", callSuper = false) +@ToString(of = "connectorId") +public class ConnectorRef { + private final String connectorId; + private final String environmentId; + private final String organizationLegalName; + private final String organizationId; + private final String endpoint; } - diff --git a/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/dao/connectors/ConnectorStatusUpdater.java b/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/dao/connectors/ConnectorStatusUpdater.java new file mode 100644 index 000000000..6dfad8125 --- /dev/null +++ b/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/dao/connectors/ConnectorStatusUpdater.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2023 sovity GmbH + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + * + * Contributors: + * sovity GmbH - initial API and implementation + * + */ + +package de.sovity.edc.ext.catalog.crawler.dao.connectors; + +import de.sovity.edc.ext.catalog.crawler.dao.utils.PostgresqlUtils; +import de.sovity.edc.ext.catalog.crawler.db.jooq.Tables; +import de.sovity.edc.ext.catalog.crawler.db.jooq.enums.ConnectorOnlineStatus; +import org.jooq.DSLContext; + +import java.util.Collection; +import java.util.stream.Collectors; + +public class ConnectorStatusUpdater { + public void markAsDead(DSLContext dsl, Collection connectorRefs) { + var connectorIds = connectorRefs.stream() + .map(ConnectorRef::getConnectorId) + .collect(Collectors.toSet()); + var c = Tables.CONNECTOR; + dsl.update(c).set(c.ONLINE_STATUS, ConnectorOnlineStatus.DEAD) + .where(PostgresqlUtils.in(c.CONNECTOR_ID, connectorIds)).execute(); + } +} diff --git a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/dao/ContractOfferQueries.java b/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/dao/contract_offers/ContractOfferQueries.java similarity index 56% rename from extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/dao/ContractOfferQueries.java rename to extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/dao/contract_offers/ContractOfferQueries.java index be5ef734c..0d350e429 100644 --- a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/dao/ContractOfferQueries.java +++ b/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/dao/contract_offers/ContractOfferQueries.java @@ -12,18 +12,18 @@ * */ -package de.sovity.edc.ext.brokerserver.dao; +package de.sovity.edc.ext.catalog.crawler.dao.contract_offers; -import de.sovity.edc.ext.brokerserver.db.jooq.Tables; -import de.sovity.edc.ext.brokerserver.db.jooq.tables.records.ContractOfferRecord; +import de.sovity.edc.ext.catalog.crawler.db.jooq.Tables; +import de.sovity.edc.ext.catalog.crawler.db.jooq.tables.records.ContractOfferRecord; import org.jooq.DSLContext; import java.util.List; public class ContractOfferQueries { - public List findByConnectorEndpoint(DSLContext dsl, String connectorEndpoint) { + public List findByConnectorId(DSLContext dsl, String connectorId) { var co = Tables.CONTRACT_OFFER; - return dsl.selectFrom(co).where(co.CONNECTOR_ENDPOINT.eq(connectorEndpoint)).stream().toList(); + return dsl.selectFrom(co).where(co.CONNECTOR_ID.eq(connectorId)).stream().toList(); } } diff --git a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/refreshing/offers/ContractOfferRecordUpdater.java b/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/dao/contract_offers/ContractOfferRecordUpdater.java similarity index 52% rename from extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/refreshing/offers/ContractOfferRecordUpdater.java rename to extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/dao/contract_offers/ContractOfferRecordUpdater.java index 3b3980294..ed23d2f07 100644 --- a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/refreshing/offers/ContractOfferRecordUpdater.java +++ b/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/dao/contract_offers/ContractOfferRecordUpdater.java @@ -12,17 +12,18 @@ * */ -package de.sovity.edc.ext.brokerserver.services.refreshing.offers; +package de.sovity.edc.ext.catalog.crawler.dao.contract_offers; -import de.sovity.edc.ext.brokerserver.dao.utils.JsonbUtils; -import de.sovity.edc.ext.brokerserver.db.jooq.tables.records.ContractOfferRecord; -import de.sovity.edc.ext.brokerserver.db.jooq.tables.records.DataOfferRecord; -import de.sovity.edc.ext.brokerserver.services.refreshing.offers.model.FetchedContractOffer; +import de.sovity.edc.ext.catalog.crawler.crawling.fetching.model.FetchedContractOffer; +import de.sovity.edc.ext.catalog.crawler.crawling.writing.utils.ChangeTracker; +import de.sovity.edc.ext.catalog.crawler.dao.utils.JsonbUtils; +import de.sovity.edc.ext.catalog.crawler.db.jooq.tables.records.ContractOfferRecord; +import de.sovity.edc.ext.catalog.crawler.db.jooq.tables.records.DataOfferRecord; +import de.sovity.edc.ext.catalog.crawler.utils.JsonUtils2; import lombok.RequiredArgsConstructor; import org.jooq.JSONB; import java.time.OffsetDateTime; -import java.util.Objects; /** * Creates or updates {@link ContractOfferRecord} DB Rows. @@ -35,13 +36,17 @@ public class ContractOfferRecordUpdater { /** * Create new {@link ContractOfferRecord} from {@link FetchedContractOffer}. * - * @param dataOffer parent data offer db row + * @param dataOffer parent data offer db row * @param fetchedContractOffer fetched contract offer * @return new db row */ - public ContractOfferRecord newContractOffer(DataOfferRecord dataOffer, FetchedContractOffer fetchedContractOffer) { + public ContractOfferRecord newContractOffer( + DataOfferRecord dataOffer, + FetchedContractOffer fetchedContractOffer + ) { var contractOffer = new ContractOfferRecord(); - contractOffer.setConnectorEndpoint(dataOffer.getConnectorEndpoint()); + + contractOffer.setConnectorId(dataOffer.getConnectorId()); contractOffer.setContractOfferId(fetchedContractOffer.getContractOfferId()); contractOffer.setAssetId(dataOffer.getAssetId()); contractOffer.setCreatedAt(OffsetDateTime.now()); @@ -52,24 +57,27 @@ public ContractOfferRecord newContractOffer(DataOfferRecord dataOffer, FetchedCo /** * Update existing {@link ContractOfferRecord} with changes from {@link FetchedContractOffer}. * - * @param contractOffer existing row + * @param contractOffer existing row * @param fetchedContractOffer changes to be integrated * @return if anything was changed */ - public boolean updateContractOffer(ContractOfferRecord contractOffer, FetchedContractOffer fetchedContractOffer) { - var existingPolicy = JsonbUtils.getDataOrNull(contractOffer.getPolicy()); - var fetchedPolicy = fetchedContractOffer.getPolicyJson(); - var changed = false; + public boolean updateContractOffer( + ContractOfferRecord contractOffer, + FetchedContractOffer fetchedContractOffer + ) { + var changes = new ChangeTracker(); - if (!Objects.equals(existingPolicy, fetchedPolicy)) { - contractOffer.setPolicy(JSONB.jsonb(fetchedPolicy)); - changed = true; - } + changes.setIfChanged( + JsonbUtils.getDataOrNull(contractOffer.getUiPolicyJson()), + fetchedContractOffer.getUiPolicyJson(), + it -> contractOffer.setUiPolicyJson(JSONB.jsonb(it)), + JsonUtils2::isEqualJson + ); - if (changed) { + if (changes.isChanged()) { contractOffer.setUpdatedAt(OffsetDateTime.now()); } - return changed; + return changes.isChanged(); } } diff --git a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/dao/DataOfferQueries.java b/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/dao/data_offers/DataOfferQueries.java similarity index 59% rename from extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/dao/DataOfferQueries.java rename to extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/dao/data_offers/DataOfferQueries.java index fed263bd0..f4a82b14c 100644 --- a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/dao/DataOfferQueries.java +++ b/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/dao/data_offers/DataOfferQueries.java @@ -12,10 +12,10 @@ * */ -package de.sovity.edc.ext.brokerserver.dao; +package de.sovity.edc.ext.catalog.crawler.dao.data_offers; -import de.sovity.edc.ext.brokerserver.db.jooq.Tables; -import de.sovity.edc.ext.brokerserver.db.jooq.tables.records.DataOfferRecord; +import de.sovity.edc.ext.catalog.crawler.db.jooq.Tables; +import de.sovity.edc.ext.catalog.crawler.db.jooq.tables.records.DataOfferRecord; import lombok.RequiredArgsConstructor; import org.jooq.DSLContext; @@ -24,8 +24,8 @@ @RequiredArgsConstructor public class DataOfferQueries { - public List findByConnectorEndpoint(DSLContext dsl, String connectorEndpoint) { + public List findByConnectorId(DSLContext dsl, String connectorId) { var d = Tables.DATA_OFFER; - return dsl.selectFrom(d).where(d.CONNECTOR_ENDPOINT.eq(connectorEndpoint)).stream().toList(); + return dsl.selectFrom(d).where(d.CONNECTOR_ID.eq(connectorId)).stream().toList(); } } diff --git a/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/dao/data_offers/DataOfferRecordUpdater.java b/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/dao/data_offers/DataOfferRecordUpdater.java new file mode 100644 index 000000000..c09a3d0b8 --- /dev/null +++ b/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/dao/data_offers/DataOfferRecordUpdater.java @@ -0,0 +1,162 @@ +/* + * Copyright (c) 2023 sovity GmbH + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + * + * Contributors: + * sovity GmbH - initial API and implementation + * + */ + +package de.sovity.edc.ext.catalog.crawler.dao.data_offers; + +import de.sovity.edc.ext.catalog.crawler.crawling.fetching.model.FetchedDataOffer; +import de.sovity.edc.ext.catalog.crawler.crawling.writing.utils.ChangeTracker; +import de.sovity.edc.ext.catalog.crawler.dao.connectors.ConnectorRef; +import de.sovity.edc.ext.catalog.crawler.dao.utils.JsonbUtils; +import de.sovity.edc.ext.catalog.crawler.db.jooq.tables.records.DataOfferRecord; +import de.sovity.edc.ext.catalog.crawler.utils.JsonUtils2; +import de.sovity.edc.ext.wrapper.api.common.mappers.asset.utils.ShortDescriptionBuilder; +import lombok.RequiredArgsConstructor; +import org.jooq.JSONB; + +import java.time.OffsetDateTime; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; + +/** + * Creates or updates {@link DataOfferRecord} DB Rows. + *

+ * (Or at least prepares them for batch inserts / updates) + */ +@RequiredArgsConstructor +public class DataOfferRecordUpdater { + private final ShortDescriptionBuilder shortDescriptionBuilder; + + /** + * Create a new {@link DataOfferRecord}. + * + * @param connectorRef connector + * @param fetchedDataOffer new db row data + * @return new db row + */ + public DataOfferRecord newDataOffer( + ConnectorRef connectorRef, + FetchedDataOffer fetchedDataOffer + ) { + var dataOffer = new DataOfferRecord(); + var connectorId = connectorRef.getConnectorId(); + + dataOffer.setConnectorId(connectorId); + dataOffer.setAssetId(fetchedDataOffer.getAssetId()); + dataOffer.setCreatedAt(OffsetDateTime.now()); + updateDataOffer(dataOffer, fetchedDataOffer, true); + return dataOffer; + } + + + /** + * Update existing {@link DataOfferRecord}. + * + * @param record existing row + * @param fetchedDataOffer changes to be incorporated + * @param changed whether the data offer should be marked as updated simply because the contract offers changed + * @return whether any fields were updated + */ + public boolean updateDataOffer( + DataOfferRecord record, + FetchedDataOffer fetchedDataOffer, + boolean changed + ) { + var asset = fetchedDataOffer.getUiAsset(); + var changes = new ChangeTracker(changed); + + changes.setIfChanged( + blankIfNull(record.getAssetTitle()), + blankIfNull(asset.getTitle()), + record::setAssetTitle + ); + + changes.setIfChanged( + blankIfNull(record.getDescriptionNoMarkdown()), + shortDescriptionBuilder.extractMarkdownText(blankIfNull(asset.getDescription())), + record::setDescriptionNoMarkdown + ); + + changes.setIfChanged( + blankIfNull(record.getShortDescriptionNoMarkdown()), + blankIfNull(asset.getDescriptionShortText()), + record::setShortDescriptionNoMarkdown + ); + + changes.setIfChanged( + blankIfNull(record.getDataCategory()), + blankIfNull(asset.getDataCategory()), + record::setDataCategory + ); + + changes.setIfChanged( + blankIfNull(record.getDataSubcategory()), + blankIfNull(asset.getDataSubcategory()), + record::setDataSubcategory + ); + + changes.setIfChanged( + blankIfNull(record.getDataModel()), + blankIfNull(asset.getDataModel()), + record::setDataModel + ); + + changes.setIfChanged( + blankIfNull(record.getTransportMode()), + blankIfNull(asset.getTransportMode()), + record::setTransportMode + ); + + changes.setIfChanged( + blankIfNull(record.getGeoReferenceMethod()), + blankIfNull(asset.getGeoReferenceMethod()), + record::setGeoReferenceMethod + ); + + changes.setIfChanged( + emptyIfNull(record.getKeywords()), + emptyIfNull(asset.getKeywords()), + it -> { + record.setKeywords(it.toArray(new String[0])); + record.setKeywordsCommaJoined(String.join(", ", it)); + } + ); + + changes.setIfChanged( + JsonbUtils.getDataOrNull(record.getUiAssetJson()), + fetchedDataOffer.getUiAssetJson(), + it -> record.setUiAssetJson(JSONB.jsonb(it)), + JsonUtils2::isEqualJson + ); + + if (changes.isChanged()) { + record.setUpdatedAt(OffsetDateTime.now()); + } + + return changes.isChanged(); + } + + private String blankIfNull(String string) { + return string == null ? "" : string; + } + + private Collection emptyIfNull(Collection collection) { + return collection == null ? List.of() : collection; + } + + private Collection emptyIfNull(T[] array) { + return array == null ? List.of() : Arrays.asList(array); + } + +} diff --git a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/dao/utils/JsonbUtils.java b/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/dao/utils/JsonbUtils.java similarity index 94% rename from extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/dao/utils/JsonbUtils.java rename to extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/dao/utils/JsonbUtils.java index 0a5157624..c3afdbabd 100644 --- a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/dao/utils/JsonbUtils.java +++ b/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/dao/utils/JsonbUtils.java @@ -12,7 +12,7 @@ * */ -package de.sovity.edc.ext.brokerserver.dao.utils; +package de.sovity.edc.ext.catalog.crawler.dao.utils; import lombok.AccessLevel; import lombok.NoArgsConstructor; diff --git a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/dao/utils/PostgresqlUtils.java b/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/dao/utils/PostgresqlUtils.java similarity index 92% rename from extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/dao/utils/PostgresqlUtils.java rename to extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/dao/utils/PostgresqlUtils.java index e5291de5e..4c7cd3e41 100644 --- a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/dao/utils/PostgresqlUtils.java +++ b/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/dao/utils/PostgresqlUtils.java @@ -12,7 +12,7 @@ * */ -package de.sovity.edc.ext.brokerserver.dao.utils; +package de.sovity.edc.ext.catalog.crawler.dao.utils; import lombok.AccessLevel; import lombok.NoArgsConstructor; @@ -31,7 +31,7 @@ public class PostgresqlUtils { /** * Replaces the IN operation with "field = ANY(...)" * - * @param field field + * @param field field * @param values values * @return condition */ diff --git a/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/dao/utils/RecordPatch.java b/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/dao/utils/RecordPatch.java new file mode 100644 index 000000000..99c6a025a --- /dev/null +++ b/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/dao/utils/RecordPatch.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2023 sovity GmbH + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + * + * Contributors: + * sovity GmbH - initial API and implementation + * + */ + +package de.sovity.edc.ext.catalog.crawler.dao.utils; + +import lombok.AccessLevel; +import lombok.Getter; +import lombok.experimental.FieldDefaults; +import org.jooq.UpdatableRecord; + +import java.util.ArrayList; +import java.util.List; + +/** + * Contains planned DB Row changes to be applied as batch. + */ +@Getter +@FieldDefaults(level = AccessLevel.PRIVATE, makeFinal = true) +public class RecordPatch> { + List insertions = new ArrayList<>(); + List updates = new ArrayList<>(); + List deletions = new ArrayList<>(); + + public void insert(T record) { + insertions.add(record); + } + + public void update(T record) { + updates.add(record); + } + + public void delete(T record) { + deletions.add(record); + } +} diff --git a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/config/BrokerServerSettings.java b/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/orchestration/config/CrawlerConfig.java similarity index 72% rename from extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/config/BrokerServerSettings.java rename to extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/orchestration/config/CrawlerConfig.java index cc4083105..af3e2a0f4 100644 --- a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/config/BrokerServerSettings.java +++ b/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/orchestration/config/CrawlerConfig.java @@ -12,7 +12,7 @@ * */ -package de.sovity.edc.ext.brokerserver.services.config; +package de.sovity.edc.ext.catalog.crawler.orchestration.config; import lombok.Builder; import lombok.Value; @@ -21,14 +21,8 @@ @Value @Builder -public class BrokerServerSettings { - String adminApiKey; - Duration hideOfflineDataOffersAfter; - - int catalogPagePageSize; - - DataSpaceConfig dataSpaceConfig; - +public class CrawlerConfig { + String environmentId; int numThreads; Duration killOfflineConnectorsAfter; diff --git a/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/orchestration/config/CrawlerConfigFactory.java b/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/orchestration/config/CrawlerConfigFactory.java new file mode 100644 index 000000000..f40e6b6af --- /dev/null +++ b/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/orchestration/config/CrawlerConfigFactory.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2023 sovity GmbH + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + * + * Contributors: + * sovity GmbH - initial API and implementation + * + */ + +package de.sovity.edc.ext.catalog.crawler.orchestration.config; + +import de.sovity.edc.ext.catalog.crawler.CrawlerExtension; +import lombok.NonNull; +import lombok.RequiredArgsConstructor; +import org.apache.commons.lang3.StringUtils; +import org.eclipse.edc.spi.system.configuration.Config; + +import java.time.Duration; + +@RequiredArgsConstructor +public class CrawlerConfigFactory { + private final Config config; + + public CrawlerConfig buildCrawlerConfig() { + var environmentId = config.getString(CrawlerExtension.ENVIRONMENT_ID); + var numThreads = config.getInteger(CrawlerExtension.NUM_THREADS, 1); + var killOfflineConnectorsAfter = getDuration(CrawlerExtension.KILL_OFFLINE_CONNECTORS_AFTER, Duration.ofDays(5)); + var maxDataOffers = config.getInteger(CrawlerExtension.MAX_DATA_OFFERS_PER_CONNECTOR, -1); + var maxContractOffers = config.getInteger(CrawlerExtension.MAX_CONTRACT_OFFERS_PER_DATA_OFFER, -1); + + return CrawlerConfig.builder() + .environmentId(environmentId) + .numThreads(numThreads) + .killOfflineConnectorsAfter(killOfflineConnectorsAfter) + .maxDataOffersPerConnector(maxDataOffers) + .maxContractOffersPerDataOffer(maxContractOffers) + .build(); + } + + private Duration getDuration(@NonNull String configProperty, Duration defaultValue) { + var value = config.getString(configProperty, ""); + + if (StringUtils.isBlank(value)) { + return defaultValue; + } + + return Duration.parse(value); + } +} diff --git a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/config/EdcConfigPropertyUtils.java b/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/orchestration/config/EdcConfigPropertyUtils.java similarity index 83% rename from extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/config/EdcConfigPropertyUtils.java rename to extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/orchestration/config/EdcConfigPropertyUtils.java index 4ce3fd64b..c0d9bdb5f 100644 --- a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/config/EdcConfigPropertyUtils.java +++ b/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/orchestration/config/EdcConfigPropertyUtils.java @@ -12,7 +12,7 @@ * */ -package de.sovity.edc.ext.brokerserver.services.config; +package de.sovity.edc.ext.catalog.crawler.orchestration.config; import lombok.AccessLevel; import lombok.NoArgsConstructor; @@ -27,8 +27,8 @@ public class EdcConfigPropertyUtils { * For better refactoring it is better if the string constant is * found in the code as it is used and documented. * - * @param envVarName e.g. "BROKER_SERVER_SOME_CONFIG_SETTING" - * @return e.g. "broker.server.some.config.setting" + * @param envVarName e.g. "MY_EDC_PROP" + * @return e.g. "my.edc.prop" */ public static String toEdcProp(String envVarName) { return Arrays.stream(envVarName.split("_")) diff --git a/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/orchestration/queue/ConnectorQueue.java b/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/orchestration/queue/ConnectorQueue.java new file mode 100644 index 000000000..e46808a3a --- /dev/null +++ b/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/orchestration/queue/ConnectorQueue.java @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2023 sovity GmbH + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + * + * Contributors: + * sovity GmbH - initial API and implementation + * + */ + +package de.sovity.edc.ext.catalog.crawler.orchestration.queue; + +import de.sovity.edc.ext.catalog.crawler.crawling.ConnectorCrawler; +import de.sovity.edc.ext.catalog.crawler.dao.connectors.ConnectorRef; +import lombok.RequiredArgsConstructor; + +import java.util.ArrayList; +import java.util.Collection; + +@RequiredArgsConstructor +public class ConnectorQueue { + private final ConnectorCrawler connectorCrawler; + private final ThreadPool threadPool; + + /** + * Enqueues connectors for update. + * + * @param connectorRefs connectors + * @param priority priority from {@link ConnectorRefreshPriority} + */ + public void addAll(Collection connectorRefs, int priority) { + var queued = threadPool.getQueuedConnectorRefs(); + connectorRefs = new ArrayList<>(connectorRefs); + connectorRefs.removeIf(queued::contains); + + for (var connectorRef : connectorRefs) { + threadPool.enqueueConnectorRefreshTask( + priority, + () -> connectorCrawler.crawlConnector(connectorRef), + connectorRef + ); + } + } +} diff --git a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/queue/ConnectorQueueFiller.java b/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/orchestration/queue/ConnectorQueueFiller.java similarity index 65% rename from extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/queue/ConnectorQueueFiller.java rename to extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/orchestration/queue/ConnectorQueueFiller.java index e85a652e4..aaf2d7da9 100644 --- a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/queue/ConnectorQueueFiller.java +++ b/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/orchestration/queue/ConnectorQueueFiller.java @@ -12,10 +12,10 @@ * */ -package de.sovity.edc.ext.brokerserver.services.queue; +package de.sovity.edc.ext.catalog.crawler.orchestration.queue; -import de.sovity.edc.ext.brokerserver.dao.ConnectorQueries; -import de.sovity.edc.ext.brokerserver.db.jooq.enums.ConnectorOnlineStatus; +import de.sovity.edc.ext.catalog.crawler.dao.connectors.ConnectorQueries; +import de.sovity.edc.ext.catalog.crawler.db.jooq.enums.ConnectorOnlineStatus; import lombok.RequiredArgsConstructor; import org.jooq.DSLContext; @@ -25,7 +25,7 @@ public class ConnectorQueueFiller { private final ConnectorQueries connectorQueries; public void enqueueConnectors(DSLContext dsl, ConnectorOnlineStatus status, int priority) { - var endpoints = connectorQueries.findConnectorsForScheduledRefresh(dsl, status); - connectorQueue.addAll(endpoints, priority); + var connectorRefs = connectorQueries.findConnectorsForScheduledRefresh(dsl, status); + connectorQueue.addAll(connectorRefs, priority); } } diff --git a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/queue/ConnectorRefreshPriority.java b/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/orchestration/queue/ConnectorRefreshPriority.java similarity index 76% rename from extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/queue/ConnectorRefreshPriority.java rename to extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/orchestration/queue/ConnectorRefreshPriority.java index 6931aad63..541c8528b 100644 --- a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/queue/ConnectorRefreshPriority.java +++ b/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/orchestration/queue/ConnectorRefreshPriority.java @@ -12,15 +12,12 @@ * */ -package de.sovity.edc.ext.brokerserver.services.queue; +package de.sovity.edc.ext.catalog.crawler.orchestration.queue; import lombok.NoArgsConstructor; @NoArgsConstructor(access = lombok.AccessLevel.PRIVATE) public class ConnectorRefreshPriority { - public static final int ADMIN_REQUESTED = 1; - public static final int ADDED_ON_STARTUP = 10; - public static final int ADDED_ON_API_CALL = 50; public static final int SCHEDULED_ONLINE_REFRESH = 100; public static final int SCHEDULED_OFFLINE_REFRESH = 200; public static final int SCHEDULED_DEAD_REFRESH = 300; diff --git a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/queue/ThreadPool.java b/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/orchestration/queue/ThreadPool.java similarity index 74% rename from extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/queue/ThreadPool.java rename to extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/orchestration/queue/ThreadPool.java index 022751243..857bf32ed 100644 --- a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/queue/ThreadPool.java +++ b/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/orchestration/queue/ThreadPool.java @@ -12,9 +12,10 @@ * */ -package de.sovity.edc.ext.brokerserver.services.queue; +package de.sovity.edc.ext.catalog.crawler.orchestration.queue; -import de.sovity.edc.ext.brokerserver.services.config.BrokerServerSettings; +import de.sovity.edc.ext.catalog.crawler.dao.connectors.ConnectorRef; +import de.sovity.edc.ext.catalog.crawler.orchestration.config.CrawlerConfig; import org.eclipse.edc.spi.monitor.Monitor; import java.util.Set; @@ -27,9 +28,9 @@ public class ThreadPool { private final boolean enabled; private final ThreadPoolExecutor threadPoolExecutor; - public ThreadPool(ThreadPoolTaskQueue queue, BrokerServerSettings brokerServerSettings, Monitor monitor) { + public ThreadPool(ThreadPoolTaskQueue queue, CrawlerConfig crawlerConfig, Monitor monitor) { this.queue = queue; - int numThreads = brokerServerSettings.getNumThreads(); + int numThreads = crawlerConfig.getNumThreads(); enabled = numThreads > 0; if (enabled) { @@ -48,12 +49,12 @@ public ThreadPool(ThreadPoolTaskQueue queue, BrokerServerSettings brokerServerSe } } - public void enqueueConnectorRefreshTask(int priority, Runnable runnable, String endpoint) { - enqueueTask(new ThreadPoolTask(priority, runnable, endpoint)); + public void enqueueConnectorRefreshTask(int priority, Runnable runnable, ConnectorRef connectorRef) { + enqueueTask(new ThreadPoolTask(priority, runnable, connectorRef)); } - public Set getQueuedConnectorEndpoints() { - return queue.getConnectorEndpoints(); + public Set getQueuedConnectorRefs() { + return queue.getConnectorRefs(); } private void enqueueTask(ThreadPoolTask task) { diff --git a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/queue/ThreadPoolTask.java b/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/orchestration/queue/ThreadPoolTask.java similarity index 86% rename from extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/queue/ThreadPoolTask.java rename to extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/orchestration/queue/ThreadPoolTask.java index ee69dd44f..66712b2d7 100644 --- a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/queue/ThreadPoolTask.java +++ b/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/orchestration/queue/ThreadPoolTask.java @@ -12,8 +12,9 @@ * */ -package de.sovity.edc.ext.brokerserver.services.queue; +package de.sovity.edc.ext.catalog.crawler.orchestration.queue; +import de.sovity.edc.ext.catalog.crawler.dao.connectors.ConnectorRef; import lombok.Getter; import lombok.RequiredArgsConstructor; @@ -35,7 +36,7 @@ public class ThreadPoolTask implements Runnable { private final long sequence = SEQ.incrementAndGet(); private final int priority; private final Runnable task; - private final String connectorEndpoint; + private final ConnectorRef connectorRef; @Override public void run() { diff --git a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/queue/ThreadPoolTaskQueue.java b/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/orchestration/queue/ThreadPoolTaskQueue.java similarity index 84% rename from extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/queue/ThreadPoolTaskQueue.java rename to extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/orchestration/queue/ThreadPoolTaskQueue.java index 44123180d..dc2b5598b 100644 --- a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/queue/ThreadPoolTaskQueue.java +++ b/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/orchestration/queue/ThreadPoolTaskQueue.java @@ -12,8 +12,9 @@ * */ -package de.sovity.edc.ext.brokerserver.services.queue; +package de.sovity.edc.ext.catalog.crawler.orchestration.queue; +import de.sovity.edc.ext.catalog.crawler.dao.connectors.ConnectorRef; import lombok.Getter; import lombok.RequiredArgsConstructor; @@ -38,11 +39,11 @@ public void add(ThreadPoolTask task) { queue.add(task); } - public Set getConnectorEndpoints() { + public Set getConnectorRefs() { var queuedRunnables = new ArrayList<>(queue); return queuedRunnables.stream() - .map(ThreadPoolTask::getConnectorEndpoint) + .map(ThreadPoolTask::getConnectorRef) .filter(Objects::nonNull) .collect(Collectors.toSet()); } diff --git a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/schedules/DeadConnectorRefreshJob.java b/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/orchestration/schedules/DeadConnectorRefreshJob.java similarity index 70% rename from extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/schedules/DeadConnectorRefreshJob.java rename to extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/orchestration/schedules/DeadConnectorRefreshJob.java index 63caca686..4f229b7fc 100644 --- a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/schedules/DeadConnectorRefreshJob.java +++ b/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/orchestration/schedules/DeadConnectorRefreshJob.java @@ -12,12 +12,12 @@ * */ -package de.sovity.edc.ext.brokerserver.services.schedules; +package de.sovity.edc.ext.catalog.crawler.orchestration.schedules; -import de.sovity.edc.ext.brokerserver.db.DslContextFactory; -import de.sovity.edc.ext.brokerserver.db.jooq.enums.ConnectorOnlineStatus; -import de.sovity.edc.ext.brokerserver.services.queue.ConnectorQueueFiller; -import de.sovity.edc.ext.brokerserver.services.queue.ConnectorRefreshPriority; +import de.sovity.edc.ext.catalog.crawler.dao.config.DslContextFactory; +import de.sovity.edc.ext.catalog.crawler.db.jooq.enums.ConnectorOnlineStatus; +import de.sovity.edc.ext.catalog.crawler.orchestration.queue.ConnectorQueueFiller; +import de.sovity.edc.ext.catalog.crawler.orchestration.queue.ConnectorRefreshPriority; import lombok.RequiredArgsConstructor; import org.quartz.Job; import org.quartz.JobExecutionContext; diff --git a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/schedules/OfflineConnectorKillerJob.java b/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/orchestration/schedules/OfflineConnectorCleanerJob.java similarity index 58% rename from extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/schedules/OfflineConnectorKillerJob.java rename to extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/orchestration/schedules/OfflineConnectorCleanerJob.java index f79826482..2c2e71853 100644 --- a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/schedules/OfflineConnectorKillerJob.java +++ b/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/orchestration/schedules/OfflineConnectorCleanerJob.java @@ -12,21 +12,21 @@ * */ -package de.sovity.edc.ext.brokerserver.services.schedules; +package de.sovity.edc.ext.catalog.crawler.orchestration.schedules; -import de.sovity.edc.ext.brokerserver.db.DslContextFactory; -import de.sovity.edc.ext.brokerserver.services.OfflineConnectorKiller; +import de.sovity.edc.ext.catalog.crawler.crawling.OfflineConnectorCleaner; +import de.sovity.edc.ext.catalog.crawler.dao.config.DslContextFactory; import lombok.RequiredArgsConstructor; import org.quartz.Job; import org.quartz.JobExecutionContext; @RequiredArgsConstructor -public class OfflineConnectorKillerJob implements Job { +public class OfflineConnectorCleanerJob implements Job { private final DslContextFactory dslContextFactory; - private final OfflineConnectorKiller offlineConnectorKiller; + private final OfflineConnectorCleaner offlineConnectorCleaner; @Override public void execute(JobExecutionContext context) { - dslContextFactory.transaction(offlineConnectorKiller::killIfOfflineTooLong); + dslContextFactory.transaction(offlineConnectorCleaner::cleanConnectorsIfOfflineTooLong); } } diff --git a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/schedules/OfflineConnectorRefreshJob.java b/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/orchestration/schedules/OfflineConnectorRefreshJob.java similarity index 70% rename from extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/schedules/OfflineConnectorRefreshJob.java rename to extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/orchestration/schedules/OfflineConnectorRefreshJob.java index 5cbeca52d..18965edf6 100644 --- a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/schedules/OfflineConnectorRefreshJob.java +++ b/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/orchestration/schedules/OfflineConnectorRefreshJob.java @@ -12,12 +12,12 @@ * */ -package de.sovity.edc.ext.brokerserver.services.schedules; +package de.sovity.edc.ext.catalog.crawler.orchestration.schedules; -import de.sovity.edc.ext.brokerserver.db.DslContextFactory; -import de.sovity.edc.ext.brokerserver.db.jooq.enums.ConnectorOnlineStatus; -import de.sovity.edc.ext.brokerserver.services.queue.ConnectorQueueFiller; -import de.sovity.edc.ext.brokerserver.services.queue.ConnectorRefreshPriority; +import de.sovity.edc.ext.catalog.crawler.dao.config.DslContextFactory; +import de.sovity.edc.ext.catalog.crawler.db.jooq.enums.ConnectorOnlineStatus; +import de.sovity.edc.ext.catalog.crawler.orchestration.queue.ConnectorQueueFiller; +import de.sovity.edc.ext.catalog.crawler.orchestration.queue.ConnectorRefreshPriority; import lombok.RequiredArgsConstructor; import org.quartz.Job; import org.quartz.JobExecutionContext; diff --git a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/schedules/OnlineConnectorRefreshJob.java b/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/orchestration/schedules/OnlineConnectorRefreshJob.java similarity index 70% rename from extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/schedules/OnlineConnectorRefreshJob.java rename to extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/orchestration/schedules/OnlineConnectorRefreshJob.java index 839a62321..6cad1899f 100644 --- a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/schedules/OnlineConnectorRefreshJob.java +++ b/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/orchestration/schedules/OnlineConnectorRefreshJob.java @@ -12,12 +12,12 @@ * */ -package de.sovity.edc.ext.brokerserver.services.schedules; +package de.sovity.edc.ext.catalog.crawler.orchestration.schedules; -import de.sovity.edc.ext.brokerserver.db.DslContextFactory; -import de.sovity.edc.ext.brokerserver.db.jooq.enums.ConnectorOnlineStatus; -import de.sovity.edc.ext.brokerserver.services.queue.ConnectorQueueFiller; -import de.sovity.edc.ext.brokerserver.services.queue.ConnectorRefreshPriority; +import de.sovity.edc.ext.catalog.crawler.dao.config.DslContextFactory; +import de.sovity.edc.ext.catalog.crawler.db.jooq.enums.ConnectorOnlineStatus; +import de.sovity.edc.ext.catalog.crawler.orchestration.queue.ConnectorQueueFiller; +import de.sovity.edc.ext.catalog.crawler.orchestration.queue.ConnectorRefreshPriority; import lombok.RequiredArgsConstructor; import org.quartz.Job; import org.quartz.JobExecutionContext; diff --git a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/schedules/QuartzScheduleInitializer.java b/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/orchestration/schedules/QuartzScheduleInitializer.java similarity index 90% rename from extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/schedules/QuartzScheduleInitializer.java rename to extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/orchestration/schedules/QuartzScheduleInitializer.java index 3e4fb294a..d4f4597e7 100644 --- a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/schedules/QuartzScheduleInitializer.java +++ b/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/orchestration/schedules/QuartzScheduleInitializer.java @@ -12,10 +12,10 @@ * */ -package de.sovity.edc.ext.brokerserver.services.schedules; +package de.sovity.edc.ext.catalog.crawler.orchestration.schedules; -import de.sovity.edc.ext.brokerserver.services.schedules.utils.CronJobRef; -import de.sovity.edc.ext.brokerserver.services.schedules.utils.JobFactoryImpl; +import de.sovity.edc.ext.catalog.crawler.orchestration.schedules.utils.CronJobRef; +import de.sovity.edc.ext.catalog.crawler.orchestration.schedules.utils.JobFactoryImpl; import lombok.RequiredArgsConstructor; import lombok.SneakyThrows; import org.apache.commons.lang3.StringUtils; diff --git a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/schedules/utils/CronJobRef.java b/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/orchestration/schedules/utils/CronJobRef.java similarity index 75% rename from extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/schedules/utils/CronJobRef.java rename to extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/orchestration/schedules/utils/CronJobRef.java index a98ad2cd7..8f435fd23 100644 --- a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/schedules/utils/CronJobRef.java +++ b/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/orchestration/schedules/utils/CronJobRef.java @@ -12,19 +12,19 @@ * */ -package de.sovity.edc.ext.brokerserver.services.schedules.utils; +package de.sovity.edc.ext.catalog.crawler.orchestration.schedules.utils; import org.quartz.Job; import java.util.function.Supplier; /** - * Broker Server CRON Job. + * CRON Job. * * @param configPropertyName EDC Config property that decides cron expression - * @param clazz class of the job - * @param factory factory that initializes the task class - * @param job type + * @param clazz class of the job + * @param factory factory that initializes the task class + * @param job type */ public record CronJobRef( String configPropertyName, diff --git a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/schedules/utils/JobFactoryImpl.java b/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/orchestration/schedules/utils/JobFactoryImpl.java similarity index 95% rename from extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/schedules/utils/JobFactoryImpl.java rename to extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/orchestration/schedules/utils/JobFactoryImpl.java index 9e1597ae2..003f0161d 100644 --- a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/services/schedules/utils/JobFactoryImpl.java +++ b/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/orchestration/schedules/utils/JobFactoryImpl.java @@ -12,7 +12,7 @@ * */ -package de.sovity.edc.ext.brokerserver.services.schedules.utils; +package de.sovity.edc.ext.catalog.crawler.orchestration.schedules.utils; import lombok.NonNull; import org.quartz.Job; diff --git a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/utils/CollectionUtils2.java b/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/utils/CollectionUtils2.java similarity index 82% rename from extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/utils/CollectionUtils2.java rename to extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/utils/CollectionUtils2.java index ef3337a62..f113d8601 100644 --- a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/utils/CollectionUtils2.java +++ b/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/utils/CollectionUtils2.java @@ -12,7 +12,7 @@ * */ -package de.sovity.edc.ext.brokerserver.utils; +package de.sovity.edc.ext.catalog.crawler.utils; import lombok.AccessLevel; import lombok.NoArgsConstructor; @@ -29,8 +29,8 @@ public class CollectionUtils2 { /** * Set Difference * - * @param a base set - * @param b remove these items + * @param a base set + * @param b remove these items * @param set item type * @return a difference b */ @@ -44,9 +44,9 @@ public static boolean isNotEmpty(Collection collection) { return collection != null && !collection.isEmpty(); } - public static List allElementsExceptForIndex(Collection source, int skipIndex) { + public static List reverse(List source) { var result = new ArrayList<>(source); - result.remove(skipIndex); + java.util.Collections.reverse(result); return result; } } diff --git a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/utils/JsonUtils2.java b/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/utils/JsonUtils2.java similarity index 74% rename from extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/utils/JsonUtils2.java rename to extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/utils/JsonUtils2.java index fbe1af366..a1d2d57bb 100644 --- a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/utils/JsonUtils2.java +++ b/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/utils/JsonUtils2.java @@ -12,7 +12,7 @@ * */ -package de.sovity.edc.ext.brokerserver.utils; +package de.sovity.edc.ext.catalog.crawler.utils; import com.fasterxml.jackson.databind.ObjectMapper; import lombok.AccessLevel; @@ -25,8 +25,8 @@ public class JsonUtils2 { @SneakyThrows public static boolean isEqualJson(String json, String otherJson) { - return - (json == null && otherJson == null) || - (json != null && otherJson != null && OBJECT_MAPPER.readTree(json).equals(OBJECT_MAPPER.readTree(otherJson))); + return (json == null && otherJson == null) || + (json != null && otherJson != null && + OBJECT_MAPPER.readTree(json).equals(OBJECT_MAPPER.readTree(otherJson))); } } diff --git a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/utils/MapUtils.java b/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/utils/MapUtils.java similarity index 95% rename from extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/utils/MapUtils.java rename to extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/utils/MapUtils.java index f43b31e56..8c2cd3a1d 100644 --- a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/utils/MapUtils.java +++ b/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/utils/MapUtils.java @@ -12,7 +12,7 @@ * */ -package de.sovity.edc.ext.brokerserver.utils; +package de.sovity.edc.ext.catalog.crawler.utils; import lombok.AccessLevel; import lombok.NoArgsConstructor; diff --git a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/utils/StringUtils2.java b/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/utils/StringUtils2.java similarity index 60% rename from extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/utils/StringUtils2.java rename to extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/utils/StringUtils2.java index cdf454183..190f16ede 100644 --- a/extensions/broker-server/src/main/java/de/sovity/edc/ext/brokerserver/utils/StringUtils2.java +++ b/extensions/catalog-crawler/catalog-crawler/src/main/java/de/sovity/edc/ext/catalog/crawler/utils/StringUtils2.java @@ -12,15 +12,11 @@ * */ -package de.sovity.edc.ext.brokerserver.utils; +package de.sovity.edc.ext.catalog.crawler.utils; import lombok.AccessLevel; import lombok.NoArgsConstructor; import lombok.NonNull; -import org.apache.commons.lang3.StringUtils; - -import java.util.List; -import java.util.stream.Stream; @NoArgsConstructor(access = AccessLevel.PRIVATE) public class StringUtils2 { @@ -38,21 +34,4 @@ public static String removeSuffix(@NonNull String string, @NonNull String suffix } return string; } - - /** - * Splits a string into its words and returns them in lowercase. - * - * @param string string - * @return list of lowercase words - */ - public static List lowercaseWords(String string) { - if (StringUtils.isBlank(string)) { - return List.of(); - } - - return Stream.of(string.split("\\s+")) - .map(String::toLowerCase) - .filter(StringUtils::isNotBlank) - .toList(); - } } diff --git a/extensions/catalog-crawler/catalog-crawler/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension b/extensions/catalog-crawler/catalog-crawler/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension new file mode 100644 index 000000000..5a369119d --- /dev/null +++ b/extensions/catalog-crawler/catalog-crawler/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension @@ -0,0 +1 @@ +de.sovity.edc.ext.catalog.crawler.CrawlerExtension diff --git a/extensions/broker-server/src/test/java/de/sovity/edc/ext/brokerserver/AssertionUtils.java b/extensions/catalog-crawler/catalog-crawler/src/test/java/de/sovity/edc/ext/catalog/crawler/AssertionUtils.java similarity index 83% rename from extensions/broker-server/src/test/java/de/sovity/edc/ext/brokerserver/AssertionUtils.java rename to extensions/catalog-crawler/catalog-crawler/src/test/java/de/sovity/edc/ext/catalog/crawler/AssertionUtils.java index c810d36eb..aef8012b7 100644 --- a/extensions/broker-server/src/test/java/de/sovity/edc/ext/brokerserver/AssertionUtils.java +++ b/extensions/catalog-crawler/catalog-crawler/src/test/java/de/sovity/edc/ext/catalog/crawler/AssertionUtils.java @@ -12,9 +12,8 @@ * */ -package de.sovity.edc.ext.brokerserver; +package de.sovity.edc.ext.catalog.crawler; -import de.sovity.edc.ext.brokerserver.client.gen.JSON; import lombok.AccessLevel; import lombok.NoArgsConstructor; import lombok.SneakyThrows; @@ -29,6 +28,6 @@ public static void assertEqualJson(String expected, String actual) { } public static void assertEqualUsingJson(Object expected, Object actual) { - assertEqualJson(JSON.serialize(expected), JSON.serialize(actual)); + assertEqualJson(JsonTestUtils.serialize(expected), JsonTestUtils.serialize(actual)); } } diff --git a/extensions/catalog-crawler/catalog-crawler/src/test/java/de/sovity/edc/ext/catalog/crawler/CrawlerTestDb.java b/extensions/catalog-crawler/catalog-crawler/src/test/java/de/sovity/edc/ext/catalog/crawler/CrawlerTestDb.java new file mode 100644 index 000000000..a4057c57b --- /dev/null +++ b/extensions/catalog-crawler/catalog-crawler/src/test/java/de/sovity/edc/ext/catalog/crawler/CrawlerTestDb.java @@ -0,0 +1,62 @@ +package de.sovity.edc.ext.catalog.crawler; + +import com.zaxxer.hikari.HikariDataSource; +import de.sovity.edc.ext.catalog.crawler.dao.config.DslContextFactory; +import de.sovity.edc.ext.catalog.crawler.dao.config.FlywayService; +import de.sovity.edc.extension.e2e.db.TestDatabaseViaTestcontainers; +import de.sovity.edc.extension.postgresql.FlywayUtils; +import de.sovity.edc.extension.postgresql.HikariDataSourceFactory; +import de.sovity.edc.extension.postgresql.JdbcCredentials; +import org.jooq.DSLContext; +import org.junit.jupiter.api.extension.AfterAllCallback; +import org.junit.jupiter.api.extension.BeforeAllCallback; +import org.junit.jupiter.api.extension.ExtensionContext; + +import java.util.function.Consumer; + +public class CrawlerTestDb implements BeforeAllCallback, AfterAllCallback { + private final TestDatabaseViaTestcontainers db = new TestDatabaseViaTestcontainers(); + + private HikariDataSource dataSource = null; + private DslContextFactory dslContextFactory = null; + + public void testTransaction(Consumer code) { + dslContextFactory.testTransaction(code); + } + + @Override + public void beforeAll(ExtensionContext extensionContext) throws Exception { + // Init DB + db.beforeAll(extensionContext); + + // Init Data Source + var credentials = new JdbcCredentials( + db.getJdbcCredentials().jdbcUrl(), + db.getJdbcCredentials().jdbcUser(), + db.getJdbcCredentials().jdbcPassword() + ); + dataSource = HikariDataSourceFactory.newDataSource(credentials, 10, 1000); + dslContextFactory = new DslContextFactory(dataSource); + + // Migrate DB + var params = FlywayService.baseConfig("classpath:db-crawler/migration-test-utils") + .migrate(true) + .build(); + try { + FlywayUtils.cleanAndMigrate(params, dataSource); + } catch (Exception e) { + var paramsWithClean = params.withClean(true).withCleanEnabled(true); + FlywayUtils.cleanAndMigrate(paramsWithClean, dataSource); + } + } + + @Override + public void afterAll(ExtensionContext extensionContext) throws Exception { + if (dataSource != null) { + dataSource.close(); + } + + // Close DB + db.afterAll(extensionContext); + } +} diff --git a/extensions/catalog-crawler/catalog-crawler/src/test/java/de/sovity/edc/ext/catalog/crawler/JsonTestUtils.java b/extensions/catalog-crawler/catalog-crawler/src/test/java/de/sovity/edc/ext/catalog/crawler/JsonTestUtils.java new file mode 100644 index 000000000..ec4f26b5e --- /dev/null +++ b/extensions/catalog-crawler/catalog-crawler/src/test/java/de/sovity/edc/ext/catalog/crawler/JsonTestUtils.java @@ -0,0 +1,23 @@ +package de.sovity.edc.ext.catalog.crawler; + +import lombok.SneakyThrows; +import org.testcontainers.shaded.com.fasterxml.jackson.databind.ObjectMapper; + +public class JsonTestUtils { + + private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); + + @SneakyThrows + public static String serialize(Object obj) { + return OBJECT_MAPPER.writeValueAsString(obj); + } + + @SneakyThrows + public static T deserialize(String json, Class clazz) { + return OBJECT_MAPPER.readValue(json, clazz); + } + + public static T jsonCast(Object obj, Class clazz) { + return deserialize(serialize(obj), clazz); + } +} diff --git a/extensions/catalog-crawler/catalog-crawler/src/test/java/de/sovity/edc/ext/catalog/crawler/TestData.java b/extensions/catalog-crawler/catalog-crawler/src/test/java/de/sovity/edc/ext/catalog/crawler/TestData.java new file mode 100644 index 000000000..b522c8881 --- /dev/null +++ b/extensions/catalog-crawler/catalog-crawler/src/test/java/de/sovity/edc/ext/catalog/crawler/TestData.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2023 sovity GmbH + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + * + * Contributors: + * sovity GmbH - initial implementation + * + */ + +package de.sovity.edc.ext.catalog.crawler; + +import de.sovity.edc.ext.catalog.crawler.dao.connectors.ConnectorRef; +import de.sovity.edc.ext.catalog.crawler.db.jooq.Tables; +import de.sovity.edc.ext.catalog.crawler.db.jooq.enums.ConnectorContractOffersExceeded; +import de.sovity.edc.ext.catalog.crawler.db.jooq.enums.ConnectorDataOffersExceeded; +import de.sovity.edc.ext.catalog.crawler.db.jooq.enums.ConnectorOnlineStatus; +import de.sovity.edc.ext.catalog.crawler.db.jooq.tables.records.ConnectorRecord; +import lombok.experimental.UtilityClass; +import org.jooq.DSLContext; + +import java.time.OffsetDateTime; +import java.util.function.Consumer; + +@UtilityClass +public class TestData { + public static OffsetDateTime old = OffsetDateTime.now().withNano(0).withSecond(0).withMinute(0).withHour(0).minusDays(100); + + public static ConnectorRef connectorRef = new ConnectorRef( + "MDSL1234XX.C1234XX", + "test", + "My Org", + "MDSL1234XX", + "https://example.com/api/dsp" + ); + + public static void insertConnector( + DSLContext dsl, + ConnectorRef connectorRef, + Consumer applier + ) { + var organization = dsl.newRecord(Tables.ORGANIZATION); + organization.setMdsId(connectorRef.getOrganizationId()); + organization.setName(connectorRef.getOrganizationLegalName()); + organization.insert(); + + var connector = dsl.newRecord(Tables.CONNECTOR); + connector.setEnvironment(connectorRef.getEnvironmentId()); + connector.setMdsId(connectorRef.getOrganizationId()); + connector.setConnectorId(connectorRef.getConnectorId()); + connector.setName(connectorRef.getConnectorId() + " Name"); + connector.setEndpointUrl(connectorRef.getEndpoint()); + connector.setOnlineStatus(ConnectorOnlineStatus.OFFLINE); + connector.setLastRefreshAttemptAt(null); + connector.setLastSuccessfulRefreshAt(null); + connector.setCreatedAt(old); + connector.setDataOffersExceeded(ConnectorDataOffersExceeded.OK); + connector.setContractOffersExceeded(ConnectorContractOffersExceeded.OK); + applier.accept(connector); + connector.insert(); + } +} diff --git a/extensions/catalog-crawler/catalog-crawler/src/test/java/de/sovity/edc/ext/catalog/crawler/crawling/logging/CrawlerEventLoggerTest.java b/extensions/catalog-crawler/catalog-crawler/src/test/java/de/sovity/edc/ext/catalog/crawler/crawling/logging/CrawlerEventLoggerTest.java new file mode 100644 index 000000000..f48ba78c8 --- /dev/null +++ b/extensions/catalog-crawler/catalog-crawler/src/test/java/de/sovity/edc/ext/catalog/crawler/crawling/logging/CrawlerEventLoggerTest.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2023 sovity GmbH + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + * + * Contributors: + * sovity GmbH - initial API and implementation + * + */ + +package de.sovity.edc.ext.catalog.crawler.crawling.logging; + +import de.sovity.edc.ext.catalog.crawler.CrawlerTestDb; +import de.sovity.edc.ext.catalog.crawler.dao.connectors.ConnectorRef; +import de.sovity.edc.ext.catalog.crawler.db.jooq.Tables; +import org.jooq.DSLContext; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import static org.assertj.core.api.Assertions.assertThat; + +class CrawlerEventLoggerTest { + @RegisterExtension + private static final CrawlerTestDb TEST_DATABASE = new CrawlerTestDb(); + + @Test + void testDataOfferWriter_allSortsOfUpdates() { + TEST_DATABASE.testTransaction(dsl -> { + var crawlerEventLogger = new CrawlerEventLogger(); + + // Test that insertions insert required fields and don't cause DB errors + var connectorRef = new ConnectorRef( + "MDSL1234XX.C1234XX", + "test", + "My Org", + "MDSL1234XX", + "https://example.com/api/dsp" + ); + crawlerEventLogger.logConnectorUpdated(dsl, connectorRef, new ConnectorChangeTracker()); + crawlerEventLogger.logConnectorOnline(dsl, connectorRef); + crawlerEventLogger.logConnectorOffline(dsl, connectorRef, new CrawlerEventErrorMessage("Message", "Stacktrace")); + crawlerEventLogger.logConnectorUpdateContractOfferLimitExceeded(dsl, connectorRef, 10); + crawlerEventLogger.logConnectorUpdateContractOfferLimitOk(dsl, connectorRef); + crawlerEventLogger.logConnectorUpdateDataOfferLimitExceeded(dsl, connectorRef, 10); + crawlerEventLogger.logConnectorUpdateDataOfferLimitOk(dsl, connectorRef); + + assertThat(numLogEntries(dsl)).isEqualTo(7); + }); + } + + private Integer numLogEntries(DSLContext dsl) { + return dsl.selectCount().from(Tables.CRAWLER_EVENT_LOG).fetchOne().component1(); + } +} diff --git a/extensions/catalog-crawler/catalog-crawler/src/test/java/de/sovity/edc/ext/catalog/crawler/crawling/writing/ConnectorSuccessWriterTest.java b/extensions/catalog-crawler/catalog-crawler/src/test/java/de/sovity/edc/ext/catalog/crawler/crawling/writing/ConnectorSuccessWriterTest.java new file mode 100644 index 000000000..4e7d6a603 --- /dev/null +++ b/extensions/catalog-crawler/catalog-crawler/src/test/java/de/sovity/edc/ext/catalog/crawler/crawling/writing/ConnectorSuccessWriterTest.java @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2023 sovity GmbH + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + * + * Contributors: + * sovity GmbH - initial implementation + * + */ + +package de.sovity.edc.ext.catalog.crawler.crawling.writing; + +import de.sovity.edc.ext.catalog.crawler.CrawlerTestDb; +import de.sovity.edc.ext.catalog.crawler.TestData; +import de.sovity.edc.ext.catalog.crawler.crawling.fetching.model.FetchedCatalog; +import de.sovity.edc.ext.catalog.crawler.crawling.fetching.model.FetchedContractOffer; +import de.sovity.edc.ext.catalog.crawler.crawling.fetching.model.FetchedDataOffer; +import de.sovity.edc.ext.catalog.crawler.db.jooq.Tables; +import de.sovity.edc.ext.catalog.crawler.db.jooq.enums.ConnectorContractOffersExceeded; +import de.sovity.edc.ext.catalog.crawler.db.jooq.enums.ConnectorDataOffersExceeded; +import de.sovity.edc.ext.catalog.crawler.db.jooq.enums.ConnectorOnlineStatus; +import de.sovity.edc.ext.wrapper.api.common.model.UiAsset; +import org.assertj.core.data.TemporalUnitLessThanOffset; +import org.jooq.impl.DSL; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import java.time.OffsetDateTime; +import java.time.temporal.ChronoUnit; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.when; + +class ConnectorSuccessWriterTest { + @RegisterExtension + private static final CrawlerTestDb TEST_DATABASE = new CrawlerTestDb(); + + ConnectorUpdateSuccessWriter connectorUpdateSuccessWriter; + + @BeforeEach + void setup() { + var container = new DataOfferWriterTestDydi(); + connectorUpdateSuccessWriter = container.getConnectorUpdateSuccessWriter(); + when(container.getCrawlerConfig().getMaxContractOffersPerDataOffer()).thenReturn(1); + when(container.getCrawlerConfig().getMaxDataOffersPerConnector()).thenReturn(1); + } + + @Test + void testDataOfferWriter_fullSingleUpdate() { + TEST_DATABASE.testTransaction(dsl -> { + // arrange + var connectorRef = TestData.connectorRef; + TestData.insertConnector(dsl, connectorRef, unused -> { + }); + var uiAsset = UiAsset.builder() + .assetId("assetId") + .title("title") + .description("# Description\n\n**with Markdown**") + .descriptionShortText("descriptionShortText") + .dataCategory("dataCategory") + .dataSubcategory("dataSubCategory") + .dataModel("dataModel") + .transportMode("transportMode") + .geoReferenceMethod("geoReferenceMethod") + .keywords(List.of("a", "b")) + .build(); + var fetchedContractOffer = FetchedContractOffer.builder() + .contractOfferId("contractOfferId") + .uiPolicyJson("\"test-policy\"") + .build(); + var fetchedDataOffer = FetchedDataOffer.builder() + .assetId("assetId") + .uiAsset(uiAsset) + .uiAssetJson("\"test\"") + .contractOffers(List.of(fetchedContractOffer)) + .build(); + var fetchedCatalog = FetchedCatalog.builder() + .connectorRef(connectorRef) + .dataOffers(List.of(fetchedDataOffer)) + .build(); + + // act + connectorUpdateSuccessWriter.handleConnectorOnline( + dsl, + connectorRef, + dsl.fetchOne( + Tables.CONNECTOR, + Tables.CONNECTOR.CONNECTOR_ID.eq(connectorRef.getConnectorId()) + ), + fetchedCatalog + ); + + // assert + var connector = dsl.fetchOne( + Tables.CONNECTOR, + Tables.CONNECTOR.CONNECTOR_ID.eq(connectorRef.getConnectorId()) + ); + var dataOffer = dsl.fetchOne( + Tables.DATA_OFFER, + DSL.and( + Tables.DATA_OFFER.CONNECTOR_ID.eq(connectorRef.getConnectorId()), + Tables.DATA_OFFER.ASSET_ID.eq("assetId") + ) + ); + var contractOffer = dsl.fetchOne( + Tables.CONTRACT_OFFER, + DSL.and( + Tables.CONTRACT_OFFER.CONNECTOR_ID.eq(connectorRef.getConnectorId()), + Tables.CONTRACT_OFFER.ASSET_ID.eq("assetId"), + Tables.CONTRACT_OFFER.CONTRACT_OFFER_ID.eq("contractOfferId") + ) + ); + + var now = OffsetDateTime.now(); + var minuteAccuracy = new TemporalUnitLessThanOffset(1, ChronoUnit.MINUTES); + assertThat(connector).isNotNull(); + assertThat(connector.getOnlineStatus()).isEqualTo(ConnectorOnlineStatus.ONLINE); + assertThat(connector.getLastRefreshAttemptAt()).isCloseTo(now, minuteAccuracy); + assertThat(connector.getLastSuccessfulRefreshAt()).isCloseTo(now, minuteAccuracy); + assertThat(connector.getDataOffersExceeded()).isEqualTo(ConnectorDataOffersExceeded.OK); + assertThat(connector.getContractOffersExceeded()).isEqualTo(ConnectorContractOffersExceeded.OK); + + assertThat(dataOffer).isNotNull(); + assertThat(dataOffer.getAssetTitle()).isEqualTo("title"); + assertThat(dataOffer.getDescriptionNoMarkdown()).isEqualTo("Description with Markdown"); + assertThat(dataOffer.getShortDescriptionNoMarkdown()).isEqualTo("descriptionShortText"); + assertThat(dataOffer.getDataCategory()).isEqualTo("dataCategory"); + assertThat(dataOffer.getDataSubcategory()).isEqualTo("dataSubCategory"); + assertThat(dataOffer.getDataModel()).isEqualTo("dataModel"); + assertThat(dataOffer.getTransportMode()).isEqualTo("transportMode"); + assertThat(dataOffer.getGeoReferenceMethod()).isEqualTo("geoReferenceMethod"); + assertThat(dataOffer.getKeywords()).containsExactly("a", "b"); + assertThat(dataOffer.getKeywordsCommaJoined()).isEqualTo("a, b"); + assertThat(dataOffer.getUiAssetJson().data()).isEqualTo("\"test\""); + + assertThat(contractOffer).isNotNull(); + assertThat(contractOffer.getUiPolicyJson().data()).isEqualTo("\"test-policy\""); + }); + } +} diff --git a/extensions/broker-server/src/test/java/de/sovity/edc/ext/brokerserver/services/refreshing/offers/DataOfferWriterTest.java b/extensions/catalog-crawler/catalog-crawler/src/test/java/de/sovity/edc/ext/catalog/crawler/crawling/writing/ConnectorUpdateCatalogWriterTest.java similarity index 80% rename from extensions/broker-server/src/test/java/de/sovity/edc/ext/brokerserver/services/refreshing/offers/DataOfferWriterTest.java rename to extensions/catalog-crawler/catalog-crawler/src/test/java/de/sovity/edc/ext/catalog/crawler/crawling/writing/ConnectorUpdateCatalogWriterTest.java index c8792e345..249d36764 100644 --- a/extensions/broker-server/src/test/java/de/sovity/edc/ext/brokerserver/services/refreshing/offers/DataOfferWriterTest.java +++ b/extensions/catalog-crawler/catalog-crawler/src/test/java/de/sovity/edc/ext/catalog/crawler/crawling/writing/ConnectorUpdateCatalogWriterTest.java @@ -12,17 +12,13 @@ * */ -package de.sovity.edc.ext.brokerserver.services.refreshing.offers; - -import de.sovity.edc.ext.brokerserver.db.FlywayTestUtils; -import de.sovity.edc.ext.brokerserver.db.TestDatabase; -import de.sovity.edc.ext.brokerserver.db.TestDatabaseFactory; -import de.sovity.edc.ext.brokerserver.db.jooq.tables.records.DataOfferRecord; -import de.sovity.edc.ext.brokerserver.services.logging.ConnectorChangeTracker; -import de.sovity.edc.ext.brokerserver.services.refreshing.offers.DataOfferWriterTestDataModels.Co; -import de.sovity.edc.ext.brokerserver.services.refreshing.offers.DataOfferWriterTestDataModels.Do; +package de.sovity.edc.ext.catalog.crawler.crawling.writing; + +import de.sovity.edc.ext.catalog.crawler.AssertionUtils; +import de.sovity.edc.ext.catalog.crawler.CrawlerTestDb; +import de.sovity.edc.ext.catalog.crawler.crawling.logging.ConnectorChangeTracker; +import de.sovity.edc.ext.catalog.crawler.db.jooq.tables.records.DataOfferRecord; import org.assertj.core.data.TemporalUnitLessThanOffset; -import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; @@ -30,18 +26,14 @@ import java.time.temporal.ChronoUnit; import java.util.List; -import static de.sovity.edc.ext.brokerserver.AssertionUtils.assertEqualJson; +import static de.sovity.edc.ext.catalog.crawler.crawling.writing.DataOfferWriterTestDataModels.Co; +import static de.sovity.edc.ext.catalog.crawler.crawling.writing.DataOfferWriterTestDataModels.Do; import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.when; -class DataOfferWriterTest { - +class ConnectorUpdateCatalogWriterTest { @RegisterExtension - private static final TestDatabase TEST_DATABASE = TestDatabaseFactory.getTestDatabase(); - - @BeforeAll - static void setup() { - FlywayTestUtils.migrate(TEST_DATABASE); - } + private static final CrawlerTestDb TEST_DATABASE = new CrawlerTestDb(); @Test void testDataOfferWriter_allSortsOfUpdates() { @@ -49,7 +41,8 @@ void testDataOfferWriter_allSortsOfUpdates() { var testDydi = new DataOfferWriterTestDydi(); var testData = new DataOfferWriterTestDataHelper(); var changes = new ConnectorChangeTracker(); - var dataOfferWriter = testDydi.getDataOfferWriter(); + var dataOfferWriter = testDydi.getConnectorUpdateCatalogWriter(); + when(testDydi.getCrawlerConfig().getEnvironmentId()).thenReturn("test"); // arrange var unchanged = Do.forName("unchanged"); @@ -79,7 +72,8 @@ void testDataOfferWriter_allSortsOfUpdates() { testData.existing(addedCoExisting); testData.fetched(addedCoFetched); - var removedCoExisting = Do.forName("contractOfferRemoved").withContractOffer(new Co("removed co", "removed co")); + var removedCoExisting = Do.forName("contractOfferRemoved") + .withContractOffer(new Co("removed co", "removed co")); var removedCoFetched = Do.forName("contractOfferRemoved"); testData.existing(removedCoExisting); testData.fetched(removedCoFetched); @@ -88,7 +82,7 @@ void testDataOfferWriter_allSortsOfUpdates() { dsl.transaction(it -> testData.initialize(it.dsl())); dsl.transaction(it -> dataOfferWriter.updateDataOffers( it.dsl(), - testData.connectorEndpoint, + testData.connectorRef, testData.fetchedDataOffers, changes )); @@ -139,10 +133,11 @@ void testDataOfferWriter_allSortsOfUpdates() { }); } - private void assertAssetPropertiesEqual(DataOfferWriterTestDataHelper testData, DataOfferRecord actual, Do expected) { - var actualAssetJson = actual.getAssetJsonLd().data(); - var expectedAssetJson = testData.dummyAssetJson(expected); - assertEqualJson(actualAssetJson, expectedAssetJson); + private void assertAssetPropertiesEqual(DataOfferWriterTestDataHelper testData, DataOfferRecord actual, + Do expected) { + var actualUiAssetJson = actual.getUiAssetJson().data(); + var expectedUiAssetJson = testData.dummyAssetJson(expected); + AssertionUtils.assertEqualJson(actualUiAssetJson, expectedUiAssetJson); } private void assertPolicyEquals( @@ -152,8 +147,8 @@ private void assertPolicyEquals( Co expectedCo ) { var actualContractOffer = actual.getContractOffer(expectedDo.getAssetId(), expectedCo.getId()); - var actualPolicy = actualContractOffer.getPolicy().data(); - var expectedPolicy = scenario.dummyPolicyJson(expectedCo.getPolicyValue()); - assertThat(actualPolicy).isEqualTo(expectedPolicy); + var actualUiPolicyJson = actualContractOffer.getUiPolicyJson().data(); + var expectedUiPolicyJson = scenario.dummyPolicyJson(expectedCo.getPolicyValue()); + assertThat(actualUiPolicyJson).isEqualTo(expectedUiPolicyJson); } } diff --git a/extensions/broker-server/src/test/java/de/sovity/edc/ext/brokerserver/services/refreshing/offers/DataOfferLimitsEnforcerTest.java b/extensions/catalog-crawler/catalog-crawler/src/test/java/de/sovity/edc/ext/catalog/crawler/crawling/writing/DataOfferLimitsEnforcerTest.java similarity index 81% rename from extensions/broker-server/src/test/java/de/sovity/edc/ext/brokerserver/services/refreshing/offers/DataOfferLimitsEnforcerTest.java rename to extensions/catalog-crawler/catalog-crawler/src/test/java/de/sovity/edc/ext/catalog/crawler/crawling/writing/DataOfferLimitsEnforcerTest.java index 9a0da5f0c..cb0bafdb5 100644 --- a/extensions/broker-server/src/test/java/de/sovity/edc/ext/brokerserver/services/refreshing/offers/DataOfferLimitsEnforcerTest.java +++ b/extensions/catalog-crawler/catalog-crawler/src/test/java/de/sovity/edc/ext/catalog/crawler/crawling/writing/DataOfferLimitsEnforcerTest.java @@ -12,15 +12,17 @@ * */ -package de.sovity.edc.ext.brokerserver.services.refreshing.offers; - -import de.sovity.edc.ext.brokerserver.db.jooq.enums.ConnectorContractOffersExceeded; -import de.sovity.edc.ext.brokerserver.db.jooq.enums.ConnectorDataOffersExceeded; -import de.sovity.edc.ext.brokerserver.db.jooq.tables.records.ConnectorRecord; -import de.sovity.edc.ext.brokerserver.services.config.BrokerServerSettings; -import de.sovity.edc.ext.brokerserver.services.logging.BrokerEventLogger; -import de.sovity.edc.ext.brokerserver.services.refreshing.offers.model.FetchedContractOffer; -import de.sovity.edc.ext.brokerserver.services.refreshing.offers.model.FetchedDataOffer; +package de.sovity.edc.ext.catalog.crawler.crawling.writing; + +import de.sovity.edc.ext.catalog.crawler.crawling.fetching.model.FetchedContractOffer; +import de.sovity.edc.ext.catalog.crawler.crawling.fetching.model.FetchedDataOffer; +import de.sovity.edc.ext.catalog.crawler.crawling.logging.CrawlerEventLogger; +import de.sovity.edc.ext.catalog.crawler.dao.connectors.ConnectorRef; +import de.sovity.edc.ext.catalog.crawler.db.jooq.enums.ConnectorContractOffersExceeded; +import de.sovity.edc.ext.catalog.crawler.db.jooq.enums.ConnectorDataOffersExceeded; +import de.sovity.edc.ext.catalog.crawler.db.jooq.tables.records.ConnectorRecord; +import de.sovity.edc.ext.catalog.crawler.orchestration.config.CrawlerConfig; +import org.assertj.core.api.Assertions; import org.jooq.DSLContext; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -37,15 +39,17 @@ class DataOfferLimitsEnforcerTest { DataOfferLimitsEnforcer dataOfferLimitsEnforcer; - BrokerServerSettings settings; - BrokerEventLogger brokerEventLogger; + CrawlerConfig settings; + CrawlerEventLogger crawlerEventLogger; DSLContext dsl; + ConnectorRef connectorRef = new DataOfferWriterTestDataHelper().connectorRef; + @BeforeEach void setup() { - settings = mock(BrokerServerSettings.class); - brokerEventLogger = mock(BrokerEventLogger.class); - dataOfferLimitsEnforcer = new DataOfferLimitsEnforcer(settings, brokerEventLogger); + settings = mock(CrawlerConfig.class); + crawlerEventLogger = mock(CrawlerEventLogger.class); + dataOfferLimitsEnforcer = new DataOfferLimitsEnforcer(settings, crawlerEventLogger); dsl = mock(DSLContext.class); } @@ -68,7 +72,7 @@ void no_limit_and_two_dataofffers_and_contractoffer_should_not_limit() { var dataOffersLimitExceeded = enforcedLimits.dataOfferLimitsExceeded(); // assert - assertThat(actual).hasSize(2); + Assertions.assertThat(actual).hasSize(2); assertFalse(contractOffersLimitExceeded); assertFalse(dataOffersLimitExceeded); } @@ -115,7 +119,7 @@ void limit_one_and_two_dataoffers_should_result_to_one() { // assert assertThat(actual).hasSize(1); - assertThat(actual.get(0).getContractOffers()).hasSize(1); + Assertions.assertThat(actual.get(0).getContractOffers()).hasSize(1); assertTrue(contractOffersLimitExceeded); assertTrue(dataOffersLimitExceeded); } @@ -124,7 +128,6 @@ void limit_one_and_two_dataoffers_should_result_to_one() { void verify_logConnectorUpdateDataOfferLimitExceeded() { // arrange var connector = new ConnectorRecord(); - connector.setEndpoint("http://localhost:8080"); connector.setDataOffersExceeded(ConnectorDataOffersExceeded.OK); int maxDataOffers = 1; @@ -138,17 +141,16 @@ void verify_logConnectorUpdateDataOfferLimitExceeded() { // act var enforcedLimits = dataOfferLimitsEnforcer.enforceLimits(dataOffers); - dataOfferLimitsEnforcer.logEnforcedLimitsIfChanged(dsl, connector, enforcedLimits); + dataOfferLimitsEnforcer.logEnforcedLimitsIfChanged(dsl, connectorRef, connector, enforcedLimits); // assert - verify(brokerEventLogger).logConnectorUpdateDataOfferLimitExceeded(dsl, 1, connector.getEndpoint()); + verify(crawlerEventLogger).logConnectorUpdateDataOfferLimitExceeded(dsl, connectorRef, 1); } @Test void verify_logConnectorUpdateDataOfferLimitOk() { // arrange var connector = new ConnectorRecord(); - connector.setEndpoint("http://localhost:8080"); connector.setDataOffersExceeded(ConnectorDataOffersExceeded.EXCEEDED); int maxDataOffers = -1; @@ -162,17 +164,16 @@ void verify_logConnectorUpdateDataOfferLimitOk() { // act var enforcedLimits = dataOfferLimitsEnforcer.enforceLimits(dataOffers); - dataOfferLimitsEnforcer.logEnforcedLimitsIfChanged(dsl, connector, enforcedLimits); + dataOfferLimitsEnforcer.logEnforcedLimitsIfChanged(dsl, connectorRef, connector, enforcedLimits); // assert - verify(brokerEventLogger).logConnectorUpdateDataOfferLimitOk(dsl, connector.getEndpoint()); + verify(crawlerEventLogger).logConnectorUpdateDataOfferLimitOk(dsl, connectorRef); } @Test void verify_logConnectorUpdateContractOfferLimitExceeded() { // arrange var connector = new ConnectorRecord(); - connector.setEndpoint("http://localhost:8080"); connector.setContractOffersExceeded(ConnectorContractOffersExceeded.OK); int maxDataOffers = 1; @@ -186,17 +187,16 @@ void verify_logConnectorUpdateContractOfferLimitExceeded() { // act var enforcedLimits = dataOfferLimitsEnforcer.enforceLimits(dataOffers); - dataOfferLimitsEnforcer.logEnforcedLimitsIfChanged(dsl, connector, enforcedLimits); + dataOfferLimitsEnforcer.logEnforcedLimitsIfChanged(dsl, connectorRef, connector, enforcedLimits); // assert - verify(brokerEventLogger).logConnectorUpdateContractOfferLimitExceeded(dsl, 1, connector.getEndpoint()); + verify(crawlerEventLogger).logConnectorUpdateContractOfferLimitExceeded(dsl, connectorRef, 1); } @Test void verify_logConnectorUpdateContractOfferLimitOk() { // arrange var connector = new ConnectorRecord(); - connector.setEndpoint("http://localhost:8080"); connector.setContractOffersExceeded(ConnectorContractOffersExceeded.EXCEEDED); int maxDataOffers = -1; @@ -210,9 +210,9 @@ void verify_logConnectorUpdateContractOfferLimitOk() { // act var enforcedLimits = dataOfferLimitsEnforcer.enforceLimits(dataOffers); - dataOfferLimitsEnforcer.logEnforcedLimitsIfChanged(dsl, connector, enforcedLimits); + dataOfferLimitsEnforcer.logEnforcedLimitsIfChanged(dsl, connectorRef, connector, enforcedLimits); // assert - verify(brokerEventLogger).logConnectorUpdateContractOfferLimitOk(dsl, connector.getEndpoint()); + verify(crawlerEventLogger).logConnectorUpdateContractOfferLimitOk(dsl, connectorRef); } } diff --git a/extensions/broker-server/src/test/java/de/sovity/edc/ext/brokerserver/services/refreshing/offers/DataOfferWriterTestDataHelper.java b/extensions/catalog-crawler/catalog-crawler/src/test/java/de/sovity/edc/ext/catalog/crawler/crawling/writing/DataOfferWriterTestDataHelper.java similarity index 53% rename from extensions/broker-server/src/test/java/de/sovity/edc/ext/brokerserver/services/refreshing/offers/DataOfferWriterTestDataHelper.java rename to extensions/catalog-crawler/catalog-crawler/src/test/java/de/sovity/edc/ext/catalog/crawler/crawling/writing/DataOfferWriterTestDataHelper.java index 664ac3b30..997141ab5 100644 --- a/extensions/broker-server/src/test/java/de/sovity/edc/ext/brokerserver/services/refreshing/offers/DataOfferWriterTestDataHelper.java +++ b/extensions/catalog-crawler/catalog-crawler/src/test/java/de/sovity/edc/ext/catalog/crawler/crawling/writing/DataOfferWriterTestDataHelper.java @@ -12,16 +12,17 @@ * */ -package de.sovity.edc.ext.brokerserver.services.refreshing.offers; - -import de.sovity.edc.ext.brokerserver.dao.ConnectorQueries; -import de.sovity.edc.ext.brokerserver.db.jooq.tables.records.ContractOfferRecord; -import de.sovity.edc.ext.brokerserver.db.jooq.tables.records.DataOfferRecord; -import de.sovity.edc.ext.brokerserver.services.ConnectorCreator; -import de.sovity.edc.ext.brokerserver.services.refreshing.offers.model.FetchedContractOffer; -import de.sovity.edc.ext.brokerserver.services.refreshing.offers.model.FetchedDataOffer; -import de.sovity.edc.ext.wrapper.api.common.model.UiAssetCreateRequest; +package de.sovity.edc.ext.catalog.crawler.crawling.writing; + +import de.sovity.edc.ext.catalog.crawler.TestData; +import de.sovity.edc.ext.catalog.crawler.crawling.fetching.model.FetchedContractOffer; +import de.sovity.edc.ext.catalog.crawler.crawling.fetching.model.FetchedDataOffer; +import de.sovity.edc.ext.catalog.crawler.dao.connectors.ConnectorRef; +import de.sovity.edc.ext.catalog.crawler.db.jooq.tables.records.ContractOfferRecord; +import de.sovity.edc.ext.catalog.crawler.db.jooq.tables.records.DataOfferRecord; +import de.sovity.edc.ext.wrapper.api.common.model.UiAsset; import de.sovity.edc.utils.JsonUtils; +import jakarta.json.Json; import org.apache.commons.lang3.Validate; import org.jetbrains.annotations.NotNull; import org.jooq.DSLContext; @@ -33,13 +34,9 @@ import java.util.Optional; import java.util.stream.Collectors; -import static de.sovity.edc.ext.brokerserver.TestAsset.getAssetJsonLd; -import static de.sovity.edc.ext.brokerserver.services.refreshing.offers.DataOfferWriterTestDataModels.Co; -import static de.sovity.edc.ext.brokerserver.services.refreshing.offers.DataOfferWriterTestDataModels.Do; - class DataOfferWriterTestDataHelper { - String connectorEndpoint = "https://example.com/api/dsp"; - OffsetDateTime old = OffsetDateTime.now().withNano(0).withSecond(0).withMinute(0).withHour(0).minusDays(100); + OffsetDateTime old = TestData.old; + ConnectorRef connectorRef = TestData.connectorRef; List existingContractOffers = new ArrayList<>(); List existingDataOffers = new ArrayList<>(); List fetchedDataOffers = new ArrayList<>(); @@ -50,7 +47,7 @@ class DataOfferWriterTestDataHelper { * * @param dataOffer fetched data offer */ - public void fetched(Do dataOffer) { + public void fetched(DataOfferWriterTestDataModels.Do dataOffer) { Validate.notEmpty(dataOffer.getContractOffers()); fetchedDataOffers.add(dummyFetchedDataOffer(dataOffer)); } @@ -61,51 +58,58 @@ public void fetched(Do dataOffer) { * * @param dataOffer data offer */ - public void existing(Do dataOffer) { + public void existing(DataOfferWriterTestDataModels.Do dataOffer) { Validate.notEmpty(dataOffer.getContractOffers()); existingDataOffers.add(dummyDataOffer(dataOffer)); dataOffer.getContractOffers().stream() - .map(contractOffer -> dummyContractOffer(dataOffer, contractOffer)) - .forEach(existingContractOffers::add); + .map(contractOffer -> dummyContractOffer(dataOffer, contractOffer)) + .forEach(existingContractOffers::add); } public void initialize(DSLContext dsl) { - var connectorQueries = new ConnectorQueries(); - var connectorCreator = new ConnectorCreator(connectorQueries); - connectorCreator.addConnector(dsl, connectorEndpoint); + TestData.insertConnector(dsl, connectorRef, record -> { + }); dsl.batchInsert(existingDataOffers).execute(); dsl.batchInsert(existingContractOffers).execute(); } - private ContractOfferRecord dummyContractOffer(Do dataOffer, Co contractOffer) { + private ContractOfferRecord dummyContractOffer( + DataOfferWriterTestDataModels.Do dataOffer, + DataOfferWriterTestDataModels.Co contractOffer + ) { var contractOfferRecord = new ContractOfferRecord(); - contractOfferRecord.setConnectorEndpoint(connectorEndpoint); + contractOfferRecord.setConnectorId(connectorRef.getConnectorId()); contractOfferRecord.setAssetId(dataOffer.getAssetId()); contractOfferRecord.setContractOfferId(contractOffer.getId()); - contractOfferRecord.setPolicy(JSONB.valueOf(dummyPolicyJson(contractOffer.getPolicyValue()))); + contractOfferRecord.setUiPolicyJson(JSONB.valueOf(dummyPolicyJson(contractOffer.getPolicyValue()))); contractOfferRecord.setCreatedAt(old); contractOfferRecord.setUpdatedAt(old); return contractOfferRecord; } - private DataOfferRecord dummyDataOffer(Do dataOffer) { + private DataOfferRecord dummyDataOffer(DataOfferWriterTestDataModels.Do dataOffer) { var assetName = Optional.of(dataOffer.getAssetTitle()).orElse(dataOffer.getAssetId()); var dataOfferRecord = new DataOfferRecord(); - dataOfferRecord.setConnectorEndpoint(connectorEndpoint); + dataOfferRecord.setConnectorId(connectorRef.getConnectorId()); dataOfferRecord.setAssetId(dataOffer.getAssetId()); dataOfferRecord.setAssetTitle(assetName); - dataOfferRecord.setAssetJsonLd(JSONB.valueOf(dummyAssetJson(dataOffer))); + dataOfferRecord.setUiAssetJson(JSONB.valueOf(dummyAssetJson(dataOffer))); dataOfferRecord.setCreatedAt(old); dataOfferRecord.setUpdatedAt(old); return dataOfferRecord; } - private FetchedDataOffer dummyFetchedDataOffer(Do dataOffer) { + private FetchedDataOffer dummyFetchedDataOffer(DataOfferWriterTestDataModels.Do dataOffer) { var fetchedDataOffer = new FetchedDataOffer(); fetchedDataOffer.setAssetId(dataOffer.getAssetId()); - fetchedDataOffer.setAssetTitle(dataOffer.getAssetTitle()); - fetchedDataOffer.setAssetJsonLd(dummyAssetJson(dataOffer)); + fetchedDataOffer.setUiAsset( + UiAsset.builder() + .assetId(dataOffer.getAssetId()) + .title(dataOffer.getAssetTitle()) + .build() + ); + fetchedDataOffer.setUiAssetJson(dummyAssetJson(dataOffer)); var contractOffersMapped = dataOffer.getContractOffers().stream().map(this::dummyFetchedContractOffer).collect(Collectors.toList()); fetchedDataOffer.setContractOffers(contractOffersMapped); @@ -113,27 +117,26 @@ private FetchedDataOffer dummyFetchedDataOffer(Do dataOffer) { return fetchedDataOffer; } - public String dummyAssetJson(Do dataOffer) { - var assetJsonLd = getAssetJsonLd( - UiAssetCreateRequest.builder() - .id(dataOffer.getAssetId()) - .title(dataOffer.getAssetTitle()) - .build() - ); - return JsonUtils.toJson(assetJsonLd); + public String dummyAssetJson(DataOfferWriterTestDataModels.Do dataOffer) { + var dummyUiAssetJson = Json.createObjectBuilder() + .add("assetId", dataOffer.getAssetId()) + .add("title", dataOffer.getAssetTitle()) + .add("assetJsonLd", "{}") + .build(); + return JsonUtils.toJson(dummyUiAssetJson); } public String dummyPolicyJson(String policyValue) { return "{\"%s\": \"%s\"}".formatted( - "SomePolicyField", policyValue + "SomePolicyField", policyValue ); } @NotNull - private FetchedContractOffer dummyFetchedContractOffer(Co it) { + private FetchedContractOffer dummyFetchedContractOffer(DataOfferWriterTestDataModels.Co it) { var contractOffer = new FetchedContractOffer(); contractOffer.setContractOfferId(it.getId()); - contractOffer.setPolicyJson(dummyPolicyJson(it.getPolicyValue())); + contractOffer.setUiPolicyJson(dummyPolicyJson(it.getPolicyValue())); return contractOffer; } } diff --git a/extensions/broker-server/src/test/java/de/sovity/edc/ext/brokerserver/services/refreshing/offers/DataOfferWriterTestDataModels.java b/extensions/catalog-crawler/catalog-crawler/src/test/java/de/sovity/edc/ext/catalog/crawler/crawling/writing/DataOfferWriterTestDataModels.java similarity index 95% rename from extensions/broker-server/src/test/java/de/sovity/edc/ext/brokerserver/services/refreshing/offers/DataOfferWriterTestDataModels.java rename to extensions/catalog-crawler/catalog-crawler/src/test/java/de/sovity/edc/ext/catalog/crawler/crawling/writing/DataOfferWriterTestDataModels.java index ab15daccb..7dd824d99 100644 --- a/extensions/broker-server/src/test/java/de/sovity/edc/ext/brokerserver/services/refreshing/offers/DataOfferWriterTestDataModels.java +++ b/extensions/catalog-crawler/catalog-crawler/src/test/java/de/sovity/edc/ext/catalog/crawler/crawling/writing/DataOfferWriterTestDataModels.java @@ -12,7 +12,7 @@ * */ -package de.sovity.edc.ext.brokerserver.services.refreshing.offers; +package de.sovity.edc.ext.catalog.crawler.crawling.writing; import lombok.Value; import lombok.With; diff --git a/extensions/catalog-crawler/catalog-crawler/src/test/java/de/sovity/edc/ext/catalog/crawler/crawling/writing/DataOfferWriterTestDydi.java b/extensions/catalog-crawler/catalog-crawler/src/test/java/de/sovity/edc/ext/catalog/crawler/crawling/writing/DataOfferWriterTestDydi.java new file mode 100644 index 000000000..a46cf1dc4 --- /dev/null +++ b/extensions/catalog-crawler/catalog-crawler/src/test/java/de/sovity/edc/ext/catalog/crawler/crawling/writing/DataOfferWriterTestDydi.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2023 sovity GmbH + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + * + * Contributors: + * sovity GmbH - initial implementation + * + */ + +package de.sovity.edc.ext.catalog.crawler.crawling.writing; + +import de.sovity.edc.ext.catalog.crawler.crawling.logging.CrawlerEventLogger; +import de.sovity.edc.ext.catalog.crawler.dao.CatalogPatchApplier; +import de.sovity.edc.ext.catalog.crawler.dao.connectors.ConnectorQueries; +import de.sovity.edc.ext.catalog.crawler.dao.contract_offers.ContractOfferQueries; +import de.sovity.edc.ext.catalog.crawler.dao.contract_offers.ContractOfferRecordUpdater; +import de.sovity.edc.ext.catalog.crawler.dao.data_offers.DataOfferQueries; +import de.sovity.edc.ext.catalog.crawler.dao.data_offers.DataOfferRecordUpdater; +import de.sovity.edc.ext.catalog.crawler.orchestration.config.CrawlerConfig; +import de.sovity.edc.ext.wrapper.api.common.mappers.asset.utils.ShortDescriptionBuilder; +import lombok.Value; +import org.eclipse.edc.spi.system.configuration.Config; + +import static org.mockito.Mockito.mock; + +@Value +class DataOfferWriterTestDydi { + Config config = mock(Config.class); + CrawlerConfig crawlerConfig = mock(CrawlerConfig.class); + DataOfferQueries dataOfferQueries = new DataOfferQueries(); + ContractOfferQueries contractOfferQueries = new ContractOfferQueries(); + ContractOfferRecordUpdater contractOfferRecordUpdater = new ContractOfferRecordUpdater(); + ConnectorQueries connectorQueries = new ConnectorQueries(crawlerConfig); + ShortDescriptionBuilder shortDescriptionBuilder = new ShortDescriptionBuilder(); + DataOfferRecordUpdater dataOfferRecordUpdater = new DataOfferRecordUpdater(shortDescriptionBuilder); + CatalogPatchBuilder catalogPatchBuilder = new CatalogPatchBuilder( + contractOfferQueries, + dataOfferQueries, + dataOfferRecordUpdater, + contractOfferRecordUpdater + ); + CatalogPatchApplier catalogPatchApplier = new CatalogPatchApplier(); + ConnectorUpdateCatalogWriter connectorUpdateCatalogWriter = new ConnectorUpdateCatalogWriter(catalogPatchBuilder, catalogPatchApplier); + + // for the ConnectorUpdateSuccessWriterTest + CrawlerEventLogger crawlerEventLogger = new CrawlerEventLogger(); + DataOfferLimitsEnforcer dataOfferLimitsEnforcer = new DataOfferLimitsEnforcer( + crawlerConfig, + crawlerEventLogger + ); + ConnectorUpdateSuccessWriter connectorUpdateSuccessWriter = new ConnectorUpdateSuccessWriter( + crawlerEventLogger, + connectorUpdateCatalogWriter, + dataOfferLimitsEnforcer + ); +} diff --git a/extensions/broker-server/src/test/java/de/sovity/edc/ext/brokerserver/services/refreshing/offers/DataOfferWriterTestResultHelper.java b/extensions/catalog-crawler/catalog-crawler/src/test/java/de/sovity/edc/ext/catalog/crawler/crawling/writing/DataOfferWriterTestResultHelper.java similarity index 78% rename from extensions/broker-server/src/test/java/de/sovity/edc/ext/brokerserver/services/refreshing/offers/DataOfferWriterTestResultHelper.java rename to extensions/catalog-crawler/catalog-crawler/src/test/java/de/sovity/edc/ext/catalog/crawler/crawling/writing/DataOfferWriterTestResultHelper.java index 1b2f04c21..e5dfa39bb 100644 --- a/extensions/broker-server/src/test/java/de/sovity/edc/ext/brokerserver/services/refreshing/offers/DataOfferWriterTestResultHelper.java +++ b/extensions/catalog-crawler/catalog-crawler/src/test/java/de/sovity/edc/ext/catalog/crawler/crawling/writing/DataOfferWriterTestResultHelper.java @@ -12,11 +12,11 @@ * */ -package de.sovity.edc.ext.brokerserver.services.refreshing.offers; +package de.sovity.edc.ext.catalog.crawler.crawling.writing; -import de.sovity.edc.ext.brokerserver.db.jooq.Tables; -import de.sovity.edc.ext.brokerserver.db.jooq.tables.records.ContractOfferRecord; -import de.sovity.edc.ext.brokerserver.db.jooq.tables.records.DataOfferRecord; +import de.sovity.edc.ext.catalog.crawler.db.jooq.Tables; +import de.sovity.edc.ext.catalog.crawler.db.jooq.tables.records.ContractOfferRecord; +import de.sovity.edc.ext.catalog.crawler.db.jooq.tables.records.DataOfferRecord; import org.jetbrains.annotations.NotNull; import org.jooq.DSLContext; @@ -33,8 +33,8 @@ class DataOfferWriterTestResultHelper { DataOfferWriterTestResultHelper(DSLContext dsl) { this.dataOffers = dsl.selectFrom(Tables.DATA_OFFER).fetchMap(Tables.DATA_OFFER.ASSET_ID); this.contractOffers = dsl.selectFrom(Tables.CONTRACT_OFFER).stream().collect(groupingBy( - ContractOfferRecord::getAssetId, - Collectors.toMap(ContractOfferRecord::getContractOfferId, Function.identity()) + ContractOfferRecord::getAssetId, + Collectors.toMap(ContractOfferRecord::getContractOfferId, Function.identity()) )); } diff --git a/extensions/broker-server/src/test/java/de/sovity/edc/ext/brokerserver/services/refreshing/offers/DiffUtilsTest.java b/extensions/catalog-crawler/catalog-crawler/src/test/java/de/sovity/edc/ext/catalog/crawler/crawling/writing/DiffUtilsTest.java similarity index 79% rename from extensions/broker-server/src/test/java/de/sovity/edc/ext/brokerserver/services/refreshing/offers/DiffUtilsTest.java rename to extensions/catalog-crawler/catalog-crawler/src/test/java/de/sovity/edc/ext/catalog/crawler/crawling/writing/DiffUtilsTest.java index 7a35e66db..79933dc2a 100644 --- a/extensions/broker-server/src/test/java/de/sovity/edc/ext/brokerserver/services/refreshing/offers/DiffUtilsTest.java +++ b/extensions/catalog-crawler/catalog-crawler/src/test/java/de/sovity/edc/ext/catalog/crawler/crawling/writing/DiffUtilsTest.java @@ -12,9 +12,9 @@ * */ -package de.sovity.edc.ext.brokerserver.services.refreshing.offers; +package de.sovity.edc.ext.catalog.crawler.crawling.writing; -import de.sovity.edc.ext.brokerserver.services.refreshing.offers.DiffUtils.DiffResultMatch; +import de.sovity.edc.ext.catalog.crawler.crawling.writing.utils.DiffUtils; import org.junit.jupiter.api.Test; import java.util.List; @@ -35,7 +35,7 @@ void testCompareLists() { // assert assertThat(actual.added()).containsExactly("3"); - assertThat(actual.updated()).containsExactly(new DiffResultMatch<>(1, "1")); + assertThat(actual.updated()).containsExactly(new DiffUtils.DiffResultMatch<>(1, "1")); assertThat(actual.removed()).containsExactly(2); } } diff --git a/extensions/catalog-crawler/catalog-crawler/src/test/java/de/sovity/edc/ext/catalog/crawler/dao/connectors/ConnectorRefTest.java b/extensions/catalog-crawler/catalog-crawler/src/test/java/de/sovity/edc/ext/catalog/crawler/dao/connectors/ConnectorRefTest.java new file mode 100644 index 000000000..6593a5397 --- /dev/null +++ b/extensions/catalog-crawler/catalog-crawler/src/test/java/de/sovity/edc/ext/catalog/crawler/dao/connectors/ConnectorRefTest.java @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2023 sovity GmbH + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + * + * Contributors: + * sovity GmbH - initial API and implementation + * + */ + +package de.sovity.edc.ext.catalog.crawler.dao.connectors; + + +import org.junit.jupiter.api.Test; + +import java.util.HashSet; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; + + +class ConnectorRefTest { + + @Test + void testEqualsTrue() { + // arrange + var a = new ConnectorRef("a", "1", "1", "1", "1"); + var b = new ConnectorRef("a", "2", "2", "2", "2"); + + // act + var result = a.equals(b); + + // assert + assertThat(result).isTrue(); + } + + @Test + void testEqualsFalse() { + // arrange + var a = new ConnectorRef("a", "1", "1", "1", "1"); + var b = new ConnectorRef("b", "1", "1", "1", "1"); + + // act + var result = a.equals(b); + + // assert + assertThat(result).isFalse(); + } + + @Test + void testSet() { + // arrange + var a = new ConnectorRef("a", "1", "1", "1", "1"); + var a2 = new ConnectorRef("a", "2", "2", "2", "2"); + var b = new ConnectorRef("b", "1", "1", "1", "1"); + + // act + var result = new HashSet<>(List.of(a, a2, b)).stream().map(ConnectorRef::getConnectorId).toList(); + + // assert + assertThat(result).containsExactlyInAnyOrder("a", "b"); + } +} diff --git a/extensions/catalog-crawler/catalog-crawler/src/test/java/de/sovity/edc/ext/catalog/crawler/orchestration/queue/ThreadPoolQueueTest.java b/extensions/catalog-crawler/catalog-crawler/src/test/java/de/sovity/edc/ext/catalog/crawler/orchestration/queue/ThreadPoolQueueTest.java new file mode 100644 index 000000000..e6b1ad053 --- /dev/null +++ b/extensions/catalog-crawler/catalog-crawler/src/test/java/de/sovity/edc/ext/catalog/crawler/orchestration/queue/ThreadPoolQueueTest.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2023 sovity GmbH + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + * + * Contributors: + * sovity GmbH - initial API and implementation + * + */ + +package de.sovity.edc.ext.catalog.crawler.orchestration.queue; + +import de.sovity.edc.ext.catalog.crawler.dao.connectors.ConnectorRef; +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.util.ArrayList; + +import static org.mockito.Mockito.mock; + +class ThreadPoolQueueTest { + + + /** + * Regression against bug where the queue did not act like a queue. + */ + @Test + void testOrdering() { + Runnable noop = () -> { + }; + + var c10 = mock(ConnectorRef.class); + var c20 = mock(ConnectorRef.class); + var c11 = mock(ConnectorRef.class); + var c21 = mock(ConnectorRef.class); + var c00 = mock(ConnectorRef.class); + + var queue = new ThreadPoolTaskQueue(); + queue.add(new ThreadPoolTask(1, noop, c10)); + queue.add(new ThreadPoolTask(2, noop, c20)); + queue.add(new ThreadPoolTask(1, noop, c11)); + queue.add(new ThreadPoolTask(2, noop, c21)); + queue.add(new ThreadPoolTask(0, noop, c00)); + + var result = new ArrayList(); + queue.getQueue().drainTo(result); + + Assertions.assertThat(result).extracting(ThreadPoolTask::getConnectorRef) + .containsExactly(c00, c10, c11, c20, c21); + } +} diff --git a/extensions/catalog-crawler/catalog-crawler/src/test/java/de/sovity/edc/ext/catalog/crawler/orchestration/schedules/OfflineConnectorRemovalJobTest.java b/extensions/catalog-crawler/catalog-crawler/src/test/java/de/sovity/edc/ext/catalog/crawler/orchestration/schedules/OfflineConnectorRemovalJobTest.java new file mode 100644 index 000000000..f054ff5b8 --- /dev/null +++ b/extensions/catalog-crawler/catalog-crawler/src/test/java/de/sovity/edc/ext/catalog/crawler/orchestration/schedules/OfflineConnectorRemovalJobTest.java @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2023 sovity GmbH + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + * + * Contributors: + * sovity GmbH - initial API and implementation + * + */ + +package de.sovity.edc.ext.catalog.crawler.orchestration.schedules; + +import de.sovity.edc.ext.catalog.crawler.CrawlerTestDb; +import de.sovity.edc.ext.catalog.crawler.TestData; +import de.sovity.edc.ext.catalog.crawler.crawling.OfflineConnectorCleaner; +import de.sovity.edc.ext.catalog.crawler.crawling.logging.CrawlerEventLogger; +import de.sovity.edc.ext.catalog.crawler.dao.CatalogCleaner; +import de.sovity.edc.ext.catalog.crawler.dao.connectors.ConnectorQueries; +import de.sovity.edc.ext.catalog.crawler.dao.connectors.ConnectorRef; +import de.sovity.edc.ext.catalog.crawler.dao.connectors.ConnectorStatusUpdater; +import de.sovity.edc.ext.catalog.crawler.db.jooq.enums.ConnectorOnlineStatus; +import de.sovity.edc.ext.catalog.crawler.orchestration.config.CrawlerConfig; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import java.time.Duration; +import java.time.OffsetDateTime; + +import static de.sovity.edc.ext.catalog.crawler.db.jooq.tables.Connector.CONNECTOR; +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +class OfflineConnectorRemovalJobTest { + @RegisterExtension + private static final CrawlerTestDb TEST_DATABASE = new CrawlerTestDb(); + + ConnectorRef connectorRef = TestData.connectorRef; + + CrawlerConfig crawlerConfig; + OfflineConnectorCleaner offlineConnectorCleaner; + ConnectorQueries connectorQueries; + + @BeforeEach + void beforeEach() { + crawlerConfig = mock(CrawlerConfig.class); + connectorQueries = new ConnectorQueries(crawlerConfig); + offlineConnectorCleaner = new OfflineConnectorCleaner( + crawlerConfig, + new ConnectorQueries(crawlerConfig), + new CrawlerEventLogger(), + new ConnectorStatusUpdater(), + new CatalogCleaner() + ); + when(crawlerConfig.getEnvironmentId()).thenReturn(connectorRef.getEnvironmentId()); + } + + @Test + void test_offlineConnectorCleaner_should_be_dead() { + TEST_DATABASE.testTransaction(dsl -> { + // arrange + when(crawlerConfig.getKillOfflineConnectorsAfter()).thenReturn(Duration.ofDays(5)); + TestData.insertConnector(dsl, connectorRef, record -> { + record.setOnlineStatus(ConnectorOnlineStatus.OFFLINE); + record.setLastSuccessfulRefreshAt(OffsetDateTime.now().minusDays(6)); + }); + + // act + offlineConnectorCleaner.cleanConnectorsIfOfflineTooLong(dsl); + + // assert + var connector = dsl.fetchOne(CONNECTOR, CONNECTOR.CONNECTOR_ID.eq(connectorRef.getConnectorId())); + assertThat(connector.getOnlineStatus()).isEqualTo(ConnectorOnlineStatus.DEAD); + }); + } + + @Test + void test_offlineConnectorCleaner_should_not_be_dead() { + TEST_DATABASE.testTransaction(dsl -> { + // arrange + when(crawlerConfig.getKillOfflineConnectorsAfter()).thenReturn(Duration.ofDays(5)); + TestData.insertConnector(dsl, connectorRef, record -> { + record.setOnlineStatus(ConnectorOnlineStatus.OFFLINE); + record.setLastSuccessfulRefreshAt(OffsetDateTime.now().minusDays(2)); + }); + + // act + offlineConnectorCleaner.cleanConnectorsIfOfflineTooLong(dsl); + + // assert + var connector = dsl.fetchOne(CONNECTOR, CONNECTOR.CONNECTOR_ID.eq(connectorRef.getConnectorId())); + assertThat(connector.getOnlineStatus()).isEqualTo(ConnectorOnlineStatus.OFFLINE); + }); + } + +} diff --git a/extensions/broker-server/src/test/java/de/sovity/edc/ext/brokerserver/utils/CollectionUtils2Test.java b/extensions/catalog-crawler/catalog-crawler/src/test/java/de/sovity/edc/ext/catalog/crawler/utils/CollectionUtils2Test.java similarity index 62% rename from extensions/broker-server/src/test/java/de/sovity/edc/ext/brokerserver/utils/CollectionUtils2Test.java rename to extensions/catalog-crawler/catalog-crawler/src/test/java/de/sovity/edc/ext/catalog/crawler/utils/CollectionUtils2Test.java index 2b5e926a8..87673188f 100644 --- a/extensions/broker-server/src/test/java/de/sovity/edc/ext/brokerserver/utils/CollectionUtils2Test.java +++ b/extensions/catalog-crawler/catalog-crawler/src/test/java/de/sovity/edc/ext/catalog/crawler/utils/CollectionUtils2Test.java @@ -12,7 +12,7 @@ * */ -package de.sovity.edc.ext.brokerserver.utils; +package de.sovity.edc.ext.catalog.crawler.utils; import org.junit.jupiter.api.Test; @@ -41,20 +41,4 @@ void isNotEmpty_withNull() { void isNotEmpty_withNonEmptyList() { assertThat(CollectionUtils2.isNotEmpty(List.of(1))).isTrue(); } - - - @Test - void allElementsWithoutGivenIndex_start() { - assertThat(CollectionUtils2.allElementsExceptForIndex(List.of("A", "B", "C", "D"), 0)).containsExactly("B", "C", "D"); - } - - @Test - void allElementsWithoutGivenIndex_middle() { - assertThat(CollectionUtils2.allElementsExceptForIndex(List.of("A", "B", "C", "D"), 2)).containsExactly("A", "B", "D"); - } - - @Test - void allElementsWithoutGivenIndex_end() { - assertThat(CollectionUtils2.allElementsExceptForIndex(List.of("A", "B", "C", "D"), 3)).containsExactly("A", "B", "C"); - } } diff --git a/extensions/broker-server/src/test/java/de/sovity/edc/ext/brokerserver/utils/JsonUtils2Test.java b/extensions/catalog-crawler/catalog-crawler/src/test/java/de/sovity/edc/ext/catalog/crawler/utils/JsonUtils2Test.java similarity index 95% rename from extensions/broker-server/src/test/java/de/sovity/edc/ext/brokerserver/utils/JsonUtils2Test.java rename to extensions/catalog-crawler/catalog-crawler/src/test/java/de/sovity/edc/ext/catalog/crawler/utils/JsonUtils2Test.java index 1279a31be..8843aebbb 100644 --- a/extensions/broker-server/src/test/java/de/sovity/edc/ext/brokerserver/utils/JsonUtils2Test.java +++ b/extensions/catalog-crawler/catalog-crawler/src/test/java/de/sovity/edc/ext/catalog/crawler/utils/JsonUtils2Test.java @@ -12,7 +12,7 @@ * */ -package de.sovity.edc.ext.brokerserver.utils; +package de.sovity.edc.ext.catalog.crawler.utils; import org.junit.jupiter.api.Test; diff --git a/extensions/broker-server/src/test/java/de/sovity/edc/ext/brokerserver/utils/StringUtils2Test.java b/extensions/catalog-crawler/catalog-crawler/src/test/java/de/sovity/edc/ext/catalog/crawler/utils/StringUtils2Test.java similarity index 68% rename from extensions/broker-server/src/test/java/de/sovity/edc/ext/brokerserver/utils/StringUtils2Test.java rename to extensions/catalog-crawler/catalog-crawler/src/test/java/de/sovity/edc/ext/catalog/crawler/utils/StringUtils2Test.java index 70f415ae5..1cbd56dd5 100644 --- a/extensions/broker-server/src/test/java/de/sovity/edc/ext/brokerserver/utils/StringUtils2Test.java +++ b/extensions/catalog-crawler/catalog-crawler/src/test/java/de/sovity/edc/ext/catalog/crawler/utils/StringUtils2Test.java @@ -12,12 +12,10 @@ * */ -package de.sovity.edc.ext.brokerserver.utils; +package de.sovity.edc.ext.catalog.crawler.utils; import org.junit.jupiter.api.Test; -import java.util.List; - import static org.assertj.core.api.Assertions.assertThat; class StringUtils2Test { @@ -43,20 +41,4 @@ void removeSuffix_withoutSuffix() { assertThat(StringUtils2.removeSuffix("test", "abc")).isEqualTo("test"); } - - @Test - void lowercaseWords_emptyString() { - assertThat(StringUtils2.lowercaseWords("")).isEmpty(); - } - - @Test - void lowercaseWords_blankString() { - assertThat(StringUtils2.lowercaseWords(" ")).isEmpty(); - } - - - @Test - void lowercaseWords_someWords() { - assertThat(StringUtils2.lowercaseWords(" a \n\t B a ")).isEqualTo(List.of("a", "b", "a")); - } } diff --git a/extensions/catalog-crawler/catalog-crawler/src/test/resources/logging.properties b/extensions/catalog-crawler/catalog-crawler/src/test/resources/logging.properties new file mode 100644 index 000000000..471bd20d6 --- /dev/null +++ b/extensions/catalog-crawler/catalog-crawler/src/test/resources/logging.properties @@ -0,0 +1,6 @@ +.level=ALL +org.eclipse.edc.level=ALL +handlers=java.util.logging.ConsoleHandler +java.util.logging.ConsoleHandler.formatter=java.util.logging.SimpleFormatter +java.util.logging.ConsoleHandler.level=ALL +java.util.logging.SimpleFormatter.format=[%1$tY-%1$tm-%1$td %1$tH:%1$tM:%1$tS] [%4$-7s] %5$s%6$s%n diff --git a/extensions/broker-server-postgres-flyway-jooq/README.md b/extensions/postgres-flyway-core/README.md similarity index 56% rename from extensions/broker-server-postgres-flyway-jooq/README.md rename to extensions/postgres-flyway-core/README.md index ac9be06e0..8c0cb00da 100644 --- a/extensions/broker-server-postgres-flyway-jooq/README.md +++ b/extensions/postgres-flyway-core/README.md @@ -5,7 +5,7 @@ Logo -

Broker Server:
PostgreSQL + Flyway + JooQ

+

EDC-Connector Extension:
Flyway + Hikari Utils

Report Bug @@ -14,13 +14,15 @@

-## About this Extension Package +## About this Module -This module contains: +Flyway and Hikari common code used between our EDC Launchers, tests and the Crawler. -- An EDC Extension migrating the db schema on startup. -- The entire Broker Server DB Schema as JooQ generated code. -- A `DslContextFactory` to quickly start using the JooQ generated code. +It is un-opinionated regarding the location of the migration scripts and does not provide an EDC extension. + +## Why does this extension exist? + +Programmatically calling Flyways migrations is verbose, and unfortunately our EDC Flyway extension is riddled with legacy code. ## License diff --git a/extensions/postgres-flyway-core/build.gradle.kts b/extensions/postgres-flyway-core/build.gradle.kts new file mode 100644 index 000000000..5e8b2ef2f --- /dev/null +++ b/extensions/postgres-flyway-core/build.gradle.kts @@ -0,0 +1,26 @@ + +plugins { + `java-library` + `maven-publish` +} + +dependencies { + annotationProcessor(libs.lombok) + compileOnly(libs.lombok) + + api(libs.flyway.core) + api(libs.postgres) + api(libs.hikari) + + implementation(libs.apache.commonsLang) +} + +group = libs.versions.sovityEdcExtensionGroup.get() + +publishing { + publications { + create(project.name) { + from(components["java"]) + } + } +} diff --git a/extensions/postgres-flyway-core/src/main/java/de/sovity/edc/extension/postgresql/FlywayExecutionParams.java b/extensions/postgres-flyway-core/src/main/java/de/sovity/edc/extension/postgresql/FlywayExecutionParams.java new file mode 100644 index 000000000..f56da9d6b --- /dev/null +++ b/extensions/postgres-flyway-core/src/main/java/de/sovity/edc/extension/postgresql/FlywayExecutionParams.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2023 sovity GmbH + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + * + * Contributors: + * sovity GmbH - initial implementation + * + */ + +package de.sovity.edc.extension.postgresql; + +import lombok.Builder; +import lombok.Singular; +import lombok.Value; +import lombok.With; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Consumer; + +@Builder +@Value +@With +public class FlywayExecutionParams { + @Builder.Default + Consumer infoLogger = System.out::println; + + @Builder.Default + List migrationLocations = new ArrayList<>(); + + @Builder.Default + boolean migrate = false; + + @Builder.Default + boolean tryRepairOnFailedMigration = false; + + @Builder.Default + boolean cleanEnabled = false; + + @Builder.Default + boolean clean = false; + + @Builder.Default + String table = "flyway_schema_history"; +} diff --git a/extensions/postgres-flyway-core/src/main/java/de/sovity/edc/extension/postgresql/FlywayUtils.java b/extensions/postgres-flyway-core/src/main/java/de/sovity/edc/extension/postgresql/FlywayUtils.java new file mode 100644 index 000000000..be116cc23 --- /dev/null +++ b/extensions/postgres-flyway-core/src/main/java/de/sovity/edc/extension/postgresql/FlywayUtils.java @@ -0,0 +1,141 @@ +/* + * Copyright (c) 2023 sovity GmbH + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + * + * Contributors: + * sovity GmbH - initial implementation + * + */ + +package de.sovity.edc.extension.postgresql; + +import lombok.AccessLevel; +import lombok.RequiredArgsConstructor; +import org.apache.commons.lang3.StringUtils; +import org.flywaydb.core.Flyway; +import org.flywaydb.core.api.FlywayException; +import org.flywaydb.core.api.output.MigrateResult; +import org.flywaydb.core.api.output.RepairResult; + +import java.util.Arrays; +import java.util.List; +import javax.sql.DataSource; + +@RequiredArgsConstructor(access = AccessLevel.PRIVATE) +public class FlywayUtils { + private final FlywayExecutionParams params; + private final DataSource dataSource; + + public static void cleanAndMigrate(FlywayExecutionParams params, DataSource dataSource) { + var instance = new FlywayUtils(params, dataSource); + instance.cleanIfEnabled(); + instance.migrateOrValidate(); + } + + public static List parseFlywayLocations(String locations) { + return Arrays.stream(locations.split(",")) + .map(String::trim) + .filter(StringUtils::isNotBlank) + .toList(); + } + + private void cleanIfEnabled() { + if (params.isClean()) { + params.getInfoLogger().accept("Running flyway clean."); + var flyway = setupFlyway(); + flyway.clean(); + } + } + + private void migrateOrValidate() { + if (params.isMigrate()) { + migrate(); + } else { + validate(); + } + } + + private void validate() { + var flyway = setupFlyway(); + flyway.validate(); + } + + private void migrate() { + var flyway = setupFlyway(); + flyway.info().getInfoResult().migrations.stream() + .map(migration -> "Found migration: %s".formatted(migration.filepath)) + .forEach(it -> params.getInfoLogger().accept(it)); + + try { + var migrateResult = flyway.migrate(); + handleFlywayMigrationResult(migrateResult); + } catch (FlywayException e) { + if (params.isTryRepairOnFailedMigration()) { + repairAndRetryMigration(flyway); + } else { + throw new IllegalStateException("Flyway migration failed for '%s'" + .formatted(params.getTable()), e); + } + } + } + + private void repairAndRetryMigration(Flyway flyway) { + try { + var repairResult = flyway.repair(); + handleFlywayRepairResult(repairResult); + var migrateResult = flyway.migrate(); + handleFlywayMigrationResult(migrateResult); + } catch (FlywayException e) { + throw new IllegalStateException("Flyway migration failed for '%s'" + .formatted(params.getTable()), e); + } + } + + private void handleFlywayRepairResult(RepairResult repairResult) { + if (!repairResult.repairActions.isEmpty()) { + var repairActions = String.join(", ", repairResult.repairActions); + params.getInfoLogger().accept("Repair actions for datasource %s: %s" + .formatted(params.getTable(), repairActions)); + } + + if (!repairResult.warnings.isEmpty()) { + var warnings = String.join(", ", repairResult.warnings); + throw new IllegalStateException("Repairing datasource %s failed: %s" + .formatted(params.getTable(), warnings)); + } + } + + private Flyway setupFlyway() { + params.getInfoLogger().accept("Flyway migration locations for '%s': %s".formatted( + params.getTable(), params.getMigrationLocations())); + return Flyway.configure() + .baselineOnMigrate(true) + .failOnMissingLocations(true) + .dataSource(dataSource) + .table(params.getTable()) + .locations(params.getMigrationLocations().toArray(new String[0])) + .cleanDisabled(!params.isCleanEnabled()) + .load(); + } + + private void handleFlywayMigrationResult(MigrateResult migrateResult) { + if (migrateResult.migrationsExecuted > 0) { + params.getInfoLogger().accept(String.format( + "Successfully migrated database for datasource %s " + + "from version %s to version %s", + params.getTable(), + migrateResult.initialSchemaVersion, + migrateResult.targetSchemaVersion)); + } else { + params.getInfoLogger().accept(String.format( + "No migration necessary for datasource %s. Current version is %s", + params.getTable(), + migrateResult.initialSchemaVersion)); + } + } +} diff --git a/extensions/broker-server-postgres-flyway-jooq/src/main/java/de/sovity/edc/ext/brokerserver/db/DataSourceFactory.java b/extensions/postgres-flyway-core/src/main/java/de/sovity/edc/extension/postgresql/HikariDataSourceFactory.java similarity index 59% rename from extensions/broker-server-postgres-flyway-jooq/src/main/java/de/sovity/edc/ext/brokerserver/db/DataSourceFactory.java rename to extensions/postgres-flyway-core/src/main/java/de/sovity/edc/extension/postgresql/HikariDataSourceFactory.java index 70abc53e8..bfbb7d3be 100644 --- a/extensions/broker-server-postgres-flyway-jooq/src/main/java/de/sovity/edc/ext/brokerserver/db/DataSourceFactory.java +++ b/extensions/postgres-flyway-core/src/main/java/de/sovity/edc/extension/postgresql/HikariDataSourceFactory.java @@ -12,40 +12,23 @@ * */ -package de.sovity.edc.ext.brokerserver.db; +package de.sovity.edc.extension.postgresql; import com.zaxxer.hikari.HikariConfig; import com.zaxxer.hikari.HikariDataSource; -import de.sovity.edc.ext.brokerserver.db.utils.JdbcCredentials; -import lombok.RequiredArgsConstructor; -import org.eclipse.edc.spi.system.configuration.Config; +import lombok.experimental.UtilityClass; import javax.sql.DataSource; -@RequiredArgsConstructor -public class DataSourceFactory { - private final Config config; - - - /** - * Create a new {@link DataSource} from EDC Config. - * - * @return {@link DataSource}. - */ - public HikariDataSource newDataSource() { - var jdbcCredentials = JdbcCredentials.fromConfig(config); - int maxPoolSize = config.getInteger(PostgresFlywayExtension.DB_CONNECTION_POOL_SIZE); - int connectionTimeoutInMs = config.getInteger(PostgresFlywayExtension.DB_CONNECTION_TIMEOUT_IN_MS); - return newDataSource(jdbcCredentials, maxPoolSize, connectionTimeoutInMs); - } - +@UtilityClass +public class HikariDataSourceFactory { /** * Create a new {@link DataSource}. *
* This method is static, so we can use from test code. * - * @param jdbcCredentials jdbc credentials - * @param maxPoolSize max pool size + * @param jdbcCredentials jdbc credentials + * @param maxPoolSize max pool size * @param connectionTimeoutInMs connection timeout in ms * @return {@link DataSource}. */ @@ -61,7 +44,7 @@ public static HikariDataSource newDataSource( hikariConfig.setMinimumIdle(1); hikariConfig.setMaximumPoolSize(maxPoolSize); hikariConfig.setIdleTimeout(30000); - hikariConfig.setPoolName("edc-broker-server"); + hikariConfig.setPoolName("edc-server"); hikariConfig.setMaxLifetime(50000); hikariConfig.setConnectionTimeout(connectionTimeoutInMs); diff --git a/extensions/broker-server/src/test/java/de/sovity/edc/ext/brokerserver/db/TestDatabaseCancelTransactionException.java b/extensions/postgres-flyway-core/src/main/java/de/sovity/edc/extension/postgresql/JdbcCredentials.java similarity index 53% rename from extensions/broker-server/src/test/java/de/sovity/edc/ext/brokerserver/db/TestDatabaseCancelTransactionException.java rename to extensions/postgres-flyway-core/src/main/java/de/sovity/edc/extension/postgresql/JdbcCredentials.java index 31126e7eb..e5cae2227 100644 --- a/extensions/broker-server/src/test/java/de/sovity/edc/ext/brokerserver/db/TestDatabaseCancelTransactionException.java +++ b/extensions/postgres-flyway-core/src/main/java/de/sovity/edc/extension/postgresql/JdbcCredentials.java @@ -12,8 +12,18 @@ * */ -package de.sovity.edc.ext.brokerserver.db; - -public class TestDatabaseCancelTransactionException extends RuntimeException { +package de.sovity.edc.extension.postgresql; +/** + * JDBC Credentials + * + * @param jdbcUrl JDBC URL without credentials + * @param jdbcUser JDBC User + * @param jdbcPassword JDBC Password + */ +public record JdbcCredentials( + String jdbcUrl, + String jdbcUser, + String jdbcPassword +) { } diff --git a/extensions/postgres-flyway/src/main/java/de/sovity/edc/extension/postgresql/PostgresFlywayExtension.java b/extensions/postgres-flyway/src/main/java/de/sovity/edc/extension/postgresql/PostgresFlywayExtension.java index 357892532..28afc4ae9 100644 --- a/extensions/postgres-flyway/src/main/java/de/sovity/edc/extension/postgresql/PostgresFlywayExtension.java +++ b/extensions/postgres-flyway/src/main/java/de/sovity/edc/extension/postgresql/PostgresFlywayExtension.java @@ -103,4 +103,10 @@ public void initialize(ServiceExtensionContext context) { migrator.updateDatabaseWithLegacyHandling(); } + @Override + public void shutdown() { + if (dataSource != null) { + dataSource.close(); + } + } } diff --git a/extensions/wrapper/README.md b/extensions/wrapper/README.md index 0d463cde7..049416077 100644 --- a/extensions/wrapper/README.md +++ b/extensions/wrapper/README.md @@ -41,8 +41,8 @@ Our EDC API Wrapper APIs and API Clients are compatible with both our sovity EDC - [TypeScript API Client Library](./clients/typescript-client) - [TypeScript API Client Library Example](./clients/typescript-client-example) - Utilities: - - Broker UI / Connector UI [Common Models](./wrapper-common-api) - - Broker / Connector [Common Services](./wrapper-common-mappers) + - Opinionated and simplified Asset and Policy [Models](./wrapper-common-api) + - Opinionated and simplified Asset and Policy [Mappers](./wrapper-common-mappers) ## License diff --git a/extensions/wrapper/wrapper-api/src/main/java/de/sovity/edc/ext/wrapper/api/ui/model/ContractAgreementTerminationInfo.java b/extensions/wrapper/wrapper-api/src/main/java/de/sovity/edc/ext/wrapper/api/ui/model/ContractAgreementTerminationInfo.java index d96223ef7..0f7cf243e 100644 --- a/extensions/wrapper/wrapper-api/src/main/java/de/sovity/edc/ext/wrapper/api/ui/model/ContractAgreementTerminationInfo.java +++ b/extensions/wrapper/wrapper-api/src/main/java/de/sovity/edc/ext/wrapper/api/ui/model/ContractAgreementTerminationInfo.java @@ -40,4 +40,10 @@ public class ContractAgreementTerminationInfo { requiredMode = Schema.RequiredMode.REQUIRED ) private String detail; + + @Schema( + description = "Indicates whether the termination comes from this EDC or the counterparty EDC.", + requiredMode = Schema.RequiredMode.REQUIRED + ) + private ContractTerminatedBy terminatedBy; } diff --git a/extensions/broker-server-api/api/src/main/java/de/sovity/edc/ext/brokerserver/api/model/ConnectorOnlineStatus.java b/extensions/wrapper/wrapper-api/src/main/java/de/sovity/edc/ext/wrapper/api/ui/model/ContractTerminatedBy.java similarity index 58% rename from extensions/broker-server-api/api/src/main/java/de/sovity/edc/ext/brokerserver/api/model/ConnectorOnlineStatus.java rename to extensions/wrapper/wrapper-api/src/main/java/de/sovity/edc/ext/wrapper/api/ui/model/ContractTerminatedBy.java index 78295e455..f249a3869 100644 --- a/extensions/broker-server-api/api/src/main/java/de/sovity/edc/ext/brokerserver/api/model/ConnectorOnlineStatus.java +++ b/extensions/wrapper/wrapper-api/src/main/java/de/sovity/edc/ext/wrapper/api/ui/model/ContractTerminatedBy.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 sovity GmbH + * Copyright (c) 2024 sovity GmbH * * This program and the accompanying materials are made available under the * terms of the Apache License, Version 2.0 which is available at @@ -9,17 +9,14 @@ * * Contributors: * sovity GmbH - initial API and implementation - * */ -package de.sovity.edc.ext.brokerserver.api.model; +package de.sovity.edc.ext.wrapper.api.ui.model; import io.swagger.v3.oas.annotations.media.Schema; -@Schema(description = "Connector's online status") -public enum ConnectorOnlineStatus { - ONLINE, - OFFLINE, - DEAD +@Schema(description = "Whether the contract termination was initiated by this EDC or a counterparty EDC.", enumAsRef = true) +public enum ContractTerminatedBy { + SELF, + COUNTERPARTY } - diff --git a/extensions/wrapper/wrapper-api/src/main/java/de/sovity/edc/ext/wrapper/api/ui/model/ContractTerminationStatus.java b/extensions/wrapper/wrapper-api/src/main/java/de/sovity/edc/ext/wrapper/api/ui/model/ContractTerminationStatus.java index b802b60ba..652c18364 100644 --- a/extensions/wrapper/wrapper-api/src/main/java/de/sovity/edc/ext/wrapper/api/ui/model/ContractTerminationStatus.java +++ b/extensions/wrapper/wrapper-api/src/main/java/de/sovity/edc/ext/wrapper/api/ui/model/ContractTerminationStatus.java @@ -13,6 +13,9 @@ package de.sovity.edc.ext.wrapper.api.ui.model; +import io.swagger.v3.oas.annotations.media.Schema; + +@Schema(description = "The contract termination status", enumAsRef = true) public enum ContractTerminationStatus { ONGOING, TERMINATED diff --git a/extensions/wrapper/wrapper-common-api/README.md b/extensions/wrapper/wrapper-common-api/README.md index 3194a827f..5a0f6b0a5 100644 --- a/extensions/wrapper/wrapper-common-api/README.md +++ b/extensions/wrapper/wrapper-common-api/README.md @@ -16,8 +16,7 @@ ## About this module -Common API models between the sovity Community Edition EDC API, sovity Enterprise Edition EDC API and/or the Broker -Server API. +Common API models between the sovity Community Edition EDC API, sovity Enterprise Edition EDC API and/or the Authority Portal. ## Why does this module exist? diff --git a/extensions/wrapper/wrapper-common-mappers/README.md b/extensions/wrapper/wrapper-common-mappers/README.md index 5020b55b5..62a63b282 100644 --- a/extensions/wrapper/wrapper-common-mappers/README.md +++ b/extensions/wrapper/wrapper-common-mappers/README.md @@ -17,13 +17,12 @@ ## About this module Common API models naooers between the sovity Community Edition EDC API, sovity Enterprise Edition EDC API and/or the -Broker -Server API. +Authority Portal. ## Why does this module exist? Our common API models defined in [wrapper-common-api](../wrapper-common-api) need mapping to and from the core EDC -types in both the EDC CE, EDC EE and Broker Server. +types in both the EDC CE, EDC EE and Authority Portal. ## License diff --git a/extensions/wrapper/wrapper-common-mappers/src/main/java/de/sovity/edc/ext/wrapper/api/common/mappers/asset/utils/ShortDescriptionBuilder.java b/extensions/wrapper/wrapper-common-mappers/src/main/java/de/sovity/edc/ext/wrapper/api/common/mappers/asset/utils/ShortDescriptionBuilder.java index 0d85792dd..1f59e9960 100644 --- a/extensions/wrapper/wrapper-common-mappers/src/main/java/de/sovity/edc/ext/wrapper/api/common/mappers/asset/utils/ShortDescriptionBuilder.java +++ b/extensions/wrapper/wrapper-common-mappers/src/main/java/de/sovity/edc/ext/wrapper/api/common/mappers/asset/utils/ShortDescriptionBuilder.java @@ -25,11 +25,11 @@ public String buildShortDescription(String descriptionMarkdown) { return null; } - var text = extractText(descriptionMarkdown); + var text = extractMarkdownText(descriptionMarkdown); return abbreviate(text, 300); } - String extractText(String markdown) { + public String extractMarkdownText(String markdown) { var options = new MutableDataSet(); var parser = Parser.builder(options).build(); var renderer = HtmlRenderer.builder(options).build(); diff --git a/extensions/wrapper/wrapper/src/main/java/de/sovity/edc/ext/wrapper/api/ui/pages/transferhistory/TransferHistoryPageApiService.java b/extensions/wrapper/wrapper/src/main/java/de/sovity/edc/ext/wrapper/api/ui/pages/transferhistory/TransferHistoryPageApiService.java index a72e1ddad..30340044c 100644 --- a/extensions/wrapper/wrapper/src/main/java/de/sovity/edc/ext/wrapper/api/ui/pages/transferhistory/TransferHistoryPageApiService.java +++ b/extensions/wrapper/wrapper/src/main/java/de/sovity/edc/ext/wrapper/api/ui/pages/transferhistory/TransferHistoryPageApiService.java @@ -35,6 +35,7 @@ import java.util.Comparator; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Optional; import java.util.function.BinaryOperator; import java.util.function.Function; @@ -60,7 +61,7 @@ public class TransferHistoryPageApiService { public List getTransferHistoryEntries() { var negotiationsById = getAllContractNegotiations().stream() - .filter(negotiation -> negotiation != null) + .filter(Objects::nonNull) .filter(negotiation -> negotiation.getContractAgreement() != null) .collect(toMap( it -> it.getContractAgreement().getId(), @@ -98,7 +99,7 @@ public List getTransferHistoryEntries() { } agreement.ifPresent(it -> transferHistoryEntry.setContractAgreementId(it.getId())); - negotiation.ifPresent( it -> { + negotiation.ifPresent(it -> { transferHistoryEntry.setCounterPartyConnectorEndpoint(it.getCounterPartyAddress()); transferHistoryEntry.setCounterPartyParticipantId(it.getCounterPartyId()); transferHistoryEntry.setCreatedDate(utcMillisToOffsetDateTime(it.getCreatedAt())); diff --git a/extensions/wrapper/wrapper/src/test/java/de/sovity/edc/ext/wrapper/api/ui/pages/policy/PolicyDefinitionApiServiceTest.java b/extensions/wrapper/wrapper/src/test/java/de/sovity/edc/ext/wrapper/api/ui/pages/policy/PolicyDefinitionApiServiceTest.java index d9edd6444..2156b609a 100644 --- a/extensions/wrapper/wrapper/src/test/java/de/sovity/edc/ext/wrapper/api/ui/pages/policy/PolicyDefinitionApiServiceTest.java +++ b/extensions/wrapper/wrapper/src/test/java/de/sovity/edc/ext/wrapper/api/ui/pages/policy/PolicyDefinitionApiServiceTest.java @@ -28,6 +28,7 @@ import org.eclipse.edc.connector.spi.policydefinition.PolicyDefinitionService; import org.eclipse.edc.junit.annotations.ApiTest; import org.eclipse.edc.junit.extensions.EdcExtension; +import org.eclipse.edc.junit.extensions.EdcRuntimeExtension; import org.eclipse.edc.spi.entity.Entity; import org.eclipse.edc.spi.query.QuerySpec; import org.junit.jupiter.api.BeforeEach; diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 594272d25..64584f996 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,7 +1,7 @@ [versions] # groups edcGroup="org.eclipse.edc" -sovityBrokerServerGroup = "de.sovity.broker" +sovityCatalogCrawlerGroup = "de.sovity.edc.catalog.crawler" sovityEdcExtensionGroup = "de.sovity.edc.ext" sovityEdcGroup = "de.sovity.edc" diff --git a/launchers/.env.broker b/launchers/.env.catalog-crawler similarity index 58% rename from launchers/.env.broker rename to launchers/.env.catalog-crawler index cc006d7cd..77aa13f53 100644 --- a/launchers/.env.broker +++ b/launchers/.env.catalog-crawler @@ -5,66 +5,55 @@ # - Watch out for escaping issues as values will be surrounded by quotes, and dollar signs must be escaped. # =========================================================== -# Available Broker Server Config +# Available Catalog Crawler Config # =========================================================== +# Environment ID +CRAWLER_ENVIRONMENT_ID=missing-env-CRAWLER_ENVIRONMENT_ID + # Fully Qualified Domain Name (e.g. example.com) MY_EDC_FQDN=missing-env-MY_EDC_FQDN # Postgres Database Connection -MY_EDC_JDBC_URL=jdbc:postgresql://missing-postgresql-url -MY_EDC_JDBC_USER=missing-postgresql-user -MY_EDC_JDBC_PASSWORD=missing-postgresql-password - -# Broker Server Admin Api Key (required) -# This is a stopgap until we have IAM -EDC_BROKER_SERVER_ADMIN_API_KEY=DefaultBrokerServerAdminApiKey +CRAWLER_DB_JDBC_URL=jdbc:postgresql://missing-postgresql-url +CRAWLER_DB_JDBC_USER=missing-postgresql-user +CRAWLER_DB_JDBC_PASSWORD=missing-postgresql-password # Database Connection Pool Size -EDC_BROKER_SERVER_DB_CONNECTION_POOL_SIZE=30 +CRAWLER_DB_CONNECTION_POOL_SIZE=30 # Database Connection Timeout (in ms) -EDC_BROKER_SERVER_DB_CONNECTION_TIMEOUT_IN_MS=30000 - -# List of Connectors to be added on startup -EDC_BROKER_SERVER_KNOWN_CONNECTORS= - -# Default Data Space Name -EDC_BROKER_SERVER_DEFAULT_DATASPACE=MDS - -# List of Data Space Names for special Connectors -# e.g. Mobilithek=https://my-connector1/api/dsp,SomeOtherDataspace=https://my-connector2/api/dsp -EDC_BROKER_SERVER_KNOWN_DATASPACE_CONNECTORS= +CRAWLER_DB_CONNECTION_TIMEOUT_IN_MS=30000 # CRON interval for crawling ONLINE connectors -EDC_BROKER_SERVER_CRON_ONLINE_CONNECTOR_REFRESH=*/20 * * ? * * +CRAWLER_CRON_ONLINE_CONNECTOR_REFRESH=*/20 * * ? * * # CRON interval for crawling OFFLINE connectors -EDC_BROKER_SERVER_CRON_OFFLINE_CONNECTOR_REFRESH=0 */5 * ? * * +CRAWLER_CRON_OFFLINE_CONNECTOR_REFRESH=0 */5 * ? * * # CRON interval for crawling DEAD connectors -EDC_BROKER_SERVER_CRON_DEAD_CONNECTOR_REFRESH=0 0 * ? * * +CRAWLER_CRON_DEAD_CONNECTOR_REFRESH=0 0 * ? * * # CRON interval for marking connectors as DEAD -EDC_BROKER_SERVER_SCHEDULED_KILL_OFFLINE_CONNECTORS=0 0 2 ? * * +CRAWLER_SCHEDULED_KILL_OFFLINE_CONNECTORS=0 0 2 ? * * # Delete data offers / mark as dead after connector has been offline for: -EDC_BROKER_SERVER_KILL_OFFLINE_CONNECTORS_AFTER=P5D +CRAWLER_KILL_OFFLINE_CONNECTORS_AFTER=P5D # Hide data offers after connector has been offline for: -EDC_BROKER_SERVER_HIDE_OFFLINE_DATA_OFFERS_AFTER=P1D +CRAWLER_HIDE_OFFLINE_DATA_OFFERS_AFTER=P1D # Parallelization for Crawling -EDC_BROKER_SERVER_NUM_THREADS=32 +CRAWLER_NUM_THREADS=32 # Maximum number of Data Offers per Connector -EDC_BROKER_SERVER_MAX_DATA_OFFERS_PER_CONNECTOR=50 +CRAWLER_MAX_DATA_OFFERS_PER_CONNECTOR=50 # Maximum number of Contract Offers per Data Offer -EDC_BROKER_SERVER_MAX_CONTRACT_OFFERS_PER_DATA_OFFER=10 +CRAWLER_MAX_CONTRACT_OFFERS_PER_DATA_OFFER=10 -# Pagination Configuration: Catalog Page Size -EDC_BROKER_SERVER_CATALOG_PAGE_PAGE_SIZE=20 +# Enable the extension +CRAWLER_EXTENSION_ENABLED=true # =========================================================== # Other EDC Config @@ -74,7 +63,7 @@ EDC_BROKER_SERVER_CATALOG_PAGE_PAGE_SIZE=20 MY_EDC_PARTICIPANT_ID=broker EDC_CONNECTOR_NAME=${MY_EDC_PARTICIPANT_ID:-MY_EDC_NAME_KEBAB_CASE} EDC_PARTICIPANT_ID=${MY_EDC_PARTICIPANT_ID:-MY_EDC_NAME_KEBAB_CASE} -MY_EDC_BASE_PATH=/backend +MY_EDC_BASE_PATH= MY_EDC_PROTOCOL=https:// WEB_HTTP_PORT=11001 WEB_HTTP_MANAGEMENT_PORT=11002 @@ -85,16 +74,9 @@ WEB_HTTP_MANAGEMENT_PATH=${MY_EDC_BASE_PATH}/api/management WEB_HTTP_PROTOCOL_PATH=${MY_EDC_BASE_PATH}/api/dsp WEB_HTTP_CONTROL_PATH=${MY_EDC_BASE_PATH}/api/control -EDC_CONNECTOR_NAME=$MY_EDC_NAME_KEBAB_CASE EDC_HOSTNAME=${MY_EDC_FQDN} EDC_DSP_CALLBACK_ADDRESS=${MY_EDC_PROTOCOL}${MY_EDC_FQDN}${WEB_HTTP_PROTOCOL_PATH} -# Flyway Extension: Defaults -EDC_DATASOURCE_DEFAULT_NAME=default -EDC_DATASOURCE_DEFAULT_URL=$MY_EDC_JDBC_URL -EDC_DATASOURCE_DEFAULT_USER=$MY_EDC_JDBC_USER -EDC_DATASOURCE_DEFAULT_PASSWORD=$MY_EDC_JDBC_PASSWORD - # Oauth default configurations for compatibility with sovity DAPS EDC_OAUTH_PROVIDER_AUDIENCE=${EDC_OAUTH_TOKEN_URL} EDC_OAUTH_ENDPOINT_AUDIENCE=idsc:IDS_CONNECTORS_ALL diff --git a/launchers/README.md b/launchers/README.md index 9a1f60f3d..dd9d43c90 100644 --- a/launchers/README.md +++ b/launchers/README.md @@ -100,7 +100,6 @@ Our sovity Community Edition EDC is built as several docker image variants in di
  • Management API Auth via API Keys
  • PostgreSQL Persistence & Flyway
  • DAPS Authentication
  • -
  • Broker Extension
  • Clearing House Extension
  • @@ -134,27 +133,24 @@ Our sovity Community Edition EDC is built as several docker image variants in di - broker-dev + catalog-crawler-dev Development
      -
    • Local Demo via our - docker-compose.yaml -
    • +
    • Local Demo
    • E2E Testing
      -
    • Broker Server Extension(s)
    • -
    • PostgreSQL Persistence & Flyway
    • +
    • Catalog Crawler for one environment
    • Mock IAM
    - broker-ce + catalog-crawler-ce Community Edition
      @@ -163,8 +159,7 @@ Our sovity Community Edition EDC is built as several docker image variants in di
        -
      • Broker Server Extension(s)
      • -
      • PostgreSQL Persistence & Flyway
      • +
      • Catalog Crawler for one environment
      • DAPS Authentication
      diff --git a/launchers/connectors/broker-server-ce/build.gradle.kts b/launchers/connectors/broker-server-ce/build.gradle.kts deleted file mode 100644 index dff7d6313..000000000 --- a/launchers/connectors/broker-server-ce/build.gradle.kts +++ /dev/null @@ -1,35 +0,0 @@ -plugins { - `java-library` - id("application") - alias(libs.plugins.shadow) -} - -dependencies { - // Control-Plane - implementation(libs.edc.controlPlaneCore) - implementation(libs.edc.dataPlaneSelectorCore) - implementation(libs.edc.apiObservability) - implementation(libs.edc.configurationFilesystem) - implementation(libs.edc.controlPlaneAggregateServices) - implementation(libs.edc.http) - implementation(libs.edc.dsp) - implementation(libs.edc.jsonLd) - - // JDK Logger - implementation(libs.edc.monitorJdkLogger) - - // Broker Server + PostgreSQL + Flyway - implementation(project(":extensions:broker-server")) - - implementation(libs.edc.vaultFilesystem) - implementation(libs.edc.oauth2Core) -} - -application { - mainClass.set("org.eclipse.edc.boot.system.runtime.BaseRuntime") -} - -tasks.withType { - mergeServiceFiles() - archiveFileName.set("app.jar") -} diff --git a/launchers/connectors/broker-server-dev/build.gradle.kts b/launchers/connectors/broker-server-dev/build.gradle.kts deleted file mode 100644 index 89df7cb7e..000000000 --- a/launchers/connectors/broker-server-dev/build.gradle.kts +++ /dev/null @@ -1,35 +0,0 @@ -plugins { - `java-library` - id("application") - alias(libs.plugins.shadow) -} - -dependencies { - // Control-Plane - implementation(libs.edc.controlPlaneCore) - implementation(libs.edc.dataPlaneSelectorCore) - implementation(libs.edc.apiObservability) - implementation(libs.edc.configurationFilesystem) - implementation(libs.edc.controlPlaneAggregateServices) - implementation(libs.edc.http) - implementation(libs.edc.dsp) - implementation(libs.edc.jsonLd) - - // JDK Logger - implementation(libs.edc.monitorJdkLogger) - - // Broker Server + PostgreSQL + Flyway - implementation(project(":extensions:broker-server")) - - // Connector-To-Connector IAM - implementation(libs.edc.iamMock) -} - -application { - mainClass.set("org.eclipse.edc.boot.system.runtime.BaseRuntime") -} - -tasks.withType { - mergeServiceFiles() - archiveFileName.set("app.jar") -} diff --git a/launchers/connectors/catalog-crawler-ce/build.gradle.kts b/launchers/connectors/catalog-crawler-ce/build.gradle.kts new file mode 100644 index 000000000..e72aa1f52 --- /dev/null +++ b/launchers/connectors/catalog-crawler-ce/build.gradle.kts @@ -0,0 +1,23 @@ +plugins { + `java-library` + id("application") + alias(libs.plugins.shadow) +} + +dependencies { + implementation(project(":extensions:catalog-crawler:catalog-crawler-launcher-base")) + + api(libs.edc.monitorJdkLogger) + api(libs.edc.apiObservability) + + implementation(project(":launchers:common:auth-daps")) +} + +application { + mainClass.set("org.eclipse.edc.boot.system.runtime.BaseRuntime") +} + +tasks.withType { + mergeServiceFiles() + archiveFileName.set("app.jar") +} diff --git a/launchers/connectors/catalog-crawler-dev/build.gradle.kts b/launchers/connectors/catalog-crawler-dev/build.gradle.kts new file mode 100644 index 000000000..c68026e6c --- /dev/null +++ b/launchers/connectors/catalog-crawler-dev/build.gradle.kts @@ -0,0 +1,23 @@ +plugins { + `java-library` + id("application") + alias(libs.plugins.shadow) +} + +dependencies { + implementation(project(":extensions:catalog-crawler:catalog-crawler-launcher-base")) + + api(libs.edc.monitorJdkLogger) + api(libs.edc.apiObservability) + + implementation(project(":launchers:common:auth-mock")) +} + +application { + mainClass.set("org.eclipse.edc.boot.system.runtime.BaseRuntime") +} + +tasks.withType { + mergeServiceFiles() + archiveFileName.set("app.jar") +} diff --git a/launchers/connectors/sovity-dev/build.gradle.kts b/launchers/connectors/sovity-dev/build.gradle.kts index c1d619f2c..c65dd86ff 100644 --- a/launchers/connectors/sovity-dev/build.gradle.kts +++ b/launchers/connectors/sovity-dev/build.gradle.kts @@ -19,4 +19,5 @@ tasks.withType { archiveFileName.set("app.jar") } + group = libs.versions.sovityEdcGroup.get() diff --git a/settings.gradle.kts b/settings.gradle.kts index 7f9ba06d0..bb5b28436 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,16 +1,16 @@ -rootProject.name = "edc-ce" +rootProject.name = "sovity-ce-edc" -include(":connector") -include(":extensions:broker-server") -include(":extensions:broker-server-api:api") -include(":extensions:broker-server-api:client") -include(":extensions:broker-server-postgres-flyway-jooq") +include(":extensions:catalog-crawler:catalog-crawler") +include(":extensions:catalog-crawler:catalog-crawler-db") +include(":extensions:catalog-crawler:catalog-crawler-launcher-base") +include(":extensions:catalog-crawler:catalog-crawler-e2e-test") include(":extensions:edc-ui-config") include(":extensions:last-commit-info") include(":extensions:policy-always-true") include(":extensions:policy-referring-connector") include(":extensions:policy-time-interval") include(":extensions:postgres-flyway") +include(":extensions:postgres-flyway-core") include(":extensions:sovity-messenger") include(":extensions:sovity-edc-extensions-package") include(":extensions:test-backend-controller") @@ -25,10 +25,11 @@ include(":extensions:wrapper:wrapper-ee-api") include(":launchers:common:auth-daps") include(":launchers:common:auth-mock") include(":launchers:common:base") +include(":launchers:common:base-catalog-crawler") include(":launchers:common:base-mds") include(":launchers:common:observability") -include(":launchers:connectors:broker-server-ce") -include(":launchers:connectors:broker-server-dev") +include(":launchers:connectors:catalog-crawler-ce") +include(":launchers:connectors:catalog-crawler-dev") include(":launchers:connectors:mds-ce") include(":launchers:connectors:sovity-ce") include(":launchers:connectors:sovity-dev") diff --git a/utils/test-connector-remote/src/main/java/de/sovity/edc/extension/e2e/connector/config/ConnectorConfigFactory.java b/utils/test-connector-remote/src/main/java/de/sovity/edc/extension/e2e/connector/config/ConnectorConfigFactory.java index 6c7a046f8..a4e3d76a4 100644 --- a/utils/test-connector-remote/src/main/java/de/sovity/edc/extension/e2e/connector/config/ConnectorConfigFactory.java +++ b/utils/test-connector-remote/src/main/java/de/sovity/edc/extension/e2e/connector/config/ConnectorConfigFactory.java @@ -54,7 +54,7 @@ public static ConnectorConfig forTestDatabase(String participantId, TestDatabase return config; } - private static synchronized int getFreePortRange(int size) { + public static synchronized int getFreePortRange(int size) { // pick a random in a reasonable range int firstPort = getFreePort(RANDOM.nextInt(10_000, 50_000)); diff --git a/utils/test-connector-remote/src/main/java/de/sovity/edc/extension/e2e/db/EdcRuntimeExtensionDeferred.java b/utils/test-connector-remote/src/main/java/de/sovity/edc/extension/e2e/db/EdcRuntimeExtensionDeferred.java new file mode 100644 index 000000000..91096b7b8 --- /dev/null +++ b/utils/test-connector-remote/src/main/java/de/sovity/edc/extension/e2e/db/EdcRuntimeExtensionDeferred.java @@ -0,0 +1,36 @@ +package de.sovity.edc.extension.e2e.db; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import lombok.experimental.Delegate; +import org.junit.jupiter.api.extension.AfterTestExecutionCallback; +import org.junit.jupiter.api.extension.BeforeAllCallback; +import org.junit.jupiter.api.extension.BeforeTestExecutionCallback; +import org.junit.jupiter.api.extension.ExtensionContext; +import org.junit.jupiter.api.extension.ParameterResolver; + +import java.util.Map; +import java.util.function.Supplier; + +@RequiredArgsConstructor +public class EdcRuntimeExtensionDeferred + implements BeforeAllCallback, BeforeTestExecutionCallback, AfterTestExecutionCallback, ParameterResolver { + + private final String moduleName; + private final String logPrefix; + + private final Supplier> propertyFactory; + + @Delegate(types = { + BeforeTestExecutionCallback.class, + AfterTestExecutionCallback.class, + ParameterResolver.class + }) + @Getter + private EdcRuntimeExtensionFixed edcRuntimeExtensionFixed = null; + + @Override + public void beforeAll(ExtensionContext extensionContext) throws Exception { + edcRuntimeExtensionFixed = new EdcRuntimeExtensionFixed(moduleName, logPrefix, propertyFactory.get()); + } +} diff --git a/utils/test-connector-remote/src/main/java/de/sovity/edc/extension/e2e/db/EdcRuntimeExtensionFixed.java b/utils/test-connector-remote/src/main/java/de/sovity/edc/extension/e2e/db/EdcRuntimeExtensionFixed.java new file mode 100644 index 000000000..d344b5f00 --- /dev/null +++ b/utils/test-connector-remote/src/main/java/de/sovity/edc/extension/e2e/db/EdcRuntimeExtensionFixed.java @@ -0,0 +1,184 @@ +/* + * Copyright (c) 2022 Microsoft Corporation + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + * + * Contributors: + * Microsoft Corporation - initial API and implementation + * Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - improvements + * + */ + +package de.sovity.edc.extension.e2e.db; + +import org.eclipse.edc.junit.extensions.EdcExtension; +import org.eclipse.edc.junit.testfixtures.TestUtils; +import org.eclipse.edc.spi.EdcException; +import org.eclipse.edc.spi.monitor.ConsoleMonitor; +import org.eclipse.edc.spi.monitor.Monitor; +import org.jetbrains.annotations.NotNull; +import org.junit.jupiter.api.extension.AfterTestExecutionCallback; +import org.junit.jupiter.api.extension.BeforeTestExecutionCallback; +import org.junit.jupiter.api.extension.ExtensionContext; + +import java.io.File; +import java.io.IOException; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.Arrays; +import java.util.Locale; +import java.util.Map; +import java.util.Properties; +import java.util.concurrent.CountDownLatch; +import java.util.stream.Stream; + +import static java.lang.String.format; +import static java.util.concurrent.TimeUnit.SECONDS; +import static org.eclipse.edc.boot.system.ExtensionLoader.loadMonitor; + +/** + * A JUnit extension for running an embedded EDC runtime as part of a test fixture. A custom gradle task printClasspath + * is used to determine the runtime classpath of the module to run. The runtime obtains a classpath determined by the + * Gradle build. + *

      + * This extension attaches an EDC runtime to the {@link BeforeTestExecutionCallback} and + * {@link AfterTestExecutionCallback} lifecycle hooks. Parameter injection of runtime services is supported. + */ +public class EdcRuntimeExtensionFixed extends EdcExtension { + private static final Monitor MONITOR = loadMonitor(); + + private final String moduleName; + private final String logPrefix; + private final Map properties; + private Thread runtimeThread; + + public EdcRuntimeExtensionFixed(String moduleName, String logPrefix, Map properties) { + this.moduleName = moduleName; + this.logPrefix = logPrefix; + this.properties = Map.copyOf(properties); + } + + @Override + public void beforeTestExecution(ExtensionContext extensionContext) throws Exception { + // Find the project root directory, moving up the directory tree + var root = TestUtils.findBuildRoot(); + + // Run a Gradle custom task to determine the runtime classpath of the module to run + String[] command = { + new File(root, TestUtils.GRADLE_WRAPPER).getCanonicalPath(), + "-q", + moduleName + ":printClasspath" + }; + Process exec = Runtime.getRuntime().exec(command); + var classpathString = new String(exec.getInputStream().readAllBytes()); + var errorOutput = new String(exec.getErrorStream().readAllBytes()); + if (exec.waitFor() != 0) { + throw new EdcException(format("Failed to run gradle command: [%s]. Output: %s %s", + String.join(" ", command), classpathString, errorOutput)); + } + + // Replace subproject JAR entries with subproject build directories in classpath. + // This ensures modified classes are picked up without needing to rebuild dependent JARs. + + var splitRegex = ":|\\s"; + if (System.getProperty("os.name").toLowerCase(Locale.ROOT).contains("windows")) { + splitRegex = ";|\\s"; + } + + var classPathEntries = Arrays.stream(classpathString.split(splitRegex)) + .filter(s -> !s.isBlank()) + .flatMap(p -> resolveClassPathEntry(root, p)) + .toArray(URL[]::new); + + // Create a ClassLoader that only has the target module class path, and is not + // parented with the current ClassLoader. + var classLoader = URLClassLoader.newInstance(classPathEntries, ClassLoader.getSystemClassLoader()); + + // Temporarily inject system properties. + var savedProperties = (Properties) System.getProperties().clone(); + properties.forEach(System::setProperty); + + var latch = new CountDownLatch(1); + + runtimeThread = new Thread(() -> { + try { + + // Make the ClassLoader available to the ServiceLoader. + // This ensures the target module's extensions are discovered and loaded at runtime boot. + Thread.currentThread().setContextClassLoader(classLoader); + + // Boot EDC runtime. + super.beforeTestExecution(extensionContext); + + latch.countDown(); + } catch (Exception e) { + throw new EdcException(e); + } + }); + + MONITOR.info("Starting module " + moduleName); + // Start thread and wait for EDC to start up. + runtimeThread.start(); + + if (!latch.await(20, SECONDS)) { + throw new EdcException("Failed to start EDC runtime"); + } + + MONITOR.info("Module " + moduleName + " started"); + // Restore system properties. + System.setProperties(savedProperties); + } + + @Override + public void afterTestExecution(ExtensionContext context) throws Exception { + if (runtimeThread != null) { + runtimeThread.join(); + } + super.afterTestExecution(context); + } + + @Override + protected @NotNull Monitor createMonitor() { + // disable logs when "quiet" log level is set + if (System.getProperty("org.gradle.logging.level") != null) { + return new Monitor() { + }; + } else { + return new ConsoleMonitor(logPrefix, ConsoleMonitor.Level.DEBUG); + } + } + + /** + * Replace Gradle subproject JAR entries with subproject build directories in classpath. This ensures modified + * classes are picked up without needing to rebuild dependent JARs. + * + * @param root project root directory. + * @param classPathEntry class path entry to resolve. + * @return resolved class path entries for the input argument. + */ + private Stream resolveClassPathEntry(File root, String classPathEntry) { + try { + File f = new File(classPathEntry).getCanonicalFile(); + + // If class path entry is not a JAR under the root (i.e. a sub-project), do not transform it + boolean isUnderRoot = f.getCanonicalPath().startsWith(root.getCanonicalPath() + File.separator); + if (!classPathEntry.toLowerCase(Locale.ROOT).endsWith(".jar") || !isUnderRoot) { + var sanitizedClassPathEntry = classPathEntry.replace("build/resources/main", "src/main/resources"); + return Stream.of(new File(sanitizedClassPathEntry).toURI().toURL()); + } + + // Replace JAR entry with the resolved classes and resources folder + var buildDir = f.getParentFile().getParentFile(); + return Stream.of( + new File(buildDir, "/classes/java/main").toURI().toURL(), + new File(buildDir, "../src/main/resources").toURI().toURL() + ); + } catch (IOException e) { + throw new EdcException(e); + } + } +} diff --git a/utils/test-connector-remote/src/main/java/de/sovity/edc/extension/e2e/db/EdcRuntimeExtensionWithTestDatabase.java b/utils/test-connector-remote/src/main/java/de/sovity/edc/extension/e2e/db/EdcRuntimeExtensionWithTestDatabase.java new file mode 100644 index 000000000..af15b7822 --- /dev/null +++ b/utils/test-connector-remote/src/main/java/de/sovity/edc/extension/e2e/db/EdcRuntimeExtensionWithTestDatabase.java @@ -0,0 +1,43 @@ +package de.sovity.edc.extension.e2e.db; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import lombok.experimental.Delegate; +import org.eclipse.edc.junit.extensions.EdcRuntimeExtension; +import org.junit.jupiter.api.extension.AfterAllCallback; +import org.junit.jupiter.api.extension.AfterTestExecutionCallback; +import org.junit.jupiter.api.extension.BeforeAllCallback; +import org.junit.jupiter.api.extension.BeforeTestExecutionCallback; +import org.junit.jupiter.api.extension.ExtensionContext; +import org.junit.jupiter.api.extension.ParameterResolver; + +import java.util.Map; +import java.util.function.Function; + +@RequiredArgsConstructor +public class EdcRuntimeExtensionWithTestDatabase + implements BeforeAllCallback, AfterAllCallback, BeforeTestExecutionCallback, AfterTestExecutionCallback, ParameterResolver { + + private final String moduleName; + private final String logPrefix; + + @Getter + @Delegate(types = {AfterAllCallback.class}) + private final TestDatabase testDatabase = new TestDatabaseViaTestcontainers(); + + private final Function> propertyFactory; + + @Delegate(types = { + BeforeTestExecutionCallback.class, + AfterTestExecutionCallback.class, + ParameterResolver.class + }) + @Getter + private EdcRuntimeExtensionFixed edcRuntimeExtension = null; + + @Override + public void beforeAll(ExtensionContext extensionContext) throws Exception { + testDatabase.beforeAll(extensionContext); + edcRuntimeExtension = new EdcRuntimeExtensionFixed(moduleName, logPrefix, propertyFactory.apply(testDatabase)); + } +}