mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-10-29 15:21:53 +00:00
Compare commits
70 Commits
20.72
...
TagCreatio
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e737daa801 | ||
|
|
640a1120fd | ||
|
|
803cea84e3 | ||
|
|
db2da8338a | ||
|
|
bb5e4d42ac | ||
|
|
dbe0d75764 | ||
|
|
c2d13e3177 | ||
|
|
e8f50da5a2 | ||
|
|
2053e3b83a | ||
|
|
bcc2eadba6 | ||
|
|
eb40dd3a45 | ||
|
|
4c511423d5 | ||
|
|
b12b21e773 | ||
|
|
569078f408 | ||
|
|
90de678d7d | ||
|
|
093bee9ace | ||
|
|
e1974e6b26 | ||
|
|
0a75cbbc67 | ||
|
|
c5f174a55d | ||
|
|
119596647a | ||
|
|
e5d5969fc4 | ||
|
|
b79dc538c9 | ||
|
|
72965efb57 | ||
|
|
d467c3cdb1 | ||
|
|
73d919435c | ||
|
|
5fb86e1bbc | ||
|
|
23de0fefd7 | ||
|
|
7c3e8a2549 | ||
|
|
6a3dbff290 | ||
|
|
0ca29a76a9 | ||
|
|
561e7330e3 | ||
|
|
628b267a2b | ||
|
|
ea9687ac33 | ||
|
|
4292a3ce1c | ||
|
|
09721dca4e | ||
|
|
0e4020452c | ||
|
|
96c1464b6c | ||
|
|
9457e019ef | ||
|
|
41d82cc5ce | ||
|
|
439e8587cf | ||
|
|
a59234f47f | ||
|
|
c9522f299e | ||
|
|
30dd78a6ab | ||
|
|
008134f5b0 | ||
|
|
285ebc29a4 | ||
|
|
9c6e8aad9c | ||
|
|
915fe193e2 | ||
|
|
a2756aa868 | ||
|
|
b28e02c6fa | ||
|
|
8d00a1ab61 | ||
|
|
a86ad3c973 | ||
|
|
2cdbe6f306 | ||
|
|
556e1923d1 | ||
|
|
22e8a506ff | ||
|
|
f63c9ee8c4 | ||
|
|
b5b9b9e2c4 | ||
|
|
9e88a6562e | ||
|
|
dbddc08fcc | ||
|
|
9b5e69e070 | ||
|
|
23f6f6fc90 | ||
|
|
9d8e93474c | ||
|
|
3d450e1d8d | ||
|
|
e587ef124e | ||
|
|
34c8f9e431 | ||
|
|
736cc74479 | ||
|
|
419f498c5a | ||
|
|
f91a35b992 | ||
|
|
1c5a9a74c7 | ||
|
|
2652552da7 | ||
|
|
ff39addcce |
84
.github/workflows/ci.yml
vendored
84
.github/workflows/ci.yml
vendored
@@ -35,8 +35,8 @@ jobs:
|
||||
!contains(github.event.head_commit.message, '[force]')
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v1.32.0
|
||||
- uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v1.32.0
|
||||
- uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v1.33.0
|
||||
- uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v1.33.0
|
||||
- name: "Init"
|
||||
run: bash ./scripts/ci/init.sh
|
||||
- name: "Prepare maven cache and check compilation"
|
||||
@@ -49,16 +49,16 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
needs: [prepare]
|
||||
if: >
|
||||
((github.ref_name == 'master' || contains(github.ref_name, 'release/')) && github.event_name != 'pull_request') &&
|
||||
((github.ref_name == 'master' || startsWith(github.ref_name, 'release/')) && github.event_name != 'pull_request') &&
|
||||
!contains(github.event.head_commit.message, '[skip tests]') &&
|
||||
!contains(github.event.head_commit.message, '[force]')
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v1.32.0
|
||||
- uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v1.32.0
|
||||
- uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v1.33.0
|
||||
- uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v1.33.0
|
||||
- name: "Init"
|
||||
run: bash ./scripts/ci/init.sh
|
||||
- uses: Alfresco/alfresco-build-tools/.github/actions/veracode@v1.32.0
|
||||
- uses: Alfresco/alfresco-build-tools/.github/actions/veracode@v1.33.0
|
||||
continue-on-error: true
|
||||
with:
|
||||
srcclr-api-token: ${{ secrets.SRCCLR_API_TOKEN }}
|
||||
@@ -75,8 +75,8 @@ jobs:
|
||||
!contains(github.event.head_commit.message, '[force]')
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v1.32.0
|
||||
- uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v1.32.0
|
||||
- uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v1.33.0
|
||||
- uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v1.33.0
|
||||
- name: "Init"
|
||||
run: bash ./scripts/ci/init.sh
|
||||
- name: "Run tests"
|
||||
@@ -112,8 +112,8 @@ jobs:
|
||||
REQUIRES_INSTALLED_ARTIFACTS: true
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v1.32.0
|
||||
- uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v1.32.0
|
||||
- uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v1.33.0
|
||||
- uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v1.33.0
|
||||
- name: "Build"
|
||||
timeout-minutes: ${{ fromJSON(env.GITHUB_ACTIONS_DEPLOY_TIMEOUT) }}
|
||||
run: |
|
||||
@@ -133,7 +133,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
needs: [prepare]
|
||||
if: >
|
||||
(((github.ref_name == 'master' || contains(github.ref_name, 'release/')) &&
|
||||
(((github.ref_name == 'master' || startsWith(github.ref_name, 'release/')) &&
|
||||
github.event_name != 'pull_request' &&
|
||||
!contains(github.event.head_commit.message, '[skip db]')) ||
|
||||
contains(github.event.head_commit.message, '[db]')) &&
|
||||
@@ -145,8 +145,8 @@ jobs:
|
||||
version: ['10.2.18', '10.4', '10.5']
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v1.32.0
|
||||
- uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v1.32.0
|
||||
- uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v1.33.0
|
||||
- uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v1.33.0
|
||||
- name: "Init"
|
||||
run: bash ./scripts/ci/init.sh
|
||||
- name: Run MariaDB ${{ matrix.version }} database
|
||||
@@ -163,7 +163,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
needs: [prepare]
|
||||
if: >
|
||||
(((github.ref_name == 'master' || contains(github.ref_name, 'release/') || github.event_name == 'pull_request') &&
|
||||
(((github.ref_name == 'master' || startsWith(github.ref_name, 'release/') || github.event_name == 'pull_request') &&
|
||||
!contains(github.event.head_commit.message, '[skip db]')) ||
|
||||
contains(github.event.head_commit.message, '[latest db]') ||
|
||||
contains(github.event.head_commit.message, '[db]')) &&
|
||||
@@ -171,8 +171,8 @@ jobs:
|
||||
!contains(github.event.head_commit.message, '[force]')
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v1.32.0
|
||||
- uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v1.32.0
|
||||
- uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v1.33.0
|
||||
- uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v1.33.0
|
||||
- name: "Init"
|
||||
run: bash ./scripts/ci/init.sh
|
||||
- name: "Run MariaDB 10.6 database"
|
||||
@@ -189,7 +189,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
needs: [prepare]
|
||||
if: >
|
||||
(((github.ref_name == 'master' || contains(github.ref_name, 'release/') || github.event_name == 'pull_request') &&
|
||||
(((github.ref_name == 'master' || startsWith(github.ref_name, 'release/') || github.event_name == 'pull_request') &&
|
||||
!contains(github.event.head_commit.message, '[skip db]')) ||
|
||||
contains(github.event.head_commit.message, '[latest db]') ||
|
||||
contains(github.event.head_commit.message, '[db]')) &&
|
||||
@@ -197,8 +197,8 @@ jobs:
|
||||
!contains(github.event.head_commit.message, '[force]')
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v1.32.0
|
||||
- uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v1.32.0
|
||||
- uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v1.33.0
|
||||
- uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v1.33.0
|
||||
- name: "Init"
|
||||
run: bash ./scripts/ci/init.sh
|
||||
- name: "Run MySQL 8 database"
|
||||
@@ -215,15 +215,15 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
needs: [prepare]
|
||||
if: >
|
||||
(((github.ref_name == 'master' || contains(github.ref_name, 'release/')) && github.event_name != 'pull_request' &&
|
||||
(((github.ref_name == 'master' || startsWith(github.ref_name, 'release/')) && github.event_name != 'pull_request' &&
|
||||
!contains(github.event.head_commit.message, '[skip db]')) ||
|
||||
contains(github.event.head_commit.message, '[db]')) &&
|
||||
!contains(github.event.head_commit.message, '[skip tests]') &&
|
||||
!contains(github.event.head_commit.message, '[force]')
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v1.32.0
|
||||
- uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v1.32.0
|
||||
- uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v1.33.0
|
||||
- uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v1.33.0
|
||||
- name: "Init"
|
||||
run: bash ./scripts/ci/init.sh
|
||||
- name: "Run PostgreSQL 13.7 database"
|
||||
@@ -247,8 +247,8 @@ jobs:
|
||||
!contains(github.event.head_commit.message, '[force]')
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v1.32.0
|
||||
- uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v1.32.0
|
||||
- uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v1.33.0
|
||||
- uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v1.33.0
|
||||
- name: "Init"
|
||||
run: bash ./scripts/ci/init.sh
|
||||
- name: "Run PostgreSQL 14.4 database"
|
||||
@@ -270,8 +270,8 @@ jobs:
|
||||
!contains(github.event.head_commit.message, '[force]')
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v1.32.0
|
||||
- uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v1.32.0
|
||||
- uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v1.33.0
|
||||
- uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v1.33.0
|
||||
- name: "Init"
|
||||
run: bash ./scripts/ci/init.sh
|
||||
- name: "Run ActiveMQ"
|
||||
@@ -315,8 +315,8 @@ jobs:
|
||||
mvn-options: '-Dindex.subsystem.name=solr6'
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v1.32.0
|
||||
- uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v1.32.0
|
||||
- uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v1.33.0
|
||||
- uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v1.33.0
|
||||
- name: "Init"
|
||||
run: bash ./scripts/ci/init.sh
|
||||
- name: "Set transformers tag"
|
||||
@@ -337,7 +337,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
needs: [prepare]
|
||||
if: >
|
||||
(((github.ref_name == 'master' || contains(github.ref_name, 'release/') || github.event_name == 'pull_request' ) &&
|
||||
(((github.ref_name == 'master' || startsWith(github.ref_name, 'release/') || github.event_name == 'pull_request' ) &&
|
||||
!contains(github.event.head_commit.message, '[skip tas]')) ||
|
||||
contains(github.event.head_commit.message, '[tas]')) &&
|
||||
!contains(github.event.head_commit.message, '[skip tests]') &&
|
||||
@@ -374,8 +374,8 @@ jobs:
|
||||
REQUIRES_LOCAL_IMAGES: true
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v1.32.0
|
||||
- uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v1.32.0
|
||||
- uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v1.33.0
|
||||
- uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v1.33.0
|
||||
- name: "Build"
|
||||
timeout-minutes: ${{ fromJSON(env.GITHUB_ACTIONS_DEPLOY_TIMEOUT) }}
|
||||
run: |
|
||||
@@ -411,8 +411,8 @@ jobs:
|
||||
!contains(github.event.head_commit.message, '[force]')
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v1.32.0
|
||||
- uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v1.32.0
|
||||
- uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v1.33.0
|
||||
- uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v1.33.0
|
||||
- name: "Init"
|
||||
run: bash ./scripts/ci/init.sh
|
||||
- name: "Run Postgres 14.4 database"
|
||||
@@ -427,7 +427,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
needs: [prepare]
|
||||
if: >
|
||||
(((github.ref_name == 'master' || contains(github.ref_name, 'release/') || github.event_name == 'pull_request' ) &&
|
||||
(((github.ref_name == 'master' || startsWith(github.ref_name, 'release/') || github.event_name == 'pull_request' ) &&
|
||||
!contains(github.event.head_commit.message, '[skip ags]')) ||
|
||||
contains(github.event.head_commit.message, '[ags]')) &&
|
||||
!contains(github.event.head_commit.message, '[skip tests]') &&
|
||||
@@ -440,8 +440,8 @@ jobs:
|
||||
REQUIRES_INSTALLED_ARTIFACTS: true
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v1.32.0
|
||||
- uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v1.32.0
|
||||
- uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v1.33.0
|
||||
- uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v1.33.0
|
||||
- name: "Build"
|
||||
timeout-minutes: ${{ fromJSON(env.GITHUB_ACTIONS_DEPLOY_TIMEOUT) }}
|
||||
run: |
|
||||
@@ -458,7 +458,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
needs: [prepare]
|
||||
if: >
|
||||
(((github.ref_name == 'master' || contains(github.ref_name, 'release/') || github.event_name == 'pull_request' ) &&
|
||||
(((github.ref_name == 'master' || startsWith(github.ref_name, 'release/') || github.event_name == 'pull_request' ) &&
|
||||
!contains(github.event.head_commit.message, '[skip ags]')) ||
|
||||
contains(github.event.head_commit.message, '[ags on MySQL]')) &&
|
||||
!contains(github.event.head_commit.message, '[skip tests]') &&
|
||||
@@ -471,8 +471,8 @@ jobs:
|
||||
REQUIRES_INSTALLED_ARTIFACTS: true
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v1.32.0
|
||||
- uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v1.32.0
|
||||
- uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v1.33.0
|
||||
- uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v1.33.0
|
||||
- name: "Build"
|
||||
timeout-minutes: ${{ fromJSON(env.GITHUB_ACTIONS_DEPLOY_TIMEOUT) }}
|
||||
run: |
|
||||
@@ -489,7 +489,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
needs: [prepare]
|
||||
if: >
|
||||
(((github.ref_name == 'master' || contains(github.ref_name, 'release/') || github.event_name == 'pull_request' ) &&
|
||||
(((github.ref_name == 'master' || startsWith(github.ref_name, 'release/') || github.event_name == 'pull_request' ) &&
|
||||
!contains(github.event.head_commit.message, '[skip ags]') && !contains(github.event.head_commit.message, '[skip tas]')) ||
|
||||
(contains(github.event.head_commit.message, '[ags]') && contains(github.event.head_commit.message, '[tas]'))) &&
|
||||
!contains(github.event.head_commit.message, '[skip tests]') &&
|
||||
@@ -498,8 +498,8 @@ jobs:
|
||||
REQUIRES_LOCAL_IMAGES: true
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v1.32.0
|
||||
- uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v1.32.0
|
||||
- uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v1.33.0
|
||||
- uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v1.33.0
|
||||
- name: "Build"
|
||||
timeout-minutes: ${{ fromJSON(env.GITHUB_ACTIONS_DEPLOY_TIMEOUT) }}
|
||||
run: |
|
||||
|
||||
22
.github/workflows/master_release.yml
vendored
22
.github/workflows/master_release.yml
vendored
@@ -27,16 +27,18 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
needs: [run_ci]
|
||||
if: >
|
||||
!failure() &&
|
||||
!(failure() || cancelled()) &&
|
||||
!contains(github.event.head_commit.message, '[no release]') &&
|
||||
github.event_name != 'pull_request'
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v1.32.0
|
||||
- uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v1.32.0
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v1.33.0
|
||||
- uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v1.33.0
|
||||
- name: "Init"
|
||||
run: bash ./scripts/ci/init.sh
|
||||
- uses: Alfresco/alfresco-build-tools/.github/actions/configure-git-author@v1.32.0
|
||||
- uses: Alfresco/alfresco-build-tools/.github/actions/configure-git-author@v1.33.0
|
||||
with:
|
||||
username: ${{ env.GIT_USERNAME }}
|
||||
email: ${{ env.GIT_EMAIL }}
|
||||
@@ -53,16 +55,18 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
needs: [push_to_nexus]
|
||||
if: >
|
||||
!failure() &&
|
||||
!(failure() || cancelled()) &&
|
||||
!contains(github.event.head_commit.message, '[no downstream]') &&
|
||||
github.event_name != 'pull_request'
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v1.32.0
|
||||
- uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v1.32.0
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v1.33.0
|
||||
- uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v1.33.0
|
||||
- name: "Init"
|
||||
run: bash ./scripts/ci/init.sh
|
||||
- uses: Alfresco/alfresco-build-tools/.github/actions/configure-git-author@v1.32.0
|
||||
- uses: Alfresco/alfresco-build-tools/.github/actions/configure-git-author@v1.33.0
|
||||
with:
|
||||
username: ${{ env.GIT_USERNAME }}
|
||||
email: ${{ env.GIT_EMAIL }}
|
||||
@@ -72,4 +76,4 @@ jobs:
|
||||
env:
|
||||
COMMIT_MESSAGE: ${{ github.event.head_commit.message }}
|
||||
- name: "Clean Maven cache"
|
||||
run: bash ./scripts/ci/cleanup_cache.sh
|
||||
run: bash ./scripts/ci/cleanup_cache.sh
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo-amps</artifactId>
|
||||
<version>20.72</version>
|
||||
<version>20.90-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<modules>
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-governance-services-community-parent</artifactId>
|
||||
<version>20.72</version>
|
||||
<version>20.90-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<modules>
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-governance-services-automation-community-repo</artifactId>
|
||||
<version>20.72</version>
|
||||
<version>20.90-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<build>
|
||||
|
||||
@@ -33,7 +33,9 @@ import org.alfresco.rest.rm.community.model.record.Record;
|
||||
import org.alfresco.rest.v0.RecordsAPI;
|
||||
import org.alfresco.utility.Utility;
|
||||
import org.alfresco.utility.constants.UserRole;
|
||||
import org.alfresco.utility.data.RandomData;
|
||||
import org.alfresco.utility.model.FileModel;
|
||||
import org.alfresco.utility.model.FileType;
|
||||
import org.alfresco.utility.model.SiteModel;
|
||||
import org.alfresco.utility.model.UserModel;
|
||||
import org.json.JSONObject;
|
||||
@@ -97,9 +99,10 @@ public class InplaceRecordSearchTests extends BaseRMRestTest {
|
||||
@Test
|
||||
public void searchForInplaceRecord() {
|
||||
// And a document that isn't a record
|
||||
final String fileName = "File" + RandomData.getRandomAlphanumeric();
|
||||
uploadedDocbyCollabUser = dataContent.usingSite(privateSite)
|
||||
.usingUser(siteCollaborator)
|
||||
.createContent(CMISUtil.DocumentType.TEXT_PLAIN);
|
||||
.createContent(new FileModel(fileName, FileType.fromName(fileName + "." + CMISUtil.DocumentType.TEXT_PLAIN.extention)));
|
||||
|
||||
assertNotNull(uploadedDocbyCollabUser.getNodeRef());
|
||||
|
||||
|
||||
@@ -72,7 +72,7 @@ public class SearchDocumentsV1Test extends BaseRMRestTest
|
||||
cmisQueryModel.setLanguage("cmis");
|
||||
|
||||
RestRequestQueryModel aftsQueryModel = new RestRequestQueryModel();
|
||||
aftsQueryModel.setQuery("cm:name:*" + SEARCH_TERM);
|
||||
aftsQueryModel.setQuery("cm:name:*" + SEARCH_TERM + ".txt");
|
||||
aftsQueryModel.setLanguage("afts");
|
||||
|
||||
return new RestRequestQueryModel[][] {
|
||||
@@ -107,7 +107,7 @@ public class SearchDocumentsV1Test extends BaseRMRestTest
|
||||
private void waitIndexing() throws Exception
|
||||
{
|
||||
RestRequestQueryModel queryType = new RestRequestQueryModel();
|
||||
queryType.setQuery("cm:name:*" + SEARCH_TERM);
|
||||
queryType.setQuery("cm:name:*" + SEARCH_TERM + ".txt");
|
||||
queryType.setLanguage("afts");
|
||||
Utility.sleep(1000, 80000, () ->
|
||||
{
|
||||
|
||||
@@ -66,7 +66,6 @@ import static org.alfresco.rest.rm.community.model.fileplancomponents.FilePlanCo
|
||||
import static org.alfresco.rest.rm.community.model.fileplancomponents.FilePlanComponentAspects.CUT_OFF_ASPECT;
|
||||
import static org.alfresco.rest.rm.community.model.recordcategory.RetentionPeriodProperty.*;
|
||||
import static org.alfresco.rest.rm.community.util.CommonTestUtils.generateTestPrefix;
|
||||
import static org.alfresco.utility.data.RandomData.getRandomName;
|
||||
import static org.alfresco.utility.report.log.Step.STEP;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
@@ -84,26 +83,29 @@ public class DispositionScheduleLinkedRecordsTest extends BaseRMRestTest {
|
||||
@Autowired
|
||||
private RecordFoldersAPI recordFoldersAPI;
|
||||
private final static String TEST_PREFIX = generateTestPrefix(DispositionScheduleLinkedRecordsTest.class);
|
||||
private RecordCategory Category1,catsameLevel1,catsameLevel2;
|
||||
private RecordCategory Category1;
|
||||
private RecordCategoryChild CopyCatFolder,folder1,CatFolder,folder2;
|
||||
private static final String categoryRM3077 = TEST_PREFIX + "RM-3077_manager_sees_me";
|
||||
private static final String copyCategoryRM3077 = "Copy_of_" + categoryRM3077;
|
||||
private static final String folderRM3077 = "RM-3077_folder_"+ categoryRM3077;
|
||||
private static final String copyFolderRM3077 = "Copy_of_" + folderRM3077;
|
||||
private final String electronicRecord = "RM-2937 electronic 2 record";
|
||||
private final String folder = TEST_PREFIX + "RM-2937 folder ghosting";
|
||||
private static final String categoryRecordsRM2526 = TEST_PREFIX + "RM-2526_category_records_immediately";
|
||||
private static final String category2RecordsRM2526 = TEST_PREFIX + "RM-2526_category_2_records_1_day";
|
||||
private static final String firstCategoryRM3060 = TEST_PREFIX + "RM-3060_category_record";
|
||||
private static final String secondCategoryRM3060 = "Copy_of_" + firstCategoryRM3060;
|
||||
private static final String firstFolderRM3060 = TEST_PREFIX + "RM-3060_folder";
|
||||
private static final String secondFolderRM3060 = TEST_PREFIX + "RM-3060_disposition_on_Record_Level";
|
||||
private static final String electronicRecordRM3060 = TEST_PREFIX + "RM-3060_electronic_1_record";
|
||||
private static final String nonElectronicRecordRM3060 = TEST_PREFIX + "RM-3060_non-electronic_record";
|
||||
private static final String firstCategoryRM1622 = TEST_PREFIX + "RM-1622_category_record";
|
||||
private static final String secondCategoryRM1622 = "Copy_of_" + firstCategoryRM1622;;
|
||||
private static final String firstFolderRM1622 = TEST_PREFIX + "RM-1622_folder";
|
||||
private static final String electronicRecordRM1622 = TEST_PREFIX + "RM-1622_electronic_1_record";
|
||||
private static final String secondFolderRM1622 = TEST_PREFIX + "RM-1622_disposition_on_Record_Level";
|
||||
private static final String TRANSFER_LOCATION = TEST_PREFIX + "RM-3060_transferred_records";
|
||||
public static final String TRANSFER_TYPE = "rma:transferred";
|
||||
private FilePlan filePlanModel;
|
||||
private UserModel rmAdmin, rmManager;
|
||||
|
||||
@BeforeClass(alwaysRun = true)
|
||||
public void setupDispositionScheduleLinkedRecordsTest() {
|
||||
createRMSiteIfNotExists();
|
||||
@@ -368,35 +370,35 @@ public class DispositionScheduleLinkedRecordsTest extends BaseRMRestTest {
|
||||
|
||||
// create a category with retention applied on records level
|
||||
RecordCategory catsameLevel1 = getRestAPIFactory().getFilePlansAPI(rmAdmin)
|
||||
.createRootRecordCategory(RecordCategory.builder().name(firstCategoryRM3060).build(),
|
||||
RecordCategory.DEFAULT_FILE_PLAN_ALIAS);
|
||||
.createRootRecordCategory(RecordCategory.builder().name(firstCategoryRM1622).build(),
|
||||
RecordCategory.DEFAULT_FILE_PLAN_ALIAS);
|
||||
RecordCategory catsameLevel2 = getRestAPIFactory().getFilePlansAPI(rmAdmin)
|
||||
.createRootRecordCategory(RecordCategory.builder().name(secondCategoryRM3060).build(),
|
||||
RecordCategory.DEFAULT_FILE_PLAN_ALIAS);
|
||||
.createRootRecordCategory(RecordCategory.builder().name(secondCategoryRM1622).build(),
|
||||
RecordCategory.DEFAULT_FILE_PLAN_ALIAS);
|
||||
|
||||
// create retention schedule applied on records for category 1
|
||||
dispositionScheduleService.createCategoryRetentionSchedule(firstCategoryRM3060, true);
|
||||
dispositionScheduleService.createCategoryRetentionSchedule(firstCategoryRM1622, true);
|
||||
|
||||
// with retain immediately after record creation date and cut 1 day after record creation date
|
||||
dispositionScheduleService.addCutOffAfterPeriodStep(firstCategoryRM3060, "day|1", DATE_FILED);
|
||||
dispositionScheduleService.addCutOffAfterPeriodStep(firstCategoryRM1622, "day|1", DATE_FILED);
|
||||
|
||||
|
||||
// create a folder on the category firstCategoryRM3060 with a complete electronic record
|
||||
RecordCategoryChild firstFolderRecordCategoryChild = createRecordFolder(catsameLevel1.getId(),firstFolderRM3060);
|
||||
Record firstElectronicRecord = createElectronicRecord(firstFolderRecordCategoryChild.getId(),electronicRecordRM3060);
|
||||
// create a folder on the category firstCategoryRM1622 with a complete electronic record
|
||||
RecordCategoryChild firstFolderRecordCategoryChild = createRecordFolder(catsameLevel1.getId(),firstFolderRM1622);
|
||||
Record firstElectronicRecord = createElectronicRecord(firstFolderRecordCategoryChild.getId(),electronicRecordRM1622);
|
||||
|
||||
String elRecordFullName = recordsAPI.getRecordFullName(getDataUser().getAdminUser().getUsername(),
|
||||
getDataUser().getAdminUser().getPassword(),firstFolderRM3060, electronicRecordRM3060);
|
||||
getDataUser().getAdminUser().getPassword(),firstFolderRM1622, electronicRecordRM1622);
|
||||
String elRecordNameNodeRef = recordsAPI.getRecordNodeRef(getDataUser().usingAdmin().getAdminUser().getUsername(),
|
||||
getDataUser().usingAdmin().getAdminUser().getPassword(), elRecordFullName, "/" + firstCategoryRM3060 + "/" + firstFolderRM3060);
|
||||
getDataUser().usingAdmin().getAdminUser().getPassword(), elRecordFullName, "/" + firstCategoryRM1622 + "/" + firstFolderRM1622);
|
||||
|
||||
recordsAPI.completeRecord(getDataUser().getAdminUser().getUsername(),
|
||||
getDataUser().getAdminUser().getPassword(), elRecordFullName);
|
||||
|
||||
// create a folder on the category secondCategoryRM3060 with a non electronic record
|
||||
RecordCategoryChild secondFolderRecordCategoryChild = createRecordFolder(catsameLevel2.getId(),secondFolderRM3060);
|
||||
// create a folder on the category secondCategoryRM1622 with a non electronic record
|
||||
RecordCategoryChild secondFolderRecordCategoryChild = createRecordFolder(catsameLevel2.getId(),secondFolderRM1622);
|
||||
String elRecordNameNodeRefs = recordsAPI.getRecordNodeRef(getDataUser().usingAdmin().getAdminUser().getUsername(),
|
||||
getDataUser().usingAdmin().getAdminUser().getPassword(), elRecordFullName, "/" + firstCategoryRM3060 + "/" + firstFolderRM3060);
|
||||
getDataUser().usingAdmin().getAdminUser().getPassword(), elRecordFullName, "/" + firstCategoryRM1622 + "/" + firstFolderRM1622);
|
||||
|
||||
|
||||
// link it to the folder in second category through the details page
|
||||
@@ -404,8 +406,8 @@ public class DispositionScheduleLinkedRecordsTest extends BaseRMRestTest {
|
||||
recordLists.add(NODE_REF_WORKSPACE_SPACES_STORE + firstElectronicRecord.getId());
|
||||
|
||||
linksAPI.linkRecord(getDataUser().getAdminUser().getUsername(),
|
||||
getDataUser().getAdminUser().getPassword(), HttpStatus.SC_OK,secondCategoryRM3060 + "/" +
|
||||
secondFolderRM3060, recordLists);
|
||||
getDataUser().getAdminUser().getPassword(), HttpStatus.SC_OK,secondCategoryRM1622 + "/" +
|
||||
secondFolderRM1622, recordLists);
|
||||
|
||||
// edit disposition date
|
||||
recordFoldersAPI.postRecordAction(getAdminUser().getUsername(),
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-governance-services-community-parent</artifactId>
|
||||
<version>20.72</version>
|
||||
<version>20.90-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<modules>
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-governance-services-community-repo-parent</artifactId>
|
||||
<version>20.72</version>
|
||||
<version>20.90-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<properties>
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-governance-services-community-repo-parent</artifactId>
|
||||
<version>20.72</version>
|
||||
<version>20.90-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<build>
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo</artifactId>
|
||||
<version>20.72</version>
|
||||
<version>20.90-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<modules>
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo-amps</artifactId>
|
||||
<version>20.72</version>
|
||||
<version>20.90-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<properties>
|
||||
|
||||
@@ -241,7 +241,7 @@ var Filters =
|
||||
filterData = filterData.slice(0, -1);
|
||||
}
|
||||
filterQuery = this.constructPathQuery(parsedArgs);
|
||||
filterParams.query = filterQuery + " +PATH:\"/cm:generalclassifiable" + Filters.iso9075EncodePath(filterData) + "/member\"";
|
||||
filterParams.query = filterQuery + " +PATH:\"/cm:categoryRoot/cm:generalclassifiable" + Filters.iso9075EncodePath(filterData) + "/member\"";
|
||||
break;
|
||||
|
||||
case "aspect":
|
||||
|
||||
@@ -230,7 +230,7 @@ var Filters =
|
||||
filterData = filterData.slice(0, -1);
|
||||
}
|
||||
filterQuery = this.constructPathQuery(parsedArgs);
|
||||
filterParams.query = filterQuery + " +PATH:\"/cm:generalclassifiable" + Filters.iso9075EncodePath(filterData) + "/member\"";
|
||||
filterParams.query = filterQuery + " +PATH:\"/cm:categoryRoot/cm:generalclassifiable" + Filters.iso9075EncodePath(filterData) + "/member\"";
|
||||
break;
|
||||
|
||||
default: // "path"
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo</artifactId>
|
||||
<version>20.72</version>
|
||||
<version>20.90-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo</artifactId>
|
||||
<version>20.72</version>
|
||||
<version>20.90-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<properties>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* #%L
|
||||
* Alfresco Data model classes
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||
* Copyright (C) 2005 - 2023 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
@@ -51,6 +51,18 @@ public class MLText extends HashMap<Locale, String>
|
||||
{
|
||||
private static final long serialVersionUID = -3696135175650511841L;
|
||||
|
||||
/**
|
||||
* Returns default locale used by the {@link MLText} implementation
|
||||
*
|
||||
* @see I18NUtil#getLocale()
|
||||
*
|
||||
* @return default locale
|
||||
*/
|
||||
public static Locale getDefaultLocale()
|
||||
{
|
||||
return I18NUtil.getLocale();
|
||||
}
|
||||
|
||||
public MLText()
|
||||
{
|
||||
super(3, 0.75F);
|
||||
@@ -61,13 +73,13 @@ public class MLText extends HashMap<Locale, String>
|
||||
*
|
||||
* @param value the value for the current default locale
|
||||
*
|
||||
* @see I18NUtil#getLocale()
|
||||
* @see #getDefaultLocale()
|
||||
* @see #MLText(Locale, String)
|
||||
* @see #getDefaultValue()
|
||||
*/
|
||||
public MLText(String value)
|
||||
{
|
||||
this(I18NUtil.getLocale(), value);
|
||||
this(getDefaultLocale(), value);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -124,7 +136,7 @@ public class MLText extends HashMap<Locale, String>
|
||||
/**
|
||||
* Retrieves a default value from the set of available locales.<br/>
|
||||
*
|
||||
* @see I18NUtil#getLocale()
|
||||
* @see #getDefaultLocale()
|
||||
* @see #getClosestValue(Locale)
|
||||
*/
|
||||
public String getDefaultValue()
|
||||
@@ -135,7 +147,7 @@ public class MLText extends HashMap<Locale, String>
|
||||
return null;
|
||||
}
|
||||
// There is some hope of getting a match
|
||||
Locale locale = I18NUtil.getLocale();
|
||||
Locale locale = getDefaultLocale();
|
||||
return getClosestValue(locale);
|
||||
}
|
||||
|
||||
@@ -168,7 +180,7 @@ public class MLText extends HashMap<Locale, String>
|
||||
if (match == null)
|
||||
{
|
||||
// No close matches for the locale - go for the default locale
|
||||
locale = I18NUtil.getLocale();
|
||||
locale = getDefaultLocale();
|
||||
match = I18NUtil.getNearestLocale(locale, options);
|
||||
if (match == null)
|
||||
{
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo</artifactId>
|
||||
<version>20.72</version>
|
||||
<version>20.90-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
|
||||
@@ -9,6 +9,6 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo-packaging</artifactId>
|
||||
<version>20.72</version>
|
||||
<version>20.90-SNAPSHOT</version>
|
||||
</parent>
|
||||
</project>
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo-packaging</artifactId>
|
||||
<version>20.72</version>
|
||||
<version>20.90-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<properties>
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo</artifactId>
|
||||
<version>20.72</version>
|
||||
<version>20.90-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<modules>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo-packaging</artifactId>
|
||||
<version>20.72</version>
|
||||
<version>20.90-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<modules>
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo-tests</artifactId>
|
||||
<version>20.72</version>
|
||||
<version>20.90-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<organization>
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo-tests</artifactId>
|
||||
<version>20.72</version>
|
||||
<version>20.90-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<developers>
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo-tests</artifactId>
|
||||
<version>20.72</version>
|
||||
<version>20.90-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<developers>
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo-tests</artifactId>
|
||||
<version>20.72</version>
|
||||
<version>20.90-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<properties>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* #%L
|
||||
* alfresco-tas-restapi
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2022 Alfresco Software Limited
|
||||
* Copyright (C) 2005 - 2023 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
@@ -27,6 +27,8 @@ package org.alfresco.rest.model;
|
||||
|
||||
import static org.alfresco.utility.report.log.Step.STEP;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
import org.alfresco.rest.core.IRestModel;
|
||||
@@ -73,4 +75,65 @@ public class RestTagModel extends TagModel implements IRestModel<RestTagModel>
|
||||
this.count = count;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o)
|
||||
{
|
||||
if (this == o)
|
||||
return true;
|
||||
if (o == null || getClass() != o.getClass())
|
||||
return false;
|
||||
RestTagModel tagModel = (RestTagModel) o;
|
||||
return Objects.equals(id, tagModel.id) && Objects.equals(tag, tagModel.tag) && Objects.equals(count, tagModel.count);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
return Objects.hash(id, tag, count);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return "RestTagModel{" + "id='" + id + ", tag='" + tag + '\'' + ", count=" + count + '\'' + '}';
|
||||
}
|
||||
|
||||
public static Builder builder()
|
||||
{
|
||||
return new Builder();
|
||||
}
|
||||
|
||||
public static class Builder
|
||||
{
|
||||
private String id;
|
||||
private String tag;
|
||||
private Integer count;
|
||||
|
||||
public Builder id(String id)
|
||||
{
|
||||
this.id = id;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder tag(String tag)
|
||||
{
|
||||
this.tag = tag;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder count(Integer count)
|
||||
{
|
||||
this.count = count;
|
||||
return this;
|
||||
}
|
||||
|
||||
public RestTagModel create()
|
||||
{
|
||||
final RestTagModel tag = new RestTagModel();
|
||||
tag.setId(id);
|
||||
tag.setTag(this.tag);
|
||||
tag.setCount(count);
|
||||
return tag;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,4 +82,15 @@ public class Tags extends ModelRequest<Tags>
|
||||
|
||||
return restWrapper.processModel(RestTagModel.class, request);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete tag.
|
||||
* - DELETE /tags/{tagId}
|
||||
*/
|
||||
public void deleteTag()
|
||||
{
|
||||
RestRequest request = RestRequest.
|
||||
simpleRequest(HttpMethod.DELETE, "/tags/{tagId}", tag.getId());
|
||||
restWrapper.processEmptyModel(request);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* #%L
|
||||
* alfresco-tas-restapi
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2022 Alfresco Software Limited
|
||||
* Copyright (C) 2005 - 2023 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
@@ -25,6 +25,12 @@
|
||||
*/
|
||||
package org.alfresco.rest.requests.coreAPI;
|
||||
|
||||
import static org.alfresco.rest.core.JsonBodyGenerator.arrayToJson;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import io.restassured.RestAssured;
|
||||
import org.alfresco.rest.core.RestRequest;
|
||||
import org.alfresco.rest.core.RestWrapper;
|
||||
import org.alfresco.rest.model.RestCategoryModel;
|
||||
import org.alfresco.rest.model.RestDownloadsModel;
|
||||
@@ -49,8 +55,7 @@ import org.alfresco.rest.requests.Trashcan;
|
||||
import org.alfresco.utility.model.RepoTestModel;
|
||||
import org.alfresco.utility.model.SiteModel;
|
||||
import org.alfresco.utility.model.UserModel;
|
||||
|
||||
import io.restassured.RestAssured;
|
||||
import org.springframework.http.HttpMethod;
|
||||
|
||||
/**
|
||||
* Defines the entire Rest Core API
|
||||
@@ -172,6 +177,30 @@ public class RestCoreAPI extends ModelRequest<RestCoreAPI>
|
||||
return new Networks(restWrapper);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a single orphan tag.
|
||||
*
|
||||
* @param tag Tag model to create.
|
||||
* @return Created tag.
|
||||
*/
|
||||
public RestTagModel createSingleTag(RestTagModel tag)
|
||||
{
|
||||
RestRequest request = RestRequest.requestWithBody(HttpMethod.POST, tag.toJson(), "tags/");
|
||||
return restWrapper.processModel(RestTagModel.class, request);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create several orphan tags in one request.
|
||||
*
|
||||
* @param tags Tags models to create.
|
||||
* @return Created tags.
|
||||
*/
|
||||
public RestTagModelsCollection createTags(List<RestTagModel> tags)
|
||||
{
|
||||
RestRequest request = RestRequest.requestWithBody(HttpMethod.POST, arrayToJson(tags), "tags/");
|
||||
return restWrapper.processModels(RestTagModelsCollection.class, request);
|
||||
}
|
||||
|
||||
public Tags usingTag(RestTagModel tag)
|
||||
{
|
||||
return new Tags(tag, restWrapper);
|
||||
|
||||
@@ -0,0 +1,207 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Remote API
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2023 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
package org.alfresco.rest.categories;
|
||||
|
||||
import static org.alfresco.utility.data.RandomData.getRandomName;
|
||||
import static org.alfresco.utility.report.log.Step.STEP;
|
||||
import static org.springframework.http.HttpStatus.CREATED;
|
||||
import static org.springframework.http.HttpStatus.OK;
|
||||
import static org.testng.Assert.assertTrue;
|
||||
|
||||
import org.alfresco.dataprep.CMISUtil;
|
||||
import org.alfresco.rest.model.RestCategoryModel;
|
||||
import org.alfresco.rest.model.RestCategoryModelsCollection;
|
||||
import org.alfresco.utility.Utility;
|
||||
import org.alfresco.utility.model.FileModel;
|
||||
import org.alfresco.utility.model.FolderModel;
|
||||
import org.alfresco.utility.model.SiteModel;
|
||||
import org.alfresco.utility.model.TestGroup;
|
||||
import org.testng.annotations.BeforeClass;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
public class CategoriesCountTests extends CategoriesRestTest
|
||||
{
|
||||
|
||||
private RestCategoryModel categoryLinkedWithFolder;
|
||||
private RestCategoryModel categoryLinkedWithFile;
|
||||
private RestCategoryModel categoryLinkedWithBoth;
|
||||
private RestCategoryModel notLinkedCategory;
|
||||
|
||||
@BeforeClass(alwaysRun = true)
|
||||
public void dataPreparation() throws Exception
|
||||
{
|
||||
STEP("Create user and site");
|
||||
user = dataUser.createRandomTestUser();
|
||||
SiteModel site = dataSite.usingUser(user).createPublicRandomSite();
|
||||
|
||||
STEP("Create a folder, file in it and few categories");
|
||||
FolderModel folder = dataContent.usingUser(user).usingSite(site).createFolder();
|
||||
FileModel file = dataContent.usingUser(user).usingResource(folder).createContent(CMISUtil.DocumentType.TEXT_PLAIN);
|
||||
categoryLinkedWithFolder = prepareCategoryUnderRoot();
|
||||
categoryLinkedWithFile = prepareCategoryUnderRoot();
|
||||
categoryLinkedWithBoth = prepareCategoryUnder(prepareCategoryUnderRoot());
|
||||
notLinkedCategory = prepareCategoryUnderRoot();
|
||||
|
||||
STEP("Link folder and file to categories");
|
||||
linkContentToCategories(folder, categoryLinkedWithFolder, categoryLinkedWithBoth);
|
||||
linkContentToCategories(file, categoryLinkedWithFile, categoryLinkedWithBoth);
|
||||
|
||||
STEP("Wait for indexing to complete");
|
||||
Utility.sleep(1000, 60000, () -> restClient.authenticateUser(user)
|
||||
.withCoreAPI()
|
||||
.usingCategory(categoryLinkedWithFolder)
|
||||
.include(INCLUDE_COUNT_PARAM)
|
||||
.getCategory()
|
||||
.assertThat()
|
||||
.field(FIELD_COUNT)
|
||||
.isNot(0));
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify count for a category linked with file and folder.
|
||||
*/
|
||||
@Test(groups = { TestGroup.REST_API })
|
||||
public void testGetCategoryById_includeCount()
|
||||
{
|
||||
STEP("Get linked category and verify if count is higher than 0");
|
||||
final RestCategoryModel actualCategory = restClient.authenticateUser(user)
|
||||
.withCoreAPI()
|
||||
.usingCategory(categoryLinkedWithBoth)
|
||||
.include(INCLUDE_COUNT_PARAM)
|
||||
.getCategory();
|
||||
|
||||
restClient.assertStatusCodeIs(OK);
|
||||
actualCategory.assertThat().field(FIELD_ID).is(categoryLinkedWithBoth.getId());
|
||||
actualCategory.assertThat().field(FIELD_COUNT).is(2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify count for a category not linked with any content.
|
||||
*/
|
||||
@Test(groups = { TestGroup.REST_API })
|
||||
public void testGetCategoryById_includeCountForNonLinkedCategory()
|
||||
{
|
||||
STEP("Get non-linked category and verify if count is 0");
|
||||
final RestCategoryModel actualCategory = restClient.authenticateUser(user)
|
||||
.withCoreAPI()
|
||||
.usingCategory(notLinkedCategory)
|
||||
.include(INCLUDE_COUNT_PARAM)
|
||||
.getCategory();
|
||||
|
||||
restClient.assertStatusCodeIs(OK);
|
||||
actualCategory.assertThat().field(FIELD_ID).is(notLinkedCategory.getId());
|
||||
actualCategory.assertThat().field(FIELD_COUNT).is(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify count for three categories: linked with file, linked with folder and third not linked to any content.
|
||||
*/
|
||||
@Test(groups = { TestGroup.REST_API })
|
||||
public void testGetCategories_includeCount()
|
||||
{
|
||||
STEP("Get few categories and verify its counts");
|
||||
final RestCategoryModel parentCategory = createCategoryModelWithId(ROOT_CATEGORY_ID);
|
||||
final RestCategoryModelsCollection actualCategories = restClient.authenticateUser(user)
|
||||
.withCoreAPI()
|
||||
.usingCategory(parentCategory)
|
||||
.include(INCLUDE_COUNT_PARAM)
|
||||
.getCategoryChildren();
|
||||
|
||||
restClient.assertStatusCodeIs(OK);
|
||||
assertTrue(actualCategories.getEntries().stream()
|
||||
.map(RestCategoryModel::onModel)
|
||||
.anyMatch(category -> category.getId().equals(categoryLinkedWithFolder.getId()) && category.getCount() == 1));
|
||||
assertTrue(actualCategories.getEntries().stream()
|
||||
.map(RestCategoryModel::onModel)
|
||||
.anyMatch(category -> category.getId().equals(categoryLinkedWithFile.getId()) && category.getCount() == 1));
|
||||
assertTrue(actualCategories.getEntries().stream()
|
||||
.map(RestCategoryModel::onModel)
|
||||
.anyMatch(category -> category.getId().equals(notLinkedCategory.getId()) && category.getCount() == 0));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create category and verify that its count is 0.
|
||||
*/
|
||||
@Test(groups = { TestGroup.REST_API })
|
||||
public void testCreateCategory_includingCount()
|
||||
{
|
||||
STEP("Create a category under root and verify if count is 0");
|
||||
final String categoryName = getRandomName("Category");
|
||||
final RestCategoryModel rootCategory = createCategoryModelWithId(ROOT_CATEGORY_ID);
|
||||
final RestCategoryModel aCategory = createCategoryModelWithName(categoryName);
|
||||
final RestCategoryModel createdCategory = restClient.authenticateUser(dataUser.getAdminUser())
|
||||
.withCoreAPI()
|
||||
.include(INCLUDE_COUNT_PARAM)
|
||||
.usingCategory(rootCategory)
|
||||
.createSingleCategory(aCategory);
|
||||
|
||||
STEP("Create a category under root category (as admin)");
|
||||
restClient.assertStatusCodeIs(CREATED);
|
||||
createdCategory.assertThat().field(FIELD_NAME).is(categoryName);
|
||||
createdCategory.assertThat().field(FIELD_COUNT).is(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update category linked to file and folder and verify that its count is 2.
|
||||
*/
|
||||
@Test(groups = { TestGroup.REST_API })
|
||||
public void testUpdateCategory_includeCount()
|
||||
{
|
||||
STEP("Update linked category and verify if count is higher than 0");
|
||||
final String categoryNewName = getRandomName("NewCategoryName");
|
||||
final RestCategoryModel fixedCategoryModel = createCategoryModelWithName(categoryNewName);
|
||||
final RestCategoryModel updatedCategory = restClient.authenticateUser(dataUser.getAdminUser())
|
||||
.withCoreAPI()
|
||||
.usingCategory(categoryLinkedWithBoth)
|
||||
.include(INCLUDE_COUNT_PARAM)
|
||||
.updateCategory(fixedCategoryModel);
|
||||
|
||||
restClient.assertStatusCodeIs(OK);
|
||||
updatedCategory.assertThat().field(FIELD_ID).is(categoryLinkedWithBoth.getId());
|
||||
updatedCategory.assertThat().field(FIELD_COUNT).is(2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update category not linked to any content and verify that its count is 0.
|
||||
*/
|
||||
@Test(groups = { TestGroup.REST_API })
|
||||
public void testUpdateCategory_includeCountForNonLinkedCategory()
|
||||
{
|
||||
STEP("Update non-linked category and verify if count is 0");
|
||||
final String categoryNewName = getRandomName("NewCategoryName");
|
||||
final RestCategoryModel fixedCategoryModel = createCategoryModelWithName(categoryNewName);
|
||||
final RestCategoryModel updatedCategory = restClient.authenticateUser(dataUser.getAdminUser())
|
||||
.withCoreAPI()
|
||||
.usingCategory(notLinkedCategory)
|
||||
.include(INCLUDE_COUNT_PARAM)
|
||||
.updateCategory(fixedCategoryModel);
|
||||
|
||||
restClient.assertStatusCodeIs(OK);
|
||||
updatedCategory.assertThat().field(FIELD_ID).is(notLinkedCategory.getId());
|
||||
updatedCategory.assertThat().field(FIELD_COUNT).is(0);
|
||||
}
|
||||
}
|
||||
@@ -30,6 +30,7 @@ import static org.alfresco.utility.data.RandomData.getRandomName;
|
||||
import static org.alfresco.utility.report.log.Step.STEP;
|
||||
import static org.springframework.http.HttpStatus.CREATED;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.IntStream;
|
||||
@@ -37,18 +38,21 @@ import java.util.stream.IntStream;
|
||||
import org.alfresco.rest.RestTest;
|
||||
import org.alfresco.rest.model.RestCategoryLinkBodyModel;
|
||||
import org.alfresco.rest.model.RestCategoryModel;
|
||||
import org.alfresco.rest.model.RestCategoryModelsCollection;
|
||||
import org.alfresco.utility.model.RepoTestModel;
|
||||
import org.alfresco.utility.model.UserModel;
|
||||
import org.testng.annotations.BeforeClass;
|
||||
|
||||
abstract class CategoriesRestTest extends RestTest
|
||||
{
|
||||
protected static final String INCLUDE_COUNT_PARAM = "count";
|
||||
protected static final String ROOT_CATEGORY_ID = "-root-";
|
||||
protected static final String CATEGORY_NAME_PREFIX = "CategoryName";
|
||||
protected static final String FIELD_NAME = "name";
|
||||
protected static final String FIELD_ID = "id";
|
||||
protected static final String FIELD_PARENT_ID = "parentId";
|
||||
protected static final String FIELD_HAS_CHILDREN = "hasChildren";
|
||||
protected static final String FIELD_COUNT = "count";
|
||||
|
||||
protected UserModel user;
|
||||
|
||||
@@ -59,14 +63,26 @@ abstract class CategoriesRestTest extends RestTest
|
||||
user = dataUser.createRandomTestUser();
|
||||
}
|
||||
|
||||
protected RestCategoryModel prepareCategoryUnderRoot()
|
||||
protected RestCategoryModelsCollection linkContentToCategories(final RepoTestModel node, final RestCategoryModel... categories)
|
||||
{
|
||||
return prepareCategoryUnder(ROOT_CATEGORY_ID);
|
||||
final List<RestCategoryLinkBodyModel> categoryLinkModels = Arrays.stream(categories)
|
||||
.map(RestCategoryModel::getId)
|
||||
.map(this::createCategoryLinkModelWithId)
|
||||
.collect(Collectors.toList());
|
||||
final RestCategoryModelsCollection linkedCategories = restClient.authenticateUser(user).withCoreAPI().usingNode(node).linkToCategories(categoryLinkModels);
|
||||
|
||||
restClient.assertStatusCodeIs(CREATED);
|
||||
|
||||
return linkedCategories;
|
||||
}
|
||||
|
||||
protected RestCategoryModel prepareCategoryUnder(final String parentId)
|
||||
protected RestCategoryModel prepareCategoryUnderRoot()
|
||||
{
|
||||
return prepareCategoryUnder(createCategoryModelWithId(ROOT_CATEGORY_ID));
|
||||
}
|
||||
|
||||
protected RestCategoryModel prepareCategoryUnder(final RestCategoryModel parentCategory)
|
||||
{
|
||||
final RestCategoryModel parentCategory = createCategoryModelWithId(parentId);
|
||||
final RestCategoryModel categoryModel = createCategoryModelWithName(getRandomName(CATEGORY_NAME_PREFIX));
|
||||
final RestCategoryModel createdCategory = restClient.authenticateUser(dataUser.getAdminUser())
|
||||
.withCoreAPI()
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* #%L
|
||||
* Alfresco Remote API
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2022 Alfresco Software Limited
|
||||
* Copyright (C) 2005 - 2023 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
@@ -26,6 +26,7 @@
|
||||
|
||||
package org.alfresco.rest.categories;
|
||||
|
||||
import static org.alfresco.utility.data.RandomData.getRandomName;
|
||||
import static org.alfresco.utility.report.log.Step.STEP;
|
||||
import static org.springframework.http.HttpStatus.BAD_REQUEST;
|
||||
import static org.springframework.http.HttpStatus.CREATED;
|
||||
@@ -38,7 +39,6 @@ import java.util.stream.IntStream;
|
||||
|
||||
import org.alfresco.rest.model.RestCategoryModel;
|
||||
import org.alfresco.rest.model.RestCategoryModelsCollection;
|
||||
import org.alfresco.utility.data.RandomData;
|
||||
import org.alfresco.utility.model.FolderModel;
|
||||
import org.alfresco.utility.model.SiteModel;
|
||||
import org.alfresco.utility.model.TestGroup;
|
||||
@@ -56,7 +56,7 @@ public class CreateCategoriesTests extends CategoriesRestTest
|
||||
{
|
||||
STEP("Create a category under root category (as admin)");
|
||||
final RestCategoryModel rootCategory = createCategoryModelWithId(ROOT_CATEGORY_ID);
|
||||
final RestCategoryModel aCategory = createCategoryModelWithName(RandomData.getRandomName("Category"));
|
||||
final RestCategoryModel aCategory = createCategoryModelWithName(getRandomName("Category"));
|
||||
final RestCategoryModel createdCategory = restClient.authenticateUser(dataUser.getAdminUser())
|
||||
.withCoreAPI()
|
||||
.usingCategory(rootCategory)
|
||||
@@ -92,7 +92,7 @@ public class CreateCategoriesTests extends CategoriesRestTest
|
||||
{
|
||||
STEP("Create a category under root category (as admin)");
|
||||
final RestCategoryModel rootCategory = createCategoryModelWithId(ROOT_CATEGORY_ID);
|
||||
final RestCategoryModel aCategory = createCategoryModelWithName(RandomData.getRandomName("Category"));
|
||||
final RestCategoryModel aCategory = createCategoryModelWithName(getRandomName("Category"));
|
||||
final RestCategoryModel createdCategory = restClient.authenticateUser(dataUser.getAdminUser())
|
||||
.withCoreAPI()
|
||||
.usingCategory(rootCategory)
|
||||
@@ -140,7 +140,7 @@ public class CreateCategoriesTests extends CategoriesRestTest
|
||||
{
|
||||
STEP("Create a category under root category (as admin)");
|
||||
final RestCategoryModel rootCategory = createCategoryModelWithId(ROOT_CATEGORY_ID);
|
||||
final RestCategoryModel aCategory = createCategoryModelWithName(RandomData.getRandomName("Category"));
|
||||
final RestCategoryModel aCategory = createCategoryModelWithName(getRandomName("Category"));
|
||||
final RestCategoryModel createdCategory = restClient.authenticateUser(dataUser.getAdminUser())
|
||||
.withCoreAPI()
|
||||
.usingCategory(rootCategory)
|
||||
@@ -186,7 +186,7 @@ public class CreateCategoriesTests extends CategoriesRestTest
|
||||
{
|
||||
STEP("Create a category under root category (as user)");
|
||||
final RestCategoryModel rootCategory = createCategoryModelWithId(ROOT_CATEGORY_ID);
|
||||
final RestCategoryModel aCategory = createCategoryModelWithName(RandomData.getRandomName("Category"));
|
||||
final RestCategoryModel aCategory = createCategoryModelWithName(getRandomName("Category"));
|
||||
restClient.authenticateUser(user)
|
||||
.withCoreAPI()
|
||||
.usingCategory(rootCategory)
|
||||
@@ -203,7 +203,7 @@ public class CreateCategoriesTests extends CategoriesRestTest
|
||||
STEP("Create a category under non existing category node (as admin)");
|
||||
final String id = "non-existing-node-id";
|
||||
final RestCategoryModel rootCategory = createCategoryModelWithId(id);
|
||||
final RestCategoryModel aCategory = createCategoryModelWithName(RandomData.getRandomName("Category"));
|
||||
final RestCategoryModel aCategory = createCategoryModelWithName(getRandomName("Category"));
|
||||
restClient.authenticateUser(dataUser.getAdminUser())
|
||||
.withCoreAPI()
|
||||
.usingCategory(rootCategory)
|
||||
@@ -223,7 +223,7 @@ public class CreateCategoriesTests extends CategoriesRestTest
|
||||
|
||||
STEP("Create a category under folder node (as admin)");
|
||||
final RestCategoryModel rootCategory = createCategoryModelWithId(folder.getNodeRef());
|
||||
final RestCategoryModel aCategory = createCategoryModelWithName(RandomData.getRandomName("Category"));
|
||||
final RestCategoryModel aCategory = createCategoryModelWithName(getRandomName("Category"));
|
||||
restClient.authenticateUser(dataUser.getAdminUser())
|
||||
.withCoreAPI()
|
||||
.usingCategory(rootCategory)
|
||||
@@ -231,10 +231,31 @@ public class CreateCategoriesTests extends CategoriesRestTest
|
||||
restClient.assertStatusCodeIs(BAD_REQUEST).assertLastError().containsSummary("Node id does not refer to a valid category");
|
||||
}
|
||||
|
||||
/**
|
||||
* Check weather count present in create category request will be ignored.
|
||||
*/
|
||||
@Test(groups = { TestGroup.REST_API })
|
||||
public void testCreateCategoryUnderRoot_verifyIfCountInRequestIsIgnored()
|
||||
{
|
||||
STEP("Try to create a category with filled count under root");
|
||||
final RestCategoryModel rootCategory = createCategoryModelWithId(ROOT_CATEGORY_ID);
|
||||
final RestCategoryModel aCategory = createCategoryModelWithName(getRandomName("Category"));
|
||||
aCategory.setCount(2);
|
||||
final RestCategoryModel createdCategory = restClient.authenticateUser(dataUser.getAdminUser())
|
||||
.withCoreAPI()
|
||||
.usingCategory(rootCategory)
|
||||
.include(INCLUDE_COUNT_PARAM)
|
||||
.createSingleCategory(aCategory);
|
||||
|
||||
restClient.assertStatusCodeIs(CREATED);
|
||||
createdCategory.assertThat().field(FIELD_NAME).is(aCategory.getName());
|
||||
createdCategory.assertThat().field(FIELD_COUNT).is(0);
|
||||
}
|
||||
|
||||
static List<RestCategoryModel> getCategoriesToCreate(final int count)
|
||||
{
|
||||
return IntStream.range(0, count)
|
||||
.mapToObj(i -> RestCategoryModel.builder().name(RandomData.getRandomName("SubCategory")).create())
|
||||
.mapToObj(i -> RestCategoryModel.builder().name(getRandomName("SubCategory")).create())
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,7 +79,7 @@ public class UpdateCategoriesTests extends CategoriesRestTest
|
||||
final RestCategoryModel createdCategory = prepareCategoryUnderRoot();
|
||||
|
||||
STEP("Prepare as admin a subcategory of root's child category");
|
||||
final RestCategoryModel createdSubcategory = prepareCategoryUnder(createdCategory.getId());
|
||||
final RestCategoryModel createdSubcategory = prepareCategoryUnder(createdCategory);
|
||||
|
||||
STEP("Update as admin newly created subcategory");
|
||||
final String categoryNewName = getRandomName(CATEGORY_NEW_NAME_PREFIX);
|
||||
@@ -233,4 +233,27 @@ public class UpdateCategoriesTests extends CategoriesRestTest
|
||||
restClient.assertStatusCodeIs(OK);
|
||||
updatedCategory.assertThat().field(FIELD_NAME).is(categoryNewName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether count present in update category request will be ignored.
|
||||
*/
|
||||
@Test(groups = { TestGroup.REST_API })
|
||||
public void testUpdateCategory_verifyIfCountInRequestIsIgnored()
|
||||
{
|
||||
STEP("Prepare a category under root category");
|
||||
final RestCategoryModel createdCategory = prepareCategoryUnderRoot();
|
||||
|
||||
STEP("Try to update newly created category providing new name and count number");
|
||||
final RestCategoryModel fixedCategoryModel = createCategoryModelWithName(getRandomName(CATEGORY_NEW_NAME_PREFIX));
|
||||
fixedCategoryModel.setCount(2);
|
||||
final RestCategoryModel updatedCategory = restClient.authenticateUser(dataUser.getAdminUser())
|
||||
.withCoreAPI()
|
||||
.usingCategory(createdCategory)
|
||||
.include(INCLUDE_COUNT_PARAM)
|
||||
.updateCategory(fixedCategoryModel);
|
||||
|
||||
restClient.assertStatusCodeIs(OK);
|
||||
updatedCategory.assertThat().field(FIELD_ID).is(createdCategory.getId());
|
||||
updatedCategory.assertThat().field(FIELD_COUNT).is(0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,226 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Remote API
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2023 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.rest.tags;
|
||||
|
||||
import static org.alfresco.utility.data.RandomData.getRandomName;
|
||||
import static org.alfresco.utility.report.log.Step.STEP;
|
||||
import static org.springframework.http.HttpStatus.BAD_REQUEST;
|
||||
import static org.springframework.http.HttpStatus.CONFLICT;
|
||||
import static org.springframework.http.HttpStatus.CREATED;
|
||||
import static org.springframework.http.HttpStatus.FORBIDDEN;
|
||||
import static org.springframework.http.HttpStatus.OK;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
import org.alfresco.rest.RestTest;
|
||||
import org.alfresco.rest.model.RestTagModel;
|
||||
import org.alfresco.rest.model.RestTagModelsCollection;
|
||||
import org.alfresco.utility.model.TestGroup;
|
||||
import org.alfresco.utility.model.UserModel;
|
||||
import org.testng.annotations.BeforeClass;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
public class CreateTagsTests extends RestTest
|
||||
{
|
||||
private static final String FIELD_ID = "id";
|
||||
private static final String FIELD_TAG = "tag";
|
||||
private static final String FIELD_COUNT = "count";
|
||||
private static final String TAG_NAME_PREFIX = "tag-name";
|
||||
|
||||
private UserModel admin;
|
||||
private UserModel user;
|
||||
|
||||
@BeforeClass
|
||||
public void init()
|
||||
{
|
||||
admin = dataUser.getAdminUser();
|
||||
user = dataUser.createRandomTestUser();
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify if tag does not exist in the system, create one as admin and check if now it's there.
|
||||
*/
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.TAGS })
|
||||
public void testCreateSingleTag()
|
||||
{
|
||||
STEP("Create single tag as admin");
|
||||
final RestTagModel tagModel = createTagModelWithName(getRandomName("99gat").toLowerCase());
|
||||
final RestTagModel createdTag = restClient.authenticateUser(admin).withCoreAPI().createSingleTag(tagModel);
|
||||
|
||||
restClient.assertStatusCodeIs(CREATED);
|
||||
createdTag.assertThat().field(FIELD_TAG).is(tagModel.getTag())
|
||||
.assertThat().field(FIELD_ID).isNotEmpty();
|
||||
|
||||
STEP("Verify that tag does exist in the system");
|
||||
RestTagModel tag = restClient.authenticateUser(admin).withCoreAPI().getTag(createdTag);
|
||||
restClient.assertStatusCodeIs(OK);
|
||||
tag.assertThat().isEqualTo(createdTag);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create multiple orphan tags.
|
||||
*/
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.TAGS })
|
||||
public void testCreateMultipleTags()
|
||||
{
|
||||
STEP("Create several tags as admin");
|
||||
final List<RestTagModel> tagModels = IntStream.range(0, 3)
|
||||
.mapToObj(i -> createTagModelWithName(getRandomName(TAG_NAME_PREFIX + "-" + i).toLowerCase()))
|
||||
.collect(Collectors.toList());
|
||||
final RestTagModelsCollection createdTags = restClient.authenticateUser(admin).withCoreAPI().createTags(tagModels);
|
||||
|
||||
restClient.assertStatusCodeIs(CREATED);
|
||||
IntStream.range(0, tagModels.size())
|
||||
.forEach(i -> createdTags.getEntries().get(i).onModel()
|
||||
.assertThat().field(FIELD_TAG).is(tagModels.get(i).getTag())
|
||||
.assertThat().field(FIELD_ID).isNotEmpty()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify that tag name's case will be lowered.
|
||||
*/
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.TAGS })
|
||||
public void testCreateSingleTag_usingUppercaseName()
|
||||
{
|
||||
STEP("Create single tag as admin using uppercase name");
|
||||
final RestTagModel tagModel = createTagModelWithName(getRandomName(TAG_NAME_PREFIX).toUpperCase());
|
||||
final RestTagModel createdTag = restClient.authenticateUser(admin).withCoreAPI().createSingleTag(tagModel);
|
||||
|
||||
restClient.assertStatusCodeIs(CREATED);
|
||||
createdTag.assertThat().field(FIELD_TAG).is(tagModel.getTag().toLowerCase())
|
||||
.assertThat().field(FIELD_ID).isNotEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to create few tags including repeating ones. Repeated tags should be omitted.
|
||||
*/
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.TAGS })
|
||||
public void testCreateMultipleTags_withRepeatedName()
|
||||
{
|
||||
STEP("Create models of tags");
|
||||
final String repeatedTagName = getRandomName(TAG_NAME_PREFIX).toLowerCase();
|
||||
final List<RestTagModel> tagModels = List.of(
|
||||
createTagModelWithName(repeatedTagName),
|
||||
createTagModelWithName(getRandomName(TAG_NAME_PREFIX).toLowerCase()),
|
||||
createTagModelWithName(repeatedTagName)
|
||||
);
|
||||
|
||||
STEP("Create several tags skipping repeating names");
|
||||
final RestTagModelsCollection createdTags = restClient.authenticateUser(admin).withCoreAPI().createTags(tagModels);
|
||||
|
||||
restClient.assertStatusCodeIs(CREATED);
|
||||
createdTags.assertThat().entriesListCountIs(2);
|
||||
createdTags.assertThat().entriesListContains(FIELD_TAG, tagModels.get(0).getTag())
|
||||
.and().entriesListContains(FIELD_TAG, tagModels.get(1).getTag());
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to create a tag as a common user and expect 403 (Forbidden)
|
||||
*/
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.TAGS })
|
||||
public void testCreateTag_asUser()
|
||||
{
|
||||
STEP("Try to create single tag as a common user and expect 403");
|
||||
final RestTagModel tagModel = createTagModelWithRandomName();
|
||||
restClient.authenticateUser(user).withCoreAPI().createSingleTag(tagModel);
|
||||
|
||||
restClient.assertStatusCodeIs(FORBIDDEN);
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to call create tag API passing empty list and expect 400 (Bad Request)
|
||||
*/
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.TAGS })
|
||||
public void testCreateTags_passingEmptyList()
|
||||
{
|
||||
STEP("Pass empty list while creating tags and expect 400");
|
||||
restClient.authenticateUser(admin).withCoreAPI().createTags(Collections.emptyList());
|
||||
|
||||
restClient.assertStatusCodeIs(BAD_REQUEST);
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to create a tag, which already exists in the system and expect 409 (Conflict)
|
||||
*/
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.TAGS })
|
||||
public void testCreateTag_usingAlreadyExistingTagName()
|
||||
{
|
||||
STEP("Create some tag in the system");
|
||||
final RestTagModel tagToCreate = createTagModelWithRandomName();
|
||||
final RestTagModel alreadyExistingTag = prepareOrphanTag(tagToCreate);
|
||||
// set original name instead the case lowered one
|
||||
alreadyExistingTag.setTag(tagToCreate.getTag());
|
||||
|
||||
STEP("Try to use already existing tag to create duplicate and expect 409");
|
||||
restClient.authenticateUser(admin).withCoreAPI().createSingleTag(alreadyExistingTag);
|
||||
|
||||
restClient
|
||||
.assertStatusCodeIs(CONFLICT)
|
||||
.assertLastError().containsSummary("Duplicate child name not allowed: " + alreadyExistingTag.getTag().toLowerCase());
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify if count field is 0 for newly created tags.
|
||||
*/
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.TAGS })
|
||||
public void testCreateTag_includingCount()
|
||||
{
|
||||
STEP("Create single tag as admin including count and verify if it is 0");
|
||||
final RestTagModel tagModel = createTagModelWithName(getRandomName(TAG_NAME_PREFIX).toLowerCase());
|
||||
final RestTagModel createdTag = restClient.authenticateUser(admin).withCoreAPI().include(FIELD_COUNT).createSingleTag(tagModel);
|
||||
|
||||
restClient.assertStatusCodeIs(CREATED);
|
||||
createdTag.assertThat().field(FIELD_TAG).is(tagModel.getTag())
|
||||
.assertThat().field(FIELD_ID).isNotEmpty()
|
||||
.assertThat().field(FIELD_COUNT).is(0);
|
||||
}
|
||||
|
||||
private RestTagModel prepareOrphanTagWithRandomName()
|
||||
{
|
||||
return prepareOrphanTag(createTagModelWithRandomName());
|
||||
}
|
||||
|
||||
private RestTagModel prepareOrphanTag(final RestTagModel tagModel)
|
||||
{
|
||||
final RestTagModel tag = restClient.authenticateUser(admin).withCoreAPI().createSingleTag(tagModel);
|
||||
restClient.assertStatusCodeIs(CREATED);
|
||||
return tag;
|
||||
}
|
||||
|
||||
private static RestTagModel createTagModelWithRandomName()
|
||||
{
|
||||
return createTagModelWithName(getRandomName(TAG_NAME_PREFIX));
|
||||
}
|
||||
|
||||
private static RestTagModel createTagModelWithName(final String tagName)
|
||||
{
|
||||
return RestTagModel.builder().tag(tagName).create();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Remote API
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2023 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
package org.alfresco.rest.tags;
|
||||
|
||||
import org.alfresco.dataprep.CMISUtil;
|
||||
import org.alfresco.rest.model.RestTagModel;
|
||||
import org.alfresco.utility.constants.UserRole;
|
||||
import org.alfresco.utility.model.TestGroup;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import static org.alfresco.utility.report.log.Step.STEP;
|
||||
import static org.springframework.http.HttpStatus.FORBIDDEN;
|
||||
import static org.springframework.http.HttpStatus.NOT_FOUND;
|
||||
import static org.springframework.http.HttpStatus.NO_CONTENT;
|
||||
|
||||
public class DeleteTagsTests extends TagsDataPrep
|
||||
{
|
||||
/**
|
||||
* Check we can delete a tag by its id.
|
||||
*/
|
||||
@Test(groups = {TestGroup.REST_API})
|
||||
public void testDeleteTag()
|
||||
{
|
||||
STEP("Create a tag assigned to a document and send a request to delete it.");
|
||||
document = dataContent.usingUser(adminUserModel).usingSite(siteModel).createContent(CMISUtil.DocumentType.TEXT_PLAIN);
|
||||
RestTagModel aTag = createTagForDocument(document);
|
||||
|
||||
restClient.authenticateUser(dataUser.getAdminUser()).withCoreAPI().usingTag(aTag).deleteTag();
|
||||
restClient.assertStatusCodeIs(NO_CONTENT);
|
||||
|
||||
STEP("Ensure that the tag has been deleted by sending a GET request and receiving 404.");
|
||||
restClient.authenticateUser(dataUser.getAdminUser()).withCoreAPI().getTag(aTag);
|
||||
restClient.assertStatusCodeIs(NOT_FOUND);
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt to delete a tag as a site manager and receive 403 error.
|
||||
* Other user roles have fewer permissions than a SiteManager and thus would also be forbidden from deleting a tag.
|
||||
*/
|
||||
@Test(groups = {TestGroup.REST_API})
|
||||
public void testDeleteTagAsSiteManager_andFail()
|
||||
{
|
||||
STEP("Create a tag assigned to a document and attempt to delete as a site manager");
|
||||
document = dataContent.usingUser(usersWithRoles.getOneUserWithRole(UserRole.SiteManager)).usingSite(siteModel).createContent(CMISUtil.DocumentType.TEXT_PLAIN);
|
||||
RestTagModel aTag = createTagForDocument(document);
|
||||
|
||||
restClient.authenticateUser(usersWithRoles.getOneUserWithRole(UserRole.SiteManager)).withCoreAPI().usingTag(aTag).deleteTag();
|
||||
restClient.assertStatusCodeIs(FORBIDDEN).assertLastError().containsSummary("Current user does not have permission to manage a tag");
|
||||
}
|
||||
|
||||
/**
|
||||
* Check we receive 404 error when trying to delete a tag with a non-existent id
|
||||
*/
|
||||
@Test(groups = {TestGroup.REST_API})
|
||||
public void testDeleteNonExistentTag()
|
||||
{
|
||||
STEP("Attempt to delete tag with non-existent id and receive 404 error");
|
||||
final String id = "non-existing-dummy-id";
|
||||
final RestTagModel tagModel = createTagModelWithId(id);
|
||||
|
||||
restClient.authenticateUser(dataUser.getAdminUser()).withCoreAPI().usingTag(tagModel).deleteTag();
|
||||
restClient.assertStatusCodeIs(NOT_FOUND);
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
package org.alfresco.rest.tags;
|
||||
|
||||
import java.util.Date;
|
||||
import org.alfresco.dataprep.CMISUtil;
|
||||
import org.alfresco.rest.RestTest;
|
||||
import org.alfresco.rest.model.RestTagModel;
|
||||
@@ -12,12 +11,9 @@ import org.alfresco.utility.data.RandomData;
|
||||
import org.alfresco.utility.model.FileModel;
|
||||
import org.alfresco.utility.model.FolderModel;
|
||||
import org.alfresco.utility.model.SiteModel;
|
||||
import org.alfresco.utility.model.TestGroup;
|
||||
import org.alfresco.utility.model.UserModel;
|
||||
import org.testng.annotations.BeforeClass;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
@Test(groups = {TestGroup.REQUIRE_SOLR})
|
||||
public class TagsDataPrep extends RestTest
|
||||
{
|
||||
|
||||
@@ -34,7 +30,9 @@ public class TagsDataPrep extends RestTest
|
||||
@BeforeClass
|
||||
public void init() throws Exception
|
||||
{
|
||||
//Create users
|
||||
adminUserModel = dataUser.getAdminUser();
|
||||
userModel = dataUser.createRandomTestUser();
|
||||
//Create public site
|
||||
siteModel = dataSite.usingUser(adminUserModel).createPublicRandomSite();
|
||||
usersWithRoles = dataUser.usingAdmin().addUsersWithRolesToSite(siteModel, UserRole.SiteManager, UserRole.SiteCollaborator, UserRole.SiteConsumer, UserRole.SiteContributor);
|
||||
@@ -60,4 +58,23 @@ public class TagsDataPrep extends RestTest
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
protected RestTagModel createTagForDocument(FileModel document)
|
||||
{
|
||||
String documentTagValue = RandomData.getRandomName("tag");
|
||||
return restClient.withCoreAPI().usingResource(document).addTag(documentTagValue);
|
||||
}
|
||||
|
||||
protected RestTagModel createTagModelWithId(final String id)
|
||||
{
|
||||
return createTagModelWithIdAndName(id, RandomData.getRandomName("tag"));
|
||||
}
|
||||
|
||||
protected RestTagModel createTagModelWithIdAndName(final String id, final String tag)
|
||||
{
|
||||
return RestTagModel.builder()
|
||||
.id(id)
|
||||
.tag(tag)
|
||||
.create();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo-tests</artifactId>
|
||||
<version>20.72</version>
|
||||
<version>20.90-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<developers>
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo-packaging</artifactId>
|
||||
<version>20.72</version>
|
||||
<version>20.90-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<properties>
|
||||
|
||||
10
pom.xml
10
pom.xml
@@ -2,7 +2,7 @@
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>alfresco-community-repo</artifactId>
|
||||
<version>20.72</version>
|
||||
<version>20.90-SNAPSHOT</version>
|
||||
<packaging>pom</packaging>
|
||||
<name>Alfresco Community Repo Parent</name>
|
||||
|
||||
@@ -53,7 +53,7 @@
|
||||
<dependency.alfresco-transform-service.version>2.0.0</dependency.alfresco-transform-service.version>
|
||||
<dependency.alfresco-transform-core.version>3.0.0</dependency.alfresco-transform-core.version>
|
||||
<dependency.alfresco-greenmail.version>6.5</dependency.alfresco-greenmail.version>
|
||||
<dependency.acs-event-model.version>0.0.16</dependency.acs-event-model.version>
|
||||
<dependency.acs-event-model.version>0.0.18</dependency.acs-event-model.version>
|
||||
|
||||
<dependency.spring.version>5.3.25</dependency.spring.version>
|
||||
<dependency.antlr.version>3.5.3</dependency.antlr.version>
|
||||
@@ -63,7 +63,7 @@
|
||||
<dependency.webscripts.version>8.33</dependency.webscripts.version>
|
||||
<dependency.bouncycastle.version>1.70</dependency.bouncycastle.version>
|
||||
<dependency.mockito-core.version>4.9.0</dependency.mockito-core.version>
|
||||
<dependency.assertj.version>3.23.1</dependency.assertj.version>
|
||||
<dependency.assertj.version>3.24.2</dependency.assertj.version>
|
||||
<dependency.org-json.version>20220320</dependency.org-json.version>
|
||||
<dependency.commons-dbcp.version>2.9.0</dependency.commons-dbcp.version>
|
||||
<dependency.commons-io.version>2.11.0</dependency.commons-io.version>
|
||||
@@ -116,7 +116,7 @@
|
||||
<alfresco.maven-plugin.version>2.2.0</alfresco.maven-plugin.version>
|
||||
<license-maven-plugin.version>2.0.1.alfresco-2</license-maven-plugin.version>
|
||||
|
||||
<dependency.postgresql.version>42.5.0</dependency.postgresql.version>
|
||||
<dependency.postgresql.version>42.5.2</dependency.postgresql.version>
|
||||
<dependency.mysql.version>8.0.30</dependency.mysql.version>
|
||||
<dependency.mysql-image.version>8</dependency.mysql-image.version>
|
||||
<dependency.mariadb.version>2.7.4</dependency.mariadb.version>
|
||||
@@ -148,7 +148,7 @@
|
||||
<connection>scm:git:https://github.com/Alfresco/alfresco-community-repo.git</connection>
|
||||
<developerConnection>scm:git:https://github.com/Alfresco/alfresco-community-repo.git</developerConnection>
|
||||
<url>https://github.com/Alfresco/alfresco-community-repo</url>
|
||||
<tag>20.72</tag>
|
||||
<tag>HEAD</tag>
|
||||
</scm>
|
||||
|
||||
<distributionManagement>
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo</artifactId>
|
||||
<version>20.72</version>
|
||||
<version>20.90-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
|
||||
@@ -26,57 +26,101 @@
|
||||
|
||||
package org.alfresco.rest.api;
|
||||
|
||||
import static org.alfresco.service.cmr.repository.StoreRef.STORE_REF_WORKSPACE_SPACESSTORE;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.alfresco.rest.api.model.Category;
|
||||
import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo;
|
||||
import org.alfresco.rest.framework.resource.parameters.Parameters;
|
||||
import org.alfresco.service.Experimental;
|
||||
import org.alfresco.service.cmr.repository.StoreRef;
|
||||
|
||||
@Experimental
|
||||
public interface Categories
|
||||
{
|
||||
Category getCategoryById(String id, Parameters parameters);
|
||||
Category getCategoryById(StoreRef storeRef, String id, Parameters parameters);
|
||||
|
||||
List<Category> createSubcategories(String parentCategoryId, List<Category> categories, Parameters parameters);
|
||||
default Category getCategoryById(String id, Parameters parameters)
|
||||
{
|
||||
return getCategoryById(STORE_REF_WORKSPACE_SPACESSTORE, id, parameters);
|
||||
}
|
||||
|
||||
CollectionWithPagingInfo<Category> getCategoryChildren(String parentCategoryId, Parameters parameters);
|
||||
List<Category> createSubcategories(StoreRef storeRef, String parentCategoryId, List<Category> categories, Parameters parameters);
|
||||
|
||||
default List<Category> createSubcategories(String parentCategoryId, List<Category> categories, Parameters parameters)
|
||||
{
|
||||
return createSubcategories(STORE_REF_WORKSPACE_SPACESSTORE, parentCategoryId, categories, parameters);
|
||||
}
|
||||
|
||||
List<Category> getCategoryChildren(StoreRef storeRef, String parentCategoryId, Parameters parameters);
|
||||
|
||||
default List<Category> getCategoryChildren(String parentCategoryId, Parameters parameters)
|
||||
{
|
||||
return getCategoryChildren(STORE_REF_WORKSPACE_SPACESSTORE, parentCategoryId, parameters);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update category by ID. Currently, it's possible only to update the name of category.
|
||||
*
|
||||
* @param storeRef Reference to node store.
|
||||
* @param id Category ID.
|
||||
* @param fixedCategoryModel Fixed category model.
|
||||
* @param parameters Additional parameters.
|
||||
* @return Updated category.
|
||||
*/
|
||||
Category updateCategoryById(String id, Category fixedCategoryModel);
|
||||
Category updateCategoryById(StoreRef storeRef, String id, Category fixedCategoryModel, Parameters parameters);
|
||||
|
||||
void deleteCategoryById(String id, Parameters parameters);
|
||||
default Category updateCategoryById(String id, Category fixedCategoryModel, Parameters parameters)
|
||||
{
|
||||
return updateCategoryById(STORE_REF_WORKSPACE_SPACESSTORE, id, fixedCategoryModel, parameters);
|
||||
}
|
||||
|
||||
void deleteCategoryById(StoreRef storeRef, String id, Parameters parameters);
|
||||
|
||||
default void deleteCategoryById(String id, Parameters parameters)
|
||||
{
|
||||
deleteCategoryById(STORE_REF_WORKSPACE_SPACESSTORE, id, parameters);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get categories linked from node. Read permission on node is required.
|
||||
* Node type is restricted to specified vales from: {@link org.alfresco.util.TypeConstraint}.
|
||||
*
|
||||
* @param nodeId Node ID.
|
||||
* @param parameters Additional parameters.
|
||||
* @return Categories linked from node.
|
||||
*/
|
||||
List<Category> listCategoriesForNode(String nodeId);
|
||||
List<Category> listCategoriesForNode(String nodeId, Parameters parameters);
|
||||
|
||||
/**
|
||||
* Link node to categories. Change permission on node is required.
|
||||
* Node types allowed for categorization are specified within {@link org.alfresco.util.TypeConstraint}.
|
||||
*
|
||||
* @param storeRef Reference to node store.
|
||||
* @param nodeId Node ID.
|
||||
* @param categoryLinks Category IDs to which content should be linked to.
|
||||
* @param parameters Additional parameters.
|
||||
* @return Linked to categories.
|
||||
*/
|
||||
List<Category> linkNodeToCategories(String nodeId, List<Category> categoryLinks);
|
||||
List<Category> linkNodeToCategories(StoreRef storeRef, String nodeId, List<Category> categoryLinks, Parameters parameters);
|
||||
|
||||
default List<Category> linkNodeToCategories(String nodeId, List<Category> categoryLinks, Parameters parameters)
|
||||
{
|
||||
return linkNodeToCategories(STORE_REF_WORKSPACE_SPACESSTORE, nodeId, categoryLinks, parameters);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unlink node from a category.
|
||||
*
|
||||
* @param storeRef Reference to node store.
|
||||
* @param nodeId Node ID.
|
||||
* @param categoryId Category ID from which content node should be unlinked from.
|
||||
* @param parameters Additional parameters.
|
||||
*/
|
||||
void unlinkNodeFromCategory(String nodeId, String categoryId, Parameters parameters);
|
||||
void unlinkNodeFromCategory(StoreRef storeRef, String nodeId, String categoryId, Parameters parameters);
|
||||
|
||||
default void unlinkNodeFromCategory(String nodeId, String categoryId, Parameters parameters)
|
||||
{
|
||||
unlinkNodeFromCategory(STORE_REF_WORKSPACE_SPACESSTORE, nodeId, categoryId, parameters);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* #%L
|
||||
* Alfresco Remote API
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||
* Copyright (C) 2005 - 2023 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
@@ -23,22 +23,35 @@
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.rest.api;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.alfresco.rest.api.model.Tag;
|
||||
import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo;
|
||||
import org.alfresco.rest.framework.resource.parameters.Paging;
|
||||
import org.alfresco.rest.framework.resource.parameters.Parameters;
|
||||
import org.alfresco.service.cmr.repository.StoreRef;
|
||||
|
||||
public interface Tags
|
||||
{
|
||||
public List<Tag> addTags(String nodeId, List<Tag> tags);
|
||||
public Tag getTag(StoreRef storeRef, String tagId);
|
||||
public void deleteTag(String nodeId, String tagId);
|
||||
public CollectionWithPagingInfo<Tag> getTags(StoreRef storeRef, Parameters params);
|
||||
public Tag changeTag(StoreRef storeRef, String tagId, Tag tag);
|
||||
public CollectionWithPagingInfo<Tag> getTags(String nodeId, Parameters params);
|
||||
}
|
||||
package org.alfresco.rest.api;
|
||||
|
||||
import static org.alfresco.service.cmr.repository.StoreRef.STORE_REF_WORKSPACE_SPACESSTORE;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.alfresco.rest.api.model.Tag;
|
||||
import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo;
|
||||
import org.alfresco.rest.framework.resource.parameters.Parameters;
|
||||
import org.alfresco.service.Experimental;
|
||||
import org.alfresco.service.cmr.repository.StoreRef;
|
||||
|
||||
public interface Tags
|
||||
{
|
||||
List<Tag> addTags(String nodeId, List<Tag> tags);
|
||||
Tag getTag(StoreRef storeRef, String tagId);
|
||||
void deleteTag(String nodeId, String tagId);
|
||||
CollectionWithPagingInfo<Tag> getTags(StoreRef storeRef, Parameters params);
|
||||
Tag changeTag(StoreRef storeRef, String tagId, Tag tag);
|
||||
CollectionWithPagingInfo<Tag> getTags(String nodeId, Parameters params);
|
||||
|
||||
@Experimental
|
||||
List<Tag> createTags(StoreRef storeRef, List<Tag> tags, Parameters parameters);
|
||||
|
||||
@Experimental
|
||||
default List<Tag> createTags(List<Tag> tags, Parameters parameters)
|
||||
{
|
||||
return createTags(STORE_REF_WORKSPACE_SPACESSTORE, tags, parameters);
|
||||
}
|
||||
|
||||
void deleteTagById(StoreRef storeRef, String tagId);
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* #%L
|
||||
* Alfresco Remote API
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||
* Copyright (C) 2005 - 2023 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
@@ -45,6 +45,7 @@ public class CategoriesEntityResource implements EntityResourceAction.ReadById<C
|
||||
EntityResourceAction.Update<Category>,
|
||||
EntityResourceAction.Delete
|
||||
{
|
||||
|
||||
private final Categories categories;
|
||||
|
||||
public CategoriesEntityResource(Categories categories)
|
||||
@@ -77,7 +78,7 @@ public class CategoriesEntityResource implements EntityResourceAction.ReadById<C
|
||||
@Override
|
||||
public Category update(String id, Category categoryModel, Parameters parameters)
|
||||
{
|
||||
return categories.updateCategoryById(id, categoryModel);
|
||||
return categories.updateCategoryById(id, categoryModel, parameters);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -63,7 +63,7 @@ public class NodesCategoryLinksRelation implements RelationshipResourceAction.Cr
|
||||
@Override
|
||||
public CollectionWithPagingInfo<Category> readAll(String nodeId, Parameters parameters)
|
||||
{
|
||||
return ListPage.of(categories.listCategoriesForNode(nodeId), parameters.getPaging());
|
||||
return ListPage.of(categories.listCategoriesForNode(nodeId, parameters), parameters.getPaging());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -77,7 +77,7 @@ public class NodesCategoryLinksRelation implements RelationshipResourceAction.Cr
|
||||
@Override
|
||||
public List<Category> create(String nodeId, List<Category> categoryLinks, Parameters parameters)
|
||||
{
|
||||
return categories.linkNodeToCategories(nodeId, categoryLinks);
|
||||
return categories.linkNodeToCategories(nodeId, categoryLinks, parameters);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -93,5 +93,4 @@ public class NodesCategoryLinksRelation implements RelationshipResourceAction.Cr
|
||||
{
|
||||
categories.unlinkNodeFromCategory(nodeId, categoryId, parameters);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* #%L
|
||||
* Alfresco Remote API
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2022 Alfresco Software Limited
|
||||
* Copyright (C) 2005 - 2023 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
@@ -26,9 +26,8 @@
|
||||
|
||||
package org.alfresco.rest.api.categories;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.util.List;
|
||||
|
||||
import org.alfresco.rest.api.Categories;
|
||||
import org.alfresco.rest.api.model.Category;
|
||||
@@ -36,6 +35,7 @@ import org.alfresco.rest.framework.WebApiDescription;
|
||||
import org.alfresco.rest.framework.resource.RelationshipResource;
|
||||
import org.alfresco.rest.framework.resource.actions.interfaces.RelationshipResourceAction;
|
||||
import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo;
|
||||
import org.alfresco.rest.framework.resource.parameters.ListPage;
|
||||
import org.alfresco.rest.framework.resource.parameters.Parameters;
|
||||
|
||||
@RelationshipResource(name = "subcategories", entityResource = CategoriesEntityResource.class, title = "Subcategories")
|
||||
@@ -69,8 +69,8 @@ public class SubcategoriesRelation implements RelationshipResourceAction.Create<
|
||||
description = "Lists direct children of a parent category",
|
||||
successStatus = HttpServletResponse.SC_OK)
|
||||
@Override
|
||||
public CollectionWithPagingInfo<Category> readAll(String parentCategoryId, Parameters params)
|
||||
public CollectionWithPagingInfo<Category> readAll(String parentCategoryId, Parameters parameters)
|
||||
{
|
||||
return categories.getCategoryChildren(parentCategoryId, params);
|
||||
return ListPage.of(categories.getCategoryChildren(parentCategoryId, parameters), parameters.getPaging());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,10 +46,8 @@ import org.alfresco.rest.api.model.Category;
|
||||
import org.alfresco.rest.api.model.Node;
|
||||
import org.alfresco.rest.framework.core.exceptions.EntityNotFoundException;
|
||||
import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException;
|
||||
import org.alfresco.rest.framework.core.exceptions.PermissionDeniedException;
|
||||
import org.alfresco.rest.framework.core.exceptions.InvalidNodeTypeException;
|
||||
import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo;
|
||||
import org.alfresco.rest.framework.resource.parameters.ListPage;
|
||||
import org.alfresco.rest.framework.core.exceptions.PermissionDeniedException;
|
||||
import org.alfresco.rest.framework.resource.parameters.Parameters;
|
||||
import org.alfresco.service.Experimental;
|
||||
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
||||
@@ -62,6 +60,7 @@ import org.alfresco.service.cmr.security.AuthorityService;
|
||||
import org.alfresco.service.cmr.security.PermissionService;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.alfresco.service.namespace.RegexQNamePattern;
|
||||
import org.alfresco.util.Pair;
|
||||
import org.alfresco.util.TypeConstraint;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
@@ -69,6 +68,7 @@ import org.apache.commons.lang3.StringUtils;
|
||||
@Experimental
|
||||
public class CategoriesImpl implements Categories
|
||||
{
|
||||
static final String INCLUDE_COUNT_PARAM = "count";
|
||||
static final String NOT_A_VALID_CATEGORY = "Node id does not refer to a valid category";
|
||||
static final String NO_PERMISSION_TO_MANAGE_A_CATEGORY = "Current user does not have permission to manage a category";
|
||||
static final String NO_PERMISSION_TO_READ_CONTENT = "Current user does not have read permission to content";
|
||||
@@ -83,8 +83,8 @@ public class CategoriesImpl implements Categories
|
||||
private final PermissionService permissionService;
|
||||
private final TypeConstraint typeConstraint;
|
||||
|
||||
public CategoriesImpl(AuthorityService authorityService, CategoryService categoryService, Nodes nodes, NodeService nodeService, PermissionService permissionService,
|
||||
TypeConstraint typeConstraint)
|
||||
public CategoriesImpl(AuthorityService authorityService, CategoryService categoryService, Nodes nodes, NodeService nodeService,
|
||||
PermissionService permissionService, TypeConstraint typeConstraint)
|
||||
{
|
||||
this.authorityService = authorityService;
|
||||
this.categoryService = categoryService;
|
||||
@@ -95,63 +95,89 @@ public class CategoriesImpl implements Categories
|
||||
}
|
||||
|
||||
@Override
|
||||
public Category getCategoryById(final String id, final Parameters params)
|
||||
public Category getCategoryById(final StoreRef storeRef, final String id, final Parameters parameters)
|
||||
{
|
||||
final NodeRef nodeRef = getCategoryNodeRef(id);
|
||||
final NodeRef nodeRef = getCategoryNodeRef(storeRef, id);
|
||||
if (isRootCategory(nodeRef))
|
||||
{
|
||||
throw new InvalidArgumentException(NOT_A_VALID_CATEGORY, new String[]{id});
|
||||
}
|
||||
|
||||
return mapToCategory(nodeRef);
|
||||
final Category category = mapToCategory(nodeRef);
|
||||
|
||||
if (parameters.getInclude().contains(INCLUDE_COUNT_PARAM))
|
||||
{
|
||||
final Map<String, Integer> categoriesCount = getCategoriesCount(storeRef);
|
||||
category.setCount(categoriesCount.getOrDefault(category.getId(), 0));
|
||||
}
|
||||
|
||||
return category;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Category> createSubcategories(String parentCategoryId, List<Category> categories, Parameters parameters)
|
||||
public List<Category> createSubcategories(final StoreRef storeRef, final String parentCategoryId, final List<Category> categories, final Parameters parameters)
|
||||
{
|
||||
verifyAdminAuthority();
|
||||
final NodeRef parentNodeRef = getCategoryNodeRef(parentCategoryId);
|
||||
final List<NodeRef> categoryNodeRefs = categories.stream()
|
||||
final NodeRef parentNodeRef = getCategoryNodeRef(storeRef, parentCategoryId);
|
||||
|
||||
return categories.stream()
|
||||
.map(c -> createCategoryNodeRef(parentNodeRef, c))
|
||||
.collect(Collectors.toList());
|
||||
return categoryNodeRefs.stream()
|
||||
.map(this::mapToCategory)
|
||||
.peek(category -> {
|
||||
if (parameters.getInclude().contains(INCLUDE_COUNT_PARAM))
|
||||
{
|
||||
category.setCount(0);
|
||||
}
|
||||
})
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public CollectionWithPagingInfo<Category> getCategoryChildren(String parentCategoryId, Parameters params)
|
||||
public List<Category> getCategoryChildren(final StoreRef storeRef, final String parentCategoryId, final Parameters parameters)
|
||||
{
|
||||
final NodeRef parentNodeRef = getCategoryNodeRef(parentCategoryId);
|
||||
final List<ChildAssociationRef> childCategoriesAssocs = nodeService.getChildAssocs(parentNodeRef).stream()
|
||||
.filter(ca -> ContentModel.ASSOC_SUBCATEGORIES.equals(ca.getTypeQName()))
|
||||
.collect(Collectors.toList());
|
||||
final List<Category> categories = childCategoriesAssocs.stream()
|
||||
.map(c -> mapToCategory(c.getChildRef()))
|
||||
.collect(Collectors.toList());
|
||||
return ListPage.of(categories, params.getPaging());
|
||||
final NodeRef parentNodeRef = getCategoryNodeRef(storeRef, parentCategoryId);
|
||||
final List<Category> categories = nodeService.getChildAssocs(parentNodeRef).stream()
|
||||
.filter(ca -> ContentModel.ASSOC_SUBCATEGORIES.equals(ca.getTypeQName()))
|
||||
.map(ChildAssociationRef::getChildRef)
|
||||
.map(this::mapToCategory)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
if (parameters.getInclude().contains(INCLUDE_COUNT_PARAM))
|
||||
{
|
||||
final Map<String, Integer> categoriesCount = getCategoriesCount(storeRef);
|
||||
categories.forEach(category -> category.setCount(categoriesCount.getOrDefault(category.getId(), 0)));
|
||||
}
|
||||
|
||||
return categories;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Category updateCategoryById(final String id, final Category fixedCategoryModel)
|
||||
public Category updateCategoryById(final StoreRef storeRef, final String id, final Category fixedCategoryModel, final Parameters parameters)
|
||||
{
|
||||
verifyAdminAuthority();
|
||||
final NodeRef categoryNodeRef = getCategoryNodeRef(id);
|
||||
final NodeRef categoryNodeRef = getCategoryNodeRef(storeRef, id);
|
||||
if (isRootCategory(categoryNodeRef))
|
||||
{
|
||||
throw new InvalidArgumentException(NOT_A_VALID_CATEGORY, new String[]{id});
|
||||
}
|
||||
|
||||
validateCategoryFields(fixedCategoryModel);
|
||||
final Category category = mapToCategory(changeCategoryName(categoryNodeRef, fixedCategoryModel.getName()));
|
||||
|
||||
return mapToCategory(changeCategoryName(categoryNodeRef, fixedCategoryModel.getName()));
|
||||
if (parameters.getInclude().contains(INCLUDE_COUNT_PARAM))
|
||||
{
|
||||
final Map<String, Integer> categoriesCount = getCategoriesCount(storeRef);
|
||||
category.setCount(categoriesCount.getOrDefault(category.getId(), 0));
|
||||
}
|
||||
|
||||
return category;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteCategoryById(String id, Parameters parameters)
|
||||
public void deleteCategoryById(final StoreRef storeRef, final String id, final Parameters parameters)
|
||||
{
|
||||
verifyAdminAuthority();
|
||||
final NodeRef nodeRef = getCategoryNodeRef(id);
|
||||
final NodeRef nodeRef = getCategoryNodeRef(storeRef, id);
|
||||
if (isRootCategory(nodeRef))
|
||||
{
|
||||
throw new InvalidArgumentException(NOT_A_VALID_CATEGORY, new String[]{id});
|
||||
@@ -161,7 +187,7 @@ public class CategoriesImpl implements Categories
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Category> listCategoriesForNode(final String nodeId)
|
||||
public List<Category> listCategoriesForNode(final String nodeId, final Parameters parameters)
|
||||
{
|
||||
final NodeRef contentNodeRef = nodes.validateNode(nodeId);
|
||||
verifyReadPermission(contentNodeRef);
|
||||
@@ -178,7 +204,7 @@ public class CategoriesImpl implements Categories
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Category> linkNodeToCategories(final String nodeId, final List<Category> categoryLinks)
|
||||
public List<Category> linkNodeToCategories(final StoreRef storeRef, final String nodeId, final List<Category> categoryLinks, final Parameters parameters)
|
||||
{
|
||||
if (CollectionUtils.isEmpty(categoryLinks))
|
||||
{
|
||||
@@ -194,7 +220,7 @@ public class CategoriesImpl implements Categories
|
||||
.map(Category::getId)
|
||||
.filter(StringUtils::isNotEmpty)
|
||||
.distinct()
|
||||
.map(this::getCategoryNodeRef)
|
||||
.map(id -> getCategoryNodeRef(storeRef, id))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
if (CollectionUtils.isEmpty(categoryNodeRefs) || isRootCategoryPresent(categoryNodeRefs))
|
||||
@@ -208,9 +234,9 @@ public class CategoriesImpl implements Categories
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unlinkNodeFromCategory(final String nodeId, final String categoryId, Parameters parameters)
|
||||
public void unlinkNodeFromCategory(final StoreRef storeRef, final String nodeId, final String categoryId, final Parameters parameters)
|
||||
{
|
||||
final NodeRef categoryNodeRef = getCategoryNodeRef(categoryId);
|
||||
final NodeRef categoryNodeRef = getCategoryNodeRef(storeRef, categoryId);
|
||||
final NodeRef contentNodeRef = nodes.validateNode(nodeId);
|
||||
verifyChangePermission(contentNodeRef);
|
||||
verifyNodeType(contentNodeRef);
|
||||
@@ -272,13 +298,14 @@ public class CategoriesImpl implements Categories
|
||||
* This method gets category NodeRef for a given category id.
|
||||
* If '-root-' is passed as category id, then it's retrieved as a call to {@link org.alfresco.service.cmr.search.CategoryService#getRootCategoryNodeRef}
|
||||
* In all other cases it's retrieved as a node of a category type {@link #validateCategoryNode(String)}
|
||||
* @param storeRef Reference to node store.
|
||||
* @param nodeId category node id
|
||||
* @return NodRef of category node
|
||||
*/
|
||||
private NodeRef getCategoryNodeRef(String nodeId)
|
||||
private NodeRef getCategoryNodeRef(StoreRef storeRef, String nodeId)
|
||||
{
|
||||
return PATH_ROOT.equals(nodeId) ?
|
||||
categoryService.getRootCategoryNodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE)
|
||||
categoryService.getRootCategoryNodeRef(storeRef)
|
||||
.orElseThrow(() -> new EntityNotFoundException(nodeId)) :
|
||||
validateCategoryNode(nodeId);
|
||||
}
|
||||
@@ -434,4 +461,18 @@ public class CategoriesImpl implements Categories
|
||||
nodeService.setProperty(nodeRef, ContentModel.PROP_CATEGORIES, (Serializable) allCategories);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get categories by usage count. Result is a map of category IDs (short form - UUID) as key and usage count as value.
|
||||
*
|
||||
* @param storeRef Reference to node store.
|
||||
* @return Map of categories IDs and usage count.
|
||||
*/
|
||||
private Map<String, Integer> getCategoriesCount(final StoreRef storeRef)
|
||||
{
|
||||
final String idPrefix = storeRef + "/";
|
||||
return categoryService.getTopCategories(storeRef, ContentModel.ASPECT_GEN_CLASSIFIABLE, Integer.MAX_VALUE)
|
||||
.stream()
|
||||
.collect(Collectors.toMap(pair -> pair.getFirst().toString().replace(idPrefix, StringUtils.EMPTY), Pair::getSecond));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* #%L
|
||||
* Alfresco Remote API
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||
* Copyright (C) 2005 - 2023 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
@@ -23,111 +23,143 @@
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.rest.api.impl;
|
||||
|
||||
import java.util.AbstractList;
|
||||
package org.alfresco.rest.api.impl;
|
||||
|
||||
import java.util.AbstractList;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.alfresco.query.PagingResults;
|
||||
import org.alfresco.repo.tagging.NonExistentTagException;
|
||||
import org.alfresco.repo.tagging.TagExistsException;
|
||||
import org.alfresco.repo.tagging.TaggingException;
|
||||
import org.alfresco.rest.api.Nodes;
|
||||
import org.alfresco.rest.api.Tags;
|
||||
import org.alfresco.rest.api.model.Tag;
|
||||
import org.alfresco.rest.framework.core.exceptions.ConstraintViolatedException;
|
||||
import org.alfresco.rest.framework.core.exceptions.EntityNotFoundException;
|
||||
import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException;
|
||||
import org.alfresco.rest.framework.core.exceptions.NotFoundException;
|
||||
import org.alfresco.rest.framework.core.exceptions.UnsupportedResourceOperationException;
|
||||
import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo;
|
||||
import org.alfresco.rest.framework.resource.parameters.Paging;
|
||||
import org.alfresco.rest.framework.resource.parameters.Parameters;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.StoreRef;
|
||||
import org.alfresco.service.cmr.tagging.TaggingService;
|
||||
import org.alfresco.util.Pair;
|
||||
import org.alfresco.util.TypeConstraint;
|
||||
|
||||
/**
|
||||
* Centralises access to tag services and maps between representations.
|
||||
*
|
||||
* @author steveglover
|
||||
* @since publicapi1.0
|
||||
*/
|
||||
public class TagsImpl implements Tags
|
||||
{
|
||||
import org.alfresco.query.PagingResults;
|
||||
import org.alfresco.repo.tagging.NonExistentTagException;
|
||||
import org.alfresco.repo.tagging.TagExistsException;
|
||||
import org.alfresco.repo.tagging.TaggingException;
|
||||
import org.alfresco.rest.api.Nodes;
|
||||
import org.alfresco.rest.api.Tags;
|
||||
import org.alfresco.rest.api.model.Tag;
|
||||
import org.alfresco.rest.framework.core.exceptions.ConstraintViolatedException;
|
||||
import org.alfresco.rest.framework.core.exceptions.EntityNotFoundException;
|
||||
import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException;
|
||||
import org.alfresco.rest.framework.core.exceptions.NotFoundException;
|
||||
import org.alfresco.rest.framework.core.exceptions.PermissionDeniedException;
|
||||
import org.alfresco.rest.framework.core.exceptions.UnsupportedResourceOperationException;
|
||||
import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo;
|
||||
import org.alfresco.rest.framework.resource.parameters.Paging;
|
||||
import org.alfresco.rest.framework.resource.parameters.Parameters;
|
||||
import org.alfresco.service.Experimental;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.StoreRef;
|
||||
import org.alfresco.service.cmr.security.AuthorityService;
|
||||
import org.alfresco.service.cmr.tagging.TaggingService;
|
||||
import org.alfresco.util.Pair;
|
||||
import org.alfresco.util.TypeConstraint;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
|
||||
/**
|
||||
* Centralises access to tag services and maps between representations.
|
||||
*
|
||||
* @author steveglover
|
||||
* @since publicapi1.0
|
||||
*/
|
||||
public class TagsImpl implements Tags
|
||||
{
|
||||
private static final Object PARAM_INCLUDE_COUNT = "count";
|
||||
private Nodes nodes;
|
||||
private TaggingService taggingService;
|
||||
private TypeConstraint typeConstraint;
|
||||
|
||||
public void setTypeConstraint(TypeConstraint typeConstraint)
|
||||
{
|
||||
this.typeConstraint = typeConstraint;
|
||||
}
|
||||
|
||||
public void setNodes(Nodes nodes)
|
||||
{
|
||||
this.nodes = nodes;
|
||||
}
|
||||
|
||||
public void setTaggingService(TaggingService taggingService)
|
||||
{
|
||||
this.taggingService = taggingService;
|
||||
}
|
||||
|
||||
public List<Tag> addTags(String nodeId, final List<Tag> tags)
|
||||
{
|
||||
NodeRef nodeRef = nodes.validateNode(nodeId);
|
||||
if(!typeConstraint.matches(nodeRef))
|
||||
{
|
||||
throw new UnsupportedResourceOperationException("Cannot tag this node");
|
||||
}
|
||||
|
||||
List<String> tagValues = new AbstractList<String>()
|
||||
{
|
||||
@Override
|
||||
public String get(int arg0)
|
||||
{
|
||||
String tag = tags.get(arg0).getTag();
|
||||
return tag;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size()
|
||||
{
|
||||
return tags.size();
|
||||
}
|
||||
};
|
||||
try
|
||||
{
|
||||
List<Pair<String, NodeRef>> tagNodeRefs = taggingService.addTags(nodeRef, tagValues);
|
||||
List<Tag> ret = new ArrayList<Tag>(tags.size());
|
||||
for(Pair<String, NodeRef> pair : tagNodeRefs)
|
||||
{
|
||||
ret.add(new Tag(pair.getSecond(), pair.getFirst()));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
catch(IllegalArgumentException e)
|
||||
{
|
||||
throw new InvalidArgumentException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public void deleteTag(String nodeId, String tagId)
|
||||
{
|
||||
NodeRef nodeRef = nodes.validateNode(nodeId);
|
||||
getTag(tagId);
|
||||
NodeRef existingTagNodeRef = validateTag(tagId);
|
||||
String tagValue = taggingService.getTagName(existingTagNodeRef);
|
||||
taggingService.removeTag(nodeRef, tagValue);
|
||||
}
|
||||
|
||||
static final String NOT_A_VALID_TAG = "An invalid parameter has been supplied";
|
||||
static final String NO_PERMISSION_TO_MANAGE_A_TAG = "Current user does not have permission to manage a tag";
|
||||
|
||||
private Nodes nodes;
|
||||
private TaggingService taggingService;
|
||||
private TypeConstraint typeConstraint;
|
||||
private AuthorityService authorityService;
|
||||
|
||||
public void setTypeConstraint(TypeConstraint typeConstraint)
|
||||
{
|
||||
this.typeConstraint = typeConstraint;
|
||||
}
|
||||
|
||||
public void setNodes(Nodes nodes)
|
||||
{
|
||||
this.nodes = nodes;
|
||||
}
|
||||
|
||||
public void setTaggingService(TaggingService taggingService)
|
||||
{
|
||||
this.taggingService = taggingService;
|
||||
}
|
||||
|
||||
public void setAuthorityService(AuthorityService authorityService)
|
||||
{
|
||||
this.authorityService = authorityService;
|
||||
}
|
||||
|
||||
public List<Tag> addTags(String nodeId, final List<Tag> tags)
|
||||
{
|
||||
NodeRef nodeRef = nodes.validateNode(nodeId);
|
||||
if(!typeConstraint.matches(nodeRef))
|
||||
{
|
||||
throw new UnsupportedResourceOperationException("Cannot tag this node");
|
||||
}
|
||||
|
||||
List<String> tagValues = new AbstractList<String>()
|
||||
{
|
||||
@Override
|
||||
|
||||
public String get(int arg0)
|
||||
{
|
||||
String tag = tags.get(arg0).getTag();
|
||||
return tag;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size()
|
||||
{
|
||||
return tags.size();
|
||||
}
|
||||
};
|
||||
try
|
||||
{
|
||||
List<Pair<String, NodeRef>> tagNodeRefs = taggingService.addTags(nodeRef, tagValues);
|
||||
List<Tag> ret = new ArrayList<Tag>(tags.size());
|
||||
List<Pair<String, Integer>> tagsCountPairList = taggingService.findTaggedNodesAndCountByTagName(nodeRef.getStoreRef());
|
||||
Map<String, Integer> tagsCountMap = tagsCountPairList.stream().collect(Collectors.toMap(Pair::getFirst,Pair::getSecond));
|
||||
for(Pair<String, NodeRef> pair : tagNodeRefs)
|
||||
{
|
||||
Tag createdTag=new Tag(pair.getSecond(), pair.getFirst());
|
||||
// The new use of the tag will not be indexed yet, so add one to whatever count we get back
|
||||
createdTag.setCount(Optional.ofNullable(tagsCountMap.get(createdTag.getTag())).orElse(0) + 1);
|
||||
ret.add(createdTag);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
catch(IllegalArgumentException e)
|
||||
{
|
||||
throw new InvalidArgumentException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public void deleteTag(String nodeId, String tagId)
|
||||
{
|
||||
NodeRef nodeRef = nodes.validateNode(nodeId);
|
||||
getTag(tagId);
|
||||
NodeRef existingTagNodeRef = validateTag(tagId);
|
||||
String tagValue = taggingService.getTagName(existingTagNodeRef);
|
||||
taggingService.removeTag(nodeRef, tagValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteTagById(StoreRef storeRef, String tagId) {
|
||||
verifyAdminAuthority();
|
||||
|
||||
NodeRef tagNodeRef = validateTag(storeRef, tagId);
|
||||
String tagValue = taggingService.getTagName(tagNodeRef);
|
||||
taggingService.deleteTag(storeRef, tagValue);
|
||||
}
|
||||
|
||||
public CollectionWithPagingInfo<Tag> getTags(StoreRef storeRef, Parameters params)
|
||||
{
|
||||
Paging paging = params.getPaging();
|
||||
@@ -153,82 +185,117 @@ public class TagsImpl implements Tags
|
||||
for (Pair<NodeRef, String> pair : page)
|
||||
{
|
||||
Tag selectedTag = new Tag(pair.getFirst(), pair.getSecond());
|
||||
selectedTag.setCount(tagsByCountMap.get(selectedTag.getTag()));
|
||||
selectedTag.setCount(Optional.ofNullable(tagsByCountMap.get(selectedTag.getTag())).orElse(0));
|
||||
tags.add(selectedTag);
|
||||
}
|
||||
|
||||
return CollectionWithPagingInfo.asPaged(paging, tags, results.hasMoreItems(), (totalItems == null ? null : totalItems.intValue()));
|
||||
}
|
||||
|
||||
public NodeRef validateTag(String tagId)
|
||||
{
|
||||
NodeRef tagNodeRef = nodes.validateNode(tagId);
|
||||
if(tagNodeRef == null)
|
||||
{
|
||||
throw new EntityNotFoundException(tagId);
|
||||
}
|
||||
return tagNodeRef;
|
||||
}
|
||||
|
||||
public NodeRef validateTag(StoreRef storeRef, String tagId)
|
||||
{
|
||||
NodeRef tagNodeRef = nodes.validateNode(storeRef, tagId);
|
||||
if(tagNodeRef == null)
|
||||
{
|
||||
throw new EntityNotFoundException(tagId);
|
||||
}
|
||||
return tagNodeRef;
|
||||
}
|
||||
|
||||
public Tag changeTag(StoreRef storeRef, String tagId, Tag tag)
|
||||
{
|
||||
try
|
||||
{
|
||||
NodeRef existingTagNodeRef = validateTag(storeRef, tagId);
|
||||
String existingTagName = taggingService.getTagName(existingTagNodeRef);
|
||||
String newTagName = tag.getTag();
|
||||
NodeRef newTagNodeRef = taggingService.changeTag(storeRef, existingTagName, newTagName);
|
||||
return new Tag(newTagNodeRef, newTagName);
|
||||
}
|
||||
catch(NonExistentTagException e)
|
||||
{
|
||||
throw new NotFoundException(e.getMessage());
|
||||
}
|
||||
catch(TagExistsException e)
|
||||
{
|
||||
throw new ConstraintViolatedException(e.getMessage());
|
||||
}
|
||||
catch(TaggingException e)
|
||||
{
|
||||
throw new InvalidArgumentException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public Tag getTag(String tagId)
|
||||
{
|
||||
return getTag(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, tagId);
|
||||
}
|
||||
|
||||
public Tag getTag(StoreRef storeRef, String tagId)
|
||||
{
|
||||
NodeRef tagNodeRef = validateTag(storeRef, tagId);
|
||||
String tagValue = taggingService.getTagName(tagNodeRef);
|
||||
return new Tag(tagNodeRef, tagValue);
|
||||
}
|
||||
|
||||
public CollectionWithPagingInfo<Tag> getTags(String nodeId, Parameters params)
|
||||
{
|
||||
NodeRef nodeRef = validateTag(nodeId);
|
||||
|
||||
PagingResults<Pair<NodeRef, String>> results = taggingService.getTags(nodeRef, Util.getPagingRequest(params.getPaging()));
|
||||
Integer totalItems = results.getTotalResultCount().getFirst();
|
||||
List<Pair<NodeRef, String>> page = results.getPage();
|
||||
List<Tag> tags = new ArrayList<Tag>(page.size());
|
||||
for(Pair<NodeRef, String> pair : page)
|
||||
{
|
||||
tags.add(new Tag(pair.getFirst(), pair.getSecond()));
|
||||
}
|
||||
|
||||
return CollectionWithPagingInfo.asPaged(params.getPaging(), tags, results.hasMoreItems(), (totalItems == null ? null : totalItems.intValue()));
|
||||
}
|
||||
}
|
||||
|
||||
public NodeRef validateTag(String tagId)
|
||||
{
|
||||
NodeRef tagNodeRef = nodes.validateNode(tagId);
|
||||
if(tagNodeRef == null)
|
||||
{
|
||||
throw new EntityNotFoundException(tagId);
|
||||
}
|
||||
return tagNodeRef;
|
||||
}
|
||||
|
||||
public NodeRef validateTag(StoreRef storeRef, String tagId)
|
||||
{
|
||||
NodeRef tagNodeRef = nodes.validateNode(storeRef, tagId);
|
||||
if(tagNodeRef == null)
|
||||
{
|
||||
throw new EntityNotFoundException(tagId);
|
||||
}
|
||||
return tagNodeRef;
|
||||
}
|
||||
|
||||
public Tag changeTag(StoreRef storeRef, String tagId, Tag tag)
|
||||
{
|
||||
try
|
||||
{
|
||||
NodeRef existingTagNodeRef = validateTag(storeRef, tagId);
|
||||
String existingTagName = taggingService.getTagName(existingTagNodeRef);
|
||||
String newTagName = tag.getTag();
|
||||
NodeRef newTagNodeRef = taggingService.changeTag(storeRef, existingTagName, newTagName);
|
||||
return new Tag(newTagNodeRef, newTagName);
|
||||
}
|
||||
catch(NonExistentTagException e)
|
||||
{
|
||||
throw new NotFoundException(e.getMessage());
|
||||
}
|
||||
catch(TagExistsException e)
|
||||
{
|
||||
throw new ConstraintViolatedException(e.getMessage());
|
||||
}
|
||||
catch(TaggingException e)
|
||||
{
|
||||
throw new InvalidArgumentException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public Tag getTag(String tagId)
|
||||
{
|
||||
return getTag(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, tagId);
|
||||
}
|
||||
|
||||
public Tag getTag(StoreRef storeRef, String tagId)
|
||||
{
|
||||
NodeRef tagNodeRef = validateTag(storeRef, tagId);
|
||||
String tagValue = taggingService.getTagName(tagNodeRef);
|
||||
return new Tag(tagNodeRef, tagValue);
|
||||
}
|
||||
|
||||
public CollectionWithPagingInfo<Tag> getTags(String nodeId, Parameters params)
|
||||
{
|
||||
NodeRef nodeRef = validateTag(nodeId);
|
||||
|
||||
PagingResults<Pair<NodeRef, String>> results = taggingService.getTags(nodeRef, Util.getPagingRequest(params.getPaging()));
|
||||
Integer totalItems = results.getTotalResultCount().getFirst();
|
||||
List<Pair<NodeRef, String>> page = results.getPage();
|
||||
List<Tag> tags = new ArrayList<Tag>(page.size());
|
||||
for(Pair<NodeRef, String> pair : page)
|
||||
{
|
||||
tags.add(new Tag(pair.getFirst(), pair.getSecond()));
|
||||
}
|
||||
|
||||
return CollectionWithPagingInfo.asPaged(params.getPaging(), tags, results.hasMoreItems(), (totalItems == null ? null : totalItems.intValue()));
|
||||
}
|
||||
|
||||
@Experimental
|
||||
@Override
|
||||
public List<Tag> createTags(final StoreRef storeRef, final List<Tag> tags, final Parameters parameters)
|
||||
{
|
||||
verifyAdminAuthority();
|
||||
final List<String> tagNames = Optional.ofNullable(tags).orElse(Collections.emptyList()).stream()
|
||||
.filter(Objects::nonNull)
|
||||
.map(Tag::getTag)
|
||||
.distinct()
|
||||
.collect(Collectors.toList());
|
||||
|
||||
if (CollectionUtils.isEmpty(tagNames))
|
||||
{
|
||||
throw new InvalidArgumentException(NOT_A_VALID_TAG);
|
||||
}
|
||||
|
||||
return taggingService.createTags(storeRef, tagNames).stream()
|
||||
.map(pair -> Tag.builder().tag(pair.getFirst()).nodeRef(pair.getSecond()).create())
|
||||
.peek(tag -> {
|
||||
if (parameters.getInclude().contains(PARAM_INCLUDE_COUNT))
|
||||
{
|
||||
// this method creates orphan tags, which are not related with any content so setting count to 0.
|
||||
tag.setCount(0);
|
||||
}
|
||||
}).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private void verifyAdminAuthority()
|
||||
{
|
||||
if (!authorityService.hasAdminAuthority())
|
||||
{
|
||||
throw new PermissionDeniedException(NO_PERMISSION_TO_MANAGE_A_TAG);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* #%L
|
||||
* Alfresco Remote API
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2022 Alfresco Software Limited
|
||||
* Copyright (C) 2005 - 2023 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
@@ -34,6 +34,7 @@ public class Category
|
||||
private String name;
|
||||
private String parentId;
|
||||
private boolean hasChildren;
|
||||
private Integer count;
|
||||
|
||||
public String getId()
|
||||
{
|
||||
@@ -80,20 +81,38 @@ public class Category
|
||||
this.hasChildren = hasChildren;
|
||||
}
|
||||
|
||||
public Integer getCount()
|
||||
{
|
||||
return count;
|
||||
}
|
||||
|
||||
public void setCount(Integer count)
|
||||
{
|
||||
this.count = count;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o)
|
||||
{
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
if (this == o)
|
||||
return true;
|
||||
if (o == null || getClass() != o.getClass())
|
||||
return false;
|
||||
Category category = (Category) o;
|
||||
return hasChildren == category.hasChildren && Objects.equals(id, category.id) && name.equals(category.name) &&
|
||||
Objects.equals(parentId, category.parentId);
|
||||
return hasChildren == category.hasChildren && Objects.equals(id, category.id) && Objects.equals(name, category.name) && Objects.equals(parentId, category.parentId)
|
||||
&& Objects.equals(count, category.count);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
return Objects.hash(id, name, parentId, hasChildren);
|
||||
return Objects.hash(id, name, parentId, hasChildren, count);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return "Category{" + "id='" + id + '\'' + ", name='" + name + '\'' + ", parentId='" + parentId + '\'' + ", hasChildren=" + hasChildren + ", count=" + count + '}';
|
||||
}
|
||||
|
||||
public static Builder builder()
|
||||
@@ -107,6 +126,7 @@ public class Category
|
||||
private String name;
|
||||
private String parentId;
|
||||
private boolean hasChildren;
|
||||
private Integer count;
|
||||
|
||||
public Builder id(String id)
|
||||
{
|
||||
@@ -132,6 +152,12 @@ public class Category
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder count(Integer count)
|
||||
{
|
||||
this.count = count;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Category create()
|
||||
{
|
||||
final Category category = new Category();
|
||||
@@ -139,6 +165,7 @@ public class Category
|
||||
category.setName(name);
|
||||
category.setParentId(parentId);
|
||||
category.setHasChildren(hasChildren);
|
||||
category.setCount(count);
|
||||
return category;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* #%L
|
||||
* Alfresco Remote API
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||
* Copyright (C) 2005 - 2023 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
@@ -25,6 +25,8 @@
|
||||
*/
|
||||
package org.alfresco.rest.api.model;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import org.alfresco.rest.framework.resource.UniqueId;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
@@ -109,7 +111,7 @@ public class Tag implements Comparable<Tag>
|
||||
|
||||
/*
|
||||
* Tags are equal if they have the same NodeRef
|
||||
*
|
||||
*
|
||||
* (non-Javadoc)
|
||||
* @see java.lang.Object#equals(java.lang.Object)
|
||||
*/
|
||||
@@ -128,13 +130,65 @@ public class Tag implements Comparable<Tag>
|
||||
return false;
|
||||
} else if (!nodeRef.equals(other.nodeRef))
|
||||
return false;
|
||||
if(tag==null)
|
||||
{
|
||||
if(other.tag != null)
|
||||
return false;
|
||||
}
|
||||
else if (!tag.equals(other.tag))
|
||||
return false;
|
||||
if (count == null)
|
||||
{
|
||||
if (other.count != null)
|
||||
return false;
|
||||
}
|
||||
else if (!count.equals(other.count))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return "Tag [nodeRef=" + nodeRef + ", tag=" + tag + "]";
|
||||
return "Tag{" + "nodeRef=" + nodeRef + ", tag='" + tag + '\'' + ", count=" + count + '}';
|
||||
}
|
||||
|
||||
public static Builder builder()
|
||||
{
|
||||
return new Builder();
|
||||
}
|
||||
|
||||
public static class Builder
|
||||
{
|
||||
private NodeRef nodeRef;
|
||||
private String tag;
|
||||
private Integer count;
|
||||
|
||||
public Builder nodeRef(NodeRef nodeRef)
|
||||
{
|
||||
this.nodeRef = nodeRef;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder tag(String tag)
|
||||
{
|
||||
this.tag = tag;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder count(Integer count)
|
||||
{
|
||||
this.count = count;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Tag create()
|
||||
{
|
||||
final Tag tag = new Tag();
|
||||
tag.setNodeRef(nodeRef);
|
||||
tag.setTag(this.tag);
|
||||
tag.setCount(count);
|
||||
return tag;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,30 +1,33 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Remote API
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Remote API
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2023 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.rest.api.tags;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.util.List;
|
||||
|
||||
import org.alfresco.rest.api.Tags;
|
||||
import org.alfresco.rest.api.model.Tag;
|
||||
import org.alfresco.rest.framework.WebApiDescription;
|
||||
@@ -33,12 +36,14 @@ import org.alfresco.rest.framework.resource.EntityResource;
|
||||
import org.alfresco.rest.framework.resource.actions.interfaces.EntityResourceAction;
|
||||
import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo;
|
||||
import org.alfresco.rest.framework.resource.parameters.Parameters;
|
||||
import org.alfresco.service.Experimental;
|
||||
import org.alfresco.service.cmr.repository.StoreRef;
|
||||
import org.alfresco.util.ParameterCheck;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
|
||||
@EntityResource(name="tags", title = "Tags")
|
||||
public class TagsEntityResource implements EntityResourceAction.Read<Tag>, EntityResourceAction.ReadById<Tag>, EntityResourceAction.Update<Tag>, InitializingBean
|
||||
public class TagsEntityResource implements EntityResourceAction.Read<Tag>,
|
||||
EntityResourceAction.ReadById<Tag>, EntityResourceAction.Update<Tag>, EntityResourceAction.Create<Tag>, EntityResourceAction.Delete, InitializingBean
|
||||
{
|
||||
private Tags tags;
|
||||
|
||||
@@ -77,4 +82,25 @@ public class TagsEntityResource implements EntityResourceAction.Read<Tag>, Entit
|
||||
{
|
||||
return tags.getTag(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, id);
|
||||
}
|
||||
|
||||
/**
|
||||
* POST /tags
|
||||
*/
|
||||
@Experimental
|
||||
@WebApiDescription(
|
||||
title = "Create an orphan tag",
|
||||
description = "Creates a tag, which is not associated with any node",
|
||||
successStatus = HttpServletResponse.SC_CREATED
|
||||
)
|
||||
@Override
|
||||
public List<Tag> create(List<Tag> tags, Parameters parameters)
|
||||
{
|
||||
return this.tags.createTags(tags, parameters);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete(String id, Parameters parameters)
|
||||
{
|
||||
tags.deleteTagById(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, id);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -856,6 +856,7 @@
|
||||
<bean id="tags" class="org.alfresco.rest.api.impl.TagsImpl">
|
||||
<property name="nodes" ref="nodes" />
|
||||
<property name="taggingService" ref="TaggingService" />
|
||||
<property name="authorityService" ref="AuthorityService" />
|
||||
<property name="typeConstraint" ref="nodeTypeConstraint" />
|
||||
</bean>
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* #%L
|
||||
* Alfresco Repository
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2022 Alfresco Software Limited
|
||||
* Copyright (C) 2005 - 2023 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
@@ -49,6 +49,8 @@ import org.junit.runners.Suite;
|
||||
org.alfresco.repo.webdav.WebDAVHelperTest.class,
|
||||
org.alfresco.repo.webdav.WebDAVLockServiceImplTest.class,
|
||||
org.alfresco.rest.api.RulesUnitTests.class,
|
||||
org.alfresco.rest.api.CategoriesUnitTests.class,
|
||||
org.alfresco.rest.api.TagsUnitTests.class,
|
||||
org.alfresco.rest.api.impl.ContentStorageInformationImplTest.class,
|
||||
org.alfresco.rest.api.nodes.NodeStorageInfoRelationTest.class,
|
||||
org.alfresco.rest.api.search.ResultMapperTests.class,
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Remote API
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2023 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
package org.alfresco.rest.api;
|
||||
|
||||
import org.alfresco.rest.api.categories.CategoriesEntityResourceTest;
|
||||
import org.alfresco.rest.api.categories.NodesCategoryLinksRelationTest;
|
||||
import org.alfresco.rest.api.categories.SubcategoriesRelationTest;
|
||||
import org.alfresco.rest.api.impl.CategoriesImplTest;
|
||||
import org.alfresco.service.Experimental;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.Suite;
|
||||
|
||||
@Experimental
|
||||
@RunWith(Suite.class)
|
||||
@Suite.SuiteClasses({
|
||||
CategoriesImplTest.class,
|
||||
CategoriesEntityResourceTest.class,
|
||||
SubcategoriesRelationTest.class,
|
||||
NodesCategoryLinksRelationTest.class
|
||||
})
|
||||
public class CategoriesUnitTests
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Remote API
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2023 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.rest.api;
|
||||
|
||||
import org.alfresco.rest.api.impl.TagsImplTest;
|
||||
import org.alfresco.rest.api.tags.TagsEntityResourceTest;
|
||||
import org.alfresco.service.Experimental;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.Suite;
|
||||
|
||||
@Experimental
|
||||
@RunWith(Suite.class)
|
||||
@Suite.SuiteClasses({
|
||||
TagsImplTest.class,
|
||||
TagsEntityResourceTest.class
|
||||
})
|
||||
public class TagsUnitTests
|
||||
{
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
* #%L
|
||||
* Alfresco Remote API
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2022 Alfresco Software Limited
|
||||
* Copyright (C) 2005 - 2023 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
@@ -26,15 +26,21 @@
|
||||
|
||||
package org.alfresco.rest.api.categories;
|
||||
|
||||
import static org.alfresco.service.cmr.repository.StoreRef.STORE_REF_WORKSPACE_SPACESSTORE;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyBoolean;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.BDDMockito.then;
|
||||
import static org.mockito.BDDMockito.willCallRealMethod;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.alfresco.rest.api.Categories;
|
||||
import org.alfresco.rest.api.model.Category;
|
||||
import org.alfresco.rest.framework.resource.parameters.Parameters;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.InjectMocks;
|
||||
@@ -45,6 +51,7 @@ import org.mockito.junit.MockitoJUnitRunner;
|
||||
public class CategoriesEntityResourceTest
|
||||
{
|
||||
private static final String CATEGORY_ID = "category-node-id";
|
||||
|
||||
@Mock
|
||||
private Categories categoriesMock;
|
||||
@Mock
|
||||
@@ -58,26 +65,37 @@ public class CategoriesEntityResourceTest
|
||||
@Test
|
||||
public void testReadCategoryById()
|
||||
{
|
||||
given(categoriesMock.getCategoryById(CATEGORY_ID, parametersMock)).willReturn(categoryMock);
|
||||
given(categoriesMock.getCategoryById(any(), any())).willCallRealMethod();
|
||||
given(categoriesMock.getCategoryById(any(), any(), any())).willReturn(categoryMock);
|
||||
|
||||
//when
|
||||
final Category category = objectUnderTest.readById(CATEGORY_ID, parametersMock);
|
||||
|
||||
then(categoriesMock).should().getCategoryById(CATEGORY_ID, parametersMock);
|
||||
then(categoriesMock).shouldHaveNoMoreInteractions();
|
||||
then(categoriesMock).should().getCategoryById(STORE_REF_WORKSPACE_SPACESSTORE, CATEGORY_ID, parametersMock);
|
||||
assertEquals(categoryMock, category);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateCategoryById()
|
||||
{
|
||||
given(categoriesMock.updateCategoryById(any(), any())).willReturn(categoryMock);
|
||||
given(categoriesMock.updateCategoryById(any(), any(), any())).willCallRealMethod();
|
||||
given(categoriesMock.updateCategoryById(any(), any(), any(), any())).willReturn(categoryMock);
|
||||
|
||||
// when
|
||||
final Category actualCategory = objectUnderTest.update(CATEGORY_ID, categoryMock, parametersMock);
|
||||
|
||||
then(categoriesMock).should().updateCategoryById(CATEGORY_ID, categoryMock);
|
||||
then(categoriesMock).shouldHaveNoMoreInteractions();
|
||||
then(categoriesMock).should().updateCategoryById(STORE_REF_WORKSPACE_SPACESSTORE, CATEGORY_ID, categoryMock, parametersMock);
|
||||
assertThat(actualCategory).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeleteCategoryById()
|
||||
{
|
||||
willCallRealMethod().given(categoriesMock).deleteCategoryById(any(), any());
|
||||
|
||||
// when
|
||||
objectUnderTest.delete(CATEGORY_ID, parametersMock);
|
||||
|
||||
then(categoriesMock).should().deleteCategoryById(STORE_REF_WORKSPACE_SPACESSTORE, CATEGORY_ID, parametersMock);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,6 +47,7 @@ import org.mockito.junit.MockitoJUnitRunner;
|
||||
public class NodesCategoryLinksRelationTest
|
||||
{
|
||||
private static final String CONTENT_ID = "content-node-id";
|
||||
private static final String CATEGORY_ID = "category-id";
|
||||
|
||||
@Mock
|
||||
private Categories categoriesMock;
|
||||
@@ -61,12 +62,12 @@ public class NodesCategoryLinksRelationTest
|
||||
@Test
|
||||
public void testReadAll()
|
||||
{
|
||||
given(categoriesMock.listCategoriesForNode(any())).willReturn(List.of(categoryMock));
|
||||
given(categoriesMock.listCategoriesForNode(any(), any())).willReturn(List.of(categoryMock));
|
||||
|
||||
// when
|
||||
final CollectionWithPagingInfo<Category> actualCategoriesPage = objectUnderTest.readAll(CONTENT_ID, parametersMock);
|
||||
|
||||
then(categoriesMock).should().listCategoriesForNode(CONTENT_ID);
|
||||
then(categoriesMock).should().listCategoriesForNode(CONTENT_ID, parametersMock);
|
||||
then(categoriesMock).shouldHaveNoMoreInteractions();
|
||||
assertThat(actualCategoriesPage)
|
||||
.isNotNull()
|
||||
@@ -77,15 +78,25 @@ public class NodesCategoryLinksRelationTest
|
||||
@Test
|
||||
public void testCreate()
|
||||
{
|
||||
given(categoriesMock.linkNodeToCategories(any(), any())).willReturn(List.of(categoryMock));
|
||||
given(categoriesMock.linkNodeToCategories(any(), any(), any())).willReturn(List.of(categoryMock));
|
||||
|
||||
// when
|
||||
final List<Category> actualCategories = objectUnderTest.create(CONTENT_ID, List.of(categoryMock), parametersMock);
|
||||
|
||||
then(categoriesMock).should().linkNodeToCategories(CONTENT_ID, List.of(categoryMock));
|
||||
then(categoriesMock).should().linkNodeToCategories(CONTENT_ID, List.of(categoryMock), parametersMock);
|
||||
then(categoriesMock).shouldHaveNoMoreInteractions();
|
||||
assertThat(actualCategories)
|
||||
.isNotNull()
|
||||
.isEqualTo(List.of(categoryMock));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDelete()
|
||||
{
|
||||
// when
|
||||
objectUnderTest.delete(CONTENT_ID, CATEGORY_ID, parametersMock);
|
||||
|
||||
then(categoriesMock).should().unlinkNodeFromCategory(CONTENT_ID, CATEGORY_ID, parametersMock);
|
||||
then(categoriesMock).shouldHaveNoMoreInteractions();
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
* #%L
|
||||
* Alfresco Remote API
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2022 Alfresco Software Limited
|
||||
* Copyright (C) 2005 - 2023 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
@@ -26,7 +26,10 @@
|
||||
|
||||
package org.alfresco.rest.api.categories;
|
||||
|
||||
import static org.alfresco.service.cmr.repository.StoreRef.STORE_REF_WORKSPACE_SPACESSTORE;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyBoolean;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.BDDMockito.then;
|
||||
|
||||
@@ -37,8 +40,8 @@ import java.util.stream.IntStream;
|
||||
import org.alfresco.rest.api.Categories;
|
||||
import org.alfresco.rest.api.model.Category;
|
||||
import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo;
|
||||
import org.alfresco.rest.framework.resource.parameters.Paging;
|
||||
import org.alfresco.rest.framework.resource.parameters.Parameters;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.InjectMocks;
|
||||
@@ -67,39 +70,37 @@ public class SubcategoriesRelationTest
|
||||
final Category categoryToCreate = Category.builder().name(CATEGORY_NAME).create();
|
||||
final Category category = Category.builder().name(CATEGORY_NAME).parentId(PARENT_CATEGORY_ID).hasChildren(false).id(CATEGORY_ID).create();
|
||||
final List<Category> categoriesToCreate = List.of(categoryToCreate);
|
||||
given(categoriesMock.createSubcategories(PARENT_CATEGORY_ID, categoriesToCreate, parametersMock)).willReturn(List.of(category));
|
||||
given(categoriesMock.createSubcategories(any(), any(), any())).willCallRealMethod();
|
||||
given(categoriesMock.createSubcategories(any(), any(), any(), any())).willReturn(List.of(category));
|
||||
|
||||
//when
|
||||
List<Category> categories = objectUnderTest.create(PARENT_CATEGORY_ID, categoriesToCreate, parametersMock);
|
||||
|
||||
then(categoriesMock).should().createSubcategories(PARENT_CATEGORY_ID, categoriesToCreate, parametersMock);
|
||||
then(categoriesMock).shouldHaveNoMoreInteractions();
|
||||
then(categoriesMock).should().createSubcategories(STORE_REF_WORKSPACE_SPACESSTORE, PARENT_CATEGORY_ID, categoriesToCreate, parametersMock);
|
||||
assertEquals(List.of(category), categories);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetCategoryChildren() {
|
||||
final CollectionWithPagingInfo<Category> categoryChildren = getCategories(3);
|
||||
given(categoriesMock.getCategoryChildren(PARENT_CATEGORY_ID, parametersMock)).willReturn(categoryChildren);
|
||||
final List<Category> categoryChildren = getCategories(3);
|
||||
given(categoriesMock.getCategoryChildren(any(), any())).willCallRealMethod();
|
||||
given(categoriesMock.getCategoryChildren(any(), any(), any())).willReturn(categoryChildren);
|
||||
|
||||
//when
|
||||
final CollectionWithPagingInfo<Category> returnedChildren = objectUnderTest.readAll(PARENT_CATEGORY_ID, parametersMock);
|
||||
|
||||
then(categoriesMock).should().getCategoryChildren(PARENT_CATEGORY_ID, parametersMock);
|
||||
then(categoriesMock).shouldHaveNoMoreInteractions();
|
||||
assertEquals(categoryChildren, returnedChildren);
|
||||
then(categoriesMock).should().getCategoryChildren(STORE_REF_WORKSPACE_SPACESSTORE, PARENT_CATEGORY_ID, parametersMock);
|
||||
assertEquals(categoryChildren, returnedChildren.getCollection());
|
||||
}
|
||||
|
||||
private CollectionWithPagingInfo<Category> getCategories(final int count)
|
||||
private List<Category> getCategories(final int count)
|
||||
{
|
||||
return CollectionWithPagingInfo.asPaged(Paging.DEFAULT,
|
||||
IntStream.range(0, count)
|
||||
.mapToObj(i -> Category.builder().name(SUBCATEGORY_NAME_PREFIX + "-" + i)
|
||||
.parentId(PARENT_CATEGORY_ID)
|
||||
.hasChildren(false)
|
||||
.id(CATEGORY_ID + "-" + i)
|
||||
.create())
|
||||
.collect(Collectors.toList())
|
||||
);
|
||||
return IntStream.range(0, count)
|
||||
.mapToObj(i -> Category.builder().name(SUBCATEGORY_NAME_PREFIX + "-" + i)
|
||||
.parentId(PARENT_CATEGORY_ID)
|
||||
.hasChildren(false)
|
||||
.id(CATEGORY_ID + "-" + i)
|
||||
.create())
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,11 +27,13 @@
|
||||
package org.alfresco.rest.api.impl;
|
||||
|
||||
import static org.alfresco.rest.api.Nodes.PATH_ROOT;
|
||||
import static org.alfresco.rest.api.impl.CategoriesImpl.INCLUDE_COUNT_PARAM;
|
||||
import static org.alfresco.rest.api.impl.CategoriesImpl.INVALID_NODE_TYPE;
|
||||
import static org.alfresco.rest.api.impl.CategoriesImpl.NOT_A_VALID_CATEGORY;
|
||||
import static org.alfresco.rest.api.impl.CategoriesImpl.NOT_NULL_OR_EMPTY;
|
||||
import static org.alfresco.rest.api.impl.CategoriesImpl.NO_PERMISSION_TO_CHANGE_CONTENT;
|
||||
import static org.alfresco.rest.api.impl.CategoriesImpl.NO_PERMISSION_TO_READ_CONTENT;
|
||||
import static org.alfresco.service.cmr.repository.StoreRef.STORE_REF_WORKSPACE_SPACESSTORE;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
import static org.assertj.core.api.Assertions.catchThrowable;
|
||||
@@ -39,6 +41,7 @@ import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertThrows;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyBoolean;
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.BDDMockito.then;
|
||||
@@ -64,7 +67,6 @@ import org.alfresco.rest.framework.core.exceptions.EntityNotFoundException;
|
||||
import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException;
|
||||
import org.alfresco.rest.framework.core.exceptions.InvalidNodeTypeException;
|
||||
import org.alfresco.rest.framework.core.exceptions.PermissionDeniedException;
|
||||
import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo;
|
||||
import org.alfresco.rest.framework.resource.parameters.Parameters;
|
||||
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
@@ -77,6 +79,7 @@ import org.alfresco.service.cmr.security.PermissionService;
|
||||
import org.alfresco.service.namespace.NamespaceService;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.alfresco.service.namespace.RegexQNamePattern;
|
||||
import org.alfresco.util.Pair;
|
||||
import org.alfresco.util.TypeConstraint;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.junit.Before;
|
||||
@@ -94,7 +97,7 @@ public class CategoriesImplTest
|
||||
private static final String PARENT_ID = "parent-node-id";
|
||||
private static final String CAT_ROOT_NODE_ID = "cat-root-node-id";
|
||||
private static final NodeRef CATEGORY_NODE_REF = createNodeRefWithId(CATEGORY_ID);
|
||||
private static final Category CATEGORY = createDefaultCategoryWithName(CATEGORY_NAME);
|
||||
private static final Category CATEGORY = createDefaultCategory();
|
||||
private static final String CONTENT_NODE_ID = "content-node-id";
|
||||
private static final NodeRef CONTENT_NODE_REF = createNodeRefWithId(CONTENT_NODE_ID);
|
||||
|
||||
@@ -103,8 +106,6 @@ public class CategoriesImplTest
|
||||
@Mock
|
||||
private NodeService nodeServiceMock;
|
||||
@Mock
|
||||
private Parameters parametersMock;
|
||||
@Mock
|
||||
private AuthorityService authorityServiceMock;
|
||||
@Mock
|
||||
private CategoryService categoryServiceMock;
|
||||
@@ -116,6 +117,8 @@ public class CategoriesImplTest
|
||||
private PermissionService permissionServiceMock;
|
||||
@Mock
|
||||
private TypeConstraint typeConstraint;
|
||||
@Mock
|
||||
private Parameters parametersMock;
|
||||
|
||||
@InjectMocks
|
||||
private CategoriesImpl objectUnderTest;
|
||||
@@ -135,7 +138,7 @@ public class CategoriesImplTest
|
||||
@Test
|
||||
public void shouldNotGetRootCategoryById()
|
||||
{
|
||||
final NodeRef categoryRootNodeRef = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, CAT_ROOT_NODE_ID);
|
||||
final NodeRef categoryRootNodeRef = createNodeRefWithId(CAT_ROOT_NODE_ID);
|
||||
given(nodesMock.validateNode(CAT_ROOT_NODE_ID)).willReturn(categoryRootNodeRef);
|
||||
given(categoryChildAssociationRefMock.getQName()).willReturn(ContentModel.ASPECT_GEN_CLASSIFIABLE);
|
||||
given(nodeServiceMock.getParentAssocs(categoryRootNodeRef)).willReturn(List.of(categoryChildAssociationRefMock));
|
||||
@@ -155,31 +158,26 @@ public class CategoriesImplTest
|
||||
@Test
|
||||
public void testGetCategoryById_withChildren()
|
||||
{
|
||||
final NodeRef categoryNodeRef = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, CATEGORY_ID);
|
||||
given(nodesMock.validateNode(CATEGORY_ID)).willReturn(categoryNodeRef);
|
||||
final Node categoryNode = new Node();
|
||||
categoryNode.setName(CATEGORY_NAME);
|
||||
categoryNode.setNodeId(CATEGORY_ID);
|
||||
final NodeRef parentNodeRef = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, PARENT_ID);
|
||||
categoryNode.setParentId(parentNodeRef);
|
||||
final NodeRef parentNodeRef = createNodeRefWithId(PARENT_ID);
|
||||
final Node categoryNode = createNode(CATEGORY_NAME, CATEGORY_ID, parentNodeRef);
|
||||
given(nodesMock.getNode(CATEGORY_ID)).willReturn(categoryNode);
|
||||
final ChildAssociationRef parentAssoc = new ChildAssociationRef(null, parentNodeRef, null, categoryNodeRef);
|
||||
given(nodeServiceMock.getPrimaryParent(categoryNodeRef)).willReturn(parentAssoc);
|
||||
final ChildAssociationRef parentAssoc = new ChildAssociationRef(null, parentNodeRef, null, CATEGORY_NODE_REF);
|
||||
given(nodeServiceMock.getPrimaryParent(CATEGORY_NODE_REF)).willReturn(parentAssoc);
|
||||
final List<ChildAssociationRef> dummyChildren = List.of(dummyChildAssociationRefMock);
|
||||
given(nodeServiceMock.getChildAssocs(categoryNodeRef, RegexQNamePattern.MATCH_ALL, RegexQNamePattern.MATCH_ALL, false))
|
||||
given(nodeServiceMock.getChildAssocs(CATEGORY_NODE_REF, RegexQNamePattern.MATCH_ALL, RegexQNamePattern.MATCH_ALL, false))
|
||||
.willReturn(dummyChildren);
|
||||
//when
|
||||
final Category category = objectUnderTest.getCategoryById(CATEGORY_ID, parametersMock);
|
||||
|
||||
then(nodesMock).should().validateNode(CATEGORY_ID);
|
||||
then(nodesMock).should().isSubClass(categoryNodeRef, ContentModel.TYPE_CATEGORY, false);
|
||||
then(nodesMock).should().isSubClass(CATEGORY_NODE_REF, ContentModel.TYPE_CATEGORY, false);
|
||||
then(nodesMock).should().getNode(CATEGORY_ID);
|
||||
then(nodesMock).shouldHaveNoMoreInteractions();
|
||||
|
||||
then(nodeServiceMock).should().getPrimaryParent(categoryNodeRef);
|
||||
then(nodeServiceMock).should().getPrimaryParent(CATEGORY_NODE_REF);
|
||||
then(nodeServiceMock).should().getParentAssocs(parentNodeRef);
|
||||
then(nodeServiceMock).should().getParentAssocs(categoryNodeRef);
|
||||
then(nodeServiceMock).should().getChildAssocs(categoryNodeRef, RegexQNamePattern.MATCH_ALL, RegexQNamePattern.MATCH_ALL, false);
|
||||
then(nodeServiceMock).should().getParentAssocs(CATEGORY_NODE_REF);
|
||||
then(nodeServiceMock).should().getChildAssocs(CATEGORY_NODE_REF, RegexQNamePattern.MATCH_ALL, RegexQNamePattern.MATCH_ALL, false);
|
||||
then(nodeServiceMock).shouldHaveNoMoreInteractions();
|
||||
|
||||
then(categoryServiceMock).shouldHaveNoInteractions();
|
||||
@@ -197,30 +195,25 @@ public class CategoriesImplTest
|
||||
@Test
|
||||
public void testGetCategoryById_withoutChildren()
|
||||
{
|
||||
final NodeRef categoryNodeRef = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, CATEGORY_ID);
|
||||
given(nodesMock.validateNode(CATEGORY_ID)).willReturn(categoryNodeRef);
|
||||
final Node categoryNode = new Node();
|
||||
categoryNode.setName(CATEGORY_NAME);
|
||||
categoryNode.setNodeId(CATEGORY_ID);
|
||||
final NodeRef parentNodeRef = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, PARENT_ID);
|
||||
categoryNode.setParentId(parentNodeRef);
|
||||
final NodeRef parentNodeRef = createNodeRefWithId(PARENT_ID);
|
||||
final Node categoryNode = createNode(CATEGORY_NAME, CATEGORY_ID, parentNodeRef);
|
||||
given(nodesMock.getNode(CATEGORY_ID)).willReturn(categoryNode);
|
||||
final ChildAssociationRef parentAssoc = new ChildAssociationRef(null, parentNodeRef, null, categoryNodeRef);
|
||||
given(nodeServiceMock.getPrimaryParent(categoryNodeRef)).willReturn(parentAssoc);
|
||||
given(nodeServiceMock.getChildAssocs(categoryNodeRef, RegexQNamePattern.MATCH_ALL, RegexQNamePattern.MATCH_ALL, false))
|
||||
final ChildAssociationRef parentAssoc = new ChildAssociationRef(null, parentNodeRef, null, CATEGORY_NODE_REF);
|
||||
given(nodeServiceMock.getPrimaryParent(CATEGORY_NODE_REF)).willReturn(parentAssoc);
|
||||
given(nodeServiceMock.getChildAssocs(CATEGORY_NODE_REF, RegexQNamePattern.MATCH_ALL, RegexQNamePattern.MATCH_ALL, false))
|
||||
.willReturn(Collections.emptyList());
|
||||
//when
|
||||
final Category category = objectUnderTest.getCategoryById(CATEGORY_ID, parametersMock);
|
||||
|
||||
then(nodesMock).should().validateNode(CATEGORY_ID);
|
||||
then(nodesMock).should().isSubClass(categoryNodeRef, ContentModel.TYPE_CATEGORY, false);
|
||||
then(nodesMock).should().isSubClass(CATEGORY_NODE_REF, ContentModel.TYPE_CATEGORY, false);
|
||||
then(nodesMock).should().getNode(CATEGORY_ID);
|
||||
then(nodesMock).shouldHaveNoMoreInteractions();
|
||||
|
||||
then(nodeServiceMock).should().getPrimaryParent(categoryNodeRef);
|
||||
then(nodeServiceMock).should().getPrimaryParent(CATEGORY_NODE_REF);
|
||||
then(nodeServiceMock).should().getParentAssocs(parentNodeRef);
|
||||
then(nodeServiceMock).should().getParentAssocs(categoryNodeRef);
|
||||
then(nodeServiceMock).should().getChildAssocs(categoryNodeRef, RegexQNamePattern.MATCH_ALL, RegexQNamePattern.MATCH_ALL, false);
|
||||
then(nodeServiceMock).should().getParentAssocs(CATEGORY_NODE_REF);
|
||||
then(nodeServiceMock).should().getChildAssocs(CATEGORY_NODE_REF, RegexQNamePattern.MATCH_ALL, RegexQNamePattern.MATCH_ALL, false);
|
||||
then(nodeServiceMock).shouldHaveNoMoreInteractions();
|
||||
|
||||
then(categoryServiceMock).shouldHaveNoInteractions();
|
||||
@@ -235,6 +228,30 @@ public class CategoriesImplTest
|
||||
assertEquals(expectedCategory, category);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetCategoryById_includeCount()
|
||||
{
|
||||
final QName categoryQName = createCmQNameOf(CATEGORY_NAME);
|
||||
final NodeRef parentCategoryNodeRef = createNodeRefWithId(PARENT_ID);
|
||||
final ChildAssociationRef parentAssociation = createAssociationOf(parentCategoryNodeRef, CATEGORY_NODE_REF, categoryQName);
|
||||
given(nodesMock.getNode(any())).willReturn(createNode());
|
||||
given(nodeServiceMock.getPrimaryParent(any())).willReturn(parentAssociation);
|
||||
given(parametersMock.getInclude()).willReturn(List.of(INCLUDE_COUNT_PARAM));
|
||||
given(categoryServiceMock.getTopCategories(any(), any(), anyInt())).willReturn(List.of(new Pair<>(CATEGORY_NODE_REF, 1)));
|
||||
|
||||
// when
|
||||
final Category actualCategory = objectUnderTest.getCategoryById(CATEGORY_ID, parametersMock);
|
||||
|
||||
then(categoryServiceMock).should().getTopCategories(STORE_REF_WORKSPACE_SPACESSTORE, ContentModel.ASPECT_GEN_CLASSIFIABLE, Integer.MAX_VALUE);
|
||||
then(categoryServiceMock).shouldHaveNoMoreInteractions();
|
||||
|
||||
assertThat(actualCategory)
|
||||
.isNotNull()
|
||||
.extracting(Category::getCount)
|
||||
.isNotNull()
|
||||
.isEqualTo(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetCategoryById_notACategory()
|
||||
{
|
||||
@@ -274,14 +291,9 @@ public class CategoriesImplTest
|
||||
public void testDeleteCategoryById_asAdmin()
|
||||
{
|
||||
given(authorityServiceMock.hasAdminAuthority()).willReturn(true);
|
||||
final NodeRef categoryNodeRef = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, CATEGORY_ID);
|
||||
final NodeRef categoryNodeRef = createNodeRefWithId(CATEGORY_ID);
|
||||
given(nodesMock.validateNode(CATEGORY_ID)).willReturn(categoryNodeRef);
|
||||
given(nodesMock.isSubClass(categoryNodeRef, ContentModel.TYPE_CATEGORY, false)).willReturn(true);
|
||||
final Node categoryNode = new Node();
|
||||
categoryNode.setName(CATEGORY_NAME);
|
||||
categoryNode.setNodeId(CATEGORY_ID);
|
||||
final NodeRef parentNodeRef = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, PARENT_ID);
|
||||
categoryNode.setParentId(parentNodeRef);
|
||||
|
||||
//when
|
||||
objectUnderTest.deleteCategoryById(CATEGORY_ID, parametersMock);
|
||||
@@ -317,7 +329,7 @@ public class CategoriesImplTest
|
||||
public void testDeleteCategoryById_nonCategoryId()
|
||||
{
|
||||
given(authorityServiceMock.hasAdminAuthority()).willReturn(true);
|
||||
final NodeRef categoryNodeRef = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, CATEGORY_ID);
|
||||
final NodeRef categoryNodeRef = createNodeRefWithId(CATEGORY_ID);
|
||||
given(nodesMock.validateNode(CATEGORY_ID)).willReturn(categoryNodeRef);
|
||||
given(nodesMock.isSubClass(categoryNodeRef, ContentModel.TYPE_CATEGORY, false)).willReturn(false);
|
||||
|
||||
@@ -336,7 +348,7 @@ public class CategoriesImplTest
|
||||
public void testDeleteCategoryById_rootCategory()
|
||||
{
|
||||
given(authorityServiceMock.hasAdminAuthority()).willReturn(true);
|
||||
final NodeRef categoryRootNodeRef = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, CAT_ROOT_NODE_ID);
|
||||
final NodeRef categoryRootNodeRef = createNodeRefWithId(CAT_ROOT_NODE_ID);
|
||||
given(nodesMock.validateNode(CAT_ROOT_NODE_ID)).willReturn(categoryRootNodeRef);
|
||||
given(nodesMock.isSubClass(categoryRootNodeRef, ContentModel.TYPE_CATEGORY, false)).willReturn(true);
|
||||
given(categoryChildAssociationRefMock.getQName()).willReturn(ContentModel.ASPECT_GEN_CLASSIFIABLE);
|
||||
@@ -359,13 +371,13 @@ public class CategoriesImplTest
|
||||
@Test
|
||||
public void testCreateCategoryUnderRoot()
|
||||
{
|
||||
final NodeRef parentCategoryNodeRef = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, PATH_ROOT);
|
||||
final NodeRef parentCategoryNodeRef = createNodeRefWithId(PATH_ROOT);
|
||||
given(categoryServiceMock.getRootCategoryNodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE))
|
||||
.willReturn(Optional.of(parentCategoryNodeRef));
|
||||
final NodeRef categoryNodeRef = createNodeRefWithId(CATEGORY_ID);
|
||||
given(categoryServiceMock.createCategory(parentCategoryNodeRef, CATEGORY_NAME)).willReturn(categoryNodeRef);
|
||||
given(nodesMock.getNode(CATEGORY_ID)).willReturn(prepareCategoryNode());
|
||||
final ChildAssociationRef parentAssoc = new ChildAssociationRef(null, parentCategoryNodeRef, null, categoryNodeRef);
|
||||
given(nodesMock.getNode(CATEGORY_ID)).willReturn(createNode());
|
||||
final ChildAssociationRef parentAssoc = createAssociationOf(parentCategoryNodeRef, categoryNodeRef);
|
||||
given(nodeServiceMock.getPrimaryParent(categoryNodeRef)).willReturn(parentAssoc);
|
||||
given(nodeServiceMock.getParentAssocs(parentCategoryNodeRef)).willReturn(List.of(parentAssoc));
|
||||
given(nodeServiceMock.getChildAssocs(categoryNodeRef, RegexQNamePattern.MATCH_ALL, RegexQNamePattern.MATCH_ALL, false))
|
||||
@@ -400,12 +412,12 @@ public class CategoriesImplTest
|
||||
@Test
|
||||
public void testCreateCategory()
|
||||
{
|
||||
final NodeRef parentCategoryNodeRef = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, PARENT_ID);
|
||||
final NodeRef parentCategoryNodeRef = createNodeRefWithId(PARENT_ID);
|
||||
given(nodesMock.validateNode(PARENT_ID)).willReturn(parentCategoryNodeRef);
|
||||
final NodeRef categoryNodeRef = createNodeRefWithId(CATEGORY_ID);
|
||||
given(categoryServiceMock.createCategory(parentCategoryNodeRef, CATEGORY_NAME)).willReturn(categoryNodeRef);
|
||||
given(nodesMock.getNode(CATEGORY_ID)).willReturn(prepareCategoryNode());
|
||||
final ChildAssociationRef parentAssoc = new ChildAssociationRef(null, parentCategoryNodeRef, null, categoryNodeRef);
|
||||
given(nodesMock.getNode(CATEGORY_ID)).willReturn(createNode());
|
||||
final ChildAssociationRef parentAssoc = createAssociationOf(parentCategoryNodeRef, categoryNodeRef);
|
||||
given(nodeServiceMock.getPrimaryParent(categoryNodeRef)).willReturn(parentAssoc);
|
||||
given(nodeServiceMock.getParentAssocs(parentCategoryNodeRef)).willReturn(List.of(parentAssoc));
|
||||
given(nodeServiceMock.getChildAssocs(categoryNodeRef, RegexQNamePattern.MATCH_ALL, RegexQNamePattern.MATCH_ALL, false))
|
||||
@@ -438,6 +450,35 @@ public class CategoriesImplTest
|
||||
assertEquals(expectedCategory, createdCategory);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateCategory_includeCount()
|
||||
{
|
||||
final QName categoryQName = createCmQNameOf(CATEGORY_NAME);
|
||||
final NodeRef categoryNodeRef = createNodeRefWithId(CATEGORY_ID);
|
||||
final NodeRef parentCategoryNodeRef = createNodeRefWithId(PARENT_ID);
|
||||
final ChildAssociationRef parentAssociation = createAssociationOf(parentCategoryNodeRef, CATEGORY_NODE_REF, categoryQName);
|
||||
given(nodesMock.validateNode(PARENT_ID)).willReturn(parentCategoryNodeRef);
|
||||
given(categoryServiceMock.createCategory(parentCategoryNodeRef, CATEGORY_NAME)).willReturn(categoryNodeRef);
|
||||
given(nodesMock.getNode(any())).willReturn(createNode());
|
||||
given(nodeServiceMock.getPrimaryParent(any())).willReturn(parentAssociation);
|
||||
given(parametersMock.getInclude()).willReturn(List.of(INCLUDE_COUNT_PARAM));
|
||||
final List<Category> categoryModels = prepareCategories().stream().peek(category -> category.setCount(1)).collect(Collectors.toList());
|
||||
|
||||
// when
|
||||
final List<Category> actualCreatedCategories = objectUnderTest.createSubcategories(PARENT_ID, categoryModels, parametersMock);
|
||||
|
||||
then(categoryServiceMock).should().createCategory(any(), any());
|
||||
then(categoryServiceMock).shouldHaveNoMoreInteractions();
|
||||
|
||||
assertThat(actualCreatedCategories)
|
||||
.isNotNull()
|
||||
.hasSize(1)
|
||||
.element(0)
|
||||
.extracting(Category::getCount)
|
||||
.isNotNull()
|
||||
.isEqualTo(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateCategories_noPermissions()
|
||||
{
|
||||
@@ -494,7 +535,7 @@ public class CategoriesImplTest
|
||||
@Test
|
||||
public void testGetRootCategoryChildren()
|
||||
{
|
||||
final NodeRef parentCategoryNodeRef = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, PATH_ROOT);
|
||||
final NodeRef parentCategoryNodeRef = createNodeRefWithId(PATH_ROOT);
|
||||
given(categoryServiceMock.getRootCategoryNodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE))
|
||||
.willReturn(Optional.of(parentCategoryNodeRef));
|
||||
final int childrenCount = 3;
|
||||
@@ -503,7 +544,7 @@ public class CategoriesImplTest
|
||||
childAssociationRefMocks.forEach(this::prepareCategoryNodeMocks);
|
||||
|
||||
//when
|
||||
final CollectionWithPagingInfo<Category> categoryChildren = objectUnderTest.getCategoryChildren(PATH_ROOT, parametersMock);
|
||||
final List<Category> categoryChildren = objectUnderTest.getCategoryChildren(PATH_ROOT, parametersMock);
|
||||
|
||||
then(categoryServiceMock).should().getRootCategoryNodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE);
|
||||
then(categoryServiceMock).shouldHaveNoMoreInteractions();
|
||||
@@ -521,16 +562,14 @@ public class CategoriesImplTest
|
||||
|
||||
then(authorityServiceMock).shouldHaveNoInteractions();
|
||||
|
||||
assertEquals(childAssociationRefMocks.size(), categoryChildren.getTotalItems().intValue());
|
||||
final List<Category> categoryChildrenList = new ArrayList<>(categoryChildren.getCollection());
|
||||
assertEquals(childAssociationRefMocks.size(), categoryChildrenList.size());
|
||||
IntStream.range(0, childrenCount).forEach(i -> doCategoryAssertions(categoryChildrenList.get(i), i, PATH_ROOT));
|
||||
assertEquals(childAssociationRefMocks.size(), categoryChildren.size());
|
||||
IntStream.range(0, childrenCount).forEach(i -> doCategoryAssertions(categoryChildren.get(i), i, PATH_ROOT));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetCategoryChildren()
|
||||
{
|
||||
final NodeRef parentCategoryNodeRef = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, PARENT_ID);
|
||||
final NodeRef parentCategoryNodeRef = createNodeRefWithId(PARENT_ID);
|
||||
given(nodesMock.validateNode(PARENT_ID)).willReturn(parentCategoryNodeRef);
|
||||
given(nodesMock.isSubClass(parentCategoryNodeRef, ContentModel.TYPE_CATEGORY, false)).willReturn(true);
|
||||
final int childrenCount = 3;
|
||||
@@ -539,7 +578,7 @@ public class CategoriesImplTest
|
||||
childAssociationRefMocks.forEach(this::prepareCategoryNodeMocks);
|
||||
|
||||
//when
|
||||
final CollectionWithPagingInfo<Category> categoryChildren = objectUnderTest.getCategoryChildren(PARENT_ID, parametersMock);
|
||||
final List<Category> categoryChildren = objectUnderTest.getCategoryChildren(PARENT_ID, parametersMock);
|
||||
|
||||
then(nodesMock).should().validateNode(PARENT_ID);
|
||||
then(nodesMock).should().isSubClass(parentCategoryNodeRef, ContentModel.TYPE_CATEGORY, false);
|
||||
@@ -558,24 +597,47 @@ public class CategoriesImplTest
|
||||
then(authorityServiceMock).shouldHaveNoInteractions();
|
||||
then(categoryServiceMock).shouldHaveNoInteractions();
|
||||
|
||||
assertEquals(childAssociationRefMocks.size(), categoryChildren.getTotalItems().intValue());
|
||||
final List<Category> categoryChildrenList = new ArrayList<>(categoryChildren.getCollection());
|
||||
assertEquals(childAssociationRefMocks.size(), categoryChildrenList.size());
|
||||
IntStream.range(0, childrenCount).forEach(i -> doCategoryAssertions(categoryChildrenList.get(i), i, PARENT_ID));
|
||||
assertEquals(childAssociationRefMocks.size(), categoryChildren.size());
|
||||
IntStream.range(0, childrenCount).forEach(i -> doCategoryAssertions(categoryChildren.get(i), i, PARENT_ID));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetCategoryChildren_includeCount()
|
||||
{
|
||||
final NodeRef parentCategoryNodeRef = createNodeRefWithId(PARENT_ID);
|
||||
given(nodesMock.validateNode(PARENT_ID)).willReturn(parentCategoryNodeRef);
|
||||
given(nodesMock.isSubClass(parentCategoryNodeRef, ContentModel.TYPE_CATEGORY, false)).willReturn(true);
|
||||
final int childrenCount = 3;
|
||||
final List<ChildAssociationRef> childAssociationRefMocks = prepareChildAssocMocks(childrenCount, parentCategoryNodeRef);
|
||||
given(nodeServiceMock.getChildAssocs(parentCategoryNodeRef)).willReturn(childAssociationRefMocks);
|
||||
childAssociationRefMocks.forEach(this::prepareCategoryNodeMocks);
|
||||
given(parametersMock.getInclude()).willReturn(List.of(INCLUDE_COUNT_PARAM));
|
||||
given(categoryServiceMock.getTopCategories(any(), any(), anyInt())).willReturn(List.of(new Pair<>(createNodeRefWithId(CATEGORY_ID.concat("-1")), 2)));
|
||||
|
||||
// when
|
||||
final List<Category> actualCategoryChildren = objectUnderTest.getCategoryChildren(PARENT_ID, parametersMock);
|
||||
|
||||
then(categoryServiceMock).should().getTopCategories(STORE_REF_WORKSPACE_SPACESSTORE, ContentModel.ASPECT_GEN_CLASSIFIABLE, Integer.MAX_VALUE);
|
||||
then(categoryServiceMock).shouldHaveNoMoreInteractions();
|
||||
|
||||
assertThat(actualCategoryChildren)
|
||||
.isNotNull()
|
||||
.hasSize(3)
|
||||
.extracting(Category::getCount)
|
||||
.isNotNull()
|
||||
.isEqualTo(List.of(0, 2, 0));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetCategoryChildren_noChildren()
|
||||
{
|
||||
final NodeRef parentCategoryNodeRef = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, PARENT_ID);
|
||||
final NodeRef parentCategoryNodeRef = createNodeRefWithId(PARENT_ID);
|
||||
given(nodesMock.validateNode(PARENT_ID)).willReturn(parentCategoryNodeRef);
|
||||
given(nodesMock.isSubClass(parentCategoryNodeRef, ContentModel.TYPE_CATEGORY, false)).willReturn(true);
|
||||
|
||||
given(nodeServiceMock.getChildAssocs(parentCategoryNodeRef)).willReturn(Collections.emptyList());
|
||||
|
||||
|
||||
//when
|
||||
final CollectionWithPagingInfo<Category> categoryChildren = objectUnderTest.getCategoryChildren(PARENT_ID, parametersMock);
|
||||
final List<Category> categoryChildren = objectUnderTest.getCategoryChildren(PARENT_ID, parametersMock);
|
||||
|
||||
then(nodesMock).should().validateNode(PARENT_ID);
|
||||
then(nodesMock).should().isSubClass(parentCategoryNodeRef, ContentModel.TYPE_CATEGORY, false);
|
||||
@@ -586,13 +648,13 @@ public class CategoriesImplTest
|
||||
then(authorityServiceMock).shouldHaveNoInteractions();
|
||||
then(categoryServiceMock).shouldHaveNoInteractions();
|
||||
|
||||
assertEquals(0, categoryChildren.getTotalItems().intValue());
|
||||
assertEquals(0, categoryChildren.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetCategoryChildren_wrongParentNodeType()
|
||||
{
|
||||
final NodeRef parentCategoryNodeRef = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, PARENT_ID);
|
||||
final NodeRef parentCategoryNodeRef = createNodeRefWithId(PARENT_ID);
|
||||
given(nodesMock.validateNode(PARENT_ID)).willReturn(parentCategoryNodeRef);
|
||||
given(nodesMock.isSubClass(parentCategoryNodeRef, ContentModel.TYPE_CATEGORY, false)).willReturn(false);
|
||||
|
||||
@@ -633,12 +695,12 @@ public class CategoriesImplTest
|
||||
final QName categoryQName = createCmQNameOf(CATEGORY_NAME);
|
||||
final NodeRef parentCategoryNodeRef = createNodeRefWithId(PARENT_ID);
|
||||
final ChildAssociationRef parentAssociation = createAssociationOf(parentCategoryNodeRef, CATEGORY_NODE_REF, categoryQName);
|
||||
given(nodesMock.getNode(any())).willReturn(prepareCategoryNode(categoryNewName));
|
||||
given(nodesMock.getNode(any())).willReturn(createNode(categoryNewName));
|
||||
given(nodeServiceMock.getPrimaryParent(any())).willReturn(parentAssociation);
|
||||
given(nodeServiceMock.moveNode(any(), any(), any(), any())).willReturn(createAssociationOf(parentCategoryNodeRef, CATEGORY_NODE_REF, createCmQNameOf(categoryNewName)));
|
||||
|
||||
// when
|
||||
final Category actualCategory = objectUnderTest.updateCategoryById(CATEGORY_ID, fixedCategory);
|
||||
final Category actualCategory = objectUnderTest.updateCategoryById(CATEGORY_ID, fixedCategory, parametersMock);
|
||||
|
||||
then(authorityServiceMock).should().hasAdminAuthority();
|
||||
then(authorityServiceMock).shouldHaveNoMoreInteractions();
|
||||
@@ -661,13 +723,41 @@ public class CategoriesImplTest
|
||||
.isEqualTo(expectedCategory);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateCategoryById_includeCount()
|
||||
{
|
||||
final String categoryNewName = "categoryNewName";
|
||||
final Category fixedCategory = createCategoryOnlyWithName(categoryNewName);
|
||||
fixedCategory.setCount(9);
|
||||
final QName categoryQName = createCmQNameOf(CATEGORY_NAME);
|
||||
final NodeRef parentCategoryNodeRef = createNodeRefWithId(PARENT_ID);
|
||||
final ChildAssociationRef parentAssociation = createAssociationOf(parentCategoryNodeRef, CATEGORY_NODE_REF, categoryQName);
|
||||
given(nodesMock.getNode(any())).willReturn(createNode(categoryNewName));
|
||||
given(nodeServiceMock.getPrimaryParent(any())).willReturn(parentAssociation);
|
||||
given(nodeServiceMock.moveNode(any(), any(), any(), any())).willReturn(createAssociationOf(parentCategoryNodeRef, CATEGORY_NODE_REF, createCmQNameOf(categoryNewName)));
|
||||
given(parametersMock.getInclude()).willReturn(List.of(INCLUDE_COUNT_PARAM));
|
||||
given(categoryServiceMock.getTopCategories(any(), any(), anyInt())).willReturn(List.of(new Pair<>(CATEGORY_NODE_REF, 1)));
|
||||
|
||||
// when
|
||||
final Category actualCategory = objectUnderTest.updateCategoryById(CATEGORY_ID, fixedCategory, parametersMock);
|
||||
|
||||
then(categoryServiceMock).should().getTopCategories(STORE_REF_WORKSPACE_SPACESSTORE, ContentModel.ASPECT_GEN_CLASSIFIABLE, Integer.MAX_VALUE);
|
||||
then(categoryServiceMock).shouldHaveNoMoreInteractions();
|
||||
|
||||
assertThat(actualCategory)
|
||||
.isNotNull()
|
||||
.extracting(Category::getCount)
|
||||
.isNotNull()
|
||||
.isEqualTo(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateCategoryById_noPermission()
|
||||
{
|
||||
given(authorityServiceMock.hasAdminAuthority()).willReturn(false);
|
||||
|
||||
// when
|
||||
assertThatExceptionOfType(PermissionDeniedException.class).isThrownBy(() -> objectUnderTest.updateCategoryById(CATEGORY_ID, CATEGORY));
|
||||
assertThatExceptionOfType(PermissionDeniedException.class).isThrownBy(() -> objectUnderTest.updateCategoryById(CATEGORY_ID, CATEGORY, parametersMock));
|
||||
|
||||
then(nodesMock).shouldHaveNoInteractions();
|
||||
then(nodeServiceMock).shouldHaveNoInteractions();
|
||||
@@ -679,7 +769,7 @@ public class CategoriesImplTest
|
||||
given(nodesMock.validateNode(any(String.class))).willThrow(EntityNotFoundException.class);
|
||||
|
||||
// when
|
||||
assertThatExceptionOfType(EntityNotFoundException.class).isThrownBy(() -> objectUnderTest.updateCategoryById(CATEGORY_ID, CATEGORY));
|
||||
assertThatExceptionOfType(EntityNotFoundException.class).isThrownBy(() -> objectUnderTest.updateCategoryById(CATEGORY_ID, CATEGORY, parametersMock));
|
||||
|
||||
then(nodeServiceMock).shouldHaveNoInteractions();
|
||||
}
|
||||
@@ -690,7 +780,7 @@ public class CategoriesImplTest
|
||||
given(nodesMock.isSubClass(any(), any(), eq(false))).willReturn(false);
|
||||
|
||||
// when
|
||||
assertThatExceptionOfType(InvalidArgumentException.class).isThrownBy(() -> objectUnderTest.updateCategoryById(CATEGORY_ID, CATEGORY))
|
||||
assertThatExceptionOfType(InvalidArgumentException.class).isThrownBy(() -> objectUnderTest.updateCategoryById(CATEGORY_ID, CATEGORY, parametersMock))
|
||||
.withMessageContaining(NOT_A_VALID_CATEGORY);
|
||||
|
||||
then(nodeServiceMock).shouldHaveNoInteractions();
|
||||
@@ -704,7 +794,7 @@ public class CategoriesImplTest
|
||||
given(categoryChildAssociationRefMock.getQName()).willReturn(ContentModel.ASPECT_GEN_CLASSIFIABLE);
|
||||
|
||||
// when
|
||||
assertThatExceptionOfType(InvalidArgumentException.class).isThrownBy(() -> objectUnderTest.updateCategoryById(PATH_ROOT, CATEGORY))
|
||||
assertThatExceptionOfType(InvalidArgumentException.class).isThrownBy(() -> objectUnderTest.updateCategoryById(PATH_ROOT, CATEGORY, parametersMock))
|
||||
.withMessageContaining(NOT_A_VALID_CATEGORY);
|
||||
|
||||
then(categoryServiceMock).should().getRootCategoryNodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE);
|
||||
@@ -727,7 +817,7 @@ public class CategoriesImplTest
|
||||
final Category categoryWithoutName = createCategoryOnlyWithName(invalidName);
|
||||
|
||||
// when
|
||||
assertThatExceptionOfType(InvalidArgumentException.class).isThrownBy(() -> objectUnderTest.updateCategoryById(CATEGORY_ID, categoryWithoutName))
|
||||
assertThatExceptionOfType(InvalidArgumentException.class).isThrownBy(() -> objectUnderTest.updateCategoryById(CATEGORY_ID, categoryWithoutName, parametersMock))
|
||||
.withMessageContaining(NOT_NULL_OR_EMPTY);
|
||||
}
|
||||
}
|
||||
@@ -741,12 +831,12 @@ public class CategoriesImplTest
|
||||
final QName categoryQName = createCmQNameOf(CATEGORY_NAME);
|
||||
final NodeRef parentCategoryNodeRef = createNodeRefWithId(PARENT_ID);
|
||||
final ChildAssociationRef parentAssociation = createAssociationOf(parentCategoryNodeRef, CATEGORY_NODE_REF, categoryQName);
|
||||
given(nodesMock.getNode(any())).willReturn(prepareCategoryNode(categoryNewName));
|
||||
given(nodesMock.getNode(any())).willReturn(createNode(categoryNewName));
|
||||
given(nodeServiceMock.getPrimaryParent(any())).willReturn(parentAssociation);
|
||||
given(nodeServiceMock.moveNode(any(), any(), any(), any())).willReturn(createAssociationOf(parentCategoryNodeRef, CATEGORY_NODE_REF, createCmQNameOf(categoryNewName)));
|
||||
|
||||
// when
|
||||
final Category actualCategory = objectUnderTest.updateCategoryById(CATEGORY_ID, categoryWithInvalidId);
|
||||
final Category actualCategory = objectUnderTest.updateCategoryById(CATEGORY_ID, categoryWithInvalidId, parametersMock);
|
||||
|
||||
final Category expectedCategory = createDefaultCategoryWithName(categoryNewName);
|
||||
assertThat(actualCategory)
|
||||
@@ -763,12 +853,12 @@ public class CategoriesImplTest
|
||||
final QName categoryQName = createCmQNameOf(CATEGORY_NAME);
|
||||
final NodeRef parentCategoryNodeRef = createNodeRefWithId(PARENT_ID);
|
||||
final ChildAssociationRef parentAssociation = createAssociationOf(parentCategoryNodeRef, CATEGORY_NODE_REF, categoryQName);
|
||||
given(nodesMock.getNode(any())).willReturn(prepareCategoryNode(categoryNewName));
|
||||
given(nodesMock.getNode(any())).willReturn(createNode(categoryNewName));
|
||||
given(nodeServiceMock.getPrimaryParent(any())).willReturn(parentAssociation);
|
||||
given(nodeServiceMock.moveNode(any(), any(), any(), any())).willReturn(createAssociationOf(parentCategoryNodeRef, CATEGORY_NODE_REF, createCmQNameOf(categoryNewName)));
|
||||
|
||||
// when
|
||||
final Category actualCategory = objectUnderTest.updateCategoryById(CATEGORY_ID, categoryWithInvalidParentId);
|
||||
final Category actualCategory = objectUnderTest.updateCategoryById(CATEGORY_ID, categoryWithInvalidParentId, parametersMock);
|
||||
|
||||
final Category expectedCategory = createDefaultCategoryWithName(categoryNewName);
|
||||
assertThat(actualCategory)
|
||||
@@ -785,12 +875,12 @@ public class CategoriesImplTest
|
||||
final QName categoryQName = createCmQNameOf(CATEGORY_NAME);
|
||||
final NodeRef parentCategoryNodeRef = createNodeRefWithId(PARENT_ID);
|
||||
final ChildAssociationRef parentAssociation = createAssociationOf(parentCategoryNodeRef, CATEGORY_NODE_REF, categoryQName);
|
||||
given(nodesMock.getNode(any())).willReturn(prepareCategoryNode(categoryNewName));
|
||||
given(nodesMock.getNode(any())).willReturn(createNode(categoryNewName));
|
||||
given(nodeServiceMock.getPrimaryParent(any())).willReturn(parentAssociation);
|
||||
given(nodeServiceMock.moveNode(any(), any(), any(), any())).willReturn(createAssociationOf(parentCategoryNodeRef, CATEGORY_NODE_REF, createCmQNameOf(categoryNewName)));
|
||||
|
||||
// when
|
||||
final Category actualCategory = objectUnderTest.updateCategoryById(CATEGORY_ID, categoryWithInvalidHasChildren);
|
||||
final Category actualCategory = objectUnderTest.updateCategoryById(CATEGORY_ID, categoryWithInvalidHasChildren, parametersMock);
|
||||
|
||||
final Category expectedCategory = createDefaultCategoryWithName(categoryNewName);
|
||||
assertThat(actualCategory)
|
||||
@@ -804,11 +894,11 @@ public class CategoriesImplTest
|
||||
final List<Category> categoryLinks = List.of(CATEGORY);
|
||||
final NodeRef categoryParentNodeRef = createNodeRefWithId(PARENT_ID);
|
||||
final ChildAssociationRef parentAssociation = createAssociationOf(categoryParentNodeRef, CATEGORY_NODE_REF);
|
||||
given(nodesMock.getNode(any())).willReturn(prepareCategoryNode());
|
||||
given(nodesMock.getNode(any())).willReturn(createNode());
|
||||
given(nodeServiceMock.getPrimaryParent(any())).willReturn(parentAssociation);
|
||||
|
||||
// when
|
||||
final List<Category> actualLinkedCategories = objectUnderTest.linkNodeToCategories(CONTENT_NODE_ID, categoryLinks);
|
||||
final List<Category> actualLinkedCategories = objectUnderTest.linkNodeToCategories(CONTENT_NODE_ID, categoryLinks, parametersMock);
|
||||
|
||||
then(nodesMock).should().validateNode(CONTENT_NODE_ID);
|
||||
then(permissionServiceMock).should().hasPermission(CONTENT_NODE_REF, PermissionService.CHANGE_PERMISSIONS);
|
||||
@@ -838,12 +928,12 @@ public class CategoriesImplTest
|
||||
{
|
||||
final NodeRef categoryParentNodeRef = createNodeRefWithId(PARENT_ID);
|
||||
final ChildAssociationRef parentAssociation = createAssociationOf(categoryParentNodeRef, CATEGORY_NODE_REF);
|
||||
given(nodesMock.getNode(any())).willReturn(prepareCategoryNode());
|
||||
given(nodesMock.getNode(any())).willReturn(createNode());
|
||||
given(nodeServiceMock.getPrimaryParent(any())).willReturn(parentAssociation);
|
||||
given(nodeServiceMock.hasAspect(any(), any())).willReturn(true);
|
||||
|
||||
// when
|
||||
final List<Category> actualLinkedCategories = objectUnderTest.linkNodeToCategories(CONTENT_NODE_ID, List.of(CATEGORY));
|
||||
final List<Category> actualLinkedCategories = objectUnderTest.linkNodeToCategories(CONTENT_NODE_ID, List.of(CATEGORY), parametersMock);
|
||||
|
||||
then(nodesMock).should().getNode(CATEGORY_ID);
|
||||
then(nodeServiceMock).should().getChildAssocs(CATEGORY_NODE_REF, RegexQNamePattern.MATCH_ALL, RegexQNamePattern.MATCH_ALL, false);
|
||||
@@ -873,11 +963,11 @@ public class CategoriesImplTest
|
||||
final ChildAssociationRef categoryParentAssociation = createAssociationOf(categoryParentNodeRef, CATEGORY_NODE_REF);
|
||||
final ChildAssociationRef secondCategoryParentAssociation = createAssociationOf(categoryParentNodeRef, secondCategoryNodeRef);
|
||||
given(nodesMock.validateNode(secondCategoryId)).willReturn(secondCategoryNodeRef);
|
||||
given(nodesMock.getNode(any())).willReturn(prepareCategoryNode(), prepareCategoryNode(secondCategoryName));
|
||||
given(nodesMock.getNode(any())).willReturn(createNode(), createNode(secondCategoryName));
|
||||
given(nodeServiceMock.getPrimaryParent(any())).willReturn(categoryParentAssociation, secondCategoryParentAssociation);
|
||||
|
||||
// when
|
||||
final List<Category> actualLinkedCategories = objectUnderTest.linkNodeToCategories(CONTENT_NODE_ID, categoryLinks);
|
||||
final List<Category> actualLinkedCategories = objectUnderTest.linkNodeToCategories(CONTENT_NODE_ID, categoryLinks, parametersMock);
|
||||
|
||||
then(nodesMock).should().validateNode(CATEGORY_ID);
|
||||
then(nodesMock).should().validateNode(secondCategoryId);
|
||||
@@ -902,13 +992,13 @@ public class CategoriesImplTest
|
||||
final Serializable previousCategories = (Serializable) List.of(otherCategoryNodeRef);
|
||||
final NodeRef categoryParentNodeRef = createNodeRefWithId(PARENT_ID);
|
||||
final ChildAssociationRef parentAssociation = createAssociationOf(categoryParentNodeRef, CATEGORY_NODE_REF);
|
||||
given(nodesMock.getNode(any())).willReturn(prepareCategoryNode());
|
||||
given(nodesMock.getNode(any())).willReturn(createNode());
|
||||
given(nodeServiceMock.getPrimaryParent(any())).willReturn(parentAssociation);
|
||||
given(nodeServiceMock.hasAspect(any(), any())).willReturn(true);
|
||||
given(nodeServiceMock.getProperty(any(), eq(ContentModel.PROP_CATEGORIES))).willReturn(previousCategories);
|
||||
|
||||
// when
|
||||
final List<Category> actualLinkedCategories = objectUnderTest.linkNodeToCategories(CONTENT_NODE_ID, List.of(CATEGORY));
|
||||
final List<Category> actualLinkedCategories = objectUnderTest.linkNodeToCategories(CONTENT_NODE_ID, List.of(CATEGORY), parametersMock);
|
||||
|
||||
final Serializable expectedCategories = (Serializable) Set.of(otherCategoryNodeRef, CATEGORY_NODE_REF);
|
||||
then(nodeServiceMock).should().setProperty(CONTENT_NODE_REF, ContentModel.PROP_CATEGORIES, expectedCategories);
|
||||
@@ -924,7 +1014,7 @@ public class CategoriesImplTest
|
||||
given(nodesMock.validateNode(CONTENT_NODE_ID)).willThrow(EntityNotFoundException.class);
|
||||
|
||||
// when
|
||||
final Throwable actualException = catchThrowable(() -> objectUnderTest.linkNodeToCategories(CONTENT_NODE_ID, List.of(CATEGORY)));
|
||||
final Throwable actualException = catchThrowable(() -> objectUnderTest.linkNodeToCategories(CONTENT_NODE_ID, List.of(CATEGORY), parametersMock));
|
||||
|
||||
then(nodesMock).should().validateNode(CONTENT_NODE_ID);
|
||||
then(permissionServiceMock).shouldHaveNoInteractions();
|
||||
@@ -939,7 +1029,7 @@ public class CategoriesImplTest
|
||||
given(permissionServiceMock.hasPermission(any(), any())).willReturn(AccessStatus.DENIED);
|
||||
|
||||
// when
|
||||
final Throwable actualException = catchThrowable(() -> objectUnderTest.linkNodeToCategories(CONTENT_NODE_ID, List.of(CATEGORY)));
|
||||
final Throwable actualException = catchThrowable(() -> objectUnderTest.linkNodeToCategories(CONTENT_NODE_ID, List.of(CATEGORY), parametersMock));
|
||||
|
||||
then(nodesMock).should().validateNode(CONTENT_NODE_ID);
|
||||
then(permissionServiceMock).should().hasPermission(CONTENT_NODE_REF, PermissionService.CHANGE_PERMISSIONS);
|
||||
@@ -954,9 +1044,8 @@ public class CategoriesImplTest
|
||||
{
|
||||
given(typeConstraint.matches(any())).willReturn(false);
|
||||
|
||||
|
||||
// when
|
||||
final Throwable actualException = catchThrowable(() -> objectUnderTest.linkNodeToCategories(CONTENT_NODE_ID, List.of(CATEGORY)));
|
||||
final Throwable actualException = catchThrowable(() -> objectUnderTest.linkNodeToCategories(CONTENT_NODE_ID, List.of(CATEGORY), parametersMock));
|
||||
|
||||
then(typeConstraint).should().matches(CONTENT_NODE_REF);
|
||||
then(nodeServiceMock).shouldHaveNoInteractions();
|
||||
@@ -971,7 +1060,7 @@ public class CategoriesImplTest
|
||||
final List<Category> categoryLinks = Collections.emptyList();
|
||||
|
||||
// when
|
||||
final Throwable actualException = catchThrowable(() -> objectUnderTest.linkNodeToCategories(CONTENT_NODE_ID, categoryLinks));
|
||||
final Throwable actualException = catchThrowable(() -> objectUnderTest.linkNodeToCategories(CONTENT_NODE_ID, categoryLinks, parametersMock));
|
||||
|
||||
then(nodesMock).shouldHaveNoInteractions();
|
||||
then(permissionServiceMock).shouldHaveNoInteractions();
|
||||
@@ -992,7 +1081,7 @@ public class CategoriesImplTest
|
||||
categoryLinks.add(categoryLinkWithEmptyId);
|
||||
|
||||
// when
|
||||
final Throwable actualException = catchThrowable(() -> objectUnderTest.linkNodeToCategories(CONTENT_NODE_ID, categoryLinks));
|
||||
final Throwable actualException = catchThrowable(() -> objectUnderTest.linkNodeToCategories(CONTENT_NODE_ID, categoryLinks, parametersMock));
|
||||
|
||||
then(nodeServiceMock).shouldHaveNoInteractions();
|
||||
assertThat(actualException)
|
||||
@@ -1006,11 +1095,11 @@ public class CategoriesImplTest
|
||||
final List<Category> categoryLinks = List.of(CATEGORY, CATEGORY);
|
||||
final NodeRef categoryParentNodeRef = createNodeRefWithId(PARENT_ID);
|
||||
final ChildAssociationRef parentAssociation = createAssociationOf(categoryParentNodeRef, CATEGORY_NODE_REF);
|
||||
given(nodesMock.getNode(any())).willReturn(prepareCategoryNode());
|
||||
given(nodesMock.getNode(any())).willReturn(createNode());
|
||||
given(nodeServiceMock.getPrimaryParent(any())).willReturn(parentAssociation);
|
||||
|
||||
// when
|
||||
final List<Category> actualLinkedCategories = objectUnderTest.linkNodeToCategories(CONTENT_NODE_ID, categoryLinks);
|
||||
final List<Category> actualLinkedCategories = objectUnderTest.linkNodeToCategories(CONTENT_NODE_ID, categoryLinks, parametersMock);
|
||||
|
||||
final Map<QName, Serializable> expectedProperties = Map.of(ContentModel.PROP_CATEGORIES, (Serializable) List.of(CATEGORY_NODE_REF));
|
||||
then(nodeServiceMock).should().addAspect(CONTENT_NODE_REF, ContentModel.ASPECT_GEN_CLASSIFIABLE, expectedProperties);
|
||||
@@ -1045,7 +1134,7 @@ public class CategoriesImplTest
|
||||
given(nodeServiceMock.hasAspect(CONTENT_NODE_REF, ContentModel.ASPECT_GEN_CLASSIFIABLE)).willReturn(false);
|
||||
|
||||
//when
|
||||
final Throwable actualException = catchThrowable(() -> objectUnderTest.unlinkNodeFromCategory(CONTENT_NODE_ID,CATEGORY_ID, parametersMock));
|
||||
final Throwable actualException = catchThrowable(() -> objectUnderTest.unlinkNodeFromCategory(CONTENT_NODE_ID, CATEGORY_ID, parametersMock));
|
||||
|
||||
then(nodeServiceMock).should().hasAspect(CONTENT_NODE_REF,ContentModel.ASPECT_GEN_CLASSIFIABLE);
|
||||
then(nodeServiceMock).shouldHaveNoMoreInteractions();
|
||||
@@ -1060,11 +1149,11 @@ public class CategoriesImplTest
|
||||
final NodeRef categoryParentNodeRef = createNodeRefWithId(PARENT_ID);
|
||||
final ChildAssociationRef parentAssociation = createAssociationOf(categoryParentNodeRef, CATEGORY_NODE_REF);
|
||||
given(nodeServiceMock.getProperty(any(), eq(ContentModel.PROP_CATEGORIES))).willReturn((Serializable) List.of(CATEGORY_NODE_REF));
|
||||
given(nodesMock.getNode(any())).willReturn(prepareCategoryNode());
|
||||
given(nodesMock.getNode(any())).willReturn(createNode());
|
||||
given(nodeServiceMock.getPrimaryParent(any())).willReturn(parentAssociation);
|
||||
|
||||
// when
|
||||
final List<Category> actualCategories = objectUnderTest.listCategoriesForNode(CONTENT_NODE_ID);
|
||||
final List<Category> actualCategories = objectUnderTest.listCategoriesForNode(CONTENT_NODE_ID, parametersMock);
|
||||
|
||||
then(nodesMock).should().validateNode(CONTENT_NODE_ID);
|
||||
then(permissionServiceMock).should().hasReadPermission(CONTENT_NODE_REF);
|
||||
@@ -1090,7 +1179,7 @@ public class CategoriesImplTest
|
||||
given(nodesMock.validateNode(CONTENT_NODE_ID)).willThrow(EntityNotFoundException.class);
|
||||
|
||||
// when
|
||||
final Throwable actualException = catchThrowable(() -> objectUnderTest.listCategoriesForNode(CONTENT_NODE_ID));
|
||||
final Throwable actualException = catchThrowable(() -> objectUnderTest.listCategoriesForNode(CONTENT_NODE_ID, parametersMock));
|
||||
|
||||
then(nodesMock).should().validateNode(CONTENT_NODE_ID);
|
||||
then(nodeServiceMock).shouldHaveNoInteractions();
|
||||
@@ -1104,7 +1193,7 @@ public class CategoriesImplTest
|
||||
given(permissionServiceMock.hasReadPermission(any())).willReturn(AccessStatus.DENIED);
|
||||
|
||||
// when
|
||||
final Throwable actualException = catchThrowable(() -> objectUnderTest.listCategoriesForNode(CONTENT_NODE_ID));
|
||||
final Throwable actualException = catchThrowable(() -> objectUnderTest.listCategoriesForNode(CONTENT_NODE_ID, parametersMock));
|
||||
|
||||
then(nodesMock).should().validateNode(CONTENT_NODE_ID);
|
||||
then(permissionServiceMock).should().hasReadPermission(CONTENT_NODE_REF);
|
||||
@@ -1120,7 +1209,7 @@ public class CategoriesImplTest
|
||||
given(typeConstraint.matches(any())).willReturn(false);
|
||||
|
||||
// when
|
||||
final Throwable actualException = catchThrowable(() -> objectUnderTest.listCategoriesForNode(CONTENT_NODE_ID));
|
||||
final Throwable actualException = catchThrowable(() -> objectUnderTest.listCategoriesForNode(CONTENT_NODE_ID, parametersMock));
|
||||
|
||||
then(typeConstraint).should().matches(CONTENT_NODE_REF);
|
||||
then(nodeServiceMock).shouldHaveNoInteractions();
|
||||
@@ -1136,45 +1225,19 @@ public class CategoriesImplTest
|
||||
given(nodeServiceMock.getProperty(any(), eq(ContentModel.PROP_CATEGORIES))).willReturn((Serializable) nullOrEmptyList);
|
||||
|
||||
// when
|
||||
final List<Category> actualCategories = objectUnderTest.listCategoriesForNode(CONTENT_NODE_ID);
|
||||
final List<Category> actualCategories = objectUnderTest.listCategoriesForNode(CONTENT_NODE_ID, parametersMock);
|
||||
|
||||
assertThat(actualCategories).isNotNull().isEmpty();
|
||||
});
|
||||
}
|
||||
|
||||
private Node prepareCategoryNode(final String name, final String id, final NodeRef parentNodeRef)
|
||||
{
|
||||
final Node categoryNode = new Node();
|
||||
categoryNode.setName(name);
|
||||
categoryNode.setNodeId(id);
|
||||
categoryNode.setParentId(parentNodeRef);
|
||||
return categoryNode;
|
||||
}
|
||||
|
||||
private Node prepareCategoryNode(final String name)
|
||||
{
|
||||
return prepareCategoryNode(name, CATEGORY_ID, createNodeRefWithId(PARENT_ID));
|
||||
}
|
||||
|
||||
private Node prepareCategoryNode()
|
||||
{
|
||||
return prepareCategoryNode(CATEGORY_NAME);
|
||||
}
|
||||
|
||||
private List<Category> prepareCategories()
|
||||
{
|
||||
return List.of(Category.builder()
|
||||
.name(CATEGORY_NAME)
|
||||
.create());
|
||||
}
|
||||
|
||||
private List<ChildAssociationRef> prepareChildAssocMocks(final int count, NodeRef parentCategoryNodeRef)
|
||||
{
|
||||
return IntStream.range(0, count).mapToObj(i -> {
|
||||
ChildAssociationRef dummyChildAssocMock = mock(ChildAssociationRef.class);
|
||||
given(dummyChildAssocMock.getTypeQName()).willReturn(ContentModel.ASSOC_SUBCATEGORIES);
|
||||
given(dummyChildAssocMock.getChildRef())
|
||||
.willReturn(new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, CATEGORY_ID + "-" + i));
|
||||
.willReturn(createNodeRefWithId(CATEGORY_ID + "-" + i));
|
||||
given(dummyChildAssocMock.getParentRef()).willReturn(parentCategoryNodeRef);
|
||||
return dummyChildAssocMock;
|
||||
}).collect(Collectors.toList());
|
||||
@@ -1186,8 +1249,8 @@ public class CategoriesImplTest
|
||||
final String id = childRef.getId();
|
||||
final String name = id.replace(CATEGORY_ID, CATEGORY_NAME);
|
||||
final NodeRef parentRef = childAssociationRef.getParentRef();
|
||||
given(nodesMock.getNode(id)).willReturn(prepareCategoryNode(name, id, parentRef));
|
||||
final ChildAssociationRef parentAssoc = new ChildAssociationRef(null, parentRef, null, childRef);
|
||||
given(nodesMock.getNode(id)).willReturn(createNode(name, id, parentRef));
|
||||
final ChildAssociationRef parentAssoc = createAssociationOf(parentRef, childRef);
|
||||
given(nodeServiceMock.getPrimaryParent(childRef)).willReturn(parentAssoc);
|
||||
given(nodeServiceMock.getParentAssocs(parentRef)).willReturn(List.of(parentAssoc));
|
||||
}
|
||||
@@ -1195,14 +1258,38 @@ public class CategoriesImplTest
|
||||
private void doCategoryAssertions(final Category category, final int index, final String parentId)
|
||||
{
|
||||
final Category expectedCategory = Category.builder()
|
||||
.id(CATEGORY_ID + "-" + index)
|
||||
.name(CATEGORY_NAME + "-" + index)
|
||||
.parentId(parentId)
|
||||
.hasChildren(false)
|
||||
.create();
|
||||
.id(CATEGORY_ID + "-" + index)
|
||||
.name(CATEGORY_NAME + "-" + index)
|
||||
.parentId(parentId)
|
||||
.hasChildren(false)
|
||||
.create();
|
||||
assertEquals(expectedCategory, category);
|
||||
}
|
||||
|
||||
private List<Category> prepareCategories()
|
||||
{
|
||||
return List.of(createCategoryOnlyWithName(CATEGORY_NAME));
|
||||
}
|
||||
|
||||
private static Node createNode(final String name, final String id, final NodeRef parentNodeRef)
|
||||
{
|
||||
final Node categoryNode = new Node();
|
||||
categoryNode.setName(name);
|
||||
categoryNode.setNodeId(id);
|
||||
categoryNode.setParentId(parentNodeRef);
|
||||
return categoryNode;
|
||||
}
|
||||
|
||||
private static Node createNode(final String name)
|
||||
{
|
||||
return createNode(name, CATEGORY_ID, createNodeRefWithId(PARENT_ID));
|
||||
}
|
||||
|
||||
private static Node createNode()
|
||||
{
|
||||
return createNode(CATEGORY_NAME);
|
||||
}
|
||||
|
||||
private static NodeRef createNodeRefWithId(final String id)
|
||||
{
|
||||
return new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, id);
|
||||
@@ -1213,6 +1300,11 @@ public class CategoriesImplTest
|
||||
return Category.builder().name(name).create();
|
||||
}
|
||||
|
||||
private static Category createDefaultCategory()
|
||||
{
|
||||
return createDefaultCategoryWithName(CATEGORY_NAME);
|
||||
}
|
||||
|
||||
private static Category createDefaultCategoryWithName(final String name)
|
||||
{
|
||||
return Category.builder()
|
||||
|
||||
@@ -0,0 +1,346 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Remote API
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2023 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.rest.api.impl;
|
||||
|
||||
import static org.alfresco.rest.api.impl.TagsImpl.NOT_A_VALID_TAG;
|
||||
import static org.alfresco.rest.api.impl.TagsImpl.NO_PERMISSION_TO_MANAGE_A_TAG;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.catchThrowable;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertThrows;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.BDDMockito.then;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.alfresco.rest.api.Nodes;
|
||||
import org.alfresco.rest.api.model.Node;
|
||||
import org.alfresco.rest.api.model.Tag;
|
||||
import org.alfresco.rest.framework.core.exceptions.EntityNotFoundException;
|
||||
import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException;
|
||||
import org.alfresco.rest.framework.core.exceptions.PermissionDeniedException;
|
||||
import org.alfresco.rest.framework.resource.parameters.Parameters;
|
||||
import org.alfresco.service.cmr.repository.DuplicateChildNodeNameException;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.StoreRef;
|
||||
import org.alfresco.service.cmr.security.AuthorityService;
|
||||
import org.alfresco.service.cmr.tagging.TaggingService;
|
||||
import org.alfresco.util.Pair;
|
||||
import org.alfresco.util.TypeConstraint;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class TagsImplTest
|
||||
{
|
||||
private static final String TAG_ID = "tag-node-id";
|
||||
private static final String NODE_ID = "node-id";
|
||||
private static final String TAG_NAME = "tag-dummy-name";
|
||||
private static final NodeRef TAG_NODE_REF = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, TAG_ID);
|
||||
|
||||
@Mock
|
||||
private Nodes nodesMock;
|
||||
@Mock
|
||||
private Node createdNodeMock;
|
||||
@Mock
|
||||
private AuthorityService authorityServiceMock;
|
||||
@Mock
|
||||
private TaggingService taggingServiceMock;
|
||||
@Mock
|
||||
private Parameters parametersMock;
|
||||
@Mock
|
||||
private TypeConstraint typeConstraint;
|
||||
|
||||
@InjectMocks
|
||||
private TagsImpl objectUnderTest;
|
||||
|
||||
@Before
|
||||
public void setup()
|
||||
{
|
||||
given(authorityServiceMock.hasAdminAuthority()).willReturn(true);
|
||||
given(nodesMock.validateNode(NODE_ID)).willReturn(TAG_NODE_REF);
|
||||
given(nodesMock.validateNode(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, TAG_ID)).willReturn(TAG_NODE_REF);
|
||||
given(nodesMock.getNode(any())).willReturn(createdNodeMock);
|
||||
given(createdNodeMock.getNodeId()).willReturn(NODE_ID);
|
||||
given(typeConstraint.matches(any())).willReturn(true);
|
||||
given(taggingServiceMock.getTagName(TAG_NODE_REF)).willReturn(TAG_NAME);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetTags() {
|
||||
final List<String> tagNames = List.of("testTag","tag11");
|
||||
final List<Tag> tagsToCreate = createTags(tagNames);
|
||||
given(taggingServiceMock.createTags(any(), any())).willAnswer(invocation -> createTagAndNodeRefPairs(invocation.getArgument(1)));
|
||||
given(parametersMock.getInclude()).willReturn(List.of("count"));
|
||||
final List<Tag> actualCreatedTags = objectUnderTest.createTags(tagsToCreate, parametersMock);
|
||||
final List<Tag> expectedTags = createTagsWithNodeRefs(tagNames).stream()
|
||||
.peek(tag -> tag.setCount(0))
|
||||
.collect(Collectors.toList());
|
||||
assertEquals(expectedTags, actualCreatedTags);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeleteTagById()
|
||||
{
|
||||
//when
|
||||
objectUnderTest.deleteTagById(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, TAG_ID);
|
||||
|
||||
then(authorityServiceMock).should().hasAdminAuthority();
|
||||
then(authorityServiceMock).shouldHaveNoMoreInteractions();
|
||||
|
||||
then(nodesMock).should().validateNode(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, TAG_ID);
|
||||
then(nodesMock).shouldHaveNoMoreInteractions();
|
||||
|
||||
then(taggingServiceMock).should().getTagName(TAG_NODE_REF);
|
||||
then(taggingServiceMock).should().deleteTag(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, TAG_NAME);
|
||||
then(taggingServiceMock).shouldHaveNoMoreInteractions();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeleteTagById_asNonAdminUser()
|
||||
{
|
||||
given(authorityServiceMock.hasAdminAuthority()).willReturn(false);
|
||||
|
||||
//when
|
||||
assertThrows(PermissionDeniedException.class, () -> objectUnderTest.deleteTagById(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, TAG_ID));
|
||||
|
||||
then(authorityServiceMock).should().hasAdminAuthority();
|
||||
then(authorityServiceMock).shouldHaveNoMoreInteractions();
|
||||
|
||||
then(nodesMock).shouldHaveNoInteractions();
|
||||
|
||||
then(taggingServiceMock).shouldHaveNoInteractions();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeleteTagById_nonExistentTag()
|
||||
{
|
||||
//when
|
||||
assertThrows(EntityNotFoundException.class, () -> objectUnderTest.deleteTagById(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, "dummy-id"));
|
||||
|
||||
then(authorityServiceMock).should().hasAdminAuthority();
|
||||
then(authorityServiceMock).shouldHaveNoMoreInteractions();
|
||||
|
||||
then(nodesMock).should().validateNode(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, "dummy-id");
|
||||
then(nodesMock).shouldHaveNoMoreInteractions();
|
||||
|
||||
then(taggingServiceMock).shouldHaveNoInteractions();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateTags()
|
||||
{
|
||||
final List<String> tagNames = List.of("tag1", "99gat");
|
||||
final List<Tag> tagsToCreate = createTags(tagNames);
|
||||
given(taggingServiceMock.createTags(any(), any())).willAnswer(invocation -> createTagAndNodeRefPairs(invocation.getArgument(1)));
|
||||
|
||||
//when
|
||||
final List<Tag> actualCreatedTags = objectUnderTest.createTags(tagsToCreate, parametersMock);
|
||||
|
||||
then(authorityServiceMock).should().hasAdminAuthority();
|
||||
then(authorityServiceMock).shouldHaveNoMoreInteractions();
|
||||
then(taggingServiceMock).should().createTags(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, tagNames);
|
||||
then(taggingServiceMock).shouldHaveNoMoreInteractions();
|
||||
final List<Tag> expectedTags = createTagsWithNodeRefs(tagNames);
|
||||
assertThat(actualCreatedTags)
|
||||
.isNotNull()
|
||||
.isEqualTo(expectedTags);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateTags_withoutPermission()
|
||||
{
|
||||
given(authorityServiceMock.hasAdminAuthority()).willReturn(false);
|
||||
|
||||
//when
|
||||
final Throwable actualException = catchThrowable(() -> objectUnderTest.createTags(List.of(createTag(TAG_NAME)), parametersMock));
|
||||
|
||||
then(authorityServiceMock).should().hasAdminAuthority();
|
||||
then(authorityServiceMock).shouldHaveNoMoreInteractions();
|
||||
then(taggingServiceMock).shouldHaveNoInteractions();
|
||||
assertThat(actualException)
|
||||
.isInstanceOf(PermissionDeniedException.class)
|
||||
.hasMessageContaining(NO_PERMISSION_TO_MANAGE_A_TAG);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateTags_passingNullInsteadList()
|
||||
{
|
||||
//when
|
||||
final Throwable actualException = catchThrowable(() -> objectUnderTest.createTags(null, parametersMock));
|
||||
|
||||
then(taggingServiceMock).shouldHaveNoInteractions();
|
||||
assertThat(actualException)
|
||||
.isInstanceOf(InvalidArgumentException.class)
|
||||
.hasMessageContaining(NOT_A_VALID_TAG);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateTags_passingEmptyList()
|
||||
{
|
||||
//when
|
||||
final Throwable actualException = catchThrowable(() -> objectUnderTest.createTags(Collections.emptyList(), parametersMock));
|
||||
|
||||
then(taggingServiceMock).shouldHaveNoInteractions();
|
||||
assertThat(actualException)
|
||||
.isInstanceOf(InvalidArgumentException.class)
|
||||
.hasMessageContaining(NOT_A_VALID_TAG);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateTags_passingListOfNulls()
|
||||
{
|
||||
//when
|
||||
final Throwable actualException = catchThrowable(() -> objectUnderTest.createTags(Collections.singletonList(null), parametersMock));
|
||||
|
||||
then(taggingServiceMock).shouldHaveNoInteractions();
|
||||
assertThat(actualException)
|
||||
.isInstanceOf(InvalidArgumentException.class)
|
||||
.hasMessageContaining(NOT_A_VALID_TAG);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateTags_whileTagAlreadyExists()
|
||||
{
|
||||
given(taggingServiceMock.createTags(any(), any())).willThrow(new DuplicateChildNodeNameException(null, null, TAG_NAME, null));
|
||||
|
||||
//when
|
||||
final Throwable actualException = catchThrowable(() -> objectUnderTest.createTags(List.of(createTag(TAG_NAME)), parametersMock));
|
||||
|
||||
then(taggingServiceMock).should().createTags(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, List.of(TAG_NAME));
|
||||
then(taggingServiceMock).shouldHaveNoMoreInteractions();
|
||||
assertThat(actualException).isInstanceOf(DuplicateChildNodeNameException.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateTags_withRepeatedTagName()
|
||||
{
|
||||
final List<String> tagNames = List.of(TAG_NAME, TAG_NAME);
|
||||
final List<Tag> tagsToCreate = createTags(tagNames);
|
||||
given(taggingServiceMock.createTags(any(), any())).willAnswer(invocation -> createTagAndNodeRefPairs(invocation.getArgument(1)));
|
||||
|
||||
//when
|
||||
final List<Tag> actualCreatedTags = objectUnderTest.createTags(tagsToCreate, parametersMock);
|
||||
|
||||
then(taggingServiceMock).should().createTags(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, List.of(TAG_NAME));
|
||||
final List<Tag> expectedTags = List.of(createTagWithNodeRef(TAG_NAME));
|
||||
assertThat(actualCreatedTags)
|
||||
.isNotNull()
|
||||
.isEqualTo(expectedTags);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateTags_includingCount()
|
||||
{
|
||||
final List<String> tagNames = List.of("tag1", "99gat");
|
||||
final List<Tag> tagsToCreate = createTags(tagNames);
|
||||
given(taggingServiceMock.createTags(any(), any())).willAnswer(invocation -> createTagAndNodeRefPairs(invocation.getArgument(1)));
|
||||
given(parametersMock.getInclude()).willReturn(List.of("count"));
|
||||
|
||||
//when
|
||||
final List<Tag> actualCreatedTags = objectUnderTest.createTags(tagsToCreate, parametersMock);
|
||||
|
||||
final List<Tag> expectedTags = createTagsWithNodeRefs(tagNames).stream()
|
||||
.peek(tag -> tag.setCount(0))
|
||||
.collect(Collectors.toList());
|
||||
assertThat(actualCreatedTags)
|
||||
.isNotNull()
|
||||
.isEqualTo(expectedTags);
|
||||
}
|
||||
|
||||
private static List<Pair<String, NodeRef>> createTagAndNodeRefPairs(final List<String> tagNames)
|
||||
{
|
||||
return tagNames.stream()
|
||||
.map(tagName -> createPair(tagName, new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, TAG_ID.concat("-").concat(tagName))))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private static Pair<String, NodeRef> createPair(final String tagName, final NodeRef nodeRef)
|
||||
{
|
||||
return new Pair<>(tagName, nodeRef);
|
||||
}
|
||||
|
||||
private static List<Tag> createTags(final List<String> tagNames)
|
||||
{
|
||||
return tagNames.stream().map(TagsImplTest::createTag).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private static List<Tag> createTagsWithNodeRefs(final List<String> tagNames)
|
||||
{
|
||||
return tagNames.stream().map(TagsImplTest::createTagWithNodeRef).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private static Tag createTag(final String tagName)
|
||||
{
|
||||
return Tag.builder()
|
||||
.tag(tagName)
|
||||
.create();
|
||||
}
|
||||
|
||||
private static Tag createTagWithNodeRef(final String tagName)
|
||||
{
|
||||
return Tag.builder()
|
||||
.nodeRef(new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, TAG_ID.concat("-").concat(tagName)))
|
||||
.tag(tagName)
|
||||
.create();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAddTagsToNode()
|
||||
{
|
||||
final List<String> tagNames = List.of("tag1","tag2");
|
||||
final List<Tag> tagsToCreate = createTags(tagNames);
|
||||
given(taggingServiceMock.addTags(any(), any())).willAnswer(invocation -> createTagAndNodeRefPairs(invocation.getArgument(1)));
|
||||
final List<Tag> actualCreatedTags = objectUnderTest.addTags(nodesMock.getNode(any()).getNodeId(),tagsToCreate);
|
||||
then(taggingServiceMock).should().addTags(TAG_NODE_REF, tagNames);
|
||||
final List<Tag> expectedTags = createTagsWithNodeRefs(tagNames).stream().peek(tag -> tag.setCount(1)).collect(Collectors.toList());;
|
||||
assertThat(actualCreatedTags)
|
||||
.isNotNull()
|
||||
.isEqualTo(expectedTags);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAddTagsToNodeWithResponseNotIndexed()
|
||||
{
|
||||
final List<String> tagNames = List.of("tag1","tag2");
|
||||
final List<Tag> tagsToCreate = createTags(tagNames);
|
||||
given(taggingServiceMock.addTags(any(), any())).willAnswer(invocation -> createTagAndNodeRefPairs(invocation.getArgument(1)));
|
||||
final List<Tag> actualCreatedTags = objectUnderTest.addTags(nodesMock.getNode(any()).getNodeId(),tagsToCreate);
|
||||
then(taggingServiceMock).should().addTags(TAG_NODE_REF, tagNames);
|
||||
final List<Tag> expectedTags = createTagsWithNodeRefs(tagNames).stream().peek(tag -> tag.setCount(1)).collect(Collectors.toList());;
|
||||
assertThat(actualCreatedTags)
|
||||
.isNotNull()
|
||||
.isEqualTo(expectedTags);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Remote API
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2023 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.rest.api.tags;
|
||||
|
||||
import static org.alfresco.service.cmr.repository.StoreRef.STORE_REF_WORKSPACE_SPACESSTORE;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.BDDMockito.then;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.alfresco.rest.api.Tags;
|
||||
import org.alfresco.rest.api.model.Tag;
|
||||
import org.alfresco.rest.framework.resource.parameters.Parameters;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class TagsEntityResourceTest
|
||||
{
|
||||
private static final String TAG_ID = "tag-dummy-id";
|
||||
private static final String TAG_NAME = "tag-dummy-name";
|
||||
private static final NodeRef TAG_NODE_REF = new NodeRef(STORE_REF_WORKSPACE_SPACESSTORE, TAG_ID);
|
||||
|
||||
@Mock
|
||||
private Parameters parametersMock;
|
||||
@Mock
|
||||
private Tags tagsMock;
|
||||
|
||||
@InjectMocks
|
||||
private TagsEntityResource tagsEntityResource;
|
||||
|
||||
@Test
|
||||
public void testCreate()
|
||||
{
|
||||
final Tag tag = Tag.builder().tag(TAG_NAME).create();
|
||||
final List<Tag> tags = List.of(tag);
|
||||
given(tagsMock.createTags(any(), any())).willCallRealMethod();
|
||||
given(tagsMock.createTags(any(), any(), any())).willReturn(List.of(Tag.builder().nodeRef(TAG_NODE_REF).tag(TAG_NAME).create()));
|
||||
|
||||
//when
|
||||
final List<Tag> actualCreatedTags = tagsEntityResource.create(tags, parametersMock);
|
||||
|
||||
then(tagsMock).should().createTags(STORE_REF_WORKSPACE_SPACESSTORE, tags, parametersMock);
|
||||
final List<Tag> expectedTags = List.of(Tag.builder().nodeRef(TAG_NODE_REF).tag(TAG_NAME).create());
|
||||
assertThat(actualCreatedTags)
|
||||
.isNotEmpty()
|
||||
.isEqualTo(expectedTags);
|
||||
}
|
||||
}
|
||||
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo</artifactId>
|
||||
<version>20.72</version>
|
||||
<version>20.90-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
|
||||
@@ -1,28 +1,28 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Repository
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Repository
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.repo.download;
|
||||
|
||||
import java.io.File;
|
||||
@@ -31,6 +31,8 @@ import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.nio.file.attribute.FileTime;
|
||||
import java.util.Date;
|
||||
import java.util.Deque;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
@@ -85,6 +87,8 @@ public class ZipDownloadExporter extends BaseExporter
|
||||
private String currentName;
|
||||
|
||||
private OutputStream outputStream;
|
||||
private Date zipTimestampCreated;
|
||||
private Date zipTimestampModified;
|
||||
|
||||
/**
|
||||
* Construct
|
||||
@@ -137,6 +141,8 @@ public class ZipDownloadExporter extends BaseExporter
|
||||
public void startNode(NodeRef nodeRef)
|
||||
{
|
||||
this.currentName = (String)nodeService.getProperty(nodeRef, ContentModel.PROP_NAME);
|
||||
this.zipTimestampCreated = (Date)nodeService.getProperty(nodeRef, ContentModel.PROP_CREATED);
|
||||
this.zipTimestampModified = (Date)nodeService.getProperty(nodeRef, ContentModel.PROP_MODIFIED);
|
||||
path.push(new Pair<String, NodeRef>(currentName, nodeRef));
|
||||
if (dictionaryService.isSubClass(nodeService.getType(nodeRef), ContentModel.TYPE_FOLDER))
|
||||
{
|
||||
@@ -144,6 +150,9 @@ public class ZipDownloadExporter extends BaseExporter
|
||||
ZipArchiveEntry archiveEntry = new ZipArchiveEntry(path);
|
||||
try
|
||||
{
|
||||
archiveEntry.setTime(zipTimestampCreated.getTime());
|
||||
archiveEntry.setCreationTime(FileTime.fromMillis(zipTimestampCreated.getTime()));
|
||||
archiveEntry.setLastModifiedTime(FileTime.fromMillis(zipTimestampModified.getTime()));
|
||||
zipStream.putArchiveEntry(archiveEntry);
|
||||
zipStream.closeArchiveEntry();
|
||||
}
|
||||
@@ -167,6 +176,9 @@ public class ZipDownloadExporter extends BaseExporter
|
||||
{
|
||||
// ALF-2016
|
||||
ZipArchiveEntry zipEntry=new ZipArchiveEntry(getPath());
|
||||
zipEntry.setTime(zipTimestampCreated.getTime());
|
||||
zipEntry.setCreationTime(FileTime.fromMillis(zipTimestampCreated.getTime()));
|
||||
zipEntry.setLastModifiedTime(FileTime.fromMillis(zipTimestampModified.getTime()));
|
||||
zipStream.putArchiveEntry(zipEntry);
|
||||
|
||||
// copy export stream to zip
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* #%L
|
||||
* Alfresco Repository
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2020 Alfresco Software Limited
|
||||
* Copyright (C) 2005 - 2023 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
@@ -304,6 +304,14 @@ public class EventConsolidator implements EventSupportedPolicies
|
||||
builder.setProperties(mappedProps);
|
||||
resourceBeforeAllFieldsNull = false;
|
||||
}
|
||||
|
||||
Map<String, Map<String, String>> localizedProps =helper.getLocalizedPropertiesBefore(changedPropsBefore, after);
|
||||
if (!localizedProps.isEmpty())
|
||||
{
|
||||
builder.setLocalizedProperties(localizedProps);
|
||||
resourceBeforeAllFieldsNull = false;
|
||||
}
|
||||
|
||||
String name = (String) changedPropsBefore.get(ContentModel.PROP_NAME);
|
||||
if (name != null)
|
||||
{
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* #%L
|
||||
* Alfresco Repository
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2020 Alfresco Software Limited
|
||||
* Copyright (C) 2005 - 2023 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
@@ -25,6 +25,8 @@
|
||||
*/
|
||||
package org.alfresco.repo.event2;
|
||||
|
||||
import static java.util.Optional.ofNullable;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.time.ZoneId;
|
||||
import java.time.ZonedDateTime;
|
||||
@@ -34,8 +36,11 @@ import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
import com.google.common.collect.Sets;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.event.v1.model.ContentInfo;
|
||||
import org.alfresco.repo.event.v1.model.NodeResource;
|
||||
@@ -43,6 +48,7 @@ import org.alfresco.repo.event.v1.model.UserInfo;
|
||||
import org.alfresco.repo.event2.filter.EventFilterRegistry;
|
||||
import org.alfresco.repo.event2.filter.NodeAspectFilter;
|
||||
import org.alfresco.repo.event2.filter.NodePropertyFilter;
|
||||
import org.alfresco.repo.node.MLPropertyInterceptor;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||
import org.alfresco.repo.security.permissions.AccessDeniedException;
|
||||
import org.alfresco.service.cmr.dictionary.DictionaryService;
|
||||
@@ -152,6 +158,7 @@ public class NodeResourceHelper implements InitializingBean
|
||||
.setPrimaryAssocQName(getPrimaryAssocQName(nodeRef))
|
||||
.setPrimaryHierarchy(PathUtil.getNodeIdsInReverse(path, false))
|
||||
.setProperties(mapToNodeProperties(properties))
|
||||
.setLocalizedProperties(mapToNodeLocalizedProperties(properties))
|
||||
.setAspectNames(getMappedAspects(nodeRef));
|
||||
}
|
||||
|
||||
@@ -200,9 +207,8 @@ public class NodeResourceHelper implements InitializingBean
|
||||
props.forEach((k, v) -> {
|
||||
if (!nodePropertyFilter.isExcluded(k))
|
||||
{
|
||||
if (v != null && v instanceof MLText)
|
||||
if (v instanceof MLText)
|
||||
{
|
||||
//TODO - should we send all of the values if multiple locales exist?
|
||||
v = ((MLText) v).getDefaultValue();
|
||||
}
|
||||
|
||||
@@ -213,6 +219,23 @@ public class NodeResourceHelper implements InitializingBean
|
||||
return filteredProps;
|
||||
}
|
||||
|
||||
public Map<String, Map<String, String>> mapToNodeLocalizedProperties(Map<QName, Serializable> props)
|
||||
{
|
||||
Map<String, Map<String, String>> filteredProps = new HashMap<>(props.size());
|
||||
|
||||
props.forEach((k, v) -> {
|
||||
if (!nodePropertyFilter.isExcluded(k) && v instanceof MLText)
|
||||
{
|
||||
final MLText mlTextValue = (MLText) v;
|
||||
final HashMap<String, String> localizedValues = new HashMap<>(mlTextValue.size());
|
||||
mlTextValue.forEach((locale, text) -> localizedValues.put(locale.toString(), text));
|
||||
filteredProps.put(getQNamePrefixString(k), localizedValues);
|
||||
}
|
||||
});
|
||||
|
||||
return filteredProps.isEmpty() ? null : filteredProps;
|
||||
}
|
||||
|
||||
public ContentInfo getContentInfo(Map<QName, Serializable> props)
|
||||
{
|
||||
final Serializable content = props.get(ContentModel.PROP_CONTENT);
|
||||
@@ -313,11 +336,6 @@ public class NodeResourceHelper implements InitializingBean
|
||||
return filteredAspects;
|
||||
}
|
||||
|
||||
private boolean isNotEmptyString(Serializable ser)
|
||||
{
|
||||
return !(ser instanceof String) || !((String) ser).isEmpty();
|
||||
}
|
||||
|
||||
public QName getNodeType(NodeRef nodeRef)
|
||||
{
|
||||
return nodeService.getType(nodeRef);
|
||||
@@ -330,7 +348,58 @@ public class NodeResourceHelper implements InitializingBean
|
||||
|
||||
public Map<QName, Serializable> getProperties(NodeRef nodeRef)
|
||||
{
|
||||
return nodeService.getProperties(nodeRef);
|
||||
//We need to have full MLText properties here. This is why we are marking the current thread as MLAware
|
||||
final boolean toRestore = MLPropertyInterceptor.isMLAware();
|
||||
MLPropertyInterceptor.setMLAware(true);
|
||||
try
|
||||
{
|
||||
return nodeService.getProperties(nodeRef);
|
||||
} finally
|
||||
{
|
||||
MLPropertyInterceptor.setMLAware(toRestore);
|
||||
}
|
||||
}
|
||||
|
||||
public Map<String, Map<String, String>> getLocalizedPropertiesBefore(Map<QName, Serializable> propsBefore, NodeResource nodeAfter)
|
||||
{
|
||||
final Map<String, Map<String, String>> locPropsBefore = ofNullable(propsBefore)
|
||||
.map(this::mapToNodeLocalizedProperties)
|
||||
.orElseGet(Map::of);
|
||||
final Map<String, Map<String, String>> locPropsAfter = ofNullable(nodeAfter)
|
||||
.map(NodeResource::getLocalizedProperties)
|
||||
.orElseGet(Map::of);
|
||||
|
||||
return getLocalizedPropertiesBefore(locPropsBefore, locPropsAfter);
|
||||
}
|
||||
|
||||
static Map<String, Map<String, String>> getLocalizedPropertiesBefore(Map<String, Map<String, String>> locPropsBefore,
|
||||
Map<String, Map<String, String>> locPropsAfter)
|
||||
{
|
||||
final Map<String, Map<String, String>> result = new HashMap<>(locPropsBefore.size());
|
||||
|
||||
Sets.union(locPropsBefore.keySet(), locPropsAfter.keySet()).forEach(propertyName -> {
|
||||
final Map<String, String> valuesBefore = ofNullable(locPropsBefore.get(propertyName)).orElseGet(Map::of);
|
||||
final Map<String, String> valuesAfter = ofNullable(locPropsAfter.get(propertyName)).orElseGet(Map::of);
|
||||
|
||||
if (!valuesAfter.isEmpty() || !valuesBefore.isEmpty())
|
||||
{
|
||||
final Map<String, String> diff = new HashMap<>(valuesBefore.size());
|
||||
Sets.union(valuesBefore.keySet(), valuesAfter.keySet()).forEach(lang -> {
|
||||
final String valueBefore = valuesBefore.get(lang);
|
||||
final String valueAfter = valuesAfter.get(lang);
|
||||
if (!Objects.equals(valueBefore, valueAfter))
|
||||
{
|
||||
diff.put(lang, valueBefore);
|
||||
}
|
||||
});
|
||||
if (!diff.isEmpty())
|
||||
{
|
||||
result.put(propertyName, diff);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public Set<String> getMappedAspects(NodeRef nodeRef)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* #%L
|
||||
* Alfresco Repository
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2020 Alfresco Software Limited
|
||||
* Copyright (C) 2005 - 2023 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
@@ -26,7 +26,6 @@
|
||||
package org.alfresco.repo.tagging;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.Serializable;
|
||||
@@ -41,9 +40,10 @@ import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.alfresco.error.AlfrescoRuntimeException;
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.query.EmptyPagingResults;
|
||||
import org.alfresco.query.PagingRequest;
|
||||
@@ -64,11 +64,13 @@ import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
|
||||
import org.alfresco.repo.transaction.AlfrescoTransactionSupport;
|
||||
import org.alfresco.repo.transaction.TransactionListener;
|
||||
import org.alfresco.service.Experimental;
|
||||
import org.alfresco.service.cmr.action.Action;
|
||||
import org.alfresco.service.cmr.action.ActionService;
|
||||
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
||||
import org.alfresco.service.cmr.repository.ContentReader;
|
||||
import org.alfresco.service.cmr.repository.ContentService;
|
||||
import org.alfresco.service.cmr.repository.DuplicateChildNodeNameException;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.NodeService;
|
||||
import org.alfresco.service.cmr.repository.Path;
|
||||
@@ -1575,4 +1577,27 @@ public class TaggingServiceImpl implements TaggingService,
|
||||
}
|
||||
}
|
||||
|
||||
@Experimental
|
||||
@Override
|
||||
public List<Pair<String, NodeRef>> createTags(final StoreRef storeRef, final List<String> tagNames)
|
||||
{
|
||||
updateTagBehaviour.disable();
|
||||
createTagBehaviour.disable();
|
||||
try
|
||||
{
|
||||
return tagNames.stream()
|
||||
.map(String::toLowerCase)
|
||||
.peek(tagName -> categoryService.getRootCategories(storeRef, ContentModel.ASPECT_TAGGABLE, tagName, false).stream()
|
||||
.filter(association -> Objects.nonNull(association.getChildRef()))
|
||||
.findAny()
|
||||
.ifPresent(association -> { throw new DuplicateChildNodeNameException(association.getParentRef(), association.getTypeQName(), tagName, null); }))
|
||||
.map(tagName -> new Pair<>(tagName, getTagNodeRef(storeRef, tagName, true)))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
finally
|
||||
{
|
||||
updateTagBehaviour.enable();
|
||||
createTagBehaviour.enable();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* #%L
|
||||
* Alfresco Repository
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||
* Copyright (C) 2005 - 2023 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
|
||||
@@ -1,36 +1,38 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Repository
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Repository
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2023 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.service.cmr.tagging;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.alfresco.api.AlfrescoPublicApi;
|
||||
import org.alfresco.query.PagingRequest;
|
||||
import org.alfresco.query.PagingResults;
|
||||
import org.alfresco.service.Auditable;
|
||||
import org.alfresco.service.Experimental;
|
||||
import org.alfresco.service.NotAuditable;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.StoreRef;
|
||||
@@ -306,17 +308,31 @@ public interface TaggingService
|
||||
*/
|
||||
@NotAuditable
|
||||
Pair<List<String>, Integer> getPagedTags(StoreRef storeRef, String filter, int fromTag, int pageSize);
|
||||
|
||||
|
||||
/**
|
||||
* Get tagged nodes and count of nodes group by tag name
|
||||
*
|
||||
* @param storeRef
|
||||
* @return
|
||||
*/
|
||||
@NotAuditable
|
||||
List<Pair<String, Integer>> findTaggedNodesAndCountByTagName(StoreRef storeRef);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get tagged nodes and count of nodes group by tag name
|
||||
*
|
||||
* @param storeRef
|
||||
* @return
|
||||
*/
|
||||
@NotAuditable
|
||||
List<Pair<String, Integer>> findTaggedNodesAndCountByTagName(StoreRef storeRef);
|
||||
|
||||
/**
|
||||
* Creates orphan tags. Tag names case will be lowered.
|
||||
*
|
||||
* @param storeRef Reference to node store.
|
||||
* @param tagNames List of tag names.
|
||||
* @return {@link List} of {@link Pair}s of tag names and node references.
|
||||
* @throws org.alfresco.service.cmr.repository.DuplicateChildNodeNameException if tag already exists.
|
||||
*/
|
||||
@Experimental
|
||||
@Auditable(parameters = {"tagNames"})
|
||||
default List<Pair<String, NodeRef>> createTags(StoreRef storeRef, List<String> tagNames)
|
||||
{
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// check category exists?
|
||||
var category = search.luceneSearch("PATH:\"/cm:generalclassifiable//cm:" + url.extension + "\"");
|
||||
var category = search.luceneSearch("PATH:\"/cm:categoryRoot/cm:generalclassifiable//cm:" + url.extension + "\"");
|
||||
if (category == undefined)
|
||||
{
|
||||
status.code = 404;
|
||||
@@ -9,6 +9,6 @@ if (category == undefined)
|
||||
else
|
||||
{
|
||||
// perform category search
|
||||
var nodes = search.luceneSearch("PATH:\"/cm:generalclassifiable//cm:" + url.extension + "//member\"");
|
||||
var nodes = search.luceneSearch("PATH:\"/cm:categoryRoot/cm:generalclassifiable//cm:" + url.extension + "//member\"");
|
||||
model.resultset = nodes;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
<value>{http://www.alfresco.org/model/content/1.0}categories</value>
|
||||
</key>
|
||||
<!-- Note - FreeMarker ${..} entries must be escaped in Spring context files -->
|
||||
<value>\$\{selectSingleNode('workspace://SpacesStore', 'lucene', 'PATH:"/cm:generalclassifiable/cm:Languages/cm:English"' )\}</value>
|
||||
<value>\$\{selectSingleNode('workspace://SpacesStore', 'lucene', 'PATH:"/cm:categoryRoot/cm:generalclassifiable/cm:Languages/cm:English"' )\}</value>
|
||||
</entry>
|
||||
</map>
|
||||
</property>
|
||||
|
||||
@@ -244,7 +244,8 @@ import org.junit.runners.Suite;
|
||||
|
||||
org.alfresco.repo.event2.RepoEvent2UnitSuite.class,
|
||||
|
||||
org.alfresco.util.schemacomp.SchemaDifferenceHelperUnitTest.class
|
||||
org.alfresco.util.schemacomp.SchemaDifferenceHelperUnitTest.class,
|
||||
org.alfresco.repo.tagging.TaggingServiceImplUnitTest.class
|
||||
})
|
||||
public class AllUnitTestsSuite
|
||||
{
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* #%L
|
||||
* Alfresco Repository
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2020 Alfresco Software Limited
|
||||
* Copyright (C) 2005 - 2023 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
@@ -32,6 +32,7 @@ import static org.awaitility.Awaitility.await;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import javax.jms.ConnectionFactory;
|
||||
|
||||
@@ -47,6 +48,7 @@ import org.alfresco.repo.event.v1.model.Resource;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||
import org.alfresco.repo.transaction.RetryingTransactionHelper;
|
||||
import org.alfresco.service.cmr.dictionary.CustomModelService;
|
||||
import org.alfresco.service.cmr.repository.MLText;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.NodeService;
|
||||
import org.alfresco.service.cmr.repository.StoreRef;
|
||||
@@ -89,6 +91,11 @@ public abstract class AbstractContextAwareRepoEvent extends BaseSpringTest
|
||||
private static final String CAMEL_ROUTE = "jms:topic:" + TOPIC_NAME;
|
||||
private static final CamelContext CAMEL_CONTEXT = new DefaultCamelContext();
|
||||
|
||||
protected final Locale defaultLocale = new Locale(MLText.getDefaultLocale().getLanguage());
|
||||
protected final Locale germanLocale = new Locale(Locale.GERMAN.getLanguage(), "XX");
|
||||
protected final Locale frenchLocale = new Locale(Locale.FRENCH.getLanguage());
|
||||
protected final Locale japaneseLocale = new Locale(Locale.JAPANESE.getLanguage(), "YY", "ZZ");
|
||||
|
||||
private static boolean isCamelConfigured;
|
||||
private static DataFormat dataFormat;
|
||||
|
||||
@@ -388,6 +395,20 @@ public abstract class AbstractContextAwareRepoEvent extends BaseSpringTest
|
||||
return (T) resource.getProperties().get(propertyName);
|
||||
}
|
||||
|
||||
protected String getLocalizedProperty(NodeResource resource, String propertyName, Locale locale)
|
||||
{
|
||||
assertTrue(containsLocalizedProperty(resource, propertyName, locale));
|
||||
return resource.getLocalizedProperties().get(propertyName).get(locale.toString());
|
||||
}
|
||||
|
||||
protected boolean containsLocalizedProperty(NodeResource resource, String propertyName, Locale locale)
|
||||
{
|
||||
assertNotNull(resource);
|
||||
assertNotNull(resource.getLocalizedProperties());
|
||||
assertNotNull(resource.getLocalizedProperties().get(propertyName));
|
||||
return resource.getLocalizedProperties().get(propertyName).containsKey(locale.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Await at most 5 seconds for the condition (ie. {@code numOfEvents})
|
||||
* to be met before throwing a timeout exception.
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* #%L
|
||||
* Alfresco Repository
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2020 Alfresco Software Limited
|
||||
* Copyright (C) 2005 - 2023 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
@@ -38,6 +38,7 @@ import org.alfresco.repo.event.v1.model.EventData;
|
||||
import org.alfresco.repo.event.v1.model.EventType;
|
||||
import org.alfresco.repo.event.v1.model.NodeResource;
|
||||
import org.alfresco.repo.event.v1.model.RepoEvent;
|
||||
import org.alfresco.service.cmr.repository.MLText;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.alfresco.util.GUID;
|
||||
@@ -50,7 +51,6 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||
*/
|
||||
public class CreateRepoEventIT extends AbstractContextAwareRepoEvent
|
||||
{
|
||||
|
||||
@Autowired
|
||||
private NodeDAO nodeDAO;
|
||||
|
||||
@@ -63,6 +63,9 @@ public class CreateRepoEventIT extends AbstractContextAwareRepoEvent
|
||||
PropertyMap propertyMap = new PropertyMap();
|
||||
propertyMap.put(ContentModel.PROP_TITLE, "test title");
|
||||
propertyMap.put(ContentModel.PROP_NAME, name);
|
||||
final MLText localizedDescription = new MLText(germanLocale, "german description");
|
||||
localizedDescription.addValue(defaultLocale, "default description");
|
||||
propertyMap.put(ContentModel.PROP_DESCRIPTION, localizedDescription);
|
||||
final NodeRef nodeRef = createNode(ContentModel.TYPE_CONTENT, localName, propertyMap);
|
||||
|
||||
final RepoEvent<EventData<NodeResource>> resultRepoEvent = getRepoEvent(1);
|
||||
@@ -91,6 +94,10 @@ public class CreateRepoEventIT extends AbstractContextAwareRepoEvent
|
||||
assertNotNull(nodeResource.getPrimaryHierarchy());
|
||||
assertNotNull("Default aspects were not added. ", nodeResource.getAspectNames());
|
||||
assertEquals("test title", getProperty(nodeResource, "cm:title"));
|
||||
assertEquals("test title", getLocalizedProperty(nodeResource, "cm:title", defaultLocale));
|
||||
assertEquals("default description", getProperty(nodeResource, "cm:description"));
|
||||
assertEquals("default description", getLocalizedProperty(nodeResource, "cm:description", defaultLocale));
|
||||
assertEquals("german description", getLocalizedProperty(nodeResource, "cm:description", germanLocale));
|
||||
assertNull("There is no content.", nodeResource.getContent());
|
||||
|
||||
assertNotNull("Missing createdByUser property.", nodeResource.getCreatedByUser());
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* #%L
|
||||
* Alfresco Repository
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2020 Alfresco Software Limited
|
||||
* Copyright (C) 2005 - 2023 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
@@ -31,6 +31,7 @@ import org.alfresco.repo.event.v1.model.EventData;
|
||||
import org.alfresco.repo.event.v1.model.EventType;
|
||||
import org.alfresco.repo.event.v1.model.NodeResource;
|
||||
import org.alfresco.repo.event.v1.model.RepoEvent;
|
||||
import org.alfresco.service.cmr.repository.MLText;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.alfresco.util.GUID;
|
||||
@@ -48,6 +49,9 @@ public class DeleteRepoEventIT extends AbstractContextAwareRepoEvent
|
||||
String localName = GUID.generate();
|
||||
PropertyMap propertyMap = new PropertyMap();
|
||||
propertyMap.put(ContentModel.PROP_TITLE, "test title");
|
||||
final MLText localizedDescription = new MLText(germanLocale, "german description");
|
||||
localizedDescription.addValue(defaultLocale, "default description");
|
||||
propertyMap.put(ContentModel.PROP_DESCRIPTION, localizedDescription);
|
||||
NodeRef nodeRef = createNode(ContentModel.TYPE_CONTENT, localName, propertyMap);
|
||||
|
||||
NodeResource createdResource = getNodeResource(1);
|
||||
@@ -62,10 +66,16 @@ public class DeleteRepoEventIT extends AbstractContextAwareRepoEvent
|
||||
|
||||
deleteNode(nodeRef);
|
||||
final RepoEvent<EventData<NodeResource>> resultRepoEvent = getRepoEvent(2);
|
||||
final NodeResource nodeResource = getNodeResource(resultRepoEvent);
|
||||
|
||||
assertEquals("Repo event type:", EventType.NODE_DELETED.getType(), resultRepoEvent.getType());
|
||||
assertEquals(createdResource.getId(), getNodeResource(resultRepoEvent).getId());
|
||||
assertEquals(createdResource.getId(), nodeResource.getId());
|
||||
assertEquals("Wrong primaryAssocQName prefix.", "ce:" + localName, createdResource.getPrimaryAssocQName());
|
||||
assertEquals("test title", getProperty(nodeResource, "cm:title"));
|
||||
assertEquals("test title", getLocalizedProperty(nodeResource, "cm:title", defaultLocale));
|
||||
assertEquals("default description", getProperty(nodeResource, "cm:description"));
|
||||
assertEquals("default description", getLocalizedProperty(nodeResource, "cm:description", defaultLocale));
|
||||
assertEquals("german description", getLocalizedProperty(nodeResource, "cm:description", germanLocale));
|
||||
|
||||
// There should be no resourceBefore
|
||||
EventData<NodeResource> eventData = getEventData(resultRepoEvent);
|
||||
|
||||
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Repository
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2023 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.repo.event2;
|
||||
|
||||
import static org.alfresco.repo.event2.NodeResourceHelper.getLocalizedPropertiesBefore;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
public class NodeResourceHelperUnitTest
|
||||
{
|
||||
@Test
|
||||
public void shouldExtractOnlyRelevantPropertiesForBeforeNode()
|
||||
{
|
||||
final Map<String, Map<String, String>> before =
|
||||
Map.of(
|
||||
"unchanged-empty", locValues(),
|
||||
"unchanged-non-empty", locValues("pl", "Kiełbasa", "en", "Sausage"),
|
||||
"changed-added", locValues("pl", "Kiełbasa"),
|
||||
"changed-modified", locValues("pl", "XYZ", "en", "Sausage"),
|
||||
"changed-deleted", locValues("pl", "Kiełbasa", "en", "Sausage"),
|
||||
"changed-added-modified-deleted", locValues("pl", "XYZ", "en", "Sausage"),
|
||||
"changed-to-empty", locValues("pl", "Kiełbasa", "en", "Sausage"),
|
||||
"changed-from-empty", locValues(),
|
||||
"removed-empty", locValues(),
|
||||
"removed-non-empty", locValues("pl", "Kiełbasa", "en", "Sausage")
|
||||
);
|
||||
|
||||
final Map<String, Map<String, String>> after =
|
||||
Map.of(
|
||||
"unchanged-empty", locValues(),
|
||||
"unchanged-non-empty", locValues("pl", "Kiełbasa", "en", "Sausage"),
|
||||
"changed-added", locValues("pl", "Kiełbasa", "en", "Sausage"),
|
||||
"changed-modified", locValues("pl", "Kiełbasa", "en", "Sausage"),
|
||||
"changed-deleted", locValues("en", "Sausage"),
|
||||
"changed-added-modified-deleted", locValues("pl", "Kiełbasa", "de", "Würst"),
|
||||
"changed-to-empty", locValues(),
|
||||
"changed-from-empty", locValues("pl", "Kiełbasa", "en", "Sausage"),
|
||||
"new-empty", locValues(),
|
||||
"new-non-empty", locValues("de", "Würst")
|
||||
);
|
||||
|
||||
final Map<String, Map<String, String>> diff = getLocalizedPropertiesBefore(before, after);
|
||||
|
||||
assertFalse(diff.containsKey("unchanged-empty"));
|
||||
assertFalse(diff.containsKey("unchanged-non-empty"));
|
||||
assertEquals(locValues("en", null), diff.get("changed-added"));
|
||||
assertEquals(locValues("pl", "XYZ"), diff.get("changed-modified"));
|
||||
assertEquals(locValues("pl", "Kiełbasa"), diff.get("changed-deleted"));
|
||||
assertEquals(locValues("pl", "XYZ", "en", "Sausage", "de", null), diff.get("changed-added-modified-deleted"));
|
||||
assertEquals(locValues("pl", "Kiełbasa", "en", "Sausage"), diff.get("changed-to-empty"));
|
||||
assertEquals(locValues("pl", null, "en", null), diff.get("changed-from-empty"));
|
||||
assertFalse(diff.containsKey("removed-empty"));
|
||||
assertEquals(locValues("pl", "Kiełbasa", "en", "Sausage"), diff.get("removed-non-empty"));
|
||||
assertFalse(diff.containsKey("new-empty"));
|
||||
assertEquals(locValues("de", null), diff.get("new-non-empty"));
|
||||
}
|
||||
|
||||
private LocalizedValues locValues(String l1, String v1, String l2, String v2, String l3, String v3)
|
||||
{
|
||||
return locValues(l1, v1, l2, v2).append(l3, v3);
|
||||
}
|
||||
|
||||
private LocalizedValues locValues(String l1, String v1, String l2, String v2)
|
||||
{
|
||||
return locValues(l1, v1).append(l2, v2);
|
||||
}
|
||||
|
||||
private LocalizedValues locValues(String l1, String v1)
|
||||
{
|
||||
return locValues().append(l1, v1);
|
||||
}
|
||||
|
||||
private LocalizedValues locValues()
|
||||
{
|
||||
return new LocalizedValues();
|
||||
}
|
||||
|
||||
private static class LocalizedValues extends HashMap<String, String>
|
||||
{
|
||||
public LocalizedValues append(String language, String value)
|
||||
{
|
||||
this.put(language, value);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
* #%L
|
||||
* Alfresco Repository
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2020 Alfresco Software Limited
|
||||
* Copyright (C) 2005 - 2023 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
@@ -34,7 +34,8 @@ import org.junit.runners.Suite.SuiteClasses;
|
||||
@SuiteClasses({ EventFilterUnitTest.class,
|
||||
EventConsolidatorUnitTest.class,
|
||||
EventJSONSchemaUnitTest.class,
|
||||
EventGeneratorQueueUnitTest.class
|
||||
EventGeneratorQueueUnitTest.class,
|
||||
NodeResourceHelperUnitTest.class
|
||||
})
|
||||
public class RepoEvent2UnitSuite
|
||||
{
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* #%L
|
||||
* Alfresco Repository
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2020 Alfresco Software Limited
|
||||
* Copyright (C) 2005 - 2023 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
@@ -26,6 +26,8 @@
|
||||
|
||||
package org.alfresco.repo.event2;
|
||||
|
||||
import static org.alfresco.model.ContentModel.PROP_DESCRIPTION;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
@@ -46,6 +48,7 @@ import org.alfresco.service.cmr.dictionary.CustomModelDefinition;
|
||||
import org.alfresco.service.cmr.dictionary.TypeDefinition;
|
||||
import org.alfresco.service.cmr.repository.ContentService;
|
||||
import org.alfresco.service.cmr.repository.ContentWriter;
|
||||
import org.alfresco.service.cmr.repository.MLText;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.alfresco.util.GUID;
|
||||
@@ -279,6 +282,60 @@ public class UpdateRepoEventIT extends AbstractContextAwareRepoEvent
|
||||
assertNull(resourceBefore.getPrimaryAssocQName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateContentWithLocalizedProperties()
|
||||
{
|
||||
final String description = "cm:description";
|
||||
final NodeRef nodeRef = createNode(ContentModel.TYPE_CONTENT);
|
||||
NodeResource resource = getNodeResource(1);
|
||||
|
||||
assertNull(getProperty(resource, description));
|
||||
assertNull(resource.getLocalizedProperties());
|
||||
assertNull(getEventData(1).getResourceBefore());
|
||||
|
||||
retryingTransactionHelper.doInTransaction(() -> {
|
||||
final MLText localizedDescription = new MLText(germanLocale, "german description");
|
||||
localizedDescription.addValue(defaultLocale, "default description");
|
||||
localizedDescription.addValue(japaneseLocale, "japanese description");
|
||||
|
||||
nodeService.setProperty(nodeRef, PROP_DESCRIPTION, localizedDescription);
|
||||
return null;
|
||||
});
|
||||
|
||||
resource = getNodeResource(2);
|
||||
NodeResource resourceBefore = getNodeResourceBefore(2);
|
||||
|
||||
assertEquals("default description", getProperty(resource, description));
|
||||
assertEquals("default description", getLocalizedProperty(resource, description, defaultLocale));
|
||||
assertEquals("german description", getLocalizedProperty(resource, description, germanLocale));
|
||||
assertEquals("japanese description", getLocalizedProperty(resource, description, japaneseLocale));
|
||||
assertNull(getLocalizedProperty(resourceBefore, description, defaultLocale));
|
||||
assertNull(getLocalizedProperty(resourceBefore, description, germanLocale));
|
||||
assertNull(getLocalizedProperty(resourceBefore, description, japaneseLocale));
|
||||
|
||||
retryingTransactionHelper.doInTransaction(() -> {
|
||||
final MLText localizedDescription = new MLText(frenchLocale, "french description added");
|
||||
localizedDescription.addValue(defaultLocale, "default description modified");
|
||||
localizedDescription.addValue(japaneseLocale, "japanese description");
|
||||
|
||||
nodeService.setProperty(nodeRef, PROP_DESCRIPTION, localizedDescription);
|
||||
return null;
|
||||
});
|
||||
|
||||
resource = getNodeResource(3);
|
||||
resourceBefore = getNodeResourceBefore(3);
|
||||
|
||||
assertEquals("default description modified", getProperty(resource, description));
|
||||
assertEquals("default description modified", getLocalizedProperty(resource, description, defaultLocale));
|
||||
assertEquals("french description added", getLocalizedProperty(resource, description, frenchLocale));
|
||||
assertEquals("japanese description", getLocalizedProperty(resource, description, japaneseLocale));
|
||||
assertFalse(containsLocalizedProperty(resource, description, germanLocale));
|
||||
assertEquals("default description", getLocalizedProperty(resourceBefore, description, defaultLocale));
|
||||
assertEquals("german description", getLocalizedProperty(resourceBefore, description, germanLocale));
|
||||
assertNull(getLocalizedProperty(resourceBefore, description, frenchLocale));
|
||||
assertFalse(containsLocalizedProperty(resourceBefore, description, japaneseLocale));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateContentTitle()
|
||||
{
|
||||
@@ -296,8 +353,11 @@ public class UpdateRepoEventIT extends AbstractContextAwareRepoEvent
|
||||
});
|
||||
|
||||
resource = getNodeResource(2);
|
||||
NodeResource resourceBefore = getNodeResourceBefore(2);
|
||||
title = getProperty(resource, "cm:title");
|
||||
assertEquals("test title", title);
|
||||
assertEquals("test title", getLocalizedProperty(resource, "cm:title", defaultLocale));
|
||||
assertNull(getLocalizedProperty(resourceBefore, "cm:title", defaultLocale));
|
||||
|
||||
// update content cm:title property again with "new test title" value
|
||||
retryingTransactionHelper.doInTransaction(() -> {
|
||||
@@ -308,10 +368,13 @@ public class UpdateRepoEventIT extends AbstractContextAwareRepoEvent
|
||||
resource = getNodeResource(3);
|
||||
title = getProperty(resource, "cm:title");
|
||||
assertEquals("new test title", title);
|
||||
assertEquals("new test title", getLocalizedProperty(resource, "cm:title", defaultLocale));
|
||||
|
||||
NodeResource resourceBefore = getNodeResourceBefore(3);
|
||||
|
||||
resourceBefore = getNodeResourceBefore(3);
|
||||
title = getProperty(resourceBefore, "cm:title");
|
||||
assertEquals("Wrong old property.", "test title", title);
|
||||
assertEquals("test title", getLocalizedProperty(resourceBefore, "cm:title", defaultLocale));
|
||||
assertNotNull(resourceBefore.getModifiedAt());
|
||||
}
|
||||
|
||||
@@ -354,7 +417,7 @@ public class UpdateRepoEventIT extends AbstractContextAwareRepoEvent
|
||||
|
||||
// update content cm:description property with "test_description" value
|
||||
retryingTransactionHelper.doInTransaction(() -> {
|
||||
nodeService.setProperty(nodeRef, ContentModel.PROP_DESCRIPTION, "test description");
|
||||
nodeService.setProperty(nodeRef, PROP_DESCRIPTION, "test description");
|
||||
return null;
|
||||
});
|
||||
|
||||
@@ -492,7 +555,7 @@ public class UpdateRepoEventIT extends AbstractContextAwareRepoEvent
|
||||
QName.createQName(TEST_NAMESPACE, GUID.generate()),
|
||||
ContentModel.TYPE_CONTENT).getChildRef();
|
||||
|
||||
nodeService.setProperty(node1, ContentModel.PROP_DESCRIPTION, "test description");
|
||||
nodeService.setProperty(node1, PROP_DESCRIPTION, "test description");
|
||||
return null;
|
||||
});
|
||||
//Create and update node are done in the same transaction so one event is expected
|
||||
|
||||
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Remote API
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2023 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.repo.tagging;
|
||||
|
||||
import static org.alfresco.service.cmr.repository.StoreRef.STORE_REF_WORKSPACE_SPACESSTORE;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.catchThrowable;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.BDDMockito.then;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.policy.PolicyComponent;
|
||||
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
||||
import org.alfresco.service.cmr.repository.DuplicateChildNodeNameException;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.StoreRef;
|
||||
import org.alfresco.service.cmr.search.CategoryService;
|
||||
import org.alfresco.util.Pair;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class TaggingServiceImplUnitTest
|
||||
{
|
||||
private static final String TAG_ID = "tag-node-id";
|
||||
private static final String TAG_NAME = "tag-dummy-name";
|
||||
private static final NodeRef TAG_NODE_REF = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, TAG_ID);
|
||||
|
||||
@Mock
|
||||
private CategoryService categoryServiceMock;
|
||||
@Mock
|
||||
private PolicyComponent policyComponentMock;
|
||||
|
||||
@InjectMocks
|
||||
private TaggingServiceImpl taggingService;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception
|
||||
{
|
||||
taggingService.init();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateTags()
|
||||
{
|
||||
final ChildAssociationRef tagAssociationMock = mock(ChildAssociationRef.class);
|
||||
given(categoryServiceMock.getRootCategories(any(), any(), any(String.class), eq(true))).willReturn(List.of(tagAssociationMock));
|
||||
given(tagAssociationMock.getChildRef()).willReturn(TAG_NODE_REF);
|
||||
|
||||
//when
|
||||
final List<Pair<String, NodeRef>> actualTagPairs = taggingService.createTags(STORE_REF_WORKSPACE_SPACESSTORE, List.of(TAG_NAME));
|
||||
|
||||
then(categoryServiceMock).should().getRootCategories(STORE_REF_WORKSPACE_SPACESSTORE, ContentModel.ASPECT_TAGGABLE, TAG_NAME, false);
|
||||
then(categoryServiceMock).should().getRootCategories(STORE_REF_WORKSPACE_SPACESSTORE, ContentModel.ASPECT_TAGGABLE, TAG_NAME, true);
|
||||
then(categoryServiceMock).shouldHaveNoMoreInteractions();
|
||||
List<Pair<String, NodeRef>> expectedTagPairs = List.of(new Pair<>(TAG_NAME, TAG_NODE_REF));
|
||||
assertThat(actualTagPairs)
|
||||
.isNotNull()
|
||||
.isEqualTo(expectedTagPairs);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateTags_whileTagAlreadyExists()
|
||||
{
|
||||
given(categoryServiceMock.getRootCategories(any(), any(), any(String.class), eq(false))).willThrow(new DuplicateChildNodeNameException(null, null, null, null));
|
||||
|
||||
//when
|
||||
final Throwable actualException = catchThrowable(() -> taggingService.createTags(STORE_REF_WORKSPACE_SPACESSTORE, List.of(TAG_NAME)));
|
||||
|
||||
then(categoryServiceMock).should().getRootCategories(STORE_REF_WORKSPACE_SPACESSTORE, ContentModel.ASPECT_TAGGABLE, TAG_NAME, false);
|
||||
then(categoryServiceMock).shouldHaveNoMoreInteractions();
|
||||
assertThat(actualException).isInstanceOf(DuplicateChildNodeNameException.class);
|
||||
}
|
||||
}
|
||||
@@ -1220,7 +1220,7 @@ public class MultiTDemoTest extends TestCase
|
||||
}
|
||||
|
||||
// Find all root categories
|
||||
String query = "PATH:\"/cm:generalclassifiable/*\"";
|
||||
String query = "PATH:\"/cm:categoryRoot/cm:generalclassifiable/*\"";
|
||||
ResultSet resultSet = searchService.query(SPACES_STORE, SearchService.LANGUAGE_LUCENE, query);
|
||||
int cnt = resultSet.length();
|
||||
|
||||
@@ -1246,7 +1246,7 @@ public class MultiTDemoTest extends TestCase
|
||||
assertEquals(cnt, resultSet.length());
|
||||
resultSet.close();
|
||||
|
||||
String queryMembers = "PATH:\"/cm:generalclassifiable//cm:catA/member\"";
|
||||
String queryMembers = "PATH:\"/cm:categoryRoot/cm:generalclassifiable//cm:catA/member\"";
|
||||
resultSet = searchService.query(SPACES_STORE, SearchService.LANGUAGE_LUCENE, queryMembers);
|
||||
assertEquals(0, resultSet.length());
|
||||
resultSet.close();
|
||||
@@ -1273,7 +1273,7 @@ public class MultiTDemoTest extends TestCase
|
||||
assertEquals(1, categories.size());
|
||||
|
||||
// test ETHREEOH-210
|
||||
queryMembers = "PATH:\"/cm:generalclassifiable//cm:CatA/member\"";
|
||||
queryMembers = "PATH:\"/cm:categoryRoot/cm:generalclassifiable//cm:CatA/member\"";
|
||||
resultSet = searchService.query(SPACES_STORE, SearchService.LANGUAGE_LUCENE, queryMembers);
|
||||
assertEquals(1, resultSet.length());
|
||||
resultSet.close();
|
||||
|
||||
@@ -5,7 +5,6 @@ set -vex
|
||||
pushd "$(dirname "${BASH_SOURCE[0]}")/../../"
|
||||
|
||||
# Maven Setup
|
||||
mkdir -p "${HOME}/.m2" && cp -f .github/.ci.settings.xml "${HOME}/.m2/settings.xml"
|
||||
find "${HOME}/.m2/repository/" -type d -name "*-SNAPSHOT*" | xargs -r -l rm -rf
|
||||
|
||||
# Docker Logins
|
||||
|
||||
Reference in New Issue
Block a user